Version 2.8.0-dev.16.0

Merge commit '41fa72ef11799676526593694801cda3954d4ff6' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b44589..bfced46 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,14 @@
   was allowed. The value of that getter on a `TypeError` was the same
   string as returned by `toString`, so it is still available.
 
+#### `dart:developer`
+
+* The constructors for `TimelineTask` now accept an optional `filterKey`
+  parameter. If provided, the arguments for all events associated with the task
+  will contain an entry named `filterKey`, set to the value of the `filterKey`
+  parameter provided in the constructor. This will be used by tooling to allow
+  for better filtering of timeline events.
+
 #### `dart:html`
 
 * **Breaking Change**: Changed the return type of several html native methods
@@ -113,10 +121,14 @@
   `external`. Previously the external could be omitted in some cases with DDC
   but doing so would cause incorrect behavior with `dart2js`.
 * JS interop classes with an index operator are now static errors.
-* Removed the `dart:mirrors` library from the SDK. Use of this library on the
-  web has been unsupported and prevented by the Dart build systems since Dart
-  v2.0.0. All known exception cases have been cleaned up. This change makes DDC
-  and dart2js now issue a compile-time error directly as well.
+* All remaining support from the `dart:mirrors` library has been removed.
+  Use of this library on the web has been unsupported and prevented by the Dart
+  build systems since Dart v2.0.0. All known exception cases have been cleaned
+  up. This change makes DDC and dart2js now behave consistently.
+  
+  The library can still be imported on web apps, but all APIs throw. In a future
+  breaking change release, imports to this library will likely become a
+  compile-time error.
 
  [announcement]: https://github.com/dart-lang/sdk/issues/38994
 
@@ -128,10 +140,6 @@
   forgiving. Corresponding type parameter bounds now only need to be mutual
   subtypes rather than structurally equal up to renaming of bound type variables
   and equating all top types.
-* Removed the `dart:mirrors` library from the SDK. Use of this library on the
-  web has been unsupported and prevented by the Dart build systems since Dart
-  v2.0.0. All known exception cases have been cleaned up. This change makes DDC
-  and dart2js now issue a compile-time error directly as well.
 * **Breaking Change**: Types are now normalized. See [normalization] for the
   full specification. Types will now be printed in their normal form, and
   mutual subtypes with the same normal form will now be considered equal.
@@ -144,13 +152,13 @@
 
 #### Linter
 
-The Linter was updated to `0.1.112`, which includes:
+The Linter was updated to `0.1.113`, which includes:
 
-* new lint: `use_raw_strings`
-* new lint: `unnecessary_raw_strings`
-* new lint: `avoid_escaping_inner_quotes`
-* new lint: `unnecessary_string_escapes`
-* incompatible rule documentation improvements
+* updated documentation links
+* `one_member_abstracts` updated to not lint classes with mixins or implementing interfaces
+* `unnecessary_getters_setters` fixed to ignore cases where a getter/setter is deprecated
+* new lint: `leading_newlines_in_multiline_strings`
+* improved highlight ranges for `avoid_private_typedef_functions` and `avoid_returning_null_for_future`
 
 #### Analyzer
 
@@ -235,6 +243,14 @@
 
 [17207]: https://github.com/dart-lang/sdk/issues/17207
 
+## 2.7.2 - 2020-03-16
+
+This is a patch release that improves compatibility with ARMv8 processors
+(issue [40001][]) and dart:io stability (issue [40589][]).
+
+[40001]: https://github.com/dart-lang/sdk/issues/40001
+[40589]: https://github.com/dart-lang/sdk/issues/40589
+
 ## 2.7.1 - 2020-01-23
 
 This is a patch release that improves dart2js compile-time (issue [40217][]).
diff --git a/DEPS b/DEPS
index 141a264..353c1c2 100644
--- a/DEPS
+++ b/DEPS
@@ -39,7 +39,7 @@
   # co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
   # hashes. It requires access to the dart-build-access group, which EngProd
   # has.
-  "co19_rev": "34a1386e6e7d3e27f5f2b4461aeb6f8794ab55c7",
+  "co19_rev": "51ee35d0459ad329287254b79ed3918d78b5bbf3",
   "co19_2_rev": "368bfa9e877a2df003547f64bb17e30596af10c7",
 
   # As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
@@ -56,8 +56,8 @@
   "gperftools_revision": "e9ab4c53041ac62feefbbb076d326e9a77dd1567",
 
   # Revisions of /third_party/* dependencies.
-  "args_tag": "1.5.3",
-  "async_tag": "2.0.8",
+  "args_tag": "1.6.0",
+  "async_tag": "2.4.1",
   "bazel_worker_tag": "v0.1.22",
   "benchmark_harness_tag": "81641290dea44c34138a109a37e215482f405f81",
   "boolean_selector_tag" : "1.0.4",
@@ -102,7 +102,7 @@
   "intl_tag": "0.15.7",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "2.0.9",
-  "linter_tag": "0.1.112",
+  "linter_tag": "0.1.113",
   "logging_tag": "0.11.3+2",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_tag": "2.1.1",
@@ -120,7 +120,7 @@
   "pool_tag": "1.3.6",
   "protobuf_rev": "3746c8fd3f2b0147623a8e3db89c3ff4330de760",
   "pub_rev": "429a06039d185149f387a65e3503b0693ce6d24e",
-  "pub_semver_tag": "1.4.2",
+  "pub_semver_tag": "v1.4.4",
   "quiver-dart_tag": "2.0.0+1",
   "resource_rev": "f8e37558a1c4f54550aa463b88a6a831e3e33cd6",
   "root_certificates_rev": "16ef64be64c7dfdff2b9f4b910726e635ccc519e",
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 e3e5ffb..6d316e6 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -2941,6 +2941,15 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExportOptOutFromOptIn = messageExportOptOutFromOptIn;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExportOptOutFromOptIn = const MessageCode(
+    "ExportOptOutFromOptIn",
+    message:
+        r"""Null safe libraries are not allowed to export declarations from of opt-out libraries.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeExpressionNotMetadata = messageExpressionNotMetadata;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_aware_access.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_aware_access.dart
index 44c192f0..586dcd2 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_aware_access.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/nullability/data/null_aware_access.dart
@@ -104,13 +104,13 @@
   // holds the result of evaluating the cascade target.  So
   // effectively, no promotion happens (because there is no way to
   // observe a change to the type of that variable).
-  c?..setter = /*cfe.nonNullable*/ c;
-  c?..getterSetter += /*cfe.nonNullable*/ c;
-  c?..getterSetter ??= /*cfe.nonNullable*/ c;
-  c?..[/*cfe.nonNullable*/ c];
-  c?..[/*cfe.nonNullable*/ c] = /*cfe.nonNullable*/ c;
-  c?..[/*cfe.nonNullable*/ c] += /*cfe.nonNullable*/ c;
-  c?..[/*cfe.nonNullable*/ c] ??= /*cfe.nonNullable*/ c;
+  c?..setter = /*nonNullable*/ c;
+  c?..getterSetter += /*nonNullable*/ c;
+  c?..getterSetter ??= /*nonNullable*/ c;
+  c?..[/*nonNullable*/ c];
+  c?..[/*nonNullable*/ c] = /*nonNullable*/ c;
+  c?..[/*nonNullable*/ c] += /*nonNullable*/ c;
+  c?..[/*nonNullable*/ c] ??= /*nonNullable*/ c;
 }
 
 void null_aware_cascades_do_not_promote_others(C? c, int? i, int? j) {
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/main.dart
index d824359..11d144e 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/main.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/in_out_in/main.dart
@@ -9,8 +9,7 @@
 
 /*class: SubClass1:Class,Interface,LegacyClass1,Object,SubClass1*/
 class SubClass1 extends LegacyClass1 {
-  /*cfe|cfe:builder.member: SubClass1.method:int Function(int?)*/
-  /*analyzer.member: SubClass1.method:int* Function(int*)**/
+  /*member: SubClass1.method:int* Function(int*)**/
 }
 
 /*class: SubClass2:Class,Interface,LegacyClass2,Object,SubClass2*/
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/infer_from_opt_in/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_from_opt_in/main.dart
new file mode 100644
index 0000000..2784dd4
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_from_opt_in/main.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for 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: nnbd=false*/
+
+// @dart = 2.5
+import 'opt_in.dart';
+
+/*class: LegacyClass1:Class,LegacyClass1,Object*/
+abstract class LegacyClass1 extends Class {
+  /*member: LegacyClass1.getter:int**/
+  /*member: LegacyClass1.method:int* Function()**/
+}
+
+/*class: LegacyClass2:Class,LegacyClass1,LegacyClass2,Object*/
+class LegacyClass2 extends Class implements LegacyClass1 {
+  /*member: LegacyClass2.method:int* Function()**/
+  method() => 0;
+
+  /*member: LegacyClass2.getter:int**/
+  get getter => 0;
+}
+
+/*class: LegacyClass3:Class,LegacyClass1,LegacyClass3,Object*/
+class LegacyClass3 extends LegacyClass1 {
+  /*member: LegacyClass3.method:int* Function()**/
+  method() => 0;
+
+  /*member: LegacyClass3.getter:int**/
+  get getter => 0;
+}
+
+/*class: EnvironmentMap:
+ EnvironmentMap,Map<String*, String*>,
+ MapBase<String*, String*>,
+ MapMixin<String*, String*>,
+ Object,
+ UnmodifiableMapBase<String*, String*>,
+ _UnmodifiableMapMixin<String*, String*>
+*/
+class EnvironmentMap extends UnmodifiableMapBase<String, String> {
+  /*member: EnvironmentMap.keys:Iterable<String*>**/
+  get keys => null;
+}
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/infer_from_opt_in/opt_in.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_from_opt_in/opt_in.dart
new file mode 100644
index 0000000..fef7d40
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/infer_from_opt_in/opt_in.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for 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: nnbd=true*/
+
+/*class: Class:Class,Object*/
+class Class {
+  /*member: Class.method:int Function()*/
+  int method() => 0;
+
+  /*member: Class.getter:int*/
+  int get getter => 0;
+}
+
+/*class: Map:Map<K, V>,Object*/
+abstract class Map<K, V> {
+  /*member: Map.keys:Iterable<K>*/
+  Iterable<K> get keys;
+}
+
+/*class: MapMixin:Map<K, V>,MapMixin<K, V>,Object*/
+abstract class MapMixin<K, V> implements Map<K, V> {
+  /*member: MapMixin.keys:Iterable<K>*/
+  Iterable<K> get keys;
+}
+
+/*class: MapBase:Map<K, V>,MapBase<K, V>,MapMixin<K, V>,Object*/
+abstract class MapBase<K, V> extends MapMixin<K, V> {
+  /*member: MapBase.keys:Iterable<K>*/
+}
+
+/*class: _UnmodifiableMapMixin:Map<K, V>,Object,_UnmodifiableMapMixin<K, V>*/
+abstract class _UnmodifiableMapMixin<K, V> implements Map<K, V> {
+  /*member: _UnmodifiableMapMixin.keys:Iterable<K>*/
+}
+
+/*cfe|cfe:builder.class: UnmodifiableMapBase:Map<K, V>,MapBase<K, V>,MapMixin<K, V>,Object,UnmodifiableMapBase<K, V>,_UnmodifiableMapMixin<K, V>*/
+/*cfe|cfe:builder.member: UnmodifiableMapBase.keys:Iterable<K>*/
+// TODO(johnniwinther,paulberry): Support named mixin declarations in id-tests.
+abstract class UnmodifiableMapBase<K, V> = MapBase<K, V>
+    with _UnmodifiableMapMixin<K, V>;
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40414/main.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40414/main.dart
index 8814e85..0d2ea90 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/issue40414/main.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/issue40414/main.dart
@@ -8,10 +8,8 @@
 
 /*class: B:A,B,NONNULLABLE,NULLABLE,Object*/
 class B extends A {
-  /*cfe|cfe:builder.member: B.i:int*/
-  /*analyzer.member: B.i:int**/
-  /*cfe|cfe:builder.member: B.i=:int?*/
-  /*analyzer.member: B.i=:int**/
+  /*member: B.i:int**/
+  /*member: B.i=:int**/
 }
 
 /*class: C:A,C,NONNULLABLE,NULLABLE,Object*/
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart
index 41a226e..65dfce3 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/core.dart
@@ -15,6 +15,8 @@
 
   bool operator ==(Object other) => true;
 
+  int get hashCode => 0;
+
   noSuchMethod(Invocation invocation) => null;
 
   String toString() => '';
diff --git a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/opt_out.dart b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/opt_out.dart
index 9173b62..ccf00fe 100644
--- a/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/opt_out.dart
+++ b/pkg/_fe_analyzer_shared/test/inheritance/data/object_opt_in/opt_out.dart
@@ -8,16 +8,17 @@
 
 /*class: Class1:Class1,Object*/
 class Class1 {
+  /*member: Class1.hashCode:int**/
   /*member: Class1.noSuchMethod:dynamic Function(Invocation*)**/
   /*member: Class1.toString:String* Function()**/
 
-  /*cfe|cfe:builder.member: Class1.==:bool* Function(dynamic)**/
-  /*analyzer.member: Class1.==:bool Function(dynamic)**/
+  /*member: Class1.==:bool* Function(dynamic)**/
   operator ==(other) => true;
 }
 
 /*class: Class2a:Class2a,Object*/
 abstract class Class2a {
+  /*member: Class2a.hashCode:int**/
   /*member: Class2a.noSuchMethod:dynamic Function(Invocation*)**/
   /*member: Class2a.toString:String* Function()**/
 
@@ -27,20 +28,24 @@
 
 /*class: Class2b:Class2a,Class2b,Object*/
 class Class2b extends Class2a {
+  /*member: Class2b.hashCode:int**/
   /*member: Class2b.noSuchMethod:dynamic Function(Invocation*)**/
   /*member: Class2b.toString:String* Function()**/
   /*member: Class2b.==:bool* Function(Object*)**/
 }
 
 /*class: Class3a:Class3a,Object*/
+/*member: Class3a.hashCode:int**/
 class Class3a {
   /*member: Class3a.noSuchMethod:dynamic Function(Invocation*)**/
   /*member: Class3a.toString:String* Function()**/
-  /*member: Class3a.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: Class3a.==:bool* Function(dynamic)**/
+/*analyzer.member: Class3a.==:bool* Function(Object*)**/
 }
 
 /*class: Class3b:Class3a,Class3b,Object*/
 abstract class Class3b extends Class3a {
+  /*member: Class3b.hashCode:int**/
   /*member: Class3b.noSuchMethod:dynamic Function(Invocation*)**/
   /*member: Class3b.toString:String* Function()**/
 
@@ -50,6 +55,7 @@
 
 /*class: Class3c:Class3a,Class3b,Class3c,Object*/
 class Class3c extends Class3b {
+  /*member: Class3c.hashCode:int**/
   /*member: Class3c.noSuchMethod:dynamic Function(Invocation*)**/
   /*member: Class3c.toString:String* Function()**/
   /*member: Class3c.==:bool* Function(Object*)**/
@@ -57,15 +63,20 @@
 
 /*class: Foo:Foo,Object*/
 class Foo extends /*error: TypeNotFound*/ Unresolved {
+  /*member: Foo.hashCode:int**/
   /*member: Foo.noSuchMethod:dynamic Function(Invocation*)**/
   /*member: Foo.toString:String* Function()**/
-  /*member: Foo.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: Foo.==:bool* Function(dynamic)**/
+/*analyzer.member: Foo.==:bool* Function(Object*)**/
 }
 
 /*class: A:A,Object*/
 abstract class A {
+  /*member: A.hashCode:int**/
   /*member: A.noSuchMethod:dynamic Function(Invocation*)**/
-  /*member: A.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: A.==:bool* Function(dynamic)**/
+
+  /*analyzer.member: A.==:bool* Function(Object*)**/
 
   /*member: A.toString:String* Function({bool* withNullability})**/
   String toString({bool withNullability = false}) {
@@ -75,8 +86,11 @@
 
 /*class: B:A,B,Object*/
 abstract class B implements A {
+  /*member: B.hashCode:int**/
   /*member: B.toString:String* Function({bool* withNullability})**/
-  /*member: B.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: B.==:bool* Function(dynamic)**/
+
+  /*analyzer.member: B.==:bool* Function(Object*)**/
 
   /*member: B.noSuchMethod:dynamic Function(Invocation*)**/
   noSuchMethod(Invocation invocation) {
@@ -88,16 +102,21 @@
 
 /*class: AbstractExpression:AbstractExpression,Object*/
 abstract class AbstractExpression {
+  /*member: AbstractExpression.hashCode:int**/
   /*member: AbstractExpression.toString:String* Function()**/
   /*member: AbstractExpression.noSuchMethod:dynamic Function(Invocation*)**/
-  /*member: AbstractExpression.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: AbstractExpression.==:bool* Function(dynamic)**/
+/*analyzer.member: AbstractExpression.==:bool* Function(Object*)**/
 }
 
 /*class: ExpressionWithEval:ExpressionWithEval,Object*/
 abstract class ExpressionWithEval {
+  /*member: ExpressionWithEval.hashCode:int**/
   /*member: ExpressionWithEval.toString:String* Function()**/
   /*member: ExpressionWithEval.noSuchMethod:dynamic Function(Invocation*)**/
-  /*member: ExpressionWithEval.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: ExpressionWithEval.==:bool* Function(dynamic)**/
+
+  /*analyzer.member: ExpressionWithEval.==:bool* Function(Object*)**/
 
   /*member: ExpressionWithEval.eval:int**/
   int get eval;
@@ -105,8 +124,11 @@
 
 /*class: ExpressionWithStringConversion:ExpressionWithStringConversion,Object*/
 abstract class ExpressionWithStringConversion {
+  /*member: ExpressionWithStringConversion.hashCode:int**/
   /*member: ExpressionWithStringConversion.noSuchMethod:dynamic Function(Invocation*)**/
-  /*member: ExpressionWithStringConversion.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: ExpressionWithStringConversion.==:bool* Function(dynamic)**/
+
+  /*analyzer.member: ExpressionWithStringConversion.==:bool* Function(Object*)**/
 
   /*member: ExpressionWithStringConversion.toString:String* Function()**/
   String toString();
@@ -116,7 +138,9 @@
 /*member: Expression.toString:String* Function()**/
 /*member: Expression.eval:int**/
 /*member: Expression.noSuchMethod:dynamic Function(Invocation*)**/
-/*member: Expression.==:bool* Function(Object*)**/
+/*cfe|cfe:builder.member: Expression.==:bool* Function(dynamic)**/
+/*analyzer.member: Expression.==:bool* Function(Object*)**/
+/*member: Expression.hashCode:int**/
 abstract class Expression = AbstractExpression
     with ExpressionWithEval, ExpressionWithStringConversion;
 
@@ -124,9 +148,12 @@
 
 /*class: A2:A2,Object*/
 abstract class A2 {
+  /*member: A2.hashCode:int**/
   /*member: A2.toString:String* Function()**/
   /*member: A2.noSuchMethod:dynamic Function(Invocation*)**/
-  /*member: A2.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: A2.==:bool* Function(dynamic)**/
+
+  /*analyzer.member: A2.==:bool* Function(Object*)**/
 
   /*member: A2.a:int**/
   int get a;
@@ -134,9 +161,12 @@
 
 /*class: B2:B2,Object*/
 abstract class B2 {
+  /*member: B2.hashCode:int**/
   /*member: B2.toString:String* Function()**/
   /*member: B2.noSuchMethod:dynamic Function(Invocation*)**/
-  /*member: B2.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: B2.==:bool* Function(dynamic)**/
+
+  /*analyzer.member: B2.==:bool* Function(Object*)**/
 
   /*member: B2.b:int**/
   int get b;
@@ -144,25 +174,80 @@
 
 /*class: M2:A2,B2,M2,Object*/
 abstract class M2 implements A2, B2 {
+  /*member: M2.hashCode:int**/
   /*member: M2.b:int**/
   /*member: M2.a:int**/
   /*member: M2.toString:String* Function()**/
   /*member: M2.noSuchMethod:dynamic Function(Invocation*)**/
-  /*member: M2.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: M2.==:bool* Function(dynamic)**/
+/*analyzer.member: M2.==:bool* Function(Object*)**/
 }
 
 /*class: S2:Object,S2*/
+/*member: S2.hashCode:int**/
 class S2 {
   /*member: S2.toString:String* Function()**/
   /*member: S2.noSuchMethod:dynamic Function(Invocation*)**/
-  /*member: S2.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: S2.==:bool* Function(dynamic)**/
+/*analyzer.member: S2.==:bool* Function(Object*)**/
 }
 
 /*class: C2:A2,B2,C2,M2,Object,S2*/
+/*member: C2.hashCode:int**/
 class /*error: MissingImplementationNotAbstract*/ C2 extends S2 with M2 {
   /*member: C2.b:int**/
   /*member: C2.a:int**/
   /*member: C2.toString:String* Function()**/
   /*member: C2.noSuchMethod:dynamic Function(Invocation*)**/
-  /*member: C2.==:bool* Function(Object*)**/
+  /*cfe|cfe:builder.member: C2.==:bool* Function(dynamic)**/
+/*analyzer.member: C2.==:bool* Function(Object*)**/
+}
+
+/*class: SuperClass:Object,SuperClass*/
+class SuperClass {
+  /*member: SuperClass.toString:String* Function()**/
+  /*member: SuperClass.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: SuperClass.hashCode:int**/
+  /*cfe|cfe:builder.member: SuperClass.==:bool* Function(dynamic)**/
+/*analyzer.member: SuperClass.==:bool* Function(Object*)**/
+}
+
+/*class: Interface1:Interface1,Object*/
+class Interface1 {
+  /*member: Interface1.toString:String* Function()**/
+  /*member: Interface1.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: Interface1.hashCode:int**/
+  /*cfe|cfe:builder.member: Interface1.==:bool* Function(dynamic)**/
+/*analyzer.member: Interface1.==:bool* Function(Object*)**/
+}
+
+/*class: Interface2:Interface1,Interface2,Object*/
+class Interface2 extends Interface1 {
+  /*member: Interface2.toString:String* Function()**/
+  /*member: Interface2.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: Interface2.hashCode:int**/
+  /*cfe|cfe:builder.member: Interface2.==:bool* Function(dynamic)**/
+/*analyzer.member: Interface2.==:bool* Function(Object*)**/
+}
+
+/*class: SubClass1:Object,SubClass1,SuperClass*/
+class SubClass1 implements SuperClass {
+  /*member: SubClass1.toString:String* Function()**/
+  /*member: SubClass1.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: SubClass1.hashCode:int**/
+  get hashCode => 0;
+
+  /*member: SubClass1.==:bool* Function(dynamic)**/
+  operator ==(var other) => false;
+}
+
+/*class: SubClass2:Interface1,Interface2,Object,SubClass2,SuperClass*/
+class SubClass2 extends SuperClass implements Interface2 {
+  /*member: SubClass2.toString:String* Function()**/
+  /*member: SubClass2.noSuchMethod:dynamic Function(Invocation*)**/
+  /*member: SubClass2.hashCode:int**/
+  get hashCode => 0;
+
+  /*member: SubClass2.==:bool* Function(dynamic)**/
+  operator ==(var other) => false;
 }
diff --git a/pkg/analysis_server/benchmark/benchmarks.dart b/pkg/analysis_server/benchmark/benchmarks.dart
index e20e28a..2926da8 100644
--- a/pkg/analysis_server/benchmark/benchmarks.dart
+++ b/pkg/analysis_server/benchmark/benchmarks.dart
@@ -30,6 +30,127 @@
   runner.run(args);
 }
 
+String get analysisServerSrcPath {
+  String script = Platform.script.toFilePath(windows: Platform.isWindows);
+  String pkgPath = path.normalize(path.join(path.dirname(script), '..', '..'));
+  return path.join(pkgPath, 'analysis_server');
+}
+
+void deleteServerCache() {
+  // ~/.dartServer/.analysis-driver/
+  ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
+  Folder stateLocation = resourceProvider.getStateLocation('.analysis-driver');
+  try {
+    if (stateLocation.exists) {
+      stateLocation.delete();
+    }
+  } catch (e) {
+    // ignore any exception
+  }
+}
+
+List<String> getProjectRoots({bool quick = false}) {
+  String script = Platform.script.toFilePath(windows: Platform.isWindows);
+  String pkgPath = path.normalize(path.join(path.dirname(script), '..', '..'));
+  return <String>[path.join(pkgPath, quick ? 'meta' : 'analysis_server')];
+}
+
+abstract class Benchmark {
+  final String id;
+  final String description;
+  final bool enabled;
+
+  /// One of 'memory', 'cpu', or 'group'.
+  final String kind;
+
+  Benchmark(this.id, this.description,
+      {this.enabled = true, this.kind = 'cpu'});
+
+  int get maxIterations => 0;
+
+  bool get needsSetup => false;
+
+  Future oneTimeCleanup() => Future.value();
+
+  Future oneTimeSetup() => Future.value();
+
+  Future<BenchMarkResult> run({
+    bool quick = false,
+    bool verbose = false,
+  });
+
+  Map toJson() =>
+      {'id': id, 'description': description, 'enabled': enabled, 'kind': kind};
+
+  @override
+  String toString() => '$id: $description';
+}
+
+class BenchMarkResult {
+  static final NumberFormat nf = NumberFormat.decimalPattern();
+
+  /// One of 'bytes', 'micros', or 'compound'.
+  final String kindName;
+
+  final int value;
+
+  BenchMarkResult(this.kindName, this.value);
+
+  BenchMarkResult combine(BenchMarkResult other) {
+    return BenchMarkResult(kindName, math.min(value, other.value));
+  }
+
+  Map toJson() => {kindName: value};
+
+  @override
+  String toString() => '$kindName: ${nf.format(value)}';
+}
+
+class CompoundBenchMarkResult extends BenchMarkResult {
+  final String name;
+
+  Map<String, BenchMarkResult> results = {};
+
+  CompoundBenchMarkResult(this.name) : super('compound', 0);
+
+  void add(String name, BenchMarkResult result) {
+    results[name] = result;
+  }
+
+  @override
+  BenchMarkResult combine(BenchMarkResult other) {
+    BenchMarkResult _combine(BenchMarkResult a, BenchMarkResult b) {
+      if (a == null) return b;
+      if (b == null) return a;
+      return a.combine(b);
+    }
+
+    CompoundBenchMarkResult o = other as CompoundBenchMarkResult;
+
+    CompoundBenchMarkResult combined = CompoundBenchMarkResult(name);
+    List<String> keys =
+        (<String>{}..addAll(results.keys)..addAll(o.results.keys)).toList();
+
+    for (String key in keys) {
+      combined.add(key, _combine(results[key], o.results[key]));
+    }
+
+    return combined;
+  }
+
+  @override
+  Map toJson() {
+    Map m = {};
+    for (String key in results.keys) {
+      m['$name-$key'] = results[key].toJson();
+    }
+    return m;
+  }
+
+  @override
+  String toString() => '${toJson()}';
+}
+
 class ListCommand extends Command {
   final List<Benchmark> benchmarks;
 
@@ -39,15 +160,15 @@
   }
 
   @override
-  String get name => 'list';
-
-  @override
   String get description => 'List available benchmarks.';
 
   @override
   String get invocation => '${runner.executableName} $name';
 
   @override
+  String get name => 'list';
+
+  @override
   void run() {
     if (argResults['machine'] as bool) {
       final Map map = {
@@ -79,15 +200,15 @@
   }
 
   @override
-  String get name => 'run';
-
-  @override
   String get description => 'Run a given benchmark.';
 
   @override
   String get invocation => '${runner.executableName} $name <benchmark-id>';
 
   @override
+  String get name => 'run';
+
+  @override
   Future run() async {
     if (argResults.rest.isEmpty) {
       printUsage();
@@ -144,124 +265,3 @@
     }
   }
 }
-
-abstract class Benchmark {
-  final String id;
-  final String description;
-  final bool enabled;
-
-  /// One of 'memory', 'cpu', or 'group'.
-  final String kind;
-
-  Benchmark(this.id, this.description,
-      {this.enabled = true, this.kind = 'cpu'});
-
-  bool get needsSetup => false;
-
-  Future oneTimeSetup() => Future.value();
-
-  Future oneTimeCleanup() => Future.value();
-
-  Future<BenchMarkResult> run({
-    bool quick = false,
-    bool verbose = false,
-  });
-
-  int get maxIterations => 0;
-
-  Map toJson() =>
-      {'id': id, 'description': description, 'enabled': enabled, 'kind': kind};
-
-  @override
-  String toString() => '$id: $description';
-}
-
-class BenchMarkResult {
-  static final NumberFormat nf = NumberFormat.decimalPattern();
-
-  /// One of 'bytes', 'micros', or 'compound'.
-  final String kindName;
-
-  final int value;
-
-  BenchMarkResult(this.kindName, this.value);
-
-  BenchMarkResult combine(BenchMarkResult other) {
-    return BenchMarkResult(kindName, math.min(value, other.value));
-  }
-
-  Map toJson() => {kindName: value};
-
-  @override
-  String toString() => '$kindName: ${nf.format(value)}';
-}
-
-class CompoundBenchMarkResult extends BenchMarkResult {
-  final String name;
-
-  CompoundBenchMarkResult(this.name) : super('compound', 0);
-
-  Map<String, BenchMarkResult> results = {};
-
-  void add(String name, BenchMarkResult result) {
-    results[name] = result;
-  }
-
-  @override
-  BenchMarkResult combine(BenchMarkResult other) {
-    BenchMarkResult _combine(BenchMarkResult a, BenchMarkResult b) {
-      if (a == null) return b;
-      if (b == null) return a;
-      return a.combine(b);
-    }
-
-    CompoundBenchMarkResult o = other as CompoundBenchMarkResult;
-
-    CompoundBenchMarkResult combined = CompoundBenchMarkResult(name);
-    List<String> keys =
-        (<String>{}..addAll(results.keys)..addAll(o.results.keys)).toList();
-
-    for (String key in keys) {
-      combined.add(key, _combine(results[key], o.results[key]));
-    }
-
-    return combined;
-  }
-
-  @override
-  Map toJson() {
-    Map m = {};
-    for (String key in results.keys) {
-      m['$name-$key'] = results[key].toJson();
-    }
-    return m;
-  }
-
-  @override
-  String toString() => '${toJson()}';
-}
-
-List<String> getProjectRoots({bool quick = false}) {
-  String script = Platform.script.toFilePath(windows: Platform.isWindows);
-  String pkgPath = path.normalize(path.join(path.dirname(script), '..', '..'));
-  return <String>[path.join(pkgPath, quick ? 'meta' : 'analysis_server')];
-}
-
-String get analysisServerSrcPath {
-  String script = Platform.script.toFilePath(windows: Platform.isWindows);
-  String pkgPath = path.normalize(path.join(path.dirname(script), '..', '..'));
-  return path.join(pkgPath, 'analysis_server');
-}
-
-void deleteServerCache() {
-  // ~/.dartServer/.analysis-driver/
-  ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
-  Folder stateLocation = resourceProvider.getStateLocation('.analysis-driver');
-  try {
-    if (stateLocation.exists) {
-      stateLocation.delete();
-    }
-  } catch (e) {
-    // ignore any exception
-  }
-}
diff --git a/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart b/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart
index 70ed839..0bdc7e1 100644
--- a/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart
+++ b/pkg/analysis_server/benchmark/perf/benchmarks_impl.dart
@@ -13,51 +13,6 @@
 import 'memory_tests.dart';
 
 /// benchmarks:
-///   - analysis-server-cold-analysis
-///   - analysis-server-cold-memory
-class ColdAnalysisBenchmark extends Benchmark {
-  ColdAnalysisBenchmark()
-      : super(
-            'analysis-server-cold',
-            'Analysis server benchmarks of a large project on start-up, no '
-                'existing driver cache.',
-            kind: 'group');
-
-  @override
-  int get maxIterations => 3;
-
-  @override
-  Future<BenchMarkResult> run({
-    bool quick = false,
-    bool verbose = false,
-  }) async {
-    if (!quick) {
-      deleteServerCache();
-    }
-
-    Stopwatch stopwatch = Stopwatch()..start();
-
-    AnalysisServerMemoryUsageTest test = AnalysisServerMemoryUsageTest();
-    await test.setUp();
-    await test.subscribeToStatusNotifications();
-    await test.sendAnalysisSetAnalysisRoots(getProjectRoots(quick: quick), []);
-    await test.analysisFinished;
-
-    stopwatch.stop();
-    int usedBytes = await test.getMemoryUsage();
-
-    CompoundBenchMarkResult result = CompoundBenchMarkResult(id);
-    result.add(
-        'analysis', BenchMarkResult('micros', stopwatch.elapsedMicroseconds));
-    result.add('memory', BenchMarkResult('bytes', usedBytes));
-
-    await test.shutdown();
-
-    return result;
-  }
-}
-
-/// benchmarks:
 ///   - analysis-server-warm-analysis
 ///   - analysis-server-warm-memory
 ///   - analysis-server-edit
@@ -109,35 +64,6 @@
     return result;
   }
 
-  Future<int> _calcEditTiming(
-      AbstractAnalysisServerIntegrationTest test) async {
-    const int kGroupCount = 5;
-
-    final String filePath =
-        path.join(analysisServerSrcPath, 'lib/src/analysis_server.dart');
-    String contents = File(filePath).readAsStringSync();
-
-    await test
-        .sendAnalysisUpdateContent({filePath: AddContentOverlay(contents)});
-
-    final Stopwatch stopwatch = Stopwatch()..start();
-
-    for (int i = 0; i < kGroupCount; i++) {
-      int startIndex = i * (contents.length ~/ (kGroupCount + 2));
-      int index = contents.indexOf(';', startIndex);
-      contents = contents.substring(0, index + 1) +
-          ' ' +
-          contents.substring(index + 1);
-      await test
-          .sendAnalysisUpdateContent({filePath: AddContentOverlay(contents)});
-      await test.analysisFinished;
-    }
-
-    stopwatch.stop();
-
-    return stopwatch.elapsedMicroseconds ~/ kGroupCount;
-  }
-
   Future<int> _calcCompletionTiming(
       AbstractAnalysisServerIntegrationTest test) async {
     const int kGroupCount = 10;
@@ -200,4 +126,78 @@
 
     return stopwatch.elapsedMicroseconds ~/ completionCount;
   }
+
+  Future<int> _calcEditTiming(
+      AbstractAnalysisServerIntegrationTest test) async {
+    const int kGroupCount = 5;
+
+    final String filePath =
+        path.join(analysisServerSrcPath, 'lib/src/analysis_server.dart');
+    String contents = File(filePath).readAsStringSync();
+
+    await test
+        .sendAnalysisUpdateContent({filePath: AddContentOverlay(contents)});
+
+    final Stopwatch stopwatch = Stopwatch()..start();
+
+    for (int i = 0; i < kGroupCount; i++) {
+      int startIndex = i * (contents.length ~/ (kGroupCount + 2));
+      int index = contents.indexOf(';', startIndex);
+      contents = contents.substring(0, index + 1) +
+          ' ' +
+          contents.substring(index + 1);
+      await test
+          .sendAnalysisUpdateContent({filePath: AddContentOverlay(contents)});
+      await test.analysisFinished;
+    }
+
+    stopwatch.stop();
+
+    return stopwatch.elapsedMicroseconds ~/ kGroupCount;
+  }
+}
+
+/// benchmarks:
+///   - analysis-server-cold-analysis
+///   - analysis-server-cold-memory
+class ColdAnalysisBenchmark extends Benchmark {
+  ColdAnalysisBenchmark()
+      : super(
+            'analysis-server-cold',
+            'Analysis server benchmarks of a large project on start-up, no '
+                'existing driver cache.',
+            kind: 'group');
+
+  @override
+  int get maxIterations => 3;
+
+  @override
+  Future<BenchMarkResult> run({
+    bool quick = false,
+    bool verbose = false,
+  }) async {
+    if (!quick) {
+      deleteServerCache();
+    }
+
+    Stopwatch stopwatch = Stopwatch()..start();
+
+    AnalysisServerMemoryUsageTest test = AnalysisServerMemoryUsageTest();
+    await test.setUp();
+    await test.subscribeToStatusNotifications();
+    await test.sendAnalysisSetAnalysisRoots(getProjectRoots(quick: quick), []);
+    await test.analysisFinished;
+
+    stopwatch.stop();
+    int usedBytes = await test.getMemoryUsage();
+
+    CompoundBenchMarkResult result = CompoundBenchMarkResult(id);
+    result.add(
+        'analysis', BenchMarkResult('micros', stopwatch.elapsedMicroseconds));
+    result.add('memory', BenchMarkResult('bytes', usedBytes));
+
+    await test.shutdown();
+
+    return result;
+  }
 }
diff --git a/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart b/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
index cf8f498..d2827ca 100644
--- a/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
+++ b/pkg/analysis_server/benchmark/perf/flutter_analyze_benchmark.dart
@@ -10,9 +10,40 @@
 
 import '../benchmarks.dart';
 
+Future<int> _runProcess(
+  String command,
+  List<String> args, {
+  String cwd,
+  bool failOnError = true,
+}) async {
+  print('\n$command ${args.join(' ')}');
+
+  Process process = await Process.start(command, args, workingDirectory: cwd);
+
+  process.stdout
+      .transform(utf8.decoder)
+      .transform(LineSplitter())
+      .listen((line) {
+    print('  $line');
+  });
+  process.stderr
+      .transform(utf8.decoder)
+      .transform(LineSplitter())
+      .listen((line) => print('  $line'));
+
+  int exitCode = await process.exitCode;
+  if (exitCode != 0 && failOnError) {
+    throw '$command exited with $exitCode';
+  }
+
+  return exitCode;
+}
+
 /// benchmarks:
 ///   - analysis-flutter-analyze
 class FlutterAnalyzeBenchmark extends Benchmark {
+  Directory flutterDir;
+
   FlutterAnalyzeBenchmark()
       : super(
           'analysis-flutter-analyze',
@@ -23,9 +54,21 @@
         );
 
   @override
+  int get maxIterations => 3;
+
+  @override
   bool get needsSetup => true;
 
-  Directory flutterDir;
+  @override
+  Future oneTimeCleanup() {
+    try {
+      flutterDir.deleteSync(recursive: true);
+    } on FileSystemException catch (e) {
+      print(e);
+    }
+
+    return Future.value();
+  }
 
   @override
   Future oneTimeSetup() async {
@@ -51,20 +94,6 @@
   }
 
   @override
-  Future oneTimeCleanup() {
-    try {
-      flutterDir.deleteSync(recursive: true);
-    } on FileSystemException catch (e) {
-      print(e);
-    }
-
-    return Future.value();
-  }
-
-  @override
-  int get maxIterations => 3;
-
-  @override
   Future<BenchMarkResult> run({
     bool quick = false,
     bool verbose = false,
@@ -96,32 +125,3 @@
     return BenchMarkResult('micros', stopwatch.elapsedMicroseconds);
   }
 }
-
-Future<int> _runProcess(
-  String command,
-  List<String> args, {
-  String cwd,
-  bool failOnError = true,
-}) async {
-  print('\n$command ${args.join(' ')}');
-
-  Process process = await Process.start(command, args, workingDirectory: cwd);
-
-  process.stdout
-      .transform(utf8.decoder)
-      .transform(LineSplitter())
-      .listen((line) {
-    print('  $line');
-  });
-  process.stderr
-      .transform(utf8.decoder)
-      .transform(LineSplitter())
-      .listen((line) => print('  $line'));
-
-  int exitCode = await process.exitCode;
-  if (exitCode != 0 && failOnError) {
-    throw '$command exited with $exitCode';
-  }
-
-  return exitCode;
-}
diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
index 163288d..4d7cf75 100644
--- a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
@@ -112,12 +112,6 @@
       }
     }
 
-    // Process each package
-    for (Folder pkgFolder in pkgFolders) {
-      await processPackage(pkgFolder);
-    }
-
-    bool hasErrors = false;
     String changedPath;
     contextManager.driverMap.values.forEach((driver) {
       // Setup a listener to remember the resource that changed during analysis
@@ -127,22 +121,12 @@
       };
     });
 
-    // Process each source file.
+    // Set up the rerun function on the NNBD migration for interactivity.
+    nonNullableFixTask?.rerunFunction = rerunTasks;
+
+    bool hasErrors;
     try {
-      await processResources((ResolvedUnitResult result) async {
-        if (await processErrors(result)) {
-          hasErrors = true;
-        }
-        if (numPhases > 0) {
-          await processCodeTasks(0, result);
-        }
-      });
-      for (int phase = 1; phase < numPhases; phase++) {
-        await processResources((ResolvedUnitResult result) async {
-          await processCodeTasks(phase, result);
-        });
-      }
-      await finishCodeTasks();
+      hasErrors = await runAllTasks();
     } on InconsistentAnalysisException catch (_) {
       // If a resource changed, report the problem without suggesting fixes
       var changedMessage = changedPath != null
@@ -151,13 +135,10 @@
       return EditDartfixResult(
         [DartFixSuggestion('Analysis canceled because $changedMessage')],
         listener.otherSuggestions,
-        hasErrors,
+        false, // We may have errors, but we do not know, and it doesn't matter.
         listener.sourceChange.edits,
         details: listener.details,
       ).toResponse(request.id);
-    } finally {
-      server.contextManager.driverMap.values
-          .forEach((d) => d.onCurrentSessionAboutToBeDiscarded = null);
     }
 
     return EditDartfixResult(
@@ -263,4 +244,45 @@
       await process(result);
     }
   }
+
+  Future<bool> rerunTasks(List<String> changedPaths) async {
+    for (String path in changedPaths) {
+      var driver = server.getAnalysisDriver(path);
+      driver.changeFile(path);
+    }
+
+    return await runAllTasks();
+  }
+
+  Future<bool> runAllTasks() async {
+    // Process each package
+    for (Folder pkgFolder in pkgFolders) {
+      await processPackage(pkgFolder);
+    }
+
+    bool hasErrors = false;
+
+    // Process each source file.
+    try {
+      await processResources((ResolvedUnitResult result) async {
+        if (await processErrors(result)) {
+          hasErrors = true;
+        }
+        if (numPhases > 0) {
+          await processCodeTasks(0, result);
+        }
+      });
+      for (int phase = 1; phase < numPhases; phase++) {
+        await processResources((ResolvedUnitResult result) async {
+          await processCodeTasks(phase, result);
+        });
+      }
+      await finishCodeTasks();
+    } finally {
+      server.contextManager.driverMap.values
+          .forEach((d) => d.onCurrentSessionAboutToBeDiscarded = null);
+    }
+
+    return hasErrors;
+  }
 }
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 98d45fc..7ea3adf 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
@@ -55,14 +55,12 @@
   /// If this occurs, then don't update any code.
   bool _packageIsNNBD = true;
 
+  Future<void> Function(List<String>) rerunFunction;
+
   NonNullableFix(this.listener, {List<String> included = const []})
       : includedRoot =
             _getIncludedRoot(included, listener.server.resourceProvider) {
-    instrumentationListener = InstrumentationListener();
-    adapter = NullabilityMigrationAdapter(listener);
-    migration = NullabilityMigration(adapter,
-        permissive: _usePermissiveMode,
-        instrumentation: instrumentationListener);
+    reset();
   }
 
   @override
@@ -76,15 +74,15 @@
 
   @override
   Future<void> finish() async {
-    migration.finish();
-
-    var state = MigrationState(
+    final state = MigrationState(
         migration, includedRoot, listener, instrumentationListener, adapter);
     await state.refresh();
 
-    server = HttpPreviewServer(state);
-    server.serveHttp();
-    port = await server.boundPort;
+    if (server == null) {
+      server = HttpPreviewServer(state, rerun);
+      server.serveHttp();
+      port = await server.boundPort;
+    }
   }
 
   /// If the package contains an analysis_options.yaml file, then update the
@@ -220,6 +218,23 @@
     _packageIsNNBD = false;
   }
 
+  Future<MigrationState> rerun(List<String> changedPaths) async {
+    reset();
+    await rerunFunction(changedPaths);
+    final state = MigrationState(
+        migration, includedRoot, listener, instrumentationListener, adapter);
+    await state.refresh();
+    return state;
+  }
+
+  void reset() {
+    instrumentationListener = InstrumentationListener();
+    adapter = NullabilityMigrationAdapter(listener);
+    migration = NullabilityMigration(adapter,
+        permissive: _usePermissiveMode,
+        instrumentation: instrumentationListener);
+  }
+
   static void task(DartFixRegistrar registrar, DartFixListener listener,
       EditDartfixParams params) {
     registrar
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 4a4e1da..bf2926f2 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
@@ -514,9 +514,32 @@
     }).toList();
   }
 
-  TraceInfo _computeTraceInfo(NullabilityNodeInfo node) {
+  void _computeTraceNonNullableInfo(
+      NullabilityNodeInfo node, List<TraceInfo> traces) {
+    List<TraceEntryInfo> entries = [];
+    var step = node.whyNotNullable;
+    if (step == null) {
+      return;
+    }
+    assert(identical(step.node, node));
+    while (step != null) {
+      entries.add(_nodeToTraceEntry(step.node));
+      if (step.codeReference != null) {
+        entries.add(_stepToTraceEntry(step));
+      }
+      step = step.principalCause;
+    }
+    var description = 'Non-nullability reason';
+    traces.add(TraceInfo(description, entries));
+  }
+
+  void _computeTraceNullableInfo(
+      NullabilityNodeInfo node, List<TraceInfo> traces) {
     List<TraceEntryInfo> entries = [];
     var step = node.whyNullable;
+    if (step == null) {
+      return;
+    }
     assert(identical(step.targetNode, node));
     while (step != null) {
       entries.add(_nodeToTraceEntry(step.targetNode));
@@ -526,25 +549,26 @@
       step = step.principalCause;
     }
     var description = 'Nullability reason';
-    return TraceInfo(description, entries);
+    traces.add(TraceInfo(description, entries));
   }
 
   List<TraceInfo> _computeTraces(List<FixReasonInfo> fixReasons) {
-    var nodes = <NullabilityNodeInfo>[];
+    List<TraceInfo> traces = [];
     for (var reason in fixReasons) {
       if (reason is NullabilityNodeInfo) {
         if (reason.isNullable) {
-          nodes.add(reason);
+          _computeTraceNullableInfo(reason, traces);
         }
       } else if (reason is EdgeInfo) {
         assert(reason.sourceNode.isNullable);
         assert(!reason.destinationNode.isNullable);
-        nodes.add(reason.sourceNode);
+        _computeTraceNullableInfo(reason.sourceNode, traces);
+        _computeTraceNonNullableInfo(reason.destinationNode, traces);
       } else {
         assert(false, 'Unrecognized reason type: ${reason.runtimeType}');
       }
     }
-    return [for (var node in nodes) _computeTraceInfo(node)];
+    return traces;
   }
 
   /// Compute details about [edgeInfos] which are upstream triggered.
@@ -815,81 +839,93 @@
   /// enclosing top-level member.
   @visibleForTesting
   static String buildEnclosingMemberDescription(AstNode node) {
-    String functionName;
-    String baseDescription;
-
-    void describeFunction(AstNode node) {
-      if (node is ConstructorDeclaration) {
-        if (node.name == null) {
-          baseDescription = 'the default constructor of';
-          functionName = '';
+    for (var enclosingNode = node;
+        enclosingNode != null;
+        enclosingNode = enclosingNode.parent) {
+      if (enclosingNode is ConstructorDeclaration) {
+        if (enclosingNode.name == null) {
+          return _describeClassOrExtensionMember(
+              enclosingNode.parent, 'the default constructor of', '');
         } else {
-          baseDescription = 'the constructor';
-          functionName = node.name.name;
+          return _describeClassOrExtensionMember(
+              enclosingNode.parent, 'the constructor', enclosingNode.name.name);
         }
-      } else if (node is MethodDeclaration) {
-        functionName = node.name.name;
-        if (node.isGetter) {
+      } else if (enclosingNode is MethodDeclaration) {
+        var functionName = enclosingNode.name.name;
+        String baseDescription;
+        if (enclosingNode.isGetter) {
           baseDescription = 'the getter';
-        } else if (node.isOperator) {
+        } else if (enclosingNode.isOperator) {
           baseDescription = 'the operator';
-        } else if (node.isSetter) {
+        } else if (enclosingNode.isSetter) {
           baseDescription = 'the setter';
           functionName += '=';
         } else {
           baseDescription = 'the method';
         }
-      } else if (node is FunctionDeclaration) {
-        functionName = node.name.name;
-        if (node.isGetter) {
+        return _describeClassOrExtensionMember(
+            enclosingNode.parent, baseDescription, functionName);
+      } else if (enclosingNode is FunctionDeclaration &&
+          enclosingNode.parent is CompilationUnit) {
+        var functionName = enclosingNode.name.name;
+        String baseDescription;
+        if (enclosingNode.isGetter) {
           baseDescription = 'the getter';
-        } else if (node.isSetter) {
+        } else if (enclosingNode.isSetter) {
           baseDescription = 'the setter';
           functionName += '=';
         } else {
           baseDescription = 'the function';
         }
-      } else if (node is FieldDeclaration) {
-        var field = node.thisOrAncestorOfType<VariableDeclaration>();
-        field ??= node.fields.variables[0];
-        functionName = field.name.name;
-        baseDescription = 'the field';
+        return "$baseDescription '$functionName'";
+      } else if (enclosingNode is VariableDeclaration) {
+        var description = _describeVariableDeclaration(enclosingNode);
+        if (description != null) return description;
+      } else if (enclosingNode is VariableDeclarationList) {
+        var description =
+            _describeVariableDeclaration(enclosingNode.variables[0]);
+        if (description != null) return description;
+      }
+    }
+    throw ArgumentError(
+        "Can't describe enclosing member of ${node.runtimeType}");
+  }
+
+  static String _describeClassOrExtensionMember(CompilationUnitMember parent,
+      String baseDescription, String functionName) {
+    if (parent is NamedCompilationUnitMember) {
+      String parentName = parent.name.name;
+      if (functionName.isEmpty) {
+        return "$baseDescription '$parentName'";
       } else {
-        // Throwing here allows us to gather more information. Not throwing here
-        // causes an NPE on line 709.
-        throw ArgumentError("Can't describe function in ${node.runtimeType}");
+        return "$baseDescription '$parentName.$functionName'";
       }
-    }
-
-    var enclosingClassMember = node.thisOrAncestorOfType<ClassMember>();
-
-    if (enclosingClassMember != null) {
-      describeFunction(enclosingClassMember);
-      CompilationUnitMember member = enclosingClassMember.parent;
-      if (member is NamedCompilationUnitMember) {
-        String memberName = member.name.name;
-        if (functionName.isEmpty) {
-          return "$baseDescription '$memberName'";
-        } else {
-          return "$baseDescription '$memberName.$functionName'";
-        }
-      } else if (member is ExtensionDeclaration) {
-        if (member.name == null) {
-          var extendedTypeString = member.extendedType.type.getDisplayString(
-            withNullability: false,
-          );
-          return "$baseDescription '$functionName' in unnamed extension on $extendedTypeString";
-        } else {
-          return "$baseDescription '${member.name.name}.$functionName'";
-        }
+    } else if (parent is ExtensionDeclaration) {
+      if (parent.name == null) {
+        var extendedTypeString = parent.extendedType.type.getDisplayString(
+          withNullability: false,
+        );
+        return "$baseDescription '$functionName' in unnamed extension on $extendedTypeString";
+      } else {
+        return "$baseDescription '${parent.name.name}.$functionName'";
       }
+    } else {
+      throw ArgumentError(
+          'Unexpected class or extension type ${parent.runtimeType}');
     }
-    FunctionDeclaration enclosingFunction =
-        node.thisOrAncestorOfType<FunctionDeclaration>();
-    if (enclosingFunction is FunctionDeclaration) {
-      describeFunction(enclosingFunction);
-      return "$baseDescription '$functionName'";
+  }
+
+  static String _describeVariableDeclaration(VariableDeclaration node) {
+    var variableName = node.name.name;
+    var parent = node.parent;
+    var grandParent = parent.parent;
+    if (grandParent is FieldDeclaration) {
+      return _describeClassOrExtensionMember(
+          grandParent.parent, 'the field', variableName);
+    } else if (grandParent is TopLevelVariableDeclaration) {
+      return "the variable '$variableName'";
+    } else {
+      return null;
     }
-    return null;
   }
 }
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
index 7a86ab0..a80ef58 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_info.dart
@@ -123,7 +123,7 @@
   }
 
   @override
-  String toString() => 'NavigationTarget["$filePath", $offset, $length]';
+  String toString() => 'NavigationTarget["$filePath", $line, $offset, $length]';
 }
 
 /// An additional detail related to a region.
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_state.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_state.dart
index fc06728..e0e2a7f 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_state.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/migration_state.dart
@@ -44,7 +44,7 @@
       this.instrumentationListener, this.adapter);
 
   /// Refresh the state of the migration after the migration has been updated.
-  void refresh() async {
+  Future<void> refresh() async {
     assert(!hasBeenApplied);
     OverlayResourceProvider provider = listener.server.resourceProvider;
     InfoBuilder infoBuilder = InfoBuilder(provider, includedRoot,
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/navigation_tree_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/navigation_tree_renderer.dart
index 8fd1348..124a631 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/navigation_tree_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/navigation_tree_renderer.dart
@@ -2,13 +2,24 @@
 // for details. 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 jsonEncode;
-
 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/nnbd_migration/unit_link.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/web/navigation_tree.dart';
 import 'package:path/path.dart' as path;
 
+/// Groups the items in [iterable] by the result of applying [groupFn] to each
+/// item.
+Map<K, List<T>> _groupBy<K, T>(
+    Iterable<T> iterable, K Function(T item) groupFn) {
+  var result = <K, List<T>>{};
+  for (var item in iterable) {
+    var key = groupFn(item);
+    result.putIfAbsent(key, () => <T>[]).add(item);
+  }
+  return result;
+}
+
 /// The HTML that is displayed for a region of code.
 class NavigationTreeRenderer {
   final MigrationInfo migrationInfo;
@@ -25,44 +36,30 @@
   path.Context get pathContext => migrationInfo.pathContext;
 
   /// Renders the navigation link tree.
-  String render() {
+  List<NavigationTreeNode> render() {
     var linkData = migrationInfo.unitLinks();
-    var tree = _renderNavigationSubtree(linkData, 0);
-    return jsonEncode(tree);
+    return _renderNavigationSubtree(linkData, 0);
   }
 
   /// Renders the navigation link subtree at [depth].
-  List<Object> _renderNavigationSubtree(List<UnitLink> links, int depth) {
+  List<NavigationTreeNode> _renderNavigationSubtree(
+      List<UnitLink> links, int depth) {
     var linksGroupedByDirectory = _groupBy(
         links.where((link) => link.depth > depth),
         (UnitLink link) => link.pathParts[depth]);
     return [
       for (var entry in linksGroupedByDirectory.entries)
-        {
-          'type': 'directory',
-          'name': entry.key,
-          'subtree': _renderNavigationSubtree(entry.value, depth + 1),
-        },
+        NavigationTreeNode.directory(
+          name: entry.key,
+          subtree: _renderNavigationSubtree(entry.value, depth + 1),
+        ),
       for (var link in links.where((link) => link.depth == depth))
-        {
-          'type': 'file',
-          'name': link.fileName,
-          'path': pathContext.joinAll(link.pathParts),
-          'href': link.url,
-          'editCount': link.editCount,
-        },
+        NavigationTreeNode.file(
+          name: link.fileName,
+          path: pathContext.joinAll(link.pathParts),
+          href: link.url,
+          editCount: link.editCount,
+        ),
     ];
   }
 }
-
-/// Groups the items in [iterable] by the result of applying [groupFn] to each
-/// item.
-Map<K, List<T>> _groupBy<K, T>(
-    Iterable<T> iterable, K Function(T item) groupFn) {
-  var result = <K, List<T>>{};
-  for (var item in iterable) {
-    var key = groupFn(item);
-    result.putIfAbsent(key, () => <T>[]).add(item);
-  }
-  return result;
-}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/region_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/region_renderer.dart
index f2de90d..30e228b 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/region_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/region_renderer.dart
@@ -10,7 +10,7 @@
 /// The HTML that is displayed for a region of code.
 class RegionRenderer {
   /// A flag indicating whether the incremental workflow is currently supported.
-  static const bool supportsIncrementalWorkflow = false;
+  static const bool supportsIncrementalWorkflow = true;
 
   /// The region to render.
   final RegionInfo region;
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
index 816c805..9dbed6e 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/index.html
@@ -8,6 +8,9 @@
     <style>{{ dartPageStyle }}</style>
 </head>
 <body class="{{ migrationAppliedStyle }}">
+<div class="rerunning-pane">
+  <h1>Rerunning...</h1>
+</div>
 <p class="root">{{ root }}</p>
 <header class="elevation-z4">
     <h1 class="before-apply">Proposed null safety changes</h1>
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/migration.css b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/migration.css
index fa34d2e..0c63e02 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/migration.css
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/migration.css
@@ -356,6 +356,28 @@
   cursor: pointer;
 }
 
+.rerunning-pane {
+  display: none;
+}
+
+body.rerunning .rerunning-pane {
+  display: block;
+  position: fixed;
+  top: 0px;
+  bottom: 0px;
+  left: 0px;
+  right: 0px;
+  background-color: #000000AA; /* translucent black */
+  z-index: 400;
+}
+
+.rerunning-pane h1 {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+
 p.trace .type-description {
   /* From HLJS's .hljs-keyword, .hljs-selector-tag, .hljs-deletion */
   color: #cc7832;
@@ -434,4 +456,4 @@
    * This allows the per-line highlights to show.
    */
   background: none;
-}
\ No newline at end of file
+}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
index 6c54a4b..3a39789 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/resources/resources.g.dart
@@ -270,7 +270,7 @@
 ''';
 
 String _index_html;
-// index_html md5 is '4ba111f269b722a6918f949e993b1238'
+// index_html md5 is '5ea053889e3c34ee57db31a5a3d2d8b9'
 String _index_html_base64 = '''
 PGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPk51bGwgU2FmZXR5IFByZXZpZXc8L3RpdGxlPgogICAgPHNj
 cmlwdCBzcmM9Int7IGhpZ2hsaWdodEpzUGF0aCB9fSI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0Pnt7IGRh
@@ -278,7 +278,8 @@
 dHBzOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzP2ZhbWlseT1PcGVuK1NhbnM6NDAwLDYwMCZkaXNw
 bGF5PXN3YXAiPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJ7eyBoaWdobGlnaHRTdHls
 ZVBhdGggfX0iPgogICAgPHN0eWxlPnt7IGRhcnRQYWdlU3R5bGUgfX08L3N0eWxlPgo8L2hlYWQ+Cjxi
-b2R5IGNsYXNzPSJ7eyBtaWdyYXRpb25BcHBsaWVkU3R5bGUgfX0iPgo8cCBjbGFzcz0icm9vdCI+e3sg
+b2R5IGNsYXNzPSJ7eyBtaWdyYXRpb25BcHBsaWVkU3R5bGUgfX0iPgo8ZGl2IGNsYXNzPSJyZXJ1bm5p
+bmctcGFuZSI+CiAgPGgxPlJlcnVubmluZy4uLjwvaDE+CjwvZGl2Pgo8cCBjbGFzcz0icm9vdCI+e3sg
 cm9vdCB9fTwvcD4KPGhlYWRlciBjbGFzcz0iZWxldmF0aW9uLXo0Ij4KICAgIDxoMSBjbGFzcz0iYmVm
 b3JlLWFwcGx5Ij5Qcm9wb3NlZCBudWxsIHNhZmV0eSBjaGFuZ2VzPC9oMT4KICAgIDxoMSBjbGFzcz0i
 YWZ0ZXItYXBwbHkiPiYjMTAwMDM7IE51bGwgc2FmZXR5IG1pZ3JhdGlvbiBhcHBsaWVkPC9oMT4KICAg
@@ -315,7 +316,7 @@
 ''';
 
 String _migration_css;
-// migration_css md5 is 'da758dd7ff2eb51b7bf862613b1029a7'
+// migration_css md5 is '2bfe65627f29ccb0a43fa1b79569a571'
 String _migration_css_base64 = '''
 LyogQ29weXJpZ2h0IChjKSAyMDE5LCB0aGUgRGFydCBwcm9qZWN0IGF1dGhvcnMuIFBsZWFzZSBzZWUg
 dGhlIEFVVEhPUlMgZmlsZSAgKi8KLyogZm9yIGRldGFpbHMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIFVz
@@ -405,32 +406,38 @@
 YWNrZ3JvdW5kLWNvbG9yOiAjMjgyYjJlOwogIG92ZXJmbG93OiBhdXRvOwp9CgouZWRpdC1wYW5lbCB7
 CiAgbWFyZ2luLXRvcDogNnB4OwogIGZsZXg6IDEgMTAwcHg7Cn0KCi5lZGl0LWxpc3QgewogIGZsZXg6
 IDIgMTAwcHg7Cn0KCi5lZGl0LWxpc3QgLmVkaXQgewogIG1hcmdpbjogM3B4IDA7Cn0KCi5lZGl0LWxp
-c3QgLmVkaXQtbGluayB7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgpwLnRyYWNlIC50eXBlLWRlc2NyaXB0
-aW9uIHsKICAvKiBGcm9tIEhMSlMncyAuaGxqcy1rZXl3b3JkLCAuaGxqcy1zZWxlY3Rvci10YWcsIC5o
-bGpzLWRlbGV0aW9uICovCiAgY29sb3I6ICNjYzc4MzI7CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsK
-fQoKdWwudHJhY2UgewogIGZvbnQtc2l6ZTogMTNweDsKICBsaXN0LXN0eWxlLXR5cGU6IG5vbmU7CiAg
-cGFkZGluZy1sZWZ0OiAwcHg7Cn0KCnVsLnRyYWNlIGxpIHsKICBjb2xvcjogd2hpdGU7CiAgbWFyZ2lu
-LWxlZnQ6IDE0cHg7CiAgdGV4dC1pbmRlbnQ6IC0xNHB4Owp9Cgp1bC50cmFjZSBsaSAuZnVuY3Rpb24g
-ewogIC8qIEZyb20gSExKUydzIC5obGpzLXNlY3Rpb24sIC5obGpzLXRpdGxlLCAuaGxqcy10eXBlICov
-CiAgY29sb3I6ICNmZmM2NmQ7CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsKICBmb250LXdlaWdodDog
-NjAwOwp9CgouZWxldmF0aW9uLXo0IHsKICBib3gtc2hhZG93OiAwcHggMnB4IDRweCAtMXB4IHJnYmEo
-MCwgMCwgMCwgMC4yKSwKICAgICAgMHB4IDRweCA1cHggMHB4IHJnYmEoMCwgMCwgMCwgMC4xNCksCiAg
-ICAgIDBweCAxcHggMTBweCAwcHggcmdiYSgwLCAwLCAwLCAuMTIpOwp9CgphIHsKICBjb2xvcjogI2Nj
-YzsKICBmaWxsOiAjY2NjOwogIHRleHQtZGVjb3JhdGlvbjogbm9uZTsKfQoKYTpob3ZlciB7CiAgY29s
-b3I6ICNmZmY7CiAgZmlsbDogI2ZmZjsKfQoKYnV0dG9uIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMzNj
-Y2ZmOwogIGJvcmRlcjogMnB4IHNvbGlkICMzN2FlZGM7CiAgYm9yZGVyLXJhZGl1czogM3B4OwogIHBh
-ZGRpbmc6IDZweCAxMHB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGNvbG9yOiAjMjgyODI4Owp9Cgpi
-dXR0b246aG92ZXIgewogIGJhY2tncm91bmQtY29sb3I6ICM4MGRmZmY7CiAgYm9yZGVyOiAycHggc29s
-aWQgIzUyYjhlMDsKICBjdXJzb3I6IHBvaW50ZXI7Cn0KCmJ1dHRvbltkaXNhYmxlZF0gewogIGJhY2tn
-cm91bmQtY29sb3I6ICM3YWE4Yjg7CiAgY29sb3I6ICM1MDcxNzc7CiAgYm9yZGVyOiAycHggc29saWQg
-IzUwNzE3NzsKICBjdXJzb3I6IG5vdC1hbGxvd2VkOwp9CgoucGxhY2Vob2xkZXIgewogIGNvbG9yOiAj
-Nzc3OwogIHRleHQtYWxpZ246IGNlbnRlcjsKICBtYXJnaW4tdG9wOiAzZW0gIWltcG9ydGFudDsKfQoK
-LyoqCiAqIEhMSlMgT3ZlcnJpZGVzCiAqLwouaGxqcyB7CiAgLyoqCiAgICogVGhpcyBhbGxvd3MgdGhl
-IHBlci1saW5lIGhpZ2hsaWdodHMgdG8gc2hvdy4KICAgKi8KICBiYWNrZ3JvdW5kOiBub25lOwp9
+c3QgLmVkaXQtbGluayB7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgoucmVydW5uaW5nLXBhbmUgewogIGRp
+c3BsYXk6IG5vbmU7Cn0KCmJvZHkucmVydW5uaW5nIC5yZXJ1bm5pbmctcGFuZSB7CiAgZGlzcGxheTog
+YmxvY2s7CiAgcG9zaXRpb246IGZpeGVkOwogIHRvcDogMHB4OwogIGJvdHRvbTogMHB4OwogIGxlZnQ6
+IDBweDsKICByaWdodDogMHB4OwogIGJhY2tncm91bmQtY29sb3I6ICMwMDAwMDBBQTsgLyogdHJhbnNs
+dWNlbnQgYmxhY2sgKi8KICB6LWluZGV4OiA0MDA7Cn0KCi5yZXJ1bm5pbmctcGFuZSBoMSB7CiAgcG9z
+aXRpb246IGFic29sdXRlOwogIHRvcDogNTAlOwogIGxlZnQ6IDUwJTsKICB0cmFuc2Zvcm06IHRyYW5z
+bGF0ZSgtNTAlLCAtNTAlKTsKfQoKcC50cmFjZSAudHlwZS1kZXNjcmlwdGlvbiB7CiAgLyogRnJvbSBI
+TEpTJ3MgLmhsanMta2V5d29yZCwgLmhsanMtc2VsZWN0b3ItdGFnLCAuaGxqcy1kZWxldGlvbiAqLwog
+IGNvbG9yOiAjY2M3ODMyOwogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7Cn0KCnVsLnRyYWNlIHsKICBm
+b250LXNpemU6IDEzcHg7CiAgbGlzdC1zdHlsZS10eXBlOiBub25lOwogIHBhZGRpbmctbGVmdDogMHB4
+Owp9Cgp1bC50cmFjZSBsaSB7CiAgY29sb3I6IHdoaXRlOwogIG1hcmdpbi1sZWZ0OiAxNHB4OwogIHRl
+eHQtaW5kZW50OiAtMTRweDsKfQoKdWwudHJhY2UgbGkgLmZ1bmN0aW9uIHsKICAvKiBGcm9tIEhMSlMn
+cyAuaGxqcy1zZWN0aW9uLCAuaGxqcy10aXRsZSwgLmhsanMtdHlwZSAqLwogIGNvbG9yOiAjZmZjNjZk
+OwogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7CiAgZm9udC13ZWlnaHQ6IDYwMDsKfQoKLmVsZXZhdGlv
+bi16NCB7CiAgYm94LXNoYWRvdzogMHB4IDJweCA0cHggLTFweCByZ2JhKDAsIDAsIDAsIDAuMiksCiAg
+ICAgIDBweCA0cHggNXB4IDBweCByZ2JhKDAsIDAsIDAsIDAuMTQpLAogICAgICAwcHggMXB4IDEwcHgg
+MHB4IHJnYmEoMCwgMCwgMCwgLjEyKTsKfQoKYSB7CiAgY29sb3I6ICNjY2M7CiAgZmlsbDogI2NjYzsK
+ICB0ZXh0LWRlY29yYXRpb246IG5vbmU7Cn0KCmE6aG92ZXIgewogIGNvbG9yOiAjZmZmOwogIGZpbGw6
+ICNmZmY7Cn0KCmJ1dHRvbiB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzY2NmZjsKICBib3JkZXI6IDJw
+eCBzb2xpZCAjMzdhZWRjOwogIGJvcmRlci1yYWRpdXM6IDNweDsKICBwYWRkaW5nOiA2cHggMTBweDsK
+ICBmb250LXdlaWdodDogYm9sZDsKICBjb2xvcjogIzI4MjgyODsKfQoKYnV0dG9uOmhvdmVyIHsKICBi
+YWNrZ3JvdW5kLWNvbG9yOiAjODBkZmZmOwogIGJvcmRlcjogMnB4IHNvbGlkICM1MmI4ZTA7CiAgY3Vy
+c29yOiBwb2ludGVyOwp9CgpidXR0b25bZGlzYWJsZWRdIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjN2Fh
+OGI4OwogIGNvbG9yOiAjNTA3MTc3OwogIGJvcmRlcjogMnB4IHNvbGlkICM1MDcxNzc7CiAgY3Vyc29y
+OiBub3QtYWxsb3dlZDsKfQoKLnBsYWNlaG9sZGVyIHsKICBjb2xvcjogIzc3NzsKICB0ZXh0LWFsaWdu
+OiBjZW50ZXI7CiAgbWFyZ2luLXRvcDogM2VtICFpbXBvcnRhbnQ7Cn0KCi8qKgogKiBITEpTIE92ZXJy
+aWRlcwogKi8KLmhsanMgewogIC8qKgogICAqIFRoaXMgYWxsb3dzIHRoZSBwZXItbGluZSBoaWdobGln
+aHRzIHRvIHNob3cuCiAgICovCiAgYmFja2dyb3VuZDogbm9uZTsKfQo=
 ''';
 
 String _migration_js;
-// migration_dart md5 is '796c253ccc9415268d590a41365d5951'
+// migration_dart md5 is 'fed856f862bffea0f76b893ef77223dc'
 String _migration_js_base64 = '''
 KGZ1bmN0aW9uIGRhcnRQcm9ncmFtKCl7ZnVuY3Rpb24gY29weVByb3BlcnRpZXMoYSxiKXt2YXIgdD1P
 YmplY3Qua2V5cyhhKQpmb3IodmFyIHM9MDtzPHQubGVuZ3RoO3MrKyl7dmFyIHI9dFtzXQpiW3JdPWFb
@@ -529,3346 +536,3415 @@
 ZiB0IT0ic3RyaW5nIil0aHJvdyBILmIoSC50TChhKSkKcmV0dXJuIHR9LAplUTpmdW5jdGlvbihhKXt2
 YXIgdD1hLiRpZGVudGl0eUhhc2gKaWYodD09bnVsbCl7dD1NYXRoLnJhbmRvbSgpKjB4M2ZmZmZmZmZ8
 MAphLiRpZGVudGl0eUhhc2g9dH1yZXR1cm4gdH0sCkhwOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEs
-cCxvLG49bnVsbAppZih0eXBlb2YgYSE9InN0cmluZyIpSC52aChILnRMKGEpKQp0PS9eXHMqWystXT8o
-KDB4W2EtZjAtOV0rKXwoXGQrKXwoW2EtejAtOV0rKSlccyokL2kuZXhlYyhhKQppZih0PT1udWxsKXJl
-dHVybiBuCmlmKDM+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsMykKcz1ILnkodFszXSkKaWYoYj09bnVs
-bCl7aWYocyE9bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwxMCkKaWYodFsyXSE9bnVsbClyZXR1cm4gcGFy
-c2VJbnQoYSwxNikKcmV0dXJuIG59aWYoYjwyfHxiPjM2KXRocm93IEguYihQLlRFKGIsMiwzNiwicmFk
-aXgiLG4pKQppZihiPT09MTAmJnMhPW51bGwpcmV0dXJuIHBhcnNlSW50KGEsMTApCmlmKGI8MTB8fHM9
-PW51bGwpe3I9Yjw9MTA/NDcrYjo4NitiCnE9dFsxXQpmb3IocD1xLmxlbmd0aCxvPTA7bzxwOysrbylp
-ZigoQy54Qi5XKHEsbyl8MzIpPnIpcmV0dXJuIG59cmV0dXJuIHBhcnNlSW50KGEsYil9LApNOmZ1bmN0
-aW9uKGEpe3ZhciB0PUguSDUoYSkKcmV0dXJuIHR9LApINTpmdW5jdGlvbihhKXt2YXIgdCxzLHIKaWYo
-YSBpbnN0YW5jZW9mIFAuaylyZXR1cm4gSC5kbShILnpLKGEpLG51bGwpCmlmKEouaWEoYSk9PT1DLk9r
-fHx1LmFrLmMoYSkpe3Q9Qy5PNChhKQppZihILmYodCkpcmV0dXJuIHQKcz1hLmNvbnN0cnVjdG9yCmlm
-KHR5cGVvZiBzPT0iZnVuY3Rpb24iKXtyPXMubmFtZQppZih0eXBlb2Ygcj09InN0cmluZyImJkguZihy
-KSlyZXR1cm4gcn19cmV0dXJuIEguZG0oSC56SyhhKSxudWxsKX0sCmY6ZnVuY3Rpb24oYSl7dmFyIHQ9
-YSE9PSJPYmplY3QiJiZhIT09IiIKcmV0dXJuIHR9LApNMDpmdW5jdGlvbigpe2lmKCEhc2VsZi5sb2Nh
-dGlvbilyZXR1cm4gc2VsZi5sb2NhdGlvbi5ocmVmCnJldHVybiBudWxsfSwKVks6ZnVuY3Rpb24oYSl7
-dmFyIHQscyxyLHEscD1hLmxlbmd0aAppZihwPD01MDApcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUu
-YXBwbHkobnVsbCxhKQpmb3IodD0iIixzPTA7czxwO3M9cil7cj1zKzUwMApxPXI8cD9yOnAKdCs9U3Ry
-aW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLGEuc2xpY2UocyxxKSl9cmV0dXJuIHR9LApQTDpmdW5j
-dGlvbihhKXt2YXIgdCxzLHIscT1ILlZNKFtdLHUudCkKZm9yKHQ9YS5sZW5ndGgscz0wO3M8YS5sZW5n
-dGg7YS5sZW5ndGg9PT10fHwoMCxILmxrKShhKSwrK3Mpe3I9YVtzXQppZighSC5vayhyKSl0aHJvdyBI
-LmIoSC50TChyKSkKaWYocjw9NjU1MzUpQy5ObS5pKHEscikKZWxzZSBpZihyPD0xMTE0MTExKXtDLk5t
-LmkocSw1NTI5NisoQy5qbi53RyhyLTY1NTM2LDEwKSYxMDIzKSkKQy5ObS5pKHEsNTYzMjArKHImMTAy
-MykpfWVsc2UgdGhyb3cgSC5iKEgudEwocikpfXJldHVybiBILlZLKHEpfSwKZVQ6ZnVuY3Rpb24oYSl7
-dmFyIHQscyxyCmZvcih0PWEubGVuZ3RoLHM9MDtzPHQ7KytzKXtyPWFbc10KaWYoIUgub2socikpdGhy
-b3cgSC5iKEgudEwocikpCmlmKHI8MCl0aHJvdyBILmIoSC50TChyKSkKaWYocj42NTUzNSlyZXR1cm4g
-SC5QTChhKX1yZXR1cm4gSC5WSyhhKX0sCmZ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihj
-PD01MDAmJmI9PT0wJiZjPT09YS5sZW5ndGgpcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHko
-bnVsbCxhKQpmb3IodD1iLHM9IiI7dDxjO3Q9cil7cj10KzUwMApxPXI8Yz9yOmMKcys9U3RyaW5nLmZy
-b21DaGFyQ29kZS5hcHBseShudWxsLGEuc3ViYXJyYXkodCxxKSl9cmV0dXJuIHN9LApMdzpmdW5jdGlv
-bihhKXt2YXIgdAppZigwPD1hKXtpZihhPD02NTUzNSlyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShh
-KQppZihhPD0xMTE0MTExKXt0PWEtNjU1MzYKcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoKDU1Mjk2
-fEMuam4ud0codCwxMCkpPj4+MCw1NjMyMHx0JjEwMjMpfX10aHJvdyBILmIoUC5URShhLDAsMTExNDEx
-MSxudWxsLG51bGwpKX0sCm8yOmZ1bmN0aW9uKGEpe2lmKGEuZGF0ZT09PXZvaWQgMClhLmRhdGU9bmV3
-IERhdGUoYS5hKQpyZXR1cm4gYS5kYXRlfSwKdEo6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vMihhKS5nZXRG
-dWxsWWVhcigpKzAKcmV0dXJuIHR9LApOUzpmdW5jdGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldE1vbnRo
-KCkrMQpyZXR1cm4gdH0sCmpBOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0RGF0ZSgpKzAKcmV0
-dXJuIHR9LApLTDpmdW5jdGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldEhvdXJzKCkrMApyZXR1cm4gdH0s
-CmNoOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0TWludXRlcygpKzAKcmV0dXJuIHR9LApKZDpm
-dW5jdGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldFNlY29uZHMoKSswCnJldHVybiB0fSwKbzE6ZnVuY3Rp
-b24oYSl7dmFyIHQ9SC5vMihhKS5nZXRNaWxsaXNlY29uZHMoKSswCnJldHVybiB0fSwKem86ZnVuY3Rp
-b24oYSxiLGMpe3ZhciB0LHMscj17fQpyLmE9MAp0PVtdCnM9W10Kci5hPWIubGVuZ3RoCkMuTm0uRlYo
-dCxiKQpyLmI9IiIKaWYoYyE9bnVsbCYmYy5hIT09MCljLksoMCxuZXcgSC5DaihyLHMsdCkpCiIiK3Iu
-YQpyZXR1cm4gSi5KeShhLG5ldyBILkxJKEMuVGUsMCx0LHMsMCkpfSwKRWs6ZnVuY3Rpb24oYSxiLGMp
-e3ZhciB0LHMscixxCmlmKGIgaW5zdGFuY2VvZiBBcnJheSl0PWM9PW51bGx8fGMuYT09PTAKZWxzZSB0
-PSExCmlmKHQpe3M9YgpyPXMubGVuZ3RoCmlmKHI9PT0wKXtpZighIWEuJDApcmV0dXJuIGEuJDAoKX1l
-bHNlIGlmKHI9PT0xKXtpZighIWEuJDEpcmV0dXJuIGEuJDEoc1swXSl9ZWxzZSBpZihyPT09Mil7aWYo
-ISFhLiQyKXJldHVybiBhLiQyKHNbMF0sc1sxXSl9ZWxzZSBpZihyPT09Myl7aWYoISFhLiQzKXJldHVy
-biBhLiQzKHNbMF0sc1sxXSxzWzJdKX1lbHNlIGlmKHI9PT00KXtpZighIWEuJDQpcmV0dXJuIGEuJDQo
-c1swXSxzWzFdLHNbMl0sc1szXSl9ZWxzZSBpZihyPT09NSlpZighIWEuJDUpcmV0dXJuIGEuJDUoc1sw
-XSxzWzFdLHNbMl0sc1szXSxzWzRdKQpxPWFbIiIrIiQiK3JdCmlmKHEhPW51bGwpcmV0dXJuIHEuYXBw
-bHkoYSxzKX1yZXR1cm4gSC5FdyhhLGIsYyl9LApFdzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEs
-cCxvLG4sbSxsLGs9YiBpbnN0YW5jZW9mIEFycmF5P2I6UC5DSChiLCEwLHUueiksaj1rLmxlbmd0aCxp
-PWEuJFIKaWYoajxpKXJldHVybiBILnpvKGEsayxjKQp0PWEuJEQKcz10PT1udWxsCnI9IXM/dCgpOm51
-bGwKcT1KLmlhKGEpCnA9cS4kQwppZih0eXBlb2YgcD09InN0cmluZyIpcD1xW3BdCmlmKHMpe2lmKGMh
-PW51bGwmJmMuYSE9PTApcmV0dXJuIEguem8oYSxrLGMpCmlmKGo9PT1pKXJldHVybiBwLmFwcGx5KGEs
-aykKcmV0dXJuIEguem8oYSxrLGMpfWlmKHIgaW5zdGFuY2VvZiBBcnJheSl7aWYoYyE9bnVsbCYmYy5h
-IT09MClyZXR1cm4gSC56byhhLGssYykKaWYoaj5pK3IubGVuZ3RoKXJldHVybiBILnpvKGEsayxudWxs
-KQpDLk5tLkZWKGssci5zbGljZShqLWkpKQpyZXR1cm4gcC5hcHBseShhLGspfWVsc2V7aWYoaj5pKXJl
-dHVybiBILnpvKGEsayxjKQpvPU9iamVjdC5rZXlzKHIpCmlmKGM9PW51bGwpZm9yKHM9by5sZW5ndGgs
-bj0wO248by5sZW5ndGg7by5sZW5ndGg9PT1zfHwoMCxILmxrKShvKSwrK24pQy5ObS5pKGsscltILnko
-b1tuXSldKQplbHNle2ZvcihzPW8ubGVuZ3RoLG09MCxuPTA7bjxvLmxlbmd0aDtvLmxlbmd0aD09PXN8
-fCgwLEgubGspKG8pLCsrbil7bD1ILnkob1tuXSkKaWYoYy54NChsKSl7KyttCkMuTm0uaShrLGMucSgw
-LGwpKX1lbHNlIEMuTm0uaShrLHJbbF0pfWlmKG0hPT1jLmEpcmV0dXJuIEguem8oYSxrLGMpfXJldHVy
-biBwLmFwcGx5KGEsayl9fSwKcFk6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKEgudEwoYSkpfSwKT0g6ZnVu
-Y3Rpb24oYSxiKXtpZihhPT1udWxsKUouSG0oYSkKdGhyb3cgSC5iKEguSFkoYSxiKSl9LApIWTpmdW5j
-dGlvbihhLGIpe3ZhciB0LHMscj0iaW5kZXgiCmlmKCFILm9rKGIpKXJldHVybiBuZXcgUC51KCEwLGIs
-cixudWxsKQp0PUguU2MoSi5IbShhKSkKaWYoIShiPDApKXtpZih0eXBlb2YgdCE9PSJudW1iZXIiKXJl
-dHVybiBILnBZKHQpCnM9Yj49dH1lbHNlIHM9ITAKaWYocylyZXR1cm4gUC5DZihiLGEscixudWxsLHQp
-CnJldHVybiBQLngoYixyKX0sCmF1OmZ1bmN0aW9uKGEsYixjKXt2YXIgdD0iSW52YWxpZCB2YWx1ZSIK
-aWYoYT5jKXJldHVybiBuZXcgUC5iSigwLGMsITAsYSwic3RhcnQiLHQpCmlmKGIhPW51bGwpe2lmKCFI
-Lm9rKGIpKXJldHVybiBuZXcgUC51KCEwLGIsImVuZCIsbnVsbCkKaWYoYjxhfHxiPmMpcmV0dXJuIG5l
-dyBQLmJKKGEsYywhMCxiLCJlbmQiLHQpfXJldHVybiBuZXcgUC51KCEwLGIsImVuZCIsbnVsbCl9LAp0
-TDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAudSghMCxhLG51bGwsbnVsbCl9LApiOmZ1bmN0aW9uKGEp
-e3ZhciB0CmlmKGE9PW51bGwpYT1uZXcgUC5uKCkKdD1uZXcgRXJyb3IoKQp0LmRhcnRFeGNlcHRpb249
-YQppZigiZGVmaW5lUHJvcGVydHkiIGluIE9iamVjdCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsIm1l
-c3NhZ2UiLHtnZXQ6SC5ofSkKdC5uYW1lPSIifWVsc2UgdC50b1N0cmluZz1ILmgKcmV0dXJuIHR9LApo
-OmZ1bmN0aW9uKCl7cmV0dXJuIEouaih0aGlzLmRhcnRFeGNlcHRpb24pfSwKdmg6ZnVuY3Rpb24oYSl7
-dGhyb3cgSC5iKGEpfSwKbGs6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKFAuYTQoYSkpfSwKY006ZnVuY3Rp
-b24oYSl7dmFyIHQscyxyLHEscCxvCmE9SC5lQShhLnJlcGxhY2UoU3RyaW5nKHt9KSwnJHJlY2VpdmVy
-JCcpKQp0PWEubWF0Y2goL1xcXCRbYS16QS1aXStcXFwkL2cpCmlmKHQ9PW51bGwpdD1ILlZNKFtdLHUu
-cykKcz10LmluZGV4T2YoIlxcJGFyZ3VtZW50c1xcJCIpCnI9dC5pbmRleE9mKCJcXCRhcmd1bWVudHNF
-eHByXFwkIikKcT10LmluZGV4T2YoIlxcJGV4cHJcXCQiKQpwPXQuaW5kZXhPZigiXFwkbWV0aG9kXFwk
-IikKbz10LmluZGV4T2YoIlxcJHJlY2VpdmVyXFwkIikKcmV0dXJuIG5ldyBILlpyKGEucmVwbGFjZShu
-ZXcgUmVnRXhwKCdcXFxcXFwkYXJndW1lbnRzXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkqKScpLnJl
-cGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJGFyZ3VtZW50c0V4cHJcXFxcXFwkJywnZycpLCcoKD86eHxb
-XnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkZXhwclxcXFxcXCQnLCdnJyksJygoPzp4
-fFteeF0pKiknKS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRtZXRob2RcXFxcXFwkJywnZycpLCco
-KD86eHxbXnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkcmVjZWl2ZXJcXFxcXFwkJywn
-ZycpLCcoKD86eHxbXnhdKSopJykscyxyLHEscCxvKX0sClM3OmZ1bmN0aW9uKGEpe3JldHVybiBmdW5j
-dGlvbigkZXhwciQpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7JGV4cHIkLiRt
-ZXRob2QkKCRhcmd1bWVudHNFeHByJCl9Y2F0Y2godCl7cmV0dXJuIHQubWVzc2FnZX19KGEpfSwKTWo6
-ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1bmN0aW9uKCRleHByJCl7dHJ5eyRleHByJC4kbWV0aG9kJH1jYXRj
-aCh0KXtyZXR1cm4gdC5tZXNzYWdlfX0oYSl9LApJajpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5X
-MChhLGI9PW51bGw/bnVsbDpiLm1ldGhvZCl9LApUMzpmdW5jdGlvbihhLGIpe3ZhciB0PWI9PW51bGws
-cz10P251bGw6Yi5tZXRob2QKcmV0dXJuIG5ldyBILmF6KGEscyx0P251bGw6Yi5yZWNlaXZlcil9LApS
-dTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGY9bnVsbCxlPW5ldyBI
-LkFtKGEpCmlmKGE9PW51bGwpcmV0dXJuIGYKaWYodHlwZW9mIGEhPT0ib2JqZWN0IilyZXR1cm4gYQpp
-ZigiZGFydEV4Y2VwdGlvbiIgaW4gYSlyZXR1cm4gZS4kMShhLmRhcnRFeGNlcHRpb24pCmVsc2UgaWYo
-ISgibWVzc2FnZSIgaW4gYSkpcmV0dXJuIGEKdD1hLm1lc3NhZ2UKaWYoIm51bWJlciIgaW4gYSYmdHlw
-ZW9mIGEubnVtYmVyPT0ibnVtYmVyIil7cz1hLm51bWJlcgpyPXMmNjU1MzUKaWYoKEMuam4ud0cocywx
-NikmODE5MSk9PT0xMClzd2l0Y2gocil7Y2FzZSA0Mzg6cmV0dXJuIGUuJDEoSC5UMyhILmQodCkrIiAo
-RXJyb3IgIityKyIpIixmKSkKY2FzZSA0NDU6Y2FzZSA1MDA3OnJldHVybiBlLiQxKEguSWooSC5kKHQp
-KyIgKEVycm9yICIrcisiKSIsZikpfX1pZihhIGluc3RhbmNlb2YgVHlwZUVycm9yKXtxPSQuU24oKQpw
-PSQubHEoKQpvPSQuTjkoKQpuPSQuaUkoKQptPSQuS2YoKQpsPSQuWmgoKQprPSQuck4oKQokLmMzKCkK
-aj0kLkhLKCkKaT0kLnIxKCkKaD1xLnFTKHQpCmlmKGghPW51bGwpcmV0dXJuIGUuJDEoSC5UMyhILnko
-dCksaCkpCmVsc2V7aD1wLnFTKHQpCmlmKGghPW51bGwpe2gubWV0aG9kPSJjYWxsIgpyZXR1cm4gZS4k
-MShILlQzKEgueSh0KSxoKSl9ZWxzZXtoPW8ucVModCkKaWYoaD09bnVsbCl7aD1uLnFTKHQpCmlmKGg9
-PW51bGwpe2g9bS5xUyh0KQppZihoPT1udWxsKXtoPWwucVModCkKaWYoaD09bnVsbCl7aD1rLnFTKHQp
-CmlmKGg9PW51bGwpe2g9bi5xUyh0KQppZihoPT1udWxsKXtoPWoucVModCkKaWYoaD09bnVsbCl7aD1p
-LnFTKHQpCmc9aCE9bnVsbH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxz
-ZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITAKaWYoZylyZXR1cm4gZS4kMShILklqKEgueSh0KSxoKSl9
-fXJldHVybiBlLiQxKG5ldyBILnZWKHR5cGVvZiB0PT0ic3RyaW5nIj90OiIiKSl9aWYoYSBpbnN0YW5j
-ZW9mIFJhbmdlRXJyb3Ipe2lmKHR5cGVvZiB0PT0ic3RyaW5nIiYmdC5pbmRleE9mKCJjYWxsIHN0YWNr
-IikhPT0tMSlyZXR1cm4gbmV3IFAuS1koKQp0PWZ1bmN0aW9uKGIpe3RyeXtyZXR1cm4gU3RyaW5nKGIp
-fWNhdGNoKGQpe31yZXR1cm4gbnVsbH0oYSkKcmV0dXJuIGUuJDEobmV3IFAudSghMSxmLGYsdHlwZW9m
-IHQ9PSJzdHJpbmciP3QucmVwbGFjZSgvXlJhbmdlRXJyb3I6XHMqLywiIik6dCkpfWlmKHR5cGVvZiBJ
-bnRlcm5hbEVycm9yPT0iZnVuY3Rpb24iJiZhIGluc3RhbmNlb2YgSW50ZXJuYWxFcnJvcilpZih0eXBl
-b2YgdD09InN0cmluZyImJnQ9PT0idG9vIG11Y2ggcmVjdXJzaW9uIilyZXR1cm4gbmV3IFAuS1koKQpy
-ZXR1cm4gYX0sCnRzOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIG5ldyBILlhPKGEp
-CnQ9YS4kY2FjaGVkVHJhY2UKaWYodCE9bnVsbClyZXR1cm4gdApyZXR1cm4gYS4kY2FjaGVkVHJhY2U9
-bmV3IEguWE8oYSl9LApCNzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxPWEubGVuZ3RoCmZvcih0PTA7
-dDxxO3Q9cil7cz10KzEKcj1zKzEKYi5ZKDAsYVt0XSxhW3NdKX1yZXR1cm4gYn0sCmZ0OmZ1bmN0aW9u
-KGEsYixjLGQsZSxmKXt1LlouYihhKQpzd2l0Y2goSC5TYyhiKSl7Y2FzZSAwOnJldHVybiBhLiQwKCkK
-Y2FzZSAxOnJldHVybiBhLiQxKGMpCmNhc2UgMjpyZXR1cm4gYS4kMihjLGQpCmNhc2UgMzpyZXR1cm4g
-YS4kMyhjLGQsZSkKY2FzZSA0OnJldHVybiBhLiQ0KGMsZCxlLGYpfXRocm93IEguYihuZXcgUC5DRCgi
-VW5zdXBwb3J0ZWQgbnVtYmVyIG9mIGFyZ3VtZW50cyBmb3Igd3JhcHBlZCBjbG9zdXJlIikpfSwKdFI6
-ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihhPT1udWxsKXJldHVybiBudWxsCnQ9YS4kaWRlbnRpdHkKaWYo
-ISF0KXJldHVybiB0CnQ9ZnVuY3Rpb24oYyxkLGUpe3JldHVybiBmdW5jdGlvbihmLGcsaCxpKXtyZXR1
-cm4gZShjLGQsZixnLGgsaSl9fShhLGIsSC5mdCkKYS4kaWRlbnRpdHk9dApyZXR1cm4gdH0sCmlBOmZ1
-bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciB0LHMscixxLHAsbyxuLG0sbD1udWxsLGs9YlswXSxqPWsu
-JGNhbGxOYW1lLGk9ZT9PYmplY3QuY3JlYXRlKG5ldyBILnp4KCkuY29uc3RydWN0b3IucHJvdG90eXBl
-KTpPYmplY3QuY3JlYXRlKG5ldyBILnJUKGwsbCxsLGwpLmNvbnN0cnVjdG9yLnByb3RvdHlwZSkKaS4k
-aW5pdGlhbGl6ZT1pLmNvbnN0cnVjdG9yCmlmKGUpdD1mdW5jdGlvbiBzdGF0aWNfdGVhcl9vZmYoKXt0
-aGlzLiRpbml0aWFsaXplKCl9CmVsc2V7cz0kLnlqCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJu
-IHMuaCgpCiQueWo9cysxCnM9bmV3IEZ1bmN0aW9uKCJhLGIsYyxkIitzLCJ0aGlzLiRpbml0aWFsaXpl
-KGEsYixjLGQiK3MrIikiKQp0PXN9aS5jb25zdHJ1Y3Rvcj10CnQucHJvdG90eXBlPWkKaWYoIWUpe3I9
-SC5ieChhLGssZikKci4kcmVmbGVjdGlvbkluZm89ZH1lbHNle2kuJHN0YXRpY19uYW1lPWcKcj1rfXE9
-SC5pbShkLGUsZikKaS4kUz1xCmlbal09cgpmb3IocD1yLG89MTtvPGIubGVuZ3RoOysrbyl7bj1iW29d
-Cm09bi4kY2FsbE5hbWUKaWYobSE9bnVsbCl7bj1lP246SC5ieChhLG4sZikKaVttXT1ufWlmKG89PT1j
-KXtuLiRyZWZsZWN0aW9uSW5mbz1kCnA9bn19aS4kQz1wCmkuJFI9ay4kUgppLiREPWsuJEQKcmV0dXJu
-IHR9LAppbTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBm
-dW5jdGlvbihkLGUpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiBkKGUpfX0oSC5CcCxhKQppZih0eXBl
-b2YgYT09InN0cmluZyIpe2lmKGIpdGhyb3cgSC5iKCJDYW5ub3QgY29tcHV0ZSBzaWduYXR1cmUgZm9y
-IHN0YXRpYyB0ZWFyb2ZmLiIpCnQ9Yz9ILlBXOkguVG4KcmV0dXJuIGZ1bmN0aW9uKGQsZSl7cmV0dXJu
-IGZ1bmN0aW9uKCl7cmV0dXJuIGUodGhpcyxkKX19KGEsdCl9dGhyb3cgSC5iKCJFcnJvciBpbiBmdW5j
-dGlvblR5cGUgb2YgdGVhcm9mZiIpfSwKdnE6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9SC5EVgpzd2l0
-Y2goYj8tMTphKXtjYXNlIDA6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0
-dXJuIGYodGhpcylbZV0oKX19KGMsdCkKY2FzZSAxOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBm
-dW5jdGlvbihnKXtyZXR1cm4gZih0aGlzKVtlXShnKX19KGMsdCkKY2FzZSAyOnJldHVybiBmdW5jdGlv
-bihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgpe3JldHVybiBmKHRoaXMpW2VdKGcsaCl9fShjLHQpCmNh
-c2UgMzpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyxoLGkpe3JldHVybiBmKHRo
-aXMpW2VdKGcsaCxpKX19KGMsdCkKY2FzZSA0OnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5j
-dGlvbihnLGgsaSxqKXtyZXR1cm4gZih0aGlzKVtlXShnLGgsaSxqKX19KGMsdCkKY2FzZSA1OnJldHVy
-biBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSxqLGspe3JldHVybiBmKHRoaXMpW2Vd
-KGcsaCxpLGosayl9fShjLHQpCmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0
-aW9uKCl7cmV0dXJuIGUuYXBwbHkoZih0aGlzKSxhcmd1bWVudHMpfX0oZCx0KX19LApieDpmdW5jdGlv
-bihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4KaWYoYylyZXR1cm4gSC5IZihhLGIpCnQ9Yi4kc3R1Yk5h
-bWUKcz1iLmxlbmd0aApyPWFbdF0KcT1iPT1udWxsP3I9PW51bGw6Yj09PXIKcD0hcXx8cz49MjcKaWYo
-cClyZXR1cm4gSC52cShzLCFxLHQsYikKaWYocz09PTApe3E9JC55agppZih0eXBlb2YgcSE9PSJudW1i
-ZXIiKXJldHVybiBxLmgoKQokLnlqPXErMQpvPSJzZWxmIitxCnE9InJldHVybiBmdW5jdGlvbigpe3Zh
-ciAiK28rIiA9IHRoaXMuIgpwPSQubUoKcmV0dXJuIG5ldyBGdW5jdGlvbihxK0guZChwPT1udWxsPyQu
-bUo9SC5FMigic2VsZiIpOnApKyI7cmV0dXJuICIrbysiLiIrSC5kKHQpKyIoKTt9IikoKX1uPSJhYmNk
-ZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiIuc3BsaXQoIiIpLnNwbGljZSgwLHMpLmpvaW4oIiwiKQpxPSQu
-eWoKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gcS5oKCkKJC55aj1xKzEKbis9cQpxPSJyZXR1
-cm4gZnVuY3Rpb24oIituKyIpe3JldHVybiB0aGlzLiIKcD0kLm1KCnJldHVybiBuZXcgRnVuY3Rpb24o
-cStILmQocD09bnVsbD8kLm1KPUguRTIoInNlbGYiKTpwKSsiLiIrSC5kKHQpKyIoIituKyIpO30iKSgp
-fSwKWjQ6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9SC5EVixzPUgueVMKc3dpdGNoKGI/LTE6YSl7Y2Fz
-ZSAwOnRocm93IEguYihILkVmKCJJbnRlcmNlcHRlZCBmdW5jdGlvbiB3aXRoIG5vIGFyZ3VtZW50cy4i
-KSkKY2FzZSAxOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYo
-dGhpcylbZV0oZyh0aGlzKSl9fShjLHQscykKY2FzZSAyOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0
-dXJuIGZ1bmN0aW9uKGgpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCl9fShjLHQscykKY2FzZSAz
-OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSl7cmV0dXJuIGYodGhpcylb
-ZV0oZyh0aGlzKSxoLGkpfX0oYyx0LHMpCmNhc2UgNDpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVy
-biBmdW5jdGlvbihoLGksail7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksail9fShjLHQscykK
-Y2FzZSA1OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqLGspe3JldHVy
-biBmKHRoaXMpW2VdKGcodGhpcyksaCxpLGosayl9fShjLHQscykKY2FzZSA2OnJldHVybiBmdW5jdGlv
-bihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqLGssbCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlz
-KSxoLGksaixrLGwpfX0oYyx0LHMpCmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKGUsZixnLGgpe3JldHVy
-biBmdW5jdGlvbigpe2g9W2codGhpcyldCkFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGgsYXJndW1l
-bnRzKQpyZXR1cm4gZS5hcHBseShmKHRoaXMpLGgpfX0oZCx0LHMpfX0sCkhmOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscyxyLHEscCxvLG4sbT0kLm1KCmlmKG09PW51bGwpbT0kLm1KPUguRTIoInNlbGYiKQp0PSQu
-UDQKaWYodD09bnVsbCl0PSQuUDQ9SC5FMigicmVjZWl2ZXIiKQpzPWIuJHN0dWJOYW1lCnI9Yi5sZW5n
-dGgKcT1hW3NdCnA9Yj09bnVsbD9xPT1udWxsOmI9PT1xCm89IXB8fHI+PTI4CmlmKG8pcmV0dXJuIEgu
-WjQociwhcCxzLGIpCmlmKHI9PT0xKXttPSJyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4iK0gu
-ZChtKSsiLiIrSC5kKHMpKyIodGhpcy4iK0guZCh0KSsiKTsiCnQ9JC55agppZih0eXBlb2YgdCE9PSJu
-dW1iZXIiKXJldHVybiB0LmgoKQokLnlqPXQrMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKG0rdCsifSIpKCl9
-bj0iYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoiLnNwbGl0KCIiKS5zcGxpY2UoMCxyLTEpLmpvaW4o
-IiwiKQptPSJyZXR1cm4gZnVuY3Rpb24oIituKyIpe3JldHVybiB0aGlzLiIrSC5kKG0pKyIuIitILmQo
-cykrIih0aGlzLiIrSC5kKHQpKyIsICIrbisiKTsiCnQ9JC55agppZih0eXBlb2YgdCE9PSJudW1iZXIi
-KXJldHVybiB0LmgoKQokLnlqPXQrMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKG0rdCsifSIpKCl9LApLcTpm
-dW5jdGlvbihhLGIsYyxkLGUsZixnKXtyZXR1cm4gSC5pQShhLGIsYyxkLCEhZSwhIWYsZyl9LApUbjpm
-dW5jdGlvbihhLGIpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLEgueksoYS5hKSxiKX0sClBXOmZ1
-bmN0aW9uKGEsYil7cmV0dXJuIEguY0Uodi50eXBlVW5pdmVyc2UsSC56SyhhLmMpLGIpfSwKRFY6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGEuYX0sCnlTOmZ1bmN0aW9uKGEpe3JldHVybiBhLmN9LApFMjpmdW5jdGlv
-bihhKXt2YXIgdCxzLHIscT1uZXcgSC5yVCgic2VsZiIsInRhcmdldCIsInJlY2VpdmVyIiwibmFtZSIp
-LHA9Si5FcChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhxKSkKZm9yKHQ9cC5sZW5ndGgscz0wO3M8
-dDsrK3Mpe3I9cFtzXQppZihxW3JdPT09YSlyZXR1cm4gcn19LApvVDpmdW5jdGlvbihhKXtpZihhPT1u
-dWxsKUguZk8oImJvb2xlYW4gZXhwcmVzc2lvbiBtdXN0IG5vdCBiZSBudWxsIikKcmV0dXJuIGF9LApm
-TzpmdW5jdGlvbihhKXt0aHJvdyBILmIobmV3IEgua1koYSkpfSwKYWc6ZnVuY3Rpb24oYSl7dGhyb3cg
-SC5iKG5ldyBQLmMoYSkpfSwKRWY6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILkVxKGEpfSwKWWc6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIHYuZ2V0SXNvbGF0ZVRhZyhhKX0sClZNOmZ1bmN0aW9uKGEsYil7YS4kdGk9
-YgpyZXR1cm4gYX0sCm9YOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIGEu
-JHRpfSwKSU06ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBILlk5KGFbIiRhIitILmQoYyldLEgub1goYikp
-fSwKWTk6ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJldHVybiBiCmE9YS5hcHBseShudWxsLGIpCmlm
-KGE9PW51bGwpcmV0dXJuIG51bGwKaWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gYQppZih0eXBlb2Yg
-YT09ImZ1bmN0aW9uIilyZXR1cm4gYS5hcHBseShudWxsLGIpCnJldHVybiBifSwKSUc6ZnVuY3Rpb24o
-YSxiLGMpe3JldHVybiBhLmFwcGx5KGIsSC5ZOShKLmlhKGIpWyIkYSIrSC5kKGMpXSxILm9YKGIpKSl9
-LAppdzpmdW5jdGlvbihhLGIsYyl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsYix7dmFsdWU6YyxlbnVt
-ZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KX0sCnczOmZ1bmN0aW9u
-KGEpe3ZhciB0LHMscixxLHA9SC55KCQuTkYuJDEoYSkpLG89JC5ud1twXQppZihvIT1udWxsKXtPYmpl
-Y3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpvLGVudW1lcmFi
-bGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBvLml9dD0kLnZ2
-W3BdCmlmKHQhPW51bGwpcmV0dXJuIHQKcz12LmludGVyY2VwdG9yc0J5VGFnW3BdCmlmKHM9PW51bGwp
-e3A9SC55KCQuVFguJDIoYSxwKSkKaWYocCE9bnVsbCl7bz0kLm53W3BdCmlmKG8hPW51bGwpe09iamVj
-dC5kZWZpbmVQcm9wZXJ0eShhLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVyYWJs
-ZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX10PSQudnZb
-cF0KaWYodCE9bnVsbClyZXR1cm4gdApzPXYuaW50ZXJjZXB0b3JzQnlUYWdbcF19fWlmKHM9PW51bGwp
-cmV0dXJuIG51bGwKdD1zLnByb3RvdHlwZQpyPXBbMF0KaWYocj09PSIhIil7bz1ILlZhKHQpCiQubndb
-cF09bwpPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpv
-LGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBv
-Lml9aWYocj09PSJ+Iil7JC52dltwXT10CnJldHVybiB0fWlmKHI9PT0iLSIpe3E9SC5WYSh0KQpPYmpl
-Y3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0
-eU5hbWUse3ZhbHVlOnEsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0
-cnVlfSkKcmV0dXJuIHEuaX1pZihyPT09IisiKXJldHVybiBILkxjKGEsdCkKaWYocj09PSIqIil0aHJv
-dyBILmIoUC5TWShwKSkKaWYodi5sZWFmVGFnc1twXT09PXRydWUpe3E9SC5WYSh0KQpPYmplY3QuZGVm
-aW5lUHJvcGVydHkoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUs
-e3ZhbHVlOnEsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkK
-cmV0dXJuIHEuaX1lbHNlIHJldHVybiBILkxjKGEsdCl9LApMYzpmdW5jdGlvbihhLGIpe3ZhciB0PU9i
-amVjdC5nZXRQcm90b3R5cGVPZihhKQpPYmplY3QuZGVmaW5lUHJvcGVydHkodCx2LmRpc3BhdGNoUHJv
-cGVydHlOYW1lLHt2YWx1ZTpKLlF1KGIsdCxudWxsLG51bGwpLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFi
-bGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBifSwKVmE6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEouUXUoYSwhMSxudWxsLCEhYS4kaVhqKX0sClZGOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1iLnByb3Rv
-dHlwZQppZih2LmxlYWZUYWdzW2FdPT09dHJ1ZSlyZXR1cm4gSC5WYSh0KQplbHNlIHJldHVybiBKLlF1
-KHQsYyxudWxsLG51bGwpfSwKWEQ6ZnVuY3Rpb24oKXtpZighMD09PSQuQnYpcmV0dXJuCiQuQnY9ITAK
-SC5aMSgpfSwKWjE6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtCiQubnc9T2JqZWN0LmNyZWF0
-ZShudWxsKQokLnZ2PU9iamVjdC5jcmVhdGUobnVsbCkKSC5rTygpCnQ9di5pbnRlcmNlcHRvcnNCeVRh
-ZwpzPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHQpCmlmKHR5cGVvZiB3aW5kb3chPSJ1bmRlZmlu
-ZWQiKXt3aW5kb3cKcj1mdW5jdGlvbigpe30KZm9yKHE9MDtxPHMubGVuZ3RoOysrcSl7cD1zW3FdCm89
-JC54Ny4kMShwKQppZihvIT1udWxsKXtuPUguVkYocCx0W3BdLG8pCmlmKG4hPW51bGwpe09iamVjdC5k
-ZWZpbmVQcm9wZXJ0eShvLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm4sZW51bWVyYWJsZTpm
-YWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKci5wcm90b3R5cGU9b319fX1mb3Io
-cT0wO3E8cy5sZW5ndGg7KytxKXtwPXNbcV0KaWYoL15bQS1aYS16X10vLnRlc3QocCkpe209dFtwXQp0
-WyIhIitwXT1tCnRbIn4iK3BdPW0KdFsiLSIrcF09bQp0WyIrIitwXT1tCnRbIioiK3BdPW19fX0sCmtP
-OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG49Qy5ZcSgpCm49SC51ZChDLktVLEgudWQoQy5mUSxI
-LnVkKEMuaTcsSC51ZChDLmk3LEgudWQoQy54aSxILnVkKEMuZGssSC51ZChDLndiKEMuTzQpLG4pKSkp
-KSkpCmlmKHR5cGVvZiBkYXJ0TmF0aXZlRGlzcGF0Y2hIb29rc1RyYW5zZm9ybWVyIT0idW5kZWZpbmVk
-Iil7dD1kYXJ0TmF0aXZlRGlzcGF0Y2hIb29rc1RyYW5zZm9ybWVyCmlmKHR5cGVvZiB0PT0iZnVuY3Rp
-b24iKXQ9W3RdCmlmKHQuY29uc3RydWN0b3I9PUFycmF5KWZvcihzPTA7czx0Lmxlbmd0aDsrK3Mpe3I9
-dFtzXQppZih0eXBlb2Ygcj09ImZ1bmN0aW9uIiluPXIobil8fG59fXE9bi5nZXRUYWcKcD1uLmdldFVu
-a25vd25UYWcKbz1uLnByb3RvdHlwZUZvclRhZwokLk5GPW5ldyBILmRDKHEpCiQuVFg9bmV3IEgud04o
-cCkKJC54Nz1uZXcgSC5WWChvKX0sCnVkOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGEoYil8fGJ9LAp2NDpm
-dW5jdGlvbihhLGIsYyxkLGUsZil7dmFyIHQ9Yj8ibSI6IiIscz1jPyIiOiJpIixyPWQ/InUiOiIiLHE9
-ZT8icyI6IiIscD1mPyJnIjoiIixvPWZ1bmN0aW9uKGcsaCl7dHJ5e3JldHVybiBuZXcgUmVnRXhwKGcs
-aCl9Y2F0Y2gobil7cmV0dXJuIG59fShhLHQrcytyK3ErcCkKaWYobyBpbnN0YW5jZW9mIFJlZ0V4cCly
-ZXR1cm4gbwp0aHJvdyBILmIoUC5ycigiSWxsZWdhbCBSZWdFeHAgcGF0dGVybiAoIitTdHJpbmcobykr
-IikiLGEsbnVsbCkpfSwKbTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKHR5cGVvZiBiPT0ic3RyaW5n
-IilyZXR1cm4gYS5pbmRleE9mKGIsYyk+PTAKZWxzZSBpZihiIGluc3RhbmNlb2YgSC5WUil7dD1DLnhC
-LkcoYSxjKQpyZXR1cm4gYi5iLnRlc3QodCl9ZWxzZXt0PUouRkwoYixDLnhCLkcoYSxjKSkKcmV0dXJu
-IXQuZ2wwKHQpfX0sCkE0OmZ1bmN0aW9uKGEpe2lmKGEuaW5kZXhPZigiJCIsMCk+PTApcmV0dXJuIGEu
-cmVwbGFjZSgvXCQvZywiJCQkJCIpCnJldHVybiBhfSwKZUE6ZnVuY3Rpb24oYSl7aWYoL1tbXF17fSgp
-Kis/LlxcXiR8XS8udGVzdChhKSlyZXR1cm4gYS5yZXBsYWNlKC9bW1xde30oKSorPy5cXF4kfF0vZywi
-XFwkJiIpCnJldHVybiBhfSwKeXM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUgubk0oYSxiLGMpCnJldHVy
-biB0fSwKbk06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmlmKGI9PT0iIil7aWYoYT09PSIiKXJl
-dHVybiBjCnQ9YS5sZW5ndGgKZm9yKHM9YyxyPTA7cjx0OysrcilzPXMrYVtyXStjCnJldHVybiBzLmNo
-YXJDb2RlQXQoMCk9PTA/czpzfXE9YS5pbmRleE9mKGIsMCkKaWYocTwwKXJldHVybiBhCmlmKGEubGVu
-Z3RoPDUwMHx8Yy5pbmRleE9mKCIkIiwwKT49MClyZXR1cm4gYS5zcGxpdChiKS5qb2luKGMpCnJldHVy
-biBhLnJlcGxhY2UobmV3IFJlZ0V4cChILmVBKGIpLCdnJyksSC5BNChjKSl9LApQRDpmdW5jdGlvbiBQ
-RChhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApXVTpmdW5jdGlvbiBXVSgpe30sCkxQOmZ1bmN0aW9u
-IExQKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sCkxJOmZ1bmN0
-aW9uIExJKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmE9YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLmY9ZX0s
-CkNqOmZ1bmN0aW9uIENqKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClpyOmZ1bmN0
-aW9uIFpyKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1l
-Cl8uZj1mfSwKVzA6ZnVuY3Rpb24gVzAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmF6OmZ1bmN0aW9u
-IGF6KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnZWOmZ1bmN0aW9uIHZWKGEpe3Ro
-aXMuYT1hfSwKQW06ZnVuY3Rpb24gQW0oYSl7dGhpcy5hPWF9LApYTzpmdW5jdGlvbiBYTyhhKXt0aGlz
-LmE9YQp0aGlzLmI9bnVsbH0sClRwOmZ1bmN0aW9uIFRwKCl7fSwKbGM6ZnVuY3Rpb24gbGMoKXt9LAp6
-eDpmdW5jdGlvbiB6eCgpe30sCnJUOmZ1bmN0aW9uIHJUKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEK
-Xy5iPWIKXy5jPWMKXy5kPWR9LApFcTpmdW5jdGlvbiBFcShhKXt0aGlzLmE9YX0sCmtZOmZ1bmN0aW9u
-IGtZKGEpe3RoaXMuYT1hfSwKTjU6ZnVuY3Rpb24gTjUoYSl7dmFyIF89dGhpcwpfLmE9MApfLmY9Xy5l
-PV8uZD1fLmM9Xy5iPW51bGwKXy5yPTAKXy4kdGk9YX0sCmRiOmZ1bmN0aW9uIGRiKGEsYil7dmFyIF89
-dGhpcwpfLmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGx9LAppNTpmdW5jdGlvbiBpNShhLGIpe3RoaXMuYT1h
-CnRoaXMuJHRpPWJ9LApONjpmdW5jdGlvbiBONihhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9Ygpf
-LmQ9Xy5jPW51bGwKXy4kdGk9Y30sCmRDOmZ1bmN0aW9uIGRDKGEpe3RoaXMuYT1hfSwKd046ZnVuY3Rp
-b24gd04oYSl7dGhpcy5hPWF9LApWWDpmdW5jdGlvbiBWWChhKXt0aGlzLmE9YX0sClZSOmZ1bmN0aW9u
-IFZSKGEsYil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGx9LApFSzpmdW5jdGlvbiBF
-SyhhKXt0aGlzLmI9YX0sCktXOmZ1bmN0aW9uIEtXKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlz
-LmM9Y30sClBiOmZ1bmN0aW9uIFBiKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8u
-ZD1udWxsfSwKdFE6ZnVuY3Rpb24gdFEoYSxiKXt0aGlzLmE9YQp0aGlzLmM9Yn0sCnVuOmZ1bmN0aW9u
-IHVuKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClNkOmZ1bmN0aW9uIFNkKGEsYixj
-KXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1udWxsfSwKWEY6ZnVuY3Rpb24oYSl7cmV0
-dXJuIGF9LApEUTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEludDhBcnJheShhKX0sCm9kOmZ1bmN0aW9u
-KGEsYixjKXtpZihhPj4+MCE9PWF8fGE+PWMpdGhyb3cgSC5iKEguSFkoYixhKSl9LApyTTpmdW5jdGlv
-bihhLGIsYyl7dmFyIHQKaWYoIShhPj4+MCE9PWEpKXQ9Yj4+PjAhPT1ifHxhPmJ8fGI+YwplbHNlIHQ9
-ITAKaWYodCl0aHJvdyBILmIoSC5hdShhLGIsYykpCnJldHVybiBifSwKRVQ6ZnVuY3Rpb24gRVQoKXt9
-LApiMDpmdW5jdGlvbiBiMCgpe30sCkRnOmZ1bmN0aW9uIERnKCl7fSwKUGc6ZnVuY3Rpb24gUGcoKXt9
-LAp4ajpmdW5jdGlvbiB4aigpe30sCmRFOmZ1bmN0aW9uIGRFKCl7fSwKWkE6ZnVuY3Rpb24gWkEoKXt9
-LAp3ZjpmdW5jdGlvbiB3Zigpe30sClBxOmZ1bmN0aW9uIFBxKCl7fSwKZUU6ZnVuY3Rpb24gZUUoKXt9
-LApWNjpmdW5jdGlvbiBWNigpe30sClJHOmZ1bmN0aW9uIFJHKCl7fSwKVlA6ZnVuY3Rpb24gVlAoKXt9
-LApXQjpmdW5jdGlvbiBXQigpe30sClpHOmZ1bmN0aW9uIFpHKCl7fSwKeFo6ZnVuY3Rpb24oYSxiKXt2
-YXIgdD1iLmQKcmV0dXJuIHQ9PW51bGw/Yi5kPUguSihhLCJiOCIsW2IuUV0pOnR9LApRMTpmdW5jdGlv
-bihhKXt2YXIgdD1hLnoKaWYodD09PTZ8fHQ9PT03fHx0PT09OClyZXR1cm4gSC5RMShhLlEpCnJldHVy
-biB0PT09MTF8fHQ9PT0xMn0sCm1EOmZ1bmN0aW9uKGEpe3JldHVybiBhLmRifSwKTjA6ZnVuY3Rpb24o
-YSl7cmV0dXJuIEguRSh2LnR5cGVVbml2ZXJzZSxhKX0sCkpTOmZ1bmN0aW9uKGEpe3ZhciB0PWEuJFMK
-aWYodCE9bnVsbCl7aWYodHlwZW9mIHQ9PSJudW1iZXIiKXJldHVybiBILkJwKHQpCnJldHVybiBhLiRT
-KCl9cmV0dXJuIG51bGx9LApVZTpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKEguUTEoYikpaWYoYSBpbnN0
-YW5jZW9mIEguVHApe3Q9SC5KUyhhKQppZih0IT1udWxsKXJldHVybiB0fXJldHVybiBILnpLKGEpfSwK
-eks6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoYSBpbnN0YW5jZW9mIFAuayl7dD1hLiR0aQpyZXR1cm4gdCE9
-bnVsbD90OkguVlUoYSl9aWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gSC50NihhKQpyZXR1cm4gSC5W
-VShKLmlhKGEpKX0sCnQ2OmZ1bmN0aW9uKGEpe3ZhciB0PWEuJHRpLHM9dS5iCmlmKHQ9PW51bGwpcmV0
-dXJuIHMKaWYodC5jb25zdHJ1Y3RvciE9PXMuY29uc3RydWN0b3IpcmV0dXJuIHMKcmV0dXJuIHR9LApM
-aDpmdW5jdGlvbihhKXt2YXIgdD1hLiR0aQpyZXR1cm4gdCE9bnVsbD90OkguVlUoYSl9LApWVTpmdW5j
-dGlvbihhKXt2YXIgdD1hLmNvbnN0cnVjdG9yLHM9dC4kY2NhY2hlCmlmKHMhPW51bGwpcmV0dXJuIHMK
-cmV0dXJuIEgucjkoYSx0KX0sCnI5OmZ1bmN0aW9uKGEsYil7dmFyIHQ9YSBpbnN0YW5jZW9mIEguVHA/
-YS5fX3Byb3RvX18uX19wcm90b19fLmNvbnN0cnVjdG9yOmIscz1ILmFpKHYudHlwZVVuaXZlcnNlLHQu
-bmFtZSkKYi4kY2NhY2hlPXMKcmV0dXJuIHN9LApCcDpmdW5jdGlvbihhKXt2YXIgdCxzPWEscj12LnR5
-cGVzLHE9cltzXQppZih0eXBlb2YgcT09InN0cmluZyIpe3Q9SC5FKHYudHlwZVVuaXZlcnNlLHEpCnJb
-c109dApyZXR1cm4gdH1yZXR1cm4gcX0sCkpKOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxyPXMueixx
-PUguWU8KaWYoSC5jYyhzKSl7cT1ILkl3CnMuYj1zLmE9SC5obn1lbHNlIGlmKHI9PT05KXt0PXMuZGIK
-aWYoIktOIj09PXQpcT1ILm9rCmVsc2UgaWYoIkNQIj09PXQpcT1ILktICmVsc2UgaWYoIkZLIj09PXQp
-cT1ILktICmVsc2UgaWYoInFVIj09PXQpcT1ILk1NCmVsc2UgaWYoImEyIj09PXQpcT1ILmwKZWxzZXty
-PXMuUQppZihzLmNoLmV2ZXJ5KEguY2MpKXtzLng9IiRpIityCnE9SC50NH19fXMuYz1xCnJldHVybiBz
-LmMoYSl9LApZTzpmdW5jdGlvbihhKXt2YXIgdD10aGlzCnJldHVybiBILldlKHYudHlwZVVuaXZlcnNl
-LEguVWUoYSx0KSxudWxsLHQsbnVsbCl9LAp0NDpmdW5jdGlvbihhKXt2YXIgdD10aGlzLngKaWYoYSBp
-bnN0YW5jZW9mIFAuaylyZXR1cm4hIWFbdF0KcmV0dXJuISFKLmlhKGEpW3RdfSwKT3o6ZnVuY3Rpb24o
-YSl7dmFyIHQKaWYoYT09bnVsbClyZXR1cm4gYQp0PXRoaXMKaWYodC5jKGEpKXJldHVybiBhCnRocm93
-IEguYihILlE1KEguV0soYSxILlVlKGEsdCksSC5kbSh0LG51bGwpKSkpfSwKQXY6ZnVuY3Rpb24oYSl7
-dmFyIHQKaWYoYT09bnVsbClyZXR1cm4gYQp0PXRoaXMKaWYodC5jKGEpKXJldHVybiBhCnRocm93IEgu
-YihILlpjKEguV0soYSxILlVlKGEsdCksSC5kbSh0LG51bGwpKSkpfSwKRGg6ZnVuY3Rpb24oYSxiLGMs
-ZCl7dmFyIHQ9bnVsbAppZihILldlKHYudHlwZVVuaXZlcnNlLGEsdCxiLHQpKXJldHVybiBhCnRocm93
-IEguYihILlpjKCJUaGUgdHlwZSBhcmd1bWVudCAnIitILmQoSC5kbShhLHQpKSsiJyBpcyBub3QgYSBz
-dWJ0eXBlIG9mIHRoZSB0eXBlIHZhcmlhYmxlIGJvdW5kICciK0guZChILmRtKGIsdCkpKyInIG9mIHR5
-cGUgdmFyaWFibGUgJyIrYysiJyBpbiAnIitILmQoZCkrIicuIikpfSwKV0s6ZnVuY3Rpb24oYSxiLGMp
-e3ZhciB0PVAucChhKSxzPUguZG0oYj09bnVsbD9ILnpLKGEpOmIsbnVsbCkKcmV0dXJuIHQrIjogdHlw
-ZSAnIitILmQocykrIicgaXMgbm90IGEgc3VidHlwZSBvZiB0eXBlICciK0guZChjKSsiJyJ9LApRNTpm
-dW5jdGlvbihhKXtyZXR1cm4gbmV3IEguaHooIkNhc3RFcnJvcjogIithKX0sClB2OmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIG5ldyBILmh6KCJDYXN0RXJyb3I6ICIrSC5XSyhhLG51bGwsYikpfSwKWmM6ZnVuY3Rp
-b24oYSl7cmV0dXJuIG5ldyBILmlNKCJUeXBlRXJyb3I6ICIrYSl9LApxOmZ1bmN0aW9uKGEsYil7cmV0
-dXJuIG5ldyBILmlNKCJUeXBlRXJyb3I6ICIrSC5XSyhhLG51bGwsYikpfSwKSXc6ZnVuY3Rpb24oYSl7
-cmV0dXJuITB9LApobjpmdW5jdGlvbihhKXtyZXR1cm4gYX0sCmw6ZnVuY3Rpb24oYSl7cmV0dXJuITA9
-PT1hfHwhMT09PWF9LApFOTpmdW5jdGlvbihhKXtpZighMD09PWF8fCExPT09YSlyZXR1cm4gYQppZihh
-PT1udWxsKXJldHVybiBhCnRocm93IEguYihILlB2KGEsImJvb2wiKSl9LAp4ZDpmdW5jdGlvbihhKXtp
-ZighMD09PWF8fCExPT09YSlyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEo
-YSwiYm9vbCIpKX0sCmRqOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQpp
-ZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILlB2KGEsImRvdWJsZSIpKX0sCklnOmZ1bmN0aW9u
-KGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93
-IEguYihILnEoYSwiZG91YmxlIikpfSwKb2s6ZnVuY3Rpb24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ibnVt
-YmVyIiYmTWF0aC5mbG9vcihhKT09PWF9LApTSDpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJl
-ciImJk1hdGguZmxvb3IoYSk9PT1hKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5i
-KEguUHYoYSwiaW50IikpfSwKU2M6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZNYXRo
-LmZsb29yKGEpPT09YSlyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwi
-aW50IikpfSwKS0g6ZnVuY3Rpb24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ibnVtYmVyIn0sCnVVOmZ1bmN0
-aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRo
-cm93IEguYihILlB2KGEsIm51bSIpKX0sCkROOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVy
-IilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwibnVtIikpfSwKTU06
-ZnVuY3Rpb24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ic3RyaW5nIn0sCmMwOmZ1bmN0aW9uKGEpe2lmKHR5
-cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILlB2
-KGEsIlN0cmluZyIpKX0sCnk6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBh
-CmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJTdHJpbmciKSl9LAppbzpmdW5jdGlv
-bihhLGIpe3ZhciB0LHMscgpmb3IodD0iIixzPSIiLHI9MDtyPGEubGVuZ3RoOysrcixzPSIsICIpdCs9
-Qy54Qi5oKHMsSC5kbShhW3JdLGIpKQpyZXR1cm4gdH0sCmJJOmZ1bmN0aW9uKGEwLGExLGEyKXt2YXIg
-dCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhPSIsICIKaWYoYTIhPW51bGwpe3Q9
-YTIubGVuZ3RoCmlmKGExPT1udWxsKXthMT1ILlZNKFtdLHUucykKcz1udWxsfWVsc2Ugcz1hMS5sZW5n
-dGgKcj1hMS5sZW5ndGgKZm9yKHE9dDtxPjA7LS1xKUMuTm0uaShhMSwiVCIrKHIrcSkpCmZvcihwPSI8
-IixvPSIiLHE9MDtxPHQ7KytxLG89YSl7cCs9bwpuPWExLmxlbmd0aAptPW4tMS1xCmlmKG08MClyZXR1
-cm4gSC5PSChhMSxtKQpwPUMueEIuaChwLGExW21dKQpsPWEyW3FdCmlmKCFILmNjKGwpKXArPUMueEIu
-aCgiIGV4dGVuZHMgIixILmRtKGwsYTEpKX1wKz0iPiJ9ZWxzZXtwPSIiCnM9bnVsbH1uPWEwLlEKaz1h
-MC5jaApqPWsuYQppPWoubGVuZ3RoCmg9ay5iCmc9aC5sZW5ndGgKZj1rLmMKZT1mLmxlbmd0aApkPUgu
-ZG0obixhMSkKZm9yKGM9IiIsYj0iIixxPTA7cTxpOysrcSxiPWEpYys9Qy54Qi5oKGIsSC5kbShqW3Fd
-LGExKSkKaWYoZz4wKXtjKz1iKyJbIgpmb3IoYj0iIixxPTA7cTxnOysrcSxiPWEpYys9Qy54Qi5oKGIs
-SC5kbShoW3FdLGExKSkKYys9Il0ifWlmKGU+MCl7Yys9YisieyIKZm9yKGI9IiIscT0wO3E8ZTtxKz0y
-LGI9YSljKz1DLnhCLmgoYixILmRtKGZbcSsxXSxhMSkpKyIgIitmW3FdCmMrPSJ9In1pZihzIT1udWxs
-KWExLmxlbmd0aD1zCnJldHVybiBwKyIoIitjKyIpID0+ICIrSC5kKGQpfSwKZG06ZnVuY3Rpb24oYSxi
-KXt2YXIgdCxzLHIscSxwPWEuegppZihwPT09NSlyZXR1cm4iZXJhc2VkIgppZihwPT09MilyZXR1cm4i
-ZHluYW1pYyIKaWYocD09PTMpcmV0dXJuInZvaWQiCmlmKHA9PT0xKXJldHVybiJOZXZlciIKaWYocD09
-PTQpcmV0dXJuImFueSIKaWYocD09PTYpcmV0dXJuIEguZChILmRtKGEuUSxiKSkrIioiCmlmKHA9PT03
-KXJldHVybiBILmQoSC5kbShhLlEsYikpKyI/IgppZihwPT09OClyZXR1cm4iRnV0dXJlT3I8IitILmQo
-SC5kbShhLlEsYikpKyI+IgppZihwPT09OSl7dD1ILm8zKGEuUSkKcz1hLmNoCnJldHVybiBzLmxlbmd0
-aCE9PTA/dCsoIjwiK0guaW8ocyxiKSsiPiIpOnR9aWYocD09PTExKXJldHVybiBILmJJKGEsYixudWxs
-KQppZihwPT09MTIpcmV0dXJuIEguYkkoYS5RLGIsYS5jaCkKaWYocD09PTEzKXtyPWEuUQpxPWIubGVu
-Z3RoCnI9cS0xLXIKaWYocjwwfHxyPj1xKXJldHVybiBILk9IKGIscikKcmV0dXJuIGJbcl19cmV0dXJu
-Ij8ifSwKbzM6ZnVuY3Rpb24oYSl7dmFyIHQscz1ILkpnKGEpCmlmKHMhPW51bGwpcmV0dXJuIHMKdD0i
-bWluaWZpZWQ6IithCnJldHVybiB0fSwKUW86ZnVuY3Rpb24oYSxiKXt2YXIgdD1hLnRSW2JdCmZvcig7
-dHlwZW9mIHQ9PSJzdHJpbmciOyl0PWEudFJbdF0KcmV0dXJuIHR9LAphaTpmdW5jdGlvbihhLGIpe3Zh
-ciB0LHMscixxLHAsbz1hLmVULG49b1tiXQppZihuPT1udWxsKXJldHVybiBILkUoYSxiKQplbHNlIGlm
-KHR5cGVvZiBuPT0ibnVtYmVyIil7dD1uCnM9SC5tKGEsNSwiIyIpCnI9W10KZm9yKHE9MDtxPHQ7Kytx
-KXIucHVzaChzKQpwPUguSihhLGIscikKb1tiXT1wCnJldHVybiBwfWVsc2UgcmV0dXJuIG59LAp4Yjpm
-dW5jdGlvbihhLGIpe3JldHVybiBILkl4KGEudFIsYil9LApGRjpmdW5jdGlvbihhLGIpe3JldHVybiBI
-Lkl4KGEuZVQsYil9LApFOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1hLmVDLHI9cy5nZXQoYikKaWYociE9
-bnVsbClyZXR1cm4gcgp0PUgueihhLG51bGwsYikKcy5zZXQoYix0KQpyZXR1cm4gdH0sCmNFOmZ1bmN0
-aW9uKGEsYixjKXt2YXIgdCxzLHI9Yi5jeAppZihyPT1udWxsKXI9Yi5jeD1uZXcgTWFwKCkKdD1yLmdl
-dChjKQppZih0IT1udWxsKXJldHVybiB0CnM9SC56KGEsYixjKQpyLnNldChjLHMpCnJldHVybiBzfSwK
-djU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPWIuY3kKaWYocT09bnVsbClxPWIuY3k9bmV3IE1h
-cCgpCnQ9Yy5kYgpzPXEuZ2V0KHQpCmlmKHMhPW51bGwpcmV0dXJuIHMKcj1ILmEoYSxiLGMuej09PTEw
-P2MuY2g6W2NdKQpxLnNldCh0LHIpCnJldHVybiByfSwKejpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5p
-KEgubyhhLGIsYykpCnJldHVybiB0fSwKV0c6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iLmRiCmEuZUMuc2V0
-KHQsYikKYi5hPUguT3oKYi5iPUguQXYKYi5jPUguSkoKcmV0dXJuIGJ9LAptOmZ1bmN0aW9uKGEsYixj
-KXt2YXIgdCxzPWEuZUMuZ2V0KGMpCmlmKHMhPW51bGwpcmV0dXJuIHMKdD1uZXcgSC5KYyhudWxsLG51
-bGwsbnVsbCkKdC56PWIKdC5kYj1jCnJldHVybiBILldHKGEsdCl9LAp2OmZ1bmN0aW9uKGEsYixjLGQp
-e3ZhciB0LHM9YS5lQy5nZXQoZCkKaWYocyE9bnVsbClyZXR1cm4gcwp0PW5ldyBILkpjKG51bGwsbnVs
-bCxudWxsKQp0Lno9Ygp0LlE9Ywp0LmRiPWQKcmV0dXJuIEguV0coYSx0KX0sCkg6ZnVuY3Rpb24oYSxi
-KXt2YXIgdCxzPSIiK2IrIl4iLHI9YS5lQy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PW5ldyBI
-LkpjKG51bGwsbnVsbCxudWxsKQp0Lno9MTMKdC5RPWIKdC5kYj1zCnJldHVybiBILldHKGEsdCl9LApV
-eDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLmxlbmd0aApmb3IodD0iIixzPSIiLHI9MDtyPHE7Kyty
-LHM9IiwiKXQrPXMrYVtyXS5kYgpyZXR1cm4gdH0sClM0OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAs
-bz1hLmxlbmd0aApmb3IodD0iIixzPSIiLHI9MDtyPG87cis9MixzPSIsIil7cT1hW3JdCnA9YVtyKzFd
-LmRiCnQrPXMrcSsiOiIrcH1yZXR1cm4gdH0sCko6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscj1iCmlm
-KGMubGVuZ3RoIT09MClyKz0iPCIrSC5VeChjKSsiPiIKdD1hLmVDLmdldChyKQppZih0IT1udWxsKXJl
-dHVybiB0CnM9bmV3IEguSmMobnVsbCxudWxsLG51bGwpCnMuej05CnMuUT1iCnMuY2g9YwppZihjLmxl
-bmd0aD4wKXMuZD1jWzBdCnMuZGI9cgpyZXR1cm4gSC5XRyhhLHMpfSwKYTpmdW5jdGlvbihhLGIsYyl7
-dmFyIHQscyxyLHEscAppZihiLno9PT0xMCl7dD1iLlEKcz1iLmNoLmNvbmNhdChjKX1lbHNle3M9Ywp0
-PWJ9cj10LmRiKyI7IisoIjwiK0guVXgocykrIj4iKQpxPWEuZUMuZ2V0KHIpCmlmKHEhPW51bGwpcmV0
-dXJuIHEKcD1uZXcgSC5KYyhudWxsLG51bGwsbnVsbCkKcC56PTEwCnAuUT10CnAuY2g9cwpwLmRiPXIK
-cmV0dXJuIEguV0coYSxwKX0sCkM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPWIuZGIscD1jLmEs
-bz1wLmxlbmd0aCxuPWMuYixtPW4ubGVuZ3RoLGw9Yy5jLGs9bC5sZW5ndGgsaj0iKCIrSC5VeChwKQpp
-ZihtPjApais9KG8+MD8iLCI6IiIpKyJbIitILlV4KG4pKyJdIgppZihrPjApais9KG8+MD8iLCI6IiIp
-KyJ7IitILlM0KGwpKyJ9Igp0PXErKGorIikiKQpzPWEuZUMuZ2V0KHQpCmlmKHMhPW51bGwpcmV0dXJu
-IHMKcj1uZXcgSC5KYyhudWxsLG51bGwsbnVsbCkKci56PTExCnIuUT1iCnIuY2g9YwpyLmRiPXQKcmV0
-dXJuIEguV0coYSxyKX0sCkQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Yi5kYisiPCIrSC5VeChjKSsi
-PiIscj1hLmVDLmdldChzKQppZihyIT1udWxsKXJldHVybiByCnQ9bmV3IEguSmMobnVsbCxudWxsLG51
-bGwpCnQuej0xMgp0LlE9Ygp0LmNoPWMKdC5kYj1zCnJldHVybiBILldHKGEsdCl9LApvOmZ1bmN0aW9u
-KGEsYixjKXtyZXR1cm57dTphLGU6YixyOmMsczpbXSxwOjB9fSwKaTpmdW5jdGlvbihhKXt2YXIgdCxz
-LHIscSxwLG8sbixtLGwsayxqLGksaCxnPWEucixmPWEucwpmb3IodD1nLmxlbmd0aCxzPTA7czx0Oyl7
-cj1nLmNoYXJDb2RlQXQocykKaWYocj49NDgmJnI8PTU3KXM9SC5BKHMrMSxyLGcsZikKZWxzZSBpZigo
-KChyfDMyKT4+PjApLTk3JjY1NTM1KTwyNnx8cj09PTk1fHxyPT09MzYpcz1ILnQoYSxzLGcsZiwhMSkK
-ZWxzZSBpZihyPT09NDYpcz1ILnQoYSxzLGcsZiwhMCkKZWxzZXsrK3MKc3dpdGNoKHIpe2Nhc2UgNDQ6
-YnJlYWsKY2FzZSA1ODpicmVhawpjYXNlIDU5OmYucHVzaChILksoYS51LGEuZSxmLnBvcCgpKSkKYnJl
-YWsKY2FzZSA5NDpmLnB1c2goSC5IKGEudSxmLnBvcCgpKSkKYnJlYWsKY2FzZSAzNTpmLnB1c2goSC5t
-KGEudSw1LCIjIikpCmJyZWFrCmNhc2UgNjQ6Zi5wdXNoKEgubShhLnUsMiwiQCIpKQpicmVhawpjYXNl
-IDEyNjpmLnB1c2goSC5tKGEudSwzLCJ+IikpCmJyZWFrCmNhc2UgNjA6Zi5wdXNoKGEucCkKYS5wPWYu
-bGVuZ3RoCmJyZWFrCmNhc2UgNjI6cT1hLnUKcD1mLnNwbGljZShhLnApCkgucihhLnUsYS5lLHApCmEu
-cD1mLnBvcCgpCm89Zi5wb3AoKQppZih0eXBlb2Ygbz09InN0cmluZyIpZi5wdXNoKEguSihxLG8scCkp
-CmVsc2V7bj1ILksocSxhLmUsbykKc3dpdGNoKG4ueil7Y2FzZSAxMTpmLnB1c2goSC5EKHEsbixwKSkK
-YnJlYWsKZGVmYXVsdDpmLnB1c2goSC5hKHEsbixwKSkKYnJlYWt9fWJyZWFrCmNhc2UgMzg6SC5JKGEs
-ZikKYnJlYWsKY2FzZSA0MjptPWEudQpsPUguSyhtLGEuZSxmLnBvcCgpKQpmLnB1c2goSC52KG0sNixs
-LGwuZGIrIioiKSkKYnJlYWsKY2FzZSA2MzptPWEudQpsPUguSyhtLGEuZSxmLnBvcCgpKQpmLnB1c2go
-SC52KG0sNyxsLGwuZGIrIj8iKSkKYnJlYWsKY2FzZSA0NzptPWEudQpsPUguSyhtLGEuZSxmLnBvcCgp
-KQpmLnB1c2goSC52KG0sOCxsLGwuZGIrIi8iKSkKYnJlYWsKY2FzZSA0MDpmLnB1c2goYS5wKQphLnA9
-Zi5sZW5ndGgKYnJlYWsKY2FzZSA0MTpxPWEudQprPW5ldyBILkcoKQpqPXEuc0VBCmk9cS5zRUEKbz1m
-LnBvcCgpCmlmKHR5cGVvZiBvPT0ibnVtYmVyIilzd2l0Y2gobyl7Y2FzZS0xOmo9Zi5wb3AoKQpicmVh
-awpjYXNlLTI6aT1mLnBvcCgpCmJyZWFrCmRlZmF1bHQ6Zi5wdXNoKG8pCmJyZWFrfWVsc2UgZi5wdXNo
-KG8pCnA9Zi5zcGxpY2UoYS5wKQpILnIoYS51LGEuZSxwKQphLnA9Zi5wb3AoKQprLmE9cAprLmI9agpr
-LmM9aQpmLnB1c2goSC5DKHEsSC5LKHEsYS5lLGYucG9wKCkpLGspKQpicmVhawpjYXNlIDkxOmYucHVz
-aChhLnApCmEucD1mLmxlbmd0aApicmVhawpjYXNlIDkzOnA9Zi5zcGxpY2UoYS5wKQpILnIoYS51LGEu
-ZSxwKQphLnA9Zi5wb3AoKQpmLnB1c2gocCkKZi5wdXNoKC0xKQpicmVhawpjYXNlIDEyMzpmLnB1c2go
-YS5wKQphLnA9Zi5sZW5ndGgKYnJlYWsKY2FzZSAxMjU6cD1mLnNwbGljZShhLnApCkguQihhLnUsYS5l
-LHApCmEucD1mLnBvcCgpCmYucHVzaChwKQpmLnB1c2goLTIpCmJyZWFrCmRlZmF1bHQ6dGhyb3ciQmFk
-IGNoYXJhY3RlciAiK3J9fX1oPWYucG9wKCkKcmV0dXJuIEguSyhhLnUsYS5lLGgpfSwKQTpmdW5jdGlv
-bihhLGIsYyxkKXt2YXIgdCxzLHI9Yi00OApmb3IodD1jLmxlbmd0aDthPHQ7KythKXtzPWMuY2hhckNv
-ZGVBdChhKQppZighKHM+PTQ4JiZzPD01NykpYnJlYWsKcj1yKjEwKyhzLTQ4KX1kLnB1c2gocikKcmV0
-dXJuIGF9LAp0OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEscCxvLG49YisxCmZvcih0PWMu
-bGVuZ3RoO248dDsrK24pe3M9Yy5jaGFyQ29kZUF0KG4pCmlmKHM9PT00Nil7aWYoZSlicmVhawplPSEw
-fWVsc2V7aWYoISgoKChzfDMyKT4+PjApLTk3JjY1NTM1KTwyNnx8cz09PTk1fHxzPT09MzYpKXI9cz49
-NDgmJnM8PTU3CmVsc2Ugcj0hMAppZighcilicmVha319cT1jLnN1YnN0cmluZyhiLG4pCmlmKGUpe3Q9
-YS51CnA9YS5lCmlmKHAuej09PTEwKXA9cC5RCm89SC5Rbyh0LHAuUSlbcV0KaWYobz09bnVsbClILnZo
-KCdObyAiJytxKyciIGluICInK0gubUQocCkrJyInKQpkLnB1c2goSC5jRSh0LHAsbykpfWVsc2UgZC5w
-dXNoKHEpCnJldHVybiBufSwKSTpmdW5jdGlvbihhLGIpe3ZhciB0PWIucG9wKCkKaWYoMD09PXQpe2Iu
-cHVzaChILm0oYS51LDEsIjAmIikpCnJldHVybn1pZigxPT09dCl7Yi5wdXNoKEgubShhLnUsNCwiMSYi
-KSkKcmV0dXJufXRocm93IEguYihQLmhWKCJVbmV4cGVjdGVkIGV4dGVuZGVkIG9wZXJhdGlvbiAiK0gu
-ZCh0KSkpfSwKSzpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGM9PSJzdHJpbmciKXJldHVybiBILkoo
-YSxjLGEuc0VBKQplbHNlIGlmKHR5cGVvZiBjPT0ibnVtYmVyIilyZXR1cm4gSC5UVihhLGIsYykKZWxz
-ZSByZXR1cm4gY30sCnI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Yy5sZW5ndGgKZm9yKHQ9MDt0PHM7
-Kyt0KWNbdF09SC5LKGEsYixjW3RdKX0sCkI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Yy5sZW5ndGgK
-Zm9yKHQ9MTt0PHM7dCs9MiljW3RdPUguSyhhLGIsY1t0XSl9LApUVjpmdW5jdGlvbihhLGIsYyl7dmFy
-IHQscyxyPWIuegppZihyPT09MTApe2lmKGM9PT0wKXJldHVybiBiLlEKdD1iLmNoCnM9dC5sZW5ndGgK
-aWYoYzw9cylyZXR1cm4gdFtjLTFdCmMtPXMKYj1iLlEKcj1iLnp9ZWxzZSBpZihjPT09MClyZXR1cm4g
-YgppZihyIT09OSl0aHJvdyBILmIoUC5oVigiSW5kZXhlZCBiYXNlIG11c3QgYmUgYW4gaW50ZXJmYWNl
-IHR5cGUiKSkKdD1iLmNoCmlmKGM8PXQubGVuZ3RoKXJldHVybiB0W2MtMV0KdGhyb3cgSC5iKFAuaFYo
-IkJhZCBpbmRleCAiK2MrIiBmb3IgIitiLncoMCkpKX0sCldlOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFy
-IHQscyxyLHEscCxvLG4sbSxsLGsKaWYoYj09PWQpcmV0dXJuITAKaWYoSC5jYyhkKSlyZXR1cm4hMAp0
-PWIuegppZih0PT09NClyZXR1cm4hMAppZihILmNjKGIpKXJldHVybiExCmlmKGI9PT11LlApcmV0dXJu
-ITAKcz10PT09MTMKaWYocylpZihILldlKGEsY1tiLlFdLGMsZCxlKSlyZXR1cm4hMApyPWQuegppZih0
-PT09NilyZXR1cm4gSC5XZShhLGIuUSxjLGQsZSkKaWYocj09PTYpe3E9ZC5RCnJldHVybiBILldlKGEs
-YixjLHEsZSl9aWYodD09PTgpe2lmKCFILldlKGEsYi5RLGMsZCxlKSlyZXR1cm4hMQpyZXR1cm4gSC5X
-ZShhLEgueFooYSxiKSxjLGQsZSl9aWYodD09PTcpe3E9SC5XZShhLGIuUSxjLGQsZSkKcmV0dXJuIHF9
-aWYocj09PTgpe2lmKEguV2UoYSxiLGMsZC5RLGUpKXJldHVybiEwCnJldHVybiBILldlKGEsYixjLEgu
-eFooYSxkKSxlKX1pZihyPT09Nyl7cT1ILldlKGEsYixjLGQuUSxlKQpyZXR1cm4gcX1pZihzKXJldHVy
-biExCnE9dCE9PTExCmlmKCghcXx8dD09PTEyKSYmZD09PXUuWilyZXR1cm4hMAppZihyPT09MTIpe2lm
-KGI9PT11LmcpcmV0dXJuITAKaWYodCE9PTEyKXJldHVybiExCnA9Yi5jaApvPWQuY2gKbj1wLmxlbmd0
-aAppZihuIT09by5sZW5ndGgpcmV0dXJuITEKZm9yKHE9dS5hdixtPTA7bTxuOysrbSl7bD1wW21dCms9
-b1ttXQpxLmIobCkKcS5iKGspCmlmKCFILldlKGEsbCxjLGssZSl8fCFILldlKGEsayxlLGwsYykpcmV0
-dXJuITF9Yz1jPT1udWxsP3A6cC5jb25jYXQoYykKZT1lPT1udWxsP286by5jb25jYXQoZSkKcmV0dXJu
-IEguYk8oYSxiLlEsYyxkLlEsZSl9aWYocj09PTExKXtpZihiPT09dS5nKXJldHVybiEwCmlmKHEpcmV0
-dXJuITEKcmV0dXJuIEguYk8oYSxiLGMsZCxlKX1pZih0PT09OSl7aWYociE9PTkpcmV0dXJuITEKcmV0
-dXJuIEgucEcoYSxiLGMsZCxlKX1yZXR1cm4hMX0sCmJPOmZ1bmN0aW9uKGEwLGExLGEyLGEzLGE0KXt2
-YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhCmlmKCFILldlKGEwLGExLlEs
-YTIsYTMuUSxhNCkpcmV0dXJuITEKdD1hMS5jaApzPWEzLmNoCnI9dC5hCnE9cy5hCnA9ci5sZW5ndGgK
-bz1xLmxlbmd0aAppZihwPm8pcmV0dXJuITEKbj1vLXAKbT10LmIKbD1zLmIKaz1tLmxlbmd0aApqPWwu
-bGVuZ3RoCmlmKHArazxvK2opcmV0dXJuITEKZm9yKGk9MDtpPHA7KytpKXtoPXJbaV0KaWYoIUguV2Uo
-YTAscVtpXSxhNCxoLGEyKSlyZXR1cm4hMX1mb3IoaT0wO2k8bjsrK2kpe2g9bVtpXQppZighSC5XZShh
-MCxxW3AraV0sYTQsaCxhMikpcmV0dXJuITF9Zm9yKGk9MDtpPGo7KytpKXtoPW1bbitpXQppZighSC5X
-ZShhMCxsW2ldLGE0LGgsYTIpKXJldHVybiExfWc9dC5jCmY9cy5jCmU9Zy5sZW5ndGgKZD1mLmxlbmd0
-aApmb3IoaT0wLGM9MDtjPGQ7Yys9Mil7Yj1mW2NdCmRve2lmKGk+PWUpcmV0dXJuITEKYT1nW2ldCmkr
-PTJ9d2hpbGUoYTxiKQppZihiPGEpcmV0dXJuITEKaD1nW2ktMV0KaWYoIUguV2UoYTAsZltjKzFdLGE0
-LGgsYTIpKXJldHVybiExfXJldHVybiEwfSwKcEc6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIs
-cSxwLG8sbixtLGw9Yi5RLGs9ZC5RCmlmKGw9PT1rKXt0PWIuY2gKcz1kLmNoCnI9dC5sZW5ndGgKZm9y
-KHE9MDtxPHI7KytxKXtwPXRbcV0Kbz1zW3FdCmlmKCFILldlKGEscCxjLG8sZSkpcmV0dXJuITF9cmV0
-dXJuITB9bj1ILlFvKGEsbCkKaWYobj09bnVsbClyZXR1cm4hMQptPW5ba10KaWYobT09bnVsbClyZXR1
-cm4hMQpyPW0ubGVuZ3RoCnM9ZC5jaApmb3IocT0wO3E8cjsrK3EpaWYoIUguV2UoYSxILmNFKGEsYixt
-W3FdKSxjLHNbcV0sZSkpcmV0dXJuITEKcmV0dXJuITB9LApjYzpmdW5jdGlvbihhKXt2YXIgdCxzCmlm
-KGE9PT11LkspcmV0dXJuITAKdD1hLnoKaWYodCE9PTIpaWYodCE9PTMpaWYodCE9PTQpaWYodCE9PTUp
-cz10PT09OCYmSC5jYyhhLlEpCmVsc2Ugcz0hMAplbHNlIHM9ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMApy
-ZXR1cm4gc30sCkl4OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPU9iamVjdC5rZXlzKGIpLHE9ci5sZW5n
-dGgKZm9yKHQ9MDt0PHE7Kyt0KXtzPXJbdF0KYVtzXT1iW3NdfX0sCkpjOmZ1bmN0aW9uIEpjKGEsYixj
-KXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8ueT1fLng9Xy5kPW51bGwKXy56PTAKXy5kYj1f
-LmN5PV8uY3g9Xy5jaD1fLlE9bnVsbH0sCkc6ZnVuY3Rpb24gRygpe3RoaXMuYz10aGlzLmI9dGhpcy5h
-PW51bGx9LAp1OTpmdW5jdGlvbiB1OSgpe30sCmh6OmZ1bmN0aW9uIGh6KGEpe3RoaXMuYT1hfSwKaU06
-ZnVuY3Rpb24gaU0oYSl7dGhpcy5hPWF9LApSOTpmdW5jdGlvbihhKXtyZXR1cm4gdS5kLmMoYSl8fHUu
-Qi5jKGEpfHx1LmR6LmMoYSl8fHUuSS5jKGEpfHx1LkEuYyhhKXx8dS5nNC5jKGEpfHx1LmcyLmMoYSl9
-LApKZzpmdW5jdGlvbihhKXtyZXR1cm4gdi5tYW5nbGVkR2xvYmFsTmFtZXNbYV19fSxKPXsKUXU6ZnVu
-Y3Rpb24oYSxiLGMsZCl7cmV0dXJue2k6YSxwOmIsZTpjLHg6ZH19LAprczpmdW5jdGlvbihhKXt2YXIg
-dCxzLHIscSxwPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV0KaWYocD09bnVsbClpZigkLkJ2PT1udWxs
-KXtILlhEKCkKcD1hW3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdfWlmKHAhPW51bGwpe3Q9cC5wCmlmKCEx
-PT09dClyZXR1cm4gcC5pCmlmKCEwPT09dClyZXR1cm4gYQpzPU9iamVjdC5nZXRQcm90b3R5cGVPZihh
-KQppZih0PT09cylyZXR1cm4gcC5pCmlmKHAuZT09PXMpdGhyb3cgSC5iKFAuU1koIlJldHVybiBpbnRl
-cmNlcHRvciBmb3IgIitILmQodChhLHApKSkpfXI9YS5jb25zdHJ1Y3RvcgpxPXI9PW51bGw/bnVsbDpy
-WyQuVU4oKV0KaWYocSE9bnVsbClyZXR1cm4gcQpxPUgudzMoYSkKaWYocSE9bnVsbClyZXR1cm4gcQpp
-Zih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gQy5ERwp0PU9iamVjdC5nZXRQcm90b3R5cGVPZihh
-KQppZih0PT1udWxsKXJldHVybiBDLlpRCmlmKHQ9PT1PYmplY3QucHJvdG90eXBlKXJldHVybiBDLlpR
-CmlmKHR5cGVvZiByPT0iZnVuY3Rpb24iKXtPYmplY3QuZGVmaW5lUHJvcGVydHkociwkLlVOKCkse3Zh
-bHVlOkMudkIsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkK
-cmV0dXJuIEMudkJ9cmV0dXJuIEMudkJ9LApRaTpmdW5jdGlvbihhLGIpe2lmKGE8MHx8YT40Mjk0OTY3
-Mjk1KXRocm93IEguYihQLlRFKGEsMCw0Mjk0OTY3Mjk1LCJsZW5ndGgiLG51bGwpKQpyZXR1cm4gSi5w
-eShuZXcgQXJyYXkoYSksYil9LApweTpmdW5jdGlvbihhLGIpe3JldHVybiBKLkVwKEguVk0oYSxiLkMo
-ImpkPDA+IikpKX0sCkVwOmZ1bmN0aW9uKGEpe2EuZml4ZWQkbGVuZ3RoPUFycmF5CnJldHVybiBhfSwK
-ekM6ZnVuY3Rpb24oYSl7YS5maXhlZCRsZW5ndGg9QXJyYXkKYS5pbW11dGFibGUkbGlzdD1BcnJheQpy
-ZXR1cm4gYX0sCkdhOmZ1bmN0aW9uKGEpe2lmKGE8MjU2KXN3aXRjaChhKXtjYXNlIDk6Y2FzZSAxMDpj
-YXNlIDExOmNhc2UgMTI6Y2FzZSAxMzpjYXNlIDMyOmNhc2UgMTMzOmNhc2UgMTYwOnJldHVybiEwCmRl
-ZmF1bHQ6cmV0dXJuITF9c3dpdGNoKGEpe2Nhc2UgNTc2MDpjYXNlIDgxOTI6Y2FzZSA4MTkzOmNhc2Ug
-ODE5NDpjYXNlIDgxOTU6Y2FzZSA4MTk2OmNhc2UgODE5NzpjYXNlIDgxOTg6Y2FzZSA4MTk5OmNhc2Ug
-ODIwMDpjYXNlIDgyMDE6Y2FzZSA4MjAyOmNhc2UgODIzMjpjYXNlIDgyMzM6Y2FzZSA4MjM5OmNhc2Ug
-ODI4NzpjYXNlIDEyMjg4OmNhc2UgNjUyNzk6cmV0dXJuITAKZGVmYXVsdDpyZXR1cm4hMX19LAptbTpm
-dW5jdGlvbihhLGIpe3ZhciB0LHMKZm9yKHQ9YS5sZW5ndGg7Yjx0Oyl7cz1DLnhCLlcoYSxiKQppZihz
-IT09MzImJnMhPT0xMyYmIUouR2EocykpYnJlYWs7KytifXJldHVybiBifSwKYzE6ZnVuY3Rpb24oYSxi
-KXt2YXIgdCxzCmZvcig7Yj4wO2I9dCl7dD1iLTEKcz1DLnhCLm0oYSx0KQppZihzIT09MzImJnMhPT0x
-MyYmIUouR2EocykpYnJlYWt9cmV0dXJuIGJ9LApSRTpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVy
-biBhCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEou
-YzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLmspcmV0dXJuIGEKcmV0dXJuIEou
-a3MoYSl9LApUSjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIEoucUkucHJv
-dG90eXBlCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09bnVs
-bClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYo
-dHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90
-b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuaylyZXR1cm4gYQpyZXR1cm4gSi5rcyhhKX0s
-ClU2OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUK
-aWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90
-b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4g
-Si5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuaylyZXR1cm4gYQpyZXR1cm4g
-Si5rcyhhKX0sCmlhOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIil7aWYoTWF0aC5mbG9v
-cihhKT09YSlyZXR1cm4gSi51ci5wcm90b3R5cGUKcmV0dXJuIEouVkEucHJvdG90eXBlfWlmKHR5cGVv
-ZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09bnVsbClyZXR1cm4gSi5ZRS5w
-cm90b3R5cGUKaWYodHlwZW9mIGE9PSJib29sZWFuIilyZXR1cm4gSi55RS5wcm90b3R5cGUKaWYoYS5j
-b25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQucHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0
-Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlm
-KGEgaW5zdGFuY2VvZiBQLmspcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApyWTpmdW5jdGlvbihhKXtp
-Zih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0dXJu
-IGEKaWYoIShhIGluc3RhbmNlb2YgUC5rKSlyZXR1cm4gSi5rZC5wcm90b3R5cGUKcmV0dXJuIGF9LAp3
-MTpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVybiBhCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJl
+cCxvCmlmKHR5cGVvZiBhIT0ic3RyaW5nIilILnZoKEgudEwoYSkpCnQ9L15ccypbKy1dPygoMHhbYS1m
+MC05XSspfChcZCspfChbYS16MC05XSspKVxzKiQvaS5leGVjKGEpCmlmKHQ9PW51bGwpcmV0dXJuCmlm
+KDM+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsMykKcz1ILnkodFszXSkKaWYoYj09bnVsbCl7aWYocyE9
+bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwxMCkKaWYodFsyXSE9bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwx
+NikKcmV0dXJufWlmKGI8Mnx8Yj4zNil0aHJvdyBILmIoUC5URShiLDIsMzYsInJhZGl4IixudWxsKSkK
+aWYoYj09PTEwJiZzIT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZihiPDEwfHxzPT1udWxsKXty
+PWI8PTEwPzQ3K2I6ODYrYgpxPXRbMV0KZm9yKHA9cS5sZW5ndGgsbz0wO288cDsrK28paWYoKEMueEIu
+VyhxLG8pfDMyKT5yKXJldHVybn1yZXR1cm4gcGFyc2VJbnQoYSxiKX0sCk06ZnVuY3Rpb24oYSl7dmFy
+IHQ9SC5INShhKQpyZXR1cm4gdH0sCkg1OmZ1bmN0aW9uKGEpe3ZhciB0LHMscgppZihhIGluc3RhbmNl
+b2YgUC5rKXJldHVybiBILmRtKEgueksoYSksbnVsbCkKaWYoSi5pYShhKT09PUMuT2t8fHUuYWsuYyhh
+KSl7dD1DLk80KGEpCmlmKEguZih0KSlyZXR1cm4gdApzPWEuY29uc3RydWN0b3IKaWYodHlwZW9mIHM9
+PSJmdW5jdGlvbiIpe3I9cy5uYW1lCmlmKHR5cGVvZiByPT0ic3RyaW5nIiYmSC5mKHIpKXJldHVybiBy
+fX1yZXR1cm4gSC5kbShILnpLKGEpLG51bGwpfSwKZjpmdW5jdGlvbihhKXt2YXIgdD1hIT09Ik9iamVj
+dCImJmEhPT0iIgpyZXR1cm4gdH0sCk0wOmZ1bmN0aW9uKCl7aWYoISFzZWxmLmxvY2F0aW9uKXJldHVy
+biBzZWxmLmxvY2F0aW9uLmhyZWYKcmV0dXJufSwKVks6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1h
+Lmxlbmd0aAppZihwPD01MDApcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxhKQpm
+b3IodD0iIixzPTA7czxwO3M9cil7cj1zKzUwMApxPXI8cD9yOnAKdCs9U3RyaW5nLmZyb21DaGFyQ29k
+ZS5hcHBseShudWxsLGEuc2xpY2UocyxxKSl9cmV0dXJuIHR9LApQTDpmdW5jdGlvbihhKXt2YXIgdCxz
+LHIscT1ILlZNKFtdLHUudCkKZm9yKHQ9YS5sZW5ndGgscz0wO3M8YS5sZW5ndGg7YS5sZW5ndGg9PT10
+fHwoMCxILmxrKShhKSwrK3Mpe3I9YVtzXQppZighSC5vayhyKSl0aHJvdyBILmIoSC50TChyKSkKaWYo
+cjw9NjU1MzUpQy5ObS5pKHEscikKZWxzZSBpZihyPD0xMTE0MTExKXtDLk5tLmkocSw1NTI5NisoQy5q
+bi53RyhyLTY1NTM2LDEwKSYxMDIzKSkKQy5ObS5pKHEsNTYzMjArKHImMTAyMykpfWVsc2UgdGhyb3cg
+SC5iKEgudEwocikpfXJldHVybiBILlZLKHEpfSwKZVQ6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCmZvcih0
+PWEubGVuZ3RoLHM9MDtzPHQ7KytzKXtyPWFbc10KaWYoIUgub2socikpdGhyb3cgSC5iKEgudEwocikp
+CmlmKHI8MCl0aHJvdyBILmIoSC50TChyKSkKaWYocj42NTUzNSlyZXR1cm4gSC5QTChhKX1yZXR1cm4g
+SC5WSyhhKX0sCmZ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihjPD01MDAmJmI9PT0wJiZj
+PT09YS5sZW5ndGgpcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxhKQpmb3IodD1i
+LHM9IiI7dDxjO3Q9cil7cj10KzUwMApxPXI8Yz9yOmMKcys9U3RyaW5nLmZyb21DaGFyQ29kZS5hcHBs
+eShudWxsLGEuc3ViYXJyYXkodCxxKSl9cmV0dXJuIHN9LApMdzpmdW5jdGlvbihhKXt2YXIgdAppZigw
+PD1hKXtpZihhPD02NTUzNSlyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShhKQppZihhPD0xMTE0MTEx
+KXt0PWEtNjU1MzYKcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoKDU1Mjk2fEMuam4ud0codCwxMCkp
+Pj4+MCw1NjMyMHx0JjEwMjMpfX10aHJvdyBILmIoUC5URShhLDAsMTExNDExMSxudWxsLG51bGwpKX0s
+Cm8yOmZ1bmN0aW9uKGEpe2lmKGEuZGF0ZT09PXZvaWQgMClhLmRhdGU9bmV3IERhdGUoYS5hKQpyZXR1
+cm4gYS5kYXRlfSwKdEo6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vMihhKS5nZXRGdWxsWWVhcigpKzAKcmV0
+dXJuIHR9LApOUzpmdW5jdGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldE1vbnRoKCkrMQpyZXR1cm4gdH0s
+CmpBOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0RGF0ZSgpKzAKcmV0dXJuIHR9LApLTDpmdW5j
+dGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldEhvdXJzKCkrMApyZXR1cm4gdH0sCmNoOmZ1bmN0aW9uKGEp
+e3ZhciB0PUgubzIoYSkuZ2V0TWludXRlcygpKzAKcmV0dXJuIHR9LApKZDpmdW5jdGlvbihhKXt2YXIg
+dD1ILm8yKGEpLmdldFNlY29uZHMoKSswCnJldHVybiB0fSwKbzE6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5v
+MihhKS5nZXRNaWxsaXNlY29uZHMoKSswCnJldHVybiB0fSwKem86ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
+LHMscj17fQpyLmE9MAp0PVtdCnM9W10Kci5hPWIubGVuZ3RoCkMuTm0uRlYodCxiKQpyLmI9IiIKaWYo
+YyE9bnVsbCYmYy5hIT09MCljLksoMCxuZXcgSC5DaihyLHMsdCkpCiIiK3IuYQpyZXR1cm4gSi5KeShh
+LG5ldyBILkxJKEMuVGUsMCx0LHMsMCkpfSwKRWs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmlm
+KGIgaW5zdGFuY2VvZiBBcnJheSl0PWM9PW51bGx8fGMuYT09PTAKZWxzZSB0PSExCmlmKHQpe3M9Ygpy
+PXMubGVuZ3RoCmlmKHI9PT0wKXtpZighIWEuJDApcmV0dXJuIGEuJDAoKX1lbHNlIGlmKHI9PT0xKXtp
+ZighIWEuJDEpcmV0dXJuIGEuJDEoc1swXSl9ZWxzZSBpZihyPT09Mil7aWYoISFhLiQyKXJldHVybiBh
+LiQyKHNbMF0sc1sxXSl9ZWxzZSBpZihyPT09Myl7aWYoISFhLiQzKXJldHVybiBhLiQzKHNbMF0sc1sx
+XSxzWzJdKX1lbHNlIGlmKHI9PT00KXtpZighIWEuJDQpcmV0dXJuIGEuJDQoc1swXSxzWzFdLHNbMl0s
+c1szXSl9ZWxzZSBpZihyPT09NSlpZighIWEuJDUpcmV0dXJuIGEuJDUoc1swXSxzWzFdLHNbMl0sc1sz
+XSxzWzRdKQpxPWFbIiIrIiQiK3JdCmlmKHEhPW51bGwpcmV0dXJuIHEuYXBwbHkoYSxzKX1yZXR1cm4g
+SC5FdyhhLGIsYyl9LApFdzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGs9YiBp
+bnN0YW5jZW9mIEFycmF5P2I6UC5DSChiLCEwLHUueiksaj1rLmxlbmd0aCxpPWEuJFIKaWYoajxpKXJl
+dHVybiBILnpvKGEsayxjKQp0PWEuJEQKcz10PT1udWxsCnI9IXM/dCgpOm51bGwKcT1KLmlhKGEpCnA9
+cS4kQwppZih0eXBlb2YgcD09InN0cmluZyIpcD1xW3BdCmlmKHMpe2lmKGMhPW51bGwmJmMuYSE9PTAp
+cmV0dXJuIEguem8oYSxrLGMpCmlmKGo9PT1pKXJldHVybiBwLmFwcGx5KGEsaykKcmV0dXJuIEguem8o
+YSxrLGMpfWlmKHIgaW5zdGFuY2VvZiBBcnJheSl7aWYoYyE9bnVsbCYmYy5hIT09MClyZXR1cm4gSC56
+byhhLGssYykKaWYoaj5pK3IubGVuZ3RoKXJldHVybiBILnpvKGEsayxudWxsKQpDLk5tLkZWKGssci5z
+bGljZShqLWkpKQpyZXR1cm4gcC5hcHBseShhLGspfWVsc2V7aWYoaj5pKXJldHVybiBILnpvKGEsayxj
+KQpvPU9iamVjdC5rZXlzKHIpCmlmKGM9PW51bGwpZm9yKHM9by5sZW5ndGgsbj0wO248by5sZW5ndGg7
+by5sZW5ndGg9PT1zfHwoMCxILmxrKShvKSwrK24pQy5ObS5pKGsscltILnkob1tuXSldKQplbHNle2Zv
+cihzPW8ubGVuZ3RoLG09MCxuPTA7bjxvLmxlbmd0aDtvLmxlbmd0aD09PXN8fCgwLEgubGspKG8pLCsr
+bil7bD1ILnkob1tuXSkKaWYoYy54NChsKSl7KyttCkMuTm0uaShrLGMucSgwLGwpKX1lbHNlIEMuTm0u
+aShrLHJbbF0pfWlmKG0hPT1jLmEpcmV0dXJuIEguem8oYSxrLGMpfXJldHVybiBwLmFwcGx5KGEsayl9
+fSwKcFk6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKEgudEwoYSkpfSwKT0g6ZnVuY3Rpb24oYSxiKXtpZihh
+PT1udWxsKUouSG0oYSkKdGhyb3cgSC5iKEguSFkoYSxiKSl9LApIWTpmdW5jdGlvbihhLGIpe3ZhciB0
+LHMscj0iaW5kZXgiCmlmKCFILm9rKGIpKXJldHVybiBuZXcgUC51KCEwLGIscixudWxsKQp0PUguU2Mo
+Si5IbShhKSkKaWYoIShiPDApKXtpZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiBILnBZKHQpCnM9
+Yj49dH1lbHNlIHM9ITAKaWYocylyZXR1cm4gUC5DZihiLGEscixudWxsLHQpCnJldHVybiBQLngoYixy
+KX0sCmF1OmZ1bmN0aW9uKGEsYixjKXt2YXIgdD0iSW52YWxpZCB2YWx1ZSIKaWYoYT5jKXJldHVybiBu
+ZXcgUC5iSigwLGMsITAsYSwic3RhcnQiLHQpCmlmKGIhPW51bGwpe2lmKCFILm9rKGIpKXJldHVybiBu
+ZXcgUC51KCEwLGIsImVuZCIsbnVsbCkKaWYoYjxhfHxiPmMpcmV0dXJuIG5ldyBQLmJKKGEsYywhMCxi
+LCJlbmQiLHQpfXJldHVybiBuZXcgUC51KCEwLGIsImVuZCIsbnVsbCl9LAp0TDpmdW5jdGlvbihhKXty
+ZXR1cm4gbmV3IFAudSghMCxhLG51bGwsbnVsbCl9LApiOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGE9PW51
+bGwpYT1uZXcgUC5uKCkKdD1uZXcgRXJyb3IoKQp0LmRhcnRFeGNlcHRpb249YQppZigiZGVmaW5lUHJv
+cGVydHkiIGluIE9iamVjdCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsIm1lc3NhZ2UiLHtnZXQ6SC5o
+fSkKdC5uYW1lPSIifWVsc2UgdC50b1N0cmluZz1ILmgKcmV0dXJuIHR9LApoOmZ1bmN0aW9uKCl7cmV0
+dXJuIEouaih0aGlzLmRhcnRFeGNlcHRpb24pfSwKdmg6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKGEpfSwK
+bGs6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKFAuYTQoYSkpfSwKY006ZnVuY3Rpb24oYSl7dmFyIHQscyxy
+LHEscCxvCmE9SC5lQShhLnJlcGxhY2UoU3RyaW5nKHt9KSwnJHJlY2VpdmVyJCcpKQp0PWEubWF0Y2go
+L1xcXCRbYS16QS1aXStcXFwkL2cpCmlmKHQ9PW51bGwpdD1ILlZNKFtdLHUucykKcz10LmluZGV4T2Yo
+IlxcJGFyZ3VtZW50c1xcJCIpCnI9dC5pbmRleE9mKCJcXCRhcmd1bWVudHNFeHByXFwkIikKcT10Lmlu
+ZGV4T2YoIlxcJGV4cHJcXCQiKQpwPXQuaW5kZXhPZigiXFwkbWV0aG9kXFwkIikKbz10LmluZGV4T2Yo
+IlxcJHJlY2VpdmVyXFwkIikKcmV0dXJuIG5ldyBILlpyKGEucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxc
+XFwkYXJndW1lbnRzXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4
+cCgnXFxcXFxcJGFyZ3VtZW50c0V4cHJcXFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJykucmVwbGFj
+ZShuZXcgUmVnRXhwKCdcXFxcXFwkZXhwclxcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKiknKS5yZXBs
+YWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRtZXRob2RcXFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJyku
+cmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkcmVjZWl2ZXJcXFxcXFwkJywnZycpLCcoKD86eHxbXnhd
+KSopJykscyxyLHEscCxvKX0sClM3OmZ1bmN0aW9uKGEpe3JldHVybiBmdW5jdGlvbigkZXhwciQpe3Zh
+ciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7JGV4cHIkLiRtZXRob2QkKCRhcmd1bWVu
+dHNFeHByJCl9Y2F0Y2godCl7cmV0dXJuIHQubWVzc2FnZX19KGEpfSwKTWo6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGZ1bmN0aW9uKCRleHByJCl7dHJ5eyRleHByJC4kbWV0aG9kJH1jYXRjaCh0KXtyZXR1cm4gdC5t
+ZXNzYWdlfX0oYSl9LApJajpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5XMChhLGI9PW51bGw/bnVs
+bDpiLm1ldGhvZCl9LApUMzpmdW5jdGlvbihhLGIpe3ZhciB0PWI9PW51bGwscz10P251bGw6Yi5tZXRo
+b2QKcmV0dXJuIG5ldyBILmF6KGEscyx0P251bGw6Yi5yZWNlaXZlcil9LApSdTpmdW5jdGlvbihhKXt2
+YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGY9bnVsbCxlPW5ldyBILkFtKGEpCmlmKGE9PW51
+bGwpcmV0dXJuCmlmKGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBlLiQxKGEuYSkKaWYodHlwZW9mIGEh
+PT0ib2JqZWN0IilyZXR1cm4gYQppZigiZGFydEV4Y2VwdGlvbiIgaW4gYSlyZXR1cm4gZS4kMShhLmRh
+cnRFeGNlcHRpb24pCmVsc2UgaWYoISgibWVzc2FnZSIgaW4gYSkpcmV0dXJuIGEKdD1hLm1lc3NhZ2UK
+aWYoIm51bWJlciIgaW4gYSYmdHlwZW9mIGEubnVtYmVyPT0ibnVtYmVyIil7cz1hLm51bWJlcgpyPXMm
+NjU1MzUKaWYoKEMuam4ud0cocywxNikmODE5MSk9PT0xMClzd2l0Y2gocil7Y2FzZSA0Mzg6cmV0dXJu
+IGUuJDEoSC5UMyhILmQodCkrIiAoRXJyb3IgIityKyIpIixmKSkKY2FzZSA0NDU6Y2FzZSA1MDA3OnJl
+dHVybiBlLiQxKEguSWooSC5kKHQpKyIgKEVycm9yICIrcisiKSIsZikpfX1pZihhIGluc3RhbmNlb2Yg
+VHlwZUVycm9yKXtxPSQuU24oKQpwPSQubHEoKQpvPSQuTjkoKQpuPSQuaUkoKQptPSQuS2YoKQpsPSQu
+WmgoKQprPSQuY1AoKQokLmMzKCkKaj0kLkhLKCkKaT0kLnIxKCkKaD1xLnFTKHQpCmlmKGghPW51bGwp
+cmV0dXJuIGUuJDEoSC5UMyhILnkodCksaCkpCmVsc2V7aD1wLnFTKHQpCmlmKGghPW51bGwpe2gubWV0
+aG9kPSJjYWxsIgpyZXR1cm4gZS4kMShILlQzKEgueSh0KSxoKSl9ZWxzZXtoPW8ucVModCkKaWYoaD09
+bnVsbCl7aD1uLnFTKHQpCmlmKGg9PW51bGwpe2g9bS5xUyh0KQppZihoPT1udWxsKXtoPWwucVModCkK
+aWYoaD09bnVsbCl7aD1rLnFTKHQpCmlmKGg9PW51bGwpe2g9bi5xUyh0KQppZihoPT1udWxsKXtoPWou
+cVModCkKaWYoaD09bnVsbCl7aD1pLnFTKHQpCmc9aCE9bnVsbH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVs
+c2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITAKaWYoZylyZXR1cm4g
+ZS4kMShILklqKEgueSh0KSxoKSl9fXJldHVybiBlLiQxKG5ldyBILnZWKHR5cGVvZiB0PT0ic3RyaW5n
+Ij90OiIiKSl9aWYoYSBpbnN0YW5jZW9mIFJhbmdlRXJyb3Ipe2lmKHR5cGVvZiB0PT0ic3RyaW5nIiYm
+dC5pbmRleE9mKCJjYWxsIHN0YWNrIikhPT0tMSlyZXR1cm4gbmV3IFAuS1koKQp0PWZ1bmN0aW9uKGIp
+e3RyeXtyZXR1cm4gU3RyaW5nKGIpfWNhdGNoKGQpe31yZXR1cm4gbnVsbH0oYSkKcmV0dXJuIGUuJDEo
+bmV3IFAudSghMSxmLGYsdHlwZW9mIHQ9PSJzdHJpbmciP3QucmVwbGFjZSgvXlJhbmdlRXJyb3I6XHMq
+LywiIik6dCkpfWlmKHR5cGVvZiBJbnRlcm5hbEVycm9yPT0iZnVuY3Rpb24iJiZhIGluc3RhbmNlb2Yg
+SW50ZXJuYWxFcnJvcilpZih0eXBlb2YgdD09InN0cmluZyImJnQ9PT0idG9vIG11Y2ggcmVjdXJzaW9u
+IilyZXR1cm4gbmV3IFAuS1koKQpyZXR1cm4gYX0sCnRzOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGEgaW5z
+dGFuY2VvZiBILmJxKXJldHVybiBhLmIKaWYoYT09bnVsbClyZXR1cm4gbmV3IEguWE8oYSkKdD1hLiRj
+YWNoZWRUcmFjZQppZih0IT1udWxsKXJldHVybiB0CnJldHVybiBhLiRjYWNoZWRUcmFjZT1uZXcgSC5Y
+TyhhKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHE9YS5sZW5ndGgKZm9yKHQ9MDt0PHE7dD1y
+KXtzPXQrMQpyPXMrMQpiLlkoMCxhW3RdLGFbc10pfXJldHVybiBifSwKZnQ6ZnVuY3Rpb24oYSxiLGMs
+ZCxlLGYpe3UuWi5iKGEpCnN3aXRjaChILlNjKGIpKXtjYXNlIDA6cmV0dXJuIGEuJDAoKQpjYXNlIDE6
+cmV0dXJuIGEuJDEoYykKY2FzZSAyOnJldHVybiBhLiQyKGMsZCkKY2FzZSAzOnJldHVybiBhLiQzKGMs
+ZCxlKQpjYXNlIDQ6cmV0dXJuIGEuJDQoYyxkLGUsZil9dGhyb3cgSC5iKG5ldyBQLkNEKCJVbnN1cHBv
+cnRlZCBudW1iZXIgb2YgYXJndW1lbnRzIGZvciB3cmFwcGVkIGNsb3N1cmUiKSl9LAp0UjpmdW5jdGlv
+bihhLGIpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuCnQ9YS4kaWRlbnRpdHkKaWYoISF0KXJldHVybiB0
+CnQ9ZnVuY3Rpb24oYyxkLGUpe3JldHVybiBmdW5jdGlvbihmLGcsaCxpKXtyZXR1cm4gZShjLGQsZixn
+LGgsaSl9fShhLGIsSC5mdCkKYS4kaWRlbnRpdHk9dApyZXR1cm4gdH0sCmlBOmZ1bmN0aW9uKGEsYixj
+LGQsZSxmLGcpe3ZhciB0LHMscixxLHAsbyxuLG0sbD1udWxsLGs9YlswXSxqPWsuJGNhbGxOYW1lLGk9
+ZT9PYmplY3QuY3JlYXRlKG5ldyBILnp4KCkuY29uc3RydWN0b3IucHJvdG90eXBlKTpPYmplY3QuY3Jl
+YXRlKG5ldyBILnJUKGwsbCxsLGwpLmNvbnN0cnVjdG9yLnByb3RvdHlwZSkKaS4kaW5pdGlhbGl6ZT1p
+LmNvbnN0cnVjdG9yCmlmKGUpdD1mdW5jdGlvbiBzdGF0aWNfdGVhcl9vZmYoKXt0aGlzLiRpbml0aWFs
+aXplKCl9CmVsc2V7cz0kLnlqCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuaCgpCiQueWo9
+cysxCnM9bmV3IEZ1bmN0aW9uKCJhLGIsYyxkIitzLCJ0aGlzLiRpbml0aWFsaXplKGEsYixjLGQiK3Mr
+IikiKQp0PXN9aS5jb25zdHJ1Y3Rvcj10CnQucHJvdG90eXBlPWkKaWYoIWUpe3I9SC5ieChhLGssZikK
+ci4kcmVmbGVjdGlvbkluZm89ZH1lbHNle2kuJHN0YXRpY19uYW1lPWcKcj1rfXE9SC5pbShkLGUsZikK
+aS4kUz1xCmlbal09cgpmb3IocD1yLG89MTtvPGIubGVuZ3RoOysrbyl7bj1iW29dCm09bi4kY2FsbE5h
+bWUKaWYobSE9bnVsbCl7bj1lP246SC5ieChhLG4sZikKaVttXT1ufWlmKG89PT1jKXtuLiRyZWZsZWN0
+aW9uSW5mbz1kCnA9bn19aS4kQz1wCmkuJFI9ay4kUgppLiREPWsuJEQKcmV0dXJuIHR9LAppbTpmdW5j
+dGlvbihhLGIsYyl7dmFyIHQKaWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBmdW5jdGlvbihkLGUp
+e3JldHVybiBmdW5jdGlvbigpe3JldHVybiBkKGUpfX0oSC5CcCxhKQppZih0eXBlb2YgYT09InN0cmlu
+ZyIpe2lmKGIpdGhyb3cgSC5iKCJDYW5ub3QgY29tcHV0ZSBzaWduYXR1cmUgZm9yIHN0YXRpYyB0ZWFy
+b2ZmLiIpCnQ9Yz9ILlBXOkguVG4KcmV0dXJuIGZ1bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7
+cmV0dXJuIGUodGhpcyxkKX19KGEsdCl9dGhyb3cgSC5iKCJFcnJvciBpbiBmdW5jdGlvblR5cGUgb2Yg
+dGVhcm9mZiIpfSwKdnE6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9SC5EVgpzd2l0Y2goYj8tMTphKXtj
+YXNlIDA6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYodGhpcylb
+ZV0oKX19KGMsdCkKY2FzZSAxOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnKXty
+ZXR1cm4gZih0aGlzKVtlXShnKX19KGMsdCkKY2FzZSAyOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVy
+biBmdW5jdGlvbihnLGgpe3JldHVybiBmKHRoaXMpW2VdKGcsaCl9fShjLHQpCmNhc2UgMzpyZXR1cm4g
+ZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyxoLGkpe3JldHVybiBmKHRoaXMpW2VdKGcsaCxp
+KX19KGMsdCkKY2FzZSA0OnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSxq
+KXtyZXR1cm4gZih0aGlzKVtlXShnLGgsaSxqKX19KGMsdCkKY2FzZSA1OnJldHVybiBmdW5jdGlvbihl
+LGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSxqLGspe3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGosayl9
+fShjLHQpCmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJu
+IGUuYXBwbHkoZih0aGlzKSxhcmd1bWVudHMpfX0oZCx0KX19LApieDpmdW5jdGlvbihhLGIsYyl7dmFy
+IHQscyxyLHEscCxvLG4KaWYoYylyZXR1cm4gSC5IZihhLGIpCnQ9Yi4kc3R1Yk5hbWUKcz1iLmxlbmd0
+aApyPWFbdF0KcT1iPT1udWxsP3I9PW51bGw6Yj09PXIKcD0hcXx8cz49MjcKaWYocClyZXR1cm4gSC52
+cShzLCFxLHQsYikKaWYocz09PTApe3E9JC55agppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBx
+LmgoKQokLnlqPXErMQpvPSJzZWxmIitxCnE9InJldHVybiBmdW5jdGlvbigpe3ZhciAiK28rIiA9IHRo
+aXMuIgpwPSQubUoKcmV0dXJuIG5ldyBGdW5jdGlvbihxK0guZChwPT1udWxsPyQubUo9SC5FMigic2Vs
+ZiIpOnApKyI7cmV0dXJuICIrbysiLiIrSC5kKHQpKyIoKTt9IikoKX1uPSJhYmNkZWZnaGlqa2xtbm9w
+cXJzdHV2d3h5eiIuc3BsaXQoIiIpLnNwbGljZSgwLHMpLmpvaW4oIiwiKQpxPSQueWoKaWYodHlwZW9m
+IHEhPT0ibnVtYmVyIilyZXR1cm4gcS5oKCkKJC55aj1xKzEKbis9cQpxPSJyZXR1cm4gZnVuY3Rpb24o
+IituKyIpe3JldHVybiB0aGlzLiIKcD0kLm1KCnJldHVybiBuZXcgRnVuY3Rpb24ocStILmQocD09bnVs
+bD8kLm1KPUguRTIoInNlbGYiKTpwKSsiLiIrSC5kKHQpKyIoIituKyIpO30iKSgpfSwKWjQ6ZnVuY3Rp
+b24oYSxiLGMsZCl7dmFyIHQ9SC5EVixzPUgueVMKc3dpdGNoKGI/LTE6YSl7Y2FzZSAwOnRocm93IEgu
+YihILkVmKCJJbnRlcmNlcHRlZCBmdW5jdGlvbiB3aXRoIG5vIGFyZ3VtZW50cy4iKSkKY2FzZSAxOnJl
+dHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYodGhpcylbZV0oZyh0
+aGlzKSl9fShjLHQscykKY2FzZSAyOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9u
+KGgpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCl9fShjLHQscykKY2FzZSAzOnJldHVybiBmdW5j
+dGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxo
+LGkpfX0oYyx0LHMpCmNhc2UgNDpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbiho
+LGksail7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksail9fShjLHQscykKY2FzZSA1OnJldHVy
+biBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqLGspe3JldHVybiBmKHRoaXMpW2Vd
+KGcodGhpcyksaCxpLGosayl9fShjLHQscykKY2FzZSA2OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0
+dXJuIGZ1bmN0aW9uKGgsaSxqLGssbCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksaixrLGwp
+fX0oYyx0LHMpCmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKGUsZixnLGgpe3JldHVybiBmdW5jdGlvbigp
+e2g9W2codGhpcyldCkFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGgsYXJndW1lbnRzKQpyZXR1cm4g
+ZS5hcHBseShmKHRoaXMpLGgpfX0oZCx0LHMpfX0sCkhmOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEs
+cCxvLG4sbT0kLm1KCmlmKG09PW51bGwpbT0kLm1KPUguRTIoInNlbGYiKQp0PSQuUDQKaWYodD09bnVs
+bCl0PSQuUDQ9SC5FMigicmVjZWl2ZXIiKQpzPWIuJHN0dWJOYW1lCnI9Yi5sZW5ndGgKcT1hW3NdCnA9
+Yj09bnVsbD9xPT1udWxsOmI9PT1xCm89IXB8fHI+PTI4CmlmKG8pcmV0dXJuIEguWjQociwhcCxzLGIp
+CmlmKHI9PT0xKXttPSJyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4iK0guZChtKSsiLiIrSC5k
+KHMpKyIodGhpcy4iK0guZCh0KSsiKTsiCnQ9JC55agppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVy
+biB0LmgoKQokLnlqPXQrMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKG0rdCsifSIpKCl9bj0iYWJjZGVmZ2hp
+amtsbW5vcHFyc3R1dnd4eXoiLnNwbGl0KCIiKS5zcGxpY2UoMCxyLTEpLmpvaW4oIiwiKQptPSJyZXR1
+cm4gZnVuY3Rpb24oIituKyIpe3JldHVybiB0aGlzLiIrSC5kKG0pKyIuIitILmQocykrIih0aGlzLiIr
+SC5kKHQpKyIsICIrbisiKTsiCnQ9JC55agppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0Lmgo
+KQokLnlqPXQrMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKG0rdCsifSIpKCl9LApLcTpmdW5jdGlvbihhLGIs
+YyxkLGUsZixnKXtyZXR1cm4gSC5pQShhLGIsYyxkLCEhZSwhIWYsZyl9LApUbjpmdW5jdGlvbihhLGIp
+e3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLEgueksoYS5hKSxiKX0sClBXOmZ1bmN0aW9uKGEsYil7
+cmV0dXJuIEguY0Uodi50eXBlVW5pdmVyc2UsSC56SyhhLmMpLGIpfSwKRFY6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEuYX0sCnlTOmZ1bmN0aW9uKGEpe3JldHVybiBhLmN9LApFMjpmdW5jdGlvbihhKXt2YXIgdCxz
+LHIscT1uZXcgSC5yVCgic2VsZiIsInRhcmdldCIsInJlY2VpdmVyIiwibmFtZSIpLHA9Si5FcChPYmpl
+Y3QuZ2V0T3duUHJvcGVydHlOYW1lcyhxKSkKZm9yKHQ9cC5sZW5ndGgscz0wO3M8dDsrK3Mpe3I9cFtz
+XQppZihxW3JdPT09YSlyZXR1cm4gcn19LApvVDpmdW5jdGlvbihhKXtpZihhPT1udWxsKUguZk8oImJv
+b2xlYW4gZXhwcmVzc2lvbiBtdXN0IG5vdCBiZSBudWxsIikKcmV0dXJuIGF9LApmTzpmdW5jdGlvbihh
+KXt0aHJvdyBILmIobmV3IEgua1koYSkpfSwKYWc6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKG5ldyBQLmMo
+YSkpfSwKRWY6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILkVxKGEpfSwKWWc6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHYuZ2V0SXNvbGF0ZVRhZyhhKX0sClZNOmZ1bmN0aW9uKGEsYil7YS4kdGk9YgpyZXR1cm4gYX0s
+Cm9YOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuCnJldHVybiBhLiR0aX0sCklNOmZ1bmN0aW9u
+KGEsYixjKXtyZXR1cm4gSC5ZOShhWyIkYSIrSC5kKGMpXSxILm9YKGIpKX0sClk5OmZ1bmN0aW9uKGEs
+Yil7aWYoYT09bnVsbClyZXR1cm4gYgphPWEuYXBwbHkobnVsbCxiKQppZihhPT1udWxsKXJldHVybgpp
+ZihBcnJheS5pc0FycmF5KGEpKXJldHVybiBhCmlmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBh
+LmFwcGx5KG51bGwsYikKcmV0dXJuIGJ9LApJRzpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIGEuYXBwbHko
+YixILlk5KEouaWEoYilbIiRhIitILmQoYyldLEgub1goYikpKX0sCml3OmZ1bmN0aW9uKGEsYixjKXtP
+YmplY3QuZGVmaW5lUHJvcGVydHkoYSxiLHt2YWx1ZTpjLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6
+dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pfSwKdzM6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1ILnko
+JC5ORi4kMShhKSksbz0kLm53W3BdCmlmKG8hPW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShhLHYu
+ZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVl
+LGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX10PSQudnZbcF0KaWYodCE9bnVsbClyZXR1cm4g
+dApzPXYuaW50ZXJjZXB0b3JzQnlUYWdbcF0KaWYocz09bnVsbCl7cD1ILnkoJC5UWC4kMihhLHApKQpp
+ZihwIT1udWxsKXtvPSQubndbcF0KaWYobyE9bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsdi5k
+aXNwYXRjaFByb3BlcnR5TmFtZSx7dmFsdWU6byxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUs
+Y29uZmlndXJhYmxlOnRydWV9KQpyZXR1cm4gby5pfXQ9JC52dltwXQppZih0IT1udWxsKXJldHVybiB0
+CnM9di5pbnRlcmNlcHRvcnNCeVRhZ1twXX19aWYocz09bnVsbClyZXR1cm4KdD1zLnByb3RvdHlwZQpy
+PXBbMF0KaWYocj09PSIhIil7bz1ILlZhKHQpCiQubndbcF09bwpPYmplY3QuZGVmaW5lUHJvcGVydHko
+YSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpvLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6
+dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBvLml9aWYocj09PSJ+Iil7JC52dltwXT10CnJl
+dHVybiB0fWlmKHI9PT0iLSIpe3E9SC5WYSh0KQpPYmplY3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0Lmdl
+dFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOnEsZW51bWVyYWJsZTpm
+YWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIHEuaX1pZihyPT09Iisi
+KXJldHVybiBILkxjKGEsdCkKaWYocj09PSIqIil0aHJvdyBILmIoUC5TWShwKSkKaWYodi5sZWFmVGFn
+c1twXT09PXRydWUpe3E9SC5WYSh0KQpPYmplY3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0LmdldFByb3Rv
+dHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOnEsZW51bWVyYWJsZTpmYWxzZSx3
+cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIHEuaX1lbHNlIHJldHVybiBILkxj
+KGEsdCl9LApMYzpmdW5jdGlvbihhLGIpe3ZhciB0PU9iamVjdC5nZXRQcm90b3R5cGVPZihhKQpPYmpl
+Y3QuZGVmaW5lUHJvcGVydHkodCx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpKLlF1KGIsdCxu
+dWxsLG51bGwpLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0p
+CnJldHVybiBifSwKVmE6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUXUoYSwhMSxudWxsLCEhYS4kaVhqKX0s
+ClZGOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1iLnByb3RvdHlwZQppZih2LmxlYWZUYWdzW2FdPT09dHJ1
+ZSlyZXR1cm4gSC5WYSh0KQplbHNlIHJldHVybiBKLlF1KHQsYyxudWxsLG51bGwpfSwKWEQ6ZnVuY3Rp
+b24oKXtpZighMD09PSQuQnYpcmV0dXJuCiQuQnY9ITAKSC5aMSgpfSwKWjE6ZnVuY3Rpb24oKXt2YXIg
+dCxzLHIscSxwLG8sbixtCiQubnc9T2JqZWN0LmNyZWF0ZShudWxsKQokLnZ2PU9iamVjdC5jcmVhdGUo
+bnVsbCkKSC5rTygpCnQ9di5pbnRlcmNlcHRvcnNCeVRhZwpzPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5h
+bWVzKHQpCmlmKHR5cGVvZiB3aW5kb3chPSJ1bmRlZmluZWQiKXt3aW5kb3cKcj1mdW5jdGlvbigpe30K
+Zm9yKHE9MDtxPHMubGVuZ3RoOysrcSl7cD1zW3FdCm89JC54Ny4kMShwKQppZihvIT1udWxsKXtuPUgu
+VkYocCx0W3BdLG8pCmlmKG4hPW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShvLHYuZGlzcGF0Y2hQ
+cm9wZXJ0eU5hbWUse3ZhbHVlOm4sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3Vy
+YWJsZTp0cnVlfSkKci5wcm90b3R5cGU9b319fX1mb3IocT0wO3E8cy5sZW5ndGg7KytxKXtwPXNbcV0K
+aWYoL15bQS1aYS16X10vLnRlc3QocCkpe209dFtwXQp0WyIhIitwXT1tCnRbIn4iK3BdPW0KdFsiLSIr
+cF09bQp0WyIrIitwXT1tCnRbIioiK3BdPW19fX0sCmtPOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxv
+LG49Qy5ZcSgpCm49SC51ZChDLktVLEgudWQoQy5mUSxILnVkKEMuaTcsSC51ZChDLmk3LEgudWQoQy54
+aSxILnVkKEMuZGssSC51ZChDLndiKEMuTzQpLG4pKSkpKSkpCmlmKHR5cGVvZiBkYXJ0TmF0aXZlRGlz
+cGF0Y2hIb29rc1RyYW5zZm9ybWVyIT0idW5kZWZpbmVkIil7dD1kYXJ0TmF0aXZlRGlzcGF0Y2hIb29r
+c1RyYW5zZm9ybWVyCmlmKHR5cGVvZiB0PT0iZnVuY3Rpb24iKXQ9W3RdCmlmKHQuY29uc3RydWN0b3I9
+PUFycmF5KWZvcihzPTA7czx0Lmxlbmd0aDsrK3Mpe3I9dFtzXQppZih0eXBlb2Ygcj09ImZ1bmN0aW9u
+IiluPXIobil8fG59fXE9bi5nZXRUYWcKcD1uLmdldFVua25vd25UYWcKbz1uLnByb3RvdHlwZUZvclRh
+ZwokLk5GPW5ldyBILmRDKHEpCiQuVFg9bmV3IEgud04ocCkKJC54Nz1uZXcgSC5WWChvKX0sCnVkOmZ1
+bmN0aW9uKGEsYil7cmV0dXJuIGEoYil8fGJ9LAp2NDpmdW5jdGlvbihhLGIsYyxkLGUsZil7dmFyIHQ9
+Yj8ibSI6IiIscz1jPyIiOiJpIixyPWQ/InUiOiIiLHE9ZT8icyI6IiIscD1mPyJnIjoiIixvPWZ1bmN0
+aW9uKGcsaCl7dHJ5e3JldHVybiBuZXcgUmVnRXhwKGcsaCl9Y2F0Y2gobil7cmV0dXJuIG59fShhLHQr
+cytyK3ErcCkKaWYobyBpbnN0YW5jZW9mIFJlZ0V4cClyZXR1cm4gbwp0aHJvdyBILmIoUC5ycigiSWxs
+ZWdhbCBSZWdFeHAgcGF0dGVybiAoIitTdHJpbmcobykrIikiLGEsbnVsbCkpfSwKbTI6ZnVuY3Rpb24o
+YSxiLGMpe3ZhciB0CmlmKHR5cGVvZiBiPT0ic3RyaW5nIilyZXR1cm4gYS5pbmRleE9mKGIsYyk+PTAK
+ZWxzZSBpZihiIGluc3RhbmNlb2YgSC5WUil7dD1DLnhCLkcoYSxjKQpyZXR1cm4gYi5iLnRlc3QodCl9
+ZWxzZXt0PUouRkwoYixDLnhCLkcoYSxjKSkKcmV0dXJuIXQuZ2wwKHQpfX0sCkE0OmZ1bmN0aW9uKGEp
+e2lmKGEuaW5kZXhPZigiJCIsMCk+PTApcmV0dXJuIGEucmVwbGFjZSgvXCQvZywiJCQkJCIpCnJldHVy
+biBhfSwKZUE6ZnVuY3Rpb24oYSl7aWYoL1tbXF17fSgpKis/LlxcXiR8XS8udGVzdChhKSlyZXR1cm4g
+YS5yZXBsYWNlKC9bW1xde30oKSorPy5cXF4kfF0vZywiXFwkJiIpCnJldHVybiBhfSwKeXM6ZnVuY3Rp
+b24oYSxiLGMpe3ZhciB0PUgubk0oYSxiLGMpCnJldHVybiB0fSwKbk06ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciB0LHMscixxCmlmKGI9PT0iIil7aWYoYT09PSIiKXJldHVybiBjCnQ9YS5sZW5ndGgKZm9yKHM9Yyxy
+PTA7cjx0OysrcilzPXMrYVtyXStjCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfXE9YS5pbmRl
+eE9mKGIsMCkKaWYocTwwKXJldHVybiBhCmlmKGEubGVuZ3RoPDUwMHx8Yy5pbmRleE9mKCIkIiwwKT49
+MClyZXR1cm4gYS5zcGxpdChiKS5qb2luKGMpCnJldHVybiBhLnJlcGxhY2UobmV3IFJlZ0V4cChILmVB
+KGIpLCdnJyksSC5BNChjKSl9LApQRDpmdW5jdGlvbiBQRChhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9
+LApXVTpmdW5jdGlvbiBXVSgpe30sCkxQOmZ1bmN0aW9uIExQKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5h
+PWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sCkxJOmZ1bmN0aW9uIExJKGEsYixjLGQsZSl7dmFyIF89dGhp
+cwpfLmE9YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLmY9ZX0sCkNqOmZ1bmN0aW9uIENqKGEsYixjKXt0aGlz
+LmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClpyOmZ1bmN0aW9uIFpyKGEsYixjLGQsZSxmKXt2YXIgXz10
+aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwKVzA6ZnVuY3Rpb24gVzAoYSxi
+KXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmF6OmZ1bmN0aW9uIGF6KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9
+Ygp0aGlzLmM9Y30sCnZWOmZ1bmN0aW9uIHZWKGEpe3RoaXMuYT1hfSwKYnE6ZnVuY3Rpb24gYnEoYSxi
+KXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkFtOmZ1bmN0aW9uIEFtKGEpe3RoaXMuYT1hfSwKWE86ZnVuY3Rp
+b24gWE8oYSl7dGhpcy5hPWEKdGhpcy5iPW51bGx9LApUcDpmdW5jdGlvbiBUcCgpe30sCmxjOmZ1bmN0
+aW9uIGxjKCl7fSwKeng6ZnVuY3Rpb24gengoKXt9LApyVDpmdW5jdGlvbiByVChhLGIsYyxkKXt2YXIg
+Xz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKRXE6ZnVuY3Rpb24gRXEoYSl7dGhpcy5hPWF9
+LAprWTpmdW5jdGlvbiBrWShhKXt0aGlzLmE9YX0sCk41OmZ1bmN0aW9uIE41KGEpe3ZhciBfPXRoaXMK
+Xy5hPTAKXy5mPV8uZT1fLmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LApkYjpmdW5jdGlvbiBk
+YihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKaTU6ZnVuY3Rpb24gaTUo
+YSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKTjY6ZnVuY3Rpb24gTjYoYSxiLGMpe3ZhciBfPXRoaXMK
+Xy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsCl8uJHRpPWN9LApkQzpmdW5jdGlvbiBkQyhhKXt0aGlzLmE9
+YX0sCndOOmZ1bmN0aW9uIHdOKGEpe3RoaXMuYT1hfSwKVlg6ZnVuY3Rpb24gVlgoYSl7dGhpcy5hPWF9
+LApWUjpmdW5jdGlvbiBWUihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwK
+RUs6ZnVuY3Rpb24gRUsoYSl7dGhpcy5iPWF9LApLVzpmdW5jdGlvbiBLVyhhLGIsYyl7dGhpcy5hPWEK
+dGhpcy5iPWIKdGhpcy5jPWN9LApQYjpmdW5jdGlvbiBQYihhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpf
+LmI9YgpfLmM9YwpfLmQ9bnVsbH0sCnRROmZ1bmN0aW9uIHRRKGEsYil7dGhpcy5hPWEKdGhpcy5jPWJ9
+LAp1bjpmdW5jdGlvbiB1bihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApTZDpmdW5j
+dGlvbiBTZChhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9bnVsbH0sClhGOmZ1
+bmN0aW9uKGEpe3JldHVybiBhfSwKRFE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBJbnQ4QXJyYXkoYSl9
+LApvZDpmdW5jdGlvbihhLGIsYyl7aWYoYT4+PjAhPT1hfHxhPj1jKXRocm93IEguYihILkhZKGIsYSkp
+fSwKck06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKCEoYT4+PjAhPT1hKSl0PWI+Pj4wIT09Ynx8YT5i
+fHxiPmMKZWxzZSB0PSEwCmlmKHQpdGhyb3cgSC5iKEguYXUoYSxiLGMpKQpyZXR1cm4gYn0sCkVUOmZ1
+bmN0aW9uIEVUKCl7fSwKYjA6ZnVuY3Rpb24gYjAoKXt9LApEZzpmdW5jdGlvbiBEZygpe30sClBnOmZ1
+bmN0aW9uIFBnKCl7fSwKeGo6ZnVuY3Rpb24geGooKXt9LApkRTpmdW5jdGlvbiBkRSgpe30sClpBOmZ1
+bmN0aW9uIFpBKCl7fSwKd2Y6ZnVuY3Rpb24gd2YoKXt9LApQcTpmdW5jdGlvbiBQcSgpe30sCmVFOmZ1
+bmN0aW9uIGVFKCl7fSwKVjY6ZnVuY3Rpb24gVjYoKXt9LApSRzpmdW5jdGlvbiBSRygpe30sClZQOmZ1
+bmN0aW9uIFZQKCl7fSwKV0I6ZnVuY3Rpb24gV0IoKXt9LApaRzpmdW5jdGlvbiBaRygpe30sCnhaOmZ1
+bmN0aW9uKGEsYil7dmFyIHQ9Yi5kCnJldHVybiB0PT1udWxsP2IuZD1ILkooYSwiYjgiLFtiLlFdKTp0
+fSwKUTE6ZnVuY3Rpb24oYSl7dmFyIHQ9YS56CmlmKHQ9PT02fHx0PT09N3x8dD09PTgpcmV0dXJuIEgu
+UTEoYS5RKQpyZXR1cm4gdD09PTExfHx0PT09MTJ9LAptRDpmdW5jdGlvbihhKXtyZXR1cm4gYS5kYn0s
+Ck4wOmZ1bmN0aW9uKGEpe3JldHVybiBILkUodi50eXBlVW5pdmVyc2UsYSl9LApKUzpmdW5jdGlvbihh
+KXt2YXIgdD1hLiRTCmlmKHQhPW51bGwpe2lmKHR5cGVvZiB0PT0ibnVtYmVyIilyZXR1cm4gSC5CcCh0
+KQpyZXR1cm4gYS4kUygpfXJldHVybn0sClVlOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoSC5RMShiKSlp
+ZihhIGluc3RhbmNlb2YgSC5UcCl7dD1ILkpTKGEpCmlmKHQhPW51bGwpcmV0dXJuIHR9cmV0dXJuIEgu
+eksoYSl9LAp6SzpmdW5jdGlvbihhKXt2YXIgdAppZihhIGluc3RhbmNlb2YgUC5rKXt0PWEuJHRpCnJl
+dHVybiB0IT1udWxsP3Q6SC5WVShhKX1pZihBcnJheS5pc0FycmF5KGEpKXJldHVybiBILnQ2KGEpCnJl
+dHVybiBILlZVKEouaWEoYSkpfSwKdDY6ZnVuY3Rpb24oYSl7dmFyIHQ9YS4kdGkscz11Lm0KaWYodD09
+bnVsbClyZXR1cm4gcwppZih0LmNvbnN0cnVjdG9yIT09cy5jb25zdHJ1Y3RvcilyZXR1cm4gcwpyZXR1
+cm4gdH0sCkxoOmZ1bmN0aW9uKGEpe3ZhciB0PWEuJHRpCnJldHVybiB0IT1udWxsP3Q6SC5WVShhKX0s
+ClZVOmZ1bmN0aW9uKGEpe3ZhciB0PWEuY29uc3RydWN0b3Iscz10LiRjY2FjaGUKaWYocyE9bnVsbCly
+ZXR1cm4gcwpyZXR1cm4gSC5yOShhLHQpfSwKcjk6ZnVuY3Rpb24oYSxiKXt2YXIgdD1hIGluc3RhbmNl
+b2YgSC5UcD9hLl9fcHJvdG9fXy5fX3Byb3RvX18uY29uc3RydWN0b3I6YixzPUguYWkodi50eXBlVW5p
+dmVyc2UsdC5uYW1lKQpiLiRjY2FjaGU9cwpyZXR1cm4gc30sCkJwOmZ1bmN0aW9uKGEpe3ZhciB0LHM9
+YSxyPXYudHlwZXMscT1yW3NdCmlmKHR5cGVvZiBxPT0ic3RyaW5nIil7dD1ILkUodi50eXBlVW5pdmVy
+c2UscSkKcltzXT10CnJldHVybiB0fXJldHVybiBxfSwKSko6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlz
+LHI9cy56LHE9SC5ZTwppZihILmNjKHMsITApKXtxPUguSXcKcy5iPXMuYT1ILmhufWVsc2UgaWYocj09
+PTkpe3Q9cy5kYgppZigiS04iPT09dClxPUgub2sKZWxzZSBpZigiQ1AiPT09dClxPUguS0gKZWxzZSBp
+ZigiRksiPT09dClxPUguS0gKZWxzZSBpZigicVUiPT09dClxPUguTU0KZWxzZSBpZigiYTIiPT09dClx
+PUgubAplbHNle3I9cy5RCmlmKHMuY2guZXZlcnkoSC5yTikpe3MueD0iJGkiK3IKcT1ILnQ0fX19cy5j
+PXEKcmV0dXJuIHMuYyhhKX0sCllPOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMKcmV0dXJuIEguV2Uodi50
+eXBlVW5pdmVyc2UsSC5VZShhLHQpLG51bGwsdCxudWxsLCEwKX0sCnQ0OmZ1bmN0aW9uKGEpe3ZhciB0
+PXRoaXMueAppZihhIGluc3RhbmNlb2YgUC5rKXJldHVybiEhYVt0XQpyZXR1cm4hIUouaWEoYSlbdF19
+LApPejpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJldHVybiBhCnQ9dGhpcwppZih0LmMoYSkp
+cmV0dXJuIGEKdGhyb3cgSC5iKEguUTUoSC5XSyhhLEguVWUoYSx0KSxILmRtKHQsbnVsbCkpKSl9LApB
+djpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJldHVybiBhCnQ9dGhpcwppZih0LmMoYSkpcmV0
+dXJuIGEKdGhyb3cgSC5iKEguWmMoSC5XSyhhLEguVWUoYSx0KSxILmRtKHQsbnVsbCkpKSl9LApEaDpm
+dW5jdGlvbihhLGIsYyxkKXt2YXIgdD1udWxsCmlmKEguV2Uodi50eXBlVW5pdmVyc2UsYSx0LGIsdCwh
+MCkpcmV0dXJuIGEKdGhyb3cgSC5iKEguWmMoIlRoZSB0eXBlIGFyZ3VtZW50ICciK0guZChILmRtKGEs
+dCkpKyInIGlzIG5vdCBhIHN1YnR5cGUgb2YgdGhlIHR5cGUgdmFyaWFibGUgYm91bmQgJyIrSC5kKEgu
+ZG0oYix0KSkrIicgb2YgdHlwZSB2YXJpYWJsZSAnIitjKyInIGluICciK0guZChkKSsiJy4iKSl9LApX
+SzpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9UC5wKGEpLHM9SC5kbShiPT1udWxsP0gueksoYSk6YixudWxs
+KQpyZXR1cm4gdCsiOiB0eXBlICciK0guZChzKSsiJyBpcyBub3QgYSBzdWJ0eXBlIG9mIHR5cGUgJyIr
+SC5kKGMpKyInIn0sClE1OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5oeigiQ2FzdEVycm9yOiAiK2Ep
+fSwKUHY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguaHooIkNhc3RFcnJvcjogIitILldLKGEsbnVs
+bCxiKSl9LApaYzpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguaU0oIlR5cGVFcnJvcjogIithKX0sCnE6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguaU0oIlR5cGVFcnJvcjogIitILldLKGEsbnVsbCxiKSl9
+LApJdzpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCmhuOmZ1bmN0aW9uKGEpe3JldHVybiBhfSwKbDpmdW5j
+dGlvbihhKXtyZXR1cm4hMD09PWF8fCExPT09YX0sCkU5OmZ1bmN0aW9uKGEpe2lmKCEwPT09YXx8ITE9
+PT1hKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEguUHYoYSwiYm9vbCIpKX0s
+CnhkOmZ1bmN0aW9uKGEpe2lmKCEwPT09YXx8ITE9PT1hKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJu
+IGEKdGhyb3cgSC5iKEgucShhLCJib29sIikpfSwKZGo6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJu
+dW1iZXIiKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEguUHYoYSwiZG91Ymxl
+IikpfSwKSWc6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKGE9PW51
+bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJkb3VibGUiKSl9LApvazpmdW5jdGlvbihhKXtyZXR1
+cm4gdHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEpPT09YX0sClNIOmZ1bmN0aW9uKGEpe2lm
+KHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihhKT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbCly
+ZXR1cm4gYQp0aHJvdyBILmIoSC5QdihhLCJpbnQiKSl9LApTYzpmdW5jdGlvbihhKXtpZih0eXBlb2Yg
+YT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEK
+dGhyb3cgSC5iKEgucShhLCJpbnQiKSl9LApLSDpmdW5jdGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJu
+dW1iZXIifSwKdVU6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKGE9
+PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEguUHYoYSwibnVtIikpfSwKRE46ZnVuY3Rpb24oYSl7aWYo
+dHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEgu
+cShhLCJudW0iKSl9LApNTTpmdW5jdGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJzdHJpbmcifSwKYzA6
+ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJu
+IGEKdGhyb3cgSC5iKEguUHYoYSwiU3RyaW5nIikpfSwKeTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09
+InN0cmluZyIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsIlN0cmlu
+ZyIpKX0sCmlvOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmZvcih0PSIiLHM9IiIscj0wO3I8YS5sZW5n
+dGg7KytyLHM9IiwgIil0Kz1DLnhCLmgocyxILmRtKGFbcl0sYikpCnJldHVybiB0fSwKYkk6ZnVuY3Rp
+b24oYTAsYTEsYTIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYyxiLGE9Iiwg
+IgppZihhMiE9bnVsbCl7dD1hMi5sZW5ndGgKaWYoYTE9PW51bGwpe2ExPUguVk0oW10sdS5zKQpzPW51
+bGx9ZWxzZSBzPWExLmxlbmd0aApyPWExLmxlbmd0aApmb3IocT10O3E+MDstLXEpQy5ObS5pKGExLCJU
+IisocitxKSkKZm9yKHA9IjwiLG89IiIscT0wO3E8dDsrK3Esbz1hKXtwKz1vCm49YTEubGVuZ3RoCm09
+bi0xLXEKaWYobTwwKXJldHVybiBILk9IKGExLG0pCnA9Qy54Qi5oKHAsYTFbbV0pCmw9YTJbcV0KaWYo
+IUguY2MobCwhMCkpcCs9Qy54Qi5oKCIgZXh0ZW5kcyAiLEguZG0obCxhMSkpfXArPSI+In1lbHNle3A9
+IiIKcz1udWxsfW49YTAuUQprPWEwLmNoCmo9ay5hCmk9ai5sZW5ndGgKaD1rLmIKZz1oLmxlbmd0aApm
+PWsuYwplPWYubGVuZ3RoCmQ9SC5kbShuLGExKQpmb3IoYz0iIixiPSIiLHE9MDtxPGk7KytxLGI9YSlj
+Kz1DLnhCLmgoYixILmRtKGpbcV0sYTEpKQppZihnPjApe2MrPWIrIlsiCmZvcihiPSIiLHE9MDtxPGc7
+KytxLGI9YSljKz1DLnhCLmgoYixILmRtKGhbcV0sYTEpKQpjKz0iXSJ9aWYoZT4wKXtjKz1iKyJ7Igpm
+b3IoYj0iIixxPTA7cTxlO3ErPTIsYj1hKWMrPUMueEIuaChiLEguZG0oZltxKzFdLGExKSkrIiAiK2Zb
+cV0KYys9In0ifWlmKHMhPW51bGwpYTEubGVuZ3RoPXMKcmV0dXJuIHArIigiK2MrIikgPT4gIitILmQo
+ZCl9LApkbTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9YS56CmlmKHA9PT01KXJldHVybiJlcmFz
+ZWQiCmlmKHA9PT0yKXJldHVybiJkeW5hbWljIgppZihwPT09MylyZXR1cm4idm9pZCIKaWYocD09PTEp
+cmV0dXJuIk5ldmVyIgppZihwPT09NClyZXR1cm4iYW55IgppZihwPT09NilyZXR1cm4gSC5kKEguZG0o
+YS5RLGIpKSsiKiIKaWYocD09PTcpcmV0dXJuIEguZChILmRtKGEuUSxiKSkrIj8iCmlmKHA9PT04KXJl
+dHVybiJGdXR1cmVPcjwiK0guZChILmRtKGEuUSxiKSkrIj4iCmlmKHA9PT05KXt0PUgubzMoYS5RKQpz
+PWEuY2gKcmV0dXJuIHMubGVuZ3RoIT09MD90KygiPCIrSC5pbyhzLGIpKyI+Iik6dH1pZihwPT09MTEp
+cmV0dXJuIEguYkkoYSxiLG51bGwpCmlmKHA9PT0xMilyZXR1cm4gSC5iSShhLlEsYixhLmNoKQppZihw
+PT09MTMpe3I9YS5RCnE9Yi5sZW5ndGgKcj1xLTEtcgppZihyPDB8fHI+PXEpcmV0dXJuIEguT0goYixy
+KQpyZXR1cm4gYltyXX1yZXR1cm4iPyJ9LApvMzpmdW5jdGlvbihhKXt2YXIgdCxzPUguSmcoYSkKaWYo
+cyE9bnVsbClyZXR1cm4gcwp0PSJtaW5pZmllZDoiK2EKcmV0dXJuIHR9LApRbzpmdW5jdGlvbihhLGIp
+e3ZhciB0PWEudFJbYl0KZm9yKDt0eXBlb2YgdD09InN0cmluZyI7KXQ9YS50Ult0XQpyZXR1cm4gdH0s
+CmFpOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvPWEuZVQsbj1vW2JdCmlmKG49PW51bGwpcmV0
+dXJuIEguRShhLGIpCmVsc2UgaWYodHlwZW9mIG49PSJudW1iZXIiKXt0PW4Kcz1ILm0oYSw1LCIjIikK
+cj1bXQpmb3IocT0wO3E8dDsrK3Epci5wdXNoKHMpCnA9SC5KKGEsYixyKQpvW2JdPXAKcmV0dXJuIHB9
+ZWxzZSByZXR1cm4gbn0sCnhiOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguSXgoYS50UixiKX0sCkZGOmZ1
+bmN0aW9uKGEsYil7cmV0dXJuIEguSXgoYS5lVCxiKX0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPWEu
+ZUMscj1zLmdldChiKQppZihyIT1udWxsKXJldHVybiByCnQ9SC56KGEsbnVsbCxiKQpzLnNldChiLHQp
+CnJldHVybiB0fSwKY0U6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscj1iLmN4CmlmKHI9PW51bGwpcj1i
+LmN4PW5ldyBNYXAoKQp0PXIuZ2V0KGMpCmlmKHQhPW51bGwpcmV0dXJuIHQKcz1ILnooYSxiLGMpCnIu
+c2V0KGMscykKcmV0dXJuIHN9LAp2NTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9Yi5jeQppZihx
+PT1udWxsKXE9Yi5jeT1uZXcgTWFwKCkKdD1jLmRiCnM9cS5nZXQodCkKaWYocyE9bnVsbClyZXR1cm4g
+cwpyPUguYShhLGIsYy56PT09MTA/Yy5jaDpbY10pCnEuc2V0KHQscikKcmV0dXJuIHJ9LAp6OmZ1bmN0
+aW9uKGEsYixjKXt2YXIgdD1ILmkoSC5vKGEsYixjKSkKcmV0dXJuIHR9LApXRzpmdW5jdGlvbihhLGIp
+e3ZhciB0PWIuZGIKYS5lQy5zZXQodCxiKQpiLmE9SC5PegpiLmI9SC5BdgpiLmM9SC5KSgpyZXR1cm4g
+Yn0sCm06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9YS5lQy5nZXQoYykKaWYocyE9bnVsbClyZXR1cm4g
+cwp0PW5ldyBILkpjKG51bGwsbnVsbCxudWxsKQp0Lno9Ygp0LmRiPWMKcmV0dXJuIEguV0coYSx0KX0s
+CnY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscz1hLmVDLmdldChkKQppZihzIT1udWxsKXJldHVybiBz
+CnQ9bmV3IEguSmMobnVsbCxudWxsLG51bGwpCnQuej1iCnQuUT1jCnQuZGI9ZApyZXR1cm4gSC5XRyhh
+LHQpfSwKSDpmdW5jdGlvbihhLGIpe3ZhciB0LHM9IiIrYisiXiIscj1hLmVDLmdldChzKQppZihyIT1u
+dWxsKXJldHVybiByCnQ9bmV3IEguSmMobnVsbCxudWxsLG51bGwpCnQuej0xMwp0LlE9Ygp0LmRiPXMK
+cmV0dXJuIEguV0coYSx0KX0sClV4OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPWEubGVuZ3RoCmZvcih0
+PSIiLHM9IiIscj0wO3I8cTsrK3Iscz0iLCIpdCs9cythW3JdLmRiCnJldHVybiB0fSwKUzQ6ZnVuY3Rp
+b24oYSl7dmFyIHQscyxyLHEscCxvPWEubGVuZ3RoCmZvcih0PSIiLHM9IiIscj0wO3I8bztyKz0yLHM9
+IiwiKXtxPWFbcl0KcD1hW3IrMV0uZGIKdCs9cytxKyI6IitwfXJldHVybiB0fSwKSjpmdW5jdGlvbihh
+LGIsYyl7dmFyIHQscyxyPWIKaWYoYy5sZW5ndGghPT0wKXIrPSI8IitILlV4KGMpKyI+Igp0PWEuZUMu
+Z2V0KHIpCmlmKHQhPW51bGwpcmV0dXJuIHQKcz1uZXcgSC5KYyhudWxsLG51bGwsbnVsbCkKcy56PTkK
+cy5RPWIKcy5jaD1jCmlmKGMubGVuZ3RoPjApcy5kPWNbMF0Kcy5kYj1yCnJldHVybiBILldHKGEscyl9
+LAphOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwCmlmKGIuej09PTEwKXt0PWIuUQpzPWIuY2gu
+Y29uY2F0KGMpfWVsc2V7cz1jCnQ9Yn1yPXQuZGIrIjsiKygiPCIrSC5VeChzKSsiPiIpCnE9YS5lQy5n
+ZXQocikKaWYocSE9bnVsbClyZXR1cm4gcQpwPW5ldyBILkpjKG51bGwsbnVsbCxudWxsKQpwLno9MTAK
+cC5RPXQKcC5jaD1zCnAuZGI9cgpyZXR1cm4gSC5XRyhhLHApfSwKQzpmdW5jdGlvbihhLGIsYyl7dmFy
+IHQscyxyLHE9Yi5kYixwPWMuYSxvPXAubGVuZ3RoLG49Yy5iLG09bi5sZW5ndGgsbD1jLmMsaz1sLmxl
+bmd0aCxqPSIoIitILlV4KHApCmlmKG0+MClqKz0obz4wPyIsIjoiIikrIlsiK0guVXgobikrIl0iCmlm
+KGs+MClqKz0obz4wPyIsIjoiIikrInsiK0guUzQobCkrIn0iCnQ9cSsoaisiKSIpCnM9YS5lQy5nZXQo
+dCkKaWYocyE9bnVsbClyZXR1cm4gcwpyPW5ldyBILkpjKG51bGwsbnVsbCxudWxsKQpyLno9MTEKci5R
+PWIKci5jaD1jCnIuZGI9dApyZXR1cm4gSC5XRyhhLHIpfSwKRDpmdW5jdGlvbihhLGIsYyl7dmFyIHQs
+cz1iLmRiKyI8IitILlV4KGMpKyI+IixyPWEuZUMuZ2V0KHMpCmlmKHIhPW51bGwpcmV0dXJuIHIKdD1u
+ZXcgSC5KYyhudWxsLG51bGwsbnVsbCkKdC56PTEyCnQuUT1iCnQuY2g9Ywp0LmRiPXMKcmV0dXJuIEgu
+V0coYSx0KX0sCm86ZnVuY3Rpb24oYSxiLGMpe3JldHVybnt1OmEsZTpiLHI6YyxzOltdLHA6MH19LApp
+OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGc9YS5yLGY9YS5zCmZvcih0
+PWcubGVuZ3RoLHM9MDtzPHQ7KXtyPWcuY2hhckNvZGVBdChzKQppZihyPj00OCYmcjw9NTcpcz1ILkEo
+cysxLHIsZyxmKQplbHNlIGlmKCgoKHJ8MzIpPj4+MCktOTcmNjU1MzUpPDI2fHxyPT09OTV8fHI9PT0z
+NilzPUgudChhLHMsZyxmLCExKQplbHNlIGlmKHI9PT00NilzPUgudChhLHMsZyxmLCEwKQplbHNleysr
+cwpzd2l0Y2gocil7Y2FzZSA0NDpicmVhawpjYXNlIDU4OmJyZWFrCmNhc2UgNTk6Zi5wdXNoKEguSyhh
+LnUsYS5lLGYucG9wKCkpKQpicmVhawpjYXNlIDk0OmYucHVzaChILkgoYS51LGYucG9wKCkpKQpicmVh
+awpjYXNlIDM1OmYucHVzaChILm0oYS51LDUsIiMiKSkKYnJlYWsKY2FzZSA2NDpmLnB1c2goSC5tKGEu
+dSwyLCJAIikpCmJyZWFrCmNhc2UgMTI2OmYucHVzaChILm0oYS51LDMsIn4iKSkKYnJlYWsKY2FzZSA2
+MDpmLnB1c2goYS5wKQphLnA9Zi5sZW5ndGgKYnJlYWsKY2FzZSA2MjpxPWEudQpwPWYuc3BsaWNlKGEu
+cCkKSC5yKGEudSxhLmUscCkKYS5wPWYucG9wKCkKbz1mLnBvcCgpCmlmKHR5cGVvZiBvPT0ic3RyaW5n
+IilmLnB1c2goSC5KKHEsbyxwKSkKZWxzZXtuPUguSyhxLGEuZSxvKQpzd2l0Y2gobi56KXtjYXNlIDEx
+OmYucHVzaChILkQocSxuLHApKQpicmVhawpkZWZhdWx0OmYucHVzaChILmEocSxuLHApKQpicmVha319
+YnJlYWsKY2FzZSAzODpILkkoYSxmKQpicmVhawpjYXNlIDQyOm09YS51Cmw9SC5LKG0sYS5lLGYucG9w
+KCkpCmYucHVzaChILnYobSw2LGwsbC5kYisiKiIpKQpicmVhawpjYXNlIDYzOm09YS51Cmw9SC5LKG0s
+YS5lLGYucG9wKCkpCmYucHVzaChILnYobSw3LGwsbC5kYisiPyIpKQpicmVhawpjYXNlIDQ3Om09YS51
+Cmw9SC5LKG0sYS5lLGYucG9wKCkpCmYucHVzaChILnYobSw4LGwsbC5kYisiLyIpKQpicmVhawpjYXNl
+IDQwOmYucHVzaChhLnApCmEucD1mLmxlbmd0aApicmVhawpjYXNlIDQxOnE9YS51Cms9bmV3IEguRygp
+Cmo9cS5zRUEKaT1xLnNFQQpvPWYucG9wKCkKaWYodHlwZW9mIG89PSJudW1iZXIiKXN3aXRjaChvKXtj
+YXNlLTE6aj1mLnBvcCgpCmJyZWFrCmNhc2UtMjppPWYucG9wKCkKYnJlYWsKZGVmYXVsdDpmLnB1c2go
+bykKYnJlYWt9ZWxzZSBmLnB1c2gobykKcD1mLnNwbGljZShhLnApCkgucihhLnUsYS5lLHApCmEucD1m
+LnBvcCgpCmsuYT1wCmsuYj1qCmsuYz1pCmYucHVzaChILkMocSxILksocSxhLmUsZi5wb3AoKSksaykp
+CmJyZWFrCmNhc2UgOTE6Zi5wdXNoKGEucCkKYS5wPWYubGVuZ3RoCmJyZWFrCmNhc2UgOTM6cD1mLnNw
+bGljZShhLnApCkgucihhLnUsYS5lLHApCmEucD1mLnBvcCgpCmYucHVzaChwKQpmLnB1c2goLTEpCmJy
+ZWFrCmNhc2UgMTIzOmYucHVzaChhLnApCmEucD1mLmxlbmd0aApicmVhawpjYXNlIDEyNTpwPWYuc3Bs
+aWNlKGEucCkKSC5CKGEudSxhLmUscCkKYS5wPWYucG9wKCkKZi5wdXNoKHApCmYucHVzaCgtMikKYnJl
+YWsKZGVmYXVsdDp0aHJvdyJCYWQgY2hhcmFjdGVyICIrcn19fWg9Zi5wb3AoKQpyZXR1cm4gSC5LKGEu
+dSxhLmUsaCl9LApBOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscj1iLTQ4CmZvcih0PWMubGVuZ3Ro
+O2E8dDsrK2Epe3M9Yy5jaGFyQ29kZUF0KGEpCmlmKCEocz49NDgmJnM8PTU3KSlicmVhawpyPXIqMTAr
+KHMtNDgpfWQucHVzaChyKQpyZXR1cm4gYX0sCnQ6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIs
+cSxwLG8sbj1iKzEKZm9yKHQ9Yy5sZW5ndGg7bjx0Oysrbil7cz1jLmNoYXJDb2RlQXQobikKaWYocz09
+PTQ2KXtpZihlKWJyZWFrCmU9ITB9ZWxzZXtpZighKCgoKHN8MzIpPj4+MCktOTcmNjU1MzUpPDI2fHxz
+PT09OTV8fHM9PT0zNikpcj1zPj00OCYmczw9NTcKZWxzZSByPSEwCmlmKCFyKWJyZWFrfX1xPWMuc3Vi
+c3RyaW5nKGIsbikKaWYoZSl7dD1hLnUKcD1hLmUKaWYocC56PT09MTApcD1wLlEKbz1ILlFvKHQscC5R
+KVtxXQppZihvPT1udWxsKUgudmgoJ05vICInK3ErJyIgaW4gIicrSC5tRChwKSsnIicpCmQucHVzaChI
+LmNFKHQscCxvKSl9ZWxzZSBkLnB1c2gocSkKcmV0dXJuIG59LApJOmZ1bmN0aW9uKGEsYil7dmFyIHQ9
+Yi5wb3AoKQppZigwPT09dCl7Yi5wdXNoKEgubShhLnUsMSwiMCYiKSkKcmV0dXJufWlmKDE9PT10KXti
+LnB1c2goSC5tKGEudSw0LCIxJiIpKQpyZXR1cm59dGhyb3cgSC5iKFAuaFYoIlVuZXhwZWN0ZWQgZXh0
+ZW5kZWQgb3BlcmF0aW9uICIrSC5kKHQpKSl9LApLOmZ1bmN0aW9uKGEsYixjKXtpZih0eXBlb2YgYz09
+InN0cmluZyIpcmV0dXJuIEguSihhLGMsYS5zRUEpCmVsc2UgaWYodHlwZW9mIGM9PSJudW1iZXIiKXJl
+dHVybiBILlRWKGEsYixjKQplbHNlIHJldHVybiBjfSwKcjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1j
+Lmxlbmd0aApmb3IodD0wO3Q8czsrK3QpY1t0XT1ILksoYSxiLGNbdF0pfSwKQjpmdW5jdGlvbihhLGIs
+Yyl7dmFyIHQscz1jLmxlbmd0aApmb3IodD0xO3Q8czt0Kz0yKWNbdF09SC5LKGEsYixjW3RdKX0sClRW
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9Yi56CmlmKHI9PT0xMCl7aWYoYz09PTApcmV0dXJuIGIu
+UQp0PWIuY2gKcz10Lmxlbmd0aAppZihjPD1zKXJldHVybiB0W2MtMV0KYy09cwpiPWIuUQpyPWIuen1l
+bHNlIGlmKGM9PT0wKXJldHVybiBiCmlmKHIhPT05KXRocm93IEguYihQLmhWKCJJbmRleGVkIGJhc2Ug
+bXVzdCBiZSBhbiBpbnRlcmZhY2UgdHlwZSIpKQp0PWIuY2gKaWYoYzw9dC5sZW5ndGgpcmV0dXJuIHRb
+Yy0xXQp0aHJvdyBILmIoUC5oVigiQmFkIGluZGV4ICIrYysiIGZvciAiK2IudygwKSkpfSwKV2U6ZnVu
+Y3Rpb24oYSxiLGMsZCxlLGYpe3ZhciB0LHMscixxLHAsbwppZihiPT09ZClyZXR1cm4hMAppZihILmNj
+KGQsITApKXJldHVybiEwCnQ9Yi56CmlmKHQ9PT00KXJldHVybiEwCmlmKEguY2MoYiwhMCkpcmV0dXJu
+ITEKaWYoYj09PXUuUClyZXR1cm4hMApzPXQ9PT0xMwppZihzKWlmKEguV2UoYSxjW2IuUV0sYyxkLGUs
+ITApKXJldHVybiEwCnI9ZC56CmlmKHQ9PT02KXJldHVybiBILldlKGEsYi5RLGMsZCxlLCEwKQppZihy
+PT09Nil7cT1kLlEKcmV0dXJuIEguV2UoYSxiLGMscSxlLCEwKX1pZih0PT09OCl7aWYoIUguV2UoYSxi
+LlEsYyxkLGUsITApKXJldHVybiExCnJldHVybiBILldlKGEsSC54WihhLGIpLGMsZCxlLCEwKX1pZih0
+PT09Nyl7cT1ILldlKGEsYi5RLGMsZCxlLCEwKQpyZXR1cm4gcX1pZihyPT09OCl7aWYoSC5XZShhLGIs
+YyxkLlEsZSwhMCkpcmV0dXJuITAKcmV0dXJuIEguV2UoYSxiLGMsSC54WihhLGQpLGUsITApfWlmKHI9
+PT03KXtxPUguV2UoYSxiLGMsZC5RLGUsITApCnJldHVybiBxfWlmKHMpcmV0dXJuITEKcT10IT09MTEK
+aWYoKCFxfHx0PT09MTIpJiZkPT09dS5aKXJldHVybiEwCmlmKHI9PT0xMil7aWYoYj09PXUuZylyZXR1
+cm4hMAppZih0IT09MTIpcmV0dXJuITEKcD1iLmNoCm89ZC5jaAppZighSC56dShwLG8sITApKXJldHVy
+biExCmM9Yz09bnVsbD9wOnAuY29uY2F0KGMpCmU9ZT09bnVsbD9vOm8uY29uY2F0KGUpCnJldHVybiBI
+LmJPKGEsYi5RLGMsZC5RLGUsITApfWlmKHI9PT0xMSl7aWYoYj09PXUuZylyZXR1cm4hMAppZihxKXJl
+dHVybiExCnJldHVybiBILmJPKGEsYixjLGQsZSwhMCl9aWYodD09PTkpe2lmKHIhPT05KXJldHVybiEx
+CnJldHVybiBILnBHKGEsYixjLGQsZSwhMCl9cmV0dXJuITF9LApiTzpmdW5jdGlvbihhMCxhMSxhMixh
+MyxhNCxhNSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYQppZighSC5X
+ZShhMCxhMS5RLGEyLGEzLlEsYTQsITApKXJldHVybiExCnQ9YTEuY2gKcz1hMy5jaApyPXQuYQpxPXMu
+YQpwPXIubGVuZ3RoCm89cS5sZW5ndGgKaWYocD5vKXJldHVybiExCm49by1wCm09dC5iCmw9cy5iCms9
+bS5sZW5ndGgKaj1sLmxlbmd0aAppZihwK2s8bytqKXJldHVybiExCmZvcihpPTA7aTxwOysraSl7aD1y
+W2ldCmlmKCFILldlKGEwLHFbaV0sYTQsaCxhMiwhMCkpcmV0dXJuITF9Zm9yKGk9MDtpPG47KytpKXto
+PW1baV0KaWYoIUguV2UoYTAscVtwK2ldLGE0LGgsYTIsITApKXJldHVybiExfWZvcihpPTA7aTxqOysr
+aSl7aD1tW24raV0KaWYoIUguV2UoYTAsbFtpXSxhNCxoLGEyLCEwKSlyZXR1cm4hMX1nPXQuYwpmPXMu
+YwplPWcubGVuZ3RoCmQ9Zi5sZW5ndGgKZm9yKGk9MCxjPTA7YzxkO2MrPTIpe2I9ZltjXQpkb3tpZihp
+Pj1lKXJldHVybiExCmE9Z1tpXQppKz0yfXdoaWxlKGE8YikKaWYoYjxhKXJldHVybiExCmg9Z1tpLTFd
+CmlmKCFILldlKGEwLGZbYysxXSxhNCxoLGEyLCEwKSlyZXR1cm4hMX1yZXR1cm4hMH0sCnBHOmZ1bmN0
+aW9uKGEsYixjLGQsZSxmKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9Yi5RLGs9ZC5RCmlmKGw9PT1rKXt0
+PWIuY2gKcz1kLmNoCnI9dC5sZW5ndGgKZm9yKHE9MDtxPHI7KytxKXtwPXRbcV0Kbz1zW3FdCmlmKCFI
+LldlKGEscCxjLG8sZSwhMCkpcmV0dXJuITF9cmV0dXJuITB9bj1ILlFvKGEsbCkKaWYobj09bnVsbCly
+ZXR1cm4hMQptPW5ba10KaWYobT09bnVsbClyZXR1cm4hMQpyPW0ubGVuZ3RoCnM9ZC5jaApmb3IocT0w
+O3E8cjsrK3EpaWYoIUguV2UoYSxILmNFKGEsYixtW3FdKSxjLHNbcV0sZSwhMCkpcmV0dXJuITEKcmV0
+dXJuITB9LApyYTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyCmlmKGE9PT1iKXJldHVybiEwCmlmKEgu
+Y2MoYSwhMCkpcmV0dXJuIEguY2MoYiwhMCkKdD1hLnoKaWYodCE9PWIueilyZXR1cm4hMQpzd2l0Y2go
+dCl7Y2FzZSA2OmNhc2UgNzpjYXNlIDg6cmV0dXJuIEgucmEoYS5RLGIuUSwhMCkKY2FzZSA5OmlmKGEu
+USE9PWIuUSlyZXR1cm4hMQpyZXR1cm4gSC56dShhLmNoLGIuY2gsITApCmNhc2UgMTA6cmV0dXJuIEgu
+cmEoYS5RLGIuUSwhMCkmJkguenUoYS5jaCxiLmNoLCEwKQpjYXNlIDExOmlmKEgucmEoYS5RLGIuUSwh
+MCkpe3M9YS5jaApyPWIuY2gKcz1ILnp1KHMuYSxyLmEsITApJiZILnp1KHMuYixyLmIsITApJiZILlhz
+KHMuYyxyLmMsITApfWVsc2Ugcz0hMQpyZXR1cm4gcwpjYXNlIDEyOnJldHVybiBILnJhKGEuUSxiLlEs
+ITApJiZILnp1KGEuY2gsYi5jaCwhMCkKZGVmYXVsdDpyZXR1cm4hMX19LAp6dTpmdW5jdGlvbihhLGIs
+Yyl7dmFyIHQscz1hLmxlbmd0aAppZihzIT09Yi5sZW5ndGgpcmV0dXJuITEKZm9yKHQ9MDt0PHM7Kyt0
+KWlmKCFILnJhKGFbdF0sYlt0XSwhMCkpcmV0dXJuITEKcmV0dXJuITB9LApYczpmdW5jdGlvbihhLGIs
+Yyl7dmFyIHQscyxyPWEubGVuZ3RoCmlmKHIhPT1iLmxlbmd0aClyZXR1cm4hMQpmb3IodD0wO3Q8cjt0
+Kz0yKXtpZihhW3RdIT09Ylt0XSlyZXR1cm4hMQpzPXQrMQppZighSC5yYShhW3NdLGJbc10sITApKXJl
+dHVybiExfXJldHVybiEwfSwKck46ZnVuY3Rpb24oYSl7cmV0dXJuIEguY2MoYSwhMCl9LApjYzpmdW5j
+dGlvbihhLGIpe3ZhciB0LHMKaWYoYT09PXUuSylyZXR1cm4hMAp0PWEuegppZih0IT09MilpZih0IT09
+MylpZih0IT09NClpZih0IT09NSlzPXQ9PT04JiZILmNjKGEuUSwhMCkKZWxzZSBzPSEwCmVsc2Ugcz0h
+MAplbHNlIHM9ITAKZWxzZSBzPSEwCnJldHVybiBzfSwKSXg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9
+T2JqZWN0LmtleXMoYikscT1yLmxlbmd0aApmb3IodD0wO3Q8cTsrK3Qpe3M9clt0XQphW3NdPWJbc119
+fSwKSmM6ZnVuY3Rpb24gSmMoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy55PV8u
+eD1fLmQ9bnVsbApfLno9MApfLmRiPV8uY3k9Xy5jeD1fLmNoPV8uUT1udWxsfSwKRzpmdW5jdGlvbiBH
+KCl7dGhpcy5jPXRoaXMuYj10aGlzLmE9bnVsbH0sCnU5OmZ1bmN0aW9uIHU5KCl7fSwKaHo6ZnVuY3Rp
+b24gaHooYSl7dGhpcy5hPWF9LAppTTpmdW5jdGlvbiBpTShhKXt0aGlzLmE9YX0sClI5OmZ1bmN0aW9u
+KGEpe3JldHVybiB1LmQuYyhhKXx8dS5CLmMoYSl8fHUuZHouYyhhKXx8dS5JLmMoYSl8fHUuQS5jKGEp
+fHx1Lmc0LmMoYSl8fHUuZzIuYyhhKX0sCkpnOmZ1bmN0aW9uKGEpe3JldHVybiB2Lm1hbmdsZWRHbG9i
+YWxOYW1lc1thXX19LEo9ewpRdTpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm57aTphLHA6YixlOmMseDpk
+fX0sCmtzOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXQpp
+ZihwPT1udWxsKWlmKCQuQnY9PW51bGwpe0guWEQoKQpwPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV19
+aWYocCE9bnVsbCl7dD1wLnAKaWYoITE9PT10KXJldHVybiBwLmkKaWYoITA9PT10KXJldHVybiBhCnM9
+T2JqZWN0LmdldFByb3RvdHlwZU9mKGEpCmlmKHQ9PT1zKXJldHVybiBwLmkKaWYocC5lPT09cyl0aHJv
+dyBILmIoUC5TWSgiUmV0dXJuIGludGVyY2VwdG9yIGZvciAiK0guZCh0KGEscCkpKSl9cj1hLmNvbnN0
+cnVjdG9yCnE9cj09bnVsbD9udWxsOnJbJC5VTigpXQppZihxIT1udWxsKXJldHVybiBxCnE9SC53Myhh
+KQppZihxIT1udWxsKXJldHVybiBxCmlmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBDLkRHCnQ9
+T2JqZWN0LmdldFByb3RvdHlwZU9mKGEpCmlmKHQ9PW51bGwpcmV0dXJuIEMuWlEKaWYodD09PU9iamVj
+dC5wcm90b3R5cGUpcmV0dXJuIEMuWlEKaWYodHlwZW9mIHI9PSJmdW5jdGlvbiIpe09iamVjdC5kZWZp
+bmVQcm9wZXJ0eShyLCQuVU4oKSx7dmFsdWU6Qy52QixlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRy
+dWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1cm4gQy52Qn1yZXR1cm4gQy52Qn0sClFpOmZ1bmN0aW9u
+KGEsYil7aWYoYTwwfHxhPjQyOTQ5NjcyOTUpdGhyb3cgSC5iKFAuVEUoYSwwLDQyOTQ5NjcyOTUsImxl
+bmd0aCIsbnVsbCkpCnJldHVybiBKLnB5KG5ldyBBcnJheShhKSxiKX0sCnB5OmZ1bmN0aW9uKGEsYil7
+cmV0dXJuIEouRXAoSC5WTShhLGIuQygiamQ8MD4iKSkpfSwKRXA6ZnVuY3Rpb24oYSl7YS5maXhlZCRs
+ZW5ndGg9QXJyYXkKcmV0dXJuIGF9LAp6QzpmdW5jdGlvbihhKXthLmZpeGVkJGxlbmd0aD1BcnJheQph
+LmltbXV0YWJsZSRsaXN0PUFycmF5CnJldHVybiBhfSwKR2E6ZnVuY3Rpb24oYSl7aWYoYTwyNTYpc3dp
+dGNoKGEpe2Nhc2UgOTpjYXNlIDEwOmNhc2UgMTE6Y2FzZSAxMjpjYXNlIDEzOmNhc2UgMzI6Y2FzZSAx
+MzM6Y2FzZSAxNjA6cmV0dXJuITAKZGVmYXVsdDpyZXR1cm4hMX1zd2l0Y2goYSl7Y2FzZSA1NzYwOmNh
+c2UgODE5MjpjYXNlIDgxOTM6Y2FzZSA4MTk0OmNhc2UgODE5NTpjYXNlIDgxOTY6Y2FzZSA4MTk3OmNh
+c2UgODE5ODpjYXNlIDgxOTk6Y2FzZSA4MjAwOmNhc2UgODIwMTpjYXNlIDgyMDI6Y2FzZSA4MjMyOmNh
+c2UgODIzMzpjYXNlIDgyMzk6Y2FzZSA4Mjg3OmNhc2UgMTIyODg6Y2FzZSA2NTI3OTpyZXR1cm4hMApk
+ZWZhdWx0OnJldHVybiExfX0sCm1tOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpmb3IodD1hLmxlbmd0aDti
+PHQ7KXtzPUMueEIuVyhhLGIpCmlmKHMhPT0zMiYmcyE9PTEzJiYhSi5HYShzKSlicmVhazsrK2J9cmV0
+dXJuIGJ9LApjMTpmdW5jdGlvbihhLGIpe3ZhciB0LHMKZm9yKDtiPjA7Yj10KXt0PWItMQpzPUMueEIu
+bShhLHQpCmlmKHMhPT0zMiYmcyE9PTEzJiYhSi5HYShzKSlicmVha31yZXR1cm4gYn0sClJFOmZ1bmN0
+aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIGEKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2Yg
+YT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9m
+IFAuaylyZXR1cm4gYQpyZXR1cm4gSi5rcyhhKX0sClRKOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0i
+bnVtYmVyIilyZXR1cm4gSi5xSS5wcm90b3R5cGUKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBK
+LkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBhCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJl
 dHVybiBKLmpkLnByb3RvdHlwZQppZih0eXBlb2YgYSE9Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVu
 Y3Rpb24iKXJldHVybiBKLmM1LnByb3RvdHlwZQpyZXR1cm4gYX1pZihhIGluc3RhbmNlb2YgUC5rKXJl
-dHVybiBhCnJldHVybiBKLmtzKGEpfSwKQ006ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouUkUoYSku
-ZHUoYSxiLGMsZCl9LApGTDpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZKGEpLmRkKGEsYil9LApHQTpm
-dW5jdGlvbihhLGIpe3JldHVybiBKLncxKGEpLkUoYSxiKX0sCkhtOmZ1bmN0aW9uKGEpe3JldHVybiBK
-LlU2KGEpLmdBKGEpfSwKSVQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEoudzEoYSkuZ2t6KGEpfSwKSnk6ZnVu
-Y3Rpb24oYSxiKXtyZXR1cm4gSi5pYShhKS5lNyhhLGIpfSwKS1Y6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
-Si5yWShhKS5HKGEsYil9LApMdDpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS53ZyhhKX0sCk0xOmZ1
-bmN0aW9uKGEsYixjKXtyZXR1cm4gSi53MShhKS5FMihhLGIsYyl9LApRejpmdW5jdGlvbihhLGIpe3Jl
-dHVybiBKLnJZKGEpLlcoYSxiKX0sClJNOmZ1bmN0aW9uKGEsYil7aWYoYT09bnVsbClyZXR1cm4gYj09
-bnVsbAppZih0eXBlb2YgYSE9Im9iamVjdCIpcmV0dXJuIGIhPW51bGwmJmE9PT1iCnJldHVybiBKLmlh
-KGEpLkROKGEsYil9LApUMDpmdW5jdGlvbihhKXtyZXR1cm4gSi5yWShhKS5iUyhhKX0sCmE2OmZ1bmN0
-aW9uKGEsYil7cmV0dXJuIEouclkoYSkubShhLGIpfSwKYlQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUo
-YSkuRDQoYSl9LApiYjpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmdHlwZW9mIGI9
-PSJudW1iZXIiKXJldHVybiBhK2IKcmV0dXJuIEouVEooYSkuaChhLGIpfSwKY0g6ZnVuY3Rpb24oYSl7
-cmV0dXJuIEouclkoYSkuaGMoYSl9LApkUjpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5nRChhKX0s
-CmRaOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBKLlJFKGEpLk9uKGEsYixjLGQpfSwKZGg6ZnVuY3Rp
-b24oYSl7cmV0dXJuIEouUkUoYSkudG4oYSl9LApoZjpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShhKS5n
-aU8oYSl9LAppZzpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5nUWcoYSl9LApqOmZ1bmN0aW9uKGEp
-e3JldHVybiBKLmlhKGEpLncoYSl9LApsNTpmdW5jdGlvbihhLGIpe3JldHVybiBKLlJFKGEpLnNoZihh
-LGIpfSwKbGQ6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLnJZKGEpLk5qKGEsYixjKX0sCnEwOmZ1bmN0
-aW9uKGEsYixjKXtyZXR1cm4gSi5yWShhKS5RaShhLGIsYyl9LApxRjpmdW5jdGlvbihhKXtyZXR1cm4g
-Si5SRShhKS5nVmwoYSl9LAp0SDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouUkUoYSkucGsoYSxiLGMp
-fSwKdzI6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYj09PSJudW1iZXIiKWlmKGEuY29uc3RydWN0b3I9
-PUFycmF5fHx0eXBlb2YgYT09InN0cmluZyJ8fEgud1YoYSxhW3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVd
-KSlpZihiPj4+MD09PWImJmI8YS5sZW5ndGgpcmV0dXJuIGFbYl0KcmV0dXJuIEouVTYoYSkucShhLGIp
-fSwKeVE6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouclkoYSkuaTcoYSxiLGMsZCl9LAp6bDpmdW5j
-dGlvbihhLGIpe3JldHVybiBKLlU2KGEpLnRnKGEsYil9LAp2QjpmdW5jdGlvbiB2Qigpe30sCnlFOmZ1
-bmN0aW9uIHlFKCl7fSwKWUU6ZnVuY3Rpb24gWUUoKXt9LApNRjpmdW5jdGlvbiBNRigpe30sCmlDOmZ1
-bmN0aW9uIGlDKCl7fSwKa2Q6ZnVuY3Rpb24ga2QoKXt9LApjNTpmdW5jdGlvbiBjNSgpe30sCmpkOmZ1
-bmN0aW9uIGpkKGEpe3RoaXMuJHRpPWF9LApQbzpmdW5jdGlvbiBQbyhhKXt0aGlzLiR0aT1hfSwKbTE6
-ZnVuY3Rpb24gbTEoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPTAKXy5kPW51bGwKXy4k
-dGk9Y30sCnFJOmZ1bmN0aW9uIHFJKCl7fSwKdXI6ZnVuY3Rpb24gdXIoKXt9LApWQTpmdW5jdGlvbiBW
-QSgpe30sCkRyOmZ1bmN0aW9uIERyKCl7fX0sUD17Ck9qOmZ1bmN0aW9uKCl7dmFyIHQscyxyPXt9Cmlm
-KHNlbGYuc2NoZWR1bGVJbW1lZGlhdGUhPW51bGwpcmV0dXJuIFAuRVgoKQppZihzZWxmLk11dGF0aW9u
-T2JzZXJ2ZXIhPW51bGwmJnNlbGYuZG9jdW1lbnQhPW51bGwpe3Q9c2VsZi5kb2N1bWVudC5jcmVhdGVF
-bGVtZW50KCJkaXYiKQpzPXNlbGYuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic3BhbiIpCnIuYT1udWxs
-Cm5ldyBzZWxmLk11dGF0aW9uT2JzZXJ2ZXIoSC50UihuZXcgUC50aChyKSwxKSkub2JzZXJ2ZSh0LHtj
-aGlsZExpc3Q6dHJ1ZX0pCnJldHVybiBuZXcgUC5oYShyLHQscyl9ZWxzZSBpZihzZWxmLnNldEltbWVk
-aWF0ZSE9bnVsbClyZXR1cm4gUC55dCgpCnJldHVybiBQLnFXKCl9LApaVjpmdW5jdGlvbihhKXtzZWxm
-LnNjaGVkdWxlSW1tZWRpYXRlKEgudFIobmV3IFAuVnModS5NLmIoYSkpLDApKX0sCm9BOmZ1bmN0aW9u
-KGEpe3NlbGYuc2V0SW1tZWRpYXRlKEgudFIobmV3IFAuRnQodS5NLmIoYSkpLDApKX0sCkJ6OmZ1bmN0
-aW9uKGEpe3UuTS5iKGEpClAuUU4oMCxhKX0sClFOOmZ1bmN0aW9uKGEsYil7dmFyIHQ9bmV3IFAuVzMo
-KQp0LkNZKGEsYikKcmV0dXJuIHR9LAprMzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgpiLmE9MQp0cnl7
-YS5TcShuZXcgUC5wVihiKSxuZXcgUC5VNyhiKSx1LlApfWNhdGNoKHIpe3Q9SC5SdShyKQpzPUgudHMo
-cikKUC5yYihuZXcgUC52cihiLHQscykpfX0sCkE5OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmZvcih0
-PXUuXztzPWEuYSxzPT09MjspYT10LmIoYS5jKQppZihzPj00KXtyPWIuYWgoKQpiLmE9YS5hCmIuYz1h
-LmMKUC5IWihiLHIpfWVsc2V7cj11LnguYihiLmMpCmIuYT0yCmIuYz1hCmEualEocil9fSwKSFo6ZnVu
-Y3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZT1udWxsLGQ9e30sYz1k
-LmE9YQpmb3IodD11Lm4scz11Lngscj11LmM7ITA7KXtxPXt9CnA9Yy5hPT09OAppZihiPT1udWxsKXtp
-ZihwKXtvPXQuYihjLmMpClAuTDIoZSxlLGMuYixvLmEsby5iKX1yZXR1cm59Zm9yKDtuPWIuYSxuIT1u
-dWxsO2I9bil7Yi5hPW51bGwKUC5IWihkLmEsYil9Yz1kLmEKbT1jLmMKcS5hPXAKcS5iPW0KbD0hcApp
-ZihsKXtrPWIuYwprPShrJjEpIT09MHx8KGsmMTUpPT09OH1lbHNlIGs9ITAKaWYoayl7az1iLmIKaj1r
-LmIKaWYocCl7aT1jLmI9PT1qCmk9IShpfHxpKX1lbHNlIGk9ITEKaWYoaSl7dC5iKG0pClAuTDIoZSxl
-LGMuYixtLmEsbS5iKQpyZXR1cm59aD0kLlgzCmlmKGghPT1qKSQuWDM9agplbHNlIGg9ZQpjPWIuYwpp
-ZigoYyYxNSk9PT04KW5ldyBQLlJUKGQscSxiLHApLiQwKCkKZWxzZSBpZihsKXtpZigoYyYxKSE9PTAp
-bmV3IFAucnEocSxiLG0pLiQwKCl9ZWxzZSBpZigoYyYyKSE9PTApbmV3IFAuUlcoZCxxLGIpLiQwKCkK
-aWYoaCE9bnVsbCkkLlgzPWgKYz1xLmIKaWYoci5jKGMpKXtpZihjLmE+PTQpe2c9cy5iKGsuYykKay5j
-PW51bGwKYj1rLk44KGcpCmsuYT1jLmEKay5jPWMuYwpkLmE9Ywpjb250aW51ZX1lbHNlIFAuQTkoYyxr
-KQpyZXR1cm59fWY9Yi5iCmc9cy5iKGYuYykKZi5jPW51bGwKYj1mLk44KGcpCmM9cS5hCmw9cS5iCmlm
-KCFjKXtmLiR0aS5kLmIobCkKZi5hPTQKZi5jPWx9ZWxzZXt0LmIobCkKZi5hPTgKZi5jPWx9ZC5hPWYK
-Yz1mfX0sClZIOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dS5XCmlmKHQuYyhhKSlyZXR1cm4gdC5iKGEpCnQ9
-dS55CmlmKHQuYyhhKSlyZXR1cm4gdC5iKGEpCnRocm93IEguYihQLkwzKGEsIm9uRXJyb3IiLCJFcnJv
-ciBoYW5kbGVyIG11c3QgYWNjZXB0IG9uZSBPYmplY3Qgb3Igb25lIE9iamVjdCBhbmQgYSBTdGFja1Ry
-YWNlIGFzIGFyZ3VtZW50cywgYW5kIHJldHVybiBhIGEgdmFsaWQgcmVzdWx0IikpfSwKcHU6ZnVuY3Rp
-b24oKXt2YXIgdCxzCmZvcig7dD0kLlM2LHQhPW51bGw7KXskLm1nPW51bGwKcz10LmIKJC5TNj1zCmlm
-KHM9PW51bGwpJC5rOD1udWxsCnQuYS4kMCgpfX0sCmVOOmZ1bmN0aW9uKCl7JC5VRD0hMAp0cnl7UC5w
-dSgpfWZpbmFsbHl7JC5tZz1udWxsCiQuVUQ9ITEKaWYoJC5TNiE9bnVsbCkkLnV0KCkuJDEoUC5VSSgp
-KX19LAplVzpmdW5jdGlvbihhKXt2YXIgdD1uZXcgUC5PTShhKQppZigkLlM2PT1udWxsKXskLlM2PSQu
-azg9dAppZighJC5VRCkkLnV0KCkuJDEoUC5VSSgpKX1lbHNlICQuazg9JC5rOC5iPXR9LApyUjpmdW5j
-dGlvbihhKXt2YXIgdCxzLHI9JC5TNgppZihyPT1udWxsKXtQLmVXKGEpCiQubWc9JC5rOApyZXR1cm59
-dD1uZXcgUC5PTShhKQpzPSQubWcKaWYocz09bnVsbCl7dC5iPXIKJC5TNj0kLm1nPXR9ZWxzZXt0LmI9
-cy5iCiQubWc9cy5iPXQKaWYodC5iPT1udWxsKSQuazg9dH19LApyYjpmdW5jdGlvbihhKXt2YXIgdD1u
-dWxsLHM9JC5YMwppZihDLk5VPT09cyl7UC5Uayh0LHQsQy5OVSxhKQpyZXR1cm59UC5Uayh0LHQscyx1
-Lk0uYihzLkdZKGEpKSl9LApMMjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0PXt9CnQuYT1kClAuclIo
-bmV3IFAucEsodCxlKSl9LApUODpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHM9JC5YMwppZihzPT09
-YylyZXR1cm4gZC4kMCgpCiQuWDM9Ywp0PXMKdHJ5e3M9ZC4kMCgpCnJldHVybiBzfWZpbmFsbHl7JC5Y
-Mz10fX0sCnl2OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciB0LHM9JC5YMwppZihzPT09YylyZXR1
-cm4gZC4kMShlKQokLlgzPWMKdD1zCnRyeXtzPWQuJDEoZSkKcmV0dXJuIHN9ZmluYWxseXskLlgzPXR9
-fSwKUXg6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyxoLGkpe3ZhciB0LHM9JC5YMwppZihzPT09YylyZXR1
-cm4gZC4kMihlLGYpCiQuWDM9Ywp0PXMKdHJ5e3M9ZC4kMihlLGYpCnJldHVybiBzfWZpbmFsbHl7JC5Y
-Mz10fX0sClRrOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0CnUuTS5iKGQpCnQ9Qy5OVSE9PWMKaWYodClk
-PSEoIXR8fCExKT9jLkdZKGQpOmMuUlQoZCx1LkgpClAuZVcoZCl9LAp0aDpmdW5jdGlvbiB0aChhKXt0
-aGlzLmE9YX0sCmhhOmZ1bmN0aW9uIGhhKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30s
-ClZzOmZ1bmN0aW9uIFZzKGEpe3RoaXMuYT1hfSwKRnQ6ZnVuY3Rpb24gRnQoYSl7dGhpcy5hPWF9LApX
-MzpmdW5jdGlvbiBXMygpe30sCnlIOmZ1bmN0aW9uIHlIKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApQ
-ZjpmdW5jdGlvbiBQZigpe30sClpmOmZ1bmN0aW9uIFpmKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0s
-CkZlOmZ1bmN0aW9uIEZlKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmE9bnVsbApfLmI9YQpfLmM9Ygpf
-LmQ9YwpfLmU9ZApfLiR0aT1lfSwKdnM6ZnVuY3Rpb24gdnMoYSxiKXt2YXIgXz10aGlzCl8uYT0wCl8u
-Yj1hCl8uYz1udWxsCl8uJHRpPWJ9LApkYTpmdW5jdGlvbiBkYShhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
-fSwKb1E6ZnVuY3Rpb24gb1EoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnBWOmZ1bmN0aW9uIHBWKGEp
-e3RoaXMuYT1hfSwKVTc6ZnVuY3Rpb24gVTcoYSl7dGhpcy5hPWF9LAp2cjpmdW5jdGlvbiB2cihhLGIs
-Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApySDpmdW5jdGlvbiBySChhLGIpe3RoaXMuYT1h
-CnRoaXMuYj1ifSwKS0Y6ZnVuY3Rpb24gS0YoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sClpMOmZ1bmN0
-aW9uIFpMKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClJUOmZ1bmN0aW9uIFJUKGEs
-YixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LApqWjpmdW5jdGlvbiBqWihh
-KXt0aGlzLmE9YX0sCnJxOmZ1bmN0aW9uIHJxKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9
-Y30sClJXOmZ1bmN0aW9uIFJXKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCk9NOmZ1
-bmN0aW9uIE9NKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxsfSwKcWg6ZnVuY3Rpb24gcWgoKXt9LApCNTpm
-dW5jdGlvbiBCNShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKUEk6ZnVuY3Rpb24gUEkoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCk1POmZ1bmN0aW9uIE1PKCl7fSwKa1Q6ZnVuY3Rpb24ga1QoKXt9LApDdzpm
-dW5jdGlvbiBDdyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKbTA6ZnVuY3Rpb24gbTAoKXt9LApwSzpm
-dW5jdGlvbiBwSyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSmk6ZnVuY3Rpb24gSmkoKXt9LApoajpm
-dW5jdGlvbiBoaihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApWcDpmdW5jdGlvbiBW
-cChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKT1I6ZnVuY3Rpb24gT1IoYSxiLGMpe3RoaXMuYT1hCnRo
-aXMuYj1iCnRoaXMuYz1jfSwKRUY6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBiLkMoIkA8MD4iKS5LcShj
-KS5DKCJGbzwxLDI+IikuYihILkI3KGEsbmV3IEguTjUoYi5DKCJAPDA+IikuS3EoYykuQygiTjU8MSwy
-PiIpKSkpfSwKRmw6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguTjUoYS5DKCJAPDA+IikuS3EoYiku
-QygiTjU8MSwyPiIpKX0sCkxzOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5iNihhLkMoImI2PDA+Iikp
-fSwKVDI6ZnVuY3Rpb24oKXt2YXIgdD1PYmplY3QuY3JlYXRlKG51bGwpCnRbIjxub24taWRlbnRpZmll
-ci1rZXk+Il09dApkZWxldGUgdFsiPG5vbi1pZGVudGlmaWVyLWtleT4iXQpyZXR1cm4gdH0sCnJqOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdD1uZXcgUC5sbShhLGIsYy5DKCJsbTwwPiIpKQp0LmM9YS5lCnJldHVy
-biB0fSwKRVA6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoUC5oQihhKSl7aWYoYj09PSIoIiYmYz09
-PSIpIilyZXR1cm4iKC4uLikiCnJldHVybiBiKyIuLi4iK2N9dD1ILlZNKFtdLHUucykKQy5ObS5pKCQu
-eGcsYSkKdHJ5e1AuVnIoYSx0KX1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3RoKXJldHVybiBILk9IKCQu
-eGcsLTEpCiQueGcucG9wKCl9cz1QLnZnKGIsdS5SLmIodCksIiwgIikrYwpyZXR1cm4gcy5jaGFyQ29k
-ZUF0KDApPT0wP3M6c30sCldFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzCmlmKFAuaEIoYSkpcmV0dXJu
-IGIrIi4uLiIrYwp0PW5ldyBQLlJuKGIpCkMuTm0uaSgkLnhnLGEpCnRyeXtzPXQKcy5hPVAudmcocy5h
-LGEsIiwgIil9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5PSCgkLnhnLC0xKQokLnhn
-LnBvcCgpfXQuYSs9YwpzPXQuYQpyZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c30sCmhCOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMKZm9yKHQ9JC54Zy5sZW5ndGgscz0wO3M8dDsrK3MpaWYoYT09PSQueGdbc10p
-cmV0dXJuITAKcmV0dXJuITF9LApWcjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG09YS5n
-a3ooYSksbD0wLGs9MAp3aGlsZSghMCl7aWYoIShsPDgwfHxrPDMpKWJyZWFrCmlmKCFtLkYoKSlyZXR1
-cm4KdD1ILmQobS5nbCgpKQpDLk5tLmkoYix0KQpsKz10Lmxlbmd0aCsyOysra31pZighbS5GKCkpe2lm
-KGs8PTUpcmV0dXJuCmlmKDA+PWIubGVuZ3RoKXJldHVybiBILk9IKGIsLTEpCnM9Yi5wb3AoKQppZigw
-Pj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpyPWIucG9wKCl9ZWxzZXtxPW0uZ2woKTsrK2sKaWYo
-IW0uRigpKXtpZihrPD00KXtDLk5tLmkoYixILmQocSkpCnJldHVybn1zPUguZChxKQppZigwPj1iLmxl
-bmd0aClyZXR1cm4gSC5PSChiLC0xKQpyPWIucG9wKCkKbCs9cy5sZW5ndGgrMn1lbHNle3A9bS5nbCgp
-Oysrawpmb3IoO20uRigpO3E9cCxwPW8pe289bS5nbCgpOysrawppZihrPjEwMCl7d2hpbGUoITApe2lm
-KCEobD43NSYmaz4zKSlicmVhawppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpsLT1iLnBv
-cCgpLmxlbmd0aCsyOy0ta31DLk5tLmkoYiwiLi4uIikKcmV0dXJufX1yPUguZChxKQpzPUguZChwKQps
-Kz1zLmxlbmd0aCtyLmxlbmd0aCs0fX1pZihrPmIubGVuZ3RoKzIpe2wrPTUKbj0iLi4uIn1lbHNlIG49
-bnVsbAp3aGlsZSghMCl7aWYoIShsPjgwJiZiLmxlbmd0aD4zKSlicmVhawppZigwPj1iLmxlbmd0aCly
-ZXR1cm4gSC5PSChiLC0xKQpsLT1iLnBvcCgpLmxlbmd0aCsyCmlmKG49PW51bGwpe2wrPTUKbj0iLi4u
-In19aWYobiE9bnVsbClDLk5tLmkoYixuKQpDLk5tLmkoYixyKQpDLk5tLmkoYixzKX0sCnRNOmZ1bmN0
-aW9uKGEsYil7dmFyIHQscyxyPVAuTHMoYikKZm9yKHQ9YS5sZW5ndGgscz0wO3M8YS5sZW5ndGg7YS5s
-ZW5ndGg9PT10fHwoMCxILmxrKShhKSwrK3Mpci5pKDAsYi5iKGFbc10pKQpyZXR1cm4gcn0sCm5POmZ1
-bmN0aW9uKGEpe3ZhciB0LHM9e30KaWYoUC5oQihhKSlyZXR1cm4iey4uLn0iCnQ9bmV3IFAuUm4oIiIp
-CnRyeXtDLk5tLmkoJC54ZyxhKQp0LmErPSJ7IgpzLmE9ITAKYS5LKDAsbmV3IFAucmEocyx0KSkKdC5h
-Kz0ifSJ9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5PSCgkLnhnLC0xKQokLnhnLnBv
-cCgpfXM9dC5hCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKYjY6ZnVuY3Rpb24gYjYoYSl7
-dmFyIF89dGhpcwpfLmE9MApfLmY9Xy5lPV8uZD1fLmM9Xy5iPW51bGwKXy5yPTAKXy4kdGk9YX0sCmJu
-OmZ1bmN0aW9uIGJuKGEpe3RoaXMuYT1hCnRoaXMuYz10aGlzLmI9bnVsbH0sCmxtOmZ1bmN0aW9uIGxt
-KGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbApfLiR0aT1jfSwKbVc6ZnVu
-Y3Rpb24gbVcoKXt9LApMVTpmdW5jdGlvbiBMVSgpe30sCmxEOmZ1bmN0aW9uIGxEKCl7fSwKaWw6ZnVu
-Y3Rpb24gaWwoKXt9LApyYTpmdW5jdGlvbiByYShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKWWs6ZnVu
-Y3Rpb24gWWsoKXt9LApLUDpmdW5jdGlvbiBLUCgpe30sClBuOmZ1bmN0aW9uIFBuKCl7fSwKR2o6ZnVu
-Y3Rpb24gR2ooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKbGY6ZnVuY3Rpb24gbGYoKXt9LApWajpm
-dW5jdGlvbiBWaigpe30sClh2OmZ1bmN0aW9uIFh2KCl7fSwKblk6ZnVuY3Rpb24gblkoKXt9LApXWTpm
-dW5jdGlvbiBXWSgpe30sClJVOmZ1bmN0aW9uIFJVKCl7fSwKQlM6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
-LHIscQppZih0eXBlb2YgYSE9InN0cmluZyIpdGhyb3cgSC5iKEgudEwoYSkpCnQ9bnVsbAp0cnl7dD1K
-U09OLnBhcnNlKGEpfWNhdGNoKHIpe3M9SC5SdShyKQpxPVAucnIoU3RyaW5nKHMpLG51bGwsbnVsbCkK
-dGhyb3cgSC5iKHEpfXE9UC5RZSh0KQpyZXR1cm4gcX0sClFlOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGE9
-PW51bGwpcmV0dXJuIG51bGwKaWYodHlwZW9mIGEhPSJvYmplY3QiKXJldHVybiBhCmlmKE9iamVjdC5n
-ZXRQcm90b3R5cGVPZihhKSE9PUFycmF5LnByb3RvdHlwZSlyZXR1cm4gbmV3IFAudXcoYSxPYmplY3Qu
-Y3JlYXRlKG51bGwpKQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KWFbdF09UC5RZShhW3RdKQpyZXR1cm4g
-YX0sCmt5OmZ1bmN0aW9uKGEsYixjLGQpe2lmKGIgaW5zdGFuY2VvZiBVaW50OEFycmF5KXJldHVybiBQ
-LlJQKCExLGIsYyxkKQpyZXR1cm4gbnVsbH0sClJQOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscj0k
-LnJmKCkKaWYocj09bnVsbClyZXR1cm4gbnVsbAp0PTA9PT1jCmlmKHQmJiEwKXJldHVybiBQLk9RKHIs
-YikKcz1iLmxlbmd0aApkPVAuakIoYyxkLHMpCmlmKHQmJmQ9PT1zKXJldHVybiBQLk9RKHIsYikKcmV0
-dXJuIFAuT1EocixiLnN1YmFycmF5KGMsZCkpfSwKT1E6ZnVuY3Rpb24oYSxiKXtpZihQLkJlKGIpKXJl
-dHVybiBudWxsCnJldHVybiBQLkpoKGEsYil9LApKaDpmdW5jdGlvbihhLGIpe3ZhciB0LHMKdHJ5e3Q9
-YS5kZWNvZGUoYikKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShzKX1yZXR1cm4gbnVsbH0sCkJlOmZ1bmN0
-aW9uKGEpe3ZhciB0LHM9YS5sZW5ndGgtMgpmb3IodD0wO3Q8czsrK3QpaWYoYVt0XT09PTIzNylpZigo
-YVt0KzFdJjIyNCk9PT0xNjApcmV0dXJuITAKcmV0dXJuITF9LApXSTpmdW5jdGlvbigpe3ZhciB0LHMK
-dHJ5e3Q9bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIse2ZhdGFsOnRydWV9KQpyZXR1cm4gdH1jYXRjaChz
-KXtILlJ1KHMpfXJldHVybiBudWxsfSwKY1A6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscgpmb3IodD1K
-LlU2KGEpLHM9YjtzPGM7KytzKXtyPXQucShhLHMpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJu
-IHIuek0oKQppZigociYxMjcpIT09cilyZXR1cm4gcy1ifXJldHVybiBjLWJ9LAp4TTpmdW5jdGlvbihh
-LGIsYyxkLGUsZil7aWYoQy5qbi56WShmLDQpIT09MCl0aHJvdyBILmIoUC5ycigiSW52YWxpZCBiYXNl
-NjQgcGFkZGluZywgcGFkZGVkIGxlbmd0aCBtdXN0IGJlIG11bHRpcGxlIG9mIGZvdXIsIGlzICIrZixh
-LGMpKQppZihkK2UhPT1mKXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2NCBwYWRkaW5nLCAnPScg
-bm90IGF0IHRoZSBlbmQiLGEsYikpCmlmKGU+Mil0aHJvdyBILmIoUC5ycigiSW52YWxpZCBiYXNlNjQg
-cGFkZGluZywgbW9yZSB0aGFuIHR3byAnPScgY2hhcmFjdGVycyIsYSxiKSl9LAp1dzpmdW5jdGlvbiB1
-dyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1udWxsfSwKaTg6ZnVuY3Rpb24gaTgoYSl7dGhp
-cy5hPWF9LApDVjpmdW5jdGlvbiBDVigpe30sClU4OmZ1bmN0aW9uIFU4KCl7fSwKVWs6ZnVuY3Rpb24g
-VWsoKXt9LAp3STpmdW5jdGlvbiB3SSgpe30sClppOmZ1bmN0aW9uIFppKCl7fSwKYnk6ZnVuY3Rpb24g
-YnkoKXt9LApNeDpmdW5jdGlvbiBNeChhKXt0aGlzLmE9YX0sCnU1OmZ1bmN0aW9uIHU1KCl7fSwKRTM6
-ZnVuY3Rpb24gRTMoKXt9LApSdzpmdW5jdGlvbiBSdyhhKXt0aGlzLmI9MAp0aGlzLmM9YX0sCkdZOmZ1
-bmN0aW9uIEdZKGEpe3RoaXMuYT1hfSwKYno6ZnVuY3Rpb24gYnooYSxiKXt2YXIgXz10aGlzCl8uYT1h
-Cl8uYj1iCl8uYz0hMApfLmY9Xy5lPV8uZD0wfSwKUUE6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUguSHAo
-YSxjKQppZih0IT1udWxsKXJldHVybiB0CmlmKGIhPW51bGwpcmV0dXJuIGIuJDEoYSkKdGhyb3cgSC5i
-KFAucnIoYSxudWxsLG51bGwpKX0sCkY6ZnVuY3Rpb24oYSl7aWYoYSBpbnN0YW5jZW9mIEguVHApcmV0
-dXJuIGEudygwKQpyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5kKEguTShhKSkrIicifSwKTzg6ZnVuY3Rp
-b24oYSxiLGMpe3ZhciB0LHM9Si5RaShhLGMpCmlmKGEhPT0wJiYhMClmb3IodD0wO3Q8cy5sZW5ndGg7
-Kyt0KUMuTm0uWShzLHQsYikKcmV0dXJuIHN9LApDSDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1ILlZN
-KFtdLGMuQygiamQ8MD4iKSkKZm9yKHQ9Si5JVChhKTt0LkYoKTspQy5ObS5pKHMsYy5iKHQuZ2woKSkp
-CmlmKGIpcmV0dXJuIHMKcmV0dXJuIGMuQygiek08MD4iKS5iKEouRXAocykpfSwKQUY6ZnVuY3Rpb24o
-YSxiKXtyZXR1cm4gYi5DKCJ6TTwwPiIpLmIoSi56QyhQLkNIKGEsITEsYikpKX0sCkhNOmZ1bmN0aW9u
-KGEsYixjKXt2YXIgdAppZihBcnJheS5pc0FycmF5KGEpKXt1LnQuYihhKQp0PWEubGVuZ3RoCmM9UC5q
-QihiLGMsdCkKcmV0dXJuIEguZVQoYj4wfHxjPHQ/Qy5ObS5hTShhLGIsYyk6YSl9aWYodS5ibS5jKGEp
-KXJldHVybiBILmZ3KGEsYixQLmpCKGIsYyxhLmxlbmd0aCkpCnJldHVybiBQLmJ3KGEsYixjKX0sCk9v
-OmZ1bmN0aW9uKGEpe3JldHVybiBILkx3KGEpfSwKYnc6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixx
-LHA9bnVsbAppZihiPDApdGhyb3cgSC5iKFAuVEUoYiwwLEouSG0oYSkscCxwKSkKdD1jPT1udWxsCmlm
-KCF0JiZjPGIpdGhyb3cgSC5iKFAuVEUoYyxiLEouSG0oYSkscCxwKSkKcz1KLklUKGEpCmZvcihyPTA7
-cjxiOysrcilpZighcy5GKCkpdGhyb3cgSC5iKFAuVEUoYiwwLHIscCxwKSkKcT1bXQppZih0KWZvcig7
-cy5GKCk7KXEucHVzaChzLmdsKCkpCmVsc2UgZm9yKHI9YjtyPGM7KytyKXtpZighcy5GKCkpdGhyb3cg
-SC5iKFAuVEUoYyxiLHIscCxwKSkKcS5wdXNoKHMuZ2woKSl9cmV0dXJuIEguZVQocSl9LApudTpmdW5j
-dGlvbihhKXtyZXR1cm4gbmV3IEguVlIoYSxILnY0KGEsITEsITAsITEsITEsITEpKX0sCnZnOmZ1bmN0
-aW9uKGEsYixjKXt2YXIgdD1KLklUKGIpCmlmKCF0LkYoKSlyZXR1cm4gYQppZihjLmxlbmd0aD09PTAp
-e2RvIGErPUguZCh0LmdsKCkpCndoaWxlKHQuRigpKX1lbHNle2ErPUguZCh0LmdsKCkpCmZvcig7dC5G
-KCk7KWE9YStjK0guZCh0LmdsKCkpfXJldHVybiBhfSwKbHI6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJu
-IG5ldyBQLm1wKGEsYixjLGQpfSwKdW86ZnVuY3Rpb24oKXt2YXIgdD1ILk0wKCkKaWYodCE9bnVsbCly
-ZXR1cm4gUC5oSyh0KQp0aHJvdyBILmIoUC5MNCgiJ1VyaS5iYXNlJyBpcyBub3Qgc3VwcG9ydGVkIikp
-fSwKZVA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscCxvLG49IjAxMjM0NTY3ODlBQkNERUYi
-CmlmKGM9PT1DLnhNKXt0PSQuejQoKS5iCmlmKHR5cGVvZiBiIT0ic3RyaW5nIilILnZoKEgudEwoYikp
-CnQ9dC50ZXN0KGIpfWVsc2UgdD0hMQppZih0KXJldHVybiBiCkguTGgoYykuQygiVWsuUyIpLmIoYikK
-cz1jLmdaRSgpLldKKGIpCmZvcih0PXMubGVuZ3RoLHI9MCxxPSIiO3I8dDsrK3Ipe3A9c1tyXQppZihw
-PDEyOCl7bz1wPj4+NAppZihvPj04KXJldHVybiBILk9IKGEsbykKbz0oYVtvXSYxPDwocCYxNSkpIT09
-MH1lbHNlIG89ITEKaWYobylxKz1ILkx3KHApCmVsc2UgcT1kJiZwPT09MzI/cSsiKyI6cSsiJSIrbltw
-Pj4+NCYxNV0rbltwJjE1XX1yZXR1cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX0sCkdxOmZ1bmN0aW9u
-KGEpe3ZhciB0PU1hdGguYWJzKGEpLHM9YTwwPyItIjoiIgppZih0Pj0xMDAwKXJldHVybiIiK2EKaWYo
-dD49MTAwKXJldHVybiBzKyIwIit0CmlmKHQ+PTEwKXJldHVybiBzKyIwMCIrdApyZXR1cm4gcysiMDAw
-Iit0fSwKVng6ZnVuY3Rpb24oYSl7aWYoYT49MTAwKXJldHVybiIiK2EKaWYoYT49MTApcmV0dXJuIjAi
-K2EKcmV0dXJuIjAwIithfSwKaDA6ZnVuY3Rpb24oYSl7aWYoYT49MTApcmV0dXJuIiIrYQpyZXR1cm4i
-MCIrYX0sCnA6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIifHxILmwoYSl8fG51bGw9PWEp
-cmV0dXJuIEouaihhKQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEpTT04uc3RyaW5naWZ5KGEp
-CnJldHVybiBQLkYoYSl9LApoVjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQzYoYSl9LAp4WTpmdW5j
-dGlvbihhKXtyZXR1cm4gbmV3IFAudSghMSxudWxsLG51bGwsYSl9LApMMzpmdW5jdGlvbihhLGIsYyl7
-cmV0dXJuIG5ldyBQLnUoITAsYSxiLGMpfSwKeDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC5iSihu
-dWxsLG51bGwsITAsYSxiLCJWYWx1ZSBub3QgaW4gcmFuZ2UiKX0sClRFOmZ1bmN0aW9uKGEsYixjLGQs
-ZSl7cmV0dXJuIG5ldyBQLmJKKGIsYywhMCxhLGQsIkludmFsaWQgdmFsdWUiKX0sCndBOmZ1bmN0aW9u
-KGEsYixjLGQpe2lmKGE8Ynx8YT5jKXRocm93IEguYihQLlRFKGEsYixjLGQsbnVsbCkpfSwKakI6ZnVu
-Y3Rpb24oYSxiLGMpe2lmKDA+YXx8YT5jKXRocm93IEguYihQLlRFKGEsMCxjLCJzdGFydCIsbnVsbCkp
-CmlmKGIhPW51bGwpe2lmKGE+Ynx8Yj5jKXRocm93IEguYihQLlRFKGIsYSxjLCJlbmQiLG51bGwpKQpy
-ZXR1cm4gYn1yZXR1cm4gY30sCmsxOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGEhPT0ibnVtYmVyIily
-ZXR1cm4gYS5KKCkKaWYoYTwwKXRocm93IEguYihQLlRFKGEsMCxudWxsLGIsbnVsbCkpfSwKQ2Y6ZnVu
-Y3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1ILlNjKGU9PW51bGw/Si5IbShiKTplKQpyZXR1cm4gbmV3IFAu
-ZVkodCwhMCxhLGMsIkluZGV4IG91dCBvZiByYW5nZSIpfSwKTDQ6ZnVuY3Rpb24oYSl7cmV0dXJuIG5l
-dyBQLnViKGEpfSwKU1k6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmRzKGEpfSwKUFY6ZnVuY3Rpb24o
-YSl7cmV0dXJuIG5ldyBQLmxqKGEpfSwKYTQ6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLlVWKGEpfSwK
-cnI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBuZXcgUC5hRShhLGIsYyl9LApkSDpmdW5jdGlvbihhLGIs
-YyxkKXt2YXIgdCxzPUguVk0oW10sZC5DKCJqZDwwPiIpKQpDLk5tLnNBKHMsYSkKZm9yKHQ9MDt0PGE7
-Kyt0KUMuTm0uWShzLHQsYi4kMSh0KSkKcmV0dXJuIHN9LApoSzpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
-cSxwLG8sbixtLGwsayxqLGksaCxnLGYsZT1udWxsLGQ9YS5sZW5ndGgKaWYoZD49NSl7dD0oKEouUXoo
-YSw0KV41OCkqM3xDLnhCLlcoYSwwKV4xMDB8Qy54Qi5XKGEsMSleOTd8Qy54Qi5XKGEsMileMTE2fEMu
-eEIuVyhhLDMpXjk3KT4+PjAKaWYodD09PTApcmV0dXJuIFAuS0QoZDxkP0MueEIuTmooYSwwLGQpOmEs
-NSxlKS5nbFIoKQplbHNlIGlmKHQ9PT0zMilyZXR1cm4gUC5LRChDLnhCLk5qKGEsNSxkKSwwLGUpLmds
-UigpfXM9bmV3IEFycmF5KDgpCnMuZml4ZWQkbGVuZ3RoPUFycmF5CnI9SC5WTShzLHUudCkKQy5ObS5Z
-KHIsMCwwKQpDLk5tLlkociwxLC0xKQpDLk5tLlkociwyLC0xKQpDLk5tLlkociw3LC0xKQpDLk5tLlko
-ciwzLDApCkMuTm0uWShyLDQsMCkKQy5ObS5ZKHIsNSxkKQpDLk5tLlkociw2LGQpCmlmKFAuVUIoYSww
-LGQsMCxyKT49MTQpQy5ObS5ZKHIsNyxkKQpxPXJbMV0KaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1
-cm4gcS50QigpCmlmKHE+PTApaWYoUC5VQihhLDAscSwyMCxyKT09PTIwKXJbN109cQpzPXJbMl0KaWYo
-dHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5oKCkKcD1zKzEKbz1yWzNdCm49cls0XQptPXJbNV0K
-bD1yWzZdCmlmKHR5cGVvZiBsIT09Im51bWJlciIpcmV0dXJuIGwuSigpCmlmKHR5cGVvZiBtIT09Im51
-bWJlciIpcmV0dXJuIEgucFkobSkKaWYobDxtKW09bAppZih0eXBlb2YgbiE9PSJudW1iZXIiKXJldHVy
-biBuLkooKQppZihuPHApbj1tCmVsc2UgaWYobjw9cSluPXErMQppZih0eXBlb2YgbyE9PSJudW1iZXIi
-KXJldHVybiBvLkooKQppZihvPHApbz1uCnM9cls3XQppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVy
-biBzLkooKQprPXM8MAppZihrKWlmKHA+cSszKXtqPWUKaz0hMX1lbHNle3M9bz4wCmlmKHMmJm8rMT09
-PW4pe2o9ZQprPSExfWVsc2V7aWYoIShtPGQmJm09PT1uKzImJkoucTAoYSwiLi4iLG4pKSlpPW0+bisy
-JiZKLnEwKGEsIi8uLiIsbS0zKQplbHNlIGk9ITAKaWYoaSl7aj1lCms9ITF9ZWxzZXtpZihxPT09NClp
-ZihKLnEwKGEsImZpbGUiLDApKXtpZihwPD0wKXtpZighQy54Qi5RaShhLCIvIixuKSl7aD0iZmlsZTov
-Ly8iCnQ9M31lbHNle2g9ImZpbGU6Ly8iCnQ9Mn1hPWgrQy54Qi5OaihhLG4sZCkKcS09MApzPXQtMApt
-Kz1zCmwrPXMKZD1hLmxlbmd0aApwPTcKbz03Cm49N31lbHNlIGlmKG49PT1tKXtnPW0rMTsrK2wKYT1D
-LnhCLmk3KGEsbixtLCIvIik7KytkCm09Z31qPSJmaWxlIn1lbHNlIGlmKEMueEIuUWkoYSwiaHR0cCIs
-MCkpe2lmKHMmJm8rMz09PW4mJkMueEIuUWkoYSwiODAiLG8rMSkpe2Y9bi0zCm0tPTMKbC09MwphPUMu
-eEIuaTcoYSxvLG4sIiIpCmQtPTMKbj1mfWo9Imh0dHAifWVsc2Ugaj1lCmVsc2UgaWYocT09PTUmJkou
-cTAoYSwiaHR0cHMiLDApKXtpZihzJiZvKzQ9PT1uJiZKLnEwKGEsIjQ0MyIsbysxKSl7Zj1uLTQKbS09
-NApsLT00CmE9Si55UShhLG8sbiwiIikKZC09MwpuPWZ9aj0iaHR0cHMifWVsc2Ugaj1lCms9ITB9fX1l
-bHNlIGo9ZQppZihrKXtzPWEubGVuZ3RoCmlmKGQ8cyl7YT1KLmxkKGEsMCxkKQpxLT0wCnAtPTAKby09
-MApuLT0wCm0tPTAKbC09MH1yZXR1cm4gbmV3IFAuVWYoYSxxLHAsbyxuLG0sbCxqKX1yZXR1cm4gUC5q
-dihhLDAsZCxxLHAsbyxuLG0sbCxqKX0sCk10OmZ1bmN0aW9uKGEpe0gueShhKQpyZXR1cm4gUC5rdShh
-LDAsYS5sZW5ndGgsQy54TSwhMSl9LApXWDpmdW5jdGlvbihhKXt2YXIgdD11Lk4KcmV0dXJuIEMuTm0u
-TjAoSC5WTShhLnNwbGl0KCImIiksdS5zKSxQLkZsKHQsdCksbmV3IFAubjEoQy54TSksdS5mKX0sCkho
-OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtPW51bGwsbD0iSVB2NCBhZGRyZXNzIHNo
-b3VsZCBjb250YWluIGV4YWN0bHkgNCBwYXJ0cyIsaz0iZWFjaCBwYXJ0IG11c3QgYmUgaW4gdGhlIHJh
-bmdlIDAuLjI1NSIsaj1uZXcgUC5jUyhhKSxpPW5ldyBVaW50OEFycmF5KDQpCmZvcih0PWkubGVuZ3Ro
-LHM9YixyPXMscT0wO3M8YzsrK3Mpe3A9Qy54Qi5tKGEscykKaWYocCE9PTQ2KXtpZigocF40OCk+OSlq
-LiQyKCJpbnZhbGlkIGNoYXJhY3RlciIscyl9ZWxzZXtpZihxPT09MylqLiQyKGwscykKbz1QLlFBKEMu
-eEIuTmooYSxyLHMpLG0sbSkKaWYodHlwZW9mIG8hPT0ibnVtYmVyIilyZXR1cm4gby5vcygpCmlmKG8+
-MjU1KWouJDIoayxyKQpuPXErMQppZihxPj10KXJldHVybiBILk9IKGkscSkKaVtxXT1vCnI9cysxCnE9
-bn19aWYocSE9PTMpai4kMihsLGMpCm89UC5RQShDLnhCLk5qKGEscixjKSxtLG0pCmlmKHR5cGVvZiBv
-IT09Im51bWJlciIpcmV0dXJuIG8ub3MoKQppZihvPjI1NSlqLiQyKGsscikKaWYocT49dClyZXR1cm4g
-SC5PSChpLHEpCmlbcV09bwpyZXR1cm4gaX0sCmVnOmZ1bmN0aW9uKGEsYixhMCl7dmFyIHQscyxyLHEs
-cCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZD1uZXcgUC5WQyhhKSxjPW5ldyBQLnRwKGQsYSkKaWYoYS5s
-ZW5ndGg8MilkLiQxKCJhZGRyZXNzIGlzIHRvbyBzaG9ydCIpCnQ9SC5WTShbXSx1LnQpCmZvcihzPWIs
-cj1zLHE9ITEscD0hMTtzPGEwOysrcyl7bz1DLnhCLm0oYSxzKQppZihvPT09NTgpe2lmKHM9PT1iKXsr
-K3MKaWYoQy54Qi5tKGEscykhPT01OClkLiQyKCJpbnZhbGlkIHN0YXJ0IGNvbG9uLiIscykKcj1zfWlm
-KHM9PT1yKXtpZihxKWQuJDIoIm9ubHkgb25lIHdpbGRjYXJkIGA6OmAgaXMgYWxsb3dlZCIscykKQy5O
-bS5pKHQsLTEpCnE9ITB9ZWxzZSBDLk5tLmkodCxjLiQyKHIscykpCnI9cysxfWVsc2UgaWYobz09PTQ2
-KXA9ITB9aWYodC5sZW5ndGg9PT0wKWQuJDEoInRvbyBmZXcgcGFydHMiKQpuPXI9PT1hMAptPUMuTm0u
-Z3JaKHQpCmlmKG4mJm0hPT0tMSlkLiQyKCJleHBlY3RlZCBhIHBhcnQgYWZ0ZXIgbGFzdCBgOmAiLGEw
-KQppZighbilpZighcClDLk5tLmkodCxjLiQyKHIsYTApKQplbHNle2w9UC5IaChhLHIsYTApCkMuTm0u
-aSh0LChsWzBdPDw4fGxbMV0pPj4+MCkKQy5ObS5pKHQsKGxbMl08PDh8bFszXSk+Pj4wKX1pZihxKXtp
-Zih0Lmxlbmd0aD43KWQuJDEoImFuIGFkZHJlc3Mgd2l0aCBhIHdpbGRjYXJkIG11c3QgaGF2ZSBsZXNz
-IHRoYW4gNyBwYXJ0cyIpfWVsc2UgaWYodC5sZW5ndGghPT04KWQuJDEoImFuIGFkZHJlc3Mgd2l0aG91
-dCBhIHdpbGRjYXJkIG11c3QgY29udGFpbiBleGFjdGx5IDggcGFydHMiKQprPW5ldyBVaW50OEFycmF5
-KDE2KQpmb3IobT10Lmxlbmd0aCxqPWsubGVuZ3RoLGk9OS1tLHM9MCxoPTA7czxtOysrcyl7Zz10W3Nd
-CmlmKGc9PT0tMSlmb3IoZj0wO2Y8aTsrK2Ype2lmKGg8MHx8aD49ailyZXR1cm4gSC5PSChrLGgpCmtb
-aF09MAplPWgrMQppZihlPj1qKXJldHVybiBILk9IKGssZSkKa1tlXT0wCmgrPTJ9ZWxzZXtlPUMuam4u
-d0coZyw4KQppZihoPDB8fGg+PWopcmV0dXJuIEguT0goayxoKQprW2hdPWUKZT1oKzEKaWYoZT49aily
-ZXR1cm4gSC5PSChrLGUpCmtbZV09ZyYyNTUKaCs9Mn19cmV0dXJuIGt9LApqdjpmdW5jdGlvbihhLGIs
-YyxkLGUsZixnLGgsaSxqKXt2YXIgdCxzLHIscSxwLG8sbixtPW51bGwKaWYoaj09bnVsbClpZihkPmIp
-aj1QLlBpKGEsYixkKQplbHNle2lmKGQ9PT1iKVAuUjMoYSxiLCJJbnZhbGlkIGVtcHR5IHNjaGVtZSIp
-Cmo9IiJ9aWYoZT5iKXt0PWQrMwpzPXQ8ZT9QLnpSKGEsdCxlLTEpOiIiCnI9UC5PZShhLGUsZiwhMSkK
-aWYodHlwZW9mIGYhPT0ibnVtYmVyIilyZXR1cm4gZi5oKCkKcT1mKzEKaWYodHlwZW9mIGchPT0ibnVt
-YmVyIilyZXR1cm4gSC5wWShnKQpwPXE8Zz9QLndCKFAuUUEoSi5sZChhLHEsZyksbmV3IFAuZTEoYSxm
-KSxtKSxqKTptfWVsc2V7cD1tCnI9cApzPSIifW89UC5rYShhLGcsaCxtLGosciE9bnVsbCkKaWYodHlw
-ZW9mIGghPT0ibnVtYmVyIilyZXR1cm4gaC5KKCkKbj1oPGk/UC5sZShhLGgrMSxpLG0pOm0KcmV0dXJu
-IG5ldyBQLkRuKGoscyxyLHAsbyxuLGk8Yz9QLnRHKGEsaSsxLGMpOm0pfSwKd0s6ZnVuY3Rpb24oYSl7
-aWYoYT09PSJodHRwIilyZXR1cm4gODAKaWYoYT09PSJodHRwcyIpcmV0dXJuIDQ0MwpyZXR1cm4gMH0s
-ClIzOmZ1bmN0aW9uKGEsYixjKXt0aHJvdyBILmIoUC5ycihjLGEsYikpfSwKa0U6ZnVuY3Rpb24oYSxi
-KXtDLk5tLksoYSxuZXcgUC5OWSghMSkpfSwKSE46ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscgpmb3Io
-dD1ILnFDKGEsYyxudWxsLEgudDYoYSkuZCksdD1uZXcgSC5hNyh0LHQuZ0EodCksdC4kdGkuQygiYTc8
-YUwuRT4iKSk7dC5GKCk7KXtzPXQuZApyPVAubnUoJ1siKi86PD4/XFxcXHxdJykKcy50b1N0cmluZwpp
-ZihILm0yKHMsciwwKSl7dD1QLkw0KCJJbGxlZ2FsIGNoYXJhY3RlciBpbiBwYXRoOiAiK3MpCnRocm93
-IEguYih0KX19fSwKcmc6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZighKDY1PD1hJiZhPD05MCkpdD05Nzw9
-YSYmYTw9MTIyCmVsc2UgdD0hMAppZih0KXJldHVybgp0PVAuTDQoIklsbGVnYWwgZHJpdmUgbGV0dGVy
-ICIrUC5PbyhhKSkKdGhyb3cgSC5iKHQpfSwKd0I6ZnVuY3Rpb24oYSxiKXtpZihhIT1udWxsJiZhPT09
-UC53SyhiKSlyZXR1cm4gbnVsbApyZXR1cm4gYX0sCk9lOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMs
-cixxLHAsbwppZihhPT1udWxsKXJldHVybiBudWxsCmlmKGI9PT1jKXJldHVybiIiCmlmKEMueEIubShh
-LGIpPT09OTEpe2lmKHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIGMuSE4oKQp0PWMtMQppZihDLnhC
-Lm0oYSx0KSE9PTkzKVAuUjMoYSxiLCJNaXNzaW5nIGVuZCBgXWAgdG8gbWF0Y2ggYFtgIGluIGhvc3Qi
-KQpzPWIrMQpyPVAudG8oYSxzLHQpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJuIHIuSigpCmlm
-KHI8dCl7cT1yKzEKcD1QLk9BKGEsQy54Qi5RaShhLCIyNSIscSk/ciszOnEsdCwiJTI1Iil9ZWxzZSBw
-PSIiClAuZWcoYSxzLHIpCnJldHVybiBDLnhCLk5qKGEsYixyKS50b0xvd2VyQ2FzZSgpK3ArIl0ifWlm
-KHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIEgucFkoYykKbz1iCmZvcig7bzxjOysrbylpZihDLnhC
-Lm0oYSxvKT09PTU4KXtyPUMueEIuWFUoYSwiJSIsYikKaWYoIShyPj1iJiZyPGMpKXI9YwppZihyPGMp
-e3E9cisxCnA9UC5PQShhLEMueEIuUWkoYSwiMjUiLHEpP3IrMzpxLGMsIiUyNSIpfWVsc2UgcD0iIgpQ
-LmVnKGEsYixyKQpyZXR1cm4iWyIrQy54Qi5OaihhLGIscikrcCsiXSJ9cmV0dXJuIFAuT0woYSxiLGMp
-fSwKdG86ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Qy54Qi5YVShhLCIlIixiKQppZihzPj1iKXtpZih0
-eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9czxjfWVsc2UgdD0hMQpyZXR1cm4gdD9z
-OmN9LApPQTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsaz1kIT09IiI/bmV3
-IFAuUm4oZCk6bnVsbAppZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9YgpzPXQK
-cj0hMApmb3IoO3Q8Yzspe3E9Qy54Qi5tKGEsdCkKaWYocT09PTM3KXtwPVAucnYoYSx0LCEwKQpvPXA9
-PW51bGwKaWYobyYmcil7dCs9Mwpjb250aW51ZX1pZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCm49ay5h
-Kz1DLnhCLk5qKGEscyx0KQppZihvKXA9Qy54Qi5OaihhLHQsdCszKQplbHNlIGlmKHA9PT0iJSIpUC5S
-MyhhLHQsIlpvbmVJRCBzaG91bGQgbm90IGNvbnRhaW4gJSBhbnltb3JlIikKay5hPW4rcAp0Kz0zCnM9
-dApyPSEwfWVsc2V7aWYocTwxMjcpe289cT4+PjQKaWYobz49OClyZXR1cm4gSC5PSChDLkYzLG8pCm89
-KEMuRjNbb10mMTw8KHEmMTUpKSE9PTB9ZWxzZSBvPSExCmlmKG8pe2lmKHImJjY1PD1xJiY5MD49cSl7
-aWYoaz09bnVsbClrPW5ldyBQLlJuKCIiKQppZihzPHQpe2suYSs9Qy54Qi5OaihhLHMsdCkKcz10fXI9
-ITF9Kyt0fWVsc2V7aWYoKHEmNjQ1MTIpPT09NTUyOTYmJnQrMTxjKXttPUMueEIubShhLHQrMSkKaWYo
-KG0mNjQ1MTIpPT09NTYzMjApe3E9NjU1MzZ8KHEmMTAyMyk8PDEwfG0mMTAyMwpsPTJ9ZWxzZSBsPTF9
-ZWxzZSBsPTEKaWYoaz09bnVsbClrPW5ldyBQLlJuKCIiKQprLmErPUMueEIuTmooYSxzLHQpCmsuYSs9
-UC56WChxKQp0Kz1sCnM9dH19fWlmKGs9PW51bGwpcmV0dXJuIEMueEIuTmooYSxiLGMpCmlmKHM8Yylr
-LmErPUMueEIuTmooYSxzLGMpCm89ay5hCnJldHVybiBvLmNoYXJDb2RlQXQoMCk9PTA/bzpvfSwKT0w6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGoKaWYodHlwZW9mIGMhPT0ibnVt
-YmVyIilyZXR1cm4gSC5wWShjKQp0PWIKcz10CnI9bnVsbApxPSEwCmZvcig7dDxjOyl7cD1DLnhCLm0o
-YSx0KQppZihwPT09Mzcpe289UC5ydihhLHQsITApCm49bz09bnVsbAppZihuJiZxKXt0Kz0zCmNvbnRp
-bnVlfWlmKHI9PW51bGwpcj1uZXcgUC5SbigiIikKbT1DLnhCLk5qKGEscyx0KQpsPXIuYSs9IXE/bS50
-b0xvd2VyQ2FzZSgpOm0KaWYobil7bz1DLnhCLk5qKGEsdCx0KzMpCms9M31lbHNlIGlmKG89PT0iJSIp
-e289IiUyNSIKaz0xfWVsc2Ugaz0zCnIuYT1sK28KdCs9awpzPXQKcT0hMH1lbHNle2lmKHA8MTI3KXtu
-PXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goQy5lYSxuKQpuPShDLmVhW25dJjE8PChwJjE1KSkhPT0w
-fWVsc2Ugbj0hMQppZihuKXtpZihxJiY2NTw9cCYmOTA+PXApe2lmKHI9PW51bGwpcj1uZXcgUC5Sbigi
-IikKaWYoczx0KXtyLmErPUMueEIuTmooYSxzLHQpCnM9dH1xPSExfSsrdH1lbHNle2lmKHA8PTkzKXtu
-PXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goQy5hayxuKQpuPShDLmFrW25dJjE8PChwJjE1KSkhPT0w
-fWVsc2Ugbj0hMQppZihuKVAuUjMoYSx0LCJJbnZhbGlkIGNoYXJhY3RlciIpCmVsc2V7aWYoKHAmNjQ1
-MTIpPT09NTUyOTYmJnQrMTxjKXtqPUMueEIubShhLHQrMSkKaWYoKGomNjQ1MTIpPT09NTYzMjApe3A9
-NjU1MzZ8KHAmMTAyMyk8PDEwfGomMTAyMwprPTJ9ZWxzZSBrPTF9ZWxzZSBrPTEKaWYocj09bnVsbCly
-PW5ldyBQLlJuKCIiKQptPUMueEIuTmooYSxzLHQpCnIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm0Kci5h
-Kz1QLnpYKHApCnQrPWsKcz10fX19fWlmKHI9PW51bGwpcmV0dXJuIEMueEIuTmooYSxiLGMpCmlmKHM8
-Yyl7bT1DLnhCLk5qKGEscyxjKQpyLmErPSFxP20udG9Mb3dlckNhc2UoKTptfW49ci5hCnJldHVybiBu
-LmNoYXJDb2RlQXQoMCk9PTA/bjpufSwKUGk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmlmKGI9
-PT1jKXJldHVybiIiCmlmKCFQLkV0KEouclkoYSkuVyhhLGIpKSlQLlIzKGEsYiwiU2NoZW1lIG5vdCBz
-dGFydGluZyB3aXRoIGFscGhhYmV0aWMgY2hhcmFjdGVyIikKZm9yKHQ9YixzPSExO3Q8YzsrK3Qpe3I9
-Qy54Qi5XKGEsdCkKaWYocjwxMjgpe3E9cj4+PjQKaWYocT49OClyZXR1cm4gSC5PSChDLm1LLHEpCnE9
-KEMubUtbcV0mMTw8KHImMTUpKSE9PTB9ZWxzZSBxPSExCmlmKCFxKVAuUjMoYSx0LCJJbGxlZ2FsIHNj
-aGVtZSBjaGFyYWN0ZXIiKQppZig2NTw9ciYmcjw9OTApcz0hMH1hPUMueEIuTmooYSxiLGMpCnJldHVy
-biBQLllhKHM/YS50b0xvd2VyQ2FzZSgpOmEpfSwKWWE6ZnVuY3Rpb24oYSl7aWYoYT09PSJodHRwIily
-ZXR1cm4iaHR0cCIKaWYoYT09PSJmaWxlIilyZXR1cm4iZmlsZSIKaWYoYT09PSJodHRwcyIpcmV0dXJu
-Imh0dHBzIgppZihhPT09InBhY2thZ2UiKXJldHVybiJwYWNrYWdlIgpyZXR1cm4gYX0sCnpSOmZ1bmN0
-aW9uKGEsYixjKXtpZihhPT1udWxsKXJldHVybiIiCnJldHVybiBQLnVPKGEsYixjLEMudG8sITEpfSwK
-a2E6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3ZhciB0LHM9ZT09PSJmaWxlIixyPXN8fGYscT1hPT1udWxs
-CmlmKHEmJiEwKXJldHVybiBzPyIvIjoiIgp0PSFxP1AudU8oYSxiLGMsQy5XZCwhMCk6Qy5qTi5FMihk
-LG5ldyBQLlJaKCksdS5OKS5IKDAsIi8iKQppZih0Lmxlbmd0aD09PTApe2lmKHMpcmV0dXJuIi8ifWVs
-c2UgaWYociYmIUMueEIubih0LCIvIikpdD0iLyIrdApyZXR1cm4gUC5Kcih0LGUsZil9LApKcjpmdW5j
-dGlvbihhLGIsYyl7dmFyIHQ9Yi5sZW5ndGg9PT0wCmlmKHQmJiFjJiYhQy54Qi5uKGEsIi8iKSlyZXR1
-cm4gUC53RihhLCF0fHxjKQpyZXR1cm4gUC54ZShhKX0sCmxlOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0
-LHM9e30KaWYoYSE9bnVsbCl7aWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgiQm90aCBxdWVyeSBhbmQg
-cXVlcnlQYXJhbWV0ZXJzIHNwZWNpZmllZCIpKQpyZXR1cm4gUC51TyhhLGIsYyxDLlZDLCEwKX1pZihk
-PT1udWxsKXJldHVybiBudWxsCnQ9bmV3IFAuUm4oIiIpCnMuYT0iIgpkLksoMCxuZXcgUC55NShuZXcg
-UC5NRShzLHQpKSkKcz10LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LAp0RzpmdW5jdGlv
-bihhLGIsYyl7aWYoYT09bnVsbClyZXR1cm4gbnVsbApyZXR1cm4gUC51TyhhLGIsYyxDLlZDLCEwKX0s
-CnJ2OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG89YisyCmlmKG8+PWEubGVuZ3RoKXJldHVy
-biIlIgp0PUMueEIubShhLGIrMSkKcz1DLnhCLm0oYSxvKQpyPUgub28odCkKcT1ILm9vKHMpCmlmKHI8
-MHx8cTwwKXJldHVybiIlIgpwPXIqMTYrcQppZihwPDEyNyl7bz1DLmpuLndHKHAsNCkKaWYobz49OCly
-ZXR1cm4gSC5PSChDLkYzLG8pCm89KEMuRjNbb10mMTw8KHAmMTUpKSE9PTB9ZWxzZSBvPSExCmlmKG8p
-cmV0dXJuIEguTHcoYyYmNjU8PXAmJjkwPj1wPyhwfDMyKT4+PjA6cCkKaWYodD49OTd8fHM+PTk3KXJl
-dHVybiBDLnhCLk5qKGEsYixiKzMpLnRvVXBwZXJDYXNlKCkKcmV0dXJuIG51bGx9LAp6WDpmdW5jdGlv
-bihhKXt2YXIgdCxzLHIscSxwLG8sbj0iMDEyMzQ1Njc4OUFCQ0RFRiIKaWYoYTwxMjgpe3Q9bmV3IEFy
-cmF5KDMpCnQuZml4ZWQkbGVuZ3RoPUFycmF5CnM9SC5WTSh0LHUudCkKQy5ObS5ZKHMsMCwzNykKQy5O
-bS5ZKHMsMSxDLnhCLlcobixhPj4+NCkpCkMuTm0uWShzLDIsQy54Qi5XKG4sYSYxNSkpfWVsc2V7aWYo
-YT4yMDQ3KWlmKGE+NjU1MzUpe3I9MjQwCnE9NH1lbHNle3I9MjI0CnE9M31lbHNle3I9MTkyCnE9Mn10
-PW5ldyBBcnJheSgzKnEpCnQuZml4ZWQkbGVuZ3RoPUFycmF5CnM9SC5WTSh0LHUudCkKZm9yKHA9MDst
-LXEscT49MDtyPTEyOCl7bz1DLmpuLmJmKGEsNipxKSY2M3xyCkMuTm0uWShzLHAsMzcpCkMuTm0uWShz
-LHArMSxDLnhCLlcobixvPj4+NCkpCkMuTm0uWShzLHArMixDLnhCLlcobixvJjE1KSkKcCs9M319cmV0
-dXJuIFAuSE0ocywwLG51bGwpfSwKdU86ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1QLlVsKGEsYixj
-LGQsZSkKcmV0dXJuIHQ9PW51bGw/Qy54Qi5OaihhLGIsYyk6dH0sClVsOmZ1bmN0aW9uKGEsYixjLGQs
-ZSl7dmFyIHQscyxyLHEscCxvPW51bGwsbj0hZSxtPWIsbD1tLGs9bwp3aGlsZSghMCl7aWYodHlwZW9m
-IG0hPT0ibnVtYmVyIilyZXR1cm4gbS5KKCkKaWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5w
-WShjKQppZighKG08YykpYnJlYWsKYyQwOnt0PUMueEIubShhLG0pCmlmKHQ8MTI3KXtzPXQ+Pj40Cmlm
-KHM+PTgpcmV0dXJuIEguT0goZCxzKQpzPShkW3NdJjE8PCh0JjE1KSkhPT0wfWVsc2Ugcz0hMQppZihz
-KSsrbQplbHNle2lmKHQ9PT0zNyl7cj1QLnJ2KGEsbSwhMSkKaWYocj09bnVsbCl7bSs9MwpicmVhayBj
-JDB9aWYoIiUiPT09cil7cj0iJTI1IgpxPTF9ZWxzZSBxPTN9ZWxzZXtpZihuKWlmKHQ8PTkzKXtzPXQ+
-Pj40CmlmKHM+PTgpcmV0dXJuIEguT0goQy5hayxzKQpzPShDLmFrW3NdJjE8PCh0JjE1KSkhPT0wfWVs
-c2Ugcz0hMQplbHNlIHM9ITEKaWYocyl7UC5SMyhhLG0sIkludmFsaWQgY2hhcmFjdGVyIikKcT1vCnI9
-cX1lbHNle2lmKCh0JjY0NTEyKT09PTU1Mjk2KXtzPW0rMQppZihzPGMpe3A9Qy54Qi5tKGEscykKaWYo
-KHAmNjQ1MTIpPT09NTYzMjApe3Q9NjU1MzZ8KHQmMTAyMyk8PDEwfHAmMTAyMwpxPTJ9ZWxzZSBxPTF9
-ZWxzZSBxPTF9ZWxzZSBxPTEKcj1QLnpYKHQpfX1pZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCmsuYSs9
-Qy54Qi5OaihhLGwsbSkKay5hKz1ILmQocikKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gSC5w
-WShxKQptKz1xCmw9bX19fWlmKGs9PW51bGwpcmV0dXJuIG8KaWYodHlwZW9mIGwhPT0ibnVtYmVyIily
-ZXR1cm4gbC5KKCkKaWYobDxjKWsuYSs9Qy54Qi5OaihhLGwsYykKbj1rLmEKcmV0dXJuIG4uY2hhckNv
-ZGVBdCgwKT09MD9uOm59LAp5QjpmdW5jdGlvbihhKXtpZihDLnhCLm4oYSwiLiIpKXJldHVybiEwCnJl
-dHVybiBDLnhCLk9ZKGEsIi8uIikhPT0tMX0sCnhlOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxu
-CmlmKCFQLnlCKGEpKXJldHVybiBhCnQ9SC5WTShbXSx1LnMpCmZvcihzPWEuc3BsaXQoIi8iKSxyPXMu
-bGVuZ3RoLHE9ITEscD0wO3A8cjsrK3Ape289c1twXQppZihKLlJNKG8sIi4uIikpe249dC5sZW5ndGgK
-aWYobiE9PTApe2lmKDA+PW4pcmV0dXJuIEguT0godCwtMSkKdC5wb3AoKQppZih0Lmxlbmd0aD09PTAp
-Qy5ObS5pKHQsIiIpfXE9ITB9ZWxzZSBpZigiLiI9PT1vKXE9ITAKZWxzZXtDLk5tLmkodCxvKQpxPSEx
-fX1pZihxKUMuTm0uaSh0LCIiKQpyZXR1cm4gQy5ObS5IKHQsIi8iKX0sCndGOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscyxyLHEscCxvCmlmKCFQLnlCKGEpKXJldHVybiFiP1AuQzEoYSk6YQp0PUguVk0oW10sdS5z
-KQpmb3Iocz1hLnNwbGl0KCIvIikscj1zLmxlbmd0aCxxPSExLHA9MDtwPHI7KytwKXtvPXNbcF0KaWYo
-Ii4uIj09PW8paWYodC5sZW5ndGghPT0wJiZDLk5tLmdyWih0KSE9PSIuLiIpe2lmKDA+PXQubGVuZ3Ro
-KXJldHVybiBILk9IKHQsLTEpCnQucG9wKCkKcT0hMH1lbHNle0MuTm0uaSh0LCIuLiIpCnE9ITF9ZWxz
-ZSBpZigiLiI9PT1vKXE9ITAKZWxzZXtDLk5tLmkodCxvKQpxPSExfX1zPXQubGVuZ3RoCmlmKHMhPT0w
-KWlmKHM9PT0xKXtpZigwPj1zKXJldHVybiBILk9IKHQsMCkKcz10WzBdLmxlbmd0aD09PTB9ZWxzZSBz
-PSExCmVsc2Ugcz0hMAppZihzKXJldHVybiIuLyIKaWYocXx8Qy5ObS5ncloodCk9PT0iLi4iKUMuTm0u
-aSh0LCIiKQppZighYil7aWYoMD49dC5sZW5ndGgpcmV0dXJuIEguT0godCwwKQpDLk5tLlkodCwwLFAu
-QzEodFswXSkpfXJldHVybiBDLk5tLkgodCwiLyIpfSwKQzE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9
-YS5sZW5ndGgKaWYocT49MiYmUC5FdChKLlF6KGEsMCkpKWZvcih0PTE7dDxxOysrdCl7cz1DLnhCLlco
-YSx0KQppZihzPT09NTgpcmV0dXJuIEMueEIuTmooYSwwLHQpKyIlM0EiK0MueEIuRyhhLHQrMSkKaWYo
-czw9MTI3KXtyPXM+Pj40CmlmKHI+PTgpcmV0dXJuIEguT0goQy5tSyxyKQpyPShDLm1LW3JdJjE8PChz
-JjE1KSk9PT0wfWVsc2Ugcj0hMAppZihyKWJyZWFrfXJldHVybiBhfSwKbW46ZnVuY3Rpb24oYSl7dmFy
-IHQscyxyLHE9YS5nRmooKSxwPXEubGVuZ3RoCmlmKHA+MCYmSi5IbShxWzBdKT09PTImJkouYTYocVsw
-XSwxKT09PTU4KXtpZigwPj1wKXJldHVybiBILk9IKHEsMCkKUC5yZyhKLmE2KHFbMF0sMCksITEpClAu
-SE4ocSwhMSwxKQp0PSEwfWVsc2V7UC5ITihxLCExLDApCnQ9ITF9cz1hLmd0VCgpJiYhdD8iXFwiOiIi
-CmlmKGEuZ2NqKCkpe3I9YS5nSmYoYSkKaWYoci5sZW5ndGghPT0wKXM9cysiXFwiK3IrIlxcIn1zPVAu
-dmcocyxxLCJcXCIpCnA9dCYmcD09PTE/cysiXFwiOnMKcmV0dXJuIHAuY2hhckNvZGVBdCgwKT09MD9w
-OnB9LApJaDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgpmb3IodD0wLHM9MDtzPDI7KytzKXtyPUMueEIu
-VyhhLGIrcykKaWYoNDg8PXImJnI8PTU3KXQ9dCoxNityLTQ4CmVsc2V7cnw9MzIKaWYoOTc8PXImJnI8
-PTEwMil0PXQqMTYrci04NwplbHNlIHRocm93IEguYihQLnhZKCJJbnZhbGlkIFVSTCBlbmNvZGluZyIp
-KX19cmV0dXJuIHR9LAprdTpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHA9Si5yWShhKSxv
-PWIKd2hpbGUoITApe2lmKCEobzxjKSl7dD0hMApicmVha31zPXAuVyhhLG8pCmlmKHM8PTEyNylpZihz
-IT09Mzcpcj1lJiZzPT09NDMKZWxzZSByPSEwCmVsc2Ugcj0hMAppZihyKXt0PSExCmJyZWFrfSsrb31p
-Zih0KXtpZihDLnhNIT09ZClyPSExCmVsc2Ugcj0hMAppZihyKXJldHVybiBwLk5qKGEsYixjKQplbHNl
-IHE9bmV3IEgucWoocC5OaihhLGIsYykpfWVsc2V7cT1ILlZNKFtdLHUudCkKZm9yKG89YjtvPGM7Kytv
-KXtzPXAuVyhhLG8pCmlmKHM+MTI3KXRocm93IEguYihQLnhZKCJJbGxlZ2FsIHBlcmNlbnQgZW5jb2Rp
-bmcgaW4gVVJJIikpCmlmKHM9PT0zNyl7aWYobyszPmEubGVuZ3RoKXRocm93IEguYihQLnhZKCJUcnVu
-Y2F0ZWQgVVJJIikpCkMuTm0uaShxLFAuSWgoYSxvKzEpKQpvKz0yfWVsc2UgaWYoZSYmcz09PTQzKUMu
-Tm0uaShxLDMyKQplbHNlIEMuTm0uaShxLHMpfX11LkwuYihxKQpyZXR1cm4gbmV3IFAuR1koITEpLldK
-KHEpfSwKRXQ6ZnVuY3Rpb24oYSl7dmFyIHQ9YXwzMgpyZXR1cm4gOTc8PXQmJnQ8PTEyMn0sCktEOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9IkludmFsaWQgTUlNRSB0eXBlIixrPUgu
-Vk0oW2ItMV0sdS50KQpmb3IodD1hLmxlbmd0aCxzPWIscj0tMSxxPW51bGw7czx0Oysrcyl7cT1DLnhC
-LlcoYSxzKQppZihxPT09NDR8fHE9PT01OSlicmVhawppZihxPT09NDcpe2lmKHI8MCl7cj1zCmNvbnRp
-bnVlfXRocm93IEguYihQLnJyKGwsYSxzKSl9fWlmKHI8MCYmcz5iKXRocm93IEguYihQLnJyKGwsYSxz
-KSkKZm9yKDtxIT09NDQ7KXtDLk5tLmkoayxzKTsrK3MKZm9yKHA9LTE7czx0Oysrcyl7cT1DLnhCLlco
-YSxzKQppZihxPT09NjEpe2lmKHA8MClwPXN9ZWxzZSBpZihxPT09NTl8fHE9PT00NClicmVha31pZihw
-Pj0wKUMuTm0uaShrLHApCmVsc2V7bz1DLk5tLmdyWihrKQppZihxIT09NDR8fHMhPT1vKzd8fCFDLnhC
-LlFpKGEsImJhc2U2NCIsbysxKSl0aHJvdyBILmIoUC5ycigiRXhwZWN0aW5nICc9JyIsYSxzKSkKYnJl
-YWt9fUMuTm0uaShrLHMpCm49cysxCmlmKChrLmxlbmd0aCYxKT09PTEpYT1DLmg5LnlyKGEsbix0KQpl
-bHNle209UC5VbChhLG4sdCxDLlZDLCEwKQppZihtIT1udWxsKWE9Qy54Qi5pNyhhLG4sdCxtKX1yZXR1
-cm4gbmV3IFAuUEUoYSxrLGMpfSwKdXg6ZnVuY3Rpb24oKXt2YXIgdD0iMDEyMzQ1Njc4OUFCQ0RFRkdI
-SUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXotLl9+ISQmJygpKissOz0i
-LHM9Ii4iLHI9IjoiLHE9Ii8iLHA9Ij8iLG89IiMiLG49dS5nYyxtPVAuZEgoMjIsbmV3IFAucTMoKSwh
-MCxuKSxsPW5ldyBQLnlJKG0pLGs9bmV3IFAuYzYoKSxqPW5ldyBQLnFkKCksaT1uLmIobC4kMigwLDIy
-NSkpCmsuJDMoaSx0LDEpCmsuJDMoaSxzLDE0KQprLiQzKGksciwzNCkKay4kMyhpLHEsMykKay4kMyhp
-LHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTQsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhp
-LHMsMTUpCmsuJDMoaSxyLDM0KQprLiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1
-KQppPW4uYihsLiQyKDE1LDIyNSkpCmsuJDMoaSx0LDEpCmsuJDMoaSwiJSIsMjI1KQprLiQzKGksciwz
-NCkKay4kMyhpLHEsOSkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMSwyMjUp
-KQprLiQzKGksdCwxKQprLiQzKGksciwzNCkKay4kMyhpLHEsMTApCmsuJDMoaSxwLDE3MikKay4kMyhp
-LG8sMjA1KQppPW4uYihsLiQyKDIsMjM1KSkKay4kMyhpLHQsMTM5KQprLiQzKGkscSwxMzEpCmsuJDMo
-aSxzLDE0NikKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMywyMzUpKQprLiQz
-KGksdCwxMSkKay4kMyhpLHEsNjgpCmsuJDMoaSxzLDE4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIw
-NSkKaT1uLmIobC4kMig0LDIyOSkpCmsuJDMoaSx0LDUpCmouJDMoaSwiQVoiLDIyOSkKay4kMyhpLHIs
-MTAyKQprLiQzKGksIkAiLDY4KQprLiQzKGksIlsiLDIzMikKay4kMyhpLHEsMTM4KQprLiQzKGkscCwx
-NzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMig1LDIyOSkpCmsuJDMoaSx0LDUpCmouJDMoaSwiQVoi
-LDIyOSkKay4kMyhpLHIsMTAyKQprLiQzKGksIkAiLDY4KQprLiQzKGkscSwxMzgpCmsuJDMoaSxwLDE3
-MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDYsMjMxKSkKai4kMyhpLCIxOSIsNykKay4kMyhpLCJA
-Iiw2OCkKay4kMyhpLHEsMTM4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMig3
-LDIzMSkpCmouJDMoaSwiMDkiLDcpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAs
-MTcyKQprLiQzKGksbywyMDUpCmsuJDMobi5iKGwuJDIoOCw4KSksIl0iLDUpCmk9bi5iKGwuJDIoOSwy
-MzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHMsMTYpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQpr
-LiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTYsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxzLDE3KQpr
-LiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDE3LDIzNSkp
-CmsuJDMoaSx0LDExKQprLiQzKGkscSw5KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIo
-bC4kMigxMCwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHMsMTgpCmsuJDMoaSxxLDIzNCkKay4kMyhp
-LHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTgsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMo
-aSxzLDE5KQprLiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQy
-KDE5LDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscSwyMzQpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8s
-MjA1KQppPW4uYihsLiQyKDExLDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscSwxMCkKay4kMyhpLHAs
-MTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTIsMjM2KSkKay4kMyhpLHQsMTIpCmsuJDMoaSxw
-LDEyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTMsMjM3KSkKay4kMyhpLHQsMTMpCmsuJDMoaSxw
-LDEzKQpqLiQzKG4uYihsLiQyKDIwLDI0NSkpLCJheiIsMjEpCmw9bi5iKGwuJDIoMjEsMjQ1KSkKai4k
-MyhsLCJheiIsMjEpCmouJDMobCwiMDkiLDIxKQprLiQzKGwsIistLiIsMjEpCnJldHVybiBtfSwKVUI6
-ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG89JC52WigpCmZvcih0PUouclkoYSkscz1i
-O3M8YzsrK3Mpe2lmKGQ8MHx8ZD49by5sZW5ndGgpcmV0dXJuIEguT0gobyxkKQpyPW9bZF0KcT10Llco
-YSxzKV45NgppZihxPjk1KXE9MzEKaWYocT49ci5sZW5ndGgpcmV0dXJuIEguT0gocixxKQpwPXJbcV0K
-ZD1wJjMxCkMuTm0uWShlLHA+Pj41LHMpfXJldHVybiBkfSwKV0Y6ZnVuY3Rpb24gV0YoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCmEyOmZ1bmN0aW9uIGEyKCl7fSwKaVA6ZnVuY3Rpb24gaVAoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCkNQOmZ1bmN0aW9uIENQKCl7fSwKWFM6ZnVuY3Rpb24gWFMoKXt9LApDNjpm
-dW5jdGlvbiBDNihhKXt0aGlzLmE9YX0sCm46ZnVuY3Rpb24gbigpe30sCnU6ZnVuY3Rpb24gdShhLGIs
-YyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKYko6ZnVuY3Rpb24gYkooYSxi
-LGMsZCxlLGYpe3ZhciBfPXRoaXMKXy5lPWEKXy5mPWIKXy5hPWMKXy5iPWQKXy5jPWUKXy5kPWZ9LApl
-WTpmdW5jdGlvbiBlWShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5mPWEKXy5hPWIKXy5iPWMKXy5jPWQK
-Xy5kPWV9LAptcDpmdW5jdGlvbiBtcChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1j
-Cl8uZD1kfSwKdWI6ZnVuY3Rpb24gdWIoYSl7dGhpcy5hPWF9LApkczpmdW5jdGlvbiBkcyhhKXt0aGlz
-LmE9YX0sCmxqOmZ1bmN0aW9uIGxqKGEpe3RoaXMuYT1hfSwKVVY6ZnVuY3Rpb24gVVYoYSl7dGhpcy5h
-PWF9LAprNTpmdW5jdGlvbiBrNSgpe30sCktZOmZ1bmN0aW9uIEtZKCl7fSwKYzpmdW5jdGlvbiBjKGEp
-e3RoaXMuYT1hfSwKQ0Q6ZnVuY3Rpb24gQ0QoYSl7dGhpcy5hPWF9LAphRTpmdW5jdGlvbiBhRShhLGIs
-Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApFSDpmdW5jdGlvbiBFSCgpe30sCktOOmZ1bmN0
-aW9uIEtOKCl7fSwKY1g6ZnVuY3Rpb24gY1goKXt9LApBbjpmdW5jdGlvbiBBbigpe30sCnpNOmZ1bmN0
-aW9uIHpNKCl7fSwKWjA6ZnVuY3Rpb24gWjAoKXt9LApjODpmdW5jdGlvbiBjOCgpe30sCkZLOmZ1bmN0
-aW9uIEZLKCl7fSwKazpmdW5jdGlvbiBrKCl7fSwKT2Q6ZnVuY3Rpb24gT2QoKXt9LAppYjpmdW5jdGlv
-biBpYigpe30sCnh1OmZ1bmN0aW9uIHh1KCl7fSwKR3o6ZnVuY3Rpb24gR3ooKXt9LApxVTpmdW5jdGlv
-biBxVSgpe30sClJuOmZ1bmN0aW9uIFJuKGEpe3RoaXMuYT1hfSwKR0Q6ZnVuY3Rpb24gR0QoKXt9LApu
-MTpmdW5jdGlvbiBuMShhKXt0aGlzLmE9YX0sCmNTOmZ1bmN0aW9uIGNTKGEpe3RoaXMuYT1hfSwKVkM6
-ZnVuY3Rpb24gVkMoYSl7dGhpcy5hPWF9LAp0cDpmdW5jdGlvbiB0cChhLGIpe3RoaXMuYT1hCnRoaXMu
-Yj1ifSwKRG46ZnVuY3Rpb24gRG4oYSxiLGMsZCxlLGYsZyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9Ygpf
-LmM9YwpfLmQ9ZApfLmU9ZQpfLmY9ZgpfLnI9ZwpfLlE9Xy56PV8ueT1fLng9bnVsbH0sCmUxOmZ1bmN0
-aW9uIGUxKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApOWTpmdW5jdGlvbiBOWShhKXt0aGlzLmE9YX0s
-ClJaOmZ1bmN0aW9uIFJaKCl7fSwKTUU6ZnVuY3Rpb24gTUUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0s
-Cnk1OmZ1bmN0aW9uIHk1KGEpe3RoaXMuYT1hfSwKUEU6ZnVuY3Rpb24gUEUoYSxiLGMpe3RoaXMuYT1h
-CnRoaXMuYj1iCnRoaXMuYz1jfSwKcTM6ZnVuY3Rpb24gcTMoKXt9LAp5STpmdW5jdGlvbiB5SShhKXt0
-aGlzLmE9YX0sCmM2OmZ1bmN0aW9uIGM2KCl7fSwKcWQ6ZnVuY3Rpb24gcWQoKXt9LApVZjpmdW5jdGlv
-biBVZihhLGIsYyxkLGUsZixnLGgpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5l
-PWUKXy5mPWYKXy5yPWcKXy54PWgKXy55PW51bGx9LApxZTpmdW5jdGlvbiBxZShhLGIsYyxkLGUsZixn
-KXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8uUT1f
-Lno9Xy55PV8ueD1udWxsfSwKaUo6ZnVuY3Rpb24gaUooKXt9LApsUjpmdW5jdGlvbiBsUihhLGIpe3Ro
-aXMuYT1hCnRoaXMuYj1ifSwKamc6ZnVuY3Rpb24gamcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkJm
-OmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApBczpmdW5jdGlvbiBBcygpe30sCkdF
-OmZ1bmN0aW9uIEdFKGEpe3RoaXMuYT1hfSwKTjc6ZnVuY3Rpb24gTjcoYSxiKXt0aGlzLmE9YQp0aGlz
-LmI9Yn0sCnVROmZ1bmN0aW9uIHVRKCl7fSwKaEY6ZnVuY3Rpb24gaEYoKXt9LApSNDpmdW5jdGlvbihh
-LGIsYyxkKXt2YXIgdCxzLHIKSC54ZChiKQp1LmouYihkKQppZihILm9UKGIpKXt0PVtjXQpDLk5tLkZW
-KHQsZCkKZD10fXM9dS56CnI9UC5DSChKLk0xKGQsUC53MCgpLHMpLCEwLHMpCnUuWi5iKGEpCnJldHVy
-biBQLndZKEguRWsoYSxyLG51bGwpKX0sCkRtOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAp0cnl7aWYoT2Jq
-ZWN0LmlzRXh0ZW5zaWJsZShhKSYmIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChh
-LGIpKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxiLHt2YWx1ZTpjfSkKcmV0dXJuITB9fWNhdGNoKHQp
-e0guUnUodCl9cmV0dXJuITF9LApPbTpmdW5jdGlvbihhLGIpe2lmKE9iamVjdC5wcm90b3R5cGUuaGFz
-T3duUHJvcGVydHkuY2FsbChhLGIpKXJldHVybiBhW2JdCnJldHVybiBudWxsfSwKd1k6ZnVuY3Rpb24o
-YSl7aWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBlb2YgYT09Im51bWJlciJ8fEgubChh
-KSlyZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5FNClyZXR1cm4gYS5hCmlmKEguUjkoYSkpcmV0dXJu
-IGEKaWYodS52LmMoYSkpcmV0dXJuIGEKaWYoYSBpbnN0YW5jZW9mIFAuaVApcmV0dXJuIEgubzIoYSkK
-aWYodS5aLmMoYSkpcmV0dXJuIFAuaEUoYSwiJGRhcnRfanNGdW5jdGlvbiIsbmV3IFAuUEMoKSkKcmV0
-dXJuIFAuaEUoYSwiXyRkYXJ0X2pzT2JqZWN0IixuZXcgUC5ZbSgkLmtJKCkpKX0sCmhFOmZ1bmN0aW9u
-KGEsYixjKXt2YXIgdD1QLk9tKGEsYikKaWYodD09bnVsbCl7dD1jLiQxKGEpClAuRG0oYSxiLHQpfXJl
-dHVybiB0fSwKTDc6ZnVuY3Rpb24oYSl7dmFyIHQscwppZihhPT1udWxsfHx0eXBlb2YgYT09InN0cmlu
-ZyJ8fHR5cGVvZiBhPT0ibnVtYmVyInx8dHlwZW9mIGE9PSJib29sZWFuIilyZXR1cm4gYQplbHNlIGlm
-KGEgaW5zdGFuY2VvZiBPYmplY3QmJkguUjkoYSkpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNlb2Yg
-T2JqZWN0JiZ1LnYuYyhhKSlyZXR1cm4gYQplbHNlIGlmKGEgaW5zdGFuY2VvZiBEYXRlKXt0PUguU2Mo
-YS5nZXRUaW1lKCkpCmlmKE1hdGguYWJzKHQpPD04NjRlMTMpcz0hMQplbHNlIHM9ITAKaWYocylILnZo
-KFAueFkoIkRhdGVUaW1lIGlzIG91dHNpZGUgdmFsaWQgcmFuZ2U6ICIrdCkpCnJldHVybiBuZXcgUC5p
-UCh0LCExKX1lbHNlIGlmKGEuY29uc3RydWN0b3I9PT0kLmtJKCkpcmV0dXJuIGEubwplbHNlIHJldHVy
-biBQLk5EKGEpfSwKTkQ6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIFAu
-aVEoYSwkLncoKSxuZXcgUC5OeigpKQppZihhIGluc3RhbmNlb2YgQXJyYXkpcmV0dXJuIFAuaVEoYSwk
-LlI4KCksbmV3IFAuUVMoKSkKcmV0dXJuIFAuaVEoYSwkLlI4KCksbmV3IFAubnAoKSl9LAppUTpmdW5j
-dGlvbihhLGIsYyl7dmFyIHQ9UC5PbShhLGIpCmlmKHQ9PW51bGx8fCEoYSBpbnN0YW5jZW9mIE9iamVj
-dCkpe3Q9Yy4kMShhKQpQLkRtKGEsYix0KX1yZXR1cm4gdH0sClBDOmZ1bmN0aW9uIFBDKCl7fSwKWW06
-ZnVuY3Rpb24gWW0oYSl7dGhpcy5hPWF9LApOejpmdW5jdGlvbiBOeigpe30sClFTOmZ1bmN0aW9uIFFT
-KCl7fSwKbnA6ZnVuY3Rpb24gbnAoKXt9LApFNDpmdW5jdGlvbiBFNChhKXt0aGlzLmE9YX0sCnI3OmZ1
-bmN0aW9uIHI3KGEpe3RoaXMuYT1hfSwKVHo6ZnVuY3Rpb24gVHooYSxiKXt0aGlzLmE9YQp0aGlzLiR0
-aT1ifSwKY286ZnVuY3Rpb24gY28oKXt9LApuZDpmdW5jdGlvbiBuZCgpe30sCktlOmZ1bmN0aW9uIEtl
-KGEpe3RoaXMuYT1hfSwKZDU6ZnVuY3Rpb24gZDUoKXt9LApuNjpmdW5jdGlvbiBuNigpe319LFc9ewpV
-OTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9ZG9jdW1lbnQuYm9keSxzPSh0JiZDLlJZKS5yNih0LGEsYixj
-KQpzLnRvU3RyaW5nCnQ9dS5hYwp0PW5ldyBILlU1KG5ldyBXLmU3KHMpLHQuQygiYTIobEQuRSkiKS5i
-KG5ldyBXLkN2KCkpLHQuQygiVTU8bEQuRT4iKSkKcmV0dXJuIHUuaC5iKHQuZ3I4KHQpKX0sCnJTOmZ1
-bmN0aW9uKGEpe3ZhciB0LHMscj0iZWxlbWVudCB0YWcgdW5hdmFpbGFibGUiCnRyeXt0PUouUkUoYSkK
-aWYodHlwZW9mIHQuZ25zKGEpPT0ic3RyaW5nIilyPXQuZ25zKGEpfWNhdGNoKHMpe0guUnUocyl9cmV0
-dXJuIHJ9LApxRDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9bmV3IFAudnMoJC5YMyx1LmFvKSxw
-PW5ldyBQLlpmKHEsdS5FKSxvPW5ldyBYTUxIdHRwUmVxdWVzdCgpCkMuRHQuZW8obyxiPT1udWxsPyJH
-RVQiOmIsYSwhMCkKYy5LKDAsbmV3IFcuYlUobykpCnQ9dS5hbgpzPXQuYihuZXcgVy5oSChvLHApKQp1
-Lk0uYihudWxsKQpyPXUucApXLkpFKG8sImxvYWQiLHMsITEscikKVy5KRShvLCJlcnJvciIsdC5iKHAu
-Z1lKKCkpLCExLHIpCm8uc2VuZCgpCnJldHVybiBxfSwKQzA6ZnVuY3Rpb24oYSxiKXthPTUzNjg3MDkx
-MSZhK2IKYT01MzY4NzA5MTEmYSsoKDUyNDI4NyZhKTw8MTApCnJldHVybiBhXmE+Pj42fSwKckU6ZnVu
-Y3Rpb24oYSxiLGMsZCl7dmFyIHQ9Vy5DMChXLkMwKFcuQzAoVy5DMCgwLGEpLGIpLGMpLGQpLHM9NTM2
-ODcwOTExJnQrKCg2NzEwODg2MyZ0KTw8MykKc149cz4+PjExCnJldHVybiA1MzY4NzA5MTEmcysoKDE2
-MzgzJnMpPDwxNSl9LApUTjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1hLmNsYXNzTGlzdApmb3IodD1i
-Lmxlbmd0aCxzPTA7czxiLmxlbmd0aDtiLmxlbmd0aD09PXR8fCgwLEgubGspKGIpLCsrcylyLmFkZChi
-W3NdKX0sCkpFOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQ9Vy5hRihuZXcgVy52TihjKSx1LkIpCmlm
-KHQhPW51bGwmJiEwKUouZFooYSxiLHQsITEpCnJldHVybiBuZXcgVy54QyhhLGIsdCwhMSxlLkMoInhD
-PDA+IikpfSwKVHc6ZnVuY3Rpb24oYSl7dmFyIHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYSIpLHM9
-bmV3IFcubWsodCx3aW5kb3cubG9jYXRpb24pCnM9bmV3IFcuSlEocykKcy5DWShhKQpyZXR1cm4gc30s
-CnlXOmZ1bmN0aW9uKGEsYixjLGQpe3UuaC5iKGEpCkgueShiKQpILnkoYykKdS5PLmIoZCkKcmV0dXJu
-ITB9LApRVzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKdS5oLmIoYSkKSC55KGIpCkgueShjKQp0
-PXUuTy5iKGQpLmEKcz10LmEKcy5ocmVmPWMKcj1zLmhvc3RuYW1lCnQ9dC5iCmlmKCEocj09dC5ob3N0
-bmFtZSYmcy5wb3J0PT10LnBvcnQmJnMucHJvdG9jb2w9PXQucHJvdG9jb2wpKWlmKHI9PT0iIilpZihz
-LnBvcnQ9PT0iIil7dD1zLnByb3RvY29sCnQ9dD09PSI6Inx8dD09PSIifWVsc2UgdD0hMQplbHNlIHQ9
-ITEKZWxzZSB0PSEwCnJldHVybiB0fSwKQmw6ZnVuY3Rpb24oKXt2YXIgdD11Lk4scz1QLnRNKEMuUXgs
-dCkscj11LmRHLmIobmV3IFcuSUEoKSkscT1ILlZNKFsiVEVNUExBVEUiXSx1LnMpCnQ9bmV3IFcuY3Qo
-cyxQLkxzKHQpLFAuTHModCksUC5Mcyh0KSxudWxsKQp0LkNZKG51bGwsbmV3IEguQTgoQy5ReCxyLHUu
-ZHYpLHEsbnVsbCkKcmV0dXJuIHR9LApxYzpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJldHVy
-biBudWxsCmlmKCJwb3N0TWVzc2FnZSIgaW4gYSl7dD1XLlAxKGEpCnJldHVybiB0fWVsc2UgcmV0dXJu
-IHUuYVMuYihhKX0sClAxOmZ1bmN0aW9uKGEpe2lmKGE9PT13aW5kb3cpcmV0dXJuIHUuY2kuYihhKQpl
-bHNlIHJldHVybiBuZXcgVy5kVygpfSwKYUY6ZnVuY3Rpb24oYSxiKXt2YXIgdD0kLlgzCmlmKHQ9PT1D
-Lk5VKXJldHVybiBhCnJldHVybiB0LlB5KGEsYil9LApxRTpmdW5jdGlvbiBxRSgpe30sCkdoOmZ1bmN0
-aW9uIEdoKCl7fSwKZlk6ZnVuY3Rpb24gZlkoKXt9LApuQjpmdW5jdGlvbiBuQigpe30sCkF6OmZ1bmN0
-aW9uIEF6KCl7fSwKUVA6ZnVuY3Rpb24gUVAoKXt9LApueDpmdW5jdGlvbiBueCgpe30sCm9KOmZ1bmN0
-aW9uIG9KKCl7fSwKaWQ6ZnVuY3Rpb24gaWQoKXt9LApRRjpmdW5jdGlvbiBRRigpe30sCk5oOmZ1bmN0
-aW9uIE5oKCl7fSwKSUI6ZnVuY3Rpb24gSUIoKXt9LApuNzpmdW5jdGlvbiBuNygpe30sCnd6OmZ1bmN0
-aW9uIHd6KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmN2OmZ1bmN0aW9uIGN2KCl7fSwKQ3Y6ZnVu
-Y3Rpb24gQ3YoKXt9LAplYTpmdW5jdGlvbiBlYSgpe30sCkQwOmZ1bmN0aW9uIEQwKCl7fSwKVDU6ZnVu
-Y3Rpb24gVDUoKXt9LApoNDpmdW5jdGlvbiBoNCgpe30sCmJyOmZ1bmN0aW9uIGJyKCl7fSwKVmI6ZnVu
-Y3Rpb24gVmIoKXt9LApPNzpmdW5jdGlvbiBPNygpe30sCmJVOmZ1bmN0aW9uIGJVKGEpe3RoaXMuYT1h
-fSwKaEg6ZnVuY3Rpb24gaEgoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCndhOmZ1bmN0aW9uIHdhKCl7
-fSwKU2c6ZnVuY3Rpb24gU2coKXt9LAp1ODpmdW5jdGlvbiB1OCgpe30sCkFqOmZ1bmN0aW9uIEFqKCl7
-fSwKZTc6ZnVuY3Rpb24gZTcoYSl7dGhpcy5hPWF9LAp1SDpmdW5jdGlvbiB1SCgpe30sCkJIOmZ1bmN0
-aW9uIEJIKCl7fSwKU046ZnVuY3Rpb24gU04oKXt9LApldzpmdW5jdGlvbiBldygpe30sCmxwOmZ1bmN0
-aW9uIGxwKCl7fSwKVGI6ZnVuY3Rpb24gVGIoKXt9LApJdjpmdW5jdGlvbiBJdigpe30sCkJUOmZ1bmN0
-aW9uIEJUKCl7fSwKeVk6ZnVuY3Rpb24geVkoKXt9LAp3NjpmdW5jdGlvbiB3Nigpe30sCks1OmZ1bmN0
-aW9uIEs1KCl7fSwKQ206ZnVuY3Rpb24gQ20oKXt9LApDUTpmdW5jdGlvbiBDUSgpe30sCnc0OmZ1bmN0
-aW9uIHc0KCl7fSwKcmg6ZnVuY3Rpb24gcmgoKXt9LApEOTpmdW5jdGlvbiBEOSgpe30sCmk3OmZ1bmN0
-aW9uIGk3KGEpe3RoaXMuYT1hfSwKU3k6ZnVuY3Rpb24gU3koYSl7dGhpcy5hPWF9LApLUzpmdW5jdGlv
-biBLUyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQTM6ZnVuY3Rpb24gQTMoYSxiKXt0aGlzLmE9YQp0
-aGlzLmI9Yn0sCkk0OmZ1bmN0aW9uIEk0KGEpe3RoaXMuYT1hfSwKRms6ZnVuY3Rpb24gRmsoYSxiKXt0
-aGlzLmE9YQp0aGlzLiR0aT1ifSwKUk86ZnVuY3Rpb24gUk8oYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9
-YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKQ3E6ZnVuY3Rpb24gQ3EoYSxiLGMsZCl7dmFyIF89dGhpcwpf
-LmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKeEM6ZnVuY3Rpb24geEMoYSxiLGMsZCxlKXt2YXIgXz10
-aGlzCl8uYj1hCl8uYz1iCl8uZD1jCl8uZT1kCl8uJHRpPWV9LAp2TjpmdW5jdGlvbiB2TihhKXt0aGlz
-LmE9YX0sCkpROmZ1bmN0aW9uIEpRKGEpe3RoaXMuYT1hfSwKR206ZnVuY3Rpb24gR20oKXt9LAp2RDpm
-dW5jdGlvbiB2RChhKXt0aGlzLmE9YX0sClV2OmZ1bmN0aW9uIFV2KGEpe3RoaXMuYT1hfSwKRWc6ZnVu
-Y3Rpb24gRWcoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKbTY6ZnVuY3Rpb24gbTYo
-KXt9LApFbzpmdW5jdGlvbiBFbygpe30sCldrOmZ1bmN0aW9uIFdrKCl7fSwKY3Q6ZnVuY3Rpb24gY3Qo
-YSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uZT1hCl8uYT1iCl8uYj1jCl8uYz1kCl8uZD1lfSwKSUE6ZnVu
-Y3Rpb24gSUEoKXt9LApPdzpmdW5jdGlvbiBPdygpe30sClc5OmZ1bmN0aW9uIFc5KGEsYixjKXt2YXIg
-Xz10aGlzCl8uYT1hCl8uYj1iCl8uYz0tMQpfLmQ9bnVsbApfLiR0aT1jfSwKZFc6ZnVuY3Rpb24gZFco
-KXt9LAprRjpmdW5jdGlvbiBrRigpe30sCm1rOmZ1bmN0aW9uIG1rKGEsYil7dGhpcy5hPWEKdGhpcy5i
-PWJ9LApLbzpmdW5jdGlvbiBLbyhhKXt0aGlzLmE9YX0sCmZtOmZ1bmN0aW9uIGZtKGEpe3RoaXMuYT1h
-fSwKTGU6ZnVuY3Rpb24gTGUoKXt9LApLNzpmdW5jdGlvbiBLNygpe30sCnJCOmZ1bmN0aW9uIHJCKCl7
-fSwKWFc6ZnVuY3Rpb24gWFcoKXt9LApvYTpmdW5jdGlvbiBvYSgpe319LFU9ewp5dTpmdW5jdGlvbihh
-KXt2YXIgdCxzLHIscSxwLG8sbj1ILlZNKFtdLHUuYlApCmZvcih0PUouVTYoYSkscz1KLklUKHUuUi5i
-KHQucShhLCJkZXRhaWxzIikpKTtzLkYoKTspe3I9cy5nbCgpCnE9Si5VNihyKQpwPUgueShxLnEociwi
-ZGVzY3JpcHRpb24iKSkKcT1xLnEociwibGluayIpCmlmKHE9PW51bGwpcT1udWxsCmVsc2V7bz1KLlU2
-KHEpCnE9bmV3IFUuTWwoSC55KG8ucShxLCJocmVmIikpLEguU2Moby5xKHEsImxpbmUiKSksSC55KG8u
-cShxLCJwYXRoIikpKX1DLk5tLmkobixuZXcgVS51RihwLHEpKX1yZXR1cm4gbmV3IFUuZDIobixVLmpm
-KHQucShhLCJlZGl0cyIpKSxILnkodC5xKGEsImV4cGxhbmF0aW9uIikpLEguU2ModC5xKGEsImxpbmUi
-KSksSC55KHQucShhLCJwYXRoIikpLFUuTmQodC5xKGEsInRyYWNlcyIpKSl9LApqZjpmdW5jdGlvbihh
-KXt2YXIgdCxzLHIscQppZihhPT1udWxsKXQ9bnVsbAplbHNle3Q9SC5WTShbXSx1LmZBKQpmb3Iocz1K
-LklUKHUuUi5iKGEpKTtzLkYoKTspe3I9cy5nbCgpCnE9Si5VNihyKQpDLk5tLmkodCxuZXcgVS5TZShI
-LnkocS5xKHIsImRlc2NyaXB0aW9uIikpLEgueShxLnEociwiaHJlZiIpKSkpfX1yZXR1cm4gdH0sCk5k
-OmZ1bmN0aW9uKGEpe3ZhciB0LHMKaWYoYT09bnVsbCl0PW51bGwKZWxzZXt0PUguVk0oW10sdS5oaCkK
-Zm9yKHM9Si5JVCh1LlIuYihhKSk7cy5GKCk7KUMuTm0uaSh0LFUuTmYocy5nbCgpKSl9cmV0dXJuIHR9
-LApOZjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG89ImRlc2NyaXB0aW9uIixuPUouVTYoYSksbT1I
-Lnkobi5xKGEsbykpLGw9SC5WTShbXSx1LmFKKQpmb3Iobj1KLklUKHUuUi5iKG4ucShhLCJlbnRyaWVz
-IikpKTtuLkYoKTspe3Q9bi5nbCgpCnM9Si5VNih0KQpyPUgueShzLnEodCxvKSkKcT1ILnkocy5xKHQs
-ImZ1bmN0aW9uIikpCnM9cy5xKHQsImxpbmsiKQppZihzPT1udWxsKXM9bnVsbAplbHNle3A9Si5VNihz
-KQpzPW5ldyBVLk1sKEgueShwLnEocywiaHJlZiIpKSxILlNjKHAucShzLCJsaW5lIikpLEgueShwLnEo
-cywicGF0aCIpKSl9Qy5ObS5pKGwsbmV3IFUud2IocixxLHMpKX1yZXR1cm4gbmV3IFUueUQobSxsKX0s
-CmQyOmZ1bmN0aW9uIGQyKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8u
-ZD1kCl8uZT1lCl8uZj1mfSwKU2U6ZnVuY3Rpb24gU2UoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnVG
-OmZ1bmN0aW9uIHVGKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApNbDpmdW5jdGlvbiBNbChhLGIsYyl7
-dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAp5RDpmdW5jdGlvbiB5RChhLGIpe3RoaXMuYT1hCnRo
-aXMuYj1ifSwKd2I6ZnVuY3Rpb24gd2IoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfX0s
-VD17R1Y6ZnVuY3Rpb24gR1YoKXt9fSxMPXsKSXE6ZnVuY3Rpb24oKXtDLkJaLkIoZG9jdW1lbnQsIkRP
-TUNvbnRlbnRMb2FkZWQiLG5ldyBMLmUoKSkKQy5vbC5CKHdpbmRvdywicG9wc3RhdGUiLG5ldyBMLkwo
-KSl9LAprejpmdW5jdGlvbihhKXt2YXIgdCxzPXUuaC5hKGEucGFyZW50Tm9kZSkucXVlcnlTZWxlY3Rv
-cigiOnNjb3BlID4gdWwiKSxyPXMuc3R5bGUscT0iIitDLkNELnpRKHMub2Zmc2V0SGVpZ2h0KSoyKyJw
-eCIKci5tYXhIZWlnaHQ9cQpyPUoucUYoYSkKcT1yLiR0aQp0PXEuQygifigxKSIpLmIobmV3IEwuV3go
-cyxhKSkKdS5NLmIobnVsbCkKVy5KRShyLmEsci5iLHQsITEscS5kKX0sCnlYOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscixxLHAsbz0icXVlcnlTZWxlY3RvckFsbCIsbj1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKGEp
-LG09dS5oCm4udG9TdHJpbmcKSC5EaChtLG0sIlQiLG8pCnQ9dS5TCnM9bmV3IFcud3oobi5xdWVyeVNl
-bGVjdG9yQWxsKCIubmF2LWxpbmsiKSx0KQpzLksocyxuZXcgTC5BTygpKQpILkRoKG0sbSwiVCIsbykK
-cj1uZXcgVy53eihuLnF1ZXJ5U2VsZWN0b3JBbGwoIi5yZWdpb24iKSx0KQppZihyLmdBKHIpIT09MCl7
-cT1uLnF1ZXJ5U2VsZWN0b3IoInRhYmxlW2RhdGEtcGF0aF0iKQpxLnRvU3RyaW5nCnIuSyhyLG5ldyBM
-LkhvKHEuZ2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcocSkpLk8oInBhdGgiKSkp
-KX1ILkRoKG0sbSwiVCIsbykKcD1uZXcgVy53eihuLnF1ZXJ5U2VsZWN0b3JBbGwoIi5wb3N0LWxpbmsi
-KSx0KQpwLksocCxuZXcgTC5JQygpKX0sCnR5OmZ1bmN0aW9uKGEpe3ZhciB0PXUuTgpyZXR1cm4gVy5x
-RChhLCJQT1NUIixQLkVGKFsiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1V
-VEYtOCJdLHQsdCkpLlc3KG5ldyBMLkwxKCksdS5yKX0sCmFLOmZ1bmN0aW9uKGEpe3ZhciB0PVAuaEso
-YSkuZ2hZKCkucSgwLCJsaW5lIikKcmV0dXJuIHQ9PW51bGw/bnVsbDpILkhwKHQsbnVsbCl9LApHNjpm
-dW5jdGlvbihhKXt2YXIgdD1QLmhLKGEpLmdoWSgpLnEoMCwib2Zmc2V0IikKcmV0dXJuIHQ9PW51bGw/
-bnVsbDpILkhwKHQsbnVsbCl9LAp0MjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuPXt9CnUu
-Vi5iKGEpCnQ9bi5hPXUuaC5iKFcucWMoYS5jdXJyZW50VGFyZ2V0KSkuZ2V0QXR0cmlidXRlKCJocmVm
-IikKaWYoSi56bCh0LCI/Iikpe3M9Qy54Qi5Oaih0LDAsQy54Qi5PWSh0LCI/IikpCm4uYT1zCnI9c31l
-bHNlIHI9dAppZihiIT1udWxsKXtxPSQublUoKQpyPW4uYT1xLm81KEQubnIocS50TShiKSxyKSl9cD1M
-Lkc2KHQpCm89TC5hSyh0KQppZihwIT1udWxsKUwuYWYocixwLG8sbmV3IEwublQobixwLG8pKQplbHNl
-IEwuYWYocixudWxsLG51bGwsbmV3IEwuQloobikpCmEucHJldmVudERlZmF1bHQoKX0sCnVtOmZ1bmN0
-aW9uKGEpe3ZhciB0CnUuVi5iKGEpCnQ9dS5oLmEoVy5xYyhhLmN1cnJlbnRUYXJnZXQpKS5nZXRBdHRy
-aWJ1dGUoImhyZWYiKQpMLnR5KHQpLk9BKG5ldyBMLkZRKHQpKQphLnByZXZlbnREZWZhdWx0KCl9LAp2
-VTpmdW5jdGlvbigpe3ZhciB0PWRvY3VtZW50LHM9dS5oCkguRGgocyxzLCJUIiwicXVlcnlTZWxlY3Rv
-ckFsbCIpCnQ9bmV3IFcud3oodC5xdWVyeVNlbGVjdG9yQWxsKCIuY29kZSIpLHUuUykKdC5LKHQsbmV3
-IEwuR0goKSl9LApoWDpmdW5jdGlvbihhLGIpe3ZhciB0PXUuTgpXLnFEKEguZChhKSsiP3JlZ2lvbj1y
-ZWdpb24mb2Zmc2V0PSIrSC5kKGIpLG51bGwsUC5FRihbIkNvbnRlbnQtVHlwZSIsImFwcGxpY2F0aW9u
-L2pzb247IGNoYXJzZXQ9VVRGLTgiXSx0LHQpKS5XNyhuZXcgTC5EVCgpLHUuUCkuT0EobmV3IEwuZUgo
-YSkpfSwKRzc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscwppZighSi5yWShhKS5UYyhhLCIuZGFydCIp
-KXtMLkJFKGEsUC5FRihbInJlZ2lvbnMiLCIiLCJuYXZpZ2F0aW9uQ29udGVudCIsIiIsImVkaXRzIixb
-XV0sdS5OLHUueikpCkwuQlgoYSxudWxsKQppZihkIT1udWxsKWQuJDAoKQpyZXR1cm59dD1DLnhCLnRn
-KGEsIj8iKT9hKyImaW5saW5lPXRydWUiOmErIj9pbmxpbmU9dHJ1ZSIKcz11Lk4KVy5xRCh0LG51bGws
-UC5FRihbIkNvbnRlbnQtVHlwZSIsImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9VVRGLTgiXSxzLHMp
-KS5XNyhuZXcgTC56RChhLGIsYyxkKSx1LlApLk9BKG5ldyBMLk9FKGEpKX0sCkdlOmZ1bmN0aW9uKCl7
-dmFyIHQ9Ii9fcHJldmlldy9uYXZpZ2F0aW9uVHJlZS5qc29uIixzPXUuTgpXLnFEKHQsbnVsbCxQLkVG
-KFsiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCJdLHMscykpLlc3
-KG5ldyBMLlRXKCksdS5QKS5PQShuZXcgTC54cih0KSl9LApxSjpmdW5jdGlvbihhLGIpe3ZhciB0Cndp
-bmRvdwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3IoYSkK
-d2luZG93CnQ9SC5kKGIpCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29s
-ZS5lcnJvcih0KX0sCnFPOmZ1bmN0aW9uKGEpe3ZhciB0PWEuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCks
-cz10LmJvdHRvbSxyPXdpbmRvdy5pbm5lckhlaWdodAppZih0eXBlb2YgciE9PSJudW1iZXIiKXJldHVy
-biBILnBZKHIpCmlmKHM+cilKLmRoKGEpCmVsc2UgaWYodC50b3A8MClKLmRoKGEpfSwKZkc6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzLHIKaWYoYSE9bnVsbCl7dD1kb2N1bWVudApzPXQuZ2V0RWxlbWVudEJ5SWQo
-Im8iK0guZChhKSkKcj10LnF1ZXJ5U2VsZWN0b3IoIi5saW5lLSIrSC5kKGIpKQppZihzIT1udWxsKXtM
-LnFPKHMpCkouZFIocykuaSgwLCJ0YXJnZXQiKX1lbHNlIGlmKHIhPW51bGwpTC5xTyhyLnBhcmVudEVs
-ZW1lbnQpCmlmKHIhPW51bGwpSi5kUih1LmguYShyLnBhcmVudE5vZGUpKS5pKDAsImhpZ2hsaWdodCIp
-fWVsc2UgTC5xTyhkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgidW5pdC1uYW1lIikpfSwKYWY6ZnVuY3Rp
-b24oYSxiLGMsZCl7dmFyIHQscyxyPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpLHE9TC5hSyh3aW5k
-b3cubG9jYXRpb24uaHJlZikKaWYociE9bnVsbCl7dD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibyIr
-SC5kKHIpKQppZih0IT1udWxsKUouZFIodCkuUigwLCJ0YXJnZXQiKX1pZihxIT1udWxsKXtzPWRvY3Vt
-ZW50LnF1ZXJ5U2VsZWN0b3IoIi5saW5lLSIrSC5kKHEpKQppZihzIT1udWxsKUouZFIocy5wYXJlbnRF
-bGVtZW50KS5SKDAsImhpZ2hsaWdodCIpfWlmKGE9PXdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSl7TC5m
-RyhiLGMpCmQuJDAoKX1lbHNlIEwuRzcoYSxiLGMsZCl9LApMeDpmdW5jdGlvbihhLGIpe3ZhciB0Cmlm
-KGE9PT0xKXQ9YgplbHNlIHQ9YisicyIKcmV0dXJuIHR9LApUMTpmdW5jdGlvbihiMCl7dmFyIHQscyxy
-LHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYSxhMCxhMSxhMixhMyxhNCxhNSxhNixhNyxh
-OD1kb2N1bWVudCxhOT1hOC5xdWVyeVNlbGVjdG9yKCIuZWRpdC1wYW5lbCAucGFuZWwtY29udGVudCIp
-CkoubDUoYTksIiIpCmlmKGIwPT1udWxsKXthOD1hOC5jcmVhdGVFbGVtZW50KCJwIikKYTgudGV4dENv
-bnRlbnQ9IlNlZSBkZXRhaWxzIGFib3V0IGEgcHJvcG9zZWQgZWRpdC4iCkMuTHQuc0QoYTgsSC5WTShb
-InBsYWNlaG9sZGVyIl0sdS5zKSkKYTkuYXBwZW5kQ2hpbGQoYTgpCnJldHVybn10PWIwLmUKcz0kLm5V
-KCkKcj1zLnRNKHQpCnE9YjAuYwpwPXMuSFAodCxKLlQwKGE4LnF1ZXJ5U2VsZWN0b3IoIi5yb290Iiku
-dGV4dENvbnRlbnQpKQpvPWIwLmQKcz1hOC5jcmVhdGVFbGVtZW50KCJwIikKbj11LmgKbi5iKGE5LmFw
-cGVuZENoaWxkKHMpKS5hcHBlbmRDaGlsZChhOC5jcmVhdGVUZXh0Tm9kZShILmQocSkrIiBhdCAiK0gu
-ZChwKSsiOiIrSC5kKG8pKyIuIikpCnM9YjAuYQppZihzLmxlbmd0aCE9PTApe209YTguY3JlYXRlRWxl
-bWVudCgicCIpCm0udGV4dENvbnRlbnQ9IkVkaXQgcmF0aW9uYWxlOiIKYTkuYXBwZW5kQ2hpbGQobSkK
-bT1hOC5jcmVhdGVFbGVtZW50KCJ1bCIpCmw9bi5iKGE5LmFwcGVuZENoaWxkKG0pKQpmb3IobT1zLmxl
-bmd0aCxrPTA7azxzLmxlbmd0aDtzLmxlbmd0aD09PW18fCgwLEgubGspKHMpLCsrayl7aj1zW2tdCmk9
-YTguY3JlYXRlRWxlbWVudCgibGkiKQpoPWwuYXBwZW5kQ2hpbGQoaSkKaC5hcHBlbmRDaGlsZChhOC5j
-cmVhdGVUZXh0Tm9kZShqLmEpKQpnPWouYgppZihnIT1udWxsKXtoLmFwcGVuZENoaWxkKGE4LmNyZWF0
-ZVRleHROb2RlKCIgKCIpKQpoLmFwcGVuZENoaWxkKEwuYzQoZyxyKSkKaC5hcHBlbmRDaGlsZChhOC5j
-cmVhdGVUZXh0Tm9kZSgiKSIpKX19fXM9YjAuYgppZihzIT1udWxsKWZvcihtPXMubGVuZ3RoLGk9dS5z
-LGY9dS5YLGs9MDtrPHMubGVuZ3RoO3MubGVuZ3RoPT09bXx8KDAsSC5saykocyksKytrKXtlPXNba10K
-ZD1hOC5jcmVhdGVFbGVtZW50KCJwIikKYz1uLmIoYTkuYXBwZW5kQ2hpbGQoZCkpCmQ9YTguY3JlYXRl
-RWxlbWVudCgiYSIpCmI9bi5iKGMuYXBwZW5kQ2hpbGQoZCkpCmIuYXBwZW5kQ2hpbGQoYTguY3JlYXRl
-VGV4dE5vZGUoZS5hKSkKYi5zZXRBdHRyaWJ1dGUoImhyZWYiLGUuYikKZD1mLmIoSC5WTShbInBvc3Qt
-bGluayIsImJlZm9yZS1hcHBseSJdLGkpKQphPUouZFIoYikKYS5WMSgwKQphLkZWKDAsZCl9Zm9yKHM9
-YjAuZixuPXMubGVuZ3RoLG09dS5zLGk9dS5YLGs9MDtrPHMubGVuZ3RoO3MubGVuZ3RoPT09bnx8KDAs
-SC5saykocyksKytrKXthMD1zW2tdCmY9YTguY3JlYXRlRWxlbWVudCgicCIpCmQ9aS5iKEguVk0oWyJ0
-cmFjZSJdLG0pKQphPUouZFIoZikKYS5WMSgwKQphLkZWKDAsZCkKYTE9YTkuYXBwZW5kQ2hpbGQoZikK
-YTEuYXBwZW5kQ2hpbGQoYTguY3JlYXRlVGV4dE5vZGUoIk51bGxhYmlsaXR5IHRyYWNlIGZvcjogIikp
-CmY9YTguY3JlYXRlRWxlbWVudCgic3BhbiIpCmQ9aS5iKEguVk0oWyJ0eXBlLWRlc2NyaXB0aW9uIl0s
-bSkpCmE9Si5kUihmKQphLlYxKDApCmEuRlYoMCxkKQpmLmFwcGVuZENoaWxkKGE4LmNyZWF0ZVRleHRO
-b2RlKGEwLmEpKQphMS5hcHBlbmRDaGlsZChmKQpmPWE4LmNyZWF0ZUVsZW1lbnQoInVsIikKZD1pLmIo
-SC5WTShbInRyYWNlIl0sbSkpCmE9Si5kUihmKQphLlYxKDApCmEuRlYoMCxkKQphMj1hMS5hcHBlbmRD
-aGlsZChmKQpmb3IoZj1hMC5iLGQ9Zi5sZW5ndGgsYTM9MDthMzxmLmxlbmd0aDtmLmxlbmd0aD09PWR8
-fCgwLEgubGspKGYpLCsrYTMpe2E0PWZbYTNdCmE1PWE4LmNyZWF0ZUVsZW1lbnQoImxpIikKSi5sNShh
-NSwiJiN4Mjc0RjsgIikKYTY9YTIuYXBwZW5kQ2hpbGQoYTUpCmE1PWE4LmNyZWF0ZUVsZW1lbnQoInNw
-YW4iKQphNz1pLmIoSC5WTShbImZ1bmN0aW9uIl0sbSkpCmE9Si5kUihhNSkKYS5WMSgwKQphLkZWKDAs
-YTcpCmE3PWE0LmIKaWYoYTc9PW51bGwpYTc9InVua25vd24iCmE1LmFwcGVuZENoaWxkKGE4LmNyZWF0
-ZVRleHROb2RlKGE3KSkKYTYuYXBwZW5kQ2hpbGQoYTUpCmc9YTQuYwppZihnIT1udWxsKXthNi5hcHBl
-bmRDaGlsZChhOC5jcmVhdGVUZXh0Tm9kZSgiICgiKSkKYTYuYXBwZW5kQ2hpbGQoTC5jNChnLHIpKQph
-Ni5hcHBlbmRDaGlsZChhOC5jcmVhdGVUZXh0Tm9kZSgiKSIpKX1hNi5hcHBlbmRDaGlsZChhOC5jcmVh
-dGVUZXh0Tm9kZSgiOiAiKSkKYTYuYXBwZW5kQ2hpbGQoYTguY3JlYXRlVGV4dE5vZGUoYTQuYSkpfX19
-LApMSDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQ9ZG9j
-dW1lbnQsYz1kLnF1ZXJ5U2VsZWN0b3IoIi5lZGl0LWxpc3QgLnBhbmVsLWNvbnRlbnQiKQpKLmw1KGMs
-IiIpCnQ9ZC5jcmVhdGVFbGVtZW50KCJwIikKcz11LmgKcj1zLmIoYy5hcHBlbmRDaGlsZCh0KSkKdD1K
-LlU2KGIpCnE9dC5nQShiKQppZihxPT09MClyLmFwcGVuZENoaWxkKGQuY3JlYXRlVGV4dE5vZGUoIk5v
-IHByb3Bvc2VkIGVkaXRzIikpCmVsc2Ugci5hcHBlbmRDaGlsZChkLmNyZWF0ZVRleHROb2RlKCIiK3Er
-IiBwcm9wb3NlZCAiK0wuTHgocSwiZWRpdCIpKyI6IikpCnA9ZC5jcmVhdGVFbGVtZW50KCJ1bCIpCm89
-cy5iKGMuYXBwZW5kQ2hpbGQocCkpCmZvcih0PXQuZ2t6KGIpLHA9dS5rLG49dS5RLG09bi5DKCJ+KDEp
-IiksbD11Lk0sbj1uLmQsaz11LmE7dC5GKCk7KXtqPWsuYih0LmdsKCkpCmk9ZC5jcmVhdGVFbGVtZW50
-KCJsaSIpCmg9cy5iKG8uYXBwZW5kQ2hpbGQoaSkpCkouZFIoaCkuaSgwLCJlZGl0IikKaT1kLmNyZWF0
-ZUVsZW1lbnQoImEiKQpnPXAuYihoLmFwcGVuZENoaWxkKGkpKQpnLmNsYXNzTGlzdC5hZGQoImVkaXQt
-bGluayIpCmY9SC5TYyhqLnEoMCwib2Zmc2V0IikpCmk9SC5kKGYpCmcuc2V0QXR0cmlidXRlKCJkYXRh
-LSIrbmV3IFcuU3kobmV3IFcuaTcoZykpLk8oIm9mZnNldCIpLGkpCmU9SC5TYyhqLnEoMCwibGluZSIp
-KQppPUguZChlKQpnLnNldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KGcpKS5PKCJs
-aW5lIiksaSkKZy5hcHBlbmRDaGlsZChkLmNyZWF0ZVRleHROb2RlKCJsaW5lICIrSC5kKGUpKSkKaT1t
-LmIobmV3IEwuRUUoZixlLGEpKQpsLmIobnVsbCkKVy5KRShnLCJjbGljayIsaSwhMSxuKQpoLmFwcGVu
-ZENoaWxkKGQuY3JlYXRlVGV4dE5vZGUoIjogIitILmQoai5xKDAsImV4cGxhbmF0aW9uIikpKSl9TC5U
-MShudWxsKX0sCkZyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT13aW5kb3cubG9jYXRpb24scD1Q
-LmhLKChxJiZDLkV4KS5nRHIocSkrSC5kKGEpKQpxPXUuegp0PVAuRmwodS5OLHEpCmlmKGIhPW51bGwp
-dC5ZKDAsIm9mZnNldCIsSC5kKGIpKQppZihjIT1udWxsKXQuWSgwLCJsaW5lIixILmQoYykpCnA9cC5u
-bSgwLHQuYT09PTA/bnVsbDp0KQpzPXdpbmRvdy5oaXN0b3J5CnI9cC53KDApCnMudG9TdHJpbmcKcy5w
-dXNoU3RhdGUobmV3IFAuQmYoW10sW10pLlB2KFAuRmwocSxxKSksIiIscil9LApFbjpmdW5jdGlvbihh
-KXt2YXIgdD1KLmJiKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENvbnRlbnQsIi8i
-KQppZihDLnhCLm4oYSx0KSlyZXR1cm4gQy54Qi5HKGEsdC5sZW5ndGgpCmVsc2UgcmV0dXJuIGF9LApC
-WDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj17fQpyLmE9YQphPUwuRW4oYSkKci5hPWEKdD1kb2N1bWVu
-dAp0LnF1ZXJ5U2VsZWN0b3IoIiN1bml0LW5hbWUiKS50ZXh0Q29udGVudD1hCnM9dS5oCkguRGgocyxz
-LCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnQ9bmV3IFcud3oodC5xdWVyeVNlbGVjdG9yQWxsKCIubmF2
-LXBhbmVsIC5uYXYtbGluayIpLHUuUykKdC5LKHQsbmV3IEwuVlMocikpfSwKQkU6ZnVuY3Rpb24oYSxi
-KXt2YXIgdD0iLnJlZ2lvbnMiLHM9ZG9jdW1lbnQscj1zLnF1ZXJ5U2VsZWN0b3IodCkscT1zLnF1ZXJ5
-U2VsZWN0b3IoIi5jb2RlIikKSi50SChyLEgueShiLnEoMCwicmVnaW9ucyIpKSwkLktHKCkpCkoudEgo
-cSxILnkoYi5xKDAsIm5hdmlnYXRpb25Db250ZW50IikpLCQuS0coKSkKTC5MSChhLHUuai5iKGIucSgw
-LCJlZGl0cyIpKSkKTC52VSgpCkwueVgoIi5jb2RlIikKTC55WCh0KX0sCnRYOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaj0ibmFtZSIsaT1kb2N1bWVudCxoPWkuY3JlYXRlRWxlbWVu
-dCgidWwiKSxnPXUuaCxmPWcuYihhLmFwcGVuZENoaWxkKGgpKQpmb3IoaD1KLklUKHUuUi5iKGIpKSx0
-PXUuTTtoLkYoKTspe3M9aC5nbCgpCnI9aS5jcmVhdGVFbGVtZW50KCJsaSIpCnE9Zy5iKGYuYXBwZW5k
-Q2hpbGQocikpCnI9Si5VNihzKQpwPUouUkUocSkKaWYoSi5STShyLnEocywidHlwZSIpLCJkaXJlY3Rv
-cnkiKSl7cC5nRChxKS5pKDAsImRpciIpCnA9aS5jcmVhdGVFbGVtZW50KCJzcGFuIikKbz1nLmIocS5h
-cHBlbmRDaGlsZChwKSkKcD1KLlJFKG8pCnAuZ0QobykuaSgwLCJhcnJvdyIpCnAuc2hmKG8sIiYjeDI1
-QkM7IikKcD1pLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpKLmw1KGcuYihxLmFwcGVuZENoaWxkKHApKSwi
-JiN4MUY0QzE7IikKcS5hcHBlbmRDaGlsZChpLmNyZWF0ZVRleHROb2RlKEgueShyLnEocyxqKSkpKQpM
-LnRYKHEsci5xKHMsInN1YnRyZWUiKSkKTC5reihvKX1lbHNle3Auc2hmKHEsIiYjeDFGNEM0OyIpCnA9
-aS5jcmVhdGVFbGVtZW50KCJhIikKbj1nLmIocS5hcHBlbmRDaGlsZChwKSkKcD1KLlJFKG4pCnAuZ0Qo
-bikuaSgwLCJuYXYtbGluayIpCm09SC55KHIucShzLCJwYXRoIikpCm4uc2V0QXR0cmlidXRlKCJkYXRh
-LSIrbmV3IFcuU3kobmV3IFcuaTcobikpLk8oaiksbSkKbi5zZXRBdHRyaWJ1dGUoImhyZWYiLEgueShy
-LnEocywiaHJlZiIpKSkKbi5hcHBlbmRDaGlsZChpLmNyZWF0ZVRleHROb2RlKEgueShyLnEocyxqKSkp
-KQpwPXAuZ1ZsKG4pCm09cC4kdGkKbS5DKCJ+KDEpIikuYihMLlhOKCkpCnQuYihudWxsKQpXLkpFKHAu
-YSxwLmIsTC5YTigpLCExLG0uZCkKbD1ILlNjKHIucShzLCJlZGl0Q291bnQiKSkKaWYodHlwZW9mIGwh
-PT0ibnVtYmVyIilyZXR1cm4gbC5vcygpCmlmKGw+MCl7cj1pLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpr
-PWcuYihxLmFwcGVuZENoaWxkKHIpKQpKLmRSKGspLmkoMCwiZWRpdC1jb3VudCIpCnI9IiIrbCsiICIK
-aWYobD09PTEpcD0iZWRpdCIKZWxzZSBwPSJlZGl0cyIKay5zZXRBdHRyaWJ1dGUoInRpdGxlIixyK3Ap
-CmsuYXBwZW5kQ2hpbGQoaS5jcmVhdGVUZXh0Tm9kZShDLmpuLncobCkpKX19fX0sCmM0OmZ1bmN0aW9u
-KGEsYil7dmFyIHQ9ZG9jdW1lbnQscz10LmNyZWF0ZUVsZW1lbnQoImEiKQp1LmsuYihzKQpzLmFwcGVu
-ZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUoSC5kKGEuYykrIjoiK0guZChhLmIpKSkKdD1ELm5yKGIsYS5h
-KQpzLnNldEF0dHJpYnV0ZSgiaHJlZiIsJC5uVSgpLm81KHQpKQpzLmNsYXNzTGlzdC5hZGQoIm5hdi1s
-aW5rIikKcmV0dXJuIHN9LAplOmZ1bmN0aW9uIGUoKXt9LApWVzpmdW5jdGlvbiBWVyhhLGIsYyl7dGhp
-cy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApvWjpmdW5jdGlvbiBvWigpe30sCmpyOmZ1bmN0aW9uIGpy
-KCl7fSwKcWw6ZnVuY3Rpb24gcWwoKXt9LApMOmZ1bmN0aW9uIEwoKXt9LApXeDpmdW5jdGlvbiBXeChh
-LGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQU86ZnVuY3Rpb24gQU8oKXt9LApkTjpmdW5jdGlvbiBkTigp
-e30sCkhvOmZ1bmN0aW9uIEhvKGEpe3RoaXMuYT1hfSwKeHo6ZnVuY3Rpb24geHooYSxiKXt0aGlzLmE9
-YQp0aGlzLmI9Yn0sCklDOmZ1bmN0aW9uIElDKCl7fSwKTDE6ZnVuY3Rpb24gTDEoKXt9LApuVDpmdW5j
-dGlvbiBuVChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApCWjpmdW5jdGlvbiBCWihh
-KXt0aGlzLmE9YX0sCkZROmZ1bmN0aW9uIEZRKGEpe3RoaXMuYT1hfSwKR0g6ZnVuY3Rpb24gR0goKXt9
-LApEVDpmdW5jdGlvbiBEVCgpe30sCmVIOmZ1bmN0aW9uIGVIKGEpe3RoaXMuYT1hfSwKekQ6ZnVuY3Rp
-b24gekQoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCk9FOmZ1bmN0
-aW9uIE9FKGEpe3RoaXMuYT1hfSwKVFc6ZnVuY3Rpb24gVFcoKXt9LAp4cjpmdW5jdGlvbiB4cihhKXt0
-aGlzLmE9YX0sCkVFOmZ1bmN0aW9uIEVFKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30s
-ClFMOmZ1bmN0aW9uIFFMKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApWUzpmdW5jdGlvbiBWUyhhKXt0
-aGlzLmE9YX0sClhBOmZ1bmN0aW9uIFhBKCl7fSwKSVY6ZnVuY3Rpb24gSVYoYSxiLGMsZCl7dmFyIF89
-dGhpcwpfLmQ9YQpfLmU9YgpfLmY9YwpfLnI9ZH19LE09ewpZRjpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
-cixxLHAsbyxuCmZvcih0PWIubGVuZ3RoLHM9MTtzPHQ7KytzKXtpZihiW3NdPT1udWxsfHxiW3MtMV0h
-PW51bGwpY29udGludWUKZm9yKDt0Pj0xO3Q9cil7cj10LTEKaWYoYltyXSE9bnVsbClicmVha31xPW5l
-dyBQLlJuKCIiKQpwPWErIigiCnEuYT1wCm89SC5xQyhiLDAsdCxILnQ2KGIpLmQpCm49by4kdGkKbj1w
-K25ldyBILkE4KG8sbi5DKCJxVShhTC5FKSIpLmIobmV3IE0uTm8oKSksbi5DKCJBODxhTC5FLHFVPiIp
-KS5IKDAsIiwgIikKcS5hPW4KcS5hPW4rKCIpOiBwYXJ0ICIrKHMtMSkrIiB3YXMgbnVsbCwgYnV0IHBh
-cnQgIitzKyIgd2FzIG5vdC4iKQp0aHJvdyBILmIoUC54WShxLncoMCkpKX19LApsSTpmdW5jdGlvbiBs
-SShhKXt0aGlzLmE9YX0sCk1pOmZ1bmN0aW9uIE1pKCl7fSwKcTc6ZnVuY3Rpb24gcTcoKXt9LApObzpm
-dW5jdGlvbiBObygpe319LEI9e0x1OmZ1bmN0aW9uIEx1KCl7fSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHQK
-aWYoIShhPj02NSYmYTw9OTApKXQ9YT49OTcmJmE8PTEyMgplbHNlIHQ9ITAKcmV0dXJuIHR9LApZdTpm
-dW5jdGlvbihhLGIpe3ZhciB0PWEubGVuZ3RoLHM9YisyCmlmKHQ8cylyZXR1cm4hMQppZighQi5PUyhD
-LnhCLm0oYSxiKSkpcmV0dXJuITEKaWYoQy54Qi5tKGEsYisxKSE9PTU4KXJldHVybiExCmlmKHQ9PT1z
-KXJldHVybiEwCnJldHVybiBDLnhCLm0oYSxzKT09PTQ3fX0sWD17CkNMOmZ1bmN0aW9uKGEsYil7dmFy
-IHQscyxyLHEscCxvPWIueFooYSkKYi5oSyhhKQppZihvIT1udWxsKWE9Si5LVihhLG8ubGVuZ3RoKQp0
-PXUucwpzPUguVk0oW10sdCkKcj1ILlZNKFtdLHQpCnQ9YS5sZW5ndGgKaWYodCE9PTAmJmIucjQoQy54
-Qi5XKGEsMCkpKXtpZigwPj10KXJldHVybiBILk9IKGEsMCkKQy5ObS5pKHIsYVswXSkKcT0xfWVsc2V7
-Qy5ObS5pKHIsIiIpCnE9MH1mb3IocD1xO3A8dDsrK3ApaWYoYi5yNChDLnhCLlcoYSxwKSkpe0MuTm0u
-aShzLEMueEIuTmooYSxxLHApKQpDLk5tLmkocixhW3BdKQpxPXArMX1pZihxPHQpe0MuTm0uaShzLEMu
-eEIuRyhhLHEpKQpDLk5tLmkociwiIil9cmV0dXJuIG5ldyBYLldEKGIsbyxzLHIpfSwKV0Q6ZnVuY3Rp
-b24gV0QoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9YwpfLmU9ZH0sCnFSOmZ1bmN0
-aW9uIHFSKGEpe3RoaXMuYT1hfSwKSlQ6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBYLmR2KGEpfSwKZHY6
-ZnVuY3Rpb24gZHYoYSl7dGhpcy5hPWF9fSxPPXsKUmg6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8s
-bixtLGwsayxqLGk9bnVsbAppZihQLnVvKCkuZ0ZpKCkhPT0iZmlsZSIpcmV0dXJuICQuRWIoKQp0PVAu
-dW8oKQppZighQy54Qi5UYyh0LmdJaSh0KSwiLyIpKXJldHVybiAkLkViKCkKcz1QLlBpKGksMCwwKQpy
-PVAuelIoaSwwLDApCnE9UC5PZShpLDAsMCwhMSkKcD1QLmxlKGksMCwwLGkpCm89UC50RyhpLDAsMCkK
-bj1QLndCKGkscykKbT1zPT09ImZpbGUiCmlmKHE9PW51bGwpdD1yLmxlbmd0aCE9PTB8fG4hPW51bGx8
-fG0KZWxzZSB0PSExCmlmKHQpcT0iIgp0PXE9PW51bGwKbD0hdAprPVAua2EoImEvYiIsMCwzLGkscyxs
-KQpqPXMubGVuZ3RoPT09MAppZihqJiZ0JiYhQy54Qi5uKGssIi8iKSlrPVAud0Yoaywhanx8bCkKZWxz
-ZSBrPVAueGUoaykKaWYobmV3IFAuRG4ocyxyLHQmJkMueEIubihrLCIvLyIpPyIiOnEsbixrLHAsbyku
-dDQoKT09PSJhXFxiIilyZXR1cm4gJC5LaygpCnJldHVybiAkLmJEKCl9LAp6TDpmdW5jdGlvbiB6TCgp
-e319LEU9e09GOmZ1bmN0aW9uIE9GKGEsYixjKXt0aGlzLmQ9YQp0aGlzLmU9Ygp0aGlzLmY9Y319LEY9
-e3J1OmZ1bmN0aW9uIHJ1KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5kPWEKXy5lPWIKXy5mPWMKXy5yPWR9
-fSxEPXsKUlg6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9UC51bygpCmlmKEouUk0ociwkLkk2KSlyZXR1cm4g
-JC5GZgokLkk2PXIKaWYoJC5IaygpPT0kLkViKCkpcmV0dXJuICQuRmY9ci5aSSgiLiIpLncoMCkKZWxz
-ZXt0PXIudDQoKQpzPXQubGVuZ3RoLTEKcmV0dXJuICQuRmY9cz09PTA/dDpDLnhCLk5qKHQsMCxzKX19
-LApucjpmdW5jdGlvbihhLGIpe3ZhciB0PW51bGwKcmV0dXJuICQublUoKS5xNygwLGEsYix0LHQsdCx0
-LHQsdCl9fQp2YXIgdz1bQyxILEosUCxXLFUsVCxMLE0sQixYLE8sRSxGLERdCmh1bmtIZWxwZXJzLnNl
-dEZ1bmN0aW9uTmFtZXNJZk5lY2Vzc2FyeSh3KQp2YXIgJD17fQpILmVvLnByb3RvdHlwZT17fQpKLnZC
-LnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9PT1ifSwKZ2lPOmZ1bmN0aW9uKGEp
-e3JldHVybiBILmVRKGEpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5kKEgu
-TShhKSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt1Lm8uYihiKQp0aHJvdyBILmIoUC5scihhLGIuZ1dh
-KCksYi5nbmQoKSxiLmdWbSgpKSl9fQpKLnlFLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJu
-IFN0cmluZyhhKX0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gYT81MTkwMTg6MjE4MTU5fSwKJGlhMjox
-fQpKLllFLnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG51bGw9PWJ9LAp3OmZ1bmN0
-aW9uKGEpe3JldHVybiJudWxsIn0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gMH0sCmU3OmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIHRoaXMuU2ooYSx1Lm8uYihiKSl9LAokaWM4OjF9CkouTUYucHJvdG90eXBlPXsK
-Z2lPOmZ1bmN0aW9uKGEpe3JldHVybiAwfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwK
-JGl2bToxfQpKLmlDLnByb3RvdHlwZT17fQpKLmtkLnByb3RvdHlwZT17fQpKLmM1LnByb3RvdHlwZT17
-Cnc6ZnVuY3Rpb24oYSl7dmFyIHQ9YVskLncoKV0KaWYodD09bnVsbClyZXR1cm4gdGhpcy50KGEpCnJl
-dHVybiJKYXZhU2NyaXB0IGZ1bmN0aW9uIGZvciAiK0guZChKLmoodCkpfSwKJFM6ZnVuY3Rpb24oKXty
-ZXR1cm57ZnVuYzoxLG9wdDpbLCwsLCwsLCwsLCwsLCwsLF19fSwKJGlFSDoxfQpKLmpkLnByb3RvdHlw
-ZT17Cmk6ZnVuY3Rpb24oYSxiKXtILnQ2KGEpLmQuYihiKQppZighIWEuZml4ZWQkbGVuZ3RoKUgudmgo
-UC5MNCgiYWRkIikpCmEucHVzaChiKX0sClc0OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoISFhLmZpeGVk
-JGxlbmd0aClILnZoKFAuTDQoInJlbW92ZUF0IikpCnQ9YS5sZW5ndGgKaWYoYj49dCl0aHJvdyBILmIo
-UC54KGIsbnVsbCkpCnJldHVybiBhLnNwbGljZShiLDEpWzBdfSwKVUc6ZnVuY3Rpb24oYSxiLGMpe3Zh
-ciB0LHMscgpILnQ2KGEpLkMoImNYPDE+IikuYihjKQppZighIWEuZml4ZWQkbGVuZ3RoKUgudmgoUC5M
-NCgiaW5zZXJ0QWxsIikpCnQ9YS5sZW5ndGgKUC53QShiLDAsdCwiaW5kZXgiKQpzPWMubGVuZ3RoCnRo
-aXMuc0EoYSx0K3MpCnI9YitzCnRoaXMuWVcoYSxyLGEubGVuZ3RoLGEsYikKdGhpcy52ZyhhLGIscixj
-KX0sCm12OmZ1bmN0aW9uKGEpe2lmKCEhYS5maXhlZCRsZW5ndGgpSC52aChQLkw0KCJyZW1vdmVMYXN0
-IikpCmlmKGEubGVuZ3RoPT09MCl0aHJvdyBILmIoSC5IWShhLC0xKSkKcmV0dXJuIGEucG9wKCl9LApG
-VjpmdW5jdGlvbihhLGIpe3ZhciB0CkgudDYoYSkuQygiY1g8MT4iKS5iKGIpCmlmKCEhYS5maXhlZCRs
-ZW5ndGgpSC52aChQLkw0KCJhZGRBbGwiKSkKZm9yKHQ9Si5JVChiKTt0LkYoKTspYS5wdXNoKHQuZ2wo
-KSl9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILnQ2KGEpLkMoIn4oMSkiKS5iKGIpCnQ9YS5sZW5n
-dGgKZm9yKHM9MDtzPHQ7KytzKXtiLiQxKGFbc10pCmlmKGEubGVuZ3RoIT09dCl0aHJvdyBILmIoUC5h
-NChhKSl9fSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUgudDYoYSkKcmV0dXJuIG5ldyBILkE4KGEs
-dC5LcShjKS5DKCIxKDIpIikuYihiKSx0LkMoIkA8MT4iKS5LcShjKS5DKCJBODwxLDI+IikpfSwKSDpm
-dW5jdGlvbihhLGIpe3ZhciB0LHM9bmV3IEFycmF5KGEubGVuZ3RoKQpzLmZpeGVkJGxlbmd0aD1BcnJh
-eQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KXRoaXMuWShzLHQsSC5kKGFbdF0pKQpyZXR1cm4gcy5qb2lu
-KGIpfSwKTjA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyCmQuYihiKQpILnQ2KGEpLktxKGQpLkMo
-IjEoMSwyKSIpLmIoYykKdD1hLmxlbmd0aApmb3Iocz1iLHI9MDtyPHQ7KytyKXtzPWMuJDIocyxhW3Jd
-KQppZihhLmxlbmd0aCE9PXQpdGhyb3cgSC5iKFAuYTQoYSkpfXJldHVybiBzfSwKRTpmdW5jdGlvbihh
-LGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCmFNOmZ1
-bmN0aW9uKGEsYixjKXtpZihiPDB8fGI+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUoYiwwLGEubGVuZ3Ro
-LCJzdGFydCIsbnVsbCkpCmlmKGM8Ynx8Yz5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShjLGIsYS5sZW5n
-dGgsImVuZCIsbnVsbCkpCmlmKGI9PT1jKXJldHVybiBILlZNKFtdLEgudDYoYSkpCnJldHVybiBILlZN
-KGEuc2xpY2UoYixjKSxILnQ2KGEpKX0sCmdyWjpmdW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aAppZih0
-PjApcmV0dXJuIGFbdC0xXQp0aHJvdyBILmIoSC5XcCgpKX0sCllXOmZ1bmN0aW9uKGEsYixjLGQsZSl7
-dmFyIHQscyxyPUgudDYoYSkKci5DKCJjWDwxPiIpLmIoZCkKaWYoISFhLmltbXV0YWJsZSRsaXN0KUgu
-dmgoUC5MNCgic2V0UmFuZ2UiKSkKUC5qQihiLGMsYS5sZW5ndGgpCnQ9Yy1iCmlmKHQ9PT0wKXJldHVy
-bgpQLmsxKGUsInNraXBDb3VudCIpCnIuQygiek08MT4iKS5iKGQpCnI9Si5VNihkKQppZihlK3Q+ci5n
-QShkKSl0aHJvdyBILmIoSC5hcigpKQppZihlPGIpZm9yKHM9dC0xO3M+PTA7LS1zKWFbYitzXT1yLnEo
-ZCxlK3MpCmVsc2UgZm9yKHM9MDtzPHQ7KytzKWFbYitzXT1yLnEoZCxlK3MpfSwKdmc6ZnVuY3Rpb24o
-YSxiLGMsZCl7cmV0dXJuIHRoaXMuWVcoYSxiLGMsZCwwKX0sClZyOmZ1bmN0aW9uKGEsYil7dmFyIHQs
-cwpILnQ2KGEpLkMoImEyKDEpIikuYihiKQp0PWEubGVuZ3RoCmZvcihzPTA7czx0Oysrcyl7aWYoSC5v
-VChiLiQxKGFbc10pKSlyZXR1cm4hMAppZihhLmxlbmd0aCE9PXQpdGhyb3cgSC5iKFAuYTQoYSkpfXJl
-dHVybiExfSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KWlmKEou
-Uk0oYVt0XSxiKSlyZXR1cm4hMApyZXR1cm4hMX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UoYSwi
-WyIsIl0iKX0sCmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEoubTEoYSxhLmxlbmd0aCxILnQ2KGEp
-LkMoIm0xPDE+IikpfSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBILmVRKGEpfSwKZ0E6ZnVuY3Rpb24o
-YSl7cmV0dXJuIGEubGVuZ3RofSwKc0E6ZnVuY3Rpb24oYSxiKXtpZighIWEuZml4ZWQkbGVuZ3RoKUgu
-dmgoUC5MNCgic2V0IGxlbmd0aCIpKQppZihiPDApdGhyb3cgSC5iKFAuVEUoYiwwLG51bGwsIm5ld0xl
-bmd0aCIsbnVsbCkpCmEubGVuZ3RoPWJ9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj1hLmxl
-bmd0aHx8YjwwKXRocm93IEguYihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIs
-Yyl7SC50NihhKS5kLmIoYykKaWYoISFhLmltbXV0YWJsZSRsaXN0KUgudmgoUC5MNCgiaW5kZXhlZCBz
-ZXQiKSkKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQphW2JdPWN9LAokaWNY
-OjEsCiRpek06MX0KSi5Qby5wcm90b3R5cGU9e30KSi5tMS5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigp
-e3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLHI9cy5hLHE9ci5sZW5ndGgK
-aWYocy5iIT09cSl0aHJvdyBILmIoSC5sayhyKSkKdD1zLmMKaWYodD49cSl7cy5zTShudWxsKQpyZXR1
-cm4hMX1zLnNNKHJbdF0pOysrcy5jCnJldHVybiEwfSwKc006ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMu
-JHRpLmQuYihhKX0sCiRpQW46MX0KSi5xSS5wcm90b3R5cGU9ewp5dTpmdW5jdGlvbihhKXt2YXIgdApp
-ZihhPj0tMjE0NzQ4MzY0OCYmYTw9MjE0NzQ4MzY0NylyZXR1cm4gYXwwCmlmKGlzRmluaXRlKGEpKXt0
-PWE8MD9NYXRoLmNlaWwoYSk6TWF0aC5mbG9vcihhKQpyZXR1cm4gdCswfXRocm93IEguYihQLkw0KCIi
-K2ErIi50b0ludCgpIikpfSwKelE6ZnVuY3Rpb24oYSl7aWYoYT4wKXtpZihhIT09MS8wKXJldHVybiBN
-YXRoLnJvdW5kKGEpfWVsc2UgaWYoYT4tMS8wKXJldHVybiAwLU1hdGgucm91bmQoMC1hKQp0aHJvdyBI
-LmIoUC5MNCgiIithKyIucm91bmQoKSIpKX0sCldaOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKaWYo
-YjwyfHxiPjM2KXRocm93IEguYihQLlRFKGIsMiwzNiwicmFkaXgiLG51bGwpKQp0PWEudG9TdHJpbmco
-YikKaWYoQy54Qi5tKHQsdC5sZW5ndGgtMSkhPT00MSlyZXR1cm4gdApzPS9eKFtcZGEtel0rKSg/Olwu
-KFtcZGEtel0rKSk/XChlXCsoXGQrKVwpJC8uZXhlYyh0KQppZihzPT1udWxsKUgudmgoUC5MNCgiVW5l
-eHBlY3RlZCB0b1N0cmluZyByZXN1bHQ6ICIrdCkpCnI9cy5sZW5ndGgKaWYoMT49cilyZXR1cm4gSC5P
-SChzLDEpCnQ9c1sxXQppZigzPj1yKXJldHVybiBILk9IKHMsMykKcT0rc1szXQpyPXNbMl0KaWYociE9
-bnVsbCl7dCs9cgpxLT1yLmxlbmd0aH1yZXR1cm4gdCtDLnhCLkl4KCIwIixxKX0sCnc6ZnVuY3Rpb24o
-YSl7aWYoYT09PTAmJjEvYTwwKXJldHVybiItMC4wIgplbHNlIHJldHVybiIiK2F9LApnaU86ZnVuY3Rp
-b24oYSl7dmFyIHQscyxyLHEscD1hfDAKaWYoYT09PXApcmV0dXJuIDUzNjg3MDkxMSZwCnQ9TWF0aC5h
-YnMoYSkKcz1NYXRoLmxvZyh0KS8wLjY5MzE0NzE4MDU1OTk0NTN8MApyPU1hdGgucG93KDIscykKcT10
-PDE/dC9yOnIvdApyZXR1cm4gNTM2ODcwOTExJigocSo5MDA3MTk5MjU0NzQwOTkyfDApKyhxKjM1NDIy
-NDMxODExNzY1MjF8MCkpKjU5OTE5NytzKjEyNTl9LAp6WTpmdW5jdGlvbihhLGIpe3ZhciB0PWElYgpp
-Zih0PT09MClyZXR1cm4gMAppZih0PjApcmV0dXJuIHQKaWYoYjwwKXJldHVybiB0LWIKZWxzZSByZXR1
-cm4gdCtifSwKd0c6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihhPjApdD10aGlzLnAzKGEsYikKZWxzZXt0
-PWI+MzE/MzE6Ygp0PWE+PnQ+Pj4wfXJldHVybiB0fSwKYmY6ZnVuY3Rpb24oYSxiKXtpZihiPDApdGhy
-b3cgSC5iKEgudEwoYikpCnJldHVybiB0aGlzLnAzKGEsYil9LApwMzpmdW5jdGlvbihhLGIpe3JldHVy
-biBiPjMxPzA6YT4+PmJ9LAokaUNQOjEsCiRpRks6MX0KSi51ci5wcm90b3R5cGU9eyRpS046MX0KSi5W
-QS5wcm90b3R5cGU9e30KSi5Eci5wcm90b3R5cGU9ewptOmZ1bmN0aW9uKGEsYil7aWYoYjwwKXRocm93
-IEguYihILkhZKGEsYikpCmlmKGI+PWEubGVuZ3RoKUgudmgoSC5IWShhLGIpKQpyZXR1cm4gYS5jaGFy
-Q29kZUF0KGIpfSwKVzpmdW5jdGlvbihhLGIpe2lmKGI+PWEubGVuZ3RoKXRocm93IEguYihILkhZKGEs
-YikpCnJldHVybiBhLmNoYXJDb2RlQXQoYil9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC51
-bihiLGEsMCl9LApoOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGIhPSJzdHJpbmciKXRocm93IEguYihQ
-LkwzKGIsbnVsbCxudWxsKSkKcmV0dXJuIGErYn0sClRjOmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5sZW5n
-dGgscz1hLmxlbmd0aAppZih0PnMpcmV0dXJuITEKcmV0dXJuIGI9PT10aGlzLkcoYSxzLXQpfSwKaTc6
-ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscwpjPVAuakIoYixjLGEubGVuZ3RoKQp0PWEuc3Vic3RyaW5n
-KDAsYikKcz1hLnN1YnN0cmluZyhjKQpyZXR1cm4gdCtkK3N9LApRaTpmdW5jdGlvbihhLGIsYyl7dmFy
-IHQKaWYoIUgub2soYykpSC52aChILnRMKGMpKQppZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBj
-LkooKQppZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUoYywwLGEubGVuZ3RoLG51bGwsbnVs
-bCkpCnQ9YytiLmxlbmd0aAppZih0PmEubGVuZ3RoKXJldHVybiExCnJldHVybiBiPT09YS5zdWJzdHJp
-bmcoYyx0KX0sCm46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5RaShhLGIsMCl9LApOajpmdW5jdGlv
-bihhLGIsYyl7aWYoIUgub2soYikpSC52aChILnRMKGIpKQppZihjPT1udWxsKWM9YS5sZW5ndGgKaWYo
-dHlwZW9mIGIhPT0ibnVtYmVyIilyZXR1cm4gYi5KKCkKaWYoYjwwKXRocm93IEguYihQLngoYixudWxs
-KSkKaWYoYj5jKXRocm93IEguYihQLngoYixudWxsKSkKaWYoYz5hLmxlbmd0aCl0aHJvdyBILmIoUC54
-KGMsbnVsbCkpCnJldHVybiBhLnN1YnN0cmluZyhiLGMpfSwKRzpmdW5jdGlvbihhLGIpe3JldHVybiB0
-aGlzLk5qKGEsYixudWxsKX0sCmhjOmZ1bmN0aW9uKGEpe3JldHVybiBhLnRvTG93ZXJDYXNlKCl9LApi
-UzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLnRyaW0oKSxwPXEubGVuZ3RoCmlmKHA9PT0wKXJldHVy
-biBxCmlmKHRoaXMuVyhxLDApPT09MTMzKXt0PUoubW0ocSwxKQppZih0PT09cClyZXR1cm4iIn1lbHNl
-IHQ9MApzPXAtMQpyPXRoaXMubShxLHMpPT09MTMzP0ouYzEocSxzKTpwCmlmKHQ9PT0wJiZyPT09cCly
-ZXR1cm4gcQpyZXR1cm4gcS5zdWJzdHJpbmcodCxyKX0sCkl4OmZ1bmN0aW9uKGEsYil7dmFyIHQscwpp
-ZigwPj1iKXJldHVybiIiCmlmKGI9PT0xfHxhLmxlbmd0aD09PTApcmV0dXJuIGEKaWYoYiE9PWI+Pj4w
-KXRocm93IEguYihDLkVxKQpmb3IodD1hLHM9IiI7ITA7KXtpZigoYiYxKT09PTEpcz10K3MKYj1iPj4+
-MQppZihiPT09MClicmVhawp0Kz10fXJldHVybiBzfSwKWFU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0Cmlm
-KGM8MHx8Yz5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKdD1h
-LmluZGV4T2YoYixjKQpyZXR1cm4gdH0sCk9ZOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuWFUoYSxi
-LDApfSwKUGs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoYz09bnVsbCljPWEubGVuZ3RoCmVsc2Ug
-aWYoYzwwfHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxudWxsLG51bGwpKQp0
-PWIubGVuZ3RoCnM9YS5sZW5ndGgKaWYoYyt0PnMpYz1zLXQKcmV0dXJuIGEubGFzdEluZGV4T2YoYixj
-KX0sCmNuOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuUGsoYSxiLG51bGwpfSwKSXM6ZnVuY3Rpb24o
-YSxiLGMpe3ZhciB0PWEubGVuZ3RoCmlmKGM+dCl0aHJvdyBILmIoUC5URShjLDAsdCxudWxsLG51bGwp
-KQpyZXR1cm4gSC5tMihhLGIsYyl9LAp0ZzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLklzKGEsYiww
-KX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGF9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQscyxyCmZvcih0
-PWEubGVuZ3RoLHM9MCxyPTA7cjx0Oysrcil7cz01MzY4NzA5MTEmcythLmNoYXJDb2RlQXQocikKcz01
-MzY4NzA5MTEmcysoKDUyNDI4NyZzKTw8MTApCnNePXM+PjZ9cz01MzY4NzA5MTEmcysoKDY3MTA4ODYz
-JnMpPDwzKQpzXj1zPj4xMQpyZXR1cm4gNTM2ODcwOTExJnMrKCgxNjM4MyZzKTw8MTUpfSwKZ0E6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKaWYoYj49YS5s
-ZW5ndGh8fCExKXRocm93IEguYihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKJGl2WDoxLAokaXFVOjF9
-CkgucWoucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1
-bmN0aW9uKGEsYil7cmV0dXJuIEMueEIubSh0aGlzLmEsSC5TYyhiKSl9fQpILmJRLnByb3RvdHlwZT17
-fQpILmFMLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzCnJldHVybiBuZXcgSC5h
-Nyh0LHQuZ0EodCksSC5MaCh0KS5DKCJhNzxhTC5FPiIpKX0sCkg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
-LHIscT10aGlzLHA9cS5nQShxKQppZihiLmxlbmd0aCE9PTApe2lmKHA9PT0wKXJldHVybiIiCnQ9SC5k
-KHEuRSgwLDApKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSkKZm9yKHM9dCxyPTE7cjxw
-Oysrcil7cz1zK2IrSC5kKHEuRSgwLHIpKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSl9
-cmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9ZWxzZXtmb3Iocj0wLHM9IiI7cjxwOysrcil7cys9
-SC5kKHEuRSgwLHIpKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSl9cmV0dXJuIHMuY2hh
-ckNvZGVBdCgwKT09MD9zOnN9fSwKZXY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5HRygwLEguTGgo
-dGhpcykuQygiYTIoYUwuRSkiKS5iKGIpKX19CkgubkgucHJvdG90eXBlPXsKZ1VEOmZ1bmN0aW9uKCl7
-dmFyIHQ9Si5IbSh0aGlzLmEpLHM9dGhpcy5jCmlmKHM9PW51bGx8fHM+dClyZXR1cm4gdApyZXR1cm4g
-c30sCmdBczpmdW5jdGlvbigpe3ZhciB0PUouSG0odGhpcy5hKSxzPXRoaXMuYgppZihzPnQpcmV0dXJu
-IHQKcmV0dXJuIHN9LApnQTpmdW5jdGlvbihhKXt2YXIgdCxzPUouSG0odGhpcy5hKSxyPXRoaXMuYgpp
-ZihyPj1zKXJldHVybiAwCnQ9dGhpcy5jCmlmKHQ9PW51bGx8fHQ+PXMpcmV0dXJuIHMtcgppZih0eXBl
-b2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkhOKCkKcmV0dXJuIHQtcn0sCkU6ZnVuY3Rpb24oYSxiKXt2
-YXIgdCxzPXRoaXMscj1zLmdBcygpK2IKaWYoYj49MCl7dD1zLmdVRCgpCmlmKHR5cGVvZiB0IT09Im51
-bWJlciIpcmV0dXJuIEgucFkodCkKdD1yPj10fWVsc2UgdD0hMAppZih0KXRocm93IEguYihQLkNmKGIs
-cywiaW5kZXgiLG51bGwsbnVsbCkpCnJldHVybiBKLkdBKHMuYSxyKX19CkguYTcucHJvdG90eXBlPXsK
-Z2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcyxyPXMu
-YSxxPUouVTYocikscD1xLmdBKHIpCmlmKHMuYiE9PXApdGhyb3cgSC5iKFAuYTQocikpCnQ9cy5jCmlm
-KHQ+PXApe3Muc0kobnVsbCkKcmV0dXJuITF9cy5zSShxLkUocix0KSk7KytzLmMKcmV0dXJuITB9LApz
-STpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlBbjoxfQpILkE4LnByb3RvdHlw
-ZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBKLkhtKHRoaXMuYSl9LApFOmZ1bmN0aW9uKGEsYil7cmV0
-dXJuIHRoaXMuYi4kMShKLkdBKHRoaXMuYSxiKSl9fQpILlU1LnByb3RvdHlwZT17CmdrejpmdW5jdGlv
-bihhKXtyZXR1cm4gbmV3IEguU08oSi5JVCh0aGlzLmEpLHRoaXMuYix0aGlzLiR0aS5DKCJTTzwxPiIp
-KX19CkguU08ucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciB0LHMKZm9yKHQ9dGhpcy5hLHM9dGhp
-cy5iO3QuRigpOylpZihILm9UKHMuJDEodC5nbCgpKSkpcmV0dXJuITAKcmV0dXJuITF9LApnbDpmdW5j
-dGlvbigpe3JldHVybiB0aGlzLmEuZ2woKX19CkguU1UucHJvdG90eXBlPXt9CkguUmUucHJvdG90eXBl
-PXsKWTpmdW5jdGlvbihhLGIsYyl7SC5MaCh0aGlzKS5DKCJSZS5FIikuYihjKQp0aHJvdyBILmIoUC5M
-NCgiQ2Fubm90IG1vZGlmeSBhbiB1bm1vZGlmaWFibGUgbGlzdCIpKX19CkguWEMucHJvdG90eXBlPXt9
-Ckgud3YucHJvdG90eXBlPXsKZ2lPOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuX2hhc2hDb2RlCmlmKHQh
-PW51bGwpcmV0dXJuIHQKdD01MzY4NzA5MTEmNjY0NTk3KkouaGYodGhpcy5hKQp0aGlzLl9oYXNoQ29k
-ZT10CnJldHVybiB0fSwKdzpmdW5jdGlvbihhKXtyZXR1cm4nU3ltYm9sKCInK0guZCh0aGlzLmEpKyci
-KSd9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFuY2Vv
-ZiBILnd2JiZ0aGlzLmE9PWIuYX0sCiRpR0Q6MX0KSC5QRC5wcm90b3R5cGU9e30KSC5XVS5wcm90b3R5
-cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLm5PKHRoaXMpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFy
-IHQ9SC5MaCh0aGlzKQp0LmQuYihiKQp0LmNoWzFdLmIoYykKcmV0dXJuIEguZGMoKX0sCiRpWjA6MX0K
-SC5MUC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKeDQ6ZnVuY3Rpb24o
-YSl7aWYodHlwZW9mIGEhPSJzdHJpbmciKXJldHVybiExCmlmKCJfX3Byb3RvX18iPT09YSlyZXR1cm4h
-MQpyZXR1cm4gdGhpcy5iLmhhc093blByb3BlcnR5KGEpfSwKcTpmdW5jdGlvbihhLGIpe2lmKCF0aGlz
-Lng0KGIpKXJldHVybiBudWxsCnJldHVybiB0aGlzLnFQKGIpfSwKcVA6ZnVuY3Rpb24oYSl7cmV0dXJu
-IHRoaXMuYltILnkoYSldfSwKSzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9SC5MaCh0aGlzKQpw
-LkMoIn4oMSwyKSIpLmIoYikKdD10aGlzLmMKZm9yKHM9dC5sZW5ndGgscD1wLmNoWzFdLHI9MDtyPHM7
-KytyKXtxPXRbcl0KYi4kMihxLHAuYih0aGlzLnFQKHEpKSl9fX0KSC5MSS5wcm90b3R5cGU9ewpnV2E6
-ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmEKcmV0dXJuIHR9LApnbmQ6ZnVuY3Rpb24oKXt2YXIgdCxzLHIs
-cSxwPXRoaXMKaWYocC5jPT09MSlyZXR1cm4gQy5kbgp0PXAuZApzPXQubGVuZ3RoLXAuZS5sZW5ndGgt
-cC5mCmlmKHM9PT0wKXJldHVybiBDLmRuCnI9W10KZm9yKHE9MDtxPHM7KytxKXtpZihxPj10Lmxlbmd0
-aClyZXR1cm4gSC5PSCh0LHEpCnIucHVzaCh0W3FdKX1yZXR1cm4gSi56QyhyKX0sCmdWbTpmdW5jdGlv
-bigpe3ZhciB0LHMscixxLHAsbyxuLG0sbD10aGlzCmlmKGwuYyE9PTApcmV0dXJuIEMuQ00KdD1sLmUK
-cz10Lmxlbmd0aApyPWwuZApxPXIubGVuZ3RoLXMtbC5mCmlmKHM9PT0wKXJldHVybiBDLkNNCnA9bmV3
-IEguTjUodS5lbykKZm9yKG89MDtvPHM7KytvKXtpZihvPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LG8p
-Cm49dFtvXQptPXErbwppZihtPDB8fG0+PXIubGVuZ3RoKXJldHVybiBILk9IKHIsbSkKcC5ZKDAsbmV3
-IEgud3YobiksclttXSl9cmV0dXJuIG5ldyBILlBEKHAsdS5nRil9LAokaXZROjF9CkguQ2oucHJvdG90
-eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdApILnkoYSkKdD10aGlzLmEKdC5iPXQuYisiJCIrSC5k
-KGEpCkMuTm0uaSh0aGlzLmIsYSkKQy5ObS5pKHRoaXMuYyxiKTsrK3QuYX0sCiRTOjE2fQpILlpyLnBy
-b3RvdHlwZT17CnFTOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9bmV3IFJlZ0V4cChyLmEpLmV4
-ZWMoYSkKaWYocT09bnVsbClyZXR1cm4gbnVsbAp0PU9iamVjdC5jcmVhdGUobnVsbCkKcz1yLmIKaWYo
-cyE9PS0xKXQuYXJndW1lbnRzPXFbcysxXQpzPXIuYwppZihzIT09LTEpdC5hcmd1bWVudHNFeHByPXFb
-cysxXQpzPXIuZAppZihzIT09LTEpdC5leHByPXFbcysxXQpzPXIuZQppZihzIT09LTEpdC5tZXRob2Q9
-cVtzKzFdCnM9ci5mCmlmKHMhPT0tMSl0LnJlY2VpdmVyPXFbcysxXQpyZXR1cm4gdH19CkguVzAucHJv
-dG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmIKaWYodD09bnVsbClyZXR1cm4iTm9TdWNo
-TWV0aG9kRXJyb3I6ICIrSC5kKHRoaXMuYSkKcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiBtZXRob2Qg
-bm90IGZvdW5kOiAnIit0KyInIG9uIG51bGwifX0KSC5hei5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEp
-e3ZhciB0LHM9dGhpcyxyPSJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9kIG5vdCBmb3VuZDogJyIscT1z
-LmIKaWYocT09bnVsbClyZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6ICIrSC5kKHMuYSkKdD1zLmMKaWYo
-dD09bnVsbClyZXR1cm4gcitxKyInICgiK0guZChzLmEpKyIpIgpyZXR1cm4gcitxKyInIG9uICciK3Qr
-IicgKCIrSC5kKHMuYSkrIikifX0KSC52Vi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRo
-aXMuYQpyZXR1cm4gdC5sZW5ndGg9PT0wPyJFcnJvciI6IkVycm9yOiAiK3R9fQpILkFtLnByb3RvdHlw
-ZT17CiQxOmZ1bmN0aW9uKGEpe2lmKHUuYlUuYyhhKSlpZihhLiR0aHJvd25Kc0Vycm9yPT1udWxsKWEu
-JHRocm93bkpzRXJyb3I9dGhpcy5hCnJldHVybiBhfSwKJFM6NH0KSC5YTy5wcm90b3R5cGU9ewp3OmZ1
-bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5iCmlmKHMhPW51bGwpcmV0dXJuIHMKcz10aGlzLmEKdD1zIT09
-bnVsbCYmdHlwZW9mIHM9PT0ib2JqZWN0Ij9zLnN0YWNrOm51bGwKcmV0dXJuIHRoaXMuYj10PT1udWxs
-PyIiOnR9LAokaUd6OjF9CkguVHAucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmNv
-bnN0cnVjdG9yLHM9dD09bnVsbD9udWxsOnQubmFtZQpyZXR1cm4iQ2xvc3VyZSAnIitILk5RKHM9PW51
-bGw/InVua25vd24iOnMpKyInIn0sCiRpRUg6MSwKZ1FsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9LAok
-QzoiJDEiLAokUjoxLAokRDpudWxsfQpILmxjLnByb3RvdHlwZT17fQpILnp4LnByb3RvdHlwZT17Cnc6
-ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy4kc3RhdGljX25hbWUKaWYodD09bnVsbClyZXR1cm4iQ2xvc3Vy
-ZSBvZiB1bmtub3duIHN0YXRpYyBtZXRob2QiCnJldHVybiJDbG9zdXJlICciK0guTlEodCkrIicifX0K
-SC5yVC5wcm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMKaWYoYj09bnVsbClyZXR1
-cm4hMQppZih0PT09YilyZXR1cm4hMAppZighKGIgaW5zdGFuY2VvZiBILnJUKSlyZXR1cm4hMQpyZXR1
-cm4gdC5hPT09Yi5hJiZ0LmI9PT1iLmImJnQuYz09PWIuY30sCmdpTzpmdW5jdGlvbihhKXt2YXIgdCxz
-PXRoaXMuYwppZihzPT1udWxsKXQ9SC5lUSh0aGlzLmEpCmVsc2UgdD10eXBlb2YgcyE9PSJvYmplY3Qi
-P0ouaGYocyk6SC5lUShzKQpyZXR1cm4odF5ILmVRKHRoaXMuYikpPj4+MH0sCnc6ZnVuY3Rpb24oYSl7
-dmFyIHQ9dGhpcy5jCmlmKHQ9PW51bGwpdD10aGlzLmEKcmV0dXJuIkNsb3N1cmUgJyIrSC5kKHRoaXMu
-ZCkrIicgb2YgIisoIkluc3RhbmNlIG9mICciK0guZChILk0odCkpKyInIil9fQpILkVxLnByb3RvdHlw
-ZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlJ1bnRpbWVFcnJvcjogIitILmQodGhpcy5hKX19Ckgua1ku
-cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDogIitQLnAodGhp
-cy5hKX19CkguTjUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCmdWOmZ1
-bmN0aW9uKCl7cmV0dXJuIG5ldyBILmk1KHRoaXMsSC5MaCh0aGlzKS5DKCJpNTwxPiIpKX0sCng0OmZ1
-bmN0aW9uKGEpe3ZhciB0LHMKaWYodHlwZW9mIGE9PSJzdHJpbmciKXt0PXRoaXMuYgppZih0PT1udWxs
-KXJldHVybiExCnJldHVybiB0aGlzLlh1KHQsYSl9ZWxzZXtzPXRoaXMuQ1goYSkKcmV0dXJuIHN9fSwK
-Q1g6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJuITEKcmV0dXJuIHRoaXMu
-RmgodGhpcy5CdCh0LEouaGYoYSkmMHgzZmZmZmZmKSxhKT49MH0sCnE6ZnVuY3Rpb24oYSxiKXt2YXIg
-dCxzLHIscSxwPXRoaXMsbz1udWxsCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7dD1wLmIKaWYodD09bnVs
-bClyZXR1cm4gbwpzPXAuajIodCxiKQpyPXM9PW51bGw/bzpzLmIKcmV0dXJuIHJ9ZWxzZSBpZih0eXBl
-b2YgYj09Im51bWJlciImJihiJjB4M2ZmZmZmZik9PT1iKXtxPXAuYwppZihxPT1udWxsKXJldHVybiBv
-CnM9cC5qMihxLGIpCnI9cz09bnVsbD9vOnMuYgpyZXR1cm4gcn1lbHNlIHJldHVybiBwLmFhKGIpfSwK
-YWE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMuZAppZihyPT1udWxsKXJldHVybiBudWxsCnQ9dGhp
-cy5CdChyLEouaGYoYSkmMHgzZmZmZmZmKQpzPXRoaXMuRmgodCxhKQppZihzPDApcmV0dXJuIG51bGwK
-cmV0dXJuIHRbc10uYn0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMsbT1I
-LkxoKG4pCm0uZC5iKGIpCm0uY2hbMV0uYihjKQppZih0eXBlb2YgYj09InN0cmluZyIpe3Q9bi5iCm4u
-RUgodD09bnVsbD9uLmI9bi56SygpOnQsYixjKX1lbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGIm
-MHgzZmZmZmZmKT09PWIpe3M9bi5jCm4uRUgocz09bnVsbD9uLmM9bi56SygpOnMsYixjKX1lbHNle3I9
-bi5kCmlmKHI9PW51bGwpcj1uLmQ9bi56SygpCnE9Si5oZihiKSYweDNmZmZmZmYKcD1uLkJ0KHIscSkK
-aWYocD09bnVsbCluLkVJKHIscSxbbi5IbihiLGMpXSkKZWxzZXtvPW4uRmgocCxiKQppZihvPj0wKXBb
-b10uYj1jCmVsc2UgcC5wdXNoKG4uSG4oYixjKSl9fX0sCks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9
-dGhpcwpILkxoKHIpLkMoIn4oMSwyKSIpLmIoYikKdD1yLmUKcz1yLnIKZm9yKDt0IT1udWxsOyl7Yi4k
-Mih0LmEsdC5iKQppZihzIT09ci5yKXRocm93IEguYihQLmE0KHIpKQp0PXQuY319LApFSDpmdW5jdGlv
-bihhLGIsYyl7dmFyIHQscz10aGlzLHI9SC5MaChzKQpyLmQuYihiKQpyLmNoWzFdLmIoYykKdD1zLmoy
-KGEsYikKaWYodD09bnVsbClzLkVJKGEsYixzLkhuKGIsYykpCmVsc2UgdC5iPWN9LAprczpmdW5jdGlv
-bigpe3RoaXMucj10aGlzLnIrMSY2NzEwODg2M30sCkhuOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlz
-LHI9SC5MaChzKSxxPW5ldyBILmRiKHIuZC5iKGEpLHIuY2hbMV0uYihiKSkKaWYocy5lPT1udWxsKXMu
-ZT1zLmY9cQplbHNle3Q9cy5mCnEuZD10CnMuZj10LmM9cX0rK3MuYQpzLmtzKCkKcmV0dXJuIHF9LApG
-aDpmdW5jdGlvbihhLGIpe3ZhciB0LHMKaWYoYT09bnVsbClyZXR1cm4tMQp0PWEubGVuZ3RoCmZvcihz
-PTA7czx0OysrcylpZihKLlJNKGFbc10uYSxiKSlyZXR1cm4gcwpyZXR1cm4tMX0sCnc6ZnVuY3Rpb24o
-YSl7cmV0dXJuIFAubk8odGhpcyl9LApqMjpmdW5jdGlvbihhLGIpe3JldHVybiBhW2JdfSwKQnQ6ZnVu
-Y3Rpb24oYSxiKXtyZXR1cm4gYVtiXX0sCkVJOmZ1bmN0aW9uKGEsYixjKXthW2JdPWN9LApybjpmdW5j
-dGlvbihhLGIpe2RlbGV0ZSBhW2JdfSwKWHU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5qMihhLGIp
-IT1udWxsfSwKeks6ZnVuY3Rpb24oKXt2YXIgdD0iPG5vbi1pZGVudGlmaWVyLWtleT4iLHM9T2JqZWN0
-LmNyZWF0ZShudWxsKQp0aGlzLkVJKHMsdCxzKQp0aGlzLnJuKHMsdCkKcmV0dXJuIHN9LAokaUZvOjF9
-CkguZGIucHJvdG90eXBlPXt9CkguaTUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
-aXMuYS5hfSwKZ2t6OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYSxzPW5ldyBILk42KHQsdC5yLHRoaXMu
-JHRpLkMoIk42PDE+IikpCnMuYz10LmUKcmV0dXJuIHN9fQpILk42LnByb3RvdHlwZT17CmdsOmZ1bmN0
-aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5hCmlmKHQuYiE9
-PXMucil0aHJvdyBILmIoUC5hNChzKSkKZWxzZXtzPXQuYwppZihzPT1udWxsKXt0LnNxWShudWxsKQpy
-ZXR1cm4hMX1lbHNle3Quc3FZKHMuYSkKdC5jPXQuYy5jCnJldHVybiEwfX19LApzcVk6ZnVuY3Rpb24o
-YSl7dGhpcy5kPXRoaXMuJHRpLmQuYihhKX0sCiRpQW46MX0KSC5kQy5wcm90b3R5cGU9ewokMTpmdW5j
-dGlvbihhKXtyZXR1cm4gdGhpcy5hKGEpfSwKJFM6NH0KSC53Ti5wcm90b3R5cGU9ewokMjpmdW5jdGlv
-bihhLGIpe3JldHVybiB0aGlzLmEoYSxiKX0sCiRTOjQwfQpILlZYLnByb3RvdHlwZT17CiQxOmZ1bmN0
-aW9uKGEpe3JldHVybiB0aGlzLmEoSC55KGEpKX0sCiRTOjMwfQpILlZSLnByb3RvdHlwZT17Cnc6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIlJlZ0V4cC8iK3RoaXMuYSsiLyIrdGhpcy5iLmZsYWdzfSwKZ0hjOmZ1bmN0
-aW9uKCl7dmFyIHQ9dGhpcyxzPXQuYwppZihzIT1udWxsKXJldHVybiBzCnM9dC5iCnJldHVybiB0LmM9
-SC52NCh0LmEscy5tdWx0aWxpbmUsIXMuaWdub3JlQ2FzZSxzLnVuaWNvZGUscy5kb3RBbGwsITApfSwK
-ZGQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguS1codGhpcyxiLDApfSwKVVo6ZnVuY3Rpb24oYSxi
-KXt2YXIgdCxzPXRoaXMuZ0hjKCkKcy5sYXN0SW5kZXg9Ygp0PXMuZXhlYyhhKQppZih0PT1udWxsKXJl
-dHVybiBudWxsCnJldHVybiBuZXcgSC5FSyh0KX0sCiRpdlg6MSwKJGl3TDoxfQpILkVLLnByb3RvdHlw
-ZT17CnE6ZnVuY3Rpb24oYSxiKXt2YXIgdApILlNjKGIpCnQ9dGhpcy5iCmlmKGI+PXQubGVuZ3RoKXJl
-dHVybiBILk9IKHQsYikKcmV0dXJuIHRbYl19LAokaU9kOjEsCiRpaWI6MX0KSC5LVy5wcm90b3R5cGU9
-ewpna3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlBiKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19Ckgu
-UGIucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3Zh
-ciB0LHMscixxLHA9dGhpcyxvPXAuYgppZihvPT1udWxsKXJldHVybiExCnQ9cC5jCmlmKHQ8PW8ubGVu
-Z3RoKXtzPXAuYQpyPXMuVVoobyx0KQppZihyIT1udWxsKXtwLmQ9cgpvPXIuYgp0PW8uaW5kZXgKcT10
-K29bMF0ubGVuZ3RoCmlmKHQ9PT1xKXtpZihzLmIudW5pY29kZSl7bz1wLmMKdD1vKzEKcz1wLmIKaWYo
-dDxzLmxlbmd0aCl7bz1KLnJZKHMpLm0ocyxvKQppZihvPj01NTI5NiYmbzw9NTYzMTkpe289Qy54Qi5t
-KHMsdCkKbz1vPj01NjMyMCYmbzw9NTczNDN9ZWxzZSBvPSExfWVsc2Ugbz0hMX1lbHNlIG89ITEKcT0o
-bz9xKzE6cSkrMX1wLmM9cQpyZXR1cm4hMH19cC5iPXAuZD1udWxsCnJldHVybiExfSwKJGlBbjoxfQpI
-LnRRLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCmlmKGIhPT0wKUgudmgoUC54KGIs
-bnVsbCkpCnJldHVybiB0aGlzLmN9LAokaU9kOjF9CkgudW4ucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9u
-KGEpe3JldHVybiBuZXcgSC5TZCh0aGlzLmEsdGhpcy5iLHRoaXMuYyl9fQpILlNkLnByb3RvdHlwZT17
-CkY6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcyxxPXIuYyxwPXIuYixvPXAubGVuZ3RoLG49ci5hLG09
-bi5sZW5ndGgKaWYocStvPm0pe3IuZD1udWxsCnJldHVybiExfXQ9bi5pbmRleE9mKHAscSkKaWYodDww
-KXtyLmM9bSsxCnIuZD1udWxsCnJldHVybiExfXM9dCtvCnIuZD1uZXcgSC50USh0LHApCnIuYz1zPT09
-ci5jP3MrMTpzCnJldHVybiEwfSwKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKJGlBbjoxfQpI
-LkVULnByb3RvdHlwZT17JGlFVDoxLCRpQVM6MX0KSC5iMC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihh
-KXtyZXR1cm4gYS5sZW5ndGh9LAokaVhqOjF9CkguRGcucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIp
-e0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7
-SC5JZyhjKQpILm9kKGIsYSxhLmxlbmd0aCkKYVtiXT1jfSwKJGljWDoxLAokaXpNOjF9CkguUGcucHJv
-dG90eXBlPXsKWTpmdW5jdGlvbihhLGIsYyl7SC5TYyhjKQpILm9kKGIsYSxhLmxlbmd0aCkKYVtiXT1j
-fSwKJGljWDoxLAokaXpNOjF9CkgueGoucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0guU2MoYikK
-SC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5kRS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9u
-KGEsYil7SC5TYyhiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILlpBLnByb3RvdHlw
-ZT17CnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19
-Ckgud2YucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgp
-CnJldHVybiBhW2JdfX0KSC5QcS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQpILm9k
-KGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmVFLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEp
-e3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCkgub2QoYixhLGEubGVuZ3Ro
-KQpyZXR1cm4gYVtiXX19CkguVjYucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVu
-Z3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2Jd
-fSwKJGlWNjoxLAokaW42OjF9CkguUkcucHJvdG90eXBlPXt9CkguVlAucHJvdG90eXBlPXt9CkguV0Iu
-cHJvdG90eXBlPXt9CkguWkcucHJvdG90eXBlPXt9CkguSmMucHJvdG90eXBlPXsKQzpmdW5jdGlvbihh
-KXtyZXR1cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEpfSwKS3E6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEgudjUodi50eXBlVW5pdmVyc2UsdGhpcyxhKX19CkguRy5wcm90b3R5cGU9e30KSC51OS5wcm90b3R5
-cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9fQpILmh6LnByb3RvdHlwZT17fQpILmlNLnBy
-b3RvdHlwZT17fQpQLnRoLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYSxzPXQu
-YQp0LmE9bnVsbApzLiQwKCl9LAokUzoxMn0KUC5oYS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2
-YXIgdCxzCnRoaXMuYS5hPXUuTS5iKGEpCnQ9dGhpcy5iCnM9dGhpcy5jCnQuZmlyc3RDaGlsZD90LnJl
-bW92ZUNoaWxkKHMpOnQuYXBwZW5kQ2hpbGQocyl9LAokUzo0MX0KUC5Wcy5wcm90b3R5cGU9ewokMDpm
-dW5jdGlvbigpe3RoaXMuYS4kMCgpfSwKJEM6IiQwIiwKJFI6MCwKJFM6MH0KUC5GdC5wcm90b3R5cGU9
-ewokMDpmdW5jdGlvbigpe3RoaXMuYS4kMCgpfSwKJEM6IiQwIiwKJFI6MCwKJFM6MH0KUC5XMy5wcm90
-b3R5cGU9ewpDWTpmdW5jdGlvbihhLGIpe2lmKHNlbGYuc2V0VGltZW91dCE9bnVsbClzZWxmLnNldFRp
-bWVvdXQoSC50UihuZXcgUC55SCh0aGlzLGIpLDApLGEpCmVsc2UgdGhyb3cgSC5iKFAuTDQoImBzZXRU
-aW1lb3V0KClgIG5vdCBmb3VuZC4iKSl9fQpQLnlILnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhp
-cy5iLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzoyfQpQLlBmLnByb3RvdHlwZT17CncwOmZ1bmN0aW9u
-KGEsYil7dmFyIHQKaWYoYT09bnVsbClhPW5ldyBQLm4oKQp0PXRoaXMuYQppZih0LmEhPT0wKXRocm93
-IEguYihQLlBWKCJGdXR1cmUgYWxyZWFkeSBjb21wbGV0ZWQiKSkKdC5OayhhLGIpfSwKcG06ZnVuY3Rp
-b24oYSl7cmV0dXJuIHRoaXMudzAoYSxudWxsKX19ClAuWmYucHJvdG90eXBlPXt9ClAuRmUucHJvdG90
-eXBlPXsKSFI6ZnVuY3Rpb24oYSl7aWYoKHRoaXMuYyYxNSkhPT02KXJldHVybiEwCnJldHVybiB0aGlz
-LmIuYi5idih1LmFsLmIodGhpcy5kKSxhLmEsdS5jSix1LkspfSwKS3c6ZnVuY3Rpb24oYSl7dmFyIHQ9
-dGhpcy5lLHM9dS56LHI9dS5LLHE9dGhpcy4kdGkuQygiMi8iKSxwPXRoaXMuYi5iCmlmKHUuVy5jKHQp
-KXJldHVybiBxLmIocC5ycCh0LGEuYSxhLmIscyxyLHUubCkpCmVsc2UgcmV0dXJuIHEuYihwLmJ2KHUu
-eS5iKHQpLGEuYSxzLHIpKX19ClAudnMucHJvdG90eXBlPXsKU3E6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
-LHMscixxPXRoaXMuJHRpCnEuS3EoYykuQygiMS8oMikiKS5iKGEpCnQ9JC5YMwppZih0IT09Qy5OVSl7
-Yy5DKCJAPDAvPiIpLktxKHEuZCkuQygiMSgyKSIpLmIoYSkKaWYoYiE9bnVsbCliPVAuVkgoYix0KX1z
-PW5ldyBQLnZzKCQuWDMsYy5DKCJ2czwwPiIpKQpyPWI9PW51bGw/MTozCnRoaXMueGYobmV3IFAuRmUo
-cyxyLGEsYixxLkMoIkA8MT4iKS5LcShjKS5DKCJGZTwxLDI+IikpKQpyZXR1cm4gc30sClc3OmZ1bmN0
-aW9uKGEsYil7cmV0dXJuIHRoaXMuU3EoYSxudWxsLGIpfSwKT0E6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
-CnUuYmYuYihudWxsKQp0PXRoaXMuJHRpCnM9JC5YMwpyPW5ldyBQLnZzKHMsdCkKaWYocyE9PUMuTlUp
-YT1QLlZIKGEscykKdGhpcy54ZihuZXcgUC5GZShyLDIsbnVsbCxhLHQuQygiQDwxPiIpLktxKHQuZCku
-QygiRmU8MSwyPiIpKSkKcmV0dXJuIHJ9LAp4ZjpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMscj1zLmEK
-aWYocjw9MSl7YS5hPXUueC5iKHMuYykKcy5jPWF9ZWxzZXtpZihyPT09Mil7dD11Ll8uYihzLmMpCnI9
-dC5hCmlmKHI8NCl7dC54ZihhKQpyZXR1cm59cy5hPXIKcy5jPXQuY31QLlRrKG51bGwsbnVsbCxzLmIs
-dS5NLmIobmV3IFAuZGEocyxhKSkpfX0sCmpROmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbz10aGlz
-LG49e30Kbi5hPWEKaWYoYT09bnVsbClyZXR1cm4KdD1vLmEKaWYodDw9MSl7cz11LnguYihvLmMpCnI9
-by5jPWEKaWYocyE9bnVsbCl7Zm9yKDtxPXIuYSxxIT1udWxsO3I9cSk7ci5hPXN9fWVsc2V7aWYodD09
-PTIpe3A9dS5fLmIoby5jKQp0PXAuYQppZih0PDQpe3AualEoYSkKcmV0dXJufW8uYT10Cm8uYz1wLmN9
-bi5hPW8uTjgoYSkKUC5UayhudWxsLG51bGwsby5iLHUuTS5iKG5ldyBQLm9RKG4sbykpKX19LAphaDpm
-dW5jdGlvbigpe3ZhciB0PXUueC5iKHRoaXMuYykKdGhpcy5jPW51bGwKcmV0dXJuIHRoaXMuTjgodCl9
-LApOODpmdW5jdGlvbihhKXt2YXIgdCxzLHIKZm9yKHQ9YSxzPW51bGw7dCE9bnVsbDtzPXQsdD1yKXty
-PXQuYQp0LmE9c31yZXR1cm4gc30sCkhIOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxyPXMuJHRpCnIu
-QygiMS8iKS5iKGEpCmlmKHIuQygiYjg8MT4iKS5jKGEpKWlmKHIuYyhhKSlQLkE5KGEscykKZWxzZSBQ
-LmszKGEscykKZWxzZXt0PXMuYWgoKQpyLmQuYihhKQpzLmE9NApzLmM9YQpQLkhaKHMsdCl9fSwKWkw6
-ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMKdS5sLmIoYikKdD1zLmFoKCkKcy5hPTgKcy5jPW5ldyBQ
-LkN3KGEsYikKUC5IWihzLHQpfSwKWGY6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPXQuJHRpCnMuQygi
-MS8iKS5iKGEpCmlmKHMuQygiYjg8MT4iKS5jKGEpKXt0LmNVKGEpCnJldHVybn10LmE9MQpQLlRrKG51
-bGwsbnVsbCx0LmIsdS5NLmIobmV3IFAuckgodCxhKSkpfSwKY1U6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhp
-cyxzPXQuJHRpCnMuQygiYjg8MT4iKS5iKGEpCmlmKHMuYyhhKSl7aWYoYS5nQVQoKSl7dC5hPTEKUC5U
-ayhudWxsLG51bGwsdC5iLHUuTS5iKG5ldyBQLktGKHQsYSkpKX1lbHNlIFAuQTkoYSx0KQpyZXR1cm59
-UC5rMyhhLHQpfSwKTms6ZnVuY3Rpb24oYSxiKXt0aGlzLmE9MQpQLlRrKG51bGwsbnVsbCx0aGlzLmIs
-dS5NLmIobmV3IFAuWkwodGhpcyxhLGIpKSl9LAokaWI4OjF9ClAuZGEucHJvdG90eXBlPXsKJDA6ZnVu
-Y3Rpb24oKXtQLkhaKHRoaXMuYSx0aGlzLmIpfSwKJFM6MH0KUC5vUS5wcm90b3R5cGU9ewokMDpmdW5j
-dGlvbigpe1AuSFoodGhpcy5iLHRoaXMuYS5hKX0sCiRTOjB9ClAucFYucHJvdG90eXBlPXsKJDE6ZnVu
-Y3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnQuYT0wCnQuSEgoYSl9LAokUzoxMn0KUC5VNy5wcm90b3R5cGU9
-ewokMjpmdW5jdGlvbihhLGIpe3UubC5iKGIpCnRoaXMuYS5aTChhLGIpfSwKJDE6ZnVuY3Rpb24oYSl7
-cmV0dXJuIHRoaXMuJDIoYSxudWxsKX0sCiRDOiIkMiIsCiREOmZ1bmN0aW9uKCl7cmV0dXJuW251bGxd
-fSwKJFM6MzV9ClAudnIucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWkwodGhpcy5iLHRo
-aXMuYyl9LAokUzowfQpQLnJILnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5hLHM9
-dC4kdGkuZC5iKHRoaXMuYikscj10LmFoKCkKdC5hPTQKdC5jPXMKUC5IWih0LHIpfSwKJFM6MH0KUC5L
-Ri5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe1AuQTkodGhpcy5iLHRoaXMuYSl9LAokUzowfQpQLlpM
-LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLlpMKHRoaXMuYix0aGlzLmMpfSwKJFM6MH0K
-UC5SVC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMsbT1udWxs
-CnRyeXtyPW4uYwptPXIuYi5iLnp6KHUuZk8uYihyLmQpLHUueil9Y2F0Y2gocSl7dD1ILlJ1KHEpCnM9
-SC50cyhxKQppZihuLmQpe3I9dS5uLmIobi5hLmEuYykuYQpwPXQKcD1yPT1udWxsP3A9PW51bGw6cj09
-PXAKcj1wfWVsc2Ugcj0hMQpwPW4uYgppZihyKXAuYj11Lm4uYihuLmEuYS5jKQplbHNlIHAuYj1uZXcg
-UC5Ddyh0LHMpCnAuYT0hMApyZXR1cm59aWYodS5jLmMobSkpe2lmKG0gaW5zdGFuY2VvZiBQLnZzJiZt
-LmE+PTQpe2lmKG0uYT09PTgpe3I9bi5iCnIuYj11Lm4uYihtLmMpCnIuYT0hMH1yZXR1cm59bz1uLmEu
-YQpyPW4uYgpyLmI9bS5XNyhuZXcgUC5qWihvKSx1LnopCnIuYT0hMX19LAokUzoyfQpQLmpaLnByb3Rv
-dHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LAokUzozNH0KUC5ycS5wcm90b3R5cGU9
-ewokMDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbyxuLG09dGhpcwp0cnl7cj1tLmIKcT1yLiR0aQpw
-PXEuZApvPXAuYihtLmMpCm0uYS5iPXIuYi5iLmJ2KHEuQygiMi8oMSkiKS5iKHIuZCksbyxxLkMoIjIv
-IikscCl9Y2F0Y2gobil7dD1ILlJ1KG4pCnM9SC50cyhuKQpyPW0uYQpyLmI9bmV3IFAuQ3codCxzKQpy
-LmE9ITB9fSwKJFM6Mn0KUC5SVy5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAs
-byxuLG0sbD10aGlzCnRyeXt0PXUubi5iKGwuYS5hLmMpCnE9bC5jCmlmKEgub1QocS5IUih0KSkmJnEu
-ZSE9bnVsbCl7cD1sLmIKcC5iPXEuS3codCkKcC5hPSExfX1jYXRjaChvKXtzPUguUnUobykKcj1ILnRz
-KG8pCnE9dS5uLmIobC5hLmEuYykKcD1xLmEKbj1zCm09bC5iCmlmKHA9PW51bGw/bj09bnVsbDpwPT09
-biltLmI9cQplbHNlIG0uYj1uZXcgUC5DdyhzLHIpCm0uYT0hMH19LAokUzoyfQpQLk9NLnByb3RvdHlw
-ZT17fQpQLnFoLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9e30scD1u
-ZXcgUC52cygkLlgzLHUuZkopCnEuYT0wCnQ9SC5MaChyKQpzPXQuQygifigxKSIpLmIobmV3IFAuQjUo
-cSxyKSkKdS5NLmIobmV3IFAuUEkocSxwKSkKVy5KRShyLmEsci5iLHMsITEsdC5kKQpyZXR1cm4gcH19
-ClAuQjUucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7SC5MaCh0aGlzLmIpLmQuYihhKTsrK3RoaXMu
-YS5hfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm4gSC5MaCh0aGlzLmIpLkMoImM4KDEpIil9fQpQLlBJLnBy
-b3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5iLkhIKHRoaXMuYS5hKX0sCiRTOjB9ClAuTU8ucHJv
-dG90eXBlPXt9ClAua1QucHJvdG90eXBlPXt9ClAuQ3cucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXty
-ZXR1cm4gSC5kKHRoaXMuYSl9LAokaVhTOjF9ClAubTAucHJvdG90eXBlPXskaUpCOjF9ClAucEsucHJv
-dG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMuYSxyPXMuYQpzPXI9PW51bGw/cy5hPW5l
-dyBQLm4oKTpyCnI9dGhpcy5iCmlmKHI9PW51bGwpdGhyb3cgSC5iKHMpCnQ9SC5iKHMpCnQuc3RhY2s9
-ci53KDApCnRocm93IHR9LAokUzowfQpQLkppLnByb3RvdHlwZT17CmJIOmZ1bmN0aW9uKGEpe3ZhciB0
-LHMscixxPW51bGwKdS5NLmIoYSkKdHJ5e2lmKEMuTlU9PT0kLlgzKXthLiQwKCkKcmV0dXJufVAuVDgo
-cSxxLHRoaXMsYSx1LkgpfWNhdGNoKHIpe3Q9SC5SdShyKQpzPUgudHMocikKUC5MMihxLHEsdGhpcyx0
-LHUubC5iKHMpKX19LApEbDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9bnVsbApjLkMoIn4oMCki
-KS5iKGEpCmMuYihiKQp0cnl7aWYoQy5OVT09PSQuWDMpe2EuJDEoYikKcmV0dXJufVAueXYocSxxLHRo
-aXMsYSxiLHUuSCxjKX1jYXRjaChyKXt0PUguUnUocikKcz1ILnRzKHIpClAuTDIocSxxLHRoaXMsdCx1
-LmwuYihzKSl9fSwKUlQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuaGoodGhpcyxiLkMoIjAoKSIp
-LmIoYSksYil9LApHWTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuVnAodGhpcyx1Lk0uYihhKSl9LApQ
-eTpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC5PUih0aGlzLGIuQygifigwKSIpLmIoYSksYil9LApx
-OmZ1bmN0aW9uKGEsYil7cmV0dXJuIG51bGx9LAp6ejpmdW5jdGlvbihhLGIpe2IuQygiMCgpIikuYihh
-KQppZigkLlgzPT09Qy5OVSlyZXR1cm4gYS4kMCgpCnJldHVybiBQLlQ4KG51bGwsbnVsbCx0aGlzLGEs
-Yil9LApidjpmdW5jdGlvbihhLGIsYyxkKXtjLkMoIkA8MD4iKS5LcShkKS5DKCIxKDIpIikuYihhKQpk
-LmIoYikKaWYoJC5YMz09PUMuTlUpcmV0dXJuIGEuJDEoYikKcmV0dXJuIFAueXYobnVsbCxudWxsLHRo
-aXMsYSxiLGMsZCl9LApycDpmdW5jdGlvbihhLGIsYyxkLGUsZil7ZC5DKCJAPDA+IikuS3EoZSkuS3Eo
-ZikuQygiMSgyLDMpIikuYihhKQplLmIoYikKZi5iKGMpCmlmKCQuWDM9PT1DLk5VKXJldHVybiBhLiQy
-KGIsYykKcmV0dXJuIFAuUXgobnVsbCxudWxsLHRoaXMsYSxiLGMsZCxlLGYpfX0KUC5oai5wcm90b3R5
-cGU9ewokMDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmEuenoodGhpcy5iLHRoaXMuYyl9LAokUzpmdW5j
-dGlvbigpe3JldHVybiB0aGlzLmMuQygiMCgpIil9fQpQLlZwLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
-KCl7cmV0dXJuIHRoaXMuYS5iSCh0aGlzLmIpfSwKJFM6Mn0KUC5PUi5wcm90b3R5cGU9ewokMTpmdW5j
-dGlvbihhKXt2YXIgdD10aGlzLmMKcmV0dXJuIHRoaXMuYS5EbCh0aGlzLmIsdC5iKGEpLHQpfSwKJFM6
-ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jLkMoIn4oMCkiKX19ClAuYjYucHJvdG90eXBlPXsKZ2t6OmZ1
-bmN0aW9uKGEpe3ZhciB0PXRoaXMscz1uZXcgUC5sbSh0LHQucixILkxoKHQpLkMoImxtPDE+IikpCnMu
-Yz10LmUKcmV0dXJuIHN9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKdGc6ZnVuY3Rpb24o
-YSxiKXt2YXIgdCxzCmlmKHR5cGVvZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXt0PXRoaXMu
-YgppZih0PT1udWxsKXJldHVybiExCnJldHVybiB1LkouYih0W2JdKSE9bnVsbH1lbHNle3M9dGhpcy5Q
-UihiKQpyZXR1cm4gc319LApQUjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmQKaWYodD09bnVsbClyZXR1
-cm4hMQpyZXR1cm4gdGhpcy5ERih0W3RoaXMuTihhKV0sYSk+PTB9LAppOmZ1bmN0aW9uKGEsYil7dmFy
-IHQscyxyPXRoaXMKSC5MaChyKS5kLmIoYikKaWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJv
-dG9fXyIpe3Q9ci5iCnJldHVybiByLmJRKHQ9PW51bGw/ci5iPVAuVDIoKTp0LGIpfWVsc2UgaWYodHlw
-ZW9mIGI9PSJudW1iZXIiJiYoYiYxMDczNzQxODIzKT09PWIpe3M9ci5jCnJldHVybiByLmJRKHM9PW51
-bGw/ci5jPVAuVDIoKTpzLGIpfWVsc2UgcmV0dXJuIHIuQjcoYil9LApCNzpmdW5jdGlvbihhKXt2YXIg
-dCxzLHIscT10aGlzCkguTGgocSkuZC5iKGEpCnQ9cS5kCmlmKHQ9PW51bGwpdD1xLmQ9UC5UMigpCnM9
-cS5OKGEpCnI9dFtzXQppZihyPT1udWxsKXRbc109W3EueW8oYSldCmVsc2V7aWYocS5ERihyLGEpPj0w
-KXJldHVybiExCnIucHVzaChxLnlvKGEpKX1yZXR1cm4hMH0sClI6ZnVuY3Rpb24oYSxiKXt2YXIgdD10
-aGlzCmlmKHR5cGVvZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXJldHVybiB0LkwodC5iLGIp
-CmVsc2UgaWYodHlwZW9mIGI9PSJudW1iZXIiJiYoYiYxMDczNzQxODIzKT09PWIpcmV0dXJuIHQuTCh0
-LmMsYikKZWxzZSByZXR1cm4gdC5xZyhiKX0sCnFnOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9dGhp
-cyxvPXAuZAppZihvPT1udWxsKXJldHVybiExCnQ9cC5OKGEpCnM9b1t0XQpyPXAuREYocyxhKQppZihy
-PDApcmV0dXJuITEKcT1zLnNwbGljZShyLDEpWzBdCmlmKDA9PT1zLmxlbmd0aClkZWxldGUgb1t0XQpw
-LkdTKHEpCnJldHVybiEwfSwKYlE6ZnVuY3Rpb24oYSxiKXtILkxoKHRoaXMpLmQuYihiKQppZih1Lkou
-YihhW2JdKSE9bnVsbClyZXR1cm4hMQphW2JdPXRoaXMueW8oYikKcmV0dXJuITB9LApMOmZ1bmN0aW9u
-KGEsYil7dmFyIHQKaWYoYT09bnVsbClyZXR1cm4hMQp0PXUuSi5iKGFbYl0pCmlmKHQ9PW51bGwpcmV0
-dXJuITEKdGhpcy5HUyh0KQpkZWxldGUgYVtiXQpyZXR1cm4hMH0sClM6ZnVuY3Rpb24oKXt0aGlzLnI9
-MTA3Mzc0MTgyMyZ0aGlzLnIrMX0sCnlvOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxyPW5ldyBQLmJu
-KEguTGgocykuZC5iKGEpKQppZihzLmU9PW51bGwpcy5lPXMuZj1yCmVsc2V7dD1zLmYKci5jPXQKcy5m
-PXQuYj1yfSsrcy5hCnMuUygpCnJldHVybiByfSwKR1M6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPWEu
-YyxyPWEuYgppZihzPT1udWxsKXQuZT1yCmVsc2Ugcy5iPXIKaWYocj09bnVsbCl0LmY9cwplbHNlIHIu
-Yz1zOy0tdC5hCnQuUygpfSwKTjpmdW5jdGlvbihhKXtyZXR1cm4gSi5oZihhKSYxMDczNzQxODIzfSwK
-REY6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCmlmKGE9PW51bGwpcmV0dXJuLTEKdD1hLmxlbmd0aApmb3Io
-cz0wO3M8dDsrK3MpaWYoSi5STShhW3NdLmEsYikpcmV0dXJuIHMKcmV0dXJuLTF9fQpQLmJuLnByb3Rv
-dHlwZT17fQpQLmxtLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVu
-Y3Rpb24oKXt2YXIgdD10aGlzLHM9dC5hCmlmKHQuYiE9PXMucil0aHJvdyBILmIoUC5hNChzKSkKZWxz
-ZXtzPXQuYwppZihzPT1udWxsKXt0LnNqKG51bGwpCnJldHVybiExfWVsc2V7dC5zaih0LiR0aS5kLmIo
-cy5hKSkKdC5jPXQuYy5iCnJldHVybiEwfX19LApzajpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGku
-ZC5iKGEpfSwKJGlBbjoxfQpQLm1XLnByb3RvdHlwZT17fQpQLkxVLnByb3RvdHlwZT17JGljWDoxLCRp
-ek06MX0KUC5sRC5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILmE3KGEsdGhp
-cy5nQShhKSxILnpLKGEpLkMoImE3PGxELkU+IikpfSwKRTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlz
-LnEoYSxiKX0sCks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCkgueksoYSkuQygifihsRC5FKSIpLmIoYikK
-dD10aGlzLmdBKGEpCmZvcihzPTA7czx0Oysrcyl7Yi4kMSh0aGlzLnEoYSxzKSkKaWYodCE9PXRoaXMu
-Z0EoYSkpdGhyb3cgSC5iKFAuYTQoYSkpfX0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILnpLKGEp
-CnJldHVybiBuZXcgSC5BOChhLHQuS3EoYykuQygiMShsRC5FKSIpLmIoYiksdC5DKCJAPGxELkU+Iiku
-S3EoYykuQygiQTg8MSwyPiIpKX0sCmR1OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0CkgueksoYSkuQygi
-bEQuRSIpLmIoZCkKUC5qQihiLGMsdGhpcy5nQShhKSkKZm9yKHQ9Yjt0PGM7Kyt0KXRoaXMuWShhLHQs
-ZCl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKGEsIlsiLCJdIil9fQpQLmlsLnByb3RvdHlwZT17
-fQpQLnJhLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmEKaWYoIXMuYSl0
-aGlzLmIuYSs9IiwgIgpzLmE9ITEKcz10aGlzLmIKdD1zLmErPUguZChhKQpzLmE9dCsiOiAiCnMuYSs9
-SC5kKGIpfSwKJFM6MX0KUC5Zay5wcm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILkxo
-KHRoaXMpLkMoIn4oWWsuSyxZay5WKSIpLmIoYikKZm9yKHQ9Si5JVCh0aGlzLmdWKCkpO3QuRigpOyl7
-cz10LmdsKCkKYi4kMihzLHRoaXMucSgwLHMpKX19LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gSi5IbSh0
-aGlzLmdWKCkpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sCiRpWjA6MX0KUC5LUC5w
-cm90b3R5cGU9ewpZOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILkxoKHRoaXMpCnQuZC5iKGIpCnQuY2hb
-MV0uYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlmaWFibGUgbWFwIikpfX0K
-UC5Qbi5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5xKDAsYil9LApZOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdD1ILkxoKHRoaXMpCnRoaXMuYS5ZKDAsdC5kLmIoYiksdC5jaFsxXS5i
-KGMpKX0sCks6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuSygwLEguTGgodGhpcykuQygifigxLDIpIikuYihi
-KSl9LApnQTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ0EodCl9LAp3OmZ1bmN0aW9u
-KGEpe3JldHVybiBKLmoodGhpcy5hKX0sCiRpWjA6MX0KUC5Hai5wcm90b3R5cGU9e30KUC5sZi5wcm90
-b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKHRoaXMsInsiLCJ9Iil9fQpQLlZqLnByb3Rv
-dHlwZT17JGljWDoxLCRpeHU6MX0KUC5Ydi5wcm90b3R5cGU9ewpGVjpmdW5jdGlvbihhLGIpe3ZhciB0
-CmZvcih0PUouSVQoSC5MaCh0aGlzKS5DKCJjWDwxPiIpLmIoYikpO3QuRigpOyl0aGlzLmkoMCx0Lmds
-KCkpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5XRSh0aGlzLCJ7IiwifSIpfSwKSDpmdW5jdGlvbihh
-LGIpe3ZhciB0LHM9UC5yaih0aGlzLHRoaXMucixILkxoKHRoaXMpLmQpCmlmKCFzLkYoKSlyZXR1cm4i
-IgppZihiPT09IiIpe3Q9IiIKZG8gdCs9SC5kKHMuZCkKd2hpbGUocy5GKCkpfWVsc2V7dD1ILmQocy5k
-KQpmb3IoO3MuRigpOyl0PXQrYitILmQocy5kKX1yZXR1cm4gdC5jaGFyQ29kZUF0KDApPT0wP3Q6dH0s
-CiRpY1g6MSwKJGl4dToxfQpQLm5ZLnByb3RvdHlwZT17fQpQLldZLnByb3RvdHlwZT17fQpQLlJVLnBy
-b3RvdHlwZT17fQpQLnV3LnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYgpp
-ZihzPT1udWxsKXJldHVybiB0aGlzLmMucSgwLGIpCmVsc2UgaWYodHlwZW9mIGIhPSJzdHJpbmciKXJl
-dHVybiBudWxsCmVsc2V7dD1zW2JdCnJldHVybiB0eXBlb2YgdD09InVuZGVmaW5lZCI/dGhpcy5mYihi
-KTp0fX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmI9PW51bGw/dGhpcy5jLmE6dGhpcy5DZigp
-Lmxlbmd0aH0sCmdWOmZ1bmN0aW9uKCl7aWYodGhpcy5iPT1udWxsKXt2YXIgdD10aGlzLmMKcmV0dXJu
-IG5ldyBILmk1KHQsSC5MaCh0KS5DKCJpNTwxPiIpKX1yZXR1cm4gbmV3IFAuaTgodGhpcyl9LApZOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9dGhpcwppZihyLmI9PW51bGwpci5jLlkoMCxiLGMpCmVsc2Ug
-aWYoci54NChiKSl7dD1yLmIKdFtiXT1jCnM9ci5hCmlmKHM9PW51bGw/dCE9bnVsbDpzIT09dClzW2Jd
-PW51bGx9ZWxzZSByLlhLKCkuWSgwLGIsYyl9LAp4NDpmdW5jdGlvbihhKXtpZih0aGlzLmI9PW51bGwp
-cmV0dXJuIHRoaXMuYy54NChhKQpyZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5j
-YWxsKHRoaXMuYSxhKX0sCks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwPXRoaXMKdS5jQS5iKGIp
-CmlmKHAuYj09bnVsbClyZXR1cm4gcC5jLksoMCxiKQp0PXAuQ2YoKQpmb3Iocz0wO3M8dC5sZW5ndGg7
-KytzKXtyPXRbc10KcT1wLmJbcl0KaWYodHlwZW9mIHE9PSJ1bmRlZmluZWQiKXtxPVAuUWUocC5hW3Jd
-KQpwLmJbcl09cX1iLiQyKHIscSkKaWYodCE9PXAuYyl0aHJvdyBILmIoUC5hNChwKSl9fSwKQ2Y6ZnVu
-Y3Rpb24oKXt2YXIgdD11LmouYih0aGlzLmMpCmlmKHQ9PW51bGwpdD10aGlzLmM9SC5WTShPYmplY3Qu
-a2V5cyh0aGlzLmEpLHUucykKcmV0dXJuIHR9LApYSzpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbz10
-aGlzCmlmKG8uYj09bnVsbClyZXR1cm4gby5jCnQ9UC5GbCh1Lk4sdS56KQpzPW8uQ2YoKQpmb3Iocj0w
-O3E9cy5sZW5ndGgscjxxOysrcil7cD1zW3JdCnQuWSgwLHAsby5xKDAscCkpfWlmKHE9PT0wKUMuTm0u
-aShzLG51bGwpCmVsc2UgQy5ObS5zQShzLDApCm8uYT1vLmI9bnVsbApyZXR1cm4gby5jPXR9LApmYjpm
-dW5jdGlvbihhKXt2YXIgdAppZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRo
-aXMuYSxhKSlyZXR1cm4gbnVsbAp0PVAuUWUodGhpcy5hW2FdKQpyZXR1cm4gdGhpcy5iW2FdPXR9fQpQ
-Lmk4LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1cm4gdC5nQSh0KX0s
-CkU6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmEKaWYodC5iPT1udWxsKXQ9dC5nVigpLkUoMCxiKQpl
-bHNle3Q9dC5DZigpCmlmKGI8MHx8Yj49dC5sZW5ndGgpcmV0dXJuIEguT0godCxiKQp0PXRbYl19cmV0
-dXJuIHR9LApna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCmlmKHQuYj09bnVsbCl7dD10LmdWKCkK
-dD10Lmdreih0KX1lbHNle3Q9dC5DZigpCnQ9bmV3IEoubTEodCx0Lmxlbmd0aCxILnQ2KHQpLkMoIm0x
-PDE+IikpfXJldHVybiB0fX0KUC5DVi5wcm90b3R5cGU9ewp5cjpmdW5jdGlvbihhLGEwLGExKXt2YXIg
-dCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYj0iSW52YWxpZCBiYXNlNjQgZW5jb2Rp
-bmcgbGVuZ3RoICIKYTE9UC5qQihhMCxhMSxhLmxlbmd0aCkKdD0kLlY3KCkKZm9yKHM9YTAscj1zLHE9
-bnVsbCxwPS0xLG89LTEsbj0wO3M8YTE7cz1tKXttPXMrMQpsPUMueEIuVyhhLHMpCmlmKGw9PT0zNyl7
-az1tKzIKaWYoazw9YTEpe2o9SC5vbyhDLnhCLlcoYSxtKSkKaT1ILm9vKEMueEIuVyhhLG0rMSkpCmg9
-aioxNitpLShpJjI1NikKaWYoaD09PTM3KWg9LTEKbT1rfWVsc2UgaD0tMX1lbHNlIGg9bAppZigwPD1o
-JiZoPD0xMjcpe2lmKGg8MHx8aD49dC5sZW5ndGgpcmV0dXJuIEguT0godCxoKQpnPXRbaF0KaWYoZz49
-MCl7aD1DLnhCLm0oIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1
-dnd4eXowMTIzNDU2Nzg5Ky8iLGcpCmlmKGg9PT1sKWNvbnRpbnVlCmw9aH1lbHNle2lmKGc9PT0tMSl7
-aWYocDwwKXtmPXE9PW51bGw/bnVsbDpxLmEubGVuZ3RoCmlmKGY9PW51bGwpZj0wCnA9Zisocy1yKQpv
-PXN9KytuCmlmKGw9PT02MSljb250aW51ZX1sPWh9aWYoZyE9PS0yKXtpZihxPT1udWxsKXE9bmV3IFAu
-Um4oIiIpCnEuYSs9Qy54Qi5OaihhLHIscykKcS5hKz1ILkx3KGwpCnI9bQpjb250aW51ZX19dGhyb3cg
-SC5iKFAucnIoIkludmFsaWQgYmFzZTY0IGRhdGEiLGEscykpfWlmKHEhPW51bGwpe2Y9cS5hKz1DLnhC
-Lk5qKGEscixhMSkKZT1mLmxlbmd0aAppZihwPj0wKVAueE0oYSxvLGExLHAsbixlKQplbHNle2Q9Qy5q
-bi56WShlLTEsNCkrMQppZihkPT09MSl0aHJvdyBILmIoUC5ycihiLGEsYTEpKQpmb3IoO2Q8NDspe2Yr
-PSI9IgpxLmE9ZjsrK2R9fWY9cS5hCnJldHVybiBDLnhCLmk3KGEsYTAsYTEsZi5jaGFyQ29kZUF0KDAp
-PT0wP2Y6Zil9Yz1hMS1hMAppZihwPj0wKVAueE0oYSxvLGExLHAsbixjKQplbHNle2Q9Qy5qbi56WShj
-LDQpCmlmKGQ9PT0xKXRocm93IEguYihQLnJyKGIsYSxhMSkpCmlmKGQ+MSlhPUMueEIuaTcoYSxhMSxh
-MSxkPT09Mj8iPT0iOiI9Iil9cmV0dXJuIGF9fQpQLlU4LnByb3RvdHlwZT17fQpQLlVrLnByb3RvdHlw
-ZT17fQpQLndJLnByb3RvdHlwZT17fQpQLlppLnByb3RvdHlwZT17fQpQLmJ5LnByb3RvdHlwZT17CnBX
-OmZ1bmN0aW9uKGEsYixjKXt2YXIgdAp1LmVwLmIoYykKdD1QLkJTKGIsdGhpcy5nSGUoKS5hKQpyZXR1
-cm4gdH0sCmdIZTpmdW5jdGlvbigpe3JldHVybiBDLkEzfX0KUC5NeC5wcm90b3R5cGU9e30KUC51NS5w
-cm90b3R5cGU9ewpnWkU6ZnVuY3Rpb24oKXtyZXR1cm4gQy5Ra319ClAuRTMucHJvdG90eXBlPXsKV0o6
-ZnVuY3Rpb24oYSl7dmFyIHQscyxyPVAuakIoMCxudWxsLGEubGVuZ3RoKSxxPXItMAppZihxPT09MCly
-ZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCkKdD1uZXcgVWludDhBcnJheShxKjMpCnM9bmV3IFAuUncodCkK
-aWYocy5HeChhLDAscikhPT1yKXMuTzYoSi5hNihhLHItMSksMCkKcmV0dXJuIG5ldyBVaW50OEFycmF5
-KHQuc3ViYXJyYXkoMCxILnJNKDAscy5iLHQubGVuZ3RoKSkpfX0KUC5Sdy5wcm90b3R5cGU9ewpPNjpm
-dW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcyxyPXMuYyxxPXMuYixwPXErMSxvPXIubGVuZ3RoCmlmKChi
-JjY0NTEyKT09PTU2MzIwKXt0PTY1NTM2KygoYSYxMDIzKTw8MTApfGImMTAyMwpzLmI9cAppZihxPj1v
-KXJldHVybiBILk9IKHIscSkKcltxXT0yNDB8dD4+PjE4CnE9cy5iPXArMQppZihwPj1vKXJldHVybiBI
-Lk9IKHIscCkKcltwXT0xMjh8dD4+PjEyJjYzCnA9cy5iPXErMQppZihxPj1vKXJldHVybiBILk9IKHIs
-cSkKcltxXT0xMjh8dD4+PjYmNjMKcy5iPXArMQppZihwPj1vKXJldHVybiBILk9IKHIscCkKcltwXT0x
-Mjh8dCY2MwpyZXR1cm4hMH1lbHNle3MuYj1wCmlmKHE+PW8pcmV0dXJuIEguT0gocixxKQpyW3FdPTIy
-NHxhPj4+MTIKcT1zLmI9cCsxCmlmKHA+PW8pcmV0dXJuIEguT0gocixwKQpyW3BdPTEyOHxhPj4+NiY2
-MwpzLmI9cSsxCmlmKHE+PW8pcmV0dXJuIEguT0gocixxKQpyW3FdPTEyOHxhJjYzCnJldHVybiExfX0s
-Ckd4OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMKaWYoYiE9PWMmJihDLnhC
-Lm0oYSxjLTEpJjY0NTEyKT09PTU1Mjk2KS0tYwpmb3IodD1tLmMscz10Lmxlbmd0aCxyPWI7cjxjOysr
-cil7cT1DLnhCLlcoYSxyKQppZihxPD0xMjcpe3A9bS5iCmlmKHA+PXMpYnJlYWsKbS5iPXArMQp0W3Bd
-PXF9ZWxzZSBpZigocSY2NDUxMik9PT01NTI5Nil7aWYobS5iKzM+PXMpYnJlYWsKbz1yKzEKaWYobS5P
-NihxLEMueEIuVyhhLG8pKSlyPW99ZWxzZSBpZihxPD0yMDQ3KXtwPW0uYgpuPXArMQppZihuPj1zKWJy
-ZWFrCm0uYj1uCmlmKHA+PXMpcmV0dXJuIEguT0godCxwKQp0W3BdPTE5MnxxPj4+NgptLmI9bisxCnRb
-bl09MTI4fHEmNjN9ZWxzZXtwPW0uYgppZihwKzI+PXMpYnJlYWsKbj1tLmI9cCsxCmlmKHA+PXMpcmV0
-dXJuIEguT0godCxwKQp0W3BdPTIyNHxxPj4+MTIKcD1tLmI9bisxCmlmKG4+PXMpcmV0dXJuIEguT0go
-dCxuKQp0W25dPTEyOHxxPj4+NiY2MwptLmI9cCsxCmlmKHA+PXMpcmV0dXJuIEguT0godCxwKQp0W3Bd
-PTEyOHxxJjYzfX1yZXR1cm4gcn19ClAuR1kucHJvdG90eXBlPXsKV0o6ZnVuY3Rpb24oYSl7dmFyIHQs
-cyxyLHEscCxvLG4sbSxsCnUuTC5iKGEpCnQ9UC5reSghMSxhLDAsbnVsbCkKaWYodCE9bnVsbClyZXR1
-cm4gdApzPVAuakIoMCxudWxsLEouSG0oYSkpCnI9UC5jUChhLDAscykKaWYocj4wKXtxPVAuSE0oYSww
-LHIpCmlmKHI9PT1zKXJldHVybiBxCnA9bmV3IFAuUm4ocSkKbz1yCm49ITF9ZWxzZXtvPTAKcD1udWxs
-Cm49ITB9aWYocD09bnVsbClwPW5ldyBQLlJuKCIiKQptPW5ldyBQLmJ6KCExLHApCm0uYz1uCm0uTUUo
-YSxvLHMpCmlmKG0uZT4wKXtILnZoKFAucnIoIlVuZmluaXNoZWQgVVRGLTggb2N0ZXQgc2VxdWVuY2Ui
-LGEscykpCnAuYSs9SC5Mdyg2NTUzMykKbS5mPW0uZT1tLmQ9MH1sPXAuYQpyZXR1cm4gbC5jaGFyQ29k
-ZUF0KDApPT0wP2w6bH19ClAuYnoucHJvdG90eXBlPXsKTUU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
-cixxLHAsbyxuLG0sbCxrLGosaSxoPXRoaXMsZz0iQmFkIFVURi04IGVuY29kaW5nIDB4Igp1LkwuYihh
-KQp0PWguZApzPWguZQpyPWguZgpoLmY9aC5lPWguZD0wCiRsYWJlbDAkMDpmb3IocT1KLlU2KGEpLHA9
-aC5iLG89YjshMDtvPWopeyRsYWJlbDEkMTppZihzPjApe2Rve2lmKG89PT1jKWJyZWFrICRsYWJlbDAk
-MApuPXEucShhLG8pCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4uek0oKQppZigobiYxOTIp
-IT09MTI4KXttPVAucnIoZytDLmpuLldaKG4sMTYpLGEsbykKdGhyb3cgSC5iKG0pfWVsc2V7dD0odDw8
-NnxuJjYzKT4+PjA7LS1zOysrb319d2hpbGUocz4wKQptPXItMQppZihtPDB8fG0+PTQpcmV0dXJuIEgu
-T0goQy5HYixtKQppZih0PD1DLkdiW21dKXttPVAucnIoIk92ZXJsb25nIGVuY29kaW5nIG9mIDB4IitD
-LmpuLldaKHQsMTYpLGEsby1yLTEpCnRocm93IEguYihtKX1pZih0PjExMTQxMTEpe209UC5ycigiQ2hh
-cmFjdGVyIG91dHNpZGUgdmFsaWQgVW5pY29kZSByYW5nZTogMHgiK0Muam4uV1oodCwxNiksYSxvLXIt
-MSkKdGhyb3cgSC5iKG0pfWlmKCFoLmN8fHQhPT02NTI3OSlwLmErPUguTHcodCkKaC5jPSExfWZvciht
-PW88YzttOyl7bD1QLmNQKGEsbyxjKQppZihsPjApe2guYz0hMQprPW8rbApwLmErPVAuSE0oYSxvLGsp
-CmlmKGs9PT1jKWJyZWFrfWVsc2Ugaz1vCmo9aysxCm49cS5xKGEsaykKaWYodHlwZW9mIG4hPT0ibnVt
-YmVyIilyZXR1cm4gbi5KKCkKaWYobjwwKXtpPVAucnIoIk5lZ2F0aXZlIFVURi04IGNvZGUgdW5pdDog
-LTB4IitDLmpuLldaKC1uLDE2KSxhLGotMSkKdGhyb3cgSC5iKGkpfWVsc2V7aWYoKG4mMjI0KT09PTE5
-Mil7dD1uJjMxCnM9MQpyPTEKY29udGludWUgJGxhYmVsMCQwfWlmKChuJjI0MCk9PT0yMjQpe3Q9biYx
-NQpzPTIKcj0yCmNvbnRpbnVlICRsYWJlbDAkMH1pZigobiYyNDgpPT09MjQwJiZuPDI0NSl7dD1uJjcK
-cz0zCnI9Mwpjb250aW51ZSAkbGFiZWwwJDB9aT1QLnJyKGcrQy5qbi5XWihuLDE2KSxhLGotMSkKdGhy
-b3cgSC5iKGkpfX1icmVhayAkbGFiZWwwJDB9aWYocz4wKXtoLmQ9dApoLmU9cwpoLmY9cn19fQpQLldG
-LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCnUuZm8uYihhKQp0PXRoaXMuYgpz
-PXRoaXMuYQp0LmErPXMuYQpyPXQuYSs9SC5kKGEuYSkKdC5hPXIrIjogIgp0LmErPVAucChiKQpzLmE9
-IiwgIn0sCiRTOjI3fQpQLmEyLnByb3RvdHlwZT17fQpQLmlQLnByb3RvdHlwZT17CkROOmZ1bmN0aW9u
-KGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4gYiBpbnN0YW5jZW9mIFAuaVAmJnRoaXMuYT09
-PWIuYSYmITB9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybih0XkMuam4ud0codCwz
-MCkpJjEwNzM3NDE4MjN9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz1QLkdxKEgudEoodCkpLHI9
-UC5oMChILk5TKHQpKSxxPVAuaDAoSC5qQSh0KSkscD1QLmgwKEguS0wodCkpLG89UC5oMChILmNoKHQp
-KSxuPVAuaDAoSC5KZCh0KSksbT1QLlZ4KEgubzEodCkpLGw9cysiLSIrcisiLSIrcSsiICIrcCsiOiIr
-bysiOiIrbisiLiIrbQpyZXR1cm4gbH19ClAuQ1AucHJvdG90eXBlPXt9ClAuWFMucHJvdG90eXBlPXt9
-ClAuQzYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKaWYodCE9bnVsbClyZXR1
-cm4iQXNzZXJ0aW9uIGZhaWxlZDogIitQLnAodCkKcmV0dXJuIkFzc2VydGlvbiBmYWlsZWQifX0KUC5u
-LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlRocm93IG9mIG51bGwuIn19ClAudS5wcm90
-b3R5cGU9ewpnWjpmdW5jdGlvbigpe3JldHVybiJJbnZhbGlkIGFyZ3VtZW50IisoIXRoaXMuYT8iKHMp
-IjoiIil9LApndTpmdW5jdGlvbigpe3JldHVybiIifSwKdzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxw
-PXRoaXMsbz1wLmMsbj1vIT1udWxsPyIgKCIrbysiKSI6IiIKbz1wLmQKdD1vPT1udWxsPyIiOiI6ICIr
-SC5kKG8pCnM9cC5nWigpK24rdAppZighcC5hKXJldHVybiBzCnI9cC5ndSgpCnE9UC5wKHAuYikKcmV0
-dXJuIHMrcisiOiAiK3F9fQpQLmJKLnByb3RvdHlwZT17CmdaOmZ1bmN0aW9uKCl7cmV0dXJuIlJhbmdl
-RXJyb3IifSwKZ3U6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcy5lCmlmKHI9PW51bGwpe3I9dGhpcy5m
-CnQ9ciE9bnVsbD8iOiBOb3QgbGVzcyB0aGFuIG9yIGVxdWFsIHRvICIrSC5kKHIpOiIifWVsc2V7cz10
-aGlzLmYKaWYocz09bnVsbCl0PSI6IE5vdCBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gIitILmQocikK
-ZWxzZSBpZihzPnIpdD0iOiBOb3QgaW4gcmFuZ2UgIitILmQocikrIi4uIitILmQocykrIiwgaW5jbHVz
-aXZlIgplbHNlIHQ9czxyPyI6IFZhbGlkIHZhbHVlIHJhbmdlIGlzIGVtcHR5IjoiOiBPbmx5IHZhbGlk
-IHZhbHVlIGlzICIrSC5kKHIpfXJldHVybiB0fX0KUC5lWS5wcm90b3R5cGU9ewpnWjpmdW5jdGlvbigp
-e3JldHVybiJSYW5nZUVycm9yIn0sCmd1OmZ1bmN0aW9uKCl7dmFyIHQscz1ILlNjKHRoaXMuYikKaWYo
-dHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5KKCkKaWYoczwwKXJldHVybiI6IGluZGV4IG11c3Qg
-bm90IGJlIG5lZ2F0aXZlIgp0PXRoaXMuZgppZih0PT09MClyZXR1cm4iOiBubyBpbmRpY2VzIGFyZSB2
-YWxpZCIKcmV0dXJuIjogaW5kZXggc2hvdWxkIGJlIGxlc3MgdGhhbiAiK0guZCh0KX0sCmdBOmZ1bmN0
-aW9uKGEpe3JldHVybiB0aGlzLmZ9fQpQLm1wLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQs
-cyxyLHEscCxvLG4sbSxsPXRoaXMsaz17fSxqPW5ldyBQLlJuKCIiKQprLmE9IiIKZm9yKHQ9bC5jLHM9
-dC5sZW5ndGgscj0wLHE9IiIscD0iIjtyPHM7KytyLHA9IiwgIil7bz10W3JdCmouYT1xK3AKcT1qLmEr
-PVAucChvKQprLmE9IiwgIn1sLmQuSygwLG5ldyBQLldGKGssaikpCm49UC5wKGwuYSkKbT1qLncoMCkK
-dD0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciK0guZChsLmIuYSkrIidcblJl
-Y2VpdmVyOiAiK24rIlxuQXJndW1lbnRzOiBbIittKyJdIgpyZXR1cm4gdH19ClAudWIucHJvdG90eXBl
-PXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iVW5zdXBwb3J0ZWQgb3BlcmF0aW9uOiAiK3RoaXMuYX19ClAu
-ZHMucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQhPW51bGw/IlVu
-aW1wbGVtZW50ZWRFcnJvcjogIit0OiJVbmltcGxlbWVudGVkRXJyb3IifX0KUC5sai5wcm90b3R5cGU9
-ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJCYWQgc3RhdGU6ICIrdGhpcy5hfX0KUC5VVi5wcm90b3R5cGU9
-ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQppZih0PT1udWxsKXJldHVybiJDb25jdXJyZW50IG1v
-ZGlmaWNhdGlvbiBkdXJpbmcgaXRlcmF0aW9uLiIKcmV0dXJuIkNvbmN1cnJlbnQgbW9kaWZpY2F0aW9u
-IGR1cmluZyBpdGVyYXRpb246ICIrUC5wKHQpKyIuIn19ClAuazUucHJvdG90eXBlPXsKdzpmdW5jdGlv
-bihhKXtyZXR1cm4iT3V0IG9mIE1lbW9yeSJ9LAokaVhTOjF9ClAuS1kucHJvdG90eXBlPXsKdzpmdW5j
-dGlvbihhKXtyZXR1cm4iU3RhY2sgT3ZlcmZsb3cifSwKJGlYUzoxfQpQLmMucHJvdG90eXBlPXsKdzpm
-dW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQ9PW51bGw/IlJlYWRpbmcgc3RhdGljIHZhcmlh
-YmxlIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24iOiJSZWFkaW5nIHN0YXRpYyB2YXJpYWJsZSAnIit0
-KyInIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24ifX0KUC5DRC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9u
-KGEpe3JldHVybiJFeGNlcHRpb246ICIrdGhpcy5hfX0KUC5hRS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9u
-KGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoPXRoaXMuYSxnPWghPW51bGwmJiIiIT09aD8i
-Rm9ybWF0RXhjZXB0aW9uOiAiK0guZChoKToiRm9ybWF0RXhjZXB0aW9uIixmPXRoaXMuYyxlPXRoaXMu
-YgppZih0eXBlb2YgZT09InN0cmluZyIpe2lmKGYhPW51bGwpaD1mPDB8fGY+ZS5sZW5ndGgKZWxzZSBo
-PSExCmlmKGgpZj1udWxsCmlmKGY9PW51bGwpe3Q9ZS5sZW5ndGg+Nzg/Qy54Qi5OaihlLDAsNzUpKyIu
-Li4iOmUKcmV0dXJuIGcrIlxuIit0fWZvcihzPTEscj0wLHE9ITEscD0wO3A8ZjsrK3Ape289Qy54Qi5X
-KGUscCkKaWYobz09PTEwKXtpZihyIT09cHx8IXEpKytzCnI9cCsxCnE9ITF9ZWxzZSBpZihvPT09MTMp
-eysrcwpyPXArMQpxPSEwfX1nPXM+MT9nKygiIChhdCBsaW5lICIrcysiLCBjaGFyYWN0ZXIgIisoZi1y
-KzEpKyIpXG4iKTpnKygiIChhdCBjaGFyYWN0ZXIgIisoZisxKSsiKVxuIikKbj1lLmxlbmd0aApmb3Io
-cD1mO3A8bjsrK3Ape289Qy54Qi5tKGUscCkKaWYobz09PTEwfHxvPT09MTMpe249cApicmVha319aWYo
-bi1yPjc4KWlmKGYtcjw3NSl7bT1yKzc1Cmw9cgprPSIiCmo9Ii4uLiJ9ZWxzZXtpZihuLWY8NzUpe2w9
-bi03NQptPW4Kaj0iIn1lbHNle2w9Zi0zNgptPWYrMzYKaj0iLi4uIn1rPSIuLi4ifWVsc2V7bT1uCmw9
-cgprPSIiCmo9IiJ9aT1DLnhCLk5qKGUsbCxtKQpyZXR1cm4gZytrK2kraisiXG4iK0MueEIuSXgoIiAi
-LGYtbCtrLmxlbmd0aCkrIl5cbiJ9ZWxzZSByZXR1cm4gZiE9bnVsbD9nKygiIChhdCBvZmZzZXQgIitI
-LmQoZikrIikiKTpnfX0KUC5FSC5wcm90b3R5cGU9e30KUC5LTi5wcm90b3R5cGU9e30KUC5jWC5wcm90
-b3R5cGU9ewpldjpmdW5jdGlvbihhLGIpe3ZhciB0PUguTGgodGhpcykKcmV0dXJuIG5ldyBILlU1KHRo
-aXMsdC5DKCJhMihjWC5FKSIpLmIoYiksdC5DKCJVNTxjWC5FPiIpKX0sCmdBOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHM9dGhpcy5na3oodGhpcykKZm9yKHQ9MDtzLkYoKTspKyt0CnJldHVybiB0fSwKZ2wwOmZ1bmN0
-aW9uKGEpe3JldHVybiF0aGlzLmdreih0aGlzKS5GKCl9LApncjg6ZnVuY3Rpb24oYSl7dmFyIHQscz10
-aGlzLmdreih0aGlzKQppZighcy5GKCkpdGhyb3cgSC5iKEguV3AoKSkKdD1zLmdsKCkKaWYocy5GKCkp
-dGhyb3cgSC5iKEguZFUoKSkKcmV0dXJuIHR9LApFOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyClAuazEo
-YiwiaW5kZXgiKQpmb3IodD10aGlzLmdreih0aGlzKSxzPTA7dC5GKCk7KXtyPXQuZ2woKQppZihiPT09
-cylyZXR1cm4gcjsrK3N9dGhyb3cgSC5iKFAuQ2YoYix0aGlzLCJpbmRleCIsbnVsbCxzKSl9LAp3OmZ1
-bmN0aW9uKGEpe3JldHVybiBQLkVQKHRoaXMsIigiLCIpIil9fQpQLkFuLnByb3RvdHlwZT17fQpQLnpN
-LnByb3RvdHlwZT17JGljWDoxfQpQLlowLnByb3RvdHlwZT17fQpQLmM4LnByb3RvdHlwZT17CmdpTzpm
-dW5jdGlvbihhKXtyZXR1cm4gUC5rLnByb3RvdHlwZS5naU8uY2FsbCh0aGlzLHRoaXMpfSwKdzpmdW5j
-dGlvbihhKXtyZXR1cm4ibnVsbCJ9fQpQLkZLLnByb3RvdHlwZT17fQpQLmsucHJvdG90eXBlPXtjb25z
-dHJ1Y3RvcjpQLmssJGlrOjEsCkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXM9PT1ifSwKZ2lPOmZ1
-bmN0aW9uKGEpe3JldHVybiBILmVRKHRoaXMpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ug
-b2YgJyIrSC5kKEguTSh0aGlzKSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt1Lm8uYihiKQp0aHJvdyBI
-LmIoUC5scih0aGlzLGIuZ1dhKCksYi5nbmQoKSxiLmdWbSgpKSl9LAp0b1N0cmluZzpmdW5jdGlvbigp
-e3JldHVybiB0aGlzLncodGhpcyl9fQpQLk9kLnByb3RvdHlwZT17fQpQLmliLnByb3RvdHlwZT17JGlP
-ZDoxfQpQLnh1LnByb3RvdHlwZT17fQpQLkd6LnByb3RvdHlwZT17fQpQLnFVLnByb3RvdHlwZT17JGl2
-WDoxfQpQLlJuLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEubGVuZ3RofSwK
-dzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAok
-aUJMOjF9ClAuR0QucHJvdG90eXBlPXt9ClAubjEucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2
-YXIgdCxzLHIscQp1LmYuYihhKQpILnkoYikKdD1KLnJZKGIpLk9ZKGIsIj0iKQppZih0PT09LTEpe2lm
-KGIhPT0iIilhLlkoMCxQLmt1KGIsMCxiLmxlbmd0aCx0aGlzLmEsITApLCIiKX1lbHNlIGlmKHQhPT0w
-KXtzPUMueEIuTmooYiwwLHQpCnI9Qy54Qi5HKGIsdCsxKQpxPXRoaXMuYQphLlkoMCxQLmt1KHMsMCxz
-Lmxlbmd0aCxxLCEwKSxQLmt1KHIsMCxyLmxlbmd0aCxxLCEwKSl9cmV0dXJuIGF9LAokUzoyNn0KUC5j
-Uy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3Rocm93IEguYihQLnJyKCJJbGxlZ2FsIElQdjQg
-YWRkcmVzcywgIithLHRoaXMuYSxiKSl9LAokUzoyM30KUC5WQy5wcm90b3R5cGU9ewokMjpmdW5jdGlv
-bihhLGIpe3Rocm93IEguYihQLnJyKCJJbGxlZ2FsIElQdjYgYWRkcmVzcywgIithLHRoaXMuYSxiKSl9
-LAokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy4kMihhLG51bGwpfSwKJFM6MjJ9ClAudHAucHJvdG90
-eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihiLWE+NCl0aGlzLmEuJDIoImFuIElQdjYgcGFy
-dCBjYW4gb25seSBjb250YWluIGEgbWF4aW11bSBvZiA0IGhleCBkaWdpdHMiLGEpCnQ9UC5RQShDLnhC
-Lk5qKHRoaXMuYixhLGIpLG51bGwsMTYpCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigp
-CmlmKHQ8MHx8dD42NTUzNSl0aGlzLmEuJDIoImVhY2ggcGFydCBtdXN0IGJlIGluIHRoZSByYW5nZSBv
-ZiBgMHgwLi4weEZGRkZgIixhKQpyZXR1cm4gdH0sCiRTOjE4fQpQLkRuLnByb3RvdHlwZT17CmdrdTpm
-dW5jdGlvbigpe3JldHVybiB0aGlzLmJ9LApnSmY6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCmlmKHQ9
-PW51bGwpcmV0dXJuIiIKaWYoQy54Qi5uKHQsIlsiKSlyZXR1cm4gQy54Qi5Oaih0LDEsdC5sZW5ndGgt
-MSkKcmV0dXJuIHR9LApndHA6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJu
-IFAud0sodGhpcy5hKQpyZXR1cm4gdH0sCmd0UDpmdW5jdGlvbigpe3ZhciB0PXRoaXMuZgpyZXR1cm4g
-dD09bnVsbD8iIjp0fSwKZ0thOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yCnJldHVybiB0PT1udWxsPyIi
-OnR9LApubTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbD10aGlzCnUuWC5iKG51bGwp
-CnUuYS5iKGIpCnQ9bC5hCnM9dD09PSJmaWxlIgpyPWwuYgpxPWwuZApwPWwuYwppZighKHAhPW51bGwp
-KXA9ci5sZW5ndGghPT0wfHxxIT1udWxsfHxzPyIiOm51bGwKbz1sLmUKaWYoIXMpbj1wIT1udWxsJiZv
-Lmxlbmd0aCE9PTAKZWxzZSBuPSEwCmlmKG4mJiFDLnhCLm4obywiLyIpKW89Ii8iK28KaWYoYiE9bnVs
-bCltPVAubGUobnVsbCwwLDAsYikKZWxzZSBtPWwuZgpyZXR1cm4gbmV3IFAuRG4odCxyLHAscSxvLG0s
-bC5yKX0sCmdGajpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcy54CmlmKHMhPW51bGwpcmV0dXJuIHMKdD10
-aGlzLmUKaWYodC5sZW5ndGghPT0wJiZDLnhCLlcodCwwKT09PTQ3KXQ9Qy54Qi5HKHQsMSkKcz10PT09
-IiI/Qy54RDpQLkFGKG5ldyBILkE4KEguVk0odC5zcGxpdCgiLyIpLHUucyksdS5kTy5iKFAuUEgoKSks
-dS5kbyksdS5OKQp0aGlzLnNvNihzKQpyZXR1cm4gc30sCmdoWTpmdW5jdGlvbigpe3ZhciB0LHM9dGhp
-cwppZihzLlE9PW51bGwpe3Q9cy5mCnMuc1JIKG5ldyBQLkdqKFAuV1godD09bnVsbD8iIjp0KSx1LlQp
-KX1yZXR1cm4gcy5RfSwKSmg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8KZm9yKHQ9MCxzPTA7
-Qy54Qi5RaShiLCIuLi8iLHMpOyl7cys9MzsrK3R9cj1DLnhCLmNuKGEsIi8iKQp3aGlsZSghMCl7aWYo
-IShyPjAmJnQ+MCkpYnJlYWsKcT1DLnhCLlBrKGEsIi8iLHItMSkKaWYocTwwKWJyZWFrCnA9ci1xCm89
-cCE9PTIKaWYoIW98fHA9PT0zKWlmKEMueEIubShhLHErMSk9PT00NilvPSFvfHxDLnhCLm0oYSxxKzIp
-PT09NDYKZWxzZSBvPSExCmVsc2Ugbz0hMQppZihvKWJyZWFrOy0tdApyPXF9cmV0dXJuIEMueEIuaTco
-YSxyKzEsbnVsbCxDLnhCLkcoYixzLTMqdCkpfSwKWkk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMubVMo
-UC5oSyhhKSl9LAptUzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsaz10aGlzLGo9bnVs
-bAppZihhLmdGaSgpLmxlbmd0aCE9PTApe3Q9YS5nRmkoKQppZihhLmdjaigpKXtzPWEuZ2t1KCkKcj1h
-LmdKZihhKQpxPWEuZ3hBKCk/YS5ndHAoYSk6an1lbHNle3E9agpyPXEKcz0iIn1wPVAueGUoYS5nSWko
-YSkpCm89YS5nUUQoKT9hLmd0UCgpOmp9ZWxzZXt0PWsuYQppZihhLmdjaigpKXtzPWEuZ2t1KCkKcj1h
-LmdKZihhKQpxPVAud0IoYS5neEEoKT9hLmd0cChhKTpqLHQpCnA9UC54ZShhLmdJaShhKSkKbz1hLmdR
-RCgpP2EuZ3RQKCk6an1lbHNle3M9ay5iCnI9ay5jCnE9ay5kCmlmKGEuZ0lpKGEpPT09IiIpe3A9ay5l
-Cm89YS5nUUQoKT9hLmd0UCgpOmsuZn1lbHNle2lmKGEuZ3RUKCkpcD1QLnhlKGEuZ0lpKGEpKQplbHNl
-e249ay5lCmlmKG4ubGVuZ3RoPT09MClpZihyPT1udWxsKXA9dC5sZW5ndGg9PT0wP2EuZ0lpKGEpOlAu
-eGUoYS5nSWkoYSkpCmVsc2UgcD1QLnhlKCIvIithLmdJaShhKSkKZWxzZXttPWsuSmgobixhLmdJaShh
-KSkKbD10Lmxlbmd0aD09PTAKaWYoIWx8fHIhPW51bGx8fEMueEIubihuLCIvIikpcD1QLnhlKG0pCmVs
-c2UgcD1QLndGKG0sIWx8fHIhPW51bGwpfX1vPWEuZ1FEKCk/YS5ndFAoKTpqfX19cmV0dXJuIG5ldyBQ
-LkRuKHQscyxyLHEscCxvLGEuZ1o4KCk/YS5nS2EoKTpqKX0sCmdjajpmdW5jdGlvbigpe3JldHVybiB0
-aGlzLmMhPW51bGx9LApneEE6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kIT1udWxsfSwKZ1FEOmZ1bmN0
-aW9uKCl7cmV0dXJuIHRoaXMuZiE9bnVsbH0sCmdaODpmdW5jdGlvbigpe3JldHVybiB0aGlzLnIhPW51
-bGx9LApndFQ6ZnVuY3Rpb24oKXtyZXR1cm4gQy54Qi5uKHRoaXMuZSwiLyIpfSwKdDQ6ZnVuY3Rpb24o
-KXt2YXIgdCxzLHI9dGhpcyxxPXIuYQppZihxIT09IiImJnEhPT0iZmlsZSIpdGhyb3cgSC5iKFAuTDQo
-IkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSAiK0guZChxKSsiIFVSSSIpKQpxPXIuZgpp
-ZigocT09bnVsbD8iIjpxKSE9PSIiKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZpbGUg
-cGF0aCBmcm9tIGEgVVJJIHdpdGggYSBxdWVyeSBjb21wb25lbnQiKSkKcT1yLnIKaWYoKHE9PW51bGw/
-IiI6cSkhPT0iIil0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBh
-IFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50IikpCnQ9JC53USgpCmlmKEgub1QodCkpcT1QLm1u
-KHIpCmVsc2V7aWYoci5jIT1udWxsJiZyLmdKZihyKSE9PSIiKUgudmgoUC5MNCgiQ2Fubm90IGV4dHJh
-Y3QgYSBub24tV2luZG93cyBmaWxlIHBhdGggZnJvbSBhIGZpbGUgVVJJIHdpdGggYW4gYXV0aG9yaXR5
-IikpCnM9ci5nRmooKQpQLmtFKHMsITEpCnE9UC52ZyhDLnhCLm4oci5lLCIvIik/Ii8iOiIiLHMsIi8i
-KQpxPXEuY2hhckNvZGVBdCgwKT09MD9xOnF9cmV0dXJuIHF9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0LHMs
-cixxPXRoaXMscD1xLnkKaWYocD09bnVsbCl7cD1xLmEKdD1wLmxlbmd0aCE9PTA/cCsiOiI6IiIKcz1x
-LmMKcj1zPT1udWxsCmlmKCFyfHxwPT09ImZpbGUiKXtwPXQrIi8vIgp0PXEuYgppZih0Lmxlbmd0aCE9
-PTApcD1wK3QrIkAiCmlmKCFyKXArPXMKdD1xLmQKaWYodCE9bnVsbClwPXArIjoiK0guZCh0KX1lbHNl
-IHA9dApwKz1xLmUKdD1xLmYKaWYodCE9bnVsbClwPXArIj8iK3QKdD1xLnIKaWYodCE9bnVsbClwPXAr
-IiMiK3QKcD1xLnk9cC5jaGFyQ29kZUF0KDApPT0wP3A6cH1yZXR1cm4gcH0sCkROOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQscyxyPXRoaXMKaWYoYj09bnVsbClyZXR1cm4hMQppZihyPT09YilyZXR1cm4hMAppZih1
-LncuYyhiKSlpZihyLmE9PWIuZ0ZpKCkpaWYoci5jIT1udWxsPT09Yi5nY2ooKSlpZihyLmI9PWIuZ2t1
-KCkpaWYoci5nSmYocik9PWIuZ0pmKGIpKWlmKHIuZ3RwKHIpPT1iLmd0cChiKSlpZihyLmU9PT1iLmdJ
-aShiKSl7dD1yLmYKcz10PT1udWxsCmlmKCFzPT09Yi5nUUQoKSl7aWYocyl0PSIiCmlmKHQ9PT1iLmd0
-UCgpKXt0PXIucgpzPXQ9PW51bGwKaWYoIXM9PT1iLmdaOCgpKXtpZihzKXQ9IiIKdD10PT09Yi5nS2Eo
-KX1lbHNlIHQ9ITF9ZWxzZSB0PSExfWVsc2UgdD0hMX1lbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0h
-MQplbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKcmV0dXJuIHR9LApnaU86ZnVu
-Y3Rpb24oYSl7dmFyIHQ9dGhpcy56CnJldHVybiB0PT1udWxsP3RoaXMuej1DLnhCLmdpTyh0aGlzLnco
-MCkpOnR9LApzbzY6ZnVuY3Rpb24oYSl7dGhpcy54PXUuaS5iKGEpfSwKc1JIOmZ1bmN0aW9uKGEpe3Ro
-aXMuUT11LmYuYihhKX0sCiRpaUQ6MSwKZ0ZpOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYX0sCmdJaTpm
-dW5jdGlvbihhKXtyZXR1cm4gdGhpcy5lfX0KUC5lMS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt0
-aHJvdyBILmIoUC5ycigiSW52YWxpZCBwb3J0Iix0aGlzLmEsdGhpcy5iKzEpKX0sCiRTOjE3fQpQLk5Z
-LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PSJJbGxlZ2FsIHBhdGggY2hhcmFjdGVyICIK
-SC55KGEpCmlmKEouemwoYSwiLyIpKWlmKHRoaXMuYSl0aHJvdyBILmIoUC54WSh0K2EpKQplbHNlIHRo
-cm93IEguYihQLkw0KHQrYSkpfSwKJFM6MTd9ClAuUloucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7
-cmV0dXJuIFAuZVAoQy5aSixhLEMueE0sITEpfSwKJFM6Nn0KUC5NRS5wcm90b3R5cGU9ewokMjpmdW5j
-dGlvbihhLGIpe3ZhciB0PXRoaXMuYixzPXRoaXMuYQp0LmErPXMuYQpzLmE9IiYiCnM9dC5hKz1ILmQo
-UC5lUChDLkYzLGEsQy54TSwhMCkpCmlmKGIhPW51bGwmJmIubGVuZ3RoIT09MCl7dC5hPXMrIj0iCnQu
-YSs9SC5kKFAuZVAoQy5GMyxiLEMueE0sITApKX19LAokUzoxOX0KUC55NS5wcm90b3R5cGU9ewokMjpm
-dW5jdGlvbihhLGIpe3ZhciB0LHMKSC55KGEpCmlmKGI9PW51bGx8fHR5cGVvZiBiPT0ic3RyaW5nIil0
-aGlzLmEuJDIoYSxILnkoYikpCmVsc2UgZm9yKHQ9Si5JVCh1LlIuYihiKSkscz10aGlzLmE7dC5GKCk7
-KXMuJDIoYSxILnkodC5nbCgpKSl9LAokUzoxNn0KUC5QRS5wcm90b3R5cGU9ewpnbFI6ZnVuY3Rpb24o
-KXt2YXIgdCxzLHIscSxwPXRoaXMsbz1udWxsLG49cC5jCmlmKG4hPW51bGwpcmV0dXJuIG4Kbj1wLmIK
-aWYoMD49bi5sZW5ndGgpcmV0dXJuIEguT0gobiwwKQp0PXAuYQpuPW5bMF0rMQpzPUMueEIuWFUodCwi
-PyIsbikKcj10Lmxlbmd0aAppZihzPj0wKXtxPVAudU8odCxzKzEscixDLlZDLCExKQpyPXN9ZWxzZSBx
-PW8KcmV0dXJuIHAuYz1uZXcgUC5xZSgiZGF0YSIsbyxvLG8sUC51Tyh0LG4scixDLldkLCExKSxxLG8p
-fSwKdzpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMuYgppZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChz
-LDApCnQ9dGhpcy5hCnJldHVybiBzWzBdPT09LTE/ImRhdGE6Iit0OnR9fQpQLnEzLnByb3RvdHlwZT17
-CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVWludDhBcnJheSg5Nil9LAokUzoyMH0KUC55SS5wcm90
-b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYQppZihhPj10Lmxlbmd0aClyZXR1cm4g
-SC5PSCh0LGEpCnQ9dFthXQpKLkNNKHQsMCw5NixiKQpyZXR1cm4gdH0sCiRTOjIxfQpQLmM2LnByb3Rv
-dHlwZT17CiQzOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQpmb3IodD1iLmxlbmd0aCxzPWEubGVu
-Z3RoLHI9MDtyPHQ7KytyKXtxPUMueEIuVyhiLHIpXjk2CmlmKHE+PXMpcmV0dXJuIEguT0goYSxxKQph
-W3FdPWN9fX0KUC5xZC5wcm90b3R5cGU9ewokMzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEKZm9y
-KHQ9Qy54Qi5XKGIsMCkscz1DLnhCLlcoYiwxKSxyPWEubGVuZ3RoO3Q8PXM7Kyt0KXtxPSh0Xjk2KT4+
-PjAKaWYocT49cilyZXR1cm4gSC5PSChhLHEpCmFbcV09Y319fQpQLlVmLnByb3RvdHlwZT17Cmdjajpm
-dW5jdGlvbigpe3JldHVybiB0aGlzLmM+MH0sCmd4QTpmdW5jdGlvbigpe3ZhciB0LHMKaWYodGhpcy5j
-PjApe3Q9dGhpcy5kCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCnM9dGhpcy5lCmlm
-KHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIEgucFkocykKcz10KzE8cwp0PXN9ZWxzZSB0PSExCnJl
-dHVybiB0fSwKZ1FEOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5mCmlmKHR5cGVvZiB0IT09Im51bWJlciIp
-cmV0dXJuIHQuSigpCnJldHVybiB0PHRoaXMucn0sCmdaODpmdW5jdGlvbigpe3JldHVybiB0aGlzLnI8
-dGhpcy5hLmxlbmd0aH0sCmdOdzpmdW5jdGlvbigpe3JldHVybiB0aGlzLmI9PT00JiZDLnhCLm4odGhp
-cy5hLCJmaWxlIil9LApndmg6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NCYmQy54Qi5uKHRoaXMu
-YSwiaHR0cCIpfSwKZ3FCOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTUmJkMueEIubih0aGlzLmEs
-Imh0dHBzIil9LApndFQ6ZnVuY3Rpb24oKXtyZXR1cm4gQy54Qi5RaSh0aGlzLmEsIi8iLHRoaXMuZSl9
-LApnRmk6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMscj0icGFja2FnZSIscT1zLmIKaWYocTw9MClyZXR1
-cm4iIgp0PXMueAppZih0IT1udWxsKXJldHVybiB0CmlmKHMuZ3ZoKCkpcT1zLng9Imh0dHAiCmVsc2Ug
-aWYocy5ncUIoKSl7cy54PSJodHRwcyIKcT0iaHR0cHMifWVsc2UgaWYocy5nTncoKSl7cy54PSJmaWxl
-IgpxPSJmaWxlIn1lbHNlIGlmKHE9PT03JiZDLnhCLm4ocy5hLHIpKXtzLng9cgpxPXJ9ZWxzZXtxPUMu
-eEIuTmoocy5hLDAscSkKcy54PXF9cmV0dXJuIHF9LApna3U6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmMs
-cz10aGlzLmIrMwpyZXR1cm4gdD5zP0MueEIuTmoodGhpcy5hLHMsdC0xKToiIn0sCmdKZjpmdW5jdGlv
-bihhKXt2YXIgdD10aGlzLmMKcmV0dXJuIHQ+MD9DLnhCLk5qKHRoaXMuYSx0LHRoaXMuZCk6IiJ9LApn
-dHA6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzCmlmKHMuZ3hBKCkpe3Q9cy5kCmlmKHR5cGVvZiB0IT09
-Im51bWJlciIpcmV0dXJuIHQuaCgpCnJldHVybiBQLlFBKEMueEIuTmoocy5hLHQrMSxzLmUpLG51bGws
-bnVsbCl9aWYocy5ndmgoKSlyZXR1cm4gODAKaWYocy5ncUIoKSlyZXR1cm4gNDQzCnJldHVybiAwfSwK
-Z0lpOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLk5qKHRoaXMuYSx0aGlzLmUsdGhpcy5mKX0sCmd0UDpm
-dW5jdGlvbigpe3ZhciB0PXRoaXMuZixzPXRoaXMucgppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVy
-biB0LkooKQpyZXR1cm4gdDxzP0MueEIuTmoodGhpcy5hLHQrMSxzKToiIn0sCmdLYTpmdW5jdGlvbigp
-e3ZhciB0PXRoaXMucixzPXRoaXMuYQpyZXR1cm4gdDxzLmxlbmd0aD9DLnhCLkcocyx0KzEpOiIifSwK
-Z0ZqOmZ1bmN0aW9uKCl7dmFyIHQscyxyPXRoaXMuZSxxPXRoaXMuZixwPXRoaXMuYQppZihDLnhCLlFp
-KHAsIi8iLHIpKXtpZih0eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiByLmgoKTsrK3J9aWYocj09cSly
-ZXR1cm4gQy54RAp0PUguVk0oW10sdS5zKQpzPXIKd2hpbGUoITApe2lmKHR5cGVvZiBzIT09Im51bWJl
-ciIpcmV0dXJuIHMuSigpCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIEgucFkocSkKaWYoIShz
-PHEpKWJyZWFrCmlmKEMueEIubShwLHMpPT09NDcpe0MuTm0uaSh0LEMueEIuTmoocCxyLHMpKQpyPXMr
-MX0rK3N9Qy5ObS5pKHQsQy54Qi5OaihwLHIscSkpCnJldHVybiBQLkFGKHQsdS5OKX0sCmdoWTpmdW5j
-dGlvbigpe3ZhciB0PXRoaXMuZgppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkooKQppZih0
-Pj10aGlzLnIpcmV0dXJuIEMuV08KcmV0dXJuIG5ldyBQLkdqKFAuV1godGhpcy5ndFAoKSksdS5UKX0s
-CmtYOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5kCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJu
-IHMuaCgpCnQ9cysxCnJldHVybiB0K2EubGVuZ3RoPT09dGhpcy5lJiZDLnhCLlFpKHRoaXMuYSxhLHQp
-fSwKTjk6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5yLHI9dC5hCmlmKHM+PXIubGVuZ3RoKXJldHVy
-biB0CnJldHVybiBuZXcgUC5VZihDLnhCLk5qKHIsMCxzKSx0LmIsdC5jLHQuZCx0LmUsdC5mLHMsdC54
-KX0sCm5tOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpPXRoaXMsaD1udWxs
-CnUuWC5iKG51bGwpCnUuYS5iKGIpCnQ9aS5nRmkoKQpzPXQ9PT0iZmlsZSIKcj1pLmMKcT1yPjA/Qy54
-Qi5OaihpLmEsaS5iKzMscik6IiIKcD1pLmd4QSgpP2kuZ3RwKGkpOmgKcj1pLmMKaWYocj4wKW89Qy54
-Qi5OaihpLmEscixpLmQpCmVsc2Ugbz1xLmxlbmd0aCE9PTB8fHAhPW51bGx8fHM/IiI6aApyPWkuYQpu
-PWkuZgptPUMueEIuTmoocixpLmUsbikKaWYoIXMpbD1vIT1udWxsJiZtLmxlbmd0aCE9PTAKZWxzZSBs
-PSEwCmlmKGwmJiFDLnhCLm4obSwiLyIpKW09Ii8iK20KaWYoYiE9bnVsbClrPVAubGUoaCwwLDAsYikK
-ZWxzZXtsPWkucgppZih0eXBlb2YgbiE9PSJudW1iZXIiKXJldHVybiBuLkooKQprPW48bD9DLnhCLk5q
-KHIsbisxLGwpOmh9bj1pLnIKaj1uPHIubGVuZ3RoP0MueEIuRyhyLG4rMSk6aApyZXR1cm4gbmV3IFAu
-RG4odCxxLG8scCxtLGssail9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5tUyhQLmhLKGEpKX0s
-Cm1TOmZ1bmN0aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBQLlVmKXJldHVybiB0aGlzLnUxKHRoaXMsYSkK
-cmV0dXJuIHRoaXMuUmUoKS5tUyhhKX0sCnUxOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4s
-bSxsLGssaixpLGgsZyxmLGU9Yi5iCmlmKGU+MClyZXR1cm4gYgp0PWIuYwppZih0PjApe3M9YS5iCmlm
-KHM8PTApcmV0dXJuIGIKaWYoYS5nTncoKSlyPWIuZSE9Yi5mCmVsc2UgaWYoYS5ndmgoKSlyPSFiLmtY
-KCI4MCIpCmVsc2Ugcj0hYS5ncUIoKXx8IWIua1goIjQ0MyIpCmlmKHIpe3E9cysxCnA9Qy54Qi5Oaihh
-LmEsMCxxKStDLnhCLkcoYi5hLGUrMSkKZT1iLmQKaWYodHlwZW9mIGUhPT0ibnVtYmVyIilyZXR1cm4g
-ZS5oKCkKbz1iLmUKaWYodHlwZW9mIG8hPT0ibnVtYmVyIilyZXR1cm4gby5oKCkKbj1iLmYKaWYodHlw
-ZW9mIG4hPT0ibnVtYmVyIilyZXR1cm4gbi5oKCkKcmV0dXJuIG5ldyBQLlVmKHAscyx0K3EsZStxLG8r
-cSxuK3EsYi5yK3EsYS54KX1lbHNlIHJldHVybiB0aGlzLlJlKCkubVMoYil9bT1iLmUKZT1iLmYKaWYo
-bT09ZSl7dD1iLnIKaWYodHlwZW9mIGUhPT0ibnVtYmVyIilyZXR1cm4gZS5KKCkKaWYoZTx0KXtzPWEu
-ZgppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLkhOKCkKcT1zLWUKcmV0dXJuIG5ldyBQLlVm
-KEMueEIuTmooYS5hLDAscykrQy54Qi5HKGIuYSxlKSxhLmIsYS5jLGEuZCxhLmUsZStxLHQrcSxhLngp
-fWU9Yi5hCmlmKHQ8ZS5sZW5ndGgpe3M9YS5yCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGEuYSwwLHMp
-K0MueEIuRyhlLHQpLGEuYixhLmMsYS5kLGEuZSxhLmYsdCsocy10KSxhLngpfXJldHVybiBhLk45KCl9
-dD1iLmEKaWYoQy54Qi5RaSh0LCIvIixtKSl7cz1hLmUKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1
-cm4gcy5ITigpCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIEgucFkobSkKcT1zLW0KcD1DLnhC
-Lk5qKGEuYSwwLHMpK0MueEIuRyh0LG0pCmlmKHR5cGVvZiBlIT09Im51bWJlciIpcmV0dXJuIGUuaCgp
-CnJldHVybiBuZXcgUC5VZihwLGEuYixhLmMsYS5kLHMsZStxLGIucitxLGEueCl9bD1hLmUKaz1hLmYK
-aWYobD09ayYmYS5jPjApe2Zvcig7Qy54Qi5RaSh0LCIuLi8iLG0pOyl7aWYodHlwZW9mIG0hPT0ibnVt
-YmVyIilyZXR1cm4gbS5oKCkKbSs9M31pZih0eXBlb2YgbCE9PSJudW1iZXIiKXJldHVybiBsLkhOKCkK
-aWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gSC5wWShtKQpxPWwtbSsxCnA9Qy54Qi5OaihhLmEs
-MCxsKSsiLyIrQy54Qi5HKHQsbSkKaWYodHlwZW9mIGUhPT0ibnVtYmVyIilyZXR1cm4gZS5oKCkKcmV0
-dXJuIG5ldyBQLlVmKHAsYS5iLGEuYyxhLmQsbCxlK3EsYi5yK3EsYS54KX1qPWEuYQpmb3IoaT1sO0Mu
-eEIuUWkoaiwiLi4vIixpKTspe2lmKHR5cGVvZiBpIT09Im51bWJlciIpcmV0dXJuIGkuaCgpCmkrPTN9
-aD0wCndoaWxlKCEwKXtpZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLmgoKQpnPW0rMwppZih0
-eXBlb2YgZSE9PSJudW1iZXIiKXJldHVybiBILnBZKGUpCmlmKCEoZzw9ZSYmQy54Qi5RaSh0LCIuLi8i
-LG0pKSlicmVhazsrK2gKbT1nfWY9IiIKd2hpbGUoITApe2lmKHR5cGVvZiBrIT09Im51bWJlciIpcmV0
-dXJuIGsub3MoKQppZih0eXBlb2YgaSE9PSJudW1iZXIiKXJldHVybiBILnBZKGkpCmlmKCEoaz5pKSli
-cmVhazstLWsKaWYoQy54Qi5tKGosayk9PT00Nyl7aWYoaD09PTApe2Y9Ii8iCmJyZWFrfS0taApmPSIv
-In19aWYoaz09PWkmJmEuYjw9MCYmIUMueEIuUWkoaiwiLyIsbCkpe20tPWgqMwpmPSIifXE9ay1tK2Yu
-bGVuZ3RoCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGosMCxrKStmK0MueEIuRyh0LG0pLGEuYixhLmMs
-YS5kLGwsZStxLGIucitxLGEueCl9LAp0NDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcwppZihw
-LmI+PTAmJiFwLmdOdygpKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0aCBm
-cm9tIGEgIitILmQocC5nRmkoKSkrIiBVUkkiKSkKdD1wLmYKcz1wLmEKaWYodHlwZW9mIHQhPT0ibnVt
-YmVyIilyZXR1cm4gdC5KKCkKaWYodDxzLmxlbmd0aCl7aWYodDxwLnIpdGhyb3cgSC5iKFAuTDQoIkNh
-bm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIHF1ZXJ5IGNvbXBvbmVudCIp
-KQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhIFVSSSB3aXRo
-IGEgZnJhZ21lbnQgY29tcG9uZW50IikpfXI9JC53USgpCmlmKEgub1QocikpdD1QLm1uKHApCmVsc2V7
-cT1wLmQKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShxKQppZihwLmM8cSlILnZoKFAu
-TDQoIkNhbm5vdCBleHRyYWN0IGEgbm9uLVdpbmRvd3MgZmlsZSBwYXRoIGZyb20gYSBmaWxlIFVSSSB3
-aXRoIGFuIGF1dGhvcml0eSIpKQp0PUMueEIuTmoocyxwLmUsdCl9cmV0dXJuIHR9LApnaU86ZnVuY3Rp
-b24oYSl7dmFyIHQ9dGhpcy55CnJldHVybiB0PT1udWxsP3RoaXMueT1DLnhCLmdpTyh0aGlzLmEpOnR9
-LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKaWYodGhpcz09PWIpcmV0dXJuITAK
-cmV0dXJuIHUudy5jKGIpJiZ0aGlzLmE9PT1iLncoMCl9LApSZTpmdW5jdGlvbigpe3ZhciB0PXRoaXMs
-cz1udWxsLHI9dC5nRmkoKSxxPXQuZ2t1KCkscD10LmM+MD90LmdKZih0KTpzLG89dC5neEEoKT90Lmd0
-cCh0KTpzLG49dC5hLG09dC5mLGw9Qy54Qi5OaihuLHQuZSxtKSxrPXQucgppZih0eXBlb2YgbSE9PSJu
-dW1iZXIiKXJldHVybiBtLkooKQptPW08az90Lmd0UCgpOnMKcmV0dXJuIG5ldyBQLkRuKHIscSxwLG8s
-bCxtLGs8bi5sZW5ndGg/dC5nS2EoKTpzKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCiRp
-aUQ6MX0KUC5xZS5wcm90b3R5cGU9e30KVy5xRS5wcm90b3R5cGU9e30KVy5HaC5wcm90b3R5cGU9ewp3
-OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LAokaUdoOjF9ClcuZlkucHJvdG90eXBlPXsKdzpm
-dW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfX0KVy5uQi5wcm90b3R5cGU9eyRpbkI6MX0KVy5Bei5w
-cm90b3R5cGU9eyRpQXo6MX0KVy5RUC5wcm90b3R5cGU9eyRpUVA6MX0KVy5ueC5wcm90b3R5cGU9ewpn
-QTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLm9KLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9u
-KGEpe3JldHVybiBhLmxlbmd0aH19ClcuaWQucHJvdG90eXBlPXt9ClcuUUYucHJvdG90eXBlPXt9Clcu
-TmgucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfX0KVy5JQi5wcm90b3R5
-cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJSZWN0YW5nbGUgKCIrSC5kKGEubGVmdCkrIiwgIitILmQo
-YS50b3ApKyIpICIrSC5kKGEud2lkdGgpKyIgeCAiK0guZChhLmhlaWdodCl9LApETjpmdW5jdGlvbihh
-LGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIHUucS5jKGIpJiZhLmxlZnQ9PT1iLmxlZnQmJmEu
-dG9wPT09Yi50b3AmJmEud2lkdGg9PT1iLndpZHRoJiZhLmhlaWdodD09PWIuaGVpZ2h0fSwKZ2lPOmZ1
-bmN0aW9uKGEpe3JldHVybiBXLnJFKEMuQ0QuZ2lPKGEubGVmdCksQy5DRC5naU8oYS50b3ApLEMuQ0Qu
-Z2lPKGEud2lkdGgpLEMuQ0QuZ2lPKGEuaGVpZ2h0KSl9LAokaXRuOjF9ClcubjcucHJvdG90eXBlPXsK
-Z0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy53ei5wcm90b3R5cGU9ewpnQTpmdW5jdGlv
-bihhKXtyZXR1cm4gdGhpcy5hLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXt2YXIgdApILlNjKGIpCnQ9
-dGhpcy5hCmlmKGI8MHx8Yj49dC5sZW5ndGgpcmV0dXJuIEguT0godCxiKQpyZXR1cm4gdGhpcy4kdGku
-ZC5iKHRbYl0pfSwKWTpmdW5jdGlvbihhLGIsYyl7dGhpcy4kdGkuZC5iKGMpCnRocm93IEguYihQLkw0
-KCJDYW5ub3QgbW9kaWZ5IGxpc3QiKSl9fQpXLmN2LnByb3RvdHlwZT17CmdRZzpmdW5jdGlvbihhKXty
-ZXR1cm4gbmV3IFcuaTcoYSl9LApnRDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuSTQoYSl9LApzRDpm
-dW5jdGlvbihhLGIpe3ZhciB0CnUuWC5iKGIpCnQ9dGhpcy5nRChhKQp0LlYxKDApCnQuRlYoMCxiKX0s
-Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubG9jYWxOYW1lfSwKdG46ZnVuY3Rpb24oYSl7dmFyIHQ9ISFh
-LnNjcm9sbEludG9WaWV3SWZOZWVkZWQKaWYodClhLnNjcm9sbEludG9WaWV3SWZOZWVkZWQoKQplbHNl
-IGEuc2Nyb2xsSW50b1ZpZXcoKX0sCnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxCmlmKGM9
-PW51bGwpe2lmKGQ9PW51bGwpe3Q9JC5sdAppZih0PT1udWxsKXt0PUguVk0oW10sdS5tKQpzPW5ldyBX
-LnZEKHQpCkMuTm0uaSh0LFcuVHcobnVsbCkpCkMuTm0uaSh0LFcuQmwoKSkKJC5sdD1zCmQ9c31lbHNl
-IGQ9dH10PSQuRVUKaWYodD09bnVsbCl7dD1uZXcgVy5LbyhkKQokLkVVPXQKYz10fWVsc2V7dC5hPWQK
-Yz10fX1lbHNlIGlmKGQhPW51bGwpdGhyb3cgSC5iKFAueFkoInZhbGlkYXRvciBjYW4gb25seSBiZSBw
-YXNzZWQgaWYgdHJlZVNhbml0aXplciBpcyBudWxsIikpCmlmKCQueG89PW51bGwpe3Q9ZG9jdW1lbnQK
-cz10LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxEb2N1bWVudCgiIikKJC54bz1zCiQuQk89cy5jcmVh
-dGVSYW5nZSgpCnM9JC54by5jcmVhdGVFbGVtZW50KCJiYXNlIikKdS5GLmIocykKcy5ocmVmPXQuYmFz
-ZVVSSQokLnhvLmhlYWQuYXBwZW5kQ2hpbGQocyl9dD0kLnhvCmlmKHQuYm9keT09bnVsbCl7cz10LmNy
-ZWF0ZUVsZW1lbnQoImJvZHkiKQp0LmJvZHk9dS5ZLmIocyl9dD0kLnhvCmlmKHUuWS5jKGEpKXI9dC5i
-b2R5CmVsc2V7cj10LmNyZWF0ZUVsZW1lbnQoYS50YWdOYW1lKQokLnhvLmJvZHkuYXBwZW5kQ2hpbGQo
-cil9aWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSYm
-IUMuTm0udGcoQy5TcSxhLnRhZ05hbWUpKXskLkJPLnNlbGVjdE5vZGVDb250ZW50cyhyKQpxPSQuQk8u
-Y3JlYXRlQ29udGV4dHVhbEZyYWdtZW50KGIpfWVsc2V7ci5pbm5lckhUTUw9YgpxPSQueG8uY3JlYXRl
-RG9jdW1lbnRGcmFnbWVudCgpCmZvcig7dD1yLmZpcnN0Q2hpbGQsdCE9bnVsbDspcS5hcHBlbmRDaGls
-ZCh0KX10PSQueG8uYm9keQppZihyPT1udWxsP3QhPW51bGw6ciE9PXQpSi5MdChyKQpjLlBuKHEpCmRv
-Y3VtZW50LmFkb3B0Tm9kZShxKQpyZXR1cm4gcX0sCkFIOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gdGhp
-cy5yNihhLGIsYyxudWxsKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMuWUMoYSxiKX0sCnBrOmZ1bmN0
-aW9uKGEsYixjKXthLnRleHRDb250ZW50PW51bGwKYS5hcHBlbmRDaGlsZCh0aGlzLnI2KGEsYixudWxs
-LGMpKX0sCllDOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucGsoYSxiLG51bGwpfSwKZ1ZsOmZ1bmN0
-aW9uKGEpe3JldHVybiBuZXcgVy5DcShhLCJjbGljayIsITEsdS5RKX0sCiRpY3Y6MSwKZ25zOmZ1bmN0
-aW9uKGEpe3JldHVybiBhLnRhZ05hbWV9fQpXLkN2LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
-dHVybiB1LmguYyh1LkEuYihhKSl9LAokUzo0NH0KVy5lYS5wcm90b3R5cGU9eyRpZWE6MX0KVy5EMC5w
-cm90b3R5cGU9ewpPbjpmdW5jdGlvbihhLGIsYyxkKXt1LlUuYihjKQppZihjIT1udWxsKXRoaXMudihh
-LGIsYyxkKX0sCkI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiB0aGlzLk9uKGEsYixjLG51bGwpfSwKdjpm
-dW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYS5hZGRFdmVudExpc3RlbmVyKGIsSC50Uih1LlUuYihjKSwx
-KSxkKX0sCiRpRDA6MX0KVy5UNS5wcm90b3R5cGU9eyRpVDU6MX0KVy5oNC5wcm90b3R5cGU9ewpnQTpm
-dW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmJyLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEp
-e3JldHVybiBhLmxlbmd0aH19ClcuVmIucHJvdG90eXBlPXt9ClcuTzcucHJvdG90eXBlPXsKZW86ZnVu
-Y3Rpb24oYSxiLGMsZCl7cmV0dXJuIGEub3BlbihiLGMsITApfSwKJGlPNzoxfQpXLmJVLnByb3RvdHlw
-ZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLnNldFJlcXVlc3RIZWFkZXIoSC55KGEpLEgueShiKSl9
-LAokUzoxMH0KVy5oSC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwCnUucC5i
-KGEpCnQ9dGhpcy5hCnM9dC5zdGF0dXMKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy50Qigp
-CnI9cz49MjAwJiZzPDMwMApxPXM+MzA3JiZzPDQwMApzPXJ8fHM9PT0wfHxzPT09MzA0fHxxCnA9dGhp
-cy5iCmlmKHMpe3AuJHRpLkMoIjEvIikuYih0KQpzPXAuYQppZihzLmEhPT0wKUgudmgoUC5QVigiRnV0
-dXJlIGFscmVhZHkgY29tcGxldGVkIikpCnMuWGYodCl9ZWxzZSBwLnBtKGEpfSwKJFM6MjR9Clcud2Eu
-cHJvdG90eXBlPXt9ClcuU2cucHJvdG90eXBlPXskaVNnOjF9ClcudTgucHJvdG90eXBlPXsKZ0RyOmZ1
-bmN0aW9uKGEpe2lmKCJvcmlnaW4iIGluIGEpcmV0dXJuIGEub3JpZ2luCnJldHVybiBILmQoYS5wcm90
-b2NvbCkrIi8vIitILmQoYS5ob3N0KX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRp
-dTg6MX0KVy5Bai5wcm90b3R5cGU9eyRpQWo6MX0KVy5lNy5wcm90b3R5cGU9ewpncjg6ZnVuY3Rpb24o
-YSl7dmFyIHQ9dGhpcy5hLHM9dC5jaGlsZE5vZGVzLmxlbmd0aAppZihzPT09MCl0aHJvdyBILmIoUC5Q
-VigiTm8gZWxlbWVudHMiKSkKaWYocz4xKXRocm93IEguYihQLlBWKCJNb3JlIHRoYW4gb25lIGVsZW1l
-bnQiKSkKcmV0dXJuIHQuZmlyc3RDaGlsZH0sCkZWOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKdS5l
-aC5iKGIpCnQ9Yi5hCnM9dGhpcy5hCmlmKHQhPT1zKWZvcihyPXQuY2hpbGROb2Rlcy5sZW5ndGgscT0w
-O3E8cjsrK3Epcy5hcHBlbmRDaGlsZCh0LmZpcnN0Q2hpbGQpCnJldHVybn0sClk6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciB0LHMKdS5BLmIoYykKdD10aGlzLmEKcz10LmNoaWxkTm9kZXMKaWYoYjwwfHxiPj1zLmxl
-bmd0aClyZXR1cm4gSC5PSChzLGIpCnQucmVwbGFjZUNoaWxkKGMsc1tiXSl9LApna3o6ZnVuY3Rpb24o
-YSl7dmFyIHQ9dGhpcy5hLmNoaWxkTm9kZXMKcmV0dXJuIG5ldyBXLlc5KHQsdC5sZW5ndGgsSC56Syh0
-KS5DKCJXOTxHbS5FPiIpKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2hpbGROb2Rlcy5s
-ZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7dmFyIHQKSC5TYyhiKQp0PXRoaXMuYS5jaGlsZE5vZGVzCmlm
-KGI8MHx8Yj49dC5sZW5ndGgpcmV0dXJuIEguT0godCxiKQpyZXR1cm4gdFtiXX19ClcudUgucHJvdG90
-eXBlPXsKd2c6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5wYXJlbnROb2RlCmlmKHQhPW51bGwpdC5yZW1vdmVD
-aGlsZChhKX0sCkQ0OmZ1bmN0aW9uKGEpe3ZhciB0CmZvcig7dD1hLmZpcnN0Q2hpbGQsdCE9bnVsbDsp
-YS5yZW1vdmVDaGlsZCh0KX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5ub2RlVmFsdWUKcmV0dXJuIHQ9
-PW51bGw/dGhpcy5VKGEpOnR9LAokaXVIOjF9ClcuQkgucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7
-cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKaWYoYj4+PjAhPT1ifHxiPj1h
-Lmxlbmd0aCl0aHJvdyBILmIoUC5DZihiLGEsbnVsbCxudWxsLG51bGwpKQpyZXR1cm4gYVtiXX0sClk6
-ZnVuY3Rpb24oYSxiLGMpe3UuQS5iKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgYXNzaWduIGVsZW1l
-bnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKRTpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5n
-dGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCiRpWGo6MSwKJGljWDoxLAokaXpNOjF9Clcu
-U04ucHJvdG90eXBlPXt9ClcuZXcucHJvdG90eXBlPXskaWV3OjF9ClcubHAucHJvdG90eXBlPXsKZ0E6
-ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5UYi5wcm90b3R5cGU9ewpyNjpmdW5jdGlvbihh
-LGIsYyxkKXt2YXIgdCxzCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5n
-ZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1XLlU5KCI8dGFibGU+IitILmQoYikr
-IjwvdGFibGU+IixjLGQpCnM9ZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnMudG9TdHJp
-bmcKdC50b1N0cmluZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHQpKQpyZXR1cm4gc319ClcuSXYu
-cHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEKaWYoImNyZWF0ZUNvbnRl
-eHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSlyZXR1cm4gdGhpcy5EVyhhLGIs
-YyxkKQp0PWRvY3VtZW50CnM9dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKdD1DLkllLnI2KHQuY3Jl
-YXRlRWxlbWVudCgidGFibGUiKSxiLGMsZCkKdC50b1N0cmluZwp0PW5ldyBXLmU3KHQpCnI9dC5ncjgo
-dCkKci50b1N0cmluZwp0PW5ldyBXLmU3KHIpCnE9dC5ncjgodCkKcy50b1N0cmluZwpxLnRvU3RyaW5n
-Cm5ldyBXLmU3KHMpLkZWKDAsbmV3IFcuZTcocSkpCnJldHVybiBzfX0KVy5CVC5wcm90b3R5cGU9ewpy
-NjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKaWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIg
-aW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSlyZXR1cm4gdGhpcy5EVyhhLGIsYyxkKQp0PWRvY3VtZW50
-CnM9dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKdD1DLkllLnI2KHQuY3JlYXRlRWxlbWVudCgidGFi
-bGUiKSxiLGMsZCkKdC50b1N0cmluZwp0PW5ldyBXLmU3KHQpCnI9dC5ncjgodCkKcy50b1N0cmluZwpy
-LnRvU3RyaW5nCm5ldyBXLmU3KHMpLkZWKDAsbmV3IFcuZTcocikpCnJldHVybiBzfX0KVy55WS5wcm90
-b3R5cGU9ewpwazpmdW5jdGlvbihhLGIsYyl7dmFyIHQscwphLnRleHRDb250ZW50PW51bGwKdD1hLmNv
-bnRlbnQKdC50b1N0cmluZwpKLmJUKHQpCnM9dGhpcy5yNihhLGIsbnVsbCxjKQphLmNvbnRlbnQuYXBw
-ZW5kQ2hpbGQocyl9LApZQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnBrKGEsYixudWxsKX0sCiRp
-eVk6MX0KVy53Ni5wcm90b3R5cGU9e30KVy5LNS5wcm90b3R5cGU9eyRpSzU6MSwkaXY2OjF9ClcuQ20u
-cHJvdG90eXBlPXskaUNtOjF9ClcuQ1EucHJvdG90eXBlPXskaUNROjF9ClcudzQucHJvdG90eXBlPXsK
-dzpmdW5jdGlvbihhKXtyZXR1cm4iUmVjdGFuZ2xlICgiK0guZChhLmxlZnQpKyIsICIrSC5kKGEudG9w
-KSsiKSAiK0guZChhLndpZHRoKSsiIHggIitILmQoYS5oZWlnaHQpfSwKRE46ZnVuY3Rpb24oYSxiKXtp
-ZihiPT1udWxsKXJldHVybiExCnJldHVybiB1LnEuYyhiKSYmYS5sZWZ0PT09Yi5sZWZ0JiZhLnRvcD09
-PWIudG9wJiZhLndpZHRoPT09Yi53aWR0aCYmYS5oZWlnaHQ9PT1iLmhlaWdodH0sCmdpTzpmdW5jdGlv
-bihhKXtyZXR1cm4gVy5yRShDLkNELmdpTyhhLmxlZnQpLEMuQ0QuZ2lPKGEudG9wKSxDLkNELmdpTyhh
-LndpZHRoKSxDLkNELmdpTyhhLmhlaWdodCkpfX0KVy5yaC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihh
-KXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+
-PWEubGVuZ3RoKXRocm93IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwK
-WTpmdW5jdGlvbihhLGIsYyl7dS5BLmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxl
-bWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApFOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxl
-bmd0aClyZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwKJGlYajoxLAokaWNYOjEsCiRpek06MX0K
-Vy5EOS5wcm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscAp1LkQuYihiKQpmb3Io
-dD10aGlzLmdWKCkscz10Lmxlbmd0aCxyPXRoaXMuYSxxPTA7cTx0Lmxlbmd0aDt0Lmxlbmd0aD09PXN8
-fCgwLEgubGspKHQpLCsrcSl7cD10W3FdCmIuJDIocCxyLmdldEF0dHJpYnV0ZShwKSl9fSwKZ1Y6ZnVu
-Y3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMuYS5hdHRyaWJ1dGVzLG89SC5WTShbXSx1LnMpCmZvcih0
-PXAubGVuZ3RoLHM9dS5oOSxyPTA7cjx0Oysrcil7aWYocj49cC5sZW5ndGgpcmV0dXJuIEguT0gocCxy
-KQpxPXMuYihwW3JdKQppZihxLm5hbWVzcGFjZVVSST09bnVsbClDLk5tLmkobyxxLm5hbWUpfXJldHVy
-biBvfX0KVy5pNy5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5nZXRBdHRy
-aWJ1dGUoSC55KGIpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5zZXRBdHRyaWJ1dGUoYixjKX0s
-CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdWKCkubGVuZ3RofX0KVy5TeS5wcm90b3R5cGU9ewpx
-OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5hLmdldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMuTyhI
-LnkoYikpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5hLnNldEF0dHJpYnV0ZSgiZGF0YS0iK3Ro
-aXMuTyhiKSxjKX0sCks6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuSygwLG5ldyBXLktTKHRoaXMsdS5ELmIo
-YikpKX0sCmdWOmZ1bmN0aW9uKCl7dmFyIHQ9SC5WTShbXSx1LnMpCnRoaXMuYS5LKDAsbmV3IFcuQTMo
-dGhpcyx0KSkKcmV0dXJuIHR9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nVigpLmxlbmd0aH0s
-Cms6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPUguVk0oYS5zcGxpdCgiLSIpLHUucykKZm9yKHQ9MTt0PHIu
-bGVuZ3RoOysrdCl7cz1yW3RdCmlmKHMubGVuZ3RoPjApQy5ObS5ZKHIsdCxzWzBdLnRvVXBwZXJDYXNl
-KCkrSi5LVihzLDEpKX1yZXR1cm4gQy5ObS5IKHIsIiIpfSwKTzpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
-cSxwCmZvcih0PWEubGVuZ3RoLHM9MCxyPSIiO3M8dDsrK3Mpe3E9YVtzXQpwPXEudG9Mb3dlckNhc2Uo
-KQpyPShxIT09cCYmcz4wP3IrIi0iOnIpK3B9cmV0dXJuIHIuY2hhckNvZGVBdCgwKT09MD9yOnJ9fQpX
-LktTLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7aWYoSi5yWShhKS5uKGEsImRhdGEtIikpdGhp
-cy5iLiQyKHRoaXMuYS5rKEMueEIuRyhhLDUpKSxiKX0sCiRTOjEwfQpXLkEzLnByb3RvdHlwZT17CiQy
-OmZ1bmN0aW9uKGEsYil7aWYoSi5yWShhKS5uKGEsImRhdGEtIikpQy5ObS5pKHRoaXMuYix0aGlzLmEu
-ayhDLnhCLkcoYSw1KSkpfSwKJFM6MTB9ClcuSTQucHJvdG90eXBlPXsKUDpmdW5jdGlvbigpe3ZhciB0
-LHMscixxLHA9UC5Mcyh1Lk4pCmZvcih0PXRoaXMuYS5jbGFzc05hbWUuc3BsaXQoIiAiKSxzPXQubGVu
-Z3RoLHI9MDtyPHM7KytyKXtxPUouVDAodFtyXSkKaWYocS5sZW5ndGghPT0wKXAuaSgwLHEpfXJldHVy
-biBwfSwKWDpmdW5jdGlvbihhKXt0aGlzLmEuY2xhc3NOYW1lPXUuQy5iKGEpLkgoMCwiICIpfSwKZ0E6
-ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5jbGFzc0xpc3QubGVuZ3RofSwKVjE6ZnVuY3Rpb24oYSl7
-dGhpcy5hLmNsYXNzTmFtZT0iIn0sCnRnOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNzTGlz
-dC5jb250YWlucyhiKQpyZXR1cm4gdH0sCmk6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmEuY2xhc3NM
-aXN0LHM9dC5jb250YWlucyhiKQp0LmFkZChiKQpyZXR1cm4hc30sClI6ZnVuY3Rpb24oYSxiKXt2YXIg
-dD10aGlzLmEuY2xhc3NMaXN0LHM9dC5jb250YWlucyhiKQp0LnJlbW92ZShiKQpyZXR1cm4gc30sCkZW
-OmZ1bmN0aW9uKGEsYil7Vy5UTih0aGlzLmEsdS5YLmIoYikpfX0KVy5Gay5wcm90b3R5cGU9e30KVy5S
-Ty5wcm90b3R5cGU9e30KVy5DcS5wcm90b3R5cGU9e30KVy54Qy5wcm90b3R5cGU9e30KVy52Ti5wcm90
-b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLiQxKHUuQi5iKGEpKX0sCiRTOjI1fQpX
-LkpRLnByb3RvdHlwZT17CkNZOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKCQub3IuYT09PTApe2Zvcih0PTA7
-dDwyNjI7Kyt0KSQub3IuWSgwLEMuY21bdF0sVy5wUygpKQpmb3IodD0wO3Q8MTI7Kyt0KSQub3IuWSgw
-LEMuQklbdF0sVy5WNCgpKX19LAppMDpmdW5jdGlvbihhKXtyZXR1cm4gJC5BTigpLnRnKDAsVy5yUyhh
-KSl9LApFYjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9JC5vci5xKDAsSC5kKFcuclMoYSkpKyI6OiIrYikK
-aWYodD09bnVsbCl0PSQub3IucSgwLCIqOjoiK2IpCmlmKHQ9PW51bGwpcmV0dXJuITEKcmV0dXJuIEgu
-eGQodC4kNChhLGIsYyx0aGlzKSl9LAokaWtGOjF9ClcuR20ucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9u
-KGEpe3JldHVybiBuZXcgVy5XOShhLHRoaXMuZ0EoYSksSC56SyhhKS5DKCJXOTxHbS5FPiIpKX19Clcu
-dkQucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuIEMuTm0uVnIodGhpcy5hLG5ldyBXLlV2
-KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gQy5ObS5Wcih0aGlzLmEsbmV3IFcuRWcoYSxi
-LGMpKX0sCiRpa0Y6MX0KVy5Vdi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5lLmIo
-YSkuaTAodGhpcy5hKX0sCiRTOjE1fQpXLkVnLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVy
-biB1LmUuYihhKS5FYih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzoxNX0KVy5tNi5wcm90b3R5cGU9
-ewpDWTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKdGhpcy5hLkZWKDAsYykKdD1iLmV2KDAsbmV3
-IFcuRW8oKSkKcz1iLmV2KDAsbmV3IFcuV2soKSkKdGhpcy5iLkZWKDAsdCkKcj10aGlzLmMKci5GVigw
-LEMueEQpCnIuRlYoMCxzKX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEudGcoMCxXLnJTKGEp
-KX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD10aGlzLHM9Vy5yUyhhKSxyPXQuYwppZihyLnRnKDAs
-SC5kKHMpKyI6OiIrYikpcmV0dXJuIHQuZC5EdChjKQplbHNlIGlmKHIudGcoMCwiKjo6IitiKSlyZXR1
-cm4gdC5kLkR0KGMpCmVsc2V7cj10LmIKaWYoci50ZygwLEguZChzKSsiOjoiK2IpKXJldHVybiEwCmVs
-c2UgaWYoci50ZygwLCIqOjoiK2IpKXJldHVybiEwCmVsc2UgaWYoci50ZygwLEguZChzKSsiOjoqIikp
-cmV0dXJuITAKZWxzZSBpZihyLnRnKDAsIio6OioiKSlyZXR1cm4hMH1yZXR1cm4hMX0sCiRpa0Y6MX0K
-Vy5Fby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4hQy5ObS50ZyhDLkJJLEgueShhKSl9
-LAokUzo4fQpXLldrLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBDLk5tLnRnKEMuQkks
-SC55KGEpKX0sCiRTOjh9ClcuY3QucHJvdG90eXBlPXsKRWI6ZnVuY3Rpb24oYSxiLGMpe2lmKHRoaXMu
-akYoYSxiLGMpKXJldHVybiEwCmlmKGI9PT0idGVtcGxhdGUiJiZjPT09IiIpcmV0dXJuITAKaWYoYS5n
-ZXRBdHRyaWJ1dGUoInRlbXBsYXRlIik9PT0iIilyZXR1cm4gdGhpcy5lLnRnKDAsYikKcmV0dXJuITF9
-fQpXLklBLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiJURU1QTEFURTo6IitILmQoSC55
-KGEpKX0sCiRTOjZ9ClcuT3cucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7dmFyIHQKaWYodS5ldy5j
-KGEpKXJldHVybiExCnQ9dS5nNy5jKGEpCmlmKHQmJlcuclMoYSk9PT0iZm9yZWlnbk9iamVjdCIpcmV0
-dXJuITEKaWYodClyZXR1cm4hMApyZXR1cm4hMX0sCkViOmZ1bmN0aW9uKGEsYixjKXtpZihiPT09Imlz
-Inx8Qy54Qi5uKGIsIm9uIikpcmV0dXJuITEKcmV0dXJuIHRoaXMuaTAoYSl9LAokaWtGOjF9ClcuVzku
-cHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciB0PXRoaXMscz10LmMrMSxyPXQuYgppZihzPHIpe3Qu
-c3AoSi53Mih0LmEscykpCnQuYz1zCnJldHVybiEwfXQuc3AobnVsbCkKdC5jPXIKcmV0dXJuITF9LApn
-bDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApzcDpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGku
-ZC5iKGEpfSwKJGlBbjoxfQpXLmRXLnByb3RvdHlwZT17JGlEMDoxLCRpdjY6MX0KVy5rRi5wcm90b3R5
-cGU9e30KVy5tay5wcm90b3R5cGU9eyRpeTA6MX0KVy5Lby5wcm90b3R5cGU9ewpQbjpmdW5jdGlvbihh
-KXtuZXcgVy5mbSh0aGlzKS4kMihhLG51bGwpfSwKRVA6ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKUou
-THQoYSkKZWxzZSBiLnJlbW92ZUNoaWxkKGEpfSwKSTQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxw
-LG89ITAsbj1udWxsLG09bnVsbAp0cnl7bj1KLmlnKGEpCm09bi5hLmdldEF0dHJpYnV0ZSgiaXMiKQp1
-LmguYihhKQp0PWZ1bmN0aW9uKGMpe2lmKCEoYy5hdHRyaWJ1dGVzIGluc3RhbmNlb2YgTmFtZWROb2Rl
-TWFwKSlyZXR1cm4gdHJ1ZQp2YXIgbD1jLmNoaWxkTm9kZXMKaWYoYy5sYXN0Q2hpbGQmJmMubGFzdENo
-aWxkIT09bFtsLmxlbmd0aC0xXSlyZXR1cm4gdHJ1ZQppZihjLmNoaWxkcmVuKWlmKCEoYy5jaGlsZHJl
-biBpbnN0YW5jZW9mIEhUTUxDb2xsZWN0aW9ufHxjLmNoaWxkcmVuIGluc3RhbmNlb2YgTm9kZUxpc3Qp
-KXJldHVybiB0cnVlCnZhciBrPTAKaWYoYy5jaGlsZHJlbilrPWMuY2hpbGRyZW4ubGVuZ3RoCmZvcih2
-YXIgaj0wO2o8aztqKyspe3ZhciBpPWMuY2hpbGRyZW5bal0KaWYoaS5pZD09J2F0dHJpYnV0ZXMnfHxp
-Lm5hbWU9PSdhdHRyaWJ1dGVzJ3x8aS5pZD09J2xhc3RDaGlsZCd8fGkubmFtZT09J2xhc3RDaGlsZCd8
-fGkuaWQ9PSdjaGlsZHJlbid8fGkubmFtZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZX1yZXR1cm4gZmFs
-c2V9KGEpCm89SC5vVCh0KT8hMDohKGEuYXR0cmlidXRlcyBpbnN0YW5jZW9mIE5hbWVkTm9kZU1hcCl9
-Y2F0Y2gocSl7SC5SdShxKX1zPSJlbGVtZW50IHVucHJpbnRhYmxlIgp0cnl7cz1KLmooYSl9Y2F0Y2go
-cSl7SC5SdShxKX10cnl7cj1XLnJTKGEpCnRoaXMua1IodS5oLmIoYSksYixvLHMscix1LkcuYihuKSxI
-LnkobSkpfWNhdGNoKHEpe2lmKEguUnUocSkgaW5zdGFuY2VvZiBQLnUpdGhyb3cgcQplbHNle3RoaXMu
-RVAoYSxiKQp3aW5kb3cKcD0iUmVtb3ZpbmcgY29ycnVwdGVkIGVsZW1lbnQgIitILmQocykKaWYodHlw
-ZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4ocCl9fX0sCmtSOmZ1bmN0
-aW9uKGEsYixjLGQsZSxmLGcpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMKaWYoYyl7bi5FUChhLGIpCndp
-bmRvdwp0PSJSZW1vdmluZyBlbGVtZW50IGR1ZSB0byBjb3JydXB0ZWQgYXR0cmlidXRlcyBvbiA8Iitk
-KyI+IgppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2Fybih0KQpy
-ZXR1cm59aWYoIW4uYS5pMChhKSl7bi5FUChhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxvd2Vk
-IGVsZW1lbnQgPCIrSC5kKGUpKyI+IGZyb20gIitILmQoYikKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRl
-ZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4odCkKcmV0dXJufWlmKGchPW51bGwpaWYoIW4uYS5FYihh
-LCJpcyIsZykpe24uRVAoYSxiKQp3aW5kb3cKdD0iUmVtb3ZpbmcgZGlzYWxsb3dlZCB0eXBlIGV4dGVu
-c2lvbiA8IitILmQoZSkrJyBpcz0iJytnKyciPicKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQi
-KXdpbmRvdy5jb25zb2xlLndhcm4odCkKcmV0dXJufXQ9Zi5nVigpCnM9SC5WTSh0LnNsaWNlKDApLEgu
-dDYodCkuQygiamQ8MT4iKSkKZm9yKHI9Zi5nVigpLmxlbmd0aC0xLHQ9Zi5hO3I+PTA7LS1yKXtpZihy
-Pj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLHIpCnE9c1tyXQpwPW4uYQpvPUouY0gocSkKSC55KHEpCmlm
-KCFwLkViKGEsbyx0LmdldEF0dHJpYnV0ZShxKSkpe3dpbmRvdwpwPSJSZW1vdmluZyBkaXNhbGxvd2Vk
-IGF0dHJpYnV0ZSA8IitILmQoZSkrIiAiK3ErJz0iJytILmQodC5nZXRBdHRyaWJ1dGUocSkpKyciPicK
-aWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4ocCkKdC5yZW1v
-dmVBdHRyaWJ1dGUocSl9fWlmKHUuYVcuYyhhKSluLlBuKGEuY29udGVudCl9LAokaW9uOjF9ClcuZm0u
-cHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwPXRoaXMuYQpzd2l0Y2goYS5u
-b2RlVHlwZSl7Y2FzZSAxOnAuSTQoYSxiKQpicmVhawpjYXNlIDg6Y2FzZSAxMTpjYXNlIDM6Y2FzZSA0
-OmJyZWFrCmRlZmF1bHQ6cC5FUChhLGIpfXQ9YS5sYXN0Q2hpbGQKZm9yKHA9dS5BO251bGwhPXQ7KXtz
-PW51bGwKdHJ5e3M9dC5wcmV2aW91c1NpYmxpbmd9Y2F0Y2gocil7SC5SdShyKQpxPXAuYih0KQphLnJl
-bW92ZUNoaWxkKHEpCnQ9bnVsbApzPWEubGFzdENoaWxkfWlmKHQhPW51bGwpdGhpcy4kMih0LGEpCnQ9
-cC5iKHMpfX0sCiRTOjI4fQpXLkxlLnByb3RvdHlwZT17fQpXLks3LnByb3RvdHlwZT17fQpXLnJCLnBy
-b3RvdHlwZT17fQpXLlhXLnByb3RvdHlwZT17fQpXLm9hLnByb3RvdHlwZT17fQpQLmlKLnByb3RvdHlw
-ZT17ClZIOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5hLHI9cy5sZW5ndGgKZm9yKHQ9MDt0PHI7Kyt0
-KWlmKHNbdF09PT1hKXJldHVybiB0CkMuTm0uaShzLGEpCkMuTm0uaSh0aGlzLmIsbnVsbCkKcmV0dXJu
-IHJ9LApQdjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT10aGlzLHA9e30KaWYoYT09bnVsbClyZXR1cm4g
-YQppZihILmwoYSkpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKHR5cGVv
-ZiBhPT0ic3RyaW5nIilyZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5pUClyZXR1cm4gbmV3IERhdGUo
-YS5hKQppZih1LmZ2LmMoYSkpdGhyb3cgSC5iKFAuU1koInN0cnVjdHVyZWQgY2xvbmUgb2YgUmVnRXhw
-IikpCmlmKHUuYzguYyhhKSlyZXR1cm4gYQppZih1LmQuYyhhKSlyZXR1cm4gYQppZih1LkkuYyhhKSly
-ZXR1cm4gYQp0PXUuZEQuYyhhKXx8ITEKaWYodClyZXR1cm4gYQppZih1LkcuYyhhKSl7cz1xLlZIKGEp
-CnQ9cS5iCmlmKHM+PXQubGVuZ3RoKXJldHVybiBILk9IKHQscykKcj1wLmE9dFtzXQppZihyIT1udWxs
-KXJldHVybiByCnI9e30KcC5hPXIKQy5ObS5ZKHQscyxyKQphLksoMCxuZXcgUC5sUihwLHEpKQpyZXR1
-cm4gcC5hfWlmKHUuai5jKGEpKXtzPXEuVkgoYSkKcD1xLmIKaWYocz49cC5sZW5ndGgpcmV0dXJuIEgu
-T0gocCxzKQpyPXBbc10KaWYociE9bnVsbClyZXR1cm4gcgpyZXR1cm4gcS5layhhLHMpfWlmKHUuZUgu
-YyhhKSl7cz1xLlZIKGEpCnQ9cS5iCmlmKHM+PXQubGVuZ3RoKXJldHVybiBILk9IKHQscykKcj1wLmI9
-dFtzXQppZihyIT1udWxsKXJldHVybiByCnI9e30KcC5iPXIKQy5ObS5ZKHQscyxyKQpxLmltKGEsbmV3
-IFAuamcocCxxKSkKcmV0dXJuIHAuYn10aHJvdyBILmIoUC5TWSgic3RydWN0dXJlZCBjbG9uZSBvZiBv
-dGhlciB0eXBlIikpfSwKZWs6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPUouVTYoYSkscj1zLmdBKGEpLHE9
-bmV3IEFycmF5KHIpCkMuTm0uWSh0aGlzLmIsYixxKQpmb3IodD0wO3Q8cjsrK3QpQy5ObS5ZKHEsdCx0
-aGlzLlB2KHMucShhLHQpKSkKcmV0dXJuIHF9fQpQLmxSLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEs
-Yil7dGhpcy5hLmFbYV09dGhpcy5iLlB2KGIpfSwKJFM6MX0KUC5qZy5wcm90b3R5cGU9ewokMjpmdW5j
-dGlvbihhLGIpe3RoaXMuYS5iW2FdPXRoaXMuYi5QdihiKX0sCiRTOjF9ClAuQmYucHJvdG90eXBlPXsK
-aW06ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQp1LmI4LmIoYikKZm9yKHQ9T2JqZWN0LmtleXMoYSks
-cz10Lmxlbmd0aCxyPTA7cjxzOysrcil7cT10W3JdCmIuJDIocSxhW3FdKX19fQpQLkFzLnByb3RvdHlw
-ZT17ClQ6ZnVuY3Rpb24oYSl7dmFyIHQKSC55KGEpCnQ9JC5oRygpLmIKaWYodHlwZW9mIGEhPSJzdHJp
-bmciKUgudmgoSC50TChhKSkKaWYodC50ZXN0KGEpKXJldHVybiBhCnRocm93IEguYihQLkwzKGEsInZh
-bHVlIiwiTm90IGEgdmFsaWQgY2xhc3MgdG9rZW4iKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
-LlAoKS5IKDAsIiAiKX0sCmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzLlAoKQpyZXR1cm4gUC5yaih0
-LHQucixILkxoKHQpLmQpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuUCgpLmF9LAp0ZzpmdW5j
-dGlvbihhLGIpe3RoaXMuVChiKQpyZXR1cm4gdGhpcy5QKCkudGcoMCxiKX0sCmk6ZnVuY3Rpb24oYSxi
-KXt0aGlzLlQoYikKcmV0dXJuIEgueGQodGhpcy5PUyhuZXcgUC5HRShiKSkpfSwKUjpmdW5jdGlvbihh
-LGIpe3ZhciB0LHMKdGhpcy5UKGIpCnQ9dGhpcy5QKCkKcz10LlIoMCxiKQp0aGlzLlgodCkKcmV0dXJu
-IHN9LApGVjpmdW5jdGlvbihhLGIpe3RoaXMuT1MobmV3IFAuTjcodGhpcyx1LlguYihiKSkpfSwKVjE6
-ZnVuY3Rpb24oYSl7dGhpcy5PUyhuZXcgUC51USgpKX0sCk9TOmZ1bmN0aW9uKGEpe3ZhciB0LHMKdS5j
-aC5iKGEpCnQ9dGhpcy5QKCkKcz1hLiQxKHQpCnRoaXMuWCh0KQpyZXR1cm4gc319ClAuR0UucHJvdG90
-eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuQy5iKGEpLmkoMCx0aGlzLmEpfSwKJFM6Mzd9ClAu
-TjcucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5iLHM9SC50Nih0KQpyZXR1cm4g
-dS5DLmIoYSkuRlYoMCxuZXcgSC5BOCh0LHMuQygicVUoMSkiKS5iKHRoaXMuYS5ndU0oKSkscy5DKCJB
-ODwxLHFVPiIpKSl9LAokUzoxNH0KUC51US5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt1LkMuYihh
-KQppZihhLmE+MCl7YS5iPWEuYz1hLmQ9YS5lPWEuZj1udWxsCmEuYT0wCmEuUygpfXJldHVybiBudWxs
-fSwKJFM6MTR9ClAuaEYucHJvdG90eXBlPXskaWhGOjF9ClAuUEMucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7dmFyIHQKdS5aLmIoYSkKdD1mdW5jdGlvbihiLGMsZCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0
-dXJuIGIoYyxkLHRoaXMsQXJyYXkucHJvdG90eXBlLnNsaWNlLmFwcGx5KGFyZ3VtZW50cykpfX0oUC5S
-NCxhLCExKQpQLkRtKHQsJC53KCksYSkKcmV0dXJuIHR9LAokUzo0fQpQLlltLnByb3RvdHlwZT17CiQx
-OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgdGhpcy5hKGEpfSwKJFM6NH0KUC5Oei5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAucjcoYSl9LAokUzozMX0KUC5RUy5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuVHooYSx1LmFtKX0sCiRTOjMyfQpQLm5wLnByb3RvdHlw
-ZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5FNChhKX0sCiRTOjMzfQpQLkU0LnByb3RvdHlw
-ZT17CnE6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyImJnR5cGVvZiBiIT0ibnVtYmVy
-Iil0aHJvdyBILmIoUC54WSgicHJvcGVydHkgaXMgbm90IGEgU3RyaW5nIG9yIG51bSIpKQpyZXR1cm4g
-UC5MNyh0aGlzLmFbYl0pfSwKWTpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGIhPSJzdHJpbmciJiZ0
-eXBlb2YgYiE9Im51bWJlciIpdGhyb3cgSC5iKFAueFkoInByb3BlcnR5IGlzIG5vdCBhIFN0cmluZyBv
-ciBudW0iKSkKdGhpcy5hW2JdPVAud1koYyl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0
-dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBQLkU0JiZ0aGlzLmE9PT1iLmF9LAp3OmZ1bmN0aW9uKGEp
-e3ZhciB0LHMKdHJ5e3Q9U3RyaW5nKHRoaXMuYSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShzKQp0PXRo
-aXMueGIoMCkKcmV0dXJuIHR9fSwKVjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYQppZihiPT1u
-dWxsKXQ9bnVsbAplbHNle3Q9SC50NihiKQp0PVAuQ0gobmV3IEguQTgoYix0LkMoIkAoMSkiKS5iKFAu
-aUcoKSksdC5DKCJBODwxLEA+IikpLCEwLHUueil9cmV0dXJuIFAuTDcoc1thXS5hcHBseShzLHQpKX0s
-CmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gMH19ClAucjcucHJvdG90eXBlPXt9ClAuVHoucHJvdG90eXBl
-PXsKY1A6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPWE8MHx8YT49dC5nQSh0KQppZihzKXRocm93IEgu
-YihQLlRFKGEsMCx0LmdBKHQpLG51bGwsbnVsbCkpfSwKcTpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBi
-PT0ibnVtYmVyIiYmYj09PUMuam4ueXUoYikpdGhpcy5jUChILlNjKGIpKQpyZXR1cm4gdGhpcy4kdGku
-ZC5iKHRoaXMuVXIoMCxiKSl9LApZOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAp0aGlzLiR0aS5kLmIoYykK
-dD1DLmpuLnl1KGIpCmlmKGI9PT10KXRoaXMuY1AoYikKdGhpcy5lNCgwLGIsYyl9LApnQTpmdW5jdGlv
-bihhKXt2YXIgdD10aGlzLmEubGVuZ3RoCmlmKHR5cGVvZiB0PT09Im51bWJlciImJnQ+Pj4wPT09dCly
-ZXR1cm4gdAp0aHJvdyBILmIoUC5QVigiQmFkIEpzQXJyYXkgbGVuZ3RoIikpfSwKJGljWDoxLAokaXpN
-OjF9ClAuY28ucHJvdG90eXBlPXt9ClAubmQucHJvdG90eXBlPXskaW5kOjF9ClAuS2UucHJvdG90eXBl
-PXsKUDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcy5hLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSxv
-PVAuTHModS5OKQppZihwPT1udWxsKXJldHVybiBvCmZvcih0PXAuc3BsaXQoIiAiKSxzPXQubGVuZ3Ro
-LHI9MDtyPHM7KytyKXtxPUouVDAodFtyXSkKaWYocS5sZW5ndGghPT0wKW8uaSgwLHEpfXJldHVybiBv
-fSwKWDpmdW5jdGlvbihhKXt0aGlzLmEuc2V0QXR0cmlidXRlKCJjbGFzcyIsYS5IKDAsIiAiKSl9fQpQ
-LmQ1LnByb3RvdHlwZT17CmdEOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5LZShhKX0sCnNoZjpmdW5j
-dGlvbihhLGIpe3RoaXMuWUMoYSxiKX0sCnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAs
-bwppZihkPT1udWxsKXt0PUguVk0oW10sdS5tKQpkPW5ldyBXLnZEKHQpCkMuTm0uaSh0LFcuVHcobnVs
-bCkpCkMuTm0uaSh0LFcuQmwoKSkKQy5ObS5pKHQsbmV3IFcuT3coKSl9Yz1uZXcgVy5LbyhkKQpzPSc8
-c3ZnIHZlcnNpb249IjEuMSI+JytILmQoYikrIjwvc3ZnPiIKdD1kb2N1bWVudApyPXQuYm9keQpxPShy
-JiZDLlJZKS5BSChyLHMsYykKcD10LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpxLnRvU3RyaW5nCnQ9
-bmV3IFcuZTcocSkKbz10LmdyOCh0KQpmb3IoO3Q9by5maXJzdENoaWxkLHQhPW51bGw7KXAuYXBwZW5k
-Q2hpbGQodCkKcmV0dXJuIHB9LApnVmw6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBXLkNxKGEsImNsaWNr
-IiwhMSx1LlEpfSwKJGlkNToxfQpQLm42LnByb3RvdHlwZT17JGljWDoxLCRpek06MSwkaUFTOjF9ClUu
-ZDIucHJvdG90eXBlPXt9ClUuU2UucHJvdG90eXBlPXt9ClUudUYucHJvdG90eXBlPXt9ClUuTWwucHJv
-dG90eXBlPXt9ClUueUQucHJvdG90eXBlPXt9ClUud2IucHJvdG90eXBlPXt9ClQuR1YucHJvdG90eXBl
-PXt9CkwuZS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8KdS5CLmIoYSkK
-dD13aW5kb3cubG9jYXRpb24ucGF0aG5hbWUKcz1MLkc2KHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpyPUwu
-YUsod2luZG93LmxvY2F0aW9uLmhyZWYpCkwuR2UoKQppZih0IT09Ii8iJiZ0IT09Si5UMChkb2N1bWVu
-dC5xdWVyeVNlbGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50KSlMLkc3KHQscyxyLG5ldyBMLlZXKHQs
-cyxyKSkKcT1KLnFGKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5hcHBseS1taWdyYXRpb24iKSkKcD1x
-LiR0aQpvPXAuQygifigxKSIpLmIobmV3IEwub1ooKSkKdS5NLmIobnVsbCkKVy5KRShxLmEscS5iLG8s
-ITEscC5kKX0sCiRTOjEzfQpMLlZXLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7TC5Gcih0aGlzLmEs
-dGhpcy5iLHRoaXMuYyl9LAokUzowfQpMLm9aLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3UuVi5i
-KGEpCkwudHkoIi9hcHBseS1taWdyYXRpb24iKS5XNyhuZXcgTC5qcigpLHUuUCkuT0EobmV3IEwucWwo
-KSl9LAokUzo1fQpMLmpyLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0CnUuci5iKGEpCnQ9
-ZG9jdW1lbnQuYm9keQp0LmNsYXNzTGlzdC5yZW1vdmUoInByb3Bvc2VkIikKdC5jbGFzc0xpc3QuYWRk
-KCJhcHBsaWVkIil9LAokUzo3fQpMLnFsLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5xSigi
-YXBwbHkgbWlncmF0aW9uIGVycm9yOiAiK0guZChhKSxiKQp3aW5kb3cuYWxlcnQoIkNvdWxkIG5vdCBh
-cHBseSBtaWdyYXRpb24gKCIrSC5kKGEpKyIpLiIpfSwKJEM6IiQyIiwKJFI6MiwKJFM6MX0KTC5MLnBy
-b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1LkIuYihhKQp0PXdpbmRvdy5sb2NhdGlv
-bi5wYXRobmFtZQpzPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpCnI9TC5hSyh3aW5kb3cubG9jYXRp
-b24uaHJlZikKaWYodC5sZW5ndGg+MSlMLkc3KHQscyxyLG51bGwpCmVsc2V7TC5CRSh0LFAuRUYoWyJy
-ZWdpb25zIiwiIiwibmF2aWdhdGlvbkNvbnRlbnQiLCIiLCJlZGl0cyIsW11dLHUuTix1LnopKQpMLkJY
-KCImbmJzcDsiLG51bGwpfX0sCiRTOjEzfQpMLld4LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscixxPSJjb2xsYXBzZWQiCnUuVi5iKGEpCnQ9dGhpcy5hCnM9Si5SRSh0KQpyPXRoaXMuYgpp
-Zighcy5nRCh0KS50ZygwLHEpKXtzLmdEKHQpLmkoMCxxKQpKLmRSKHIpLmkoMCxxKX1lbHNle3MuZ0Qo
-dCkuUigwLHEpCkouZFIocikuUigwLHEpfX0sCiRTOjV9CkwuQU8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7dmFyIHQ9Si5xRih1LmguYihhKSkscz10LiR0aSxyPXMuQygifigxKSIpLmIobmV3IEwuZE4o
-KSkKdS5NLmIobnVsbCkKVy5KRSh0LmEsdC5iLHIsITEscy5kKX0sCiRTOjN9CkwuZE4ucHJvdG90eXBl
-PXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5WLmIoYSkKdD1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJ0
-YWJsZVtkYXRhLXBhdGhdIikKdC50b1N0cmluZwpMLnQyKGEsdC5nZXRBdHRyaWJ1dGUoImRhdGEtIitu
-ZXcgVy5TeShuZXcgVy5pNyh0KSkuTygicGF0aCIpKSl9LAokUzo1fQpMLkhvLnByb3RvdHlwZT17CiQx
-OmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1LmguYihhKQp0PUoucUYoYSkKcz10LiR0aQpyPXMuQygifigx
-KSIpLmIobmV3IEwueHooYSx0aGlzLmEpKQp1Lk0uYihudWxsKQpXLkpFKHQuYSx0LmIsciwhMSxzLmQp
-fSwKJFM6M30KTC54ei5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdAp1LlYuYihhKQp0PXRo
-aXMuYQpMLmhYKHRoaXMuYixQLlFBKHQuZ2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcu
-aTcodCkpLk8oIm9mZnNldCIpKSxudWxsLG51bGwpKX0sCiRTOjV9CkwuSUMucHJvdG90eXBlPXsKJDE6
-ZnVuY3Rpb24oYSl7dmFyIHQ9Si5xRih1LmguYihhKSkscz10LiR0aQpzLkMoIn4oMSkiKS5iKEwuSDAo
-KSkKdS5NLmIobnVsbCkKVy5KRSh0LmEsdC5iLEwuSDAoKSwhMSxzLmQpfSwKJFM6M30KTC5MMS5wcm90
-b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdAp1LnIuYihhKQp0PWEuc3RhdHVzCmlmKHQ9PT0yMDAp
-cmV0dXJuIGEKZWxzZSB0aHJvdyBILmIoIlJlcXVlc3QgZmFpbGVkOyBzdGF0dXMgb2YgIitILmQodCkp
-fSwKJFM6Mzh9CkwublQucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYS5hLHRoaXMu
-Yix0aGlzLmMpfSwKJFM6MH0KTC5CWi5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhpcy5h
-LmEsbnVsbCxudWxsKX0sCiRTOjB9CkwuRlEucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtMLnFK
-KCJoYW5kbGVQb3N0TGlua0NsaWNrOiAiK0guZChhKSxiKQp3aW5kb3cuYWxlcnQoIkNvdWxkIG5vdCBs
-b2FkICIrSC5kKHRoaXMuYSkrIiAoIitILmQoYSkrIikuIil9LAokQzoiJDIiLAokUjoyLAokUzoxfQpM
-LkdILnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3UuaC5iKGEpCiQuekIoKS50b1N0cmluZwp1LnUu
-YigkLm93KCkucSgwLCJobGpzIikpLlY3KCJoaWdobGlnaHRCbG9jayIsW2FdKX0sCiRTOjN9CkwuRFQu
-cHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5yLmIoYSkKdD1hLnN0YXR1cwppZih0PT09
-MjAwKXtMLlQxKFUueXUoQy5DdC5wVygwLGEucmVzcG9uc2VUZXh0LG51bGwpKSkKTC55WCgiLmVkaXQt
-cGFuZWwgLnBhbmVsLWNvbnRlbnQiKX1lbHNlIHdpbmRvdy5hbGVydCgiUmVxdWVzdCBmYWlsZWQ7IHN0
-YXR1cyBvZiAiK0guZCh0KSl9LAokUzo3fQpMLmVILnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7
-TC5xSigibG9hZFJlZ2lvbkV4cGxhbmF0aW9uOiAiK0guZChhKSxiKQp3aW5kb3cuYWxlcnQoIkNvdWxk
-IG5vdCBsb2FkICIrSC5kKHRoaXMuYSkrIiAoIitILmQoYSkrIikuIil9LAokQzoiJDIiLAokUjoyLAok
-UzoxfQpMLnpELnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzCnUuci5iKGEp
-CnQ9YS5zdGF0dXMKaWYodD09PTIwMCl7cz1yLmEKTC5CRShzLHUuYS5iKEMuQ3QucFcoMCxhLnJlc3Bv
-bnNlVGV4dCxudWxsKSkpCnQ9ci5iCkwuZkcodCxyLmMpCkwuQlgoQy54Qi50ZyhzLCI/Iik/Qy54Qi5O
-aihzLDAsQy54Qi5PWShzLCI/IikpOnMsdCkKdD1yLmQKaWYodCE9bnVsbCl0LiQwKCl9ZWxzZSB3aW5k
-b3cuYWxlcnQoIlJlcXVlc3QgZmFpbGVkOyBzdGF0dXMgb2YgIitILmQodCkpfSwKJFM6N30KTC5PRS5w
-cm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe0wucUooImxvYWRGaWxlOiAiK0guZChhKSxiKQp3aW5k
-b3cuYWxlcnQoIkNvdWxkIG5vdCBsb2FkICIrdGhpcy5hKyIgKCIrSC5kKGEpKyIpLiIpfSwKJEM6IiQy
-IiwKJFI6MiwKJFM6MX0KTC5UVy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIKdS5y
-LmIoYSkKdD1hLnN0YXR1cwppZih0PT09MjAwKXtzPUMuQ3QucFcoMCxhLnJlc3BvbnNlVGV4dCxudWxs
-KQpyPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5uYXYtdHJlZSIpCkoubDUociwiIikKTC50WChyLHMp
-fWVsc2Ugd2luZG93LmFsZXJ0KCJSZXF1ZXN0IGZhaWxlZDsgc3RhdHVzIG9mICIrSC5kKHQpKX0sCiRT
-Ojd9CkwueHIucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtMLnFKKCJsb2FkTmF2aWdhdGlvblRy
-ZWU6ICIrSC5kKGEpLGIpCndpbmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIit0aGlzLmErIiAoIitI
-LmQoYSkrIikuIil9LAokQzoiJDIiLAokUjoyLAokUzoxfQpMLkVFLnByb3RvdHlwZT17CiQxOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMKdS5WLmIoYSkKdD10aGlzLmEKcz10aGlzLmIKTC5hZih3aW5kb3cubG9jYXRp
-b24ucGF0aG5hbWUsdCxzLG5ldyBMLlFMKHQscykpCkwuaFgodGhpcy5jLHQpfSwKJFM6NX0KTC5RTC5w
-cm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHRoaXMu
-YSx0aGlzLmIpfSwKJFM6MH0KTC5WUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzPSJz
-ZWxlY3RlZC1maWxlIgp1LmguYihhKQphLnRvU3RyaW5nCnQ9Si5SRShhKQppZihhLmdldEF0dHJpYnV0
-ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KGEpKS5PKCJuYW1lIikpPT09dGhpcy5hLmEpdC5nRChh
-KS5pKDAscykKZWxzZSB0LmdEKGEpLlIoMCxzKX0sCiRTOjN9CkwuWEEucHJvdG90eXBlPXsKRWI6ZnVu
-Y3Rpb24oYSxiLGMpe3JldHVybiEwfSwKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuITB9LAokaWtGOjF9Ck0u
-bEkucHJvdG90eXBlPXsKV086ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPW51bGwKTS5ZRigiYWJzb2x1dGUi
-LEguVk0oW2IsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGxdLHUucykpCnQ9dGhpcy5hCnQ9dC5Z
-cihiKT4wJiYhdC5oSyhiKQppZih0KXJldHVybiBiCnQ9RC5SWCgpCnJldHVybiB0aGlzLnE3KDAsdCxi
-LHMscyxzLHMscyxzKX0sCnRNOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj1YLkNMKGEsdGhpcy5hKQpyLklW
-KCkKdD1yLmQKcz10Lmxlbmd0aAppZihzPT09MCl7dD1yLmIKcmV0dXJuIHQ9PW51bGw/Ii4iOnR9aWYo
-cz09PTEpe3Q9ci5iCnJldHVybiB0PT1udWxsPyIuIjp0fWlmKDA+PXMpcmV0dXJuIEguT0godCwtMSkK
-dC5wb3AoKQpDLk5tLm12KHIuZSkKci5JVigpCnJldHVybiByLncoMCl9LApxNzpmdW5jdGlvbihhLGIs
-YyxkLGUsZixnLGgsaSl7dmFyIHQ9SC5WTShbYixjLGQsZSxmLGcsaCxpXSx1LnMpCk0uWUYoImpvaW4i
-LHQpCnJldHVybiB0aGlzLklQKG5ldyBILlU1KHQsdS5iQi5iKG5ldyBNLk1pKCkpLHUuY2MpKX0sCklQ
-OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbAp1LlguYihhKQpmb3IodD1hLiR0aSxzPXQu
-QygiYTIoY1guRSkiKS5iKG5ldyBNLnE3KCkpLHI9YS5na3ooYSksdD1uZXcgSC5TTyhyLHMsdC5DKCJT
-TzxjWC5FPiIpKSxzPXRoaXMuYSxxPSExLHA9ITEsbz0iIjt0LkYoKTspe249ci5nbCgpCmlmKHMuaEso
-bikmJnApe209WC5DTChuLHMpCmw9by5jaGFyQ29kZUF0KDApPT0wP286bwpvPUMueEIuTmoobCwwLHMu
-U3AobCwhMCkpCm0uYj1vCmlmKHMuZHMobykpQy5ObS5ZKG0uZSwwLHMuZ21JKCkpCm89bS53KDApfWVs
-c2UgaWYocy5ZcihuKT4wKXtwPSFzLmhLKG4pCm89SC5kKG4pfWVsc2V7aWYoIShuLmxlbmd0aD4wJiZz
-LlVkKG5bMF0pKSlpZihxKW8rPXMuZ21JKCkKbys9SC5kKG4pfXE9cy5kcyhuKX1yZXR1cm4gby5jaGFy
-Q29kZUF0KDApPT0wP286b30sCm81OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKCF0aGlzLnkzKGEpKXJldHVy
-biBhCnQ9WC5DTChhLHRoaXMuYSkKdC5yUigpCnJldHVybiB0LncoMCl9LAp5MzpmdW5jdGlvbihhKXt2
-YXIgdCxzLHIscSxwLG8sbixtLGwsawphLnRvU3RyaW5nCnQ9dGhpcy5hCnM9dC5ZcihhKQppZihzIT09
-MCl7aWYodD09PSQuS2soKSlmb3Iocj0wO3I8czsrK3IpaWYoQy54Qi5XKGEscik9PT00NylyZXR1cm4h
-MApxPXMKcD00N31lbHNle3E9MApwPW51bGx9Zm9yKG89bmV3IEgucWooYSkuYSxuPW8ubGVuZ3RoLHI9
-cSxtPW51bGw7cjxuOysrcixtPXAscD1sKXtsPUMueEIubShvLHIpCmlmKHQucjQobCkpe2lmKHQ9PT0k
-LktrKCkmJmw9PT00NylyZXR1cm4hMAppZihwIT1udWxsJiZ0LnI0KHApKXJldHVybiEwCmlmKHA9PT00
-NilrPW09PW51bGx8fG09PT00Nnx8dC5yNChtKQplbHNlIGs9ITEKaWYoaylyZXR1cm4hMH19aWYocD09
-bnVsbClyZXR1cm4hMAppZih0LnI0KHApKXJldHVybiEwCmlmKHA9PT00Nil0PW09PW51bGx8fHQucjQo
-bSl8fG09PT00NgplbHNlIHQ9ITEKaWYodClyZXR1cm4hMApyZXR1cm4hMX0sCkhQOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQscyxyLHEscCxvPXRoaXMsbj0nVW5hYmxlIHRvIGZpbmQgYSBwYXRoIHRvICInCmI9by5X
-TygwLGIpCnQ9by5hCmlmKHQuWXIoYik8PTAmJnQuWXIoYSk+MClyZXR1cm4gby5vNShhKQppZih0Llly
-KGEpPD0wfHx0LmhLKGEpKWE9by5XTygwLGEpCmlmKHQuWXIoYSk8PTAmJnQuWXIoYik+MCl0aHJvdyBI
-LmIoWC5KVChuK0guZChhKSsnIiBmcm9tICInK0guZChiKSsnIi4nKSkKcz1YLkNMKGIsdCkKcy5yUigp
-CnI9WC5DTChhLHQpCnIuclIoKQpxPXMuZAppZihxLmxlbmd0aD4wJiZKLlJNKHFbMF0sIi4iKSlyZXR1
-cm4gci53KDApCnE9cy5iCnA9ci5iCmlmKHEhPXApcT1xPT1udWxsfHxwPT1udWxsfHwhdC5OYyhxLHAp
-CmVsc2UgcT0hMQppZihxKXJldHVybiByLncoMCkKd2hpbGUoITApe3E9cy5kCmlmKHEubGVuZ3RoPjAp
-e3A9ci5kCnE9cC5sZW5ndGg+MCYmdC5OYyhxWzBdLHBbMF0pfWVsc2UgcT0hMQppZighcSlicmVhawpD
-Lk5tLlc0KHMuZCwwKQpDLk5tLlc0KHMuZSwxKQpDLk5tLlc0KHIuZCwwKQpDLk5tLlc0KHIuZSwxKX1x
-PXMuZAppZihxLmxlbmd0aD4wJiZKLlJNKHFbMF0sIi4uIikpdGhyb3cgSC5iKFguSlQobitILmQoYSkr
-JyIgZnJvbSAiJytILmQoYikrJyIuJykpCnE9dS5OCkMuTm0uVUcoci5kLDAsUC5POChzLmQubGVuZ3Ro
-LCIuLiIscSkpCkMuTm0uWShyLmUsMCwiIikKQy5ObS5VRyhyLmUsMSxQLk84KHMuZC5sZW5ndGgsdC5n
-bUkoKSxxKSkKdD1yLmQKcT10Lmxlbmd0aAppZihxPT09MClyZXR1cm4iLiIKaWYocT4xJiZKLlJNKEMu
-Tm0uZ3JaKHQpLCIuIikpe3Q9ci5kCmlmKDA+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsLTEpCnQucG9w
-KCkKdD1yLmUKQy5ObS5tdih0KQpDLk5tLm12KHQpCkMuTm0uaSh0LCIiKX1yLmI9IiIKci5JVigpCnJl
-dHVybiByLncoMCl9fQpNLk1pLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBILnkoYSkh
-PW51bGx9LAokUzo4fQpNLnE3LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBILnkoYSkh
-PT0iIn0sCiRTOjh9Ck0uTm8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7SC55KGEpCnJldHVybiBh
-PT1udWxsPyJudWxsIjonIicrYSsnIid9LAokUzo2fQpCLkx1LnByb3RvdHlwZT17CnhaOmZ1bmN0aW9u
-KGEpe3ZhciB0LHM9dGhpcy5ZcihhKQppZihzPjApcmV0dXJuIEoubGQoYSwwLHMpCmlmKHRoaXMuaEso
-YSkpe2lmKDA+PWEubGVuZ3RoKXJldHVybiBILk9IKGEsMCkKdD1hWzBdfWVsc2UgdD1udWxsCnJldHVy
-biB0fSwKTmM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT09Yn19ClguV0QucHJvdG90eXBlPXsKSVY6ZnVu
-Y3Rpb24oKXt2YXIgdCxzLHI9dGhpcwp3aGlsZSghMCl7dD1yLmQKaWYoISh0Lmxlbmd0aCE9PTAmJkou
-Uk0oQy5ObS5ncloodCksIiIpKSlicmVhawp0PXIuZAppZigwPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0
-LC0xKQp0LnBvcCgpCkMuTm0ubXYoci5lKX10PXIuZQpzPXQubGVuZ3RoCmlmKHM+MClDLk5tLlkodCxz
-LTEsIiIpfSwKclI6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMsbD1ILlZNKFtdLHUu
-cykKZm9yKHQ9bS5kLHM9dC5sZW5ndGgscj0wLHE9MDtxPHQubGVuZ3RoO3QubGVuZ3RoPT09c3x8KDAs
-SC5saykodCksKytxKXtwPXRbcV0Kbz1KLmlhKHApCmlmKCEoby5ETihwLCIuIil8fG8uRE4ocCwiIikp
-KWlmKG8uRE4ocCwiLi4iKSlpZihsLmxlbmd0aD4wKWwucG9wKCkKZWxzZSArK3IKZWxzZSBDLk5tLmko
-bCxwKX1pZihtLmI9PW51bGwpQy5ObS5VRyhsLDAsUC5POChyLCIuLiIsdS5OKSkKaWYobC5sZW5ndGg9
-PT0wJiZtLmI9PW51bGwpQy5ObS5pKGwsIi4iKQpuPVAuZEgobC5sZW5ndGgsbmV3IFgucVIobSksITAs
-dS5OKQp0PW0uYgp0PXQhPW51bGwmJmwubGVuZ3RoPjAmJm0uYS5kcyh0KT9tLmEuZ21JKCk6IiIKSC50
-NihuKS5kLmIodCkKaWYoISFuLmZpeGVkJGxlbmd0aClILnZoKFAuTDQoImluc2VydCIpKQpuLnNwbGlj
-ZSgwLDAsdCkKbS5zbkoobCkKbS5zUGgobikKdD1tLmIKaWYodCE9bnVsbCYmbS5hPT09JC5LaygpKXt0
-LnRvU3RyaW5nCm0uYj1ILnlzKHQsIi8iLCJcXCIpfW0uSVYoKX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHQs
-cyxyPXRoaXMscT1yLmIKcT1xIT1udWxsP3E6IiIKZm9yKHQ9MDt0PHIuZC5sZW5ndGg7Kyt0KXtzPXIu
-ZQppZih0Pj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLHQpCnM9cStILmQoc1t0XSkKcT1yLmQKaWYodD49
-cS5sZW5ndGgpcmV0dXJuIEguT0gocSx0KQpxPXMrSC5kKHFbdF0pfXErPUguZChDLk5tLmdyWihyLmUp
-KQpyZXR1cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX0sCnNuSjpmdW5jdGlvbihhKXt0aGlzLmQ9dS5p
-LmIoYSl9LApzUGg6ZnVuY3Rpb24oYSl7dGhpcy5lPXUuaS5iKGEpfX0KWC5xUi5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmEuZ21JKCl9LAokUzozOX0KWC5kdi5wcm90b3R5cGU9
-ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJQYXRoRXhjZXB0aW9uOiAiK3RoaXMuYX19Ck8uekwucHJvdG90
-eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nb2ModGhpcyl9fQpFLk9GLnByb3RvdHlwZT17
-ClVkOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLnRnKGEsIi8iKX0sCnI0OmZ1bmN0aW9uKGEpe3JldHVy
-biBhPT09NDd9LApkczpmdW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aApyZXR1cm4gdCE9PTAmJkMueEIu
-bShhLHQtMSkhPT00N30sClNwOmZ1bmN0aW9uKGEsYil7aWYoYS5sZW5ndGghPT0wJiZDLnhCLlcoYSww
-KT09PTQ3KXJldHVybiAxCnJldHVybiAwfSwKWXI6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuU3AoYSwh
-MSl9LApoSzpmdW5jdGlvbihhKXtyZXR1cm4hMX0sCmdvYzpmdW5jdGlvbigpe3JldHVybiJwb3NpeCJ9
-LApnbUk6ZnVuY3Rpb24oKXtyZXR1cm4iLyJ9fQpGLnJ1LnByb3RvdHlwZT17ClVkOmZ1bmN0aW9uKGEp
-e3JldHVybiBDLnhCLnRnKGEsIi8iKX0sCnI0OmZ1bmN0aW9uKGEpe3JldHVybiBhPT09NDd9LApkczpm
-dW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aAppZih0PT09MClyZXR1cm4hMQppZihDLnhCLm0oYSx0LTEp
-IT09NDcpcmV0dXJuITAKcmV0dXJuIEMueEIuVGMoYSwiOi8vIikmJnRoaXMuWXIoYSk9PT10fSwKU3A6
-ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwPWEubGVuZ3RoCmlmKHA9PT0wKXJldHVybiAwCmlmKEMu
-eEIuVyhhLDApPT09NDcpcmV0dXJuIDEKZm9yKHQ9MDt0PHA7Kyt0KXtzPUMueEIuVyhhLHQpCmlmKHM9
-PT00NylyZXR1cm4gMAppZihzPT09NTgpe2lmKHQ9PT0wKXJldHVybiAwCnI9Qy54Qi5YVShhLCIvIixD
-LnhCLlFpKGEsIi8vIix0KzEpP3QrMzp0KQppZihyPD0wKXJldHVybiBwCmlmKCFifHxwPHIrMylyZXR1
-cm4gcgppZighQy54Qi5uKGEsImZpbGU6Ly8iKSlyZXR1cm4gcgppZighQi5ZdShhLHIrMSkpcmV0dXJu
-IHIKcT1yKzMKcmV0dXJuIHA9PT1xP3E6cis0fX1yZXR1cm4gMH0sCllyOmZ1bmN0aW9uKGEpe3JldHVy
-biB0aGlzLlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RoIT09MCYmQy54Qi5X
-KGEsMCk9PT00N30sCmdvYzpmdW5jdGlvbigpe3JldHVybiJ1cmwifSwKZ21JOmZ1bmN0aW9uKCl7cmV0
-dXJuIi8ifX0KTC5JVi5wcm90b3R5cGU9ewpVZDpmdW5jdGlvbihhKXtyZXR1cm4gQy54Qi50ZyhhLCIv
-Iil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09PTQ3fHxhPT09OTJ9LApkczpmdW5jdGlvbihhKXt2
-YXIgdD1hLmxlbmd0aAppZih0PT09MClyZXR1cm4hMQp0PUMueEIubShhLHQtMSkKcmV0dXJuISh0PT09
-NDd8fHQ9PT05Mil9LApTcDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1hLmxlbmd0aAppZihyPT09MCly
-ZXR1cm4gMAp0PUMueEIuVyhhLDApCmlmKHQ9PT00NylyZXR1cm4gMQppZih0PT09OTIpe2lmKHI8Mnx8
-Qy54Qi5XKGEsMSkhPT05MilyZXR1cm4gMQpzPUMueEIuWFUoYSwiXFwiLDIpCmlmKHM+MCl7cz1DLnhC
-LlhVKGEsIlxcIixzKzEpCmlmKHM+MClyZXR1cm4gc31yZXR1cm4gcn1pZihyPDMpcmV0dXJuIDAKaWYo
-IUIuT1ModCkpcmV0dXJuIDAKaWYoQy54Qi5XKGEsMSkhPT01OClyZXR1cm4gMApyPUMueEIuVyhhLDIp
-CmlmKCEocj09PTQ3fHxyPT09OTIpKXJldHVybiAwCnJldHVybiAzfSwKWXI6ZnVuY3Rpb24oYSl7cmV0
-dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5ZcihhKT09PTF9LApP
-dDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PT1iKXJldHVybiEwCmlmKGE9PT00NylyZXR1cm4gYj09
-PTkyCmlmKGE9PT05MilyZXR1cm4gYj09PTQ3CmlmKChhXmIpIT09MzIpcmV0dXJuITEKdD1hfDMyCnJl
-dHVybiB0Pj05NyYmdDw9MTIyfSwKTmM6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKaWYoYT09YilyZXR1
-cm4hMAp0PWEubGVuZ3RoCmlmKHQhPT1iLmxlbmd0aClyZXR1cm4hMQpmb3Iocz1KLnJZKGIpLHI9MDty
-PHQ7KytyKWlmKCF0aGlzLk90KEMueEIuVyhhLHIpLHMuVyhiLHIpKSlyZXR1cm4hMQpyZXR1cm4hMH0s
-CmdvYzpmdW5jdGlvbigpe3JldHVybiJ3aW5kb3dzIn0sCmdtSTpmdW5jdGlvbigpe3JldHVybiJcXCJ9
-fTsoZnVuY3Rpb24gYWxpYXNlcygpe3ZhciB0PUoudkIucHJvdG90eXBlCnQuVT10LncKdC5Taj10LmU3
-CnQ9Si5NRi5wcm90b3R5cGUKdC50PXQudwp0PVAuY1gucHJvdG90eXBlCnQuR0c9dC5ldgp0PVAuay5w
-cm90b3R5cGUKdC54Yj10LncKdD1XLmN2LnByb3RvdHlwZQp0LkRXPXQucjYKdD1XLm02LnByb3RvdHlw
-ZQp0LmpGPXQuRWIKdD1QLkU0LnByb3RvdHlwZQp0LlVyPXQucQp0LmU0PXQuWX0pKCk7KGZ1bmN0aW9u
-IGluc3RhbGxUZWFyT2Zmcygpe3ZhciB0PWh1bmtIZWxwZXJzLl9zdGF0aWNfMSxzPWh1bmtIZWxwZXJz
-Ll9zdGF0aWNfMCxyPWh1bmtIZWxwZXJzLmluc3RhbGxJbnN0YW5jZVRlYXJPZmYscT1odW5rSGVscGVy
-cy5pbnN0YWxsU3RhdGljVGVhck9mZixwPWh1bmtIZWxwZXJzLl9pbnN0YW5jZV8xdQp0KFAsIkVYIiwi
-WlYiLDkpCnQoUCwieXQiLCJvQSIsOSkKdChQLCJxVyIsIkJ6Iiw5KQpzKFAsIlVJIiwiZU4iLDIpCnIo
-UC5QZi5wcm90b3R5cGUsImdZSiIsMCwxLG51bGwsWyIkMiIsIiQxIl0sWyJ3MCIsInBtIl0sMzYsMCkK
-dChQLCJQSCIsIk10Iiw2KQpxKFcsInBTIiw0LG51bGwsWyIkNCJdLFsieVciXSwxMSwwKQpxKFcsIlY0
-Iiw0LG51bGwsWyIkNCJdLFsiUVciXSwxMSwwKQpwKFAuQXMucHJvdG90eXBlLCJndU0iLCJUIiw2KQp0
-KFAsImlHIiwid1kiLDQpCnQoUCwidzAiLCJMNyIsNDIpCnEoTCwiWE4iLDEsbnVsbCxbIiQyJHJlbGF0
-aXZlVG8iLCIkMSJdLFsidDIiLGZ1bmN0aW9uKGEpe3JldHVybiBMLnQyKGEsbnVsbCl9XSw0MywwKQp0
-KEwsIkgwIiwidW0iLDI5KX0pKCk7KGZ1bmN0aW9uIGluaGVyaXRhbmNlKCl7dmFyIHQ9aHVua0hlbHBl
-cnMubWl4aW4scz1odW5rSGVscGVycy5pbmhlcml0LHI9aHVua0hlbHBlcnMuaW5oZXJpdE1hbnkKcyhQ
-LmssbnVsbCkKcihQLmssW0guZW8sSi52QixKLm0xLFAublksUC5jWCxILmE3LFAuQW4sSC5TVSxILlJl
-LEgud3YsUC5QbixILldVLEguTEksSC5UcCxILlpyLFAuWFMsSC5YTyxQLllrLEguZGIsSC5ONixILlZS
-LEguRUssSC5QYixILnRRLEguU2QsSC5KYyxILkcsUC5XMyxQLlBmLFAuRmUsUC52cyxQLk9NLFAucWgs
-UC5NTyxQLmtULFAuQ3csUC5tMCxQLlh2LFAuYm4sUC5sbSxQLmxELFAuS1AsUC5sZixQLldZLFAuVWss
-UC5SdyxQLmJ6LFAuYTIsUC5pUCxQLkZLLFAuazUsUC5LWSxQLkNELFAuYUUsUC5FSCxQLnpNLFAuWjAs
-UC5jOCxQLk9kLFAuaWIsUC5HeixQLnFVLFAuUm4sUC5HRCxQLkRuLFAuUEUsUC5VZixXLmlkLFcuRmss
-Vy5KUSxXLkdtLFcudkQsVy5tNixXLk93LFcuVzksVy5kVyxXLmtGLFcubWssVy5LbyxQLmlKLFAuRTQs
-UC5uNixVLmQyLFUuU2UsVS51RixVLk1sLFUueUQsVS53YixULkdWLEwuWEEsTS5sSSxPLnpMLFguV0Qs
-WC5kdl0pCnIoSi52QixbSi55RSxKLllFLEouTUYsSi5qZCxKLnFJLEouRHIsSC5FVCxXLkQwLFcuQXos
-Vy5MZSxXLk5oLFcuSUIsVy5uNyxXLmVhLFcuYnIsVy5TZyxXLnU4LFcuSzcsVy5YVyxQLmhGXSkKcihK
-Lk1GLFtKLmlDLEoua2QsSi5jNV0pCnMoSi5QbyxKLmpkKQpyKEoucUksW0oudXIsSi5WQV0pCnMoUC5M
-VSxQLm5ZKQpyKFAuTFUsW0guWEMsVy53eixXLmU3XSkKcyhILnFqLEguWEMpCnIoUC5jWCxbSC5iUSxI
-LlU1LFAubVcsSC51bl0pCnIoSC5iUSxbSC5hTCxILmk1LFAueHVdKQpyKEguYUwsW0gubkgsSC5BOCxQ
-Lmk4XSkKcyhILlNPLFAuQW4pCnMoUC5SVSxQLlBuKQpzKFAuR2osUC5SVSkKcyhILlBELFAuR2opCnMo
-SC5MUCxILldVKQpyKEguVHAsW0guQ2osSC5BbSxILmxjLEguZEMsSC53TixILlZYLFAudGgsUC5oYSxQ
-LlZzLFAuRnQsUC55SCxQLmRhLFAub1EsUC5wVixQLlU3LFAudnIsUC5ySCxQLktGLFAuWkwsUC5SVCxQ
-LmpaLFAucnEsUC5SVyxQLkI1LFAuUEksUC5wSyxQLmhqLFAuVnAsUC5PUixQLnJhLFAuV0YsUC5uMSxQ
-LmNTLFAuVkMsUC50cCxQLmUxLFAuTlksUC5SWixQLk1FLFAueTUsUC5xMyxQLnlJLFAuYzYsUC5xZCxX
-LkN2LFcuYlUsVy5oSCxXLktTLFcuQTMsVy52TixXLlV2LFcuRWcsVy5FbyxXLldrLFcuSUEsVy5mbSxQ
-LmxSLFAuamcsUC5HRSxQLk43LFAudVEsUC5QQyxQLlltLFAuTnosUC5RUyxQLm5wLEwuZSxMLlZXLEwu
-b1osTC5qcixMLnFsLEwuTCxMLld4LEwuQU8sTC5kTixMLkhvLEwueHosTC5JQyxMLkwxLEwublQsTC5C
-WixMLkZRLEwuR0gsTC5EVCxMLmVILEwuekQsTC5PRSxMLlRXLEwueHIsTC5FRSxMLlFMLEwuVlMsTS5N
-aSxNLnE3LE0uTm8sWC5xUl0pCnIoUC5YUyxbSC5XMCxILmF6LEgudlYsSC5FcSxQLkM2LEgudTksUC5u
-LFAudSxQLm1wLFAudWIsUC5kcyxQLmxqLFAuVVYsUC5jXSkKcihILmxjLFtILnp4LEguclRdKQpzKEgu
-a1ksUC5DNikKcyhQLmlsLFAuWWspCnIoUC5pbCxbSC5ONSxQLnV3LFcuRDksVy5TeV0pCnMoSC5LVyxQ
-Lm1XKQpzKEguYjAsSC5FVCkKcihILmIwLFtILlJHLEguV0JdKQpzKEguVlAsSC5SRykKcyhILkRnLEgu
-VlApCnMoSC5aRyxILldCKQpzKEguUGcsSC5aRykKcihILlBnLFtILnhqLEguZEUsSC5aQSxILndmLEgu
-UHEsSC5lRSxILlY2XSkKcihILnU5LFtILmh6LEguaU1dKQpzKFAuWmYsUC5QZikKcyhQLkppLFAubTAp
-CnMoUC5iNixQLlh2KQpzKFAuVmosUC5XWSkKcihQLlVrLFtQLkNWLFAuWmksUC5ieV0pCnMoUC53SSxQ
-LmtUKQpyKFAud0ksW1AuVTgsUC5NeCxQLkUzLFAuR1ldKQpzKFAudTUsUC5aaSkKcihQLkZLLFtQLkNQ
-LFAuS05dKQpyKFAudSxbUC5iSixQLmVZXSkKcyhQLnFlLFAuRG4pCnIoVy5EMCxbVy51SCxXLndhLFcu
-SzUsVy5DbV0pCnIoVy51SCxbVy5jdixXLm54LFcuUUYsVy5DUV0pCnIoVy5jdixbVy5xRSxQLmQ1XSkK
-cihXLnFFLFtXLkdoLFcuZlksVy5uQixXLlFQLFcuaDQsVy5TTixXLmxwLFcuVGIsVy5JdixXLkJULFcu
-eVldKQpzKFcub0osVy5MZSkKcyhXLlQ1LFcuQXopCnMoVy5WYixXLlFGKQpzKFcuTzcsVy53YSkKcihX
-LmVhLFtXLnc2LFcuZXddKQpzKFcuQWosVy53NikKcyhXLnJCLFcuSzcpCnMoVy5CSCxXLnJCKQpzKFcu
-dzQsVy5JQikKcyhXLm9hLFcuWFcpCnMoVy5yaCxXLm9hKQpzKFcuaTcsVy5EOSkKcyhQLkFzLFAuVmop
-CnIoUC5BcyxbVy5JNCxQLktlXSkKcyhXLlJPLFAucWgpCnMoVy5DcSxXLlJPKQpzKFcueEMsUC5NTykK
-cyhXLmN0LFcubTYpCnMoUC5CZixQLmlKKQpyKFAuRTQsW1AucjcsUC5jb10pCnMoUC5UeixQLmNvKQpz
-KFAubmQsUC5kNSkKcyhCLkx1LE8uekwpCnIoQi5MdSxbRS5PRixGLnJ1LEwuSVZdKQp0KEguWEMsSC5S
-ZSkKdChILlJHLFAubEQpCnQoSC5WUCxILlNVKQp0KEguV0IsUC5sRCkKdChILlpHLEguU1UpCnQoUC5u
-WSxQLmxEKQp0KFAuV1ksUC5sZikKdChQLlJVLFAuS1ApCnQoVy5MZSxXLmlkKQp0KFcuSzcsUC5sRCkK
-dChXLnJCLFcuR20pCnQoVy5YVyxQLmxEKQp0KFcub2EsVy5HbSkKdChQLmNvLFAubEQpfSkoKQp2YXIg
-dj17dHlwZVVuaXZlcnNlOntlQzpuZXcgTWFwKCksdFI6e30sZVQ6e30sdFBWOnt9LHNFQTpbXX0sbWFu
-Z2xlZEdsb2JhbE5hbWVzOntLTjoiaW50IixDUDoiZG91YmxlIixGSzoibnVtIixxVToiU3RyaW5nIixh
-MjoiYm9vbCIsYzg6Ik51bGwiLHpNOiJMaXN0In0sbWFuZ2xlZE5hbWVzOnt9LGdldFR5cGVGcm9tTmFt
-ZTpnZXRHbG9iYWxGcm9tTmFtZSxtZXRhZGF0YTpbXSx0eXBlczpbImM4KCkiLCJjOChALEApIiwifigp
-IiwiYzgoY3YpIiwiQChAKSIsImM4KEFqKSIsInFVKHFVKSIsImM4KE83KSIsImEyKHFVKSIsIn4ofigp
-KSIsImM4KHFVLHFVKSIsImEyKGN2LHFVLHFVLEpRKSIsImM4KEApIiwiYzgoZWEpIiwifih4dTxxVT4p
-IiwiYTIoa0YpIiwiYzgocVUsQCkiLCJjOChxVSkiLCJLTihLTixLTikiLCJ+KHFVLHFVKSIsIm42KEtO
-KSIsIm42KEAsQCkiLCJ+KHFVW0BdKSIsIn4ocVUsS04pIiwiYzgoZXcpIiwiQChlYSkiLCJaMDxxVSxx
-VT4oWjA8cVUscVU+LHFVKSIsImM4KEdELEApIiwifih1SCx1SCkiLCJ+KEFqKSIsIkAocVUpIiwicjco
-QCkiLCJUejxAPihAKSIsIkU0KEApIiwidnM8QD4oQCkiLCJjOChAW0d6XSkiLCJ+KGtbR3pdKSIsImEy
-KHh1PHFVPikiLCJPNyhPNykiLCJxVShLTikiLCJAKEAscVUpIiwiYzgofigpKSIsImsoQCkiLCJ+KEFq
-e3JlbGF0aXZlVG86cVV9KSIsImEyKHVIKSJdLGludGVyY2VwdG9yc0J5VGFnOm51bGwsbGVhZlRhZ3M6
-bnVsbH0KSC54Yih2LnR5cGVVbml2ZXJzZSxKU09OLnBhcnNlKCd7ImM1IjoiTUYiLCJpQyI6Ik1GIiwi
-a2QiOiJNRiIsInJ4IjoiZWEiLCJlNSI6ImVhIiwiWTAiOiJkNSIsIld0IjoiZDUiLCJ2MCI6ImV3Iiwi
-TXIiOiJxRSIsImVMIjoicUUiLCJJMCI6InVIIiwiaHMiOiJ1SCIsIlhnIjoiUUYiLCJ5YyI6IkFqIiwi
-eTQiOiJ3NiIsImFQIjoiQ20iLCJ4YyI6Im54Iiwia0oiOiJueCIsInpVIjoiRGciLCJkZiI6IkVUIiwi
-eUUiOnsiYTIiOltdfSwiWUUiOnsiYzgiOltdfSwiTUYiOnsidm0iOltdLCJFSCI6W119LCJqZCI6eyJ6
-TSI6WyIxIl0sImNYIjpbIjEiXX0sIlBvIjp7ImpkIjpbIjEiXSwiek0iOlsiMSJdLCJjWCI6WyIxIl19
-LCJtMSI6eyJBbiI6WyIxIl19LCJxSSI6eyJDUCI6W10sIkZLIjpbXX0sInVyIjp7IktOIjpbXSwiQ1Ai
-OltdLCJGSyI6W119LCJWQSI6eyJDUCI6W10sIkZLIjpbXX0sIkRyIjp7InFVIjpbXSwidlgiOltdfSwi
-cWoiOnsiUmUiOlsiS04iXSwibEQiOlsiS04iXSwiek0iOlsiS04iXSwiY1giOlsiS04iXSwibEQuRSI6
-IktOIiwiUmUuRSI6IktOIn0sImJRIjp7ImNYIjpbIjEiXX0sImFMIjp7ImNYIjpbIjEiXX0sIm5IIjp7
-ImFMIjpbIjEiXSwiY1giOlsiMSJdLCJhTC5FIjoiMSIsImNYLkUiOiIxIn0sImE3Ijp7IkFuIjpbIjEi
-XX0sIkE4Ijp7ImFMIjpbIjIiXSwiY1giOlsiMiJdLCJhTC5FIjoiMiIsImNYLkUiOiIyIn0sIlU1Ijp7
-ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiU08iOnsiQW4iOlsiMSJdfSwiWEMiOnsiUmUiOlsiMSJdLCJs
-RCI6WyIxIl0sInpNIjpbIjEiXSwiY1giOlsiMSJdfSwid3YiOnsiR0QiOltdfSwiUEQiOnsiR2oiOlsi
-MSIsIjIiXSwiUlUiOlsiMSIsIjIiXSwiUG4iOlsiMSIsIjIiXSwiS1AiOlsiMSIsIjIiXSwiWjAiOlsi
-MSIsIjIiXX0sIldVIjp7IlowIjpbIjEiLCIyIl19LCJMUCI6eyJXVSI6WyIxIiwiMiJdLCJaMCI6WyIx
-IiwiMiJdfSwiTEkiOnsidlEiOltdfSwiVzAiOnsiWFMiOltdfSwiYXoiOnsiWFMiOltdfSwidlYiOnsi
-WFMiOltdfSwiWE8iOnsiR3oiOltdfSwiVHAiOnsiRUgiOltdfSwibGMiOnsiRUgiOltdfSwiengiOnsi
-RUgiOltdfSwiclQiOnsiRUgiOltdfSwiRXEiOnsiWFMiOltdfSwia1kiOnsiWFMiOltdfSwiTjUiOnsi
-Rm8iOlsiMSIsIjIiXSwiWWsiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXSwiWWsuSyI6IjEiLCJZay5W
-IjoiMiJ9LCJpNSI6eyJjWCI6WyIxIl0sImNYLkUiOiIxIn0sIk42Ijp7IkFuIjpbIjEiXX0sIlZSIjp7
-IndMIjpbXSwidlgiOltdfSwiRUsiOnsiaWIiOltdLCJPZCI6W119LCJLVyI6eyJjWCI6WyJpYiJdLCJj
-WC5FIjoiaWIifSwiUGIiOnsiQW4iOlsiaWIiXX0sInRRIjp7Ik9kIjpbXX0sInVuIjp7ImNYIjpbIk9k
-Il0sImNYLkUiOiJPZCJ9LCJTZCI6eyJBbiI6WyJPZCJdfSwiRVQiOnsiQVMiOltdfSwiYjAiOnsiWGoi
-OlsiQCJdLCJFVCI6W10sIkFTIjpbXX0sIkRnIjp7ImxEIjpbIkNQIl0sIlhqIjpbIkAiXSwiek0iOlsi
-Q1AiXSwiRVQiOltdLCJTVSI6WyJDUCJdLCJBUyI6W10sImNYIjpbIkNQIl0sImxELkUiOiJDUCJ9LCJQ
-ZyI6eyJsRCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJYaiI6WyJAIl0sIkVUIjpbXSwiU1UiOlsiS04iXSwi
-QVMiOltdLCJjWCI6WyJLTiJdfSwieGoiOnsibEQiOlsiS04iXSwiek0iOlsiS04iXSwiWGoiOlsiQCJd
-LCJFVCI6W10sIlNVIjpbIktOIl0sIkFTIjpbXSwiY1giOlsiS04iXSwibEQuRSI6IktOIn0sImRFIjp7
-ImxEIjpbIktOIl0sInpNIjpbIktOIl0sIlhqIjpbIkAiXSwiRVQiOltdLCJTVSI6WyJLTiJdLCJBUyI6
-W10sImNYIjpbIktOIl0sImxELkUiOiJLTiJ9LCJaQSI6eyJsRCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJY
-aiI6WyJAIl0sIkVUIjpbXSwiU1UiOlsiS04iXSwiQVMiOltdLCJjWCI6WyJLTiJdLCJsRC5FIjoiS04i
-fSwid2YiOnsibEQiOlsiS04iXSwiek0iOlsiS04iXSwiWGoiOlsiQCJdLCJFVCI6W10sIlNVIjpbIktO
-Il0sIkFTIjpbXSwiY1giOlsiS04iXSwibEQuRSI6IktOIn0sIlBxIjp7ImxEIjpbIktOIl0sInpNIjpb
-IktOIl0sIlhqIjpbIkAiXSwiRVQiOltdLCJTVSI6WyJLTiJdLCJBUyI6W10sImNYIjpbIktOIl0sImxE
-LkUiOiJLTiJ9LCJlRSI6eyJsRCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJYaiI6WyJAIl0sIkVUIjpbXSwi
-U1UiOlsiS04iXSwiQVMiOltdLCJjWCI6WyJLTiJdLCJsRC5FIjoiS04ifSwiVjYiOnsibjYiOltdLCJs
-RCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJYaiI6WyJAIl0sIkVUIjpbXSwiU1UiOlsiS04iXSwiQVMiOltd
-LCJjWCI6WyJLTiJdLCJsRC5FIjoiS04ifSwidTkiOnsiWFMiOltdfSwiaHoiOnsiWFMiOltdfSwiaU0i
-OnsiWFMiOltdfSwiWmYiOnsiUGYiOlsiMSJdfSwidnMiOnsiYjgiOlsiMSJdfSwiQ3ciOnsiWFMiOltd
-fSwibTAiOnsiSkIiOltdfSwiSmkiOnsiSkIiOltdfSwiYjYiOnsiWHYiOlsiMSJdLCJ4dSI6WyIxIl0s
-ImNYIjpbIjEiXX0sImxtIjp7IkFuIjpbIjEiXX0sIm1XIjp7ImNYIjpbIjEiXX0sIkxVIjp7ImxEIjpb
-IjEiXSwiek0iOlsiMSJdLCJjWCI6WyIxIl19LCJpbCI6eyJZayI6WyIxIiwiMiJdLCJaMCI6WyIxIiwi
-MiJdfSwiWWsiOnsiWjAiOlsiMSIsIjIiXX0sIlBuIjp7IlowIjpbIjEiLCIyIl19LCJHaiI6eyJSVSI6
-WyIxIiwiMiJdLCJQbiI6WyIxIiwiMiJdLCJLUCI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiVmoi
-OnsibGYiOlsiMSJdLCJ4dSI6WyIxIl0sImNYIjpbIjEiXX0sIlh2Ijp7Inh1IjpbIjEiXSwiY1giOlsi
-MSJdfSwidXciOnsiWWsiOlsicVUiLCJAIl0sIlowIjpbInFVIiwiQCJdLCJZay5LIjoicVUiLCJZay5W
-IjoiQCJ9LCJpOCI6eyJhTCI6WyJxVSJdLCJjWCI6WyJxVSJdLCJhTC5FIjoicVUiLCJjWC5FIjoicVUi
-fSwiQ1YiOnsiVWsiOlsiek08S04+IiwicVUiXSwiVWsuUyI6InpNPEtOPiJ9LCJVOCI6eyJ3SSI6WyJ6
-TTxLTj4iLCJxVSJdfSwiWmkiOnsiVWsiOlsicVUiLCJ6TTxLTj4iXX0sImJ5Ijp7IlVrIjpbImsiLCJx
-VSJdLCJVay5TIjoiayJ9LCJNeCI6eyJ3SSI6WyJxVSIsImsiXX0sInU1Ijp7IlVrIjpbInFVIiwiek08
-S04+Il0sIlVrLlMiOiJxVSJ9LCJFMyI6eyJ3SSI6WyJxVSIsInpNPEtOPiJdfSwiR1kiOnsid0kiOlsi
-ek08S04+IiwicVUiXX0sIkNQIjp7IkZLIjpbXX0sIkM2Ijp7IlhTIjpbXX0sIm4iOnsiWFMiOltdfSwi
-dSI6eyJYUyI6W119LCJiSiI6eyJYUyI6W119LCJlWSI6eyJYUyI6W119LCJtcCI6eyJYUyI6W119LCJ1
-YiI6eyJYUyI6W119LCJkcyI6eyJYUyI6W119LCJsaiI6eyJYUyI6W119LCJVViI6eyJYUyI6W119LCJr
-NSI6eyJYUyI6W119LCJLWSI6eyJYUyI6W119LCJjIjp7IlhTIjpbXX0sIktOIjp7IkZLIjpbXX0sInpN
-Ijp7ImNYIjpbIjEiXX0sImliIjp7Ik9kIjpbXX0sInh1Ijp7ImNYIjpbIjEiXX0sInFVIjp7InZYIjpb
-XX0sIlJuIjp7IkJMIjpbXX0sIkRuIjp7ImlEIjpbXX0sIlVmIjp7ImlEIjpbXX0sInFlIjp7ImlEIjpb
-XX0sInFFIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJHaCI6eyJjdiI6W10sInVIIjpbXSwiRDAi
-OltdfSwiZlkiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm5CIjp7ImN2IjpbXSwidUgiOltdLCJE
-MCI6W119LCJRUCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwibngiOnsidUgiOltdLCJEMCI6W119
-LCJRRiI6eyJ1SCI6W10sIkQwIjpbXX0sIklCIjp7InRuIjpbIkZLIl19LCJ3eiI6eyJsRCI6WyIxIl0s
-InpNIjpbIjEiXSwiY1giOlsiMSJdLCJsRC5FIjoiMSJ9LCJjdiI6eyJ1SCI6W10sIkQwIjpbXX0sIlQ1
-Ijp7IkF6IjpbXX0sImg0Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJWYiI6eyJ1SCI6W10sIkQw
-IjpbXX0sIk83Ijp7IkQwIjpbXX0sIndhIjp7IkQwIjpbXX0sIkFqIjp7ImVhIjpbXX0sImU3Ijp7ImxE
-IjpbInVIIl0sInpNIjpbInVIIl0sImNYIjpbInVIIl0sImxELkUiOiJ1SCJ9LCJ1SCI6eyJEMCI6W119
-LCJCSCI6eyJHbSI6WyJ1SCJdLCJsRCI6WyJ1SCJdLCJ6TSI6WyJ1SCJdLCJYaiI6WyJ1SCJdLCJjWCI6
-WyJ1SCJdLCJsRC5FIjoidUgiLCJHbS5FIjoidUgifSwiU04iOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpb
-XX0sImV3Ijp7ImVhIjpbXX0sImxwIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJUYiI6eyJjdiI6
-W10sInVIIjpbXSwiRDAiOltdfSwiSXYiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIkJUIjp7ImN2
-IjpbXSwidUgiOltdLCJEMCI6W119LCJ5WSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwidzYiOnsi
-ZWEiOltdfSwiSzUiOnsidjYiOltdLCJEMCI6W119LCJDbSI6eyJEMCI6W119LCJDUSI6eyJ1SCI6W10s
-IkQwIjpbXX0sInc0Ijp7InRuIjpbIkZLIl19LCJyaCI6eyJHbSI6WyJ1SCJdLCJsRCI6WyJ1SCJdLCJ6
-TSI6WyJ1SCJdLCJYaiI6WyJ1SCJdLCJjWCI6WyJ1SCJdLCJsRC5FIjoidUgiLCJHbS5FIjoidUgifSwi
-RDkiOnsiWWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFVIl19LCJpNyI6eyJZayI6WyJxVSIsInFV
-Il0sIlowIjpbInFVIiwicVUiXSwiWWsuSyI6InFVIiwiWWsuViI6InFVIn0sIlN5Ijp7IllrIjpbInFV
-IiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZay5LIjoicVUiLCJZay5WIjoicVUifSwiSTQiOnsibGYi
-OlsicVUiXSwieHUiOlsicVUiXSwiY1giOlsicVUiXX0sIlJPIjp7InFoIjpbIjEiXX0sIkNxIjp7IlJP
-IjpbIjEiXSwicWgiOlsiMSJdfSwiSlEiOnsia0YiOltdfSwidkQiOnsia0YiOltdfSwibTYiOnsia0Yi
-OltdfSwiY3QiOnsia0YiOltdfSwiT3ciOnsia0YiOltdfSwiVzkiOnsiQW4iOlsiMSJdfSwiZFciOnsi
-djYiOltdLCJEMCI6W119LCJtayI6eyJ5MCI6W119LCJLbyI6eyJvbiI6W119LCJBcyI6eyJsZiI6WyJx
-VSJdLCJ4dSI6WyJxVSJdLCJjWCI6WyJxVSJdfSwicjciOnsiRTQiOltdfSwiVHoiOnsibEQiOlsiMSJd
-LCJ6TSI6WyIxIl0sIkU0IjpbXSwiY1giOlsiMSJdLCJsRC5FIjoiMSJ9LCJuZCI6eyJkNSI6W10sImN2
-IjpbXSwidUgiOltdLCJEMCI6W119LCJLZSI6eyJsZiI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJjWCI6WyJx
-VSJdfSwiZDUiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm42Ijp7InpNIjpbIktOIl0sIkFTIjpb
-XSwiY1giOlsiS04iXX0sIlhBIjp7ImtGIjpbXX0sIk9GIjp7Ikx1IjpbXX0sInJ1Ijp7Ikx1IjpbXX0s
-IklWIjp7Ikx1IjpbXX19JykpCkguRkYodi50eXBlVW5pdmVyc2UsSlNPTi5wYXJzZSgneyJiUSI6MSwi
-WEMiOjEsIk1PIjoxLCJrVCI6MiwibVciOjEsIkxVIjoxLCJpbCI6MiwiVmoiOjEsIm5ZIjoxLCJXWSI6
-MSwiY28iOjF9JykpCnZhciB1PShmdW5jdGlvbiBydGlpKCl7dmFyIHQ9SC5OMApyZXR1cm57azp0KCJH
-aCIpLG46dCgiQ3ciKSxGOnQoIm5CIiksZDp0KCJBeiIpLFk6dCgiUVAiKSxnRjp0KCJQRDxHRCxAPiIp
-LGg6dCgiY3YiKSxiVTp0KCJYUyIpLEI6dCgiZWEiKSxhUzp0KCJEMCIpLGM4OnQoIlQ1IiksWjp0KCJF
-SCIpLGM6dCgiYjg8QD4iKSxyOnQoIk83IiksSTp0KCJTZyIpLG86dCgidlEiKSxlaDp0KCJjWDx1SD4i
-KSxYOnQoImNYPHFVPiIpLFI6dCgiY1g8QD4iKSxmQTp0KCJqZDxTZT4iKSxiUDp0KCJqZDx1Rj4iKSxt
-OnQoImpkPGtGPiIpLHM6dCgiamQ8cVU+IiksaGg6dCgiamQ8eUQ+IiksYUo6dCgiamQ8d2I+IiksYjp0
-KCJqZDxAPiIpLHQ6dCgiamQ8S04+IiksZUg6dCgidm0iKSxnOnQoImM1IiksYVU6dCgiWGo8QD4iKSxh
-bTp0KCJUejxAPiIpLGVvOnQoIk41PEdELEA+IiksdTp0KCJFNCIpLGR6OnQoImhGIiksaTp0KCJ6TTxx
-VT4iKSxqOnQoInpNPEA+IiksTDp0KCJ6TTxLTj4iKSxmOnQoIlowPHFVLHFVPiIpLGE6dCgiWjA8cVUs
-QD4iKSxHOnQoIlowPEAsQD4iKSxkdjp0KCJBODxxVSxxVT4iKSxkbzp0KCJBODxxVSxAPiIpLFY6dCgi
-QWoiKSxkRDp0KCJFVCIpLGJtOnQoIlY2IiksQTp0KCJ1SCIpLGU6dCgia0YiKSxQOnQoImM4IiksSzp0
-KCJrIikscDp0KCJldyIpLHE6dCgidG48Rks+IiksZnY6dCgid0wiKSxhdjp0KCJKYyIpLGV3OnQoIm5k
-IiksQzp0KCJ4dTxxVT4iKSxsOnQoIkd6IiksTjp0KCJxVSIpLGRHOnQoInFVKHFVKSIpLGc3OnQoImQ1
-IiksZm86dCgiR0QiKSxhVzp0KCJ5WSIpLHY6dCgiQVMiKSxnYzp0KCJuNiIpLGFrOnQoImtkIiksVDp0
-KCJHajxxVSxxVT4iKSx3OnQoImlEIiksY2M6dCgiVTU8cVU+IiksZzQ6dCgiSzUiKSxjaTp0KCJ2NiIp
-LGcyOnQoIkNtIiksRTp0KCJaZjxPNz4iKSxoOTp0KCJDUSIpLGFjOnQoImU3IiksUTp0KCJDcTxBaj4i
-KSxTOnQoInd6PGN2PiIpLHg6dCgiRmU8QCxAPiIpLGFvOnQoInZzPE83PiIpLF86dCgidnM8QD4iKSxm
-Sjp0KCJ2czxLTj4iKSxPOnQoIkpRIiksSjp0KCJibiIpLGNKOnQoImEyIiksYWw6dCgiYTIoaykiKSxi
-Qjp0KCJhMihxVSkiKSxiZjp0KCJhMihAKSIpLHo6dCgiQCIpLGZPOnQoIkAoKSIpLFU6dCgiQChlYSki
-KSx5OnQoIkAoaykiKSxlcDp0KCJAKGssaykiKSxXOnQoIkAoayxHeikiKSxjaDp0KCJAKHh1PHFVPiki
-KSxkTzp0KCJAKHFVKSIpLGI4OnQoIkAoQCxAKSIpLEg6dCgifiIpLE06dCgifigpIiksYW46dCgifihl
-dykiKSxEOnQoIn4ocVUscVUpIiksY0E6dCgifihxVSxAKSIpfX0pKCk7KGZ1bmN0aW9uIGNvbnN0YW50
-cygpe3ZhciB0PWh1bmtIZWxwZXJzLm1ha2VDb25zdExpc3QKQy5SWT1XLlFQLnByb3RvdHlwZQpDLkJa
-PVcuVmIucHJvdG90eXBlCkMuRHQ9Vy5PNy5wcm90b3R5cGUKQy5Paz1KLnZCLnByb3RvdHlwZQpDLk5t
-PUouamQucHJvdG90eXBlCkMuam49Si51ci5wcm90b3R5cGUKQy5qTj1KLllFLnByb3RvdHlwZQpDLkNE
-PUoucUkucHJvdG90eXBlCkMueEI9Si5Eci5wcm90b3R5cGUKQy5ERz1KLmM1LnByb3RvdHlwZQpDLkV4
-PVcudTgucHJvdG90eXBlCkMuTHQ9Vy5TTi5wcm90b3R5cGUKQy5aUT1KLmlDLnByb3RvdHlwZQpDLkll
-PVcuVGIucHJvdG90eXBlCkMudkI9Si5rZC5wcm90b3R5cGUKQy5vbD1XLks1LnByb3RvdHlwZQpDLnk4
-PW5ldyBQLlU4KCkKQy5oOT1uZXcgUC5DVigpCkMuTzQ9ZnVuY3Rpb24gZ2V0VGFnRmFsbGJhY2sobykg
-ewogIHZhciBzID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG8pOwogIHJldHVybiBzLnN1
-YnN0cmluZyg4LCBzLmxlbmd0aCAtIDEpOwp9CkMuWXE9ZnVuY3Rpb24oKSB7CiAgdmFyIHRvU3RyaW5n
-RnVuY3Rpb24gPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOwogIGZ1bmN0aW9uIGdldFRhZyhvKSB7
-CiAgICB2YXIgcyA9IHRvU3RyaW5nRnVuY3Rpb24uY2FsbChvKTsKICAgIHJldHVybiBzLnN1YnN0cmlu
-Zyg4LCBzLmxlbmd0aCAtIDEpOwogIH0KICBmdW5jdGlvbiBnZXRVbmtub3duVGFnKG9iamVjdCwgdGFn
-KSB7CiAgICBpZiAoL15IVE1MW0EtWl0uKkVsZW1lbnQkLy50ZXN0KHRhZykpIHsKICAgICAgdmFyIG5h
-bWUgPSB0b1N0cmluZ0Z1bmN0aW9uLmNhbGwob2JqZWN0KTsKICAgICAgaWYgKG5hbWUgPT0gIltvYmpl
-Y3QgT2JqZWN0XSIpIHJldHVybiBudWxsOwogICAgICByZXR1cm4gIkhUTUxFbGVtZW50IjsKICAgIH0K
-ICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2VyKG9iamVjdCwgdGFnKSB7CiAg
-ICBpZiAoc2VsZi5IVE1MRWxlbWVudCAmJiBvYmplY3QgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkgcmV0
-dXJuICJIVE1MRWxlbWVudCI7CiAgICByZXR1cm4gZ2V0VW5rbm93blRhZyhvYmplY3QsIHRhZyk7CiAg
-fQogIGZ1bmN0aW9uIHByb3RvdHlwZUZvclRhZyh0YWcpIHsKICAgIGlmICh0eXBlb2Ygd2luZG93ID09
-ICJ1bmRlZmluZWQiKSByZXR1cm4gbnVsbDsKICAgIGlmICh0eXBlb2Ygd2luZG93W3RhZ10gPT0gInVu
-ZGVmaW5lZCIpIHJldHVybiBudWxsOwogICAgdmFyIGNvbnN0cnVjdG9yID0gd2luZG93W3RhZ107CiAg
-ICBpZiAodHlwZW9mIGNvbnN0cnVjdG9yICE9ICJmdW5jdGlvbiIpIHJldHVybiBudWxsOwogICAgcmV0
-dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlwZTsKICB9CiAgZnVuY3Rpb24gZGlzY3JpbWluYXRvcih0YWcp
-IHsgcmV0dXJuIG51bGw7IH0KICB2YXIgaXNCcm93c2VyID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2Jq
-ZWN0IjsKICByZXR1cm4gewogICAgZ2V0VGFnOiBnZXRUYWcsCiAgICBnZXRVbmtub3duVGFnOiBpc0Jy
-b3dzZXIgPyBnZXRVbmtub3duVGFnR2VuZXJpY0Jyb3dzZXIgOiBnZXRVbmtub3duVGFnLAogICAgcHJv
-dG90eXBlRm9yVGFnOiBwcm90b3R5cGVGb3JUYWcsCiAgICBkaXNjcmltaW5hdG9yOiBkaXNjcmltaW5h
-dG9yIH07Cn0KQy53Yj1mdW5jdGlvbihnZXRUYWdGYWxsYmFjaykgewogIHJldHVybiBmdW5jdGlvbiho
-b29rcykgewogICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgIT0gIm9iamVjdCIpIHJldHVybiBob29rczsK
-ICAgIHZhciB1YSA9IG5hdmlnYXRvci51c2VyQWdlbnQ7CiAgICBpZiAodWEuaW5kZXhPZigiRHVtcFJl
-bmRlclRyZWUiKSA+PSAwKSByZXR1cm4gaG9va3M7CiAgICBpZiAodWEuaW5kZXhPZigiQ2hyb21lIikg
-Pj0gMCkgewogICAgICBmdW5jdGlvbiBjb25maXJtKHApIHsKICAgICAgICByZXR1cm4gdHlwZW9mIHdp
-bmRvdyA9PSAib2JqZWN0IiAmJiB3aW5kb3dbcF0gJiYgd2luZG93W3BdLm5hbWUgPT0gcDsKICAgICAg
-fQogICAgICBpZiAoY29uZmlybSgiV2luZG93IikgJiYgY29uZmlybSgiSFRNTEVsZW1lbnQiKSkgcmV0
-dXJuIGhvb2tzOwogICAgfQogICAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnRmFsbGJhY2s7CiAgfTsKfQpD
-LktVPWZ1bmN0aW9uKGhvb2tzKSB7CiAgaWYgKHR5cGVvZiBkYXJ0RXhwZXJpbWVudGFsRml4dXBHZXRU
-YWcgIT0gImZ1bmN0aW9uIikgcmV0dXJuIGhvb2tzOwogIGhvb2tzLmdldFRhZyA9IGRhcnRFeHBlcmlt
-ZW50YWxGaXh1cEdldFRhZyhob29rcy5nZXRUYWcpOwp9CkMuZlE9ZnVuY3Rpb24oaG9va3MpIHsKICB2
-YXIgZ2V0VGFnID0gaG9va3MuZ2V0VGFnOwogIHZhciBwcm90b3R5cGVGb3JUYWcgPSBob29rcy5wcm90
-b3R5cGVGb3JUYWc7CiAgZnVuY3Rpb24gZ2V0VGFnRml4ZWQobykgewogICAgdmFyIHRhZyA9IGdldFRh
-ZyhvKTsKICAgIGlmICh0YWcgPT0gIkRvY3VtZW50IikgewogICAgICBpZiAoISFvLnhtbFZlcnNpb24p
-IHJldHVybiAiIURvY3VtZW50IjsKICAgICAgcmV0dXJuICIhSFRNTERvY3VtZW50IjsKICAgIH0KICAg
-IHJldHVybiB0YWc7CiAgfQogIGZ1bmN0aW9uIHByb3RvdHlwZUZvclRhZ0ZpeGVkKHRhZykgewogICAg
-aWYgKHRhZyA9PSAiRG9jdW1lbnQiKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBwcm90b3R5cGVGb3JU
-YWcodGFnKTsKICB9CiAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnRml4ZWQ7CiAgaG9va3MucHJvdG90eXBl
-Rm9yVGFnID0gcHJvdG90eXBlRm9yVGFnRml4ZWQ7Cn0KQy5kaz1mdW5jdGlvbihob29rcykgewogIHZh
-ciB1c2VyQWdlbnQgPSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJB
-Z2VudCA6ICIiOwogIGlmICh1c2VyQWdlbnQuaW5kZXhPZigiRmlyZWZveCIpID09IC0xKSByZXR1cm4g
-aG9va3M7CiAgdmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcXVpY2tNYXAgPSB7CiAgICAi
-QmVmb3JlVW5sb2FkRXZlbnQiOiAiRXZlbnQiLAogICAgIkRhdGFUcmFuc2ZlciI6ICJDbGlwYm9hcmQi
-LAogICAgIkdlb0dlb2xvY2F0aW9uIjogIkdlb2xvY2F0aW9uIiwKICAgICJMb2NhdGlvbiI6ICIhTG9j
-YXRpb24iLAogICAgIldvcmtlck1lc3NhZ2VFdmVudCI6ICJNZXNzYWdlRXZlbnQiLAogICAgIlhNTERv
-Y3VtZW50IjogIiFEb2N1bWVudCJ9OwogIGZ1bmN0aW9uIGdldFRhZ0ZpcmVmb3gobykgewogICAgdmFy
-IHRhZyA9IGdldFRhZyhvKTsKICAgIHJldHVybiBxdWlja01hcFt0YWddIHx8IHRhZzsKICB9CiAgaG9v
-a3MuZ2V0VGFnID0gZ2V0VGFnRmlyZWZveDsKfQpDLnhpPWZ1bmN0aW9uKGhvb2tzKSB7CiAgdmFyIHVz
-ZXJBZ2VudCA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9iamVjdCIgPyBuYXZpZ2F0b3IudXNlckFnZW50
-IDogIiI7CiAgaWYgKHVzZXJBZ2VudC5pbmRleE9mKCJUcmlkZW50LyIpID09IC0xKSByZXR1cm4gaG9v
-a3M7CiAgdmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcXVpY2tNYXAgPSB7CiAgICAiQmVm
-b3JlVW5sb2FkRXZlbnQiOiAiRXZlbnQiLAogICAgIkRhdGFUcmFuc2ZlciI6ICJDbGlwYm9hcmQiLAog
-ICAgIkhUTUxEREVsZW1lbnQiOiAiSFRNTEVsZW1lbnQiLAogICAgIkhUTUxEVEVsZW1lbnQiOiAiSFRN
-TEVsZW1lbnQiLAogICAgIkhUTUxQaHJhc2VFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJQb3Np
-dGlvbiI6ICJHZW9wb3NpdGlvbiIKICB9OwogIGZ1bmN0aW9uIGdldFRhZ0lFKG8pIHsKICAgIHZhciB0
-YWcgPSBnZXRUYWcobyk7CiAgICB2YXIgbmV3VGFnID0gcXVpY2tNYXBbdGFnXTsKICAgIGlmIChuZXdU
-YWcpIHJldHVybiBuZXdUYWc7CiAgICBpZiAodGFnID09ICJPYmplY3QiKSB7CiAgICAgIGlmICh3aW5k
-b3cuRGF0YVZpZXcgJiYgKG8gaW5zdGFuY2VvZiB3aW5kb3cuRGF0YVZpZXcpKSByZXR1cm4gIkRhdGFW
-aWV3IjsKICAgIH0KICAgIHJldHVybiB0YWc7CiAgfQogIGZ1bmN0aW9uIHByb3RvdHlwZUZvclRhZ0lF
-KHRhZykgewogICAgdmFyIGNvbnN0cnVjdG9yID0gd2luZG93W3RhZ107CiAgICBpZiAoY29uc3RydWN0
-b3IgPT0gbnVsbCkgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gY29uc3RydWN0b3IucHJvdG90eXBlOwog
-IH0KICBob29rcy5nZXRUYWcgPSBnZXRUYWdJRTsKICBob29rcy5wcm90b3R5cGVGb3JUYWcgPSBwcm90
-b3R5cGVGb3JUYWdJRTsKfQpDLmk3PWZ1bmN0aW9uKGhvb2tzKSB7IHJldHVybiBob29rczsgfQoKQy5D
-dD1uZXcgUC5ieSgpCkMuRXE9bmV3IFAuazUoKQpDLnhNPW5ldyBQLnU1KCkKQy5Raz1uZXcgUC5FMygp
-CkMuTlU9bmV3IFAuSmkoKQpDLkEzPW5ldyBQLk14KG51bGwpCkMuR2I9SC5WTSh0KFsxMjcsMjA0Nyw2
-NTUzNSwxMTE0MTExXSksdS50KQpDLmFrPUguVk0odChbMCwwLDMyNzc2LDMzNzkyLDEsMTAyNDAsMCww
-XSksdS50KQpDLmNtPUguVk0odChbIio6OmNsYXNzIiwiKjo6ZGlyIiwiKjo6ZHJhZ2dhYmxlIiwiKjo6
-aGlkZGVuIiwiKjo6aWQiLCIqOjppbmVydCIsIio6Oml0ZW1wcm9wIiwiKjo6aXRlbXJlZiIsIio6Oml0
-ZW1zY29wZSIsIio6OmxhbmciLCIqOjpzcGVsbGNoZWNrIiwiKjo6dGl0bGUiLCIqOjp0cmFuc2xhdGUi
-LCJBOjphY2Nlc3NrZXkiLCJBOjpjb29yZHMiLCJBOjpocmVmbGFuZyIsIkE6Om5hbWUiLCJBOjpzaGFw
-ZSIsIkE6OnRhYmluZGV4IiwiQTo6dGFyZ2V0IiwiQTo6dHlwZSIsIkFSRUE6OmFjY2Vzc2tleSIsIkFS
-RUE6OmFsdCIsIkFSRUE6OmNvb3JkcyIsIkFSRUE6Om5vaHJlZiIsIkFSRUE6OnNoYXBlIiwiQVJFQTo6
-dGFiaW5kZXgiLCJBUkVBOjp0YXJnZXQiLCJBVURJTzo6Y29udHJvbHMiLCJBVURJTzo6bG9vcCIsIkFV
-RElPOjptZWRpYWdyb3VwIiwiQVVESU86Om11dGVkIiwiQVVESU86OnByZWxvYWQiLCJCRE86OmRpciIs
-IkJPRFk6OmFsaW5rIiwiQk9EWTo6Ymdjb2xvciIsIkJPRFk6OmxpbmsiLCJCT0RZOjp0ZXh0IiwiQk9E
-WTo6dmxpbmsiLCJCUjo6Y2xlYXIiLCJCVVRUT046OmFjY2Vzc2tleSIsIkJVVFRPTjo6ZGlzYWJsZWQi
-LCJCVVRUT046Om5hbWUiLCJCVVRUT046OnRhYmluZGV4IiwiQlVUVE9OOjp0eXBlIiwiQlVUVE9OOjp2
-YWx1ZSIsIkNBTlZBUzo6aGVpZ2h0IiwiQ0FOVkFTOjp3aWR0aCIsIkNBUFRJT046OmFsaWduIiwiQ09M
-OjphbGlnbiIsIkNPTDo6Y2hhciIsIkNPTDo6Y2hhcm9mZiIsIkNPTDo6c3BhbiIsIkNPTDo6dmFsaWdu
-IiwiQ09MOjp3aWR0aCIsIkNPTEdST1VQOjphbGlnbiIsIkNPTEdST1VQOjpjaGFyIiwiQ09MR1JPVVA6
-OmNoYXJvZmYiLCJDT0xHUk9VUDo6c3BhbiIsIkNPTEdST1VQOjp2YWxpZ24iLCJDT0xHUk9VUDo6d2lk
-dGgiLCJDT01NQU5EOjpjaGVja2VkIiwiQ09NTUFORDo6Y29tbWFuZCIsIkNPTU1BTkQ6OmRpc2FibGVk
-IiwiQ09NTUFORDo6bGFiZWwiLCJDT01NQU5EOjpyYWRpb2dyb3VwIiwiQ09NTUFORDo6dHlwZSIsIkRB
-VEE6OnZhbHVlIiwiREVMOjpkYXRldGltZSIsIkRFVEFJTFM6Om9wZW4iLCJESVI6OmNvbXBhY3QiLCJE
-SVY6OmFsaWduIiwiREw6OmNvbXBhY3QiLCJGSUVMRFNFVDo6ZGlzYWJsZWQiLCJGT05UOjpjb2xvciIs
-IkZPTlQ6OmZhY2UiLCJGT05UOjpzaXplIiwiRk9STTo6YWNjZXB0IiwiRk9STTo6YXV0b2NvbXBsZXRl
-IiwiRk9STTo6ZW5jdHlwZSIsIkZPUk06Om1ldGhvZCIsIkZPUk06Om5hbWUiLCJGT1JNOjpub3ZhbGlk
-YXRlIiwiRk9STTo6dGFyZ2V0IiwiRlJBTUU6Om5hbWUiLCJIMTo6YWxpZ24iLCJIMjo6YWxpZ24iLCJI
-Mzo6YWxpZ24iLCJINDo6YWxpZ24iLCJINTo6YWxpZ24iLCJINjo6YWxpZ24iLCJIUjo6YWxpZ24iLCJI
-Ujo6bm9zaGFkZSIsIkhSOjpzaXplIiwiSFI6OndpZHRoIiwiSFRNTDo6dmVyc2lvbiIsIklGUkFNRTo6
-YWxpZ24iLCJJRlJBTUU6OmZyYW1lYm9yZGVyIiwiSUZSQU1FOjpoZWlnaHQiLCJJRlJBTUU6Om1hcmdp
-bmhlaWdodCIsIklGUkFNRTo6bWFyZ2lud2lkdGgiLCJJRlJBTUU6OndpZHRoIiwiSU1HOjphbGlnbiIs
-IklNRzo6YWx0IiwiSU1HOjpib3JkZXIiLCJJTUc6OmhlaWdodCIsIklNRzo6aHNwYWNlIiwiSU1HOjpp
-c21hcCIsIklNRzo6bmFtZSIsIklNRzo6dXNlbWFwIiwiSU1HOjp2c3BhY2UiLCJJTUc6OndpZHRoIiwi
-SU5QVVQ6OmFjY2VwdCIsIklOUFVUOjphY2Nlc3NrZXkiLCJJTlBVVDo6YWxpZ24iLCJJTlBVVDo6YWx0
-IiwiSU5QVVQ6OmF1dG9jb21wbGV0ZSIsIklOUFVUOjphdXRvZm9jdXMiLCJJTlBVVDo6Y2hlY2tlZCIs
-IklOUFVUOjpkaXNhYmxlZCIsIklOUFVUOjppbnB1dG1vZGUiLCJJTlBVVDo6aXNtYXAiLCJJTlBVVDo6
-bGlzdCIsIklOUFVUOjptYXgiLCJJTlBVVDo6bWF4bGVuZ3RoIiwiSU5QVVQ6Om1pbiIsIklOUFVUOjpt
-dWx0aXBsZSIsIklOUFVUOjpuYW1lIiwiSU5QVVQ6OnBsYWNlaG9sZGVyIiwiSU5QVVQ6OnJlYWRvbmx5
-IiwiSU5QVVQ6OnJlcXVpcmVkIiwiSU5QVVQ6OnNpemUiLCJJTlBVVDo6c3RlcCIsIklOUFVUOjp0YWJp
-bmRleCIsIklOUFVUOjp0eXBlIiwiSU5QVVQ6OnVzZW1hcCIsIklOUFVUOjp2YWx1ZSIsIklOUzo6ZGF0
-ZXRpbWUiLCJLRVlHRU46OmRpc2FibGVkIiwiS0VZR0VOOjprZXl0eXBlIiwiS0VZR0VOOjpuYW1lIiwi
-TEFCRUw6OmFjY2Vzc2tleSIsIkxBQkVMOjpmb3IiLCJMRUdFTkQ6OmFjY2Vzc2tleSIsIkxFR0VORDo6
-YWxpZ24iLCJMSTo6dHlwZSIsIkxJOjp2YWx1ZSIsIkxJTks6OnNpemVzIiwiTUFQOjpuYW1lIiwiTUVO
-VTo6Y29tcGFjdCIsIk1FTlU6OmxhYmVsIiwiTUVOVTo6dHlwZSIsIk1FVEVSOjpoaWdoIiwiTUVURVI6
-OmxvdyIsIk1FVEVSOjptYXgiLCJNRVRFUjo6bWluIiwiTUVURVI6OnZhbHVlIiwiT0JKRUNUOjp0eXBl
-bXVzdG1hdGNoIiwiT0w6OmNvbXBhY3QiLCJPTDo6cmV2ZXJzZWQiLCJPTDo6c3RhcnQiLCJPTDo6dHlw
-ZSIsIk9QVEdST1VQOjpkaXNhYmxlZCIsIk9QVEdST1VQOjpsYWJlbCIsIk9QVElPTjo6ZGlzYWJsZWQi
-LCJPUFRJT046OmxhYmVsIiwiT1BUSU9OOjpzZWxlY3RlZCIsIk9QVElPTjo6dmFsdWUiLCJPVVRQVVQ6
-OmZvciIsIk9VVFBVVDo6bmFtZSIsIlA6OmFsaWduIiwiUFJFOjp3aWR0aCIsIlBST0dSRVNTOjptYXgi
-LCJQUk9HUkVTUzo6bWluIiwiUFJPR1JFU1M6OnZhbHVlIiwiU0VMRUNUOjphdXRvY29tcGxldGUiLCJT
-RUxFQ1Q6OmRpc2FibGVkIiwiU0VMRUNUOjptdWx0aXBsZSIsIlNFTEVDVDo6bmFtZSIsIlNFTEVDVDo6
-cmVxdWlyZWQiLCJTRUxFQ1Q6OnNpemUiLCJTRUxFQ1Q6OnRhYmluZGV4IiwiU09VUkNFOjp0eXBlIiwi
-VEFCTEU6OmFsaWduIiwiVEFCTEU6OmJnY29sb3IiLCJUQUJMRTo6Ym9yZGVyIiwiVEFCTEU6OmNlbGxw
-YWRkaW5nIiwiVEFCTEU6OmNlbGxzcGFjaW5nIiwiVEFCTEU6OmZyYW1lIiwiVEFCTEU6OnJ1bGVzIiwi
-VEFCTEU6OnN1bW1hcnkiLCJUQUJMRTo6d2lkdGgiLCJUQk9EWTo6YWxpZ24iLCJUQk9EWTo6Y2hhciIs
-IlRCT0RZOjpjaGFyb2ZmIiwiVEJPRFk6OnZhbGlnbiIsIlREOjphYmJyIiwiVEQ6OmFsaWduIiwiVEQ6
-OmF4aXMiLCJURDo6Ymdjb2xvciIsIlREOjpjaGFyIiwiVEQ6OmNoYXJvZmYiLCJURDo6Y29sc3BhbiIs
-IlREOjpoZWFkZXJzIiwiVEQ6OmhlaWdodCIsIlREOjpub3dyYXAiLCJURDo6cm93c3BhbiIsIlREOjpz
-Y29wZSIsIlREOjp2YWxpZ24iLCJURDo6d2lkdGgiLCJURVhUQVJFQTo6YWNjZXNza2V5IiwiVEVYVEFS
-RUE6OmF1dG9jb21wbGV0ZSIsIlRFWFRBUkVBOjpjb2xzIiwiVEVYVEFSRUE6OmRpc2FibGVkIiwiVEVY
-VEFSRUE6OmlucHV0bW9kZSIsIlRFWFRBUkVBOjpuYW1lIiwiVEVYVEFSRUE6OnBsYWNlaG9sZGVyIiwi
-VEVYVEFSRUE6OnJlYWRvbmx5IiwiVEVYVEFSRUE6OnJlcXVpcmVkIiwiVEVYVEFSRUE6OnJvd3MiLCJU
-RVhUQVJFQTo6dGFiaW5kZXgiLCJURVhUQVJFQTo6d3JhcCIsIlRGT09UOjphbGlnbiIsIlRGT09UOjpj
-aGFyIiwiVEZPT1Q6OmNoYXJvZmYiLCJURk9PVDo6dmFsaWduIiwiVEg6OmFiYnIiLCJUSDo6YWxpZ24i
-LCJUSDo6YXhpcyIsIlRIOjpiZ2NvbG9yIiwiVEg6OmNoYXIiLCJUSDo6Y2hhcm9mZiIsIlRIOjpjb2xz
-cGFuIiwiVEg6OmhlYWRlcnMiLCJUSDo6aGVpZ2h0IiwiVEg6Om5vd3JhcCIsIlRIOjpyb3dzcGFuIiwi
-VEg6OnNjb3BlIiwiVEg6OnZhbGlnbiIsIlRIOjp3aWR0aCIsIlRIRUFEOjphbGlnbiIsIlRIRUFEOjpj
-aGFyIiwiVEhFQUQ6OmNoYXJvZmYiLCJUSEVBRDo6dmFsaWduIiwiVFI6OmFsaWduIiwiVFI6OmJnY29s
-b3IiLCJUUjo6Y2hhciIsIlRSOjpjaGFyb2ZmIiwiVFI6OnZhbGlnbiIsIlRSQUNLOjpkZWZhdWx0Iiwi
-VFJBQ0s6OmtpbmQiLCJUUkFDSzo6bGFiZWwiLCJUUkFDSzo6c3JjbGFuZyIsIlVMOjpjb21wYWN0Iiwi
-VUw6OnR5cGUiLCJWSURFTzo6Y29udHJvbHMiLCJWSURFTzo6aGVpZ2h0IiwiVklERU86Omxvb3AiLCJW
-SURFTzo6bWVkaWFncm91cCIsIlZJREVPOjptdXRlZCIsIlZJREVPOjpwcmVsb2FkIiwiVklERU86Ondp
-ZHRoIl0pLHUucykKQy5WQz1ILlZNKHQoWzAsMCw2NTQ5MCw0NTA1NSw2NTUzNSwzNDgxNSw2NTUzNCwx
-ODQzMV0pLHUudCkKQy5tSz1ILlZNKHQoWzAsMCwyNjYyNCwxMDIzLDY1NTM0LDIwNDcsNjU1MzQsMjA0
-N10pLHUudCkKQy5TcT1ILlZNKHQoWyJIRUFEIiwiQVJFQSIsIkJBU0UiLCJCQVNFRk9OVCIsIkJSIiwi
-Q09MIiwiQ09MR1JPVVAiLCJFTUJFRCIsIkZSQU1FIiwiRlJBTUVTRVQiLCJIUiIsIklNQUdFIiwiSU1H
-IiwiSU5QVVQiLCJJU0lOREVYIiwiTElOSyIsIk1FVEEiLCJQQVJBTSIsIlNPVVJDRSIsIlNUWUxFIiwi
-VElUTEUiLCJXQlIiXSksdS5zKQpDLnhEPUguVk0odChbXSksdS5zKQpDLmRuPUguVk0odChbXSksdS5i
-KQpDLnRvPUguVk0odChbMCwwLDMyNzIyLDEyMjg3LDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50
-KQpDLkYzPUguVk0odChbMCwwLDI0NTc2LDEwMjMsNjU1MzQsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1LnQp
-CkMuZWE9SC5WTSh0KFswLDAsMzI3NTQsMTEyNjMsNjU1MzQsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1LnQp
-CkMuWko9SC5WTSh0KFswLDAsMzI3MjIsMTIyODcsNjU1MzUsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1LnQp
-CkMuV2Q9SC5WTSh0KFswLDAsNjU0OTAsMTIyODcsNjU1MzUsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1LnQp
-CkMuUXg9SC5WTSh0KFsiYmluZCIsImlmIiwicmVmIiwicmVwZWF0Iiwic3ludGF4Il0pLHUucykKQy5C
-ST1ILlZNKHQoWyJBOjpocmVmIiwiQVJFQTo6aHJlZiIsIkJMT0NLUVVPVEU6OmNpdGUiLCJCT0RZOjpi
-YWNrZ3JvdW5kIiwiQ09NTUFORDo6aWNvbiIsIkRFTDo6Y2l0ZSIsIkZPUk06OmFjdGlvbiIsIklNRzo6
-c3JjIiwiSU5QVVQ6OnNyYyIsIklOUzo6Y2l0ZSIsIlE6OmNpdGUiLCJWSURFTzo6cG9zdGVyIl0pLHUu
-cykKQy5XTz1uZXcgSC5MUCgwLHt9LEMueEQsSC5OMCgiTFA8cVUscVU+IikpCkMuaFU9SC5WTSh0KFtd
-KSxILk4wKCJqZDxHRD4iKSkKQy5DTT1uZXcgSC5MUCgwLHt9LEMuaFUsSC5OMCgiTFA8R0QsQD4iKSkK
-Qy5UZT1uZXcgSC53digiY2FsbCIpfSkoKTsoZnVuY3Rpb24gc3RhdGljRmllbGRzKCl7JC55aj0wCiQu
-bUo9bnVsbAokLlA0PW51bGwKJC5ORj1udWxsCiQuVFg9bnVsbAokLng3PW51bGwKJC5udz1udWxsCiQu
-dnY9bnVsbAokLkJ2PW51bGwKJC5TNj1udWxsCiQuazg9bnVsbAokLm1nPW51bGwKJC5VRD0hMQokLlgz
-PUMuTlUKJC54Zz1bXQokLnhvPW51bGwKJC5CTz1udWxsCiQubHQ9bnVsbAokLkVVPW51bGwKJC5vcj1Q
-LkZsKHUuTix1LlopCiQuSTY9bnVsbAokLkZmPW51bGx9KSgpOyhmdW5jdGlvbiBsYXp5SW5pdGlhbGl6
-ZXJzKCl7dmFyIHQ9aHVua0hlbHBlcnMubGF6eQp0KCQsImZhIiwidyIsZnVuY3Rpb24oKXtyZXR1cm4g
-SC5ZZygiXyRkYXJ0X2RhcnRDbG9zdXJlIil9KQp0KCQsIllmIiwiVU4iLGZ1bmN0aW9uKCl7cmV0dXJu
-IEguWWcoIl8kZGFydF9qcyIpfSkKdCgkLCJVMiIsIlNuIixmdW5jdGlvbigpe3JldHVybiBILmNNKEgu
-Uzcoewp0b1N0cmluZzpmdW5jdGlvbigpe3JldHVybiIkcmVjZWl2ZXIkIn19KSl9KQp0KCQsInhxIiwi
-bHEiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5TNyh7JG1ldGhvZCQ6bnVsbCwKdG9TdHJpbmc6ZnVu
-Y3Rpb24oKXtyZXR1cm4iJHJlY2VpdmVyJCJ9fSkpfSkKdCgkLCJSMSIsIk45IixmdW5jdGlvbigpe3Jl
-dHVybiBILmNNKEguUzcobnVsbCkpfSkKdCgkLCJmTiIsImlJIixmdW5jdGlvbigpe3JldHVybiBILmNN
-KGZ1bmN0aW9uKCl7dmFyICRhcmd1bWVudHNFeHByJD0nJGFyZ3VtZW50cyQnCnRyeXtudWxsLiRtZXRo
-b2QkKCRhcmd1bWVudHNFeHByJCl9Y2F0Y2gocyl7cmV0dXJuIHMubWVzc2FnZX19KCkpfSkKdCgkLCJx
-aSIsIktmIixmdW5jdGlvbigpe3JldHVybiBILmNNKEguUzcodm9pZCAwKSl9KQp0KCQsInJaIiwiWmgi
-LGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVuY3Rpb24oKXt2YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJn
-dW1lbnRzJCcKdHJ5eyh2b2lkIDApLiRtZXRob2QkKCRhcmd1bWVudHNFeHByJCl9Y2F0Y2gocyl7cmV0
-dXJuIHMubWVzc2FnZX19KCkpfSkKdCgkLCJrcSIsInJOIixmdW5jdGlvbigpe3JldHVybiBILmNNKEgu
-TWoobnVsbCkpfSkKdCgkLCJ0dCIsImMzIixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7
-dHJ5e251bGwuJG1ldGhvZCR9Y2F0Y2gocyl7cmV0dXJuIHMubWVzc2FnZX19KCkpfSkKdCgkLCJkdCIs
-IkhLIixmdW5jdGlvbigpe3JldHVybiBILmNNKEguTWoodm9pZCAwKSl9KQp0KCQsIkE3IiwicjEiLGZ1
-bmN0aW9uKCl7cmV0dXJuIEguY00oZnVuY3Rpb24oKXt0cnl7KHZvaWQgMCkuJG1ldGhvZCR9Y2F0Y2go
-cyl7cmV0dXJuIHMubWVzc2FnZX19KCkpfSkKdCgkLCJXYyIsInV0IixmdW5jdGlvbigpe3JldHVybiBQ
-Lk9qKCl9KQp0KCQsImtoIiwicmYiLGZ1bmN0aW9uKCl7cmV0dXJuIFAuV0koKX0pCnQoJCwiYnQiLCJW
-NyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5EUShILlhGKEguVk0oWy0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
+dHVybiBhCnJldHVybiBKLmtzKGEpfSwKVTY6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJzdHJpbmci
+KXJldHVybiBKLkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBhCmlmKGEuY29uc3RydWN0b3I9
+PUFycmF5KXJldHVybiBKLmpkLnByb3RvdHlwZQppZih0eXBlb2YgYSE9Im9iamVjdCIpe2lmKHR5cGVv
+ZiBhPT0iZnVuY3Rpb24iKXJldHVybiBKLmM1LnByb3RvdHlwZQpyZXR1cm4gYX1pZihhIGluc3RhbmNl
+b2YgUC5rKXJldHVybiBhCnJldHVybiBKLmtzKGEpfSwKaWE6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9
+PSJudW1iZXIiKXtpZihNYXRoLmZsb29yKGEpPT1hKXJldHVybiBKLnVyLnByb3RvdHlwZQpyZXR1cm4g
+Si5WQS5wcm90b3R5cGV9aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3RvdHlwZQpp
+ZihhPT1udWxsKXJldHVybiBKLllFLnByb3RvdHlwZQppZih0eXBlb2YgYT09ImJvb2xlYW4iKXJldHVy
+biBKLnlFLnByb3RvdHlwZQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5
+cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5j
+NS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuaylyZXR1cm4gYQpyZXR1cm4gSi5r
+cyhhKX0sCnJZOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90
+b3R5cGUKaWYoYT09bnVsbClyZXR1cm4gYQppZighKGEgaW5zdGFuY2VvZiBQLmspKXJldHVybiBKLmtk
+LnByb3RvdHlwZQpyZXR1cm4gYX0sCncxOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIGEKaWYo
+YS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQucHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2Jq
+ZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBh
+fWlmKGEgaW5zdGFuY2VvZiBQLmspcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApBTTpmdW5jdGlvbihh
+LGIpe3JldHVybiBKLncxKGEpLkUoYSxiKX0sCkNNOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBKLlJF
+KGEpLmR1KGEsYixjLGQpfSwKRkw6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5kZChhLGIpfSwK
+R3I6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSkuZ21XKGEpfSwKSG06ZnVuY3Rpb24oYSl7cmV0dXJu
+IEouVTYoYSkuZ0EoYSl9LApJVDpmdW5jdGlvbihhKXtyZXR1cm4gSi53MShhKS5na3ooYSl9LApKeTpm
+dW5jdGlvbihhLGIpe3JldHVybiBKLmlhKGEpLmU3KGEsYil9LApLVjpmdW5jdGlvbihhLGIpe3JldHVy
+biBKLnJZKGEpLkcoYSxiKX0sCkx0OmZ1bmN0aW9uKGEpe3JldHVybiBKLlJFKGEpLndnKGEpfSwKTTE6
+ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLncxKGEpLkUyKGEsYixjKX0sClF6OmZ1bmN0aW9uKGEsYil7
+cmV0dXJuIEouclkoYSkuVyhhLGIpfSwKUk06ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJldHVybiBi
+PT1udWxsCmlmKHR5cGVvZiBhIT0ib2JqZWN0IilyZXR1cm4gYiE9bnVsbCYmYT09PWIKcmV0dXJuIEou
+aWEoYSkuRE4oYSxiKX0sClQwOmZ1bmN0aW9uKGEpe3JldHVybiBKLnJZKGEpLmJTKGEpfSwKYTY6ZnVu
+Y3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5tKGEsYil9LApiVDpmdW5jdGlvbihhKXtyZXR1cm4gSi5S
+RShhKS5ENChhKX0sCmJiOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZ0eXBlb2Yg
+Yj09Im51bWJlciIpcmV0dXJuIGErYgpyZXR1cm4gSi5USihhKS5oKGEsYil9LApjSDpmdW5jdGlvbihh
+KXtyZXR1cm4gSi5yWShhKS5oYyhhKX0sCmRSOmZ1bmN0aW9uKGEpe3JldHVybiBKLlJFKGEpLmdEKGEp
+fSwKZFo6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouUkUoYSkuT24oYSxiLGMsZCl9LApkaDpmdW5j
+dGlvbihhKXtyZXR1cm4gSi5SRShhKS50bihhKX0sCmhmOmZ1bmN0aW9uKGEpe3JldHVybiBKLmlhKGEp
+LmdpTyhhKX0sCmlnOmZ1bmN0aW9uKGEpe3JldHVybiBKLlJFKGEpLmdRZyhhKX0sCmo6ZnVuY3Rpb24o
+YSl7cmV0dXJuIEouaWEoYSkudyhhKX0sCmw1OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouUkUoYSkuc2hm
+KGEsYil9LApsZDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouclkoYSkuTmooYSxiLGMpfSwKcTA6ZnVu
+Y3Rpb24oYSxiLGMpe3JldHVybiBKLnJZKGEpLlFpKGEsYixjKX0sCnFGOmZ1bmN0aW9uKGEpe3JldHVy
+biBKLlJFKGEpLmdWbChhKX0sCnRIOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5SRShhKS5wayhhLGIs
+Yyl9LAp3MjpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiPT09Im51bWJlciIpaWYoYS5jb25zdHJ1Y3Rv
+cj09QXJyYXl8fHR5cGVvZiBhPT0ic3RyaW5nInx8SC53VihhLGFbdi5kaXNwYXRjaFByb3BlcnR5TmFt
+ZV0pKWlmKGI+Pj4wPT09YiYmYjxhLmxlbmd0aClyZXR1cm4gYVtiXQpyZXR1cm4gSi5VNihhKS5xKGEs
+Yil9LAp5UTpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5yWShhKS5pNyhhLGIsYyxkKX0sCnpsOmZ1
+bmN0aW9uKGEsYil7cmV0dXJuIEouVTYoYSkudGcoYSxiKX0sCnZCOmZ1bmN0aW9uIHZCKCl7fSwKeUU6
+ZnVuY3Rpb24geUUoKXt9LApZRTpmdW5jdGlvbiBZRSgpe30sCk1GOmZ1bmN0aW9uIE1GKCl7fSwKaUM6
+ZnVuY3Rpb24gaUMoKXt9LAprZDpmdW5jdGlvbiBrZCgpe30sCmM1OmZ1bmN0aW9uIGM1KCl7fSwKamQ6
+ZnVuY3Rpb24gamQoYSl7dGhpcy4kdGk9YX0sClBvOmZ1bmN0aW9uIFBvKGEpe3RoaXMuJHRpPWF9LApt
+MTpmdW5jdGlvbiBtMShhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9MApfLmQ9bnVsbApf
+LiR0aT1jfSwKcUk6ZnVuY3Rpb24gcUkoKXt9LAp1cjpmdW5jdGlvbiB1cigpe30sClZBOmZ1bmN0aW9u
+IFZBKCl7fSwKRHI6ZnVuY3Rpb24gRHIoKXt9fSxQPXsKT2o6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9e30K
+aWYoc2VsZi5zY2hlZHVsZUltbWVkaWF0ZSE9bnVsbClyZXR1cm4gUC5FWCgpCmlmKHNlbGYuTXV0YXRp
+b25PYnNlcnZlciE9bnVsbCYmc2VsZi5kb2N1bWVudCE9bnVsbCl7dD1zZWxmLmRvY3VtZW50LmNyZWF0
+ZUVsZW1lbnQoImRpdiIpCnM9c2VsZi5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzcGFuIikKci5hPW51
+bGwKbmV3IHNlbGYuTXV0YXRpb25PYnNlcnZlcihILnRSKG5ldyBQLnRoKHIpLDEpKS5vYnNlcnZlKHQs
+e2NoaWxkTGlzdDp0cnVlfSkKcmV0dXJuIG5ldyBQLmhhKHIsdCxzKX1lbHNlIGlmKHNlbGYuc2V0SW1t
+ZWRpYXRlIT1udWxsKXJldHVybiBQLnl0KCkKcmV0dXJuIFAucVcoKX0sClpWOmZ1bmN0aW9uKGEpe3Nl
+bGYuc2NoZWR1bGVJbW1lZGlhdGUoSC50UihuZXcgUC5Wcyh1Lk0uYihhKSksMCkpfSwKb0E6ZnVuY3Rp
+b24oYSl7c2VsZi5zZXRJbW1lZGlhdGUoSC50UihuZXcgUC5GdCh1Lk0uYihhKSksMCkpfSwKQno6ZnVu
+Y3Rpb24oYSl7dS5NLmIoYSkKUC5RTigwLGEpfSwKUU46ZnVuY3Rpb24oYSxiKXt2YXIgdD1uZXcgUC5X
+MygpCnQuQ1koYSxiKQpyZXR1cm4gdH0sCkZYOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5paChuZXcg
+UC52cygkLlgzLGEuQygidnM8MD4iKSksYS5DKCJpaDwwPiIpKX0sCkRJOmZ1bmN0aW9uKGEsYil7YS4k
+MigwLG51bGwpCmIuYj0hMApyZXR1cm4gYi5hfSwKalE6ZnVuY3Rpb24oYSxiKXtQLkplKGEsYil9LAp5
+QzpmdW5jdGlvbihhLGIpe2IuYU0oMCxhKX0sCmYzOmZ1bmN0aW9uKGEsYil7Yi53MChILlJ1KGEpLEgu
+dHMoYSkpfSwKSmU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9bmV3IFAuV00oYikscT1uZXcgUC5TWChi
+KQppZihhIGluc3RhbmNlb2YgUC52cylhLlFkKHIscSx1LnopCmVsc2V7dD11LnoKaWYodS5jLmMoYSkp
+YS5TcShyLHEsdCkKZWxzZXtzPW5ldyBQLnZzKCQuWDMsdS5fKQpzLmE9NApzLmM9YQpzLlFkKHIsbnVs
+bCx0KX19fSwKbHo6ZnVuY3Rpb24oYSl7dmFyIHQ9ZnVuY3Rpb24oYixjKXtyZXR1cm4gZnVuY3Rpb24o
+ZCxlKXt3aGlsZSh0cnVlKXRyeXtiKGQsZSkKYnJlYWt9Y2F0Y2gocyl7ZT1zCmQ9Y319fShhLDEpCnJl
+dHVybiAkLlgzLkxqKG5ldyBQLkdzKHQpLHUuUCx1LmVnLHUueil9LAprMzpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMscgpiLmE9MQp0cnl7YS5TcShuZXcgUC5wVihiKSxuZXcgUC5VNyhiKSx1LlApfWNhdGNoKHIp
+e3Q9SC5SdShyKQpzPUgudHMocikKUC5yYihuZXcgUC52cihiLHQscykpfX0sCkE5OmZ1bmN0aW9uKGEs
+Yil7dmFyIHQscyxyCmZvcih0PXUuXztzPWEuYSxzPT09MjspYT10LmIoYS5jKQppZihzPj00KXtyPWIu
+YWgoKQpiLmE9YS5hCmIuYz1hLmMKUC5IWihiLHIpfWVsc2V7cj11LnguYihiLmMpCmIuYT0yCmIuYz1h
+CmEualEocil9fSwKSFo6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxn
+LGYsZT1udWxsLGQ9e30sYz1kLmE9YQpmb3IodD11Lm4scz11Lngscj11LmM7ITA7KXtxPXt9CnA9Yy5h
+PT09OAppZihiPT1udWxsKXtpZihwKXtvPXQuYihjLmMpClAuTDIoZSxlLGMuYixvLmEsby5iKX1yZXR1
+cm59Zm9yKDtuPWIuYSxuIT1udWxsO2I9bil7Yi5hPW51bGwKUC5IWihkLmEsYil9Yz1kLmEKbT1jLmMK
+cS5hPXAKcS5iPW0KbD0hcAppZihsKXtrPWIuYwprPShrJjEpIT09MHx8KGsmMTUpPT09OH1lbHNlIGs9
+ITAKaWYoayl7az1iLmIKaj1rLmIKaWYocCl7aT1jLmI9PT1qCmk9IShpfHxpKX1lbHNlIGk9ITEKaWYo
+aSl7dC5iKG0pClAuTDIoZSxlLGMuYixtLmEsbS5iKQpyZXR1cm59aD0kLlgzCmlmKGghPT1qKSQuWDM9
+agplbHNlIGg9ZQpjPWIuYwppZigoYyYxNSk9PT04KW5ldyBQLlJUKGQscSxiLHApLiQwKCkKZWxzZSBp
+ZihsKXtpZigoYyYxKSE9PTApbmV3IFAucnEocSxiLG0pLiQwKCl9ZWxzZSBpZigoYyYyKSE9PTApbmV3
+IFAuUlcoZCxxLGIpLiQwKCkKaWYoaCE9bnVsbCkkLlgzPWgKYz1xLmIKaWYoci5jKGMpKXtpZihjLmE+
+PTQpe2c9cy5iKGsuYykKay5jPW51bGwKYj1rLk44KGcpCmsuYT1jLmEKay5jPWMuYwpkLmE9Ywpjb250
+aW51ZX1lbHNlIFAuQTkoYyxrKQpyZXR1cm59fWY9Yi5iCmc9cy5iKGYuYykKZi5jPW51bGwKYj1mLk44
+KGcpCmM9cS5hCmw9cS5iCmlmKCFjKXtmLiR0aS5kLmIobCkKZi5hPTQKZi5jPWx9ZWxzZXt0LmIobCkK
+Zi5hPTgKZi5jPWx9ZC5hPWYKYz1mfX0sClZIOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYodS5XLmMoYSkp
+cmV0dXJuIGIuTGooYSx1LnosdS5LLHUubCkKdD11LnkKaWYodC5jKGEpKXJldHVybiB0LmIoYSkKdGhy
+b3cgSC5iKFAuTDMoYSwib25FcnJvciIsIkVycm9yIGhhbmRsZXIgbXVzdCBhY2NlcHQgb25lIE9iamVj
+dCBvciBvbmUgT2JqZWN0IGFuZCBhIFN0YWNrVHJhY2UgYXMgYXJndW1lbnRzLCBhbmQgcmV0dXJuIGEg
+YSB2YWxpZCByZXN1bHQiKSl9LApwdTpmdW5jdGlvbigpe3ZhciB0LHMKZm9yKDt0PSQuUzYsdCE9bnVs
+bDspeyQubWc9bnVsbApzPXQuYgokLlM2PXMKaWYocz09bnVsbCkkLms4PW51bGwKdC5hLiQwKCl9fSwK
+ZU46ZnVuY3Rpb24oKXskLlVEPSEwCnRyeXtQLnB1KCl9ZmluYWxseXskLm1nPW51bGwKJC5VRD0hMQpp
+ZigkLlM2IT1udWxsKSQudXQoKS4kMShQLlVJKCkpfX0sCmVXOmZ1bmN0aW9uKGEpe3ZhciB0PW5ldyBQ
+Lk9NKGEpCmlmKCQuUzY9PW51bGwpeyQuUzY9JC5rOD10CmlmKCEkLlVEKSQudXQoKS4kMShQLlVJKCkp
+fWVsc2UgJC5rOD0kLms4LmI9dH0sCnJSOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj0kLlM2CmlmKHI9PW51
+bGwpe1AuZVcoYSkKJC5tZz0kLms4CnJldHVybn10PW5ldyBQLk9NKGEpCnM9JC5tZwppZihzPT1udWxs
+KXt0LmI9cgokLlM2PSQubWc9dH1lbHNle3QuYj1zLmIKJC5tZz1zLmI9dAppZih0LmI9PW51bGwpJC5r
+OD10fX0sCnJiOmZ1bmN0aW9uKGEpe3ZhciB0PW51bGwscz0kLlgzCmlmKEMuTlU9PT1zKXtQLlRrKHQs
+dCxDLk5VLGEpCnJldHVybn1QLlRrKHQsdCxzLHUuTS5iKHMuR1koYSkpKX0sClF3OmZ1bmN0aW9uKGEs
+Yil7aWYoYT09bnVsbClILnZoKFAuRWUoInN0cmVhbSIpKQpyZXR1cm4gbmV3IFAueEkoYi5DKCJ4STww
+PiIpKX0sCkwyOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQ9e30KdC5hPWQKUC5yUihuZXcgUC5wSyh0
+LGUpKX0sClQ4OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVybiBk
+LiQwKCkKJC5YMz1jCnQ9cwp0cnl7cz1kLiQwKCkKcmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwKeXY6
+ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVybiBkLiQxKGUp
+CiQuWDM9Ywp0PXMKdHJ5e3M9ZC4kMShlKQpyZXR1cm4gc31maW5hbGx5eyQuWDM9dH19LApReDpmdW5j
+dGlvbihhLGIsYyxkLGUsZixnLGgsaSl7dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVybiBkLiQyKGUs
+ZikKJC5YMz1jCnQ9cwp0cnl7cz1kLiQyKGUsZikKcmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwKVGs6
+ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQKdS5NLmIoZCkKdD1DLk5VIT09YwppZih0KWQ9ISghdHx8ITEp
+P2MuR1koZCk6Yy5SVChkLHUuSCkKUC5lVyhkKX0sCnRoOmZ1bmN0aW9uIHRoKGEpe3RoaXMuYT1hfSwK
+aGE6ZnVuY3Rpb24gaGEoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKVnM6ZnVuY3Rp
+b24gVnMoYSl7dGhpcy5hPWF9LApGdDpmdW5jdGlvbiBGdChhKXt0aGlzLmE9YX0sClczOmZ1bmN0aW9u
+IFczKCl7fSwKeUg6ZnVuY3Rpb24geUgoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmloOmZ1bmN0aW9u
+IGloKGEsYil7dGhpcy5hPWEKdGhpcy5iPSExCnRoaXMuJHRpPWJ9LApXTTpmdW5jdGlvbiBXTShhKXt0
+aGlzLmE9YX0sClNYOmZ1bmN0aW9uIFNYKGEpe3RoaXMuYT1hfSwKR3M6ZnVuY3Rpb24gR3MoYSl7dGhp
+cy5hPWF9LApQZjpmdW5jdGlvbiBQZigpe30sClpmOmZ1bmN0aW9uIFpmKGEsYil7dGhpcy5hPWEKdGhp
+cy4kdGk9Yn0sCkZlOmZ1bmN0aW9uIEZlKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmE9bnVsbApfLmI9
+YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLiR0aT1lfSwKdnM6ZnVuY3Rpb24gdnMoYSxiKXt2YXIgXz10aGlz
+Cl8uYT0wCl8uYj1hCl8uYz1udWxsCl8uJHRpPWJ9LApkYTpmdW5jdGlvbiBkYShhLGIpe3RoaXMuYT1h
+CnRoaXMuYj1ifSwKb1E6ZnVuY3Rpb24gb1EoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnBWOmZ1bmN0
+aW9uIHBWKGEpe3RoaXMuYT1hfSwKVTc6ZnVuY3Rpb24gVTcoYSl7dGhpcy5hPWF9LAp2cjpmdW5jdGlv
+biB2cihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApySDpmdW5jdGlvbiBySChhLGIp
+e3RoaXMuYT1hCnRoaXMuYj1ifSwKS0Y6ZnVuY3Rpb24gS0YoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0s
+ClpMOmZ1bmN0aW9uIFpMKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClJUOmZ1bmN0
+aW9uIFJUKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LApqWjpmdW5j
+dGlvbiBqWihhKXt0aGlzLmE9YX0sCnJxOmZ1bmN0aW9uIHJxKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9
+Ygp0aGlzLmM9Y30sClJXOmZ1bmN0aW9uIFJXKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9
+Y30sCk9NOmZ1bmN0aW9uIE9NKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxsfSwKcWg6ZnVuY3Rpb24gcWgo
+KXt9LApCNTpmdW5jdGlvbiBCNShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKUEk6ZnVuY3Rpb24gUEko
+YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1POmZ1bmN0aW9uIE1PKCl7fSwKa1Q6ZnVuY3Rpb24ga1Qo
+KXt9LAp4STpmdW5jdGlvbiB4SShhKXt0aGlzLiR0aT1hfSwKQ3c6ZnVuY3Rpb24gQ3coYSxiKXt0aGlz
+LmE9YQp0aGlzLmI9Yn0sCm0wOmZ1bmN0aW9uIG0wKCl7fSwKcEs6ZnVuY3Rpb24gcEsoYSxiKXt0aGlz
+LmE9YQp0aGlzLmI9Yn0sCkppOmZ1bmN0aW9uIEppKCl7fSwKaGo6ZnVuY3Rpb24gaGooYSxiLGMpe3Ro
+aXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKVnA6ZnVuY3Rpb24gVnAoYSxiKXt0aGlzLmE9YQp0aGlz
+LmI9Yn0sCk9SOmZ1bmN0aW9uIE9SKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCkVG
+OmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gYi5DKCJAPDA+IikuS3EoYykuQygiRm88MSwyPiIpLmIoSC5C
+NyhhLG5ldyBILk41KGIuQygiQDwwPiIpLktxKGMpLkMoIk41PDEsMj4iKSkpKX0sCkZsOmZ1bmN0aW9u
+KGEsYil7cmV0dXJuIG5ldyBILk41KGEuQygiQDwwPiIpLktxKGIpLkMoIk41PDEsMj4iKSl9LApMczpm
+dW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuYjYoYS5DKCJiNjwwPiIpKX0sClQyOmZ1bmN0aW9uKCl7dmFy
+IHQ9T2JqZWN0LmNyZWF0ZShudWxsKQp0WyI8bm9uLWlkZW50aWZpZXIta2V5PiJdPXQKZGVsZXRlIHRb
+Ijxub24taWRlbnRpZmllci1rZXk+Il0KcmV0dXJuIHR9LApyajpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9
+bmV3IFAubG0oYSxiLGMuQygibG08MD4iKSkKdC5jPWEuZQpyZXR1cm4gdH0sCkVQOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdCxzCmlmKFAuaEIoYSkpe2lmKGI9PT0iKCImJmM9PT0iKSIpcmV0dXJuIiguLi4pIgpy
+ZXR1cm4gYisiLi4uIitjfXQ9SC5WTShbXSx1LnMpCkMuTm0uaSgkLnhnLGEpCnRyeXtQLlZyKGEsdCl9
+ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5PSCgkLnhnLC0xKQokLnhnLnBvcCgpfXM9
+UC52ZyhiLHUuUi5iKHQpLCIsICIpK2MKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LApXRTpm
+dW5jdGlvbihhLGIsYyl7dmFyIHQscwppZihQLmhCKGEpKXJldHVybiBiKyIuLi4iK2MKdD1uZXcgUC5S
+bihiKQpDLk5tLmkoJC54ZyxhKQp0cnl7cz10CnMuYT1QLnZnKHMuYSxhLCIsICIpfWZpbmFsbHl7aWYo
+MD49JC54Zy5sZW5ndGgpcmV0dXJuIEguT0goJC54ZywtMSkKJC54Zy5wb3AoKX10LmErPWMKcz10LmEK
+cmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LApoQjpmdW5jdGlvbihhKXt2YXIgdCxzCmZvcih0
+PSQueGcubGVuZ3RoLHM9MDtzPHQ7KytzKWlmKGE9PT0kLnhnW3NdKXJldHVybiEwCnJldHVybiExfSwK
+VnI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtPWEuZ2t6KGEpLGw9MCxrPTAKd2hpbGUo
+ITApe2lmKCEobDw4MHx8azwzKSlicmVhawppZighbS5GKCkpcmV0dXJuCnQ9SC5kKG0uZ2woKSkKQy5O
+bS5pKGIsdCkKbCs9dC5sZW5ndGgrMjsrK2t9aWYoIW0uRigpKXtpZihrPD01KXJldHVybgppZigwPj1i
+Lmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpzPWIucG9wKCkKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEgu
+T0goYiwtMSkKcj1iLnBvcCgpfWVsc2V7cT1tLmdsKCk7KytrCmlmKCFtLkYoKSl7aWYoazw9NCl7Qy5O
+bS5pKGIsSC5kKHEpKQpyZXR1cm59cz1ILmQocSkKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwt
+MSkKcj1iLnBvcCgpCmwrPXMubGVuZ3RoKzJ9ZWxzZXtwPW0uZ2woKTsrK2sKZm9yKDttLkYoKTtxPXAs
+cD1vKXtvPW0uZ2woKTsrK2sKaWYoaz4xMDApe3doaWxlKCEwKXtpZighKGw+NzUmJms+MykpYnJlYWsK
+aWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKbC09Yi5wb3AoKS5sZW5ndGgrMjstLWt9Qy5O
+bS5pKGIsIi4uLiIpCnJldHVybn19cj1ILmQocSkKcz1ILmQocCkKbCs9cy5sZW5ndGgrci5sZW5ndGgr
+NH19aWYoaz5iLmxlbmd0aCsyKXtsKz01Cm49Ii4uLiJ9ZWxzZSBuPW51bGwKd2hpbGUoITApe2lmKCEo
+bD44MCYmYi5sZW5ndGg+MykpYnJlYWsKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKbC09
+Yi5wb3AoKS5sZW5ndGgrMgppZihuPT1udWxsKXtsKz01Cm49Ii4uLiJ9fWlmKG4hPW51bGwpQy5ObS5p
+KGIsbikKQy5ObS5pKGIscikKQy5ObS5pKGIscyl9LAp0TTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1Q
+LkxzKGIpCmZvcih0PWEubGVuZ3RoLHM9MDtzPGEubGVuZ3RoO2EubGVuZ3RoPT09dHx8KDAsSC5sayko
+YSksKytzKXIuaSgwLGIuYihhW3NdKSkKcmV0dXJuIHJ9LApuTzpmdW5jdGlvbihhKXt2YXIgdCxzPXt9
+CmlmKFAuaEIoYSkpcmV0dXJuInsuLi59Igp0PW5ldyBQLlJuKCIiKQp0cnl7Qy5ObS5pKCQueGcsYSkK
+dC5hKz0ieyIKcy5hPSEwCmEuSygwLG5ldyBQLkdBKHMsdCkpCnQuYSs9In0ifWZpbmFsbHl7aWYoMD49
+JC54Zy5sZW5ndGgpcmV0dXJuIEguT0goJC54ZywtMSkKJC54Zy5wb3AoKX1zPXQuYQpyZXR1cm4gcy5j
+aGFyQ29kZUF0KDApPT0wP3M6c30sCmI2OmZ1bmN0aW9uIGI2KGEpe3ZhciBfPXRoaXMKXy5hPTAKXy5m
+PV8uZT1fLmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LApibjpmdW5jdGlvbiBibihhKXt0aGlz
+LmE9YQp0aGlzLmM9dGhpcy5iPW51bGx9LApsbTpmdW5jdGlvbiBsbShhLGIsYyl7dmFyIF89dGhpcwpf
+LmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGwKXy4kdGk9Y30sCm1XOmZ1bmN0aW9uIG1XKCl7fSwKTFU6ZnVu
+Y3Rpb24gTFUoKXt9LApsRDpmdW5jdGlvbiBsRCgpe30sCmlsOmZ1bmN0aW9uIGlsKCl7fSwKR0E6ZnVu
+Y3Rpb24gR0EoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCllrOmZ1bmN0aW9uIFlrKCl7fSwKS1A6ZnVu
+Y3Rpb24gS1AoKXt9LApQbjpmdW5jdGlvbiBQbigpe30sCkdqOmZ1bmN0aW9uIEdqKGEsYil7dGhpcy5h
+PWEKdGhpcy4kdGk9Yn0sCmxmOmZ1bmN0aW9uIGxmKCl7fSwKVmo6ZnVuY3Rpb24gVmooKXt9LApYdjpm
+dW5jdGlvbiBYdigpe30sCm5ZOmZ1bmN0aW9uIG5ZKCl7fSwKV1k6ZnVuY3Rpb24gV1koKXt9LApSVTpm
+dW5jdGlvbiBSVSgpe30sCkJTOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKaWYodHlwZW9mIGEhPSJz
+dHJpbmciKXRocm93IEguYihILnRMKGEpKQp0PW51bGwKdHJ5e3Q9SlNPTi5wYXJzZShhKX1jYXRjaChy
+KXtzPUguUnUocikKcT1QLnJyKFN0cmluZyhzKSxudWxsLG51bGwpCnRocm93IEguYihxKX1xPVAuUWUo
+dCkKcmV0dXJuIHF9LApRZTpmdW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJldHVybgppZih0eXBl
+b2YgYSE9Im9iamVjdCIpcmV0dXJuIGEKaWYoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpIT09QXJyYXku
+cHJvdG90eXBlKXJldHVybiBuZXcgUC51dyhhLE9iamVjdC5jcmVhdGUobnVsbCkpCmZvcih0PTA7dDxh
+Lmxlbmd0aDsrK3QpYVt0XT1QLlFlKGFbdF0pCnJldHVybiBhfSwKa3k6ZnVuY3Rpb24oYSxiLGMsZCl7
+aWYoYiBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpcmV0dXJuIFAuUlAoITEsYixjLGQpCnJldHVybn0sClJQ
+OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscj0kLnJmKCkKaWYocj09bnVsbClyZXR1cm4KdD0wPT09
+YwppZih0JiYhMClyZXR1cm4gUC5PUShyLGIpCnM9Yi5sZW5ndGgKZD1QLmpCKGMsZCxzKQppZih0JiZk
+PT09cylyZXR1cm4gUC5PUShyLGIpCnJldHVybiBQLk9RKHIsYi5zdWJhcnJheShjLGQpKX0sCk9ROmZ1
+bmN0aW9uKGEsYil7aWYoUC5CZShiKSlyZXR1cm4KcmV0dXJuIFAuSmgoYSxiKX0sCkpoOmZ1bmN0aW9u
+KGEsYil7dmFyIHQscwp0cnl7dD1hLmRlY29kZShiKQpyZXR1cm4gdH1jYXRjaChzKXtILlJ1KHMpfXJl
+dHVybn0sCkJlOmZ1bmN0aW9uKGEpe3ZhciB0LHM9YS5sZW5ndGgtMgpmb3IodD0wO3Q8czsrK3QpaWYo
+YVt0XT09PTIzNylpZigoYVt0KzFdJjIyNCk9PT0xNjApcmV0dXJuITAKcmV0dXJuITF9LApXSTpmdW5j
+dGlvbigpe3ZhciB0LHMKdHJ5e3Q9bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIse2ZhdGFsOnRydWV9KQpy
+ZXR1cm4gdH1jYXRjaChzKXtILlJ1KHMpfXJldHVybn0sCndHOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
+LHIKZm9yKHQ9Si5VNihhKSxzPWI7czxjOysrcyl7cj10LnEoYSxzKQppZih0eXBlb2YgciE9PSJudW1i
+ZXIiKXJldHVybiByLnpNKCkKaWYoKHImMTI3KSE9PXIpcmV0dXJuIHMtYn1yZXR1cm4gYy1ifSwKeE06
+ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe2lmKEMuam4uelkoZiw0KSE9PTApdGhyb3cgSC5iKFAucnIoIklu
+dmFsaWQgYmFzZTY0IHBhZGRpbmcsIHBhZGRlZCBsZW5ndGggbXVzdCBiZSBtdWx0aXBsZSBvZiBmb3Vy
+LCBpcyAiK2YsYSxjKSkKaWYoZCtlIT09Zil0aHJvdyBILmIoUC5ycigiSW52YWxpZCBiYXNlNjQgcGFk
+ZGluZywgJz0nIG5vdCBhdCB0aGUgZW5kIixhLGIpKQppZihlPjIpdGhyb3cgSC5iKFAucnIoIkludmFs
+aWQgYmFzZTY0IHBhZGRpbmcsIG1vcmUgdGhhbiB0d28gJz0nIGNoYXJhY3RlcnMiLGEsYikpfSwKdXc6
+ZnVuY3Rpb24gdXcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9bnVsbH0sCmk4OmZ1bmN0aW9u
+IGk4KGEpe3RoaXMuYT1hfSwKQ1Y6ZnVuY3Rpb24gQ1YoKXt9LApVODpmdW5jdGlvbiBVOCgpe30sClVr
+OmZ1bmN0aW9uIFVrKCl7fSwKd0k6ZnVuY3Rpb24gd0koKXt9LApaaTpmdW5jdGlvbiBaaSgpe30sCmJ5
+OmZ1bmN0aW9uIGJ5KCl7fSwKTXg6ZnVuY3Rpb24gTXgoYSl7dGhpcy5hPWF9LAp1NTpmdW5jdGlvbiB1
+NSgpe30sCkUzOmZ1bmN0aW9uIEUzKCl7fSwKUnc6ZnVuY3Rpb24gUncoYSl7dGhpcy5iPTAKdGhpcy5j
+PWF9LApHWTpmdW5jdGlvbiBHWShhKXt0aGlzLmE9YX0sCmJ6OmZ1bmN0aW9uIGJ6KGEsYil7dmFyIF89
+dGhpcwpfLmE9YQpfLmI9YgpfLmM9ITAKXy5mPV8uZT1fLmQ9MH0sClFBOmZ1bmN0aW9uKGEsYixjKXt2
+YXIgdD1ILkhwKGEsYykKaWYodCE9bnVsbClyZXR1cm4gdAppZihiIT1udWxsKXJldHVybiBiLiQxKGEp
+CnRocm93IEguYihQLnJyKGEsbnVsbCxudWxsKSl9LApGOmZ1bmN0aW9uKGEpe2lmKGEgaW5zdGFuY2Vv
+ZiBILlRwKXJldHVybiBhLncoMCkKcmV0dXJuIkluc3RhbmNlIG9mICciK0guZChILk0oYSkpKyInIn0s
+Ck84OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPUouUWkoYSxjKQppZihhIT09MCYmITApZm9yKHQ9MDt0
+PHMubGVuZ3RoOysrdClDLk5tLlkocyx0LGIpCnJldHVybiBzfSwKQ0g6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciB0LHM9SC5WTShbXSxjLkMoImpkPDA+IikpCmZvcih0PUouSVQoYSk7dC5GKCk7KUMuTm0uaShzLGMu
+Yih0LmdsKCkpKQppZihiKXJldHVybiBzCnJldHVybiBjLkMoInpNPDA+IikuYihKLkVwKHMpKX0sCkFG
+OmZ1bmN0aW9uKGEsYil7cmV0dXJuIGIuQygiek08MD4iKS5iKEouekMoUC5DSChhLCExLGIpKSl9LApI
+TTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYoQXJyYXkuaXNBcnJheShhKSl7dS50LmIoYSkKdD1hLmxl
+bmd0aApjPVAuakIoYixjLHQpCnJldHVybiBILmVUKGI+MHx8Yzx0P0MuTm0uRDYoYSxiLGMpOmEpfWlm
+KHUuYm0uYyhhKSlyZXR1cm4gSC5mdyhhLGIsUC5qQihiLGMsYS5sZW5ndGgpKQpyZXR1cm4gUC5idyhh
+LGIsYyl9LApPbzpmdW5jdGlvbihhKXtyZXR1cm4gSC5MdyhhKX0sCmJ3OmZ1bmN0aW9uKGEsYixjKXt2
+YXIgdCxzLHIscSxwPW51bGwKaWYoYjwwKXRocm93IEguYihQLlRFKGIsMCxKLkhtKGEpLHAscCkpCnQ9
+Yz09bnVsbAppZighdCYmYzxiKXRocm93IEguYihQLlRFKGMsYixKLkhtKGEpLHAscCkpCnM9Si5JVChh
+KQpmb3Iocj0wO3I8YjsrK3IpaWYoIXMuRigpKXRocm93IEguYihQLlRFKGIsMCxyLHAscCkpCnE9W10K
+aWYodClmb3IoO3MuRigpOylxLnB1c2gocy5nbCgpKQplbHNlIGZvcihyPWI7cjxjOysrcil7aWYoIXMu
+RigpKXRocm93IEguYihQLlRFKGMsYixyLHAscCkpCnEucHVzaChzLmdsKCkpfXJldHVybiBILmVUKHEp
+fSwKbnU6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlZSKGEsSC52NChhLCExLCEwLCExLCExLCExKSl9
+LAp2ZzpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9Si5JVChiKQppZighdC5GKCkpcmV0dXJuIGEKaWYoYy5s
+ZW5ndGg9PT0wKXtkbyBhKz1ILmQodC5nbCgpKQp3aGlsZSh0LkYoKSl9ZWxzZXthKz1ILmQodC5nbCgp
+KQpmb3IoO3QuRigpOylhPWErYytILmQodC5nbCgpKX1yZXR1cm4gYX0sCmxyOmZ1bmN0aW9uKGEsYixj
+LGQpe3JldHVybiBuZXcgUC5tcChhLGIsYyxkKX0sCnVvOmZ1bmN0aW9uKCl7dmFyIHQ9SC5NMCgpCmlm
+KHQhPW51bGwpcmV0dXJuIFAuaEsodCkKdGhyb3cgSC5iKFAuTDQoIidVcmkuYmFzZScgaXMgbm90IHN1
+cHBvcnRlZCIpKX0sCmVQOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbyxuPSIwMTIzNDU2
+Nzg5QUJDREVGIgppZihjPT09Qy54TSl7dD0kLno0KCkuYgppZih0eXBlb2YgYiE9InN0cmluZyIpSC52
+aChILnRMKGIpKQp0PXQudGVzdChiKX1lbHNlIHQ9ITEKaWYodClyZXR1cm4gYgpILkxoKGMpLkMoIlVr
+LlMiKS5iKGIpCnM9Yy5nWkUoKS5XSihiKQpmb3IodD1zLmxlbmd0aCxyPTAscT0iIjtyPHQ7KytyKXtw
+PXNbcl0KaWYocDwxMjgpe289cD4+PjQKaWYobz49OClyZXR1cm4gSC5PSChhLG8pCm89KGFbb10mMTw8
+KHAmMTUpKSE9PTB9ZWxzZSBvPSExCmlmKG8pcSs9SC5MdyhwKQplbHNlIHE9ZCYmcD09PTMyP3ErIisi
+OnErIiUiK25bcD4+PjQmMTVdK25bcCYxNV19cmV0dXJuIHEuY2hhckNvZGVBdCgwKT09MD9xOnF9LApH
+cTpmdW5jdGlvbihhKXt2YXIgdD1NYXRoLmFicyhhKSxzPWE8MD8iLSI6IiIKaWYodD49MTAwMClyZXR1
+cm4iIithCmlmKHQ+PTEwMClyZXR1cm4gcysiMCIrdAppZih0Pj0xMClyZXR1cm4gcysiMDAiK3QKcmV0
+dXJuIHMrIjAwMCIrdH0sClZ4OmZ1bmN0aW9uKGEpe2lmKGE+PTEwMClyZXR1cm4iIithCmlmKGE+PTEw
+KXJldHVybiIwIithCnJldHVybiIwMCIrYX0sCmgwOmZ1bmN0aW9uKGEpe2lmKGE+PTEwKXJldHVybiIi
+K2EKcmV0dXJuIjAiK2F9LApwOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyInx8SC5sKGEp
+fHxudWxsPT1hKXJldHVybiBKLmooYSkKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBKU09OLnN0
+cmluZ2lmeShhKQpyZXR1cm4gUC5GKGEpfSwKaFY6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkM2KGEp
+fSwKeFk6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLnUoITEsbnVsbCxudWxsLGEpfSwKTDM6ZnVuY3Rp
+b24oYSxiLGMpe3JldHVybiBuZXcgUC51KCEwLGEsYixjKX0sCkVlOmZ1bmN0aW9uKGEpe3JldHVybiBu
+ZXcgUC51KCExLG51bGwsYSwiTXVzdCBub3QgYmUgbnVsbCIpfSwKeDpmdW5jdGlvbihhLGIpe3JldHVy
+biBuZXcgUC5iSihudWxsLG51bGwsITAsYSxiLCJWYWx1ZSBub3QgaW4gcmFuZ2UiKX0sClRFOmZ1bmN0
+aW9uKGEsYixjLGQsZSl7cmV0dXJuIG5ldyBQLmJKKGIsYywhMCxhLGQsIkludmFsaWQgdmFsdWUiKX0s
+CndBOmZ1bmN0aW9uKGEsYixjLGQpe2lmKGE8Ynx8YT5jKXRocm93IEguYihQLlRFKGEsYixjLGQsbnVs
+bCkpfSwKakI6ZnVuY3Rpb24oYSxiLGMpe2lmKDA+YXx8YT5jKXRocm93IEguYihQLlRFKGEsMCxjLCJz
+dGFydCIsbnVsbCkpCmlmKGIhPW51bGwpe2lmKGE+Ynx8Yj5jKXRocm93IEguYihQLlRFKGIsYSxjLCJl
+bmQiLG51bGwpKQpyZXR1cm4gYn1yZXR1cm4gY30sCmsxOmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGEh
+PT0ibnVtYmVyIilyZXR1cm4gYS5KKCkKaWYoYTwwKXRocm93IEguYihQLlRFKGEsMCxudWxsLGIsbnVs
+bCkpfSwKQ2Y6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1ILlNjKGU9PW51bGw/Si5IbShiKTplKQpy
+ZXR1cm4gbmV3IFAuZVkodCwhMCxhLGMsIkluZGV4IG91dCBvZiByYW5nZSIpfSwKTDQ6ZnVuY3Rpb24o
+YSl7cmV0dXJuIG5ldyBQLnViKGEpfSwKU1k6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmRzKGEpfSwK
+UFY6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmxqKGEpfSwKYTQ6ZnVuY3Rpb24oYSl7cmV0dXJuIG5l
+dyBQLlVWKGEpfSwKcnI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBuZXcgUC5hRShhLGIsYyl9LApkSDpm
+dW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzPUguVk0oW10sZC5DKCJqZDwwPiIpKQpDLk5tLnNBKHMsYSkK
+Zm9yKHQ9MDt0PGE7Kyt0KUMuTm0uWShzLHQsYi4kMSh0KSkKcmV0dXJuIHN9LApoSzpmdW5jdGlvbihh
+KXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZT1udWxsLGQ9YS5sZW5ndGgKaWYoZD49
+NSl7dD0oKEouUXooYSw0KV41OCkqM3xDLnhCLlcoYSwwKV4xMDB8Qy54Qi5XKGEsMSleOTd8Qy54Qi5X
+KGEsMileMTE2fEMueEIuVyhhLDMpXjk3KT4+PjAKaWYodD09PTApcmV0dXJuIFAuS0QoZDxkP0MueEIu
+TmooYSwwLGQpOmEsNSxlKS5nbFIoKQplbHNlIGlmKHQ9PT0zMilyZXR1cm4gUC5LRChDLnhCLk5qKGEs
+NSxkKSwwLGUpLmdsUigpfXM9bmV3IEFycmF5KDgpCnMuZml4ZWQkbGVuZ3RoPUFycmF5CnI9SC5WTShz
+LHUudCkKQy5ObS5ZKHIsMCwwKQpDLk5tLlkociwxLC0xKQpDLk5tLlkociwyLC0xKQpDLk5tLlkociw3
+LC0xKQpDLk5tLlkociwzLDApCkMuTm0uWShyLDQsMCkKQy5ObS5ZKHIsNSxkKQpDLk5tLlkociw2LGQp
+CmlmKFAuVUIoYSwwLGQsMCxyKT49MTQpQy5ObS5ZKHIsNyxkKQpxPXJbMV0KaWYodHlwZW9mIHEhPT0i
+bnVtYmVyIilyZXR1cm4gcS50QigpCmlmKHE+PTApaWYoUC5VQihhLDAscSwyMCxyKT09PTIwKXJbN109
+cQpzPXJbMl0KaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5oKCkKcD1zKzEKbz1yWzNdCm49
+cls0XQptPXJbNV0KbD1yWzZdCmlmKHR5cGVvZiBsIT09Im51bWJlciIpcmV0dXJuIGwuSigpCmlmKHR5
+cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIEgucFkobSkKaWYobDxtKW09bAppZih0eXBlb2YgbiE9PSJu
+dW1iZXIiKXJldHVybiBuLkooKQppZihuPHApbj1tCmVsc2UgaWYobjw9cSluPXErMQppZih0eXBlb2Yg
+byE9PSJudW1iZXIiKXJldHVybiBvLkooKQppZihvPHApbz1uCnM9cls3XQppZih0eXBlb2YgcyE9PSJu
+dW1iZXIiKXJldHVybiBzLkooKQprPXM8MAppZihrKWlmKHA+cSszKXtqPWUKaz0hMX1lbHNle3M9bz4w
+CmlmKHMmJm8rMT09PW4pe2o9ZQprPSExfWVsc2V7aWYoIShtPGQmJm09PT1uKzImJkoucTAoYSwiLi4i
+LG4pKSlpPW0+bisyJiZKLnEwKGEsIi8uLiIsbS0zKQplbHNlIGk9ITAKaWYoaSl7aj1lCms9ITF9ZWxz
+ZXtpZihxPT09NClpZihKLnEwKGEsImZpbGUiLDApKXtpZihwPD0wKXtpZighQy54Qi5RaShhLCIvIixu
+KSl7aD0iZmlsZTovLy8iCnQ9M31lbHNle2g9ImZpbGU6Ly8iCnQ9Mn1hPWgrQy54Qi5OaihhLG4sZCkK
+cS09MApzPXQtMAptKz1zCmwrPXMKZD1hLmxlbmd0aApwPTcKbz03Cm49N31lbHNlIGlmKG49PT1tKXtn
+PW0rMTsrK2wKYT1DLnhCLmk3KGEsbixtLCIvIik7KytkCm09Z31qPSJmaWxlIn1lbHNlIGlmKEMueEIu
+UWkoYSwiaHR0cCIsMCkpe2lmKHMmJm8rMz09PW4mJkMueEIuUWkoYSwiODAiLG8rMSkpe2Y9bi0zCm0t
+PTMKbC09MwphPUMueEIuaTcoYSxvLG4sIiIpCmQtPTMKbj1mfWo9Imh0dHAifWVsc2Ugaj1lCmVsc2Ug
+aWYocT09PTUmJkoucTAoYSwiaHR0cHMiLDApKXtpZihzJiZvKzQ9PT1uJiZKLnEwKGEsIjQ0MyIsbysx
+KSl7Zj1uLTQKbS09NApsLT00CmE9Si55UShhLG8sbiwiIikKZC09MwpuPWZ9aj0iaHR0cHMifWVsc2Ug
+aj1lCms9ITB9fX1lbHNlIGo9ZQppZihrKXtzPWEubGVuZ3RoCmlmKGQ8cyl7YT1KLmxkKGEsMCxkKQpx
+LT0wCnAtPTAKby09MApuLT0wCm0tPTAKbC09MH1yZXR1cm4gbmV3IFAuVWYoYSxxLHAsbyxuLG0sbCxq
+KX1yZXR1cm4gUC5qdihhLDAsZCxxLHAsbyxuLG0sbCxqKX0sCk10OmZ1bmN0aW9uKGEpe0gueShhKQpy
+ZXR1cm4gUC5rdShhLDAsYS5sZW5ndGgsQy54TSwhMSl9LApXWDpmdW5jdGlvbihhKXt2YXIgdD11Lk4K
+cmV0dXJuIEMuTm0uTjAoSC5WTShhLnNwbGl0KCImIiksdS5zKSxQLkZsKHQsdCksbmV3IFAubjEoQy54
+TSksdS5mKX0sCkhoOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtPW51bGwsbD0iSVB2
+NCBhZGRyZXNzIHNob3VsZCBjb250YWluIGV4YWN0bHkgNCBwYXJ0cyIsaz0iZWFjaCBwYXJ0IG11c3Qg
+YmUgaW4gdGhlIHJhbmdlIDAuLjI1NSIsaj1uZXcgUC5jUyhhKSxpPW5ldyBVaW50OEFycmF5KDQpCmZv
+cih0PWkubGVuZ3RoLHM9YixyPXMscT0wO3M8YzsrK3Mpe3A9Qy54Qi5tKGEscykKaWYocCE9PTQ2KXtp
+ZigocF40OCk+OSlqLiQyKCJpbnZhbGlkIGNoYXJhY3RlciIscyl9ZWxzZXtpZihxPT09MylqLiQyKGws
+cykKbz1QLlFBKEMueEIuTmooYSxyLHMpLG0sbSkKaWYodHlwZW9mIG8hPT0ibnVtYmVyIilyZXR1cm4g
+by5vcygpCmlmKG8+MjU1KWouJDIoayxyKQpuPXErMQppZihxPj10KXJldHVybiBILk9IKGkscSkKaVtx
+XT1vCnI9cysxCnE9bn19aWYocSE9PTMpai4kMihsLGMpCm89UC5RQShDLnhCLk5qKGEscixjKSxtLG0p
+CmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJuIG8ub3MoKQppZihvPjI1NSlqLiQyKGsscikKaWYo
+cT49dClyZXR1cm4gSC5PSChpLHEpCmlbcV09bwpyZXR1cm4gaX0sCmVnOmZ1bmN0aW9uKGEsYixhMCl7
+dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZD1uZXcgUC5WQyhhKSxjPW5ldyBQLnRw
+KGQsYSkKaWYoYS5sZW5ndGg8MilkLiQxKCJhZGRyZXNzIGlzIHRvbyBzaG9ydCIpCnQ9SC5WTShbXSx1
+LnQpCmZvcihzPWIscj1zLHE9ITEscD0hMTtzPGEwOysrcyl7bz1DLnhCLm0oYSxzKQppZihvPT09NTgp
+e2lmKHM9PT1iKXsrK3MKaWYoQy54Qi5tKGEscykhPT01OClkLiQyKCJpbnZhbGlkIHN0YXJ0IGNvbG9u
+LiIscykKcj1zfWlmKHM9PT1yKXtpZihxKWQuJDIoIm9ubHkgb25lIHdpbGRjYXJkIGA6OmAgaXMgYWxs
+b3dlZCIscykKQy5ObS5pKHQsLTEpCnE9ITB9ZWxzZSBDLk5tLmkodCxjLiQyKHIscykpCnI9cysxfWVs
+c2UgaWYobz09PTQ2KXA9ITB9aWYodC5sZW5ndGg9PT0wKWQuJDEoInRvbyBmZXcgcGFydHMiKQpuPXI9
+PT1hMAptPUMuTm0uZ3JaKHQpCmlmKG4mJm0hPT0tMSlkLiQyKCJleHBlY3RlZCBhIHBhcnQgYWZ0ZXIg
+bGFzdCBgOmAiLGEwKQppZighbilpZighcClDLk5tLmkodCxjLiQyKHIsYTApKQplbHNle2w9UC5IaChh
+LHIsYTApCkMuTm0uaSh0LChsWzBdPDw4fGxbMV0pPj4+MCkKQy5ObS5pKHQsKGxbMl08PDh8bFszXSk+
+Pj4wKX1pZihxKXtpZih0Lmxlbmd0aD43KWQuJDEoImFuIGFkZHJlc3Mgd2l0aCBhIHdpbGRjYXJkIG11
+c3QgaGF2ZSBsZXNzIHRoYW4gNyBwYXJ0cyIpfWVsc2UgaWYodC5sZW5ndGghPT04KWQuJDEoImFuIGFk
+ZHJlc3Mgd2l0aG91dCBhIHdpbGRjYXJkIG11c3QgY29udGFpbiBleGFjdGx5IDggcGFydHMiKQprPW5l
+dyBVaW50OEFycmF5KDE2KQpmb3IobT10Lmxlbmd0aCxqPWsubGVuZ3RoLGk9OS1tLHM9MCxoPTA7czxt
+Oysrcyl7Zz10W3NdCmlmKGc9PT0tMSlmb3IoZj0wO2Y8aTsrK2Ype2lmKGg8MHx8aD49ailyZXR1cm4g
+SC5PSChrLGgpCmtbaF09MAplPWgrMQppZihlPj1qKXJldHVybiBILk9IKGssZSkKa1tlXT0wCmgrPTJ9
+ZWxzZXtlPUMuam4ud0coZyw4KQppZihoPDB8fGg+PWopcmV0dXJuIEguT0goayxoKQprW2hdPWUKZT1o
+KzEKaWYoZT49ailyZXR1cm4gSC5PSChrLGUpCmtbZV09ZyYyNTUKaCs9Mn19cmV0dXJuIGt9LApqdjpm
+dW5jdGlvbihhLGIsYyxkLGUsZixnLGgsaSxqKXt2YXIgdCxzLHIscSxwLG8sbixtPW51bGwKaWYoaj09
+bnVsbClpZihkPmIpaj1QLlBpKGEsYixkKQplbHNle2lmKGQ9PT1iKVAuUjMoYSxiLCJJbnZhbGlkIGVt
+cHR5IHNjaGVtZSIpCmo9IiJ9aWYoZT5iKXt0PWQrMwpzPXQ8ZT9QLnpSKGEsdCxlLTEpOiIiCnI9UC5P
+ZShhLGUsZiwhMSkKaWYodHlwZW9mIGYhPT0ibnVtYmVyIilyZXR1cm4gZi5oKCkKcT1mKzEKaWYodHlw
+ZW9mIGchPT0ibnVtYmVyIilyZXR1cm4gSC5wWShnKQpwPXE8Zz9QLndCKFAuUUEoSi5sZChhLHEsZyks
+bmV3IFAuZTEoYSxmKSxtKSxqKTptfWVsc2V7cD1tCnI9cApzPSIifW89UC5rYShhLGcsaCxtLGosciE9
+bnVsbCkKaWYodHlwZW9mIGghPT0ibnVtYmVyIilyZXR1cm4gaC5KKCkKbj1oPGk/UC5sZShhLGgrMSxp
+LG0pOm0KcmV0dXJuIG5ldyBQLkRuKGoscyxyLHAsbyxuLGk8Yz9QLnRHKGEsaSsxLGMpOm0pfSwKd0s6
+ZnVuY3Rpb24oYSl7aWYoYT09PSJodHRwIilyZXR1cm4gODAKaWYoYT09PSJodHRwcyIpcmV0dXJuIDQ0
+MwpyZXR1cm4gMH0sClIzOmZ1bmN0aW9uKGEsYixjKXt0aHJvdyBILmIoUC5ycihjLGEsYikpfSwKa0U6
+ZnVuY3Rpb24oYSxiKXtDLk5tLksoYSxuZXcgUC5OWSghMSkpfSwKSE46ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciB0LHMscgpmb3IodD1ILnFDKGEsYyxudWxsLEgudDYoYSkuZCksdD1uZXcgSC5hNyh0LHQuZ0EodCks
+dC4kdGkuQygiYTc8YUwuRT4iKSk7dC5GKCk7KXtzPXQuZApyPVAubnUoJ1siKi86PD4/XFxcXHxdJykK
+cy50b1N0cmluZwppZihILm0yKHMsciwwKSl7dD1QLkw0KCJJbGxlZ2FsIGNoYXJhY3RlciBpbiBwYXRo
+OiAiK3MpCnRocm93IEguYih0KX19fSwKcmc6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZighKDY1PD1hJiZh
+PD05MCkpdD05Nzw9YSYmYTw9MTIyCmVsc2UgdD0hMAppZih0KXJldHVybgp0PVAuTDQoIklsbGVnYWwg
+ZHJpdmUgbGV0dGVyICIrUC5PbyhhKSkKdGhyb3cgSC5iKHQpfSwKd0I6ZnVuY3Rpb24oYSxiKXtpZihh
+IT1udWxsJiZhPT09UC53SyhiKSlyZXR1cm4KcmV0dXJuIGF9LApPZTpmdW5jdGlvbihhLGIsYyxkKXt2
+YXIgdCxzLHIscSxwLG8KaWYoYT09bnVsbClyZXR1cm4KaWYoYj09PWMpcmV0dXJuIiIKaWYoQy54Qi5t
+KGEsYik9PT05MSl7aWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gYy5ITigpCnQ9Yy0xCmlmKEMu
+eEIubShhLHQpIT09OTMpUC5SMyhhLGIsIk1pc3NpbmcgZW5kIGBdYCB0byBtYXRjaCBgW2AgaW4gaG9z
+dCIpCnM9YisxCnI9UC50byhhLHMsdCkKaWYodHlwZW9mIHIhPT0ibnVtYmVyIilyZXR1cm4gci5KKCkK
+aWYocjx0KXtxPXIrMQpwPVAuT0EoYSxDLnhCLlFpKGEsIjI1IixxKT9yKzM6cSx0LCIlMjUiKX1lbHNl
+IHA9IiIKUC5lZyhhLHMscikKcmV0dXJuIEMueEIuTmooYSxiLHIpLnRvTG93ZXJDYXNlKCkrcCsiXSJ9
+aWYodHlwZW9mIGMhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShjKQpvPWIKZm9yKDtvPGM7KytvKWlmKEMu
+eEIubShhLG8pPT09NTgpe3I9Qy54Qi5YVShhLCIlIixiKQppZighKHI+PWImJnI8Yykpcj1jCmlmKHI8
+Yyl7cT1yKzEKcD1QLk9BKGEsQy54Qi5RaShhLCIyNSIscSk/ciszOnEsYywiJTI1Iil9ZWxzZSBwPSIi
+ClAuZWcoYSxiLHIpCnJldHVybiJbIitDLnhCLk5qKGEsYixyKStwKyJdIn1yZXR1cm4gUC5PTChhLGIs
+Yyl9LAp0bzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1DLnhCLlhVKGEsIiUiLGIpCmlmKHM+PWIpe2lm
+KHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIEgucFkoYykKdD1zPGN9ZWxzZSB0PSExCnJldHVybiB0
+P3M6Y30sCk9BOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrPWQhPT0iIj9u
+ZXcgUC5SbihkKTpudWxsCmlmKHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIEgucFkoYykKdD1iCnM9
+dApyPSEwCmZvcig7dDxjOyl7cT1DLnhCLm0oYSx0KQppZihxPT09Mzcpe3A9UC5ydihhLHQsITApCm89
+cD09bnVsbAppZihvJiZyKXt0Kz0zCmNvbnRpbnVlfWlmKGs9PW51bGwpaz1uZXcgUC5SbigiIikKbj1r
+LmErPUMueEIuTmooYSxzLHQpCmlmKG8pcD1DLnhCLk5qKGEsdCx0KzMpCmVsc2UgaWYocD09PSIlIilQ
+LlIzKGEsdCwiWm9uZUlEIHNob3VsZCBub3QgY29udGFpbiAlIGFueW1vcmUiKQprLmE9bitwCnQrPTMK
+cz10CnI9ITB9ZWxzZXtpZihxPDEyNyl7bz1xPj4+NAppZihvPj04KXJldHVybiBILk9IKEMuRjMsbykK
+bz0oQy5GM1tvXSYxPDwocSYxNSkpIT09MH1lbHNlIG89ITEKaWYobyl7aWYociYmNjU8PXEmJjkwPj1x
+KXtpZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCmlmKHM8dCl7ay5hKz1DLnhCLk5qKGEscyx0KQpzPXR9
+cj0hMX0rK3R9ZWxzZXtpZigocSY2NDUxMik9PT01NTI5NiYmdCsxPGMpe209Qy54Qi5tKGEsdCsxKQpp
+ZigobSY2NDUxMik9PT01NjMyMCl7cT02NTUzNnwocSYxMDIzKTw8MTB8bSYxMDIzCmw9Mn1lbHNlIGw9
+MX1lbHNlIGw9MQppZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCmsuYSs9Qy54Qi5OaihhLHMsdCkKay5h
+Kz1QLkhIKHEpCnQrPWwKcz10fX19aWYoaz09bnVsbClyZXR1cm4gQy54Qi5OaihhLGIsYykKaWYoczxj
+KWsuYSs9Qy54Qi5OaihhLHMsYykKbz1rLmEKcmV0dXJuIG8uY2hhckNvZGVBdCgwKT09MD9vOm99LApP
+TDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssagppZih0eXBlb2YgYyE9PSJu
+dW1iZXIiKXJldHVybiBILnBZKGMpCnQ9YgpzPXQKcj1udWxsCnE9ITAKZm9yKDt0PGM7KXtwPUMueEIu
+bShhLHQpCmlmKHA9PT0zNyl7bz1QLnJ2KGEsdCwhMCkKbj1vPT1udWxsCmlmKG4mJnEpe3QrPTMKY29u
+dGludWV9aWYocj09bnVsbClyPW5ldyBQLlJuKCIiKQptPUMueEIuTmooYSxzLHQpCmw9ci5hKz0hcT9t
+LnRvTG93ZXJDYXNlKCk6bQppZihuKXtvPUMueEIuTmooYSx0LHQrMykKaz0zfWVsc2UgaWYobz09PSIl
+Iil7bz0iJTI1IgprPTF9ZWxzZSBrPTMKci5hPWwrbwp0Kz1rCnM9dApxPSEwfWVsc2V7aWYocDwxMjcp
+e249cD4+PjQKaWYobj49OClyZXR1cm4gSC5PSChDLmVhLG4pCm49KEMuZWFbbl0mMTw8KHAmMTUpKSE9
+PTB9ZWxzZSBuPSExCmlmKG4pe2lmKHEmJjY1PD1wJiY5MD49cCl7aWYocj09bnVsbClyPW5ldyBQLlJu
+KCIiKQppZihzPHQpe3IuYSs9Qy54Qi5OaihhLHMsdCkKcz10fXE9ITF9Kyt0fWVsc2V7aWYocDw9OTMp
+e249cD4+PjQKaWYobj49OClyZXR1cm4gSC5PSChDLmFrLG4pCm49KEMuYWtbbl0mMTw8KHAmMTUpKSE9
+PTB9ZWxzZSBuPSExCmlmKG4pUC5SMyhhLHQsIkludmFsaWQgY2hhcmFjdGVyIikKZWxzZXtpZigocCY2
+NDUxMik9PT01NTI5NiYmdCsxPGMpe2o9Qy54Qi5tKGEsdCsxKQppZigoaiY2NDUxMik9PT01NjMyMCl7
+cD02NTUzNnwocCYxMDIzKTw8MTB8aiYxMDIzCms9Mn1lbHNlIGs9MX1lbHNlIGs9MQppZihyPT1udWxs
+KXI9bmV3IFAuUm4oIiIpCm09Qy54Qi5OaihhLHMsdCkKci5hKz0hcT9tLnRvTG93ZXJDYXNlKCk6bQpy
+LmErPVAuSEgocCkKdCs9awpzPXR9fX19aWYocj09bnVsbClyZXR1cm4gQy54Qi5OaihhLGIsYykKaWYo
+czxjKXttPUMueEIuTmooYSxzLGMpCnIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm19bj1yLmEKcmV0dXJu
+IG4uY2hhckNvZGVBdCgwKT09MD9uOm59LApQaTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEKaWYo
+Yj09PWMpcmV0dXJuIiIKaWYoIVAuRXQoSi5yWShhKS5XKGEsYikpKVAuUjMoYSxiLCJTY2hlbWUgbm90
+IHN0YXJ0aW5nIHdpdGggYWxwaGFiZXRpYyBjaGFyYWN0ZXIiKQpmb3IodD1iLHM9ITE7dDxjOysrdCl7
+cj1DLnhCLlcoYSx0KQppZihyPDEyOCl7cT1yPj4+NAppZihxPj04KXJldHVybiBILk9IKEMubUsscSkK
+cT0oQy5tS1txXSYxPDwociYxNSkpIT09MH1lbHNlIHE9ITEKaWYoIXEpUC5SMyhhLHQsIklsbGVnYWwg
+c2NoZW1lIGNoYXJhY3RlciIpCmlmKDY1PD1yJiZyPD05MClzPSEwfWE9Qy54Qi5OaihhLGIsYykKcmV0
+dXJuIFAuWWEocz9hLnRvTG93ZXJDYXNlKCk6YSl9LApZYTpmdW5jdGlvbihhKXtpZihhPT09Imh0dHAi
+KXJldHVybiJodHRwIgppZihhPT09ImZpbGUiKXJldHVybiJmaWxlIgppZihhPT09Imh0dHBzIilyZXR1
+cm4iaHR0cHMiCmlmKGE9PT0icGFja2FnZSIpcmV0dXJuInBhY2thZ2UiCnJldHVybiBhfSwKelI6ZnVu
+Y3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpcmV0dXJuIiIKcmV0dXJuIFAudU8oYSxiLGMsQy50bywhMSl9
+LAprYTpmdW5jdGlvbihhLGIsYyxkLGUsZil7dmFyIHQscz1lPT09ImZpbGUiLHI9c3x8ZixxPWE9PW51
+bGwKaWYocSYmITApcmV0dXJuIHM/Ii8iOiIiCnQ9IXE/UC51TyhhLGIsYyxDLldkLCEwKTpDLmpOLkUy
+KGQsbmV3IFAuUlooKSx1Lk4pLkgoMCwiLyIpCmlmKHQubGVuZ3RoPT09MCl7aWYocylyZXR1cm4iLyJ9
+ZWxzZSBpZihyJiYhQy54Qi5uKHQsIi8iKSl0PSIvIit0CnJldHVybiBQLkpyKHQsZSxmKX0sCkpyOmZ1
+bmN0aW9uKGEsYixjKXt2YXIgdD1iLmxlbmd0aD09PTAKaWYodCYmIWMmJiFDLnhCLm4oYSwiLyIpKXJl
+dHVybiBQLndGKGEsIXR8fGMpCnJldHVybiBQLnhlKGEpfSwKbGU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHQscz17fQppZihhIT1udWxsKXtpZihkIT1udWxsKXRocm93IEguYihQLnhZKCJCb3RoIHF1ZXJ5IGFu
+ZCBxdWVyeVBhcmFtZXRlcnMgc3BlY2lmaWVkIikpCnJldHVybiBQLnVPKGEsYixjLEMuVkMsITApfWlm
+KGQ9PW51bGwpcmV0dXJuCnQ9bmV3IFAuUm4oIiIpCnMuYT0iIgpkLksoMCxuZXcgUC55NShuZXcgUC5N
+RShzLHQpKSkKcz10LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LAp0RzpmdW5jdGlvbihh
+LGIsYyl7aWYoYT09bnVsbClyZXR1cm4KcmV0dXJuIFAudU8oYSxiLGMsQy5WQywhMCl9LApydjpmdW5j
+dGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvPWIrMgppZihvPj1hLmxlbmd0aClyZXR1cm4iJSIKdD1D
+LnhCLm0oYSxiKzEpCnM9Qy54Qi5tKGEsbykKcj1ILm9vKHQpCnE9SC5vbyhzKQppZihyPDB8fHE8MCly
+ZXR1cm4iJSIKcD1yKjE2K3EKaWYocDwxMjcpe289Qy5qbi53RyhwLDQpCmlmKG8+PTgpcmV0dXJuIEgu
+T0goQy5GMyxvKQpvPShDLkYzW29dJjE8PChwJjE1KSkhPT0wfWVsc2Ugbz0hMQppZihvKXJldHVybiBI
+Lkx3KGMmJjY1PD1wJiY5MD49cD8ocHwzMik+Pj4wOnApCmlmKHQ+PTk3fHxzPj05NylyZXR1cm4gQy54
+Qi5OaihhLGIsYiszKS50b1VwcGVyQ2FzZSgpCnJldHVybn0sCkhIOmZ1bmN0aW9uKGEpe3ZhciB0LHMs
+cixxLHAsbyxuPSIwMTIzNDU2Nzg5QUJDREVGIgppZihhPDEyOCl7dD1uZXcgQXJyYXkoMykKdC5maXhl
+ZCRsZW5ndGg9QXJyYXkKcz1ILlZNKHQsdS50KQpDLk5tLlkocywwLDM3KQpDLk5tLlkocywxLEMueEIu
+VyhuLGE+Pj40KSkKQy5ObS5ZKHMsMixDLnhCLlcobixhJjE1KSl9ZWxzZXtpZihhPjIwNDcpaWYoYT42
+NTUzNSl7cj0yNDAKcT00fWVsc2V7cj0yMjQKcT0zfWVsc2V7cj0xOTIKcT0yfXQ9bmV3IEFycmF5KDMq
+cSkKdC5maXhlZCRsZW5ndGg9QXJyYXkKcz1ILlZNKHQsdS50KQpmb3IocD0wOy0tcSxxPj0wO3I9MTI4
+KXtvPUMuam4uYmYoYSw2KnEpJjYzfHIKQy5ObS5ZKHMscCwzNykKQy5ObS5ZKHMscCsxLEMueEIuVyhu
+LG8+Pj40KSkKQy5ObS5ZKHMscCsyLEMueEIuVyhuLG8mMTUpKQpwKz0zfX1yZXR1cm4gUC5ITShzLDAs
+bnVsbCl9LAp1TzpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0PVAuVWwoYSxiLGMsZCxlKQpyZXR1cm4g
+dD09bnVsbD9DLnhCLk5qKGEsYixjKTp0fSwKVWw6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIs
+cSxwLG89IWUsbj1iLG09bixsPW51bGwKd2hpbGUoITApe2lmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0
+dXJuIG4uSigpCmlmKHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIEgucFkoYykKaWYoIShuPGMpKWJy
+ZWFrCmMkMDp7dD1DLnhCLm0oYSxuKQppZih0PDEyNyl7cz10Pj4+NAppZihzPj04KXJldHVybiBILk9I
+KGQscykKcz0oZFtzXSYxPDwodCYxNSkpIT09MH1lbHNlIHM9ITEKaWYocykrK24KZWxzZXtpZih0PT09
+Mzcpe3I9UC5ydihhLG4sITEpCmlmKHI9PW51bGwpe24rPTMKYnJlYWsgYyQwfWlmKCIlIj09PXIpe3I9
+IiUyNSIKcT0xfWVsc2UgcT0zfWVsc2V7aWYobylpZih0PD05Myl7cz10Pj4+NAppZihzPj04KXJldHVy
+biBILk9IKEMuYWsscykKcz0oQy5ha1tzXSYxPDwodCYxNSkpIT09MH1lbHNlIHM9ITEKZWxzZSBzPSEx
+CmlmKHMpe1AuUjMoYSxuLCJJbnZhbGlkIGNoYXJhY3RlciIpCnI9bnVsbApxPW51bGx9ZWxzZXtpZigo
+dCY2NDUxMik9PT01NTI5Nil7cz1uKzEKaWYoczxjKXtwPUMueEIubShhLHMpCmlmKChwJjY0NTEyKT09
+PTU2MzIwKXt0PTY1NTM2fCh0JjEwMjMpPDwxMHxwJjEwMjMKcT0yfWVsc2UgcT0xfWVsc2UgcT0xfWVs
+c2UgcT0xCnI9UC5ISCh0KX19aWYobD09bnVsbClsPW5ldyBQLlJuKCIiKQpsLmErPUMueEIuTmooYSxt
+LG4pCmwuYSs9SC5kKHIpCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIEgucFkocSkKbis9cQpt
+PW59fX1pZihsPT1udWxsKXJldHVybgppZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLkooKQpp
+ZihtPGMpbC5hKz1DLnhCLk5qKGEsbSxjKQpvPWwuYQpyZXR1cm4gby5jaGFyQ29kZUF0KDApPT0wP286
+b30sCnlCOmZ1bmN0aW9uKGEpe2lmKEMueEIubihhLCIuIikpcmV0dXJuITAKcmV0dXJuIEMueEIuT1ko
+YSwiLy4iKSE9PS0xfSwKeGU6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4KaWYoIVAueUIoYSkp
+cmV0dXJuIGEKdD1ILlZNKFtdLHUucykKZm9yKHM9YS5zcGxpdCgiLyIpLHI9cy5sZW5ndGgscT0hMSxw
+PTA7cDxyOysrcCl7bz1zW3BdCmlmKEouUk0obywiLi4iKSl7bj10Lmxlbmd0aAppZihuIT09MCl7aWYo
+MD49bilyZXR1cm4gSC5PSCh0LC0xKQp0LnBvcCgpCmlmKHQubGVuZ3RoPT09MClDLk5tLmkodCwiIil9
+cT0hMH1lbHNlIGlmKCIuIj09PW8pcT0hMAplbHNle0MuTm0uaSh0LG8pCnE9ITF9fWlmKHEpQy5ObS5p
+KHQsIiIpCnJldHVybiBDLk5tLkgodCwiLyIpfSwKd0Y6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxw
+LG8KaWYoIVAueUIoYSkpcmV0dXJuIWI/UC5DMShhKTphCnQ9SC5WTShbXSx1LnMpCmZvcihzPWEuc3Bs
+aXQoIi8iKSxyPXMubGVuZ3RoLHE9ITEscD0wO3A8cjsrK3Ape289c1twXQppZigiLi4iPT09bylpZih0
+Lmxlbmd0aCE9PTAmJkMuTm0uZ3JaKHQpIT09Ii4uIil7aWYoMD49dC5sZW5ndGgpcmV0dXJuIEguT0go
+dCwtMSkKdC5wb3AoKQpxPSEwfWVsc2V7Qy5ObS5pKHQsIi4uIikKcT0hMX1lbHNlIGlmKCIuIj09PW8p
+cT0hMAplbHNle0MuTm0uaSh0LG8pCnE9ITF9fXM9dC5sZW5ndGgKaWYocyE9PTApaWYocz09PTEpe2lm
+KDA+PXMpcmV0dXJuIEguT0godCwwKQpzPXRbMF0ubGVuZ3RoPT09MH1lbHNlIHM9ITEKZWxzZSBzPSEw
+CmlmKHMpcmV0dXJuIi4vIgppZihxfHxDLk5tLmdyWih0KT09PSIuLiIpQy5ObS5pKHQsIiIpCmlmKCFi
+KXtpZigwPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LDApCkMuTm0uWSh0LDAsUC5DMSh0WzBdKSl9cmV0
+dXJuIEMuTm0uSCh0LCIvIil9LApDMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLmxlbmd0aAppZihx
+Pj0yJiZQLkV0KEouUXooYSwwKSkpZm9yKHQ9MTt0PHE7Kyt0KXtzPUMueEIuVyhhLHQpCmlmKHM9PT01
+OClyZXR1cm4gQy54Qi5OaihhLDAsdCkrIiUzQSIrQy54Qi5HKGEsdCsxKQppZihzPD0xMjcpe3I9cz4+
+PjQKaWYocj49OClyZXR1cm4gSC5PSChDLm1LLHIpCnI9KEMubUtbcl0mMTw8KHMmMTUpKT09PTB9ZWxz
+ZSByPSEwCmlmKHIpYnJlYWt9cmV0dXJuIGF9LAptbjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLmdG
+aigpLHA9cS5sZW5ndGgKaWYocD4wJiZKLkhtKHFbMF0pPT09MiYmSi5hNihxWzBdLDEpPT09NTgpe2lm
+KDA+PXApcmV0dXJuIEguT0gocSwwKQpQLnJnKEouYTYocVswXSwwKSwhMSkKUC5ITihxLCExLDEpCnQ9
+ITB9ZWxzZXtQLkhOKHEsITEsMCkKdD0hMX1zPWEuZ3RUKCkmJiF0PyJcXCI6IiIKaWYoYS5nY2ooKSl7
+cj1hLmdKZihhKQppZihyLmxlbmd0aCE9PTApcz1zKyJcXCIrcisiXFwifXM9UC52ZyhzLHEsIlxcIikK
+cD10JiZwPT09MT9zKyJcXCI6cwpyZXR1cm4gcC5jaGFyQ29kZUF0KDApPT0wP3A6cH0sCkloOmZ1bmN0
+aW9uKGEsYil7dmFyIHQscyxyCmZvcih0PTAscz0wO3M8MjsrK3Mpe3I9Qy54Qi5XKGEsYitzKQppZig0
+ODw9ciYmcjw9NTcpdD10KjE2K3ItNDgKZWxzZXtyfD0zMgppZig5Nzw9ciYmcjw9MTAyKXQ9dCoxNity
+LTg3CmVsc2UgdGhyb3cgSC5iKFAueFkoIkludmFsaWQgVVJMIGVuY29kaW5nIikpfX1yZXR1cm4gdH0s
+Cmt1OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEscD1KLnJZKGEpLG89Ygp3aGlsZSghMCl7
+aWYoIShvPGMpKXt0PSEwCmJyZWFrfXM9cC5XKGEsbykKaWYoczw9MTI3KWlmKHMhPT0zNylyPWUmJnM9
+PT00MwplbHNlIHI9ITAKZWxzZSByPSEwCmlmKHIpe3Q9ITEKYnJlYWt9KytvfWlmKHQpe2lmKEMueE0h
+PT1kKXI9ITEKZWxzZSByPSEwCmlmKHIpcmV0dXJuIHAuTmooYSxiLGMpCmVsc2UgcT1uZXcgSC5xaihw
+Lk5qKGEsYixjKSl9ZWxzZXtxPUguVk0oW10sdS50KQpmb3Iobz1iO288YzsrK28pe3M9cC5XKGEsbykK
+aWYocz4xMjcpdGhyb3cgSC5iKFAueFkoIklsbGVnYWwgcGVyY2VudCBlbmNvZGluZyBpbiBVUkkiKSkK
+aWYocz09PTM3KXtpZihvKzM+YS5sZW5ndGgpdGhyb3cgSC5iKFAueFkoIlRydW5jYXRlZCBVUkkiKSkK
+Qy5ObS5pKHEsUC5JaChhLG8rMSkpCm8rPTJ9ZWxzZSBpZihlJiZzPT09NDMpQy5ObS5pKHEsMzIpCmVs
+c2UgQy5ObS5pKHEscyl9fXUuTC5iKHEpCnJldHVybiBuZXcgUC5HWSghMSkuV0oocSl9LApFdDpmdW5j
+dGlvbihhKXt2YXIgdD1hfDMyCnJldHVybiA5Nzw9dCYmdDw9MTIyfSwKS0Q6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0LHMscixxLHAsbyxuLG0sbD0iSW52YWxpZCBNSU1FIHR5cGUiLGs9SC5WTShbYi0xXSx1LnQp
+CmZvcih0PWEubGVuZ3RoLHM9YixyPS0xLHE9bnVsbDtzPHQ7KytzKXtxPUMueEIuVyhhLHMpCmlmKHE9
+PT00NHx8cT09PTU5KWJyZWFrCmlmKHE9PT00Nyl7aWYocjwwKXtyPXMKY29udGludWV9dGhyb3cgSC5i
+KFAucnIobCxhLHMpKX19aWYocjwwJiZzPmIpdGhyb3cgSC5iKFAucnIobCxhLHMpKQpmb3IoO3EhPT00
+NDspe0MuTm0uaShrLHMpOysrcwpmb3IocD0tMTtzPHQ7KytzKXtxPUMueEIuVyhhLHMpCmlmKHE9PT02
+MSl7aWYocDwwKXA9c31lbHNlIGlmKHE9PT01OXx8cT09PTQ0KWJyZWFrfWlmKHA+PTApQy5ObS5pKGss
+cCkKZWxzZXtvPUMuTm0uZ3JaKGspCmlmKHEhPT00NHx8cyE9PW8rN3x8IUMueEIuUWkoYSwiYmFzZTY0
+IixvKzEpKXRocm93IEguYihQLnJyKCJFeHBlY3RpbmcgJz0nIixhLHMpKQpicmVha319Qy5ObS5pKGss
+cykKbj1zKzEKaWYoKGsubGVuZ3RoJjEpPT09MSlhPUMuaDkueXIoYSxuLHQpCmVsc2V7bT1QLlVsKGEs
+bix0LEMuVkMsITApCmlmKG0hPW51bGwpYT1DLnhCLmk3KGEsbix0LG0pfXJldHVybiBuZXcgUC5QRShh
+LGssYyl9LAp1eDpmdW5jdGlvbigpe3ZhciB0PSIwMTIzNDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RV
+VldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ei0uX34hJCYnKCkqKyw7PSIscz0iLiIscj0iOiIs
+cT0iLyIscD0iPyIsbz0iIyIsbj11LmdjLG09UC5kSCgyMixuZXcgUC5xMygpLCEwLG4pLGw9bmV3IFAu
+eUkobSksaz1uZXcgUC5jNigpLGo9bmV3IFAucWQoKSxpPW4uYihsLiQyKDAsMjI1KSkKay4kMyhpLHQs
+MSkKay4kMyhpLHMsMTQpCmsuJDMoaSxyLDM0KQprLiQzKGkscSwzKQprLiQzKGkscCwxNzIpCmsuJDMo
+aSxvLDIwNSkKaT1uLmIobC4kMigxNCwyMjUpKQprLiQzKGksdCwxKQprLiQzKGkscywxNSkKay4kMyhp
+LHIsMzQpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIo
+MTUsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLCIlIiwyMjUpCmsuJDMoaSxyLDM0KQprLiQzKGkscSw5
+KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMigxLDIyNSkpCmsuJDMoaSx0LDEp
+CmsuJDMoaSxyLDM0KQprLiQzKGkscSwxMCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5i
+KGwuJDIoMiwyMzUpKQprLiQzKGksdCwxMzkpCmsuJDMoaSxxLDEzMSkKay4kMyhpLHMsMTQ2KQprLiQz
+KGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmIobC4kMigzLDIzNSkpCmsuJDMoaSx0LDExKQprLiQz
+KGkscSw2OCkKay4kMyhpLHMsMTgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQy
+KDQsMjI5KSkKay4kMyhpLHQsNSkKai4kMyhpLCJBWiIsMjI5KQprLiQzKGksciwxMDIpCmsuJDMoaSwi
+QCIsNjgpCmsuJDMoaSwiWyIsMjMyKQprLiQzKGkscSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8s
+MjA1KQppPW4uYihsLiQyKDUsMjI5KSkKay4kMyhpLHQsNSkKai4kMyhpLCJBWiIsMjI5KQprLiQzKGks
+ciwxMDIpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSxxLDEzOCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywy
+MDUpCmk9bi5iKGwuJDIoNiwyMzEpKQpqLiQzKGksIjE5Iiw3KQprLiQzKGksIkAiLDY4KQprLiQzKGks
+cSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDcsMjMxKSkKai4kMyhp
+LCIwOSIsNykKay4kMyhpLCJAIiw2OCkKay4kMyhpLHEsMTM4KQprLiQzKGkscCwxNzIpCmsuJDMoaSxv
+LDIwNSkKay4kMyhuLmIobC4kMig4LDgpKSwiXSIsNSkKaT1uLmIobC4kMig5LDIzNSkpCmsuJDMoaSx0
+LDExKQprLiQzKGkscywxNikKay4kMyhpLHEsMjM0KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkK
+aT1uLmIobC4kMigxNiwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHMsMTcpCmsuJDMoaSxxLDIzNCkK
+ay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTcsMjM1KSkKay4kMyhpLHQsMTEp
+CmsuJDMoaSxxLDkpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYihsLiQyKDEwLDIzNSkp
+CmsuJDMoaSx0LDExKQprLiQzKGkscywxOCkKay4kMyhpLHEsMjM0KQprLiQzKGkscCwxNzIpCmsuJDMo
+aSxvLDIwNSkKaT1uLmIobC4kMigxOCwyMzUpKQprLiQzKGksdCwxMSkKay4kMyhpLHMsMTkpCmsuJDMo
+aSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwuJDIoMTksMjM1KSkKay4k
+MyhpLHQsMTEpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5iKGwu
+JDIoMTEsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDEwKQprLiQzKGkscCwxNzIpCmsuJDMoaSxv
+LDIwNSkKaT1uLmIobC4kMigxMiwyMzYpKQprLiQzKGksdCwxMikKay4kMyhpLHAsMTIpCmsuJDMoaSxv
+LDIwNSkKaT1uLmIobC4kMigxMywyMzcpKQprLiQzKGksdCwxMykKay4kMyhpLHAsMTMpCmouJDMobi5i
+KGwuJDIoMjAsMjQ1KSksImF6IiwyMSkKbD1uLmIobC4kMigyMSwyNDUpKQpqLiQzKGwsImF6IiwyMSkK
+ai4kMyhsLCIwOSIsMjEpCmsuJDMobCwiKy0uIiwyMSkKcmV0dXJuIG19LApVQjpmdW5jdGlvbihhLGIs
+YyxkLGUpe3ZhciB0LHMscixxLHAsbz0kLnZaKCkKZm9yKHQ9Si5yWShhKSxzPWI7czxjOysrcyl7aWYo
+ZDwwfHxkPj1vLmxlbmd0aClyZXR1cm4gSC5PSChvLGQpCnI9b1tkXQpxPXQuVyhhLHMpXjk2CmlmKHE+
+OTUpcT0zMQppZihxPj1yLmxlbmd0aClyZXR1cm4gSC5PSChyLHEpCnA9cltxXQpkPXAmMzEKQy5ObS5Z
+KGUscD4+PjUscyl9cmV0dXJuIGR9LApXRjpmdW5jdGlvbiBXRihhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
+fSwKYTI6ZnVuY3Rpb24gYTIoKXt9LAppUDpmdW5jdGlvbiBpUChhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
+fSwKQ1A6ZnVuY3Rpb24gQ1AoKXt9LApYUzpmdW5jdGlvbiBYUygpe30sCkM2OmZ1bmN0aW9uIEM2KGEp
+e3RoaXMuYT1hfSwKbjpmdW5jdGlvbiBuKCl7fSwKdTpmdW5jdGlvbiB1KGEsYixjLGQpe3ZhciBfPXRo
+aXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LApiSjpmdW5jdGlvbiBiSihhLGIsYyxkLGUsZil7dmFy
+IF89dGhpcwpfLmU9YQpfLmY9YgpfLmE9YwpfLmI9ZApfLmM9ZQpfLmQ9Zn0sCmVZOmZ1bmN0aW9uIGVZ
+KGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmY9YQpfLmE9YgpfLmI9YwpfLmM9ZApfLmQ9ZX0sCm1wOmZ1
+bmN0aW9uIG1wKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LAp1Yjpm
+dW5jdGlvbiB1YihhKXt0aGlzLmE9YX0sCmRzOmZ1bmN0aW9uIGRzKGEpe3RoaXMuYT1hfSwKbGo6ZnVu
+Y3Rpb24gbGooYSl7dGhpcy5hPWF9LApVVjpmdW5jdGlvbiBVVihhKXt0aGlzLmE9YX0sCms1OmZ1bmN0
+aW9uIGs1KCl7fSwKS1k6ZnVuY3Rpb24gS1koKXt9LApjOmZ1bmN0aW9uIGMoYSl7dGhpcy5hPWF9LApD
+RDpmdW5jdGlvbiBDRChhKXt0aGlzLmE9YX0sCmFFOmZ1bmN0aW9uIGFFKGEsYixjKXt0aGlzLmE9YQp0
+aGlzLmI9Ygp0aGlzLmM9Y30sCkVIOmZ1bmN0aW9uIEVIKCl7fSwKS046ZnVuY3Rpb24gS04oKXt9LApj
+WDpmdW5jdGlvbiBjWCgpe30sCkFuOmZ1bmN0aW9uIEFuKCl7fSwKek06ZnVuY3Rpb24gek0oKXt9LApa
+MDpmdW5jdGlvbiBaMCgpe30sCmM4OmZ1bmN0aW9uIGM4KCl7fSwKRks6ZnVuY3Rpb24gRksoKXt9LApr
+OmZ1bmN0aW9uIGsoKXt9LApPZDpmdW5jdGlvbiBPZCgpe30sCmliOmZ1bmN0aW9uIGliKCl7fSwKeHU6
+ZnVuY3Rpb24geHUoKXt9LApHejpmdW5jdGlvbiBHeigpe30sCnFVOmZ1bmN0aW9uIHFVKCl7fSwKUm46
+ZnVuY3Rpb24gUm4oYSl7dGhpcy5hPWF9LApHRDpmdW5jdGlvbiBHRCgpe30sCm4xOmZ1bmN0aW9uIG4x
+KGEpe3RoaXMuYT1hfSwKY1M6ZnVuY3Rpb24gY1MoYSl7dGhpcy5hPWF9LApWQzpmdW5jdGlvbiBWQyhh
+KXt0aGlzLmE9YX0sCnRwOmZ1bmN0aW9uIHRwKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApEbjpmdW5j
+dGlvbiBEbihhLGIsYyxkLGUsZixnKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8u
+ZT1lCl8uZj1mCl8ucj1nCl8uUT1fLno9Xy55PV8ueD1udWxsfSwKZTE6ZnVuY3Rpb24gZTEoYSxiKXt0
+aGlzLmE9YQp0aGlzLmI9Yn0sCk5ZOmZ1bmN0aW9uIE5ZKGEpe3RoaXMuYT1hfSwKUlo6ZnVuY3Rpb24g
+UlooKXt9LApNRTpmdW5jdGlvbiBNRShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKeTU6ZnVuY3Rpb24g
+eTUoYSl7dGhpcy5hPWF9LApQRTpmdW5jdGlvbiBQRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhp
+cy5jPWN9LApxMzpmdW5jdGlvbiBxMygpe30sCnlJOmZ1bmN0aW9uIHlJKGEpe3RoaXMuYT1hfSwKYzY6
+ZnVuY3Rpb24gYzYoKXt9LApxZDpmdW5jdGlvbiBxZCgpe30sClVmOmZ1bmN0aW9uIFVmKGEsYixjLGQs
+ZSxmLGcsaCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9ZgpfLnI9
+ZwpfLng9aApfLnk9bnVsbH0sCnFlOmZ1bmN0aW9uIHFlKGEsYixjLGQsZSxmLGcpe3ZhciBfPXRoaXMK
+Xy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5yPWcKXy5RPV8uej1fLnk9Xy54PW51
+bGx9LAppSjpmdW5jdGlvbiBpSigpe30sCmxSOmZ1bmN0aW9uIGxSKGEsYil7dGhpcy5hPWEKdGhpcy5i
+PWJ9LApqZzpmdW5jdGlvbiBqZyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQmY6ZnVuY3Rpb24gQmYo
+YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkFzOmZ1bmN0aW9uIEFzKCl7fSwKR0U6ZnVuY3Rpb24gR0Uo
+YSl7dGhpcy5hPWF9LApONzpmdW5jdGlvbiBONyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKdVE6ZnVu
+Y3Rpb24gdVEoKXt9LApoRjpmdW5jdGlvbiBoRigpe30sClI0OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0
+LHMscgpILnhkKGIpCnUuai5iKGQpCmlmKEgub1QoYikpe3Q9W2NdCkMuTm0uRlYodCxkKQpkPXR9cz11
+LnoKcj1QLkNIKEouTTEoZCxQLncwKCkscyksITAscykKdS5aLmIoYSkKcmV0dXJuIFAud1koSC5Fayhh
+LHIsbnVsbCkpfSwKRG06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CnRyeXtpZihPYmplY3QuaXNFeHRlbnNp
+YmxlKGEpJiYhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGEsYikpe09iamVjdC5k
+ZWZpbmVQcm9wZXJ0eShhLGIse3ZhbHVlOmN9KQpyZXR1cm4hMH19Y2F0Y2godCl7SC5SdSh0KX1yZXR1
+cm4hMX0sCk9tOmZ1bmN0aW9uKGEsYil7aWYoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5j
+YWxsKGEsYikpcmV0dXJuIGFbYl0KcmV0dXJufSwKd1k6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbHx8dHlw
+ZW9mIGE9PSJzdHJpbmcifHx0eXBlb2YgYT09Im51bWJlciJ8fEgubChhKSlyZXR1cm4gYQppZihhIGlu
+c3RhbmNlb2YgUC5FNClyZXR1cm4gYS5hCmlmKEguUjkoYSkpcmV0dXJuIGEKaWYodS53LmMoYSkpcmV0
+dXJuIGEKaWYoYSBpbnN0YW5jZW9mIFAuaVApcmV0dXJuIEgubzIoYSkKaWYodS5aLmMoYSkpcmV0dXJu
+IFAuaEUoYSwiJGRhcnRfanNGdW5jdGlvbiIsbmV3IFAuUEMoKSkKcmV0dXJuIFAuaEUoYSwiXyRkYXJ0
+X2pzT2JqZWN0IixuZXcgUC5ZbSgkLmtJKCkpKX0sCmhFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1QLk9t
+KGEsYikKaWYodD09bnVsbCl7dD1jLiQxKGEpClAuRG0oYSxiLHQpfXJldHVybiB0fSwKTDc6ZnVuY3Rp
+b24oYSl7dmFyIHQscwppZihhPT1udWxsfHx0eXBlb2YgYT09InN0cmluZyJ8fHR5cGVvZiBhPT0ibnVt
+YmVyInx8dHlwZW9mIGE9PSJib29sZWFuIilyZXR1cm4gYQplbHNlIGlmKGEgaW5zdGFuY2VvZiBPYmpl
+Y3QmJkguUjkoYSkpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNlb2YgT2JqZWN0JiZ1LncuYyhhKSly
+ZXR1cm4gYQplbHNlIGlmKGEgaW5zdGFuY2VvZiBEYXRlKXt0PUguU2MoYS5nZXRUaW1lKCkpCmlmKE1h
+dGguYWJzKHQpPD04NjRlMTMpcz0hMQplbHNlIHM9ITAKaWYocylILnZoKFAueFkoIkRhdGVUaW1lIGlz
+IG91dHNpZGUgdmFsaWQgcmFuZ2U6ICIrdCkpCnJldHVybiBuZXcgUC5pUCh0LCExKX1lbHNlIGlmKGEu
+Y29uc3RydWN0b3I9PT0kLmtJKCkpcmV0dXJuIGEubwplbHNlIHJldHVybiBQLk5EKGEpfSwKTkQ6ZnVu
+Y3Rpb24oYSl7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIFAuaVEoYSwkLncoKSxuZXcgUC5O
+eigpKQppZihhIGluc3RhbmNlb2YgQXJyYXkpcmV0dXJuIFAuaVEoYSwkLlI4KCksbmV3IFAubnAoKSkK
+cmV0dXJuIFAuaVEoYSwkLlI4KCksbmV3IFAuVXQoKSl9LAppUTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9
+UC5PbShhLGIpCmlmKHQ9PW51bGx8fCEoYSBpbnN0YW5jZW9mIE9iamVjdCkpe3Q9Yy4kMShhKQpQLkRt
+KGEsYix0KX1yZXR1cm4gdH0sClBDOmZ1bmN0aW9uIFBDKCl7fSwKWW06ZnVuY3Rpb24gWW0oYSl7dGhp
+cy5hPWF9LApOejpmdW5jdGlvbiBOeigpe30sCm5wOmZ1bmN0aW9uIG5wKCl7fSwKVXQ6ZnVuY3Rpb24g
+VXQoKXt9LApFNDpmdW5jdGlvbiBFNChhKXt0aGlzLmE9YX0sCnI3OmZ1bmN0aW9uIHI3KGEpe3RoaXMu
+YT1hfSwKVHo6ZnVuY3Rpb24gVHooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKY286ZnVuY3Rpb24g
+Y28oKXt9LApuZDpmdW5jdGlvbiBuZCgpe30sCktlOmZ1bmN0aW9uIEtlKGEpe3RoaXMuYT1hfSwKZDU6
+ZnVuY3Rpb24gZDUoKXt9LApuNjpmdW5jdGlvbiBuNigpe319LFc9ewpVOTpmdW5jdGlvbihhLGIsYyl7
+dmFyIHQ9ZG9jdW1lbnQuYm9keSxzPSh0JiZDLlJZKS5yNih0LGEsYixjKQpzLnRvU3RyaW5nCnQ9dS5h
+Ywp0PW5ldyBILlU1KG5ldyBXLmU3KHMpLHQuQygiYTIobEQuRSkiKS5iKG5ldyBXLkN2KCkpLHQuQygi
+VTU8bEQuRT4iKSkKcmV0dXJuIHUuaC5iKHQuZ3I4KHQpKX0sCnJTOmZ1bmN0aW9uKGEpe3ZhciB0LHMs
+cj0iZWxlbWVudCB0YWcgdW5hdmFpbGFibGUiCnRyeXt0PUouUkUoYSkKaWYodHlwZW9mIHQuZ25zKGEp
+PT0ic3RyaW5nIilyPXQuZ25zKGEpfWNhdGNoKHMpe0guUnUocyl9cmV0dXJuIHJ9LApxRDpmdW5jdGlv
+bihhLGIsYyl7dmFyIHQscyxyLHE9bmV3IFAudnMoJC5YMyx1LmFvKSxwPW5ldyBQLlpmKHEsdS5iaiks
+bz1uZXcgWE1MSHR0cFJlcXVlc3QoKQpDLkR0LmVvKG8sYj09bnVsbD8iR0VUIjpiLGEsITApCmMuSygw
+LG5ldyBXLmJVKG8pKQp0PXUuYW4Kcz10LmIobmV3IFcuaEgobyxwKSkKdS5NLmIobnVsbCkKcj11LnAK
+Vy5KRShvLCJsb2FkIixzLCExLHIpClcuSkUobywiZXJyb3IiLHQuYihwLmdZSigpKSwhMSxyKQpvLnNl
+bmQoKQpyZXR1cm4gcX0sCkMwOmZ1bmN0aW9uKGEsYil7YT01MzY4NzA5MTEmYStiCmE9NTM2ODcwOTEx
+JmErKCg1MjQyODcmYSk8PDEwKQpyZXR1cm4gYV5hPj4+Nn0sCnJFOmZ1bmN0aW9uKGEsYixjLGQpe3Zh
+ciB0PVcuQzAoVy5DMChXLkMwKFcuQzAoMCxhKSxiKSxjKSxkKSxzPTUzNjg3MDkxMSZ0KygoNjcxMDg4
+NjMmdCk8PDMpCnNePXM+Pj4xMQpyZXR1cm4gNTM2ODcwOTExJnMrKCgxNjM4MyZzKTw8MTUpfSwKVE46
+ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9YS5jbGFzc0xpc3QKZm9yKHQ9Yi5sZW5ndGgscz0wO3M8Yi5s
+ZW5ndGg7Yi5sZW5ndGg9PT10fHwoMCxILmxrKShiKSwrK3Mpci5hZGQoYltzXSl9LApKRTpmdW5jdGlv
+bihhLGIsYyxkLGUpe3ZhciB0PVcuYUYobmV3IFcudk4oYyksdS5CKQppZih0IT1udWxsJiYhMClKLmRa
+KGEsYix0LCExKQpyZXR1cm4gbmV3IFcueEMoYSxiLHQsITEsZS5DKCJ4QzwwPiIpKX0sClR3OmZ1bmN0
+aW9uKGEpe3ZhciB0PWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKSxzPW5ldyBXLm1rKHQsd2luZG93
+LmxvY2F0aW9uKQpzPW5ldyBXLkpRKHMpCnMuQ1koYSkKcmV0dXJuIHN9LAp5VzpmdW5jdGlvbihhLGIs
+YyxkKXt1LmguYihhKQpILnkoYikKSC55KGMpCnUuTy5iKGQpCnJldHVybiEwfSwKUVc6ZnVuY3Rpb24o
+YSxiLGMsZCl7dmFyIHQscyxyCnUuaC5iKGEpCkgueShiKQpILnkoYykKdD11Lk8uYihkKS5hCnM9dC5h
+CnMuaHJlZj1jCnI9cy5ob3N0bmFtZQp0PXQuYgppZighKHI9PXQuaG9zdG5hbWUmJnMucG9ydD09dC5w
+b3J0JiZzLnByb3RvY29sPT10LnByb3RvY29sKSlpZihyPT09IiIpaWYocy5wb3J0PT09IiIpe3Q9cy5w
+cm90b2NvbAp0PXQ9PT0iOiJ8fHQ9PT0iIn1lbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMApyZXR1
+cm4gdH0sCkJsOmZ1bmN0aW9uKCl7dmFyIHQ9dS5OLHM9UC50TShDLlF4LHQpLHI9dS5kRy5iKG5ldyBX
+LklBKCkpLHE9SC5WTShbIlRFTVBMQVRFIl0sdS5zKQp0PW5ldyBXLmN0KHMsUC5Mcyh0KSxQLkxzKHQp
+LFAuTHModCksbnVsbCkKdC5DWShudWxsLG5ldyBILkE4KEMuUXgscix1LmR2KSxxLG51bGwpCnJldHVy
+biB0fSwKdVY6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4KcmV0dXJuIFcuUDEoYSl9LApxYzpm
+dW5jdGlvbihhKXt2YXIgdAppZihhPT1udWxsKXJldHVybgppZigicG9zdE1lc3NhZ2UiIGluIGEpe3Q9
+Vy5QMShhKQpyZXR1cm4gdH1lbHNlIHJldHVybiB1LmFTLmIoYSl9LApQMTpmdW5jdGlvbihhKXtpZihh
+PT09d2luZG93KXJldHVybiB1LmNpLmIoYSkKZWxzZSByZXR1cm4gbmV3IFcuZFcoYSl9LAp6WDpmdW5j
+dGlvbihhKXtpZihhPT09d2luZG93LmxvY2F0aW9uKXJldHVybiBhCmVsc2UgcmV0dXJuIG5ldyBXLkZi
+KCl9LAphRjpmdW5jdGlvbihhLGIpe3ZhciB0PSQuWDMKaWYodD09PUMuTlUpcmV0dXJuIGEKcmV0dXJu
+IHQuUHkoYSxiKX0sCnFFOmZ1bmN0aW9uIHFFKCl7fSwKR2g6ZnVuY3Rpb24gR2goKXt9LApmWTpmdW5j
+dGlvbiBmWSgpe30sCm5COmZ1bmN0aW9uIG5CKCl7fSwKQXo6ZnVuY3Rpb24gQXooKXt9LApRUDpmdW5j
+dGlvbiBRUCgpe30sCm54OmZ1bmN0aW9uIG54KCl7fSwKb0o6ZnVuY3Rpb24gb0ooKXt9LAppZDpmdW5j
+dGlvbiBpZCgpe30sClFGOmZ1bmN0aW9uIFFGKCl7fSwKTmg6ZnVuY3Rpb24gTmgoKXt9LApJQjpmdW5j
+dGlvbiBJQigpe30sCm43OmZ1bmN0aW9uIG43KCl7fSwKd3o6ZnVuY3Rpb24gd3ooYSxiKXt0aGlzLmE9
+YQp0aGlzLiR0aT1ifSwKY3Y6ZnVuY3Rpb24gY3YoKXt9LApDdjpmdW5jdGlvbiBDdigpe30sCmVhOmZ1
+bmN0aW9uIGVhKCl7fSwKRDA6ZnVuY3Rpb24gRDAoKXt9LApUNTpmdW5jdGlvbiBUNSgpe30sCmg0OmZ1
+bmN0aW9uIGg0KCl7fSwKYnI6ZnVuY3Rpb24gYnIoKXt9LApWYjpmdW5jdGlvbiBWYigpe30sCk83OmZ1
+bmN0aW9uIE83KCl7fSwKYlU6ZnVuY3Rpb24gYlUoYSl7dGhpcy5hPWF9LApoSDpmdW5jdGlvbiBoSChh
+LGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKd2E6ZnVuY3Rpb24gd2EoKXt9LApTZzpmdW5jdGlvbiBTZygp
+e30sCnU4OmZ1bmN0aW9uIHU4KCl7fSwKQWo6ZnVuY3Rpb24gQWooKXt9LAplNzpmdW5jdGlvbiBlNyhh
+KXt0aGlzLmE9YX0sCnVIOmZ1bmN0aW9uIHVIKCl7fSwKQkg6ZnVuY3Rpb24gQkgoKXt9LApTTjpmdW5j
+dGlvbiBTTigpe30sCmV3OmZ1bmN0aW9uIGV3KCl7fSwKbHA6ZnVuY3Rpb24gbHAoKXt9LApUYjpmdW5j
+dGlvbiBUYigpe30sCkl2OmZ1bmN0aW9uIEl2KCl7fSwKQlQ6ZnVuY3Rpb24gQlQoKXt9LAp5WTpmdW5j
+dGlvbiB5WSgpe30sCnc2OmZ1bmN0aW9uIHc2KCl7fSwKSzU6ZnVuY3Rpb24gSzUoKXt9LApDbTpmdW5j
+dGlvbiBDbSgpe30sCkNROmZ1bmN0aW9uIENRKCl7fSwKdzQ6ZnVuY3Rpb24gdzQoKXt9LApyaDpmdW5j
+dGlvbiByaCgpe30sCkQ5OmZ1bmN0aW9uIEQ5KCl7fSwKaTc6ZnVuY3Rpb24gaTcoYSl7dGhpcy5hPWF9
+LApTeTpmdW5jdGlvbiBTeShhKXt0aGlzLmE9YX0sCktTOmZ1bmN0aW9uIEtTKGEsYil7dGhpcy5hPWEK
+dGhpcy5iPWJ9LApBMzpmdW5jdGlvbiBBMyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSTQ6ZnVuY3Rp
+b24gSTQoYSl7dGhpcy5hPWF9LApGazpmdW5jdGlvbiBGayhhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9
+LApSTzpmdW5jdGlvbiBSTyhhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uJHRp
+PWR9LApDcTpmdW5jdGlvbiBDcShhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8u
+JHRpPWR9LAp4QzpmdW5jdGlvbiB4QyhhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5iPWEKXy5jPWIKXy5k
+PWMKXy5lPWQKXy4kdGk9ZX0sCnZOOmZ1bmN0aW9uIHZOKGEpe3RoaXMuYT1hfSwKSlE6ZnVuY3Rpb24g
+SlEoYSl7dGhpcy5hPWF9LApHbTpmdW5jdGlvbiBHbSgpe30sCnZEOmZ1bmN0aW9uIHZEKGEpe3RoaXMu
+YT1hfSwKVXY6ZnVuY3Rpb24gVXYoYSl7dGhpcy5hPWF9LApFZzpmdW5jdGlvbiBFZyhhLGIsYyl7dGhp
+cy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAptNjpmdW5jdGlvbiBtNigpe30sCkVvOmZ1bmN0aW9uIEVv
+KCl7fSwKV2s6ZnVuY3Rpb24gV2soKXt9LApjdDpmdW5jdGlvbiBjdChhLGIsYyxkLGUpe3ZhciBfPXRo
+aXMKXy5lPWEKXy5hPWIKXy5iPWMKXy5jPWQKXy5kPWV9LApJQTpmdW5jdGlvbiBJQSgpe30sCk93OmZ1
+bmN0aW9uIE93KCl7fSwKVzk6ZnVuY3Rpb24gVzkoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIK
+Xy5jPS0xCl8uZD1udWxsCl8uJHRpPWN9LApkVzpmdW5jdGlvbiBkVyhhKXt0aGlzLmE9YX0sCkZiOmZ1
+bmN0aW9uIEZiKCl7fSwKa0Y6ZnVuY3Rpb24ga0YoKXt9LAptazpmdW5jdGlvbiBtayhhLGIpe3RoaXMu
+YT1hCnRoaXMuYj1ifSwKS286ZnVuY3Rpb24gS28oYSl7dGhpcy5hPWF9LApmbTpmdW5jdGlvbiBmbShh
+KXt0aGlzLmE9YX0sCkxlOmZ1bmN0aW9uIExlKCl7fSwKSzc6ZnVuY3Rpb24gSzcoKXt9LApyQjpmdW5j
+dGlvbiByQigpe30sClhXOmZ1bmN0aW9uIFhXKCl7fSwKb2E6ZnVuY3Rpb24gb2EoKXt9fSxVPXsKeXU6
+ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG49SC5WTShbXSx1LmJQKQpmb3IodD1KLlU2KGEpLHM9
+Si5JVCh1LlIuYih0LnEoYSwiZGV0YWlscyIpKSk7cy5GKCk7KXtyPXMuZ2woKQpxPUouVTYocikKcD1I
+LnkocS5xKHIsImRlc2NyaXB0aW9uIikpCnE9cS5xKHIsImxpbmsiKQppZihxPT1udWxsKXE9bnVsbApl
+bHNle289Si5VNihxKQpxPW5ldyBVLk1sKEgueShvLnEocSwiaHJlZiIpKSxILlNjKG8ucShxLCJsaW5l
+IikpLEgueShvLnEocSwicGF0aCIpKSl9Qy5ObS5pKG4sbmV3IFUudUYocCxxKSl9cmV0dXJuIG5ldyBV
+LmQyKG4sVS5qZih0LnEoYSwiZWRpdHMiKSksSC55KHQucShhLCJleHBsYW5hdGlvbiIpKSxILlNjKHQu
+cShhLCJsaW5lIikpLEgueSh0LnEoYSwicGF0aCIpKSxVLk5kKHQucShhLCJ0cmFjZXMiKSkpfSwKamY6
+ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEKaWYoYT09bnVsbCl0PW51bGwKZWxzZXt0PUguVk0oW10sdS5m
+QSkKZm9yKHM9Si5JVCh1LlIuYihhKSk7cy5GKCk7KXtyPXMuZ2woKQpxPUouVTYocikKQy5ObS5pKHQs
+bmV3IFUuU2UoSC55KHEucShyLCJkZXNjcmlwdGlvbiIpKSxILnkocS5xKHIsImhyZWYiKSkpKX19cmV0
+dXJuIHR9LApOZDpmdW5jdGlvbihhKXt2YXIgdCxzCmlmKGE9PW51bGwpdD1udWxsCmVsc2V7dD1ILlZN
+KFtdLHUuaGgpCmZvcihzPUouSVQodS5SLmIoYSkpO3MuRigpOylDLk5tLmkodCxVLk5mKHMuZ2woKSkp
+fXJldHVybiB0fSwKTmY6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvPSJkZXNjcmlwdGlvbiIsbj1K
+LlU2KGEpLG09SC55KG4ucShhLG8pKSxsPUguVk0oW10sdS5hSikKZm9yKG49Si5JVCh1LlIuYihuLnEo
+YSwiZW50cmllcyIpKSk7bi5GKCk7KXt0PW4uZ2woKQpzPUouVTYodCkKcj1ILnkocy5xKHQsbykpCnE9
+SC55KHMucSh0LCJmdW5jdGlvbiIpKQpzPXMucSh0LCJsaW5rIikKaWYocz09bnVsbClzPW51bGwKZWxz
+ZXtwPUouVTYocykKcz1uZXcgVS5NbChILnkocC5xKHMsImhyZWYiKSksSC5TYyhwLnEocywibGluZSIp
+KSxILnkocC5xKHMsInBhdGgiKSkpfUMuTm0uaShsLG5ldyBVLndiKHIscSxzKSl9cmV0dXJuIG5ldyBV
+LnlEKG0sbCl9LApkMjpmdW5jdGlvbiBkMihhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmE9YQpfLmI9
+YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zn0sClNlOmZ1bmN0aW9uIFNlKGEsYil7dGhpcy5hPWEKdGhp
+cy5iPWJ9LAp1RjpmdW5jdGlvbiB1RihhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKTWw6ZnVuY3Rpb24g
+TWwoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKeUQ6ZnVuY3Rpb24geUQoYSxiKXt0
+aGlzLmE9YQp0aGlzLmI9Yn0sCndiOmZ1bmN0aW9uIHdiKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0
+aGlzLmM9Y319LEI9ewpZZjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1ILnkoYS5xKDAsInJlZ2lvbnMi
+KSkscD1ILnkoYS5xKDAsIm5hdmlnYXRpb25Db250ZW50IikpLG89SC55KGEucSgwLCJzb3VyY2VDb2Rl
+IikpLG49SC5WTShbXSx1LnUpCmZvcih0PUouSVQodS5SLmIoYS5xKDAsImVkaXRzIikpKTt0LkYoKTsp
+e3M9dC5nbCgpCnI9Si5VNihzKQpDLk5tLmkobixuZXcgQi5qOChILlNjKHIucShzLCJsaW5lIikpLEgu
+eShyLnEocywiZXhwbGFuYXRpb24iKSksSC5TYyhyLnEocywib2Zmc2V0IikpKSl9cmV0dXJuIG5ldyBC
+LnFwKHEscCxvLG4pfSwKajg6ZnVuY3Rpb24gajgoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMu
+Yz1jfSwKcXA6ZnVuY3Rpb24gcXAoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9Ywpf
+LmQ9ZH0sCkx1OmZ1bmN0aW9uIEx1KCl7fSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoIShhPj02NSYm
+YTw9OTApKXQ9YT49OTcmJmE8PTEyMgplbHNlIHQ9ITAKcmV0dXJuIHR9LApZdTpmdW5jdGlvbihhLGIp
+e3ZhciB0PWEubGVuZ3RoLHM9YisyCmlmKHQ8cylyZXR1cm4hMQppZighQi5PUyhDLnhCLm0oYSxiKSkp
+cmV0dXJuITEKaWYoQy54Qi5tKGEsYisxKSE9PTU4KXJldHVybiExCmlmKHQ9PT1zKXJldHVybiEwCnJl
+dHVybiBDLnhCLm0oYSxzKT09PTQ3fX0sVD17R1Y6ZnVuY3Rpb24gR1YoKXt9fSxMPXsKSXE6ZnVuY3Rp
+b24oKXtDLkJaLkIoZG9jdW1lbnQsIkRPTUNvbnRlbnRMb2FkZWQiLG5ldyBMLmUoKSkKQy5vbC5CKHdp
+bmRvdywicG9wc3RhdGUiLG5ldyBMLkwoKSl9LAprejpmdW5jdGlvbihhKXt2YXIgdCxzPXUuaC5hKGEu
+cGFyZW50Tm9kZSkucXVlcnlTZWxlY3RvcigiOnNjb3BlID4gdWwiKSxyPXMuc3R5bGUscT0iIitDLkNE
+LnpRKHMub2Zmc2V0SGVpZ2h0KSoyKyJweCIKci5tYXhIZWlnaHQ9cQpyPUoucUYoYSkKcT1yLiR0aQp0
+PXEuQygifigxKSIpLmIobmV3IEwuV3gocyxhKSkKdS5NLmIobnVsbCkKVy5KRShyLmEsci5iLHQsITEs
+cS5kKX0sCnlYOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbz0icXVlcnlTZWxlY3RvckFsbCIsbj1k
+b2N1bWVudC5xdWVyeVNlbGVjdG9yKGEpLG09dS5oCm4udG9TdHJpbmcKSC5EaChtLG0sIlQiLG8pCnQ9
+dS5TCnM9bmV3IFcud3oobi5xdWVyeVNlbGVjdG9yQWxsKCIubmF2LWxpbmsiKSx0KQpzLksocyxuZXcg
+TC5BTygpKQpILkRoKG0sbSwiVCIsbykKcj1uZXcgVy53eihuLnF1ZXJ5U2VsZWN0b3JBbGwoIi5yZWdp
+b24iKSx0KQppZihyLmdBKHIpIT09MCl7cT1uLnF1ZXJ5U2VsZWN0b3IoInRhYmxlW2RhdGEtcGF0aF0i
+KQpxLnRvU3RyaW5nCnIuSyhyLG5ldyBMLkhvKHEuZ2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3ko
+bmV3IFcuaTcocSkpLk8oInBhdGgiKSkpKX1ILkRoKG0sbSwiVCIsbykKcD1uZXcgVy53eihuLnF1ZXJ5
+U2VsZWN0b3JBbGwoIi5wb3N0LWxpbmsiKSx0KQpwLksocCxuZXcgTC5JQygpKX0sCnR5OmZ1bmN0aW9u
+KGEpe3ZhciB0PXUuTgpyZXR1cm4gVy5xRChhLCJQT1NUIixQLkVGKFsiQ29udGVudC1UeXBlIiwiYXBw
+bGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCJdLHQsdCkpLlc3KG5ldyBMLkwxKCksdS5yKX0sCmFL
+OmZ1bmN0aW9uKGEpe3ZhciB0PVAuaEsoYSkuZ2hZKCkucSgwLCJsaW5lIikKcmV0dXJuIHQ9PW51bGw/
+bnVsbDpILkhwKHQsbnVsbCl9LApHNjpmdW5jdGlvbihhKXt2YXIgdD1QLmhLKGEpLmdoWSgpLnEoMCwi
+b2Zmc2V0IikKcmV0dXJuIHQ9PW51bGw/bnVsbDpILkhwKHQsbnVsbCl9LAp0MjpmdW5jdGlvbihhLGIp
+e3ZhciB0LHMscixxLHAsbyxuPXt9CnUuVi5iKGEpCnQ9bi5hPXUuaC5iKFcucWMoYS5jdXJyZW50VGFy
+Z2V0KSkuZ2V0QXR0cmlidXRlKCJocmVmIikKaWYoSi56bCh0LCI/Iikpe3M9Qy54Qi5Oaih0LDAsQy54
+Qi5PWSh0LCI/IikpCm4uYT1zCnI9c31lbHNlIHI9dAppZihiIT1udWxsKXtxPSQublUoKQpyPW4uYT1x
+Lm81KEQubnIocS50TShiKSxyKSl9cD1MLkc2KHQpCm89TC5hSyh0KQppZihwIT1udWxsKUwuYWYocixw
+LG8sbmV3IEwublQobixwLG8pKQplbHNlIEwuYWYocixudWxsLG51bGwsbmV3IEwuQloobikpCmEucHJl
+dmVudERlZmF1bHQoKX0sCnVtOmZ1bmN0aW9uKGEpe3JldHVybiBMLlFTKHUuVi5iKGEpKX0sClFTOmZ1
+bmN0aW9uKGEpe3ZhciB0PTAscz1QLkZYKHUueikscj0xLHEscD1bXSxvLG4sbSxsLGssagp2YXIgJGFz
+eW5jJHVtPVAubHooZnVuY3Rpb24oYixjKXtpZihiPT09MSl7cT1jCnQ9cn13aGlsZSh0cnVlKXN3aXRj
+aCh0KXtjYXNlIDA6az11LmguYShXLnFjKGEuY3VycmVudFRhcmdldCkpLmdldEF0dHJpYnV0ZSgiaHJl
+ZiIpCmEucHJldmVudERlZmF1bHQoKQptPWRvY3VtZW50Cm0uYm9keS5jbGFzc0xpc3QuYWRkKCJyZXJ1
+bm5pbmciKQpyPTMKdD02CnJldHVybiBQLmpRKEwudHkoayksJGFzeW5jJHVtKQpjYXNlIDY6dS5GLmEo
+Si5HcihXLnVWKG0uZGVmYXVsdFZpZXcpKSkucmVsb2FkKCkKcC5wdXNoKDUpCnQ9NApicmVhawpjYXNl
+IDM6cj0yCmo9cQpvPUguUnUoaikKbj1ILnRzKGopCkwucUooImhhbmRsZVBvc3RMaW5rQ2xpY2s6ICIr
+SC5kKG8pLG4pCndpbmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIitILmQoaykrIiAoIitILmQobykr
+IikuIikKcC5wdXNoKDUpCnQ9NApicmVhawpjYXNlIDI6cD1bMV0KY2FzZSA0OnI9MQptLmJvZHkuY2xh
+c3NMaXN0LnJlbW92ZSgicmVydW5uaW5nIikKdD1wLnBvcCgpCmJyZWFrCmNhc2UgNTpyZXR1cm4gUC55
+QyhudWxsLHMpCmNhc2UgMTpyZXR1cm4gUC5mMyhxLHMpfX0pCnJldHVybiBQLkRJKCRhc3luYyR1bSxz
+KX0sCnZVOmZ1bmN0aW9uKCl7dmFyIHQ9ZG9jdW1lbnQscz11LmgKSC5EaChzLHMsIlQiLCJxdWVyeVNl
+bGVjdG9yQWxsIikKdD1uZXcgVy53eih0LnF1ZXJ5U2VsZWN0b3JBbGwoIi5jb2RlIiksdS5TKQp0Lkso
+dCxuZXcgTC5HSCgpKX0sCmhYOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dS5OClcucUQoSC5kKGEpKyI/cmVn
+aW9uPXJlZ2lvbiZvZmZzZXQ9IitILmQoYiksbnVsbCxQLkVGKFsiQ29udGVudC1UeXBlIiwiYXBwbGlj
+YXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCJdLHQsdCkpLlc3KG5ldyBMLkRUKCksdS5QKS5PQShuZXcg
+TC5lSChhKSl9LApHNzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzCmlmKCFKLnJZKGEpLlRjKGEsIi5k
+YXJ0Iikpe0wuQkUoYSxuZXcgQi5xcCgiIiwiIiwiIixDLnhEKSkKTC5CWChhLG51bGwpCmlmKGQhPW51
+bGwpZC4kMCgpCnJldHVybn10PUMueEIudGcoYSwiPyIpP2ErIiZpbmxpbmU9dHJ1ZSI6YSsiP2lubGlu
+ZT10cnVlIgpzPXUuTgpXLnFEKHQsbnVsbCxQLkVGKFsiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24v
+anNvbjsgY2hhcnNldD1VVEYtOCJdLHMscykpLlc3KG5ldyBMLnpEKGEsYixjLGQpLHUuUCkuT0EobmV3
+IEwuT0UoYSkpfSwKR2U6ZnVuY3Rpb24oKXt2YXIgdD0iL19wcmV2aWV3L25hdmlnYXRpb25UcmVlLmpz
+b24iLHM9dS5OClcucUQodCxudWxsLFAuRUYoWyJDb250ZW50LVR5cGUiLCJhcHBsaWNhdGlvbi9qc29u
+OyBjaGFyc2V0PVVURi04Il0scyxzKSkuVzcobmV3IEwuVFcoKSx1LlApLk9BKG5ldyBMLnhyKHQpKX0s
+CnFKOmZ1bmN0aW9uKGEsYil7dmFyIHQKd2luZG93CmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVk
+Iil3aW5kb3cuY29uc29sZS5lcnJvcihhKQp3aW5kb3cKdD1ILmQoYikKaWYodHlwZW9mIGNvbnNvbGUh
+PSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLmVycm9yKHQpfSwKcU86ZnVuY3Rpb24oYSl7dmFyIHQ9
+YS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKSxzPXQuYm90dG9tLHI9d2luZG93LmlubmVySGVpZ2h0Cmlm
+KHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJuIEgucFkocikKaWYocz5yKUouZGgoYSkKZWxzZSBpZih0
+LnRvcDwwKUouZGgoYSl9LApmRzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgppZihhIT1udWxsKXt0PWRv
+Y3VtZW50CnM9dC5nZXRFbGVtZW50QnlJZCgibyIrSC5kKGEpKQpyPXQucXVlcnlTZWxlY3RvcigiLmxp
+bmUtIitILmQoYikpCmlmKHMhPW51bGwpe0wucU8ocykKSi5kUihzKS5pKDAsInRhcmdldCIpfWVsc2Ug
+aWYociE9bnVsbClMLnFPKHIucGFyZW50RWxlbWVudCkKaWYociE9bnVsbClKLmRSKHUuaC5hKHIucGFy
+ZW50Tm9kZSkpLmkoMCwiaGlnaGxpZ2h0Iil9ZWxzZSBMLnFPKGRvY3VtZW50LmdldEVsZW1lbnRCeUlk
+KCJ1bml0LW5hbWUiKSl9LAphZjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHI9TC5HNih3aW5kb3cu
+bG9jYXRpb24uaHJlZikscT1MLmFLKHdpbmRvdy5sb2NhdGlvbi5ocmVmKQppZihyIT1udWxsKXt0PWRv
+Y3VtZW50LmdldEVsZW1lbnRCeUlkKCJvIitILmQocikpCmlmKHQhPW51bGwpSi5kUih0KS5SKDAsInRh
+cmdldCIpfWlmKHEhPW51bGwpe3M9ZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLmxpbmUtIitILmQocSkp
+CmlmKHMhPW51bGwpSi5kUihzLnBhcmVudEVsZW1lbnQpLlIoMCwiaGlnaGxpZ2h0Iil9aWYoYT09d2lu
+ZG93LmxvY2F0aW9uLnBhdGhuYW1lKXtMLmZHKGIsYykKZC4kMCgpfWVsc2UgTC5HNyhhLGIsYyxkKX0s
+Ckx4OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT09PTEpdD1iCmVsc2UgdD1iKyJzIgpyZXR1cm4gdH0s
+ClQxOmZ1bmN0aW9uKGIwKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixh
+LGEwLGExLGEyLGEzLGE0LGE1LGE2LGE3LGE4PWRvY3VtZW50LGE5PWE4LnF1ZXJ5U2VsZWN0b3IoIi5l
+ZGl0LXBhbmVsIC5wYW5lbC1jb250ZW50IikKSi5sNShhOSwiIikKaWYoYjA9PW51bGwpe2E4PWE4LmNy
+ZWF0ZUVsZW1lbnQoInAiKQphOC50ZXh0Q29udGVudD0iU2VlIGRldGFpbHMgYWJvdXQgYSBwcm9wb3Nl
+ZCBlZGl0LiIKQy5MdC5zRChhOCxILlZNKFsicGxhY2Vob2xkZXIiXSx1LnMpKQphOS5hcHBlbmRDaGls
+ZChhOCkKcmV0dXJufXQ9YjAuZQpzPSQublUoKQpyPXMudE0odCkKcT1iMC5jCnA9cy5IUCh0LEouVDAo
+YTgucXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCkpCm89YjAuZApzPWE4LmNyZWF0ZUVs
+ZW1lbnQoInAiKQpuPXUuaApuLmIoYTkuYXBwZW5kQ2hpbGQocykpLmFwcGVuZENoaWxkKGE4LmNyZWF0
+ZVRleHROb2RlKEguZChxKSsiIGF0ICIrSC5kKHApKyI6IitILmQobykrIi4iKSkKcz1iMC5hCmlmKHMu
+bGVuZ3RoIT09MCl7bT1hOC5jcmVhdGVFbGVtZW50KCJwIikKbS50ZXh0Q29udGVudD0iRWRpdCByYXRp
+b25hbGU6IgphOS5hcHBlbmRDaGlsZChtKQptPWE4LmNyZWF0ZUVsZW1lbnQoInVsIikKbD1uLmIoYTku
+YXBwZW5kQ2hpbGQobSkpCmZvcihtPXMubGVuZ3RoLGs9MDtrPHMubGVuZ3RoO3MubGVuZ3RoPT09bXx8
+KDAsSC5saykocyksKytrKXtqPXNba10KaT1hOC5jcmVhdGVFbGVtZW50KCJsaSIpCmg9bC5hcHBlbmRD
+aGlsZChpKQpoLmFwcGVuZENoaWxkKGE4LmNyZWF0ZVRleHROb2RlKGouYSkpCmc9ai5iCmlmKGchPW51
+bGwpe2guYXBwZW5kQ2hpbGQoYTguY3JlYXRlVGV4dE5vZGUoIiAoIikpCmguYXBwZW5kQ2hpbGQoTC5j
+NChnLHIpKQpoLmFwcGVuZENoaWxkKGE4LmNyZWF0ZVRleHROb2RlKCIpIikpfX19cz1iMC5iCmlmKHMh
+PW51bGwpZm9yKG09cy5sZW5ndGgsaT11LnMsZj11Llgsaz0wO2s8cy5sZW5ndGg7cy5sZW5ndGg9PT1t
+fHwoMCxILmxrKShzKSwrK2spe2U9c1trXQpkPWE4LmNyZWF0ZUVsZW1lbnQoInAiKQpjPW4uYihhOS5h
+cHBlbmRDaGlsZChkKSkKZD1hOC5jcmVhdGVFbGVtZW50KCJhIikKYj1uLmIoYy5hcHBlbmRDaGlsZChk
+KSkKYi5hcHBlbmRDaGlsZChhOC5jcmVhdGVUZXh0Tm9kZShlLmEpKQpiLnNldEF0dHJpYnV0ZSgiaHJl
+ZiIsZS5iKQpkPWYuYihILlZNKFsicG9zdC1saW5rIiwiYmVmb3JlLWFwcGx5Il0saSkpCmE9Si5kUihi
+KQphLlYxKDApCmEuRlYoMCxkKX1mb3Iocz1iMC5mLG49cy5sZW5ndGgsbT11LnMsaT11Llgsaz0wO2s8
+cy5sZW5ndGg7cy5sZW5ndGg9PT1ufHwoMCxILmxrKShzKSwrK2spe2EwPXNba10KZj1hOC5jcmVhdGVF
+bGVtZW50KCJwIikKZD1pLmIoSC5WTShbInRyYWNlIl0sbSkpCmE9Si5kUihmKQphLlYxKDApCmEuRlYo
+MCxkKQphMT1hOS5hcHBlbmRDaGlsZChmKQphMS5hcHBlbmRDaGlsZChhOC5jcmVhdGVUZXh0Tm9kZSgi
+TnVsbGFiaWxpdHkgdHJhY2UgZm9yOiAiKSkKZj1hOC5jcmVhdGVFbGVtZW50KCJzcGFuIikKZD1pLmIo
+SC5WTShbInR5cGUtZGVzY3JpcHRpb24iXSxtKSkKYT1KLmRSKGYpCmEuVjEoMCkKYS5GVigwLGQpCmYu
+YXBwZW5kQ2hpbGQoYTguY3JlYXRlVGV4dE5vZGUoYTAuYSkpCmExLmFwcGVuZENoaWxkKGYpCmY9YTgu
+Y3JlYXRlRWxlbWVudCgidWwiKQpkPWkuYihILlZNKFsidHJhY2UiXSxtKSkKYT1KLmRSKGYpCmEuVjEo
+MCkKYS5GVigwLGQpCmEyPWExLmFwcGVuZENoaWxkKGYpCmZvcihmPWEwLmIsZD1mLmxlbmd0aCxhMz0w
+O2EzPGYubGVuZ3RoO2YubGVuZ3RoPT09ZHx8KDAsSC5saykoZiksKythMyl7YTQ9ZlthM10KYTU9YTgu
+Y3JlYXRlRWxlbWVudCgibGkiKQpKLmw1KGE1LCImI3gyNzRGOyAiKQphNj1hMi5hcHBlbmRDaGlsZChh
+NSkKYTU9YTguY3JlYXRlRWxlbWVudCgic3BhbiIpCmE3PWkuYihILlZNKFsiZnVuY3Rpb24iXSxtKSkK
+YT1KLmRSKGE1KQphLlYxKDApCmEuRlYoMCxhNykKYTc9YTQuYgppZihhNz09bnVsbClhNz0idW5rbm93
+biIKYTUuYXBwZW5kQ2hpbGQoYTguY3JlYXRlVGV4dE5vZGUoYTcpKQphNi5hcHBlbmRDaGlsZChhNSkK
+Zz1hNC5jCmlmKGchPW51bGwpe2E2LmFwcGVuZENoaWxkKGE4LmNyZWF0ZVRleHROb2RlKCIgKCIpKQph
+Ni5hcHBlbmRDaGlsZChMLmM0KGcscikpCmE2LmFwcGVuZENoaWxkKGE4LmNyZWF0ZVRleHROb2RlKCIp
+IikpfWE2LmFwcGVuZENoaWxkKGE4LmNyZWF0ZVRleHROb2RlKCI6ICIpKQphNi5hcHBlbmRDaGlsZChh
+OC5jcmVhdGVUZXh0Tm9kZShhNC5hKSl9fX0sCkxIOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxv
+LG4sbSxsLGssaixpLGgsZyxmLGUsZD1kb2N1bWVudCxjPWQucXVlcnlTZWxlY3RvcigiLmVkaXQtbGlz
+dCAucGFuZWwtY29udGVudCIpCkoubDUoYywiIikKdD1kLmNyZWF0ZUVsZW1lbnQoInAiKQpzPXUuaApy
+PXMuYihjLmFwcGVuZENoaWxkKHQpKQpxPWIubGVuZ3RoCmlmKHE9PT0wKXIuYXBwZW5kQ2hpbGQoZC5j
+cmVhdGVUZXh0Tm9kZSgiTm8gcHJvcG9zZWQgZWRpdHMiKSkKZWxzZSByLmFwcGVuZENoaWxkKGQuY3Jl
+YXRlVGV4dE5vZGUoIiIrcSsiIHByb3Bvc2VkICIrTC5MeChxLCJlZGl0IikrIjoiKSkKdD1kLmNyZWF0
+ZUVsZW1lbnQoInVsIikKcD1zLmIoYy5hcHBlbmRDaGlsZCh0KSkKZm9yKHQ9Yi5sZW5ndGgsbz11Lmks
+bj11LlEsbT1uLkMoIn4oMSkiKSxsPXUuTSxuPW4uZCxrPTA7azxiLmxlbmd0aDtiLmxlbmd0aD09PXR8
+fCgwLEgubGspKGIpLCsrayl7aj1iW2tdCmk9ZC5jcmVhdGVFbGVtZW50KCJsaSIpCmg9cy5iKHAuYXBw
+ZW5kQ2hpbGQoaSkpCkouZFIoaCkuaSgwLCJlZGl0IikKaT1kLmNyZWF0ZUVsZW1lbnQoImEiKQpnPW8u
+YihoLmFwcGVuZENoaWxkKGkpKQpnLmNsYXNzTGlzdC5hZGQoImVkaXQtbGluayIpCmY9ai5jCmk9SC5k
+KGYpCmcuc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcoZykpLk8oIm9mZnNldCIp
+LGkpCmU9ai5hCmk9SC5kKGUpCmcuc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTco
+ZykpLk8oImxpbmUiKSxpKQpnLmFwcGVuZENoaWxkKGQuY3JlYXRlVGV4dE5vZGUoImxpbmUgIitILmQo
+ZSkpKQppPW0uYihuZXcgTC5FRShmLGUsYSkpCmwuYihudWxsKQpXLkpFKGcsImNsaWNrIixpLCExLG4p
+CmguYXBwZW5kQ2hpbGQoZC5jcmVhdGVUZXh0Tm9kZSgiOiAiK0guZChqLmIpKSl9TC5UMShudWxsKX0s
+CkZyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT13aW5kb3cubG9jYXRpb24scD1QLmhLKChxJiZD
+LkV4KS5nRHIocSkrSC5kKGEpKQpxPXUuegp0PVAuRmwodS5OLHEpCmlmKGIhPW51bGwpdC5ZKDAsIm9m
+ZnNldCIsSC5kKGIpKQppZihjIT1udWxsKXQuWSgwLCJsaW5lIixILmQoYykpCnA9cC5ubSgwLHQuYT09
+PTA/bnVsbDp0KQpzPXdpbmRvdy5oaXN0b3J5CnI9cC53KDApCnMudG9TdHJpbmcKcy5wdXNoU3RhdGUo
+bmV3IFAuQmYoW10sW10pLlB2KFAuRmwocSxxKSksIiIscil9LApFbjpmdW5jdGlvbihhKXt2YXIgdD1K
+LmJiKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENvbnRlbnQsIi8iKQppZihDLnhC
+Lm4oYSx0KSlyZXR1cm4gQy54Qi5HKGEsdC5sZW5ndGgpCmVsc2UgcmV0dXJuIGF9LApCWDpmdW5jdGlv
+bihhLGIpe3ZhciB0LHMscj17fQpyLmE9YQphPUwuRW4oYSkKci5hPWEKdD1kb2N1bWVudAp0LnF1ZXJ5
+U2VsZWN0b3IoIiN1bml0LW5hbWUiKS50ZXh0Q29udGVudD1hCnM9dS5oCkguRGgocyxzLCJUIiwicXVl
+cnlTZWxlY3RvckFsbCIpCnQ9bmV3IFcud3oodC5xdWVyeVNlbGVjdG9yQWxsKCIubmF2LXBhbmVsIC5u
+YXYtbGluayIpLHUuUykKdC5LKHQsbmV3IEwuVlMocikpfSwKQkU6ZnVuY3Rpb24oYSxiKXt2YXIgdD0i
+LnJlZ2lvbnMiLHM9ZG9jdW1lbnQscj1zLnF1ZXJ5U2VsZWN0b3IodCkscT1zLnF1ZXJ5U2VsZWN0b3Io
+Ii5jb2RlIikKSi50SChyLGIuYSwkLktHKCkpCkoudEgocSxiLmIsJC5LRygpKQpMLkxIKGEsYi5kKQpM
+LnZVKCkKTC55WCgiLmNvZGUiKQpMLnlYKHQpfSwKdFg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxw
+LG8sbixtLGwsayxqPWRvY3VtZW50LGk9ai5jcmVhdGVFbGVtZW50KCJ1bCIpLGg9dS5oLGc9aC5iKGEu
+YXBwZW5kQ2hpbGQoaSkpCmZvcihpPWIubGVuZ3RoLHQ9dS5NLHM9MDtzPGIubGVuZ3RoO2IubGVuZ3Ro
+PT09aXx8KDAsSC5saykoYiksKytzKXtyPWJbc10KcT1qLmNyZWF0ZUVsZW1lbnQoImxpIikKcD1oLmIo
+Zy5hcHBlbmRDaGlsZChxKSkKcT1KLlJFKHApCmlmKHIuYT09PUMuWTIpe3EuZ0QocCkuaSgwLCJkaXIi
+KQpxPWouY3JlYXRlRWxlbWVudCgic3BhbiIpCm89aC5iKHAuYXBwZW5kQ2hpbGQocSkpCnE9Si5SRShv
+KQpxLmdEKG8pLmkoMCwiYXJyb3ciKQpxLnNoZihvLCImI3gyNUJDOyIpCnE9ai5jcmVhdGVFbGVtZW50
+KCJzcGFuIikKSi5sNShoLmIocC5hcHBlbmRDaGlsZChxKSksIiYjeDFGNEMxOyIpCnAuYXBwZW5kQ2hp
+bGQoai5jcmVhdGVUZXh0Tm9kZShyLmIpKQpMLnRYKHAsci5jKQpMLmt6KG8pfWVsc2V7cS5zaGYocCwi
+JiN4MUY0QzQ7IikKcT1qLmNyZWF0ZUVsZW1lbnQoImEiKQpuPWguYihwLmFwcGVuZENoaWxkKHEpKQpx
+PUouUkUobikKcS5nRChuKS5pKDAsIm5hdi1saW5rIikKbi5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcg
+Vy5TeShuZXcgVy5pNyhuKSkuTygibmFtZSIpLHIuZCkKbi5zZXRBdHRyaWJ1dGUoImhyZWYiLHIuZSkK
+bi5hcHBlbmRDaGlsZChqLmNyZWF0ZVRleHROb2RlKHIuYikpCnE9cS5nVmwobikKbT1xLiR0aQptLkMo
+In4oMSkiKS5iKEwuWE4oKSkKdC5iKG51bGwpClcuSkUocS5hLHEuYixMLlhOKCksITEsbS5kKQpsPXIu
+ZgppZih0eXBlb2YgbCE9PSJudW1iZXIiKXJldHVybiBsLm9zKCkKaWYobD4wKXtxPWouY3JlYXRlRWxl
+bWVudCgic3BhbiIpCms9aC5iKHAuYXBwZW5kQ2hpbGQocSkpCkouZFIoaykuaSgwLCJlZGl0LWNvdW50
+IikKcT0iIitsKyIgIgppZihsPT09MSltPSJlZGl0IgplbHNlIG09ImVkaXRzIgprLnNldEF0dHJpYnV0
+ZSgidGl0bGUiLHErbSkKay5hcHBlbmRDaGlsZChqLmNyZWF0ZVRleHROb2RlKEMuam4udyhsKSkpfX19
+fSwKYzQ6ZnVuY3Rpb24oYSxiKXt2YXIgdD1kb2N1bWVudCxzPXQuY3JlYXRlRWxlbWVudCgiYSIpCnUu
+aS5iKHMpCnMuYXBwZW5kQ2hpbGQodC5jcmVhdGVUZXh0Tm9kZShILmQoYS5jKSsiOiIrSC5kKGEuYikp
+KQp0PUQubnIoYixhLmEpCnMuc2V0QXR0cmlidXRlKCJocmVmIiwkLm5VKCkubzUodCkpCnMuY2xhc3NM
+aXN0LmFkZCgibmF2LWxpbmsiKQpyZXR1cm4gc30sCmU6ZnVuY3Rpb24gZSgpe30sClZXOmZ1bmN0aW9u
+IFZXKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCm9aOmZ1bmN0aW9uIG9aKCl7fSwK
+anI6ZnVuY3Rpb24ganIoKXt9LApxbDpmdW5jdGlvbiBxbCgpe30sCkw6ZnVuY3Rpb24gTCgpe30sCld4
+OmZ1bmN0aW9uIFd4KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApBTzpmdW5jdGlvbiBBTygpe30sCmRO
+OmZ1bmN0aW9uIGROKCl7fSwKSG86ZnVuY3Rpb24gSG8oYSl7dGhpcy5hPWF9LAp4ejpmdW5jdGlvbiB4
+eihhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSUM6ZnVuY3Rpb24gSUMoKXt9LApMMTpmdW5jdGlvbiBM
+MSgpe30sCm5UOmZ1bmN0aW9uIG5UKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCkJa
+OmZ1bmN0aW9uIEJaKGEpe3RoaXMuYT1hfSwKR0g6ZnVuY3Rpb24gR0goKXt9LApEVDpmdW5jdGlvbiBE
+VCgpe30sCmVIOmZ1bmN0aW9uIGVIKGEpe3RoaXMuYT1hfSwKekQ6ZnVuY3Rpb24gekQoYSxiLGMsZCl7
+dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCk9FOmZ1bmN0aW9uIE9FKGEpe3RoaXMu
+YT1hfSwKVFc6ZnVuY3Rpb24gVFcoKXt9LAp4cjpmdW5jdGlvbiB4cihhKXt0aGlzLmE9YX0sCkVFOmZ1
+bmN0aW9uIEVFKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClFMOmZ1bmN0aW9uIFFM
+KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApWUzpmdW5jdGlvbiBWUyhhKXt0aGlzLmE9YX0sClhBOmZ1
+bmN0aW9uIFhBKCl7fSwKbUs6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG49SC5WTShbXSx1LmZo
+KQpmb3IodD1KLklUKHUuUi5iKGEpKTt0LkYoKTspe3M9dC5nbCgpCnI9Si5VNihzKQpxPUwucDIoSC55
+KHIucShzLCJ0eXBlIikpKQpwPUgueShyLnEocywibmFtZSIpKQpvPXIucShzLCJzdWJ0cmVlIikKbz1v
+PT1udWxsP251bGw6TC5tSyhvKQpDLk5tLmkobixuZXcgTC5aWihxLHAsbyxILnkoci5xKHMsInBhdGgi
+KSksSC55KHIucShzLCJocmVmIikpLEguU2Moci5xKHMsImVkaXRDb3VudCIpKSkpfXJldHVybiBufSwK
+cDI6ZnVuY3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2UiZGlyZWN0b3J5IjpyZXR1cm4gQy5ZMgpjYXNlImZp
+bGUiOnJldHVybiBDLnJmCmRlZmF1bHQ6dGhyb3cgSC5iKFAuUFYoIlVucmVjb2duaXplZCBuYXZpZ2F0
+aW9uIHRyZWUgbm9kZSB0eXBlOiAiK0guZChhKSkpfX0sClpaOmZ1bmN0aW9uIFpaKGEsYixjLGQsZSxm
+KXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwKeTg6ZnVuY3Rp
+b24geTgoYSl7dGhpcy5iPWF9LApJVjpmdW5jdGlvbiBJVihhLGIsYyxkKXt2YXIgXz10aGlzCl8uZD1h
+Cl8uZT1iCl8uZj1jCl8ucj1kfX0sTT17CllGOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4K
+Zm9yKHQ9Yi5sZW5ndGgscz0xO3M8dDsrK3Mpe2lmKGJbc109PW51bGx8fGJbcy0xXSE9bnVsbCljb250
+aW51ZQpmb3IoO3Q+PTE7dD1yKXtyPXQtMQppZihiW3JdIT1udWxsKWJyZWFrfXE9bmV3IFAuUm4oIiIp
+CnA9YSsiKCIKcS5hPXAKbz1ILnFDKGIsMCx0LEgudDYoYikuZCkKbj1vLiR0aQpuPXArbmV3IEguQTgo
+byxuLkMoInFVKGFMLkUpIikuYihuZXcgTS5ObygpKSxuLkMoIkE4PGFMLkUscVU+IikpLkgoMCwiLCAi
+KQpxLmE9bgpxLmE9bisoIik6IHBhcnQgIisocy0xKSsiIHdhcyBudWxsLCBidXQgcGFydCAiK3MrIiB3
+YXMgbm90LiIpCnRocm93IEguYihQLnhZKHEudygwKSkpfX0sCmxJOmZ1bmN0aW9uIGxJKGEpe3RoaXMu
+YT1hfSwKTWk6ZnVuY3Rpb24gTWkoKXt9LApxNzpmdW5jdGlvbiBxNygpe30sCk5vOmZ1bmN0aW9uIE5v
+KCl7fX0sWD17CkNMOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvPWIueFooYSkKYi5oSyhhKQpp
+ZihvIT1udWxsKWE9Si5LVihhLG8ubGVuZ3RoKQp0PXUucwpzPUguVk0oW10sdCkKcj1ILlZNKFtdLHQp
+CnQ9YS5sZW5ndGgKaWYodCE9PTAmJmIucjQoQy54Qi5XKGEsMCkpKXtpZigwPj10KXJldHVybiBILk9I
+KGEsMCkKQy5ObS5pKHIsYVswXSkKcT0xfWVsc2V7Qy5ObS5pKHIsIiIpCnE9MH1mb3IocD1xO3A8dDsr
+K3ApaWYoYi5yNChDLnhCLlcoYSxwKSkpe0MuTm0uaShzLEMueEIuTmooYSxxLHApKQpDLk5tLmkocixh
+W3BdKQpxPXArMX1pZihxPHQpe0MuTm0uaShzLEMueEIuRyhhLHEpKQpDLk5tLmkociwiIil9cmV0dXJu
+IG5ldyBYLldEKGIsbyxzLHIpfSwKV0Q6ZnVuY3Rpb24gV0QoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9
+YQpfLmI9YgpfLmQ9YwpfLmU9ZH0sCnFSOmZ1bmN0aW9uIHFSKGEpe3RoaXMuYT1hfSwKSlQ6ZnVuY3Rp
+b24oYSl7cmV0dXJuIG5ldyBYLmR2KGEpfSwKZHY6ZnVuY3Rpb24gZHYoYSl7dGhpcy5hPWF9fSxPPXsK
+Umg6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGk9bnVsbAppZihQLnVvKCkuZ0Zp
+KCkhPT0iZmlsZSIpcmV0dXJuICQuRWIoKQp0PVAudW8oKQppZighQy54Qi5UYyh0LmdJaSh0KSwiLyIp
+KXJldHVybiAkLkViKCkKcz1QLlBpKGksMCwwKQpyPVAuelIoaSwwLDApCnE9UC5PZShpLDAsMCwhMSkK
+cD1QLmxlKGksMCwwLGkpCm89UC50RyhpLDAsMCkKbj1QLndCKGkscykKbT1zPT09ImZpbGUiCmlmKHE9
+PW51bGwpdD1yLmxlbmd0aCE9PTB8fG4hPW51bGx8fG0KZWxzZSB0PSExCmlmKHQpcT0iIgp0PXE9PW51
+bGwKbD0hdAprPVAua2EoImEvYiIsMCwzLGkscyxsKQpqPXMubGVuZ3RoPT09MAppZihqJiZ0JiYhQy54
+Qi5uKGssIi8iKSlrPVAud0Yoaywhanx8bCkKZWxzZSBrPVAueGUoaykKaWYobmV3IFAuRG4ocyxyLHQm
+JkMueEIubihrLCIvLyIpPyIiOnEsbixrLHAsbykudDQoKT09PSJhXFxiIilyZXR1cm4gJC5LaygpCnJl
+dHVybiAkLmJEKCl9LAp6TDpmdW5jdGlvbiB6TCgpe319LEU9e09GOmZ1bmN0aW9uIE9GKGEsYixjKXt0
+aGlzLmQ9YQp0aGlzLmU9Ygp0aGlzLmY9Y319LEY9e3J1OmZ1bmN0aW9uIHJ1KGEsYixjLGQpe3ZhciBf
+PXRoaXMKXy5kPWEKXy5lPWIKXy5mPWMKXy5yPWR9fSxEPXsKUlg6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9
+UC51bygpCmlmKEouUk0ociwkLkk2KSlyZXR1cm4gJC5GZgokLkk2PXIKaWYoJC5IaygpPT0kLkViKCkp
+cmV0dXJuICQuRmY9ci5aSSgiLiIpLncoMCkKZWxzZXt0PXIudDQoKQpzPXQubGVuZ3RoLTEKcmV0dXJu
+ICQuRmY9cz09PTA/dDpDLnhCLk5qKHQsMCxzKX19LApucjpmdW5jdGlvbihhLGIpe3ZhciB0PW51bGwK
+cmV0dXJuICQublUoKS5xNygwLGEsYix0LHQsdCx0LHQsdCl9fQp2YXIgdz1bQyxILEosUCxXLFUsQixU
+LEwsTSxYLE8sRSxGLERdCmh1bmtIZWxwZXJzLnNldEZ1bmN0aW9uTmFtZXNJZk5lY2Vzc2FyeSh3KQp2
+YXIgJD17fQpILmVvLnByb3RvdHlwZT17fQpKLnZCLnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7
+cmV0dXJuIGE9PT1ifSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBILmVRKGEpfSwKdzpmdW5jdGlvbihh
+KXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5kKEguTShhKSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt1
+Lm8uYihiKQp0aHJvdyBILmIoUC5scihhLGIuZ1dhKCksYi5nbmQoKSxiLmdWbSgpKSl9fQpKLnlFLnBy
+b3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCmdpTzpmdW5jdGlvbihhKXty
+ZXR1cm4gYT81MTkwMTg6MjE4MTU5fSwKJGlhMjoxfQpKLllFLnByb3RvdHlwZT17CkROOmZ1bmN0aW9u
+KGEsYil7cmV0dXJuIG51bGw9PWJ9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiJudWxsIn0sCmdpTzpmdW5j
+dGlvbihhKXtyZXR1cm4gMH0sCmU3OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuU2ooYSx1Lm8uYihi
+KSl9LAokaWM4OjF9CkouTUYucHJvdG90eXBlPXsKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiAwfSwKdzpm
+dW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGl2bToxfQpKLmlDLnByb3RvdHlwZT17fQpKLmtk
+LnByb3RvdHlwZT17fQpKLmM1LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQ9YVskLncoKV0K
+aWYodD09bnVsbClyZXR1cm4gdGhpcy50KGEpCnJldHVybiJKYXZhU2NyaXB0IGZ1bmN0aW9uIGZvciAi
+K0guZChKLmoodCkpfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm57ZnVuYzoxLG9wdDpbLCwsLCwsLCwsLCws
+LCwsLF19fSwKJGlFSDoxfQpKLmpkLnByb3RvdHlwZT17Cmk6ZnVuY3Rpb24oYSxiKXtILnQ2KGEpLmQu
+YihiKQppZighIWEuZml4ZWQkbGVuZ3RoKUgudmgoUC5MNCgiYWRkIikpCmEucHVzaChiKX0sClc0OmZ1
+bmN0aW9uKGEsYil7dmFyIHQKaWYoISFhLmZpeGVkJGxlbmd0aClILnZoKFAuTDQoInJlbW92ZUF0Iikp
+CnQ9YS5sZW5ndGgKaWYoYj49dCl0aHJvdyBILmIoUC54KGIsbnVsbCkpCnJldHVybiBhLnNwbGljZShi
+LDEpWzBdfSwKVUc6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscgpILnQ2KGEpLkMoImNYPDE+IikuYihj
+KQppZighIWEuZml4ZWQkbGVuZ3RoKUgudmgoUC5MNCgiaW5zZXJ0QWxsIikpCnQ9YS5sZW5ndGgKUC53
+QShiLDAsdCwiaW5kZXgiKQpzPWMubGVuZ3RoCnRoaXMuc0EoYSx0K3MpCnI9YitzCnRoaXMuWVcoYSxy
+LGEubGVuZ3RoLGEsYikKdGhpcy52ZyhhLGIscixjKX0sCm12OmZ1bmN0aW9uKGEpe2lmKCEhYS5maXhl
+ZCRsZW5ndGgpSC52aChQLkw0KCJyZW1vdmVMYXN0IikpCmlmKGEubGVuZ3RoPT09MCl0aHJvdyBILmIo
+SC5IWShhLC0xKSkKcmV0dXJuIGEucG9wKCl9LApGVjpmdW5jdGlvbihhLGIpe3ZhciB0CkgudDYoYSku
+QygiY1g8MT4iKS5iKGIpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC52aChQLkw0KCJhZGRBbGwiKSkKZm9y
+KHQ9Si5JVChiKTt0LkYoKTspYS5wdXNoKHQuZ2woKSl9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpI
+LnQ2KGEpLkMoIn4oMSkiKS5iKGIpCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKXtiLiQxKGFbc10p
+CmlmKGEubGVuZ3RoIT09dCl0aHJvdyBILmIoUC5hNChhKSl9fSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciB0PUgudDYoYSkKcmV0dXJuIG5ldyBILkE4KGEsdC5LcShjKS5DKCIxKDIpIikuYihiKSx0LkMoIkA8
+MT4iKS5LcShjKS5DKCJBODwxLDI+IikpfSwKSDpmdW5jdGlvbihhLGIpe3ZhciB0LHM9bmV3IEFycmF5
+KGEubGVuZ3RoKQpzLmZpeGVkJGxlbmd0aD1BcnJheQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KXRoaXMu
+WShzLHQsSC5kKGFbdF0pKQpyZXR1cm4gcy5qb2luKGIpfSwKTjA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHQscyxyCmQuYihiKQpILnQ2KGEpLktxKGQpLkMoIjEoMSwyKSIpLmIoYykKdD1hLmxlbmd0aApmb3Io
+cz1iLHI9MDtyPHQ7KytyKXtzPWMuJDIocyxhW3JdKQppZihhLmxlbmd0aCE9PXQpdGhyb3cgSC5iKFAu
+YTQoYSkpfXJldHVybiBzfSwKRTpmdW5jdGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJu
+IEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCkQ2OmZ1bmN0aW9uKGEsYixjKXtpZihiPDB8fGI+YS5sZW5n
+dGgpdGhyb3cgSC5iKFAuVEUoYiwwLGEubGVuZ3RoLCJzdGFydCIsbnVsbCkpCmlmKGM8Ynx8Yz5hLmxl
+bmd0aCl0aHJvdyBILmIoUC5URShjLGIsYS5sZW5ndGgsImVuZCIsbnVsbCkpCmlmKGI9PT1jKXJldHVy
+biBILlZNKFtdLEgudDYoYSkpCnJldHVybiBILlZNKGEuc2xpY2UoYixjKSxILnQ2KGEpKX0sCmdyWjpm
+dW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aAppZih0PjApcmV0dXJuIGFbdC0xXQp0aHJvdyBILmIoSC5X
+cCgpKX0sCllXOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyPUgudDYoYSkKci5DKCJjWDwxPiIp
+LmIoZCkKaWYoISFhLmltbXV0YWJsZSRsaXN0KUgudmgoUC5MNCgic2V0UmFuZ2UiKSkKUC5qQihiLGMs
+YS5sZW5ndGgpCnQ9Yy1iCmlmKHQ9PT0wKXJldHVybgpQLmsxKGUsInNraXBDb3VudCIpCnIuQygiek08
+MT4iKS5iKGQpCnI9Si5VNihkKQppZihlK3Q+ci5nQShkKSl0aHJvdyBILmIoSC5hcigpKQppZihlPGIp
+Zm9yKHM9dC0xO3M+PTA7LS1zKWFbYitzXT1yLnEoZCxlK3MpCmVsc2UgZm9yKHM9MDtzPHQ7KytzKWFb
+YitzXT1yLnEoZCxlK3MpfSwKdmc6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIHRoaXMuWVcoYSxiLGMs
+ZCwwKX0sClZyOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILnQ2KGEpLkMoImEyKDEpIikuYihiKQp0PWEu
+bGVuZ3RoCmZvcihzPTA7czx0Oysrcyl7aWYoSC5vVChiLiQxKGFbc10pKSlyZXR1cm4hMAppZihhLmxl
+bmd0aCE9PXQpdGhyb3cgSC5iKFAuYTQoYSkpfXJldHVybiExfSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIg
+dApmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KWlmKEouUk0oYVt0XSxiKSlyZXR1cm4hMApyZXR1cm4hMX0s
+Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UoYSwiWyIsIl0iKX0sCmdrejpmdW5jdGlvbihhKXtyZXR1
+cm4gbmV3IEoubTEoYSxhLmxlbmd0aCxILnQ2KGEpLkMoIm0xPDE+IikpfSwKZ2lPOmZ1bmN0aW9uKGEp
+e3JldHVybiBILmVRKGEpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKc0E6ZnVuY3Rp
+b24oYSxiKXtpZighIWEuZml4ZWQkbGVuZ3RoKUgudmgoUC5MNCgic2V0IGxlbmd0aCIpKQppZihiPDAp
+dGhyb3cgSC5iKFAuVEUoYiwwLG51bGwsIm5ld0xlbmd0aCIsbnVsbCkpCmEubGVuZ3RoPWJ9LApxOmZ1
+bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj1hLmxlbmd0aHx8YjwwKXRocm93IEguYihILkhZKGEsYikp
+CnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7SC50NihhKS5kLmIoYykKaWYoISFhLmltbXV0
+YWJsZSRsaXN0KUgudmgoUC5MNCgiaW5kZXhlZCBzZXQiKSkKaWYoYj49YS5sZW5ndGh8fGI8MCl0aHJv
+dyBILmIoSC5IWShhLGIpKQphW2JdPWN9LAokaWNYOjEsCiRpek06MX0KSi5Qby5wcm90b3R5cGU9e30K
+Si5tMS5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7
+dmFyIHQscz10aGlzLHI9cy5hLHE9ci5sZW5ndGgKaWYocy5iIT09cSl0aHJvdyBILmIoSC5sayhyKSkK
+dD1zLmMKaWYodD49cSl7cy5zTShudWxsKQpyZXR1cm4hMX1zLnNNKHJbdF0pOysrcy5jCnJldHVybiEw
+fSwKc006ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmQuYihhKX0sCiRpQW46MX0KSi5xSS5wcm90
+b3R5cGU9ewp5dTpmdW5jdGlvbihhKXt2YXIgdAppZihhPj0tMjE0NzQ4MzY0OCYmYTw9MjE0NzQ4MzY0
+NylyZXR1cm4gYXwwCmlmKGlzRmluaXRlKGEpKXt0PWE8MD9NYXRoLmNlaWwoYSk6TWF0aC5mbG9vcihh
+KQpyZXR1cm4gdCswfXRocm93IEguYihQLkw0KCIiK2ErIi50b0ludCgpIikpfSwKelE6ZnVuY3Rpb24o
+YSl7aWYoYT4wKXtpZihhIT09MS8wKXJldHVybiBNYXRoLnJvdW5kKGEpfWVsc2UgaWYoYT4tMS8wKXJl
+dHVybiAwLU1hdGgucm91bmQoMC1hKQp0aHJvdyBILmIoUC5MNCgiIithKyIucm91bmQoKSIpKX0sClda
+OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKaWYoYjwyfHxiPjM2KXRocm93IEguYihQLlRFKGIsMiwz
+NiwicmFkaXgiLG51bGwpKQp0PWEudG9TdHJpbmcoYikKaWYoQy54Qi5tKHQsdC5sZW5ndGgtMSkhPT00
+MSlyZXR1cm4gdApzPS9eKFtcZGEtel0rKSg/OlwuKFtcZGEtel0rKSk/XChlXCsoXGQrKVwpJC8uZXhl
+Yyh0KQppZihzPT1udWxsKUgudmgoUC5MNCgiVW5leHBlY3RlZCB0b1N0cmluZyByZXN1bHQ6ICIrdCkp
+CnI9cy5sZW5ndGgKaWYoMT49cilyZXR1cm4gSC5PSChzLDEpCnQ9c1sxXQppZigzPj1yKXJldHVybiBI
+Lk9IKHMsMykKcT0rc1szXQpyPXNbMl0KaWYociE9bnVsbCl7dCs9cgpxLT1yLmxlbmd0aH1yZXR1cm4g
+dCtDLnhCLkl4KCIwIixxKX0sCnc6ZnVuY3Rpb24oYSl7aWYoYT09PTAmJjEvYTwwKXJldHVybiItMC4w
+IgplbHNlIHJldHVybiIiK2F9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1hfDAKaWYoYT09
+PXApcmV0dXJuIDUzNjg3MDkxMSZwCnQ9TWF0aC5hYnMoYSkKcz1NYXRoLmxvZyh0KS8wLjY5MzE0NzE4
+MDU1OTk0NTN8MApyPU1hdGgucG93KDIscykKcT10PDE/dC9yOnIvdApyZXR1cm4gNTM2ODcwOTExJigo
+cSo5MDA3MTk5MjU0NzQwOTkyfDApKyhxKjM1NDIyNDMxODExNzY1MjF8MCkpKjU5OTE5NytzKjEyNTl9
+LAp6WTpmdW5jdGlvbihhLGIpe3ZhciB0PWElYgppZih0PT09MClyZXR1cm4gMAppZih0PjApcmV0dXJu
+IHQKaWYoYjwwKXJldHVybiB0LWIKZWxzZSByZXR1cm4gdCtifSwKd0c6ZnVuY3Rpb24oYSxiKXt2YXIg
+dAppZihhPjApdD10aGlzLnAzKGEsYikKZWxzZXt0PWI+MzE/MzE6Ygp0PWE+PnQ+Pj4wfXJldHVybiB0
+fSwKYmY6ZnVuY3Rpb24oYSxiKXtpZihiPDApdGhyb3cgSC5iKEgudEwoYikpCnJldHVybiB0aGlzLnAz
+KGEsYil9LApwMzpmdW5jdGlvbihhLGIpe3JldHVybiBiPjMxPzA6YT4+PmJ9LAokaUNQOjEsCiRpRks6
+MX0KSi51ci5wcm90b3R5cGU9eyRpS046MX0KSi5WQS5wcm90b3R5cGU9e30KSi5Eci5wcm90b3R5cGU9
+ewptOmZ1bmN0aW9uKGEsYil7aWYoYjwwKXRocm93IEguYihILkhZKGEsYikpCmlmKGI+PWEubGVuZ3Ro
+KUgudmgoSC5IWShhLGIpKQpyZXR1cm4gYS5jaGFyQ29kZUF0KGIpfSwKVzpmdW5jdGlvbihhLGIpe2lm
+KGI+PWEubGVuZ3RoKXRocm93IEguYihILkhZKGEsYikpCnJldHVybiBhLmNoYXJDb2RlQXQoYil9LApk
+ZDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC51bihiLGEsMCl9LApoOmZ1bmN0aW9uKGEsYil7aWYo
+dHlwZW9mIGIhPSJzdHJpbmciKXRocm93IEguYihQLkwzKGIsbnVsbCxudWxsKSkKcmV0dXJuIGErYn0s
+ClRjOmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5sZW5ndGgscz1hLmxlbmd0aAppZih0PnMpcmV0dXJuITEK
+cmV0dXJuIGI9PT10aGlzLkcoYSxzLXQpfSwKaTc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscwpjPVAu
+akIoYixjLGEubGVuZ3RoKQp0PWEuc3Vic3RyaW5nKDAsYikKcz1hLnN1YnN0cmluZyhjKQpyZXR1cm4g
+dCtkK3N9LApRaTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYoIUgub2soYykpSC52aChILnRMKGMpKQpp
+Zih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBjLkooKQppZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cg
+SC5iKFAuVEUoYywwLGEubGVuZ3RoLG51bGwsbnVsbCkpCnQ9YytiLmxlbmd0aAppZih0PmEubGVuZ3Ro
+KXJldHVybiExCnJldHVybiBiPT09YS5zdWJzdHJpbmcoYyx0KX0sCm46ZnVuY3Rpb24oYSxiKXtyZXR1
+cm4gdGhpcy5RaShhLGIsMCl9LApOajpmdW5jdGlvbihhLGIsYyl7aWYoIUgub2soYikpSC52aChILnRM
+KGIpKQppZihjPT1udWxsKWM9YS5sZW5ndGgKaWYodHlwZW9mIGIhPT0ibnVtYmVyIilyZXR1cm4gYi5K
+KCkKaWYoYjwwKXRocm93IEguYihQLngoYixudWxsKSkKaWYoYj5jKXRocm93IEguYihQLngoYixudWxs
+KSkKaWYoYz5hLmxlbmd0aCl0aHJvdyBILmIoUC54KGMsbnVsbCkpCnJldHVybiBhLnN1YnN0cmluZyhi
+LGMpfSwKRzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLk5qKGEsYixudWxsKX0sCmhjOmZ1bmN0aW9u
+KGEpe3JldHVybiBhLnRvTG93ZXJDYXNlKCl9LApiUzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLnRy
+aW0oKSxwPXEubGVuZ3RoCmlmKHA9PT0wKXJldHVybiBxCmlmKHRoaXMuVyhxLDApPT09MTMzKXt0PUou
+bW0ocSwxKQppZih0PT09cClyZXR1cm4iIn1lbHNlIHQ9MApzPXAtMQpyPXRoaXMubShxLHMpPT09MTMz
+P0ouYzEocSxzKTpwCmlmKHQ9PT0wJiZyPT09cClyZXR1cm4gcQpyZXR1cm4gcS5zdWJzdHJpbmcodCxy
+KX0sCkl4OmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZigwPj1iKXJldHVybiIiCmlmKGI9PT0xfHxhLmxl
+bmd0aD09PTApcmV0dXJuIGEKaWYoYiE9PWI+Pj4wKXRocm93IEguYihDLkVxKQpmb3IodD1hLHM9IiI7
+ITA7KXtpZigoYiYxKT09PTEpcz10K3MKYj1iPj4+MQppZihiPT09MClicmVhawp0Kz10fXJldHVybiBz
+fSwKWFU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKGM8MHx8Yz5hLmxlbmd0aCl0aHJvdyBILmIoUC5U
+RShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKdD1hLmluZGV4T2YoYixjKQpyZXR1cm4gdH0sCk9ZOmZ1
+bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuWFUoYSxiLDApfSwKUGs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
+LHMKaWYoYz09bnVsbCljPWEubGVuZ3RoCmVsc2UgaWYoYzwwfHxjPmEubGVuZ3RoKXRocm93IEguYihQ
+LlRFKGMsMCxhLmxlbmd0aCxudWxsLG51bGwpKQp0PWIubGVuZ3RoCnM9YS5sZW5ndGgKaWYoYyt0PnMp
+Yz1zLXQKcmV0dXJuIGEubGFzdEluZGV4T2YoYixjKX0sCmNuOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRo
+aXMuUGsoYSxiLG51bGwpfSwKSXM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PWEubGVuZ3RoCmlmKGM+dCl0
+aHJvdyBILmIoUC5URShjLDAsdCxudWxsLG51bGwpKQpyZXR1cm4gSC5tMihhLGIsYyl9LAp0ZzpmdW5j
+dGlvbihhLGIpe3JldHVybiB0aGlzLklzKGEsYiwwKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGF9LApn
+aU86ZnVuY3Rpb24oYSl7dmFyIHQscyxyCmZvcih0PWEubGVuZ3RoLHM9MCxyPTA7cjx0Oysrcil7cz01
+MzY4NzA5MTEmcythLmNoYXJDb2RlQXQocikKcz01MzY4NzA5MTEmcysoKDUyNDI4NyZzKTw8MTApCnNe
+PXM+PjZ9cz01MzY4NzA5MTEmcysoKDY3MTA4ODYzJnMpPDwzKQpzXj1zPj4xMQpyZXR1cm4gNTM2ODcw
+OTExJnMrKCgxNjM4MyZzKTw8MTUpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpm
+dW5jdGlvbihhLGIpe0guU2MoYikKaWYoYj49YS5sZW5ndGh8fCExKXRocm93IEguYihILkhZKGEsYikp
+CnJldHVybiBhW2JdfSwKJGl2WDoxLAokaXFVOjF9CkgucWoucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEMueEIubSh0aGlz
+LmEsSC5TYyhiKSl9fQpILmJRLnByb3RvdHlwZT17fQpILmFMLnByb3RvdHlwZT17CmdrejpmdW5jdGlv
+bihhKXt2YXIgdD10aGlzCnJldHVybiBuZXcgSC5hNyh0LHQuZ0EodCksSC5MaCh0KS5DKCJhNzxhTC5F
+PiIpKX0sCkg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscT10aGlzLHA9cS5nQShxKQppZihiLmxlbmd0
+aCE9PTApe2lmKHA9PT0wKXJldHVybiIiCnQ9SC5kKHEuRSgwLDApKQppZihwIT09cS5nQShxKSl0aHJv
+dyBILmIoUC5hNChxKSkKZm9yKHM9dCxyPTE7cjxwOysrcil7cz1zK2IrSC5kKHEuRSgwLHIpKQppZihw
+IT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSl9cmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9
+ZWxzZXtmb3Iocj0wLHM9IiI7cjxwOysrcil7cys9SC5kKHEuRSgwLHIpKQppZihwIT09cS5nQShxKSl0
+aHJvdyBILmIoUC5hNChxKSl9cmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9fSwKZXY6ZnVuY3Rp
+b24oYSxiKXtyZXR1cm4gdGhpcy5HRygwLEguTGgodGhpcykuQygiYTIoYUwuRSkiKS5iKGIpKX19Ckgu
+bkgucHJvdG90eXBlPXsKZ1VEOmZ1bmN0aW9uKCl7dmFyIHQ9Si5IbSh0aGlzLmEpLHM9dGhpcy5jCmlm
+KHM9PW51bGx8fHM+dClyZXR1cm4gdApyZXR1cm4gc30sCmdBczpmdW5jdGlvbigpe3ZhciB0PUouSG0o
+dGhpcy5hKSxzPXRoaXMuYgppZihzPnQpcmV0dXJuIHQKcmV0dXJuIHN9LApnQTpmdW5jdGlvbihhKXt2
+YXIgdCxzPUouSG0odGhpcy5hKSxyPXRoaXMuYgppZihyPj1zKXJldHVybiAwCnQ9dGhpcy5jCmlmKHQ9
+PW51bGx8fHQ+PXMpcmV0dXJuIHMtcgppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkhOKCkK
+cmV0dXJuIHQtcn0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMscj1zLmdBcygpK2IKaWYoYj49
+MCl7dD1zLmdVRCgpCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIEgucFkodCkKdD1yPj10fWVs
+c2UgdD0hMAppZih0KXRocm93IEguYihQLkNmKGIscywiaW5kZXgiLG51bGwsbnVsbCkpCnJldHVybiBK
+LkFNKHMuYSxyKX19CkguYTcucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwK
+RjpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcyxyPXMuYSxxPUouVTYocikscD1xLmdBKHIpCmlmKHMuYiE9
+PXApdGhyb3cgSC5iKFAuYTQocikpCnQ9cy5jCmlmKHQ+PXApe3Muc0kobnVsbCkKcmV0dXJuITF9cy5z
+SShxLkUocix0KSk7KytzLmMKcmV0dXJuITB9LApzSTpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGku
+ZC5iKGEpfSwKJGlBbjoxfQpILkE4LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBKLkht
+KHRoaXMuYSl9LApFOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYi4kMShKLkFNKHRoaXMuYSxiKSl9
+fQpILlU1LnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguU08oSi5JVCh0aGlz
+LmEpLHRoaXMuYix0aGlzLiR0aS5DKCJTTzwxPiIpKX19CkguU08ucHJvdG90eXBlPXsKRjpmdW5jdGlv
+bigpe3ZhciB0LHMKZm9yKHQ9dGhpcy5hLHM9dGhpcy5iO3QuRigpOylpZihILm9UKHMuJDEodC5nbCgp
+KSkpcmV0dXJuITAKcmV0dXJuITF9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmEuZ2woKX19Ckgu
+U1UucHJvdG90eXBlPXt9CkguUmUucHJvdG90eXBlPXsKWTpmdW5jdGlvbihhLGIsYyl7SC5MaCh0aGlz
+KS5DKCJSZS5FIikuYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSBhbiB1bm1vZGlmaWFi
+bGUgbGlzdCIpKX19CkguWEMucHJvdG90eXBlPXt9Ckgud3YucHJvdG90eXBlPXsKZ2lPOmZ1bmN0aW9u
+KGEpe3ZhciB0PXRoaXMuX2hhc2hDb2RlCmlmKHQhPW51bGwpcmV0dXJuIHQKdD01MzY4NzA5MTEmNjY0
+NTk3KkouaGYodGhpcy5hKQp0aGlzLl9oYXNoQ29kZT10CnJldHVybiB0fSwKdzpmdW5jdGlvbihhKXty
+ZXR1cm4nU3ltYm9sKCInK0guZCh0aGlzLmEpKyciKSd9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51
+bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBILnd2JiZ0aGlzLmE9PWIuYX0sCiRpR0Q6MX0K
+SC5QRC5wcm90b3R5cGU9e30KSC5XVS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLm5P
+KHRoaXMpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5MaCh0aGlzKQp0LmQuYihiKQp0LmNoWzFd
+LmIoYykKcmV0dXJuIEguZGMoKX0sCiRpWjA6MX0KSC5MUC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihh
+KXtyZXR1cm4gdGhpcy5hfSwKeDQ6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGEhPSJzdHJpbmciKXJldHVy
+biExCmlmKCJfX3Byb3RvX18iPT09YSlyZXR1cm4hMQpyZXR1cm4gdGhpcy5iLmhhc093blByb3BlcnR5
+KGEpfSwKcTpmdW5jdGlvbihhLGIpe2lmKCF0aGlzLng0KGIpKXJldHVybgpyZXR1cm4gdGhpcy5xUChi
+KX0sCnFQOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJbSC55KGEpXX0sCks6ZnVuY3Rpb24oYSxiKXt2
+YXIgdCxzLHIscSxwPUguTGgodGhpcykKcC5DKCJ+KDEsMikiKS5iKGIpCnQ9dGhpcy5jCmZvcihzPXQu
+bGVuZ3RoLHA9cC5jaFsxXSxyPTA7cjxzOysrcil7cT10W3JdCmIuJDIocSxwLmIodGhpcy5xUChxKSkp
+fX19CkguTEkucHJvdG90eXBlPXsKZ1dhOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5hCnJldHVybiB0fSwK
+Z25kOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD10aGlzCmlmKHAuYz09PTEpcmV0dXJuIEMuaFUKdD1w
+LmQKcz10Lmxlbmd0aC1wLmUubGVuZ3RoLXAuZgppZihzPT09MClyZXR1cm4gQy5oVQpyPVtdCmZvcihx
+PTA7cTxzOysrcSl7aWYocT49dC5sZW5ndGgpcmV0dXJuIEguT0godCxxKQpyLnB1c2godFtxXSl9cmV0
+dXJuIEouekMocil9LApnVm06ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9dGhpcwppZihs
+LmMhPT0wKXJldHVybiBDLkNNCnQ9bC5lCnM9dC5sZW5ndGgKcj1sLmQKcT1yLmxlbmd0aC1zLWwuZgpp
+ZihzPT09MClyZXR1cm4gQy5DTQpwPW5ldyBILk41KHUuZW8pCmZvcihvPTA7bzxzOysrbyl7aWYobz49
+dC5sZW5ndGgpcmV0dXJuIEguT0godCxvKQpuPXRbb10KbT1xK28KaWYobTwwfHxtPj1yLmxlbmd0aCly
+ZXR1cm4gSC5PSChyLG0pCnAuWSgwLG5ldyBILnd2KG4pLHJbbV0pfXJldHVybiBuZXcgSC5QRChwLHUu
+Z0YpfSwKJGl2UToxfQpILkNqLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQKSC55KGEp
+CnQ9dGhpcy5hCnQuYj10LmIrIiQiK0guZChhKQpDLk5tLmkodGhpcy5iLGEpCkMuTm0uaSh0aGlzLmMs
+Yik7Kyt0LmF9LAokUzoxM30KSC5aci5wcm90b3R5cGU9ewpxUzpmdW5jdGlvbihhKXt2YXIgdCxzLHI9
+dGhpcyxxPW5ldyBSZWdFeHAoci5hKS5leGVjKGEpCmlmKHE9PW51bGwpcmV0dXJuCnQ9T2JqZWN0LmNy
+ZWF0ZShudWxsKQpzPXIuYgppZihzIT09LTEpdC5hcmd1bWVudHM9cVtzKzFdCnM9ci5jCmlmKHMhPT0t
+MSl0LmFyZ3VtZW50c0V4cHI9cVtzKzFdCnM9ci5kCmlmKHMhPT0tMSl0LmV4cHI9cVtzKzFdCnM9ci5l
+CmlmKHMhPT0tMSl0Lm1ldGhvZD1xW3MrMV0Kcz1yLmYKaWYocyE9PS0xKXQucmVjZWl2ZXI9cVtzKzFd
+CnJldHVybiB0fX0KSC5XMC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYgppZih0
+PT1udWxsKXJldHVybiJOb1N1Y2hNZXRob2RFcnJvcjogIitILmQodGhpcy5hKQpyZXR1cm4iTm9TdWNo
+TWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciK3QrIicgb24gbnVsbCJ9fQpILmF6LnByb3Rv
+dHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLHI9Ik5vU3VjaE1ldGhvZEVycm9yOiBtZXRo
+b2Qgbm90IGZvdW5kOiAnIixxPXMuYgppZihxPT1udWxsKXJldHVybiJOb1N1Y2hNZXRob2RFcnJvcjog
+IitILmQocy5hKQp0PXMuYwppZih0PT1udWxsKXJldHVybiByK3ErIicgKCIrSC5kKHMuYSkrIikiCnJl
+dHVybiByK3ErIicgb24gJyIrdCsiJyAoIitILmQocy5hKSsiKSJ9fQpILnZWLnByb3RvdHlwZT17Cnc6
+ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0Lmxlbmd0aD09PTA/IkVycm9yIjoiRXJyb3I6
+ICIrdH19CkguYnEucHJvdG90eXBlPXt9CkguQW0ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7aWYo
+dS5iVS5jKGEpKWlmKGEuJHRocm93bkpzRXJyb3I9PW51bGwpYS4kdGhyb3duSnNFcnJvcj10aGlzLmEK
+cmV0dXJuIGF9LAokUzozfQpILlhPLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlz
+LmIKaWYocyE9bnVsbClyZXR1cm4gcwpzPXRoaXMuYQp0PXMhPT1udWxsJiZ0eXBlb2Ygcz09PSJvYmpl
+Y3QiP3Muc3RhY2s6bnVsbApyZXR1cm4gdGhpcy5iPXQ9PW51bGw/IiI6dH0sCiRpR3o6MX0KSC5UcC5w
+cm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuY29uc3RydWN0b3Iscz10PT1udWxsP251
+bGw6dC5uYW1lCnJldHVybiJDbG9zdXJlICciK0guTlEocz09bnVsbD8idW5rbm93biI6cykrIicifSwK
+JGlFSDoxLApnUWw6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc30sCiRDOiIkMSIsCiRSOjEsCiREOm51bGx9
+CkgubGMucHJvdG90eXBlPXt9CkguengucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlz
+LiRzdGF0aWNfbmFtZQppZih0PT1udWxsKXJldHVybiJDbG9zdXJlIG9mIHVua25vd24gc3RhdGljIG1l
+dGhvZCIKcmV0dXJuIkNsb3N1cmUgJyIrSC5OUSh0KSsiJyJ9fQpILnJULnByb3RvdHlwZT17CkROOmZ1
+bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwppZihiPT1udWxsKXJldHVybiExCmlmKHQ9PT1iKXJldHVybiEw
+CmlmKCEoYiBpbnN0YW5jZW9mIEguclQpKXJldHVybiExCnJldHVybiB0LmE9PT1iLmEmJnQuYj09PWIu
+YiYmdC5jPT09Yi5jfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5jCmlmKHM9PW51bGwpdD1I
+LmVRKHRoaXMuYSkKZWxzZSB0PXR5cGVvZiBzIT09Im9iamVjdCI/Si5oZihzKTpILmVRKHMpCnJldHVy
+bih0XkguZVEodGhpcy5iKSk+Pj4wfSwKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmMKaWYodD09bnVs
+bCl0PXRoaXMuYQpyZXR1cm4iQ2xvc3VyZSAnIitILmQodGhpcy5kKSsiJyBvZiAiKygiSW5zdGFuY2Ug
+b2YgJyIrSC5kKEguTSh0KSkrIiciKX19CkguRXEucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1
+cm4iUnVudGltZUVycm9yOiAiK0guZCh0aGlzLmEpfX0KSC5rWS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9u
+KGEpe3JldHVybiJBc3NlcnRpb24gZmFpbGVkOiAiK1AucCh0aGlzLmEpfX0KSC5ONS5wcm90b3R5cGU9
+ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKZ1Y6ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEgu
+aTUodGhpcyxILkxoKHRoaXMpLkMoImk1PDE+IikpfSwKeDQ6ZnVuY3Rpb24oYSl7dmFyIHQscwppZih0
+eXBlb2YgYT09InN0cmluZyIpe3Q9dGhpcy5iCmlmKHQ9PW51bGwpcmV0dXJuITEKcmV0dXJuIHRoaXMu
+WHUodCxhKX1lbHNle3M9dGhpcy5DWChhKQpyZXR1cm4gc319LApDWDpmdW5jdGlvbihhKXt2YXIgdD10
+aGlzLmQKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5GaCh0aGlzLkJ0KHQsSi5oZihhKSYw
+eDNmZmZmZmYpLGEpPj0wfSwKcTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9dGhpcwppZih0eXBl
+b2YgYj09InN0cmluZyIpe3Q9cC5iCmlmKHQ9PW51bGwpcmV0dXJuCnM9cC5qMih0LGIpCnI9cz09bnVs
+bD9udWxsOnMuYgpyZXR1cm4gcn1lbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGImMHgzZmZmZmZm
+KT09PWIpe3E9cC5jCmlmKHE9PW51bGwpcmV0dXJuCnM9cC5qMihxLGIpCnI9cz09bnVsbD9udWxsOnMu
+YgpyZXR1cm4gcn1lbHNlIHJldHVybiBwLmFhKGIpfSwKYWE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRo
+aXMuZAppZihyPT1udWxsKXJldHVybgp0PXRoaXMuQnQocixKLmhmKGEpJjB4M2ZmZmZmZikKcz10aGlz
+LkZoKHQsYSkKaWYoczwwKXJldHVybgpyZXR1cm4gdFtzXS5ifSwKWTpmdW5jdGlvbihhLGIsYyl7dmFy
+IHQscyxyLHEscCxvLG49dGhpcyxtPUguTGgobikKbS5kLmIoYikKbS5jaFsxXS5iKGMpCmlmKHR5cGVv
+ZiBiPT0ic3RyaW5nIil7dD1uLmIKbi5FSCh0PT1udWxsP24uYj1uLnpLKCk6dCxiLGMpfWVsc2UgaWYo
+dHlwZW9mIGI9PSJudW1iZXIiJiYoYiYweDNmZmZmZmYpPT09Yil7cz1uLmMKbi5FSChzPT1udWxsP24u
+Yz1uLnpLKCk6cyxiLGMpfWVsc2V7cj1uLmQKaWYocj09bnVsbClyPW4uZD1uLnpLKCkKcT1KLmhmKGIp
+JjB4M2ZmZmZmZgpwPW4uQnQocixxKQppZihwPT1udWxsKW4uRUkocixxLFtuLkhuKGIsYyldKQplbHNl
+e289bi5GaChwLGIpCmlmKG8+PTApcFtvXS5iPWMKZWxzZSBwLnB1c2gobi5IbihiLGMpKX19fSwKSzpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMscj10aGlzCkguTGgocikuQygifigxLDIpIikuYihiKQp0PXIuZQpz
+PXIucgpmb3IoO3QhPW51bGw7KXtiLiQyKHQuYSx0LmIpCmlmKHMhPT1yLnIpdGhyb3cgSC5iKFAuYTQo
+cikpCnQ9dC5jfX0sCkVIOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPXRoaXMscj1ILkxoKHMpCnIuZC5i
+KGIpCnIuY2hbMV0uYihjKQp0PXMuajIoYSxiKQppZih0PT1udWxsKXMuRUkoYSxiLHMuSG4oYixjKSkK
+ZWxzZSB0LmI9Y30sCmtzOmZ1bmN0aW9uKCl7dGhpcy5yPXRoaXMucisxJjY3MTA4ODYzfSwKSG46ZnVu
+Y3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMscj1ILkxoKHMpLHE9bmV3IEguZGIoci5kLmIoYSksci5jaFsx
+XS5iKGIpKQppZihzLmU9PW51bGwpcy5lPXMuZj1xCmVsc2V7dD1zLmYKcS5kPXQKcy5mPXQuYz1xfSsr
+cy5hCnMua3MoKQpyZXR1cm4gcX0sCkZoOmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZihhPT1udWxsKXJl
+dHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKWlmKEouUk0oYVtzXS5hLGIpKXJldHVybiBz
+CnJldHVybi0xfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sCmoyOmZ1bmN0aW9uKGEs
+Yil7cmV0dXJuIGFbYl19LApCdDpmdW5jdGlvbihhLGIpe3JldHVybiBhW2JdfSwKRUk6ZnVuY3Rpb24o
+YSxiLGMpe2FbYl09Y30sCnJuOmZ1bmN0aW9uKGEsYil7ZGVsZXRlIGFbYl19LApYdTpmdW5jdGlvbihh
+LGIpe3JldHVybiB0aGlzLmoyKGEsYikhPW51bGx9LAp6SzpmdW5jdGlvbigpe3ZhciB0PSI8bm9uLWlk
+ZW50aWZpZXIta2V5PiIscz1PYmplY3QuY3JlYXRlKG51bGwpCnRoaXMuRUkocyx0LHMpCnRoaXMucm4o
+cyx0KQpyZXR1cm4gc30sCiRpRm86MX0KSC5kYi5wcm90b3R5cGU9e30KSC5pNS5wcm90b3R5cGU9ewpn
+QTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmF9LApna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5h
+LHM9bmV3IEguTjYodCx0LnIsdGhpcy4kdGkuQygiTjY8MT4iKSkKcy5jPXQuZQpyZXR1cm4gc319Ckgu
+TjYucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3Zh
+ciB0PXRoaXMscz10LmEKaWYodC5iIT09cy5yKXRocm93IEguYihQLmE0KHMpKQplbHNle3M9dC5jCmlm
+KHM9PW51bGwpe3Quc3FZKG51bGwpCnJldHVybiExfWVsc2V7dC5zcVkocy5hKQp0LmM9dC5jLmMKcmV0
+dXJuITB9fX0sCnNxWTpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuZC5iKGEpfSwKJGlBbjoxfQpI
+LmRDLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEoYSl9LAokUzozfQpILndO
+LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYShhLGIpfSwKJFM6Mzh9Ckgu
+VlgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYShILnkoYSkpfSwKJFM6Mzd9
+CkguVlIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iUmVnRXhwLyIrdGhpcy5hKyIvIit0
+aGlzLmIuZmxhZ3N9LApnSGM6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5jCmlmKHMhPW51bGwpcmV0
+dXJuIHMKcz10LmIKcmV0dXJuIHQuYz1ILnY0KHQuYSxzLm11bHRpbGluZSwhcy5pZ25vcmVDYXNlLHMu
+dW5pY29kZSxzLmRvdEFsbCwhMCl9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5LVyh0aGlz
+LGIsMCl9LApVWjpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcy5nSGMoKQpzLmxhc3RJbmRleD1iCnQ9
+cy5leGVjKGEpCmlmKHQ9PW51bGwpcmV0dXJuCnJldHVybiBuZXcgSC5FSyh0KX0sCiRpdlg6MSwKJGl3
+TDoxfQpILkVLLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXt2YXIgdApILlNjKGIpCnQ9dGhpcy5i
+CmlmKGI+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsYikKcmV0dXJuIHRbYl19LAokaU9kOjEsCiRpaWI6
+MX0KSC5LVy5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlBiKHRoaXMuYSx0
+aGlzLmIsdGhpcy5jKX19CkguUGIucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5k
+fSwKRjpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9dGhpcyxvPXAuYgppZihvPT1udWxsKXJldHVybiEx
+CnQ9cC5jCmlmKHQ8PW8ubGVuZ3RoKXtzPXAuYQpyPXMuVVoobyx0KQppZihyIT1udWxsKXtwLmQ9cgpv
+PXIuYgp0PW8uaW5kZXgKcT10K29bMF0ubGVuZ3RoCmlmKHQ9PT1xKXtpZihzLmIudW5pY29kZSl7bz1w
+LmMKdD1vKzEKcz1wLmIKaWYodDxzLmxlbmd0aCl7bz1KLnJZKHMpLm0ocyxvKQppZihvPj01NTI5NiYm
+bzw9NTYzMTkpe289Qy54Qi5tKHMsdCkKbz1vPj01NjMyMCYmbzw9NTczNDN9ZWxzZSBvPSExfWVsc2Ug
+bz0hMX1lbHNlIG89ITEKcT0obz9xKzE6cSkrMX1wLmM9cQpyZXR1cm4hMH19cC5iPXAuZD1udWxsCnJl
+dHVybiExfSwKJGlBbjoxfQpILnRRLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCmlm
+KGIhPT0wKUgudmgoUC54KGIsbnVsbCkpCnJldHVybiB0aGlzLmN9LAokaU9kOjF9CkgudW4ucHJvdG90
+eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5TZCh0aGlzLmEsdGhpcy5iLHRoaXMuYyl9
+fQpILlNkLnByb3RvdHlwZT17CkY6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcyxxPXIuYyxwPXIuYixv
+PXAubGVuZ3RoLG49ci5hLG09bi5sZW5ndGgKaWYocStvPm0pe3IuZD1udWxsCnJldHVybiExfXQ9bi5p
+bmRleE9mKHAscSkKaWYodDwwKXtyLmM9bSsxCnIuZD1udWxsCnJldHVybiExfXM9dCtvCnIuZD1uZXcg
+SC50USh0LHApCnIuYz1zPT09ci5jP3MrMTpzCnJldHVybiEwfSwKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4g
+dGhpcy5kfSwKJGlBbjoxfQpILkVULnByb3RvdHlwZT17JGlFVDoxLCRpQVM6MX0KSC5iMC5wcm90b3R5
+cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LAokaVhqOjF9CkguRGcucHJvdG90eXBl
+PXsKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfSwK
+WTpmdW5jdGlvbihhLGIsYyl7SC5JZyhjKQpILm9kKGIsYSxhLmxlbmd0aCkKYVtiXT1jfSwKJGljWDox
+LAokaXpNOjF9CkguUGcucHJvdG90eXBlPXsKWTpmdW5jdGlvbihhLGIsYyl7SC5TYyhjKQpILm9kKGIs
+YSxhLmxlbmd0aCkKYVtiXT1jfSwKJGljWDoxLAokaXpNOjF9CkgueGoucHJvdG90eXBlPXsKcTpmdW5j
+dGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5kRS5wcm90
+b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5TYyhiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFb
+Yl19fQpILlpBLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCkgub2QoYixhLGEubGVu
+Z3RoKQpyZXR1cm4gYVtiXX19Ckgud2YucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0guU2MoYikK
+SC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5QcS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9u
+KGEsYil7SC5TYyhiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmVFLnByb3RvdHlw
+ZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIp
+Ckgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguVjYucHJvdG90eXBlPXsKZ0E6ZnVuY3Rp
+b24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guU2MoYikKSC5vZChiLGEsYS5s
+ZW5ndGgpCnJldHVybiBhW2JdfSwKJGlWNjoxLAokaW42OjF9CkguUkcucHJvdG90eXBlPXt9CkguVlAu
+cHJvdG90eXBlPXt9CkguV0IucHJvdG90eXBlPXt9CkguWkcucHJvdG90eXBlPXt9CkguSmMucHJvdG90
+eXBlPXsKQzpmdW5jdGlvbihhKXtyZXR1cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEpfSwKS3E6
+ZnVuY3Rpb24oYSl7cmV0dXJuIEgudjUodi50eXBlVW5pdmVyc2UsdGhpcyxhKX19CkguRy5wcm90b3R5
+cGU9e30KSC51OS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9fQpILmh6LnBy
+b3RvdHlwZT17fQpILmlNLnByb3RvdHlwZT17fQpQLnRoLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
+e3ZhciB0PXRoaXMuYSxzPXQuYQp0LmE9bnVsbApzLiQwKCl9LAokUzoxMn0KUC5oYS5wcm90b3R5cGU9
+ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzCnRoaXMuYS5hPXUuTS5iKGEpCnQ9dGhpcy5iCnM9dGhpcy5j
+CnQuZmlyc3RDaGlsZD90LnJlbW92ZUNoaWxkKHMpOnQuYXBwZW5kQ2hpbGQocyl9LAokUzoyMH0KUC5W
+cy5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS4kMCgpfSwKJEM6IiQwIiwKJFI6MCwKJFM6
+MH0KUC5GdC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS4kMCgpfSwKJEM6IiQwIiwKJFI6
+MCwKJFM6MH0KUC5XMy5wcm90b3R5cGU9ewpDWTpmdW5jdGlvbihhLGIpe2lmKHNlbGYuc2V0VGltZW91
+dCE9bnVsbClzZWxmLnNldFRpbWVvdXQoSC50UihuZXcgUC55SCh0aGlzLGIpLDApLGEpCmVsc2UgdGhy
+b3cgSC5iKFAuTDQoImBzZXRUaW1lb3V0KClgIG5vdCBmb3VuZC4iKSl9fQpQLnlILnByb3RvdHlwZT17
+CiQwOmZ1bmN0aW9uKCl7dGhpcy5iLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzoyfQpQLmloLnByb3Rv
+dHlwZT17CmFNOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXRoaXMuJHRpCnIuQygiMS8iKS5iKGIpCnQ9
+IXRoaXMuYnx8ci5DKCJiODwxPiIpLmMoYikKcz10aGlzLmEKaWYodClzLlhmKGIpCmVsc2Ugcy5YMihy
+LmQuYihiKSl9LAp3MDpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYQppZih0aGlzLmIpdC5aTChhLGIp
+CmVsc2UgdC5OayhhLGIpfX0KUC5XTS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
+cy5hLiQyKDAsYSl9LAokUzo0N30KUC5TWC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMu
+YS4kMigxLG5ldyBILmJxKGEsdS5sLmIoYikpKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjIxfQpQLkdzLnBy
+b3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hKEguU2MoYSksYil9LAokUzoyNn0KUC5QZi5w
+cm90b3R5cGU9ewp3MDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwpYT1uZXcgUC5uKCkKdD10
+aGlzLmEKaWYodC5hIT09MCl0aHJvdyBILmIoUC5QVigiRnV0dXJlIGFscmVhZHkgY29tcGxldGVkIikp
+CnQuTmsoYSxiKX0sCnBtOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLncwKGEsbnVsbCl9fQpQLlpmLnBy
+b3RvdHlwZT17CmFNOmZ1bmN0aW9uKGEsYil7dmFyIHQKdGhpcy4kdGkuQygiMS8iKS5iKGIpCnQ9dGhp
+cy5hCmlmKHQuYSE9PTApdGhyb3cgSC5iKFAuUFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQp0
+LlhmKGIpfX0KUC5GZS5wcm90b3R5cGU9ewpIUjpmdW5jdGlvbihhKXtpZigodGhpcy5jJjE1KSE9PTYp
+cmV0dXJuITAKcmV0dXJuIHRoaXMuYi5iLmJ2KHUuYWwuYih0aGlzLmQpLGEuYSx1LmNKLHUuSyl9LApL
+dzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmUscz11Lnoscj11LksscT10aGlzLiR0aS5DKCIyLyIpLHA9
+dGhpcy5iLmIKaWYodS5XLmModCkpcmV0dXJuIHEuYihwLnJwKHQsYS5hLGEuYixzLHIsdS5sKSkKZWxz
+ZSByZXR1cm4gcS5iKHAuYnYodS55LmIodCksYS5hLHMscikpfX0KUC52cy5wcm90b3R5cGU9ewpTcTpm
+dW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9dGhpcy4kdGkKcS5LcShjKS5DKCIxLygyKSIpLmIoYSkK
+dD0kLlgzCmlmKHQhPT1DLk5VKXtjLkMoIkA8MC8+IikuS3EocS5kKS5DKCIxKDIpIikuYihhKQppZihi
+IT1udWxsKWI9UC5WSChiLHQpfXM9bmV3IFAudnMoJC5YMyxjLkMoInZzPDA+IikpCnI9Yj09bnVsbD8x
+OjMKdGhpcy54ZihuZXcgUC5GZShzLHIsYSxiLHEuQygiQDwxPiIpLktxKGMpLkMoIkZlPDEsMj4iKSkp
+CnJldHVybiBzfSwKVzc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5TcShhLG51bGwsYil9LApRZDpm
+dW5jdGlvbihhLGIsYyl7dmFyIHQscz10aGlzLiR0aQpzLktxKGMpLkMoIjEvKDIpIikuYihhKQp0PW5l
+dyBQLnZzKCQuWDMsYy5DKCJ2czwwPiIpKQp0aGlzLnhmKG5ldyBQLkZlKHQsKGI9PW51bGw/MTozKXwx
+NixhLGIscy5DKCJAPDE+IikuS3EoYykuQygiRmU8MSwyPiIpKSkKcmV0dXJuIHR9LApPQTpmdW5jdGlv
+bihhKXt2YXIgdCxzLHIKdS5iZi5iKG51bGwpCnQ9dGhpcy4kdGkKcz0kLlgzCnI9bmV3IFAudnMocyx0
+KQppZihzIT09Qy5OVSlhPVAuVkgoYSxzKQp0aGlzLnhmKG5ldyBQLkZlKHIsMixudWxsLGEsdC5DKCJA
+PDE+IikuS3EodC5kKS5DKCJGZTwxLDI+IikpKQpyZXR1cm4gcn0sCnhmOmZ1bmN0aW9uKGEpe3ZhciB0
+LHM9dGhpcyxyPXMuYQppZihyPD0xKXthLmE9dS54LmIocy5jKQpzLmM9YX1lbHNle2lmKHI9PT0yKXt0
+PXUuXy5iKHMuYykKcj10LmEKaWYocjw0KXt0LnhmKGEpCnJldHVybn1zLmE9cgpzLmM9dC5jfVAuVGso
+bnVsbCxudWxsLHMuYix1Lk0uYihuZXcgUC5kYShzLGEpKSl9fSwKalE6ZnVuY3Rpb24oYSl7dmFyIHQs
+cyxyLHEscCxvPXRoaXMsbj17fQpuLmE9YQppZihhPT1udWxsKXJldHVybgp0PW8uYQppZih0PD0xKXtz
+PXUueC5iKG8uYykKcj1vLmM9YQppZihzIT1udWxsKXtmb3IoO3E9ci5hLHEhPW51bGw7cj1xKTtyLmE9
+c319ZWxzZXtpZih0PT09Mil7cD11Ll8uYihvLmMpCnQ9cC5hCmlmKHQ8NCl7cC5qUShhKQpyZXR1cm59
+by5hPXQKby5jPXAuY31uLmE9by5OOChhKQpQLlRrKG51bGwsbnVsbCxvLmIsdS5NLmIobmV3IFAub1Eo
+bixvKSkpfX0sCmFoOmZ1bmN0aW9uKCl7dmFyIHQ9dS54LmIodGhpcy5jKQp0aGlzLmM9bnVsbApyZXR1
+cm4gdGhpcy5OOCh0KX0sCk44OmZ1bmN0aW9uKGEpe3ZhciB0LHMscgpmb3IodD1hLHM9bnVsbDt0IT1u
+dWxsO3M9dCx0PXIpe3I9dC5hCnQuYT1zfXJldHVybiBzfSwKSEg6ZnVuY3Rpb24oYSl7dmFyIHQscz10
+aGlzLHI9cy4kdGkKci5DKCIxLyIpLmIoYSkKaWYoci5DKCJiODwxPiIpLmMoYSkpaWYoci5jKGEpKVAu
+QTkoYSxzKQplbHNlIFAuazMoYSxzKQplbHNle3Q9cy5haCgpCnIuZC5iKGEpCnMuYT00CnMuYz1hClAu
+SFoocyx0KX19LApYMjpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMKcy4kdGkuZC5iKGEpCnQ9cy5haCgp
+CnMuYT00CnMuYz1hClAuSFoocyx0KX0sClpMOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzCnUubC5i
+KGIpCnQ9cy5haCgpCnMuYT04CnMuYz1uZXcgUC5DdyhhLGIpClAuSFoocyx0KX0sClhmOmZ1bmN0aW9u
+KGEpe3ZhciB0PXRoaXMscz10LiR0aQpzLkMoIjEvIikuYihhKQppZihzLkMoImI4PDE+IikuYyhhKSl7
+dC5jVShhKQpyZXR1cm59dC5hPTEKUC5UayhudWxsLG51bGwsdC5iLHUuTS5iKG5ldyBQLnJIKHQsYSkp
+KX0sCmNVOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz10LiR0aQpzLkMoImI4PDE+IikuYihhKQppZihz
+LmMoYSkpe2lmKGEuYT09PTgpe3QuYT0xClAuVGsobnVsbCxudWxsLHQuYix1Lk0uYihuZXcgUC5LRih0
+LGEpKSl9ZWxzZSBQLkE5KGEsdCkKcmV0dXJufVAuazMoYSx0KX0sCk5rOmZ1bmN0aW9uKGEsYil7dGhp
+cy5hPTEKUC5UayhudWxsLG51bGwsdGhpcy5iLHUuTS5iKG5ldyBQLlpMKHRoaXMsYSxiKSkpfSwKJGli
+ODoxfQpQLmRhLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5IWih0aGlzLmEsdGhpcy5iKX0sCiRT
+OjB9ClAub1EucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtQLkhaKHRoaXMuYix0aGlzLmEuYSl9LAok
+UzowfQpQLnBWLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQp0LmE9MAp0LkhI
+KGEpfSwKJFM6MTJ9ClAuVTcucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt1LmwuYihiKQp0aGlz
+LmEuWkwoYSxiKX0sCiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLiQyKGEsbnVsbCl9LAokQzoiJDIi
+LAokRDpmdW5jdGlvbigpe3JldHVybltudWxsXX0sCiRTOjMwfQpQLnZyLnByb3RvdHlwZT17CiQwOmZ1
+bmN0aW9uKCl7dGhpcy5hLlpMKHRoaXMuYix0aGlzLmMpfSwKJFM6MH0KUC5ySC5wcm90b3R5cGU9ewok
+MDpmdW5jdGlvbigpe3ZhciB0PXRoaXMuYQp0LlgyKHQuJHRpLmQuYih0aGlzLmIpKX0sCiRTOjB9ClAu
+S0YucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtQLkE5KHRoaXMuYix0aGlzLmEpfSwKJFM6MH0KUC5a
+TC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS5aTCh0aGlzLmIsdGhpcy5jKX0sCiRTOjB9
+ClAuUlQucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbj10aGlzLG09bnVs
+bAp0cnl7cj1uLmMKbT1yLmIuYi56eih1LmZPLmIoci5kKSx1LnopfWNhdGNoKHEpe3Q9SC5SdShxKQpz
+PUgudHMocSkKaWYobi5kKXtyPXUubi5iKG4uYS5hLmMpLmEKcD10CnA9cj09bnVsbD9wPT1udWxsOnI9
+PT1wCnI9cH1lbHNlIHI9ITEKcD1uLmIKaWYocilwLmI9dS5uLmIobi5hLmEuYykKZWxzZSBwLmI9bmV3
+IFAuQ3codCxzKQpwLmE9ITAKcmV0dXJufWlmKHUuYy5jKG0pKXtpZihtIGluc3RhbmNlb2YgUC52cyYm
+bS5hPj00KXtpZihtLmE9PT04KXtyPW4uYgpyLmI9dS5uLmIobS5jKQpyLmE9ITB9cmV0dXJufW89bi5h
+LmEKcj1uLmIKci5iPW0uVzcobmV3IFAualoobyksdS56KQpyLmE9ITF9fSwKJFM6Mn0KUC5qWi5wcm90
+b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKJFM6MzN9ClAucnEucHJvdG90eXBl
+PXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMKdHJ5e3I9bS5iCnE9ci4kdGkK
+cD1xLmQKbz1wLmIobS5jKQptLmEuYj1yLmIuYi5idihxLkMoIjIvKDEpIikuYihyLmQpLG8scS5DKCIy
+LyIpLHApfWNhdGNoKG4pe3Q9SC5SdShuKQpzPUgudHMobikKcj1tLmEKci5iPW5ldyBQLkN3KHQscykK
+ci5hPSEwfX0sCiRTOjJ9ClAuUlcucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxw
+LG8sbixtLGw9dGhpcwp0cnl7dD11Lm4uYihsLmEuYS5jKQpxPWwuYwppZihILm9UKHEuSFIodCkpJiZx
+LmUhPW51bGwpe3A9bC5iCnAuYj1xLkt3KHQpCnAuYT0hMX19Y2F0Y2gobyl7cz1ILlJ1KG8pCnI9SC50
+cyhvKQpxPXUubi5iKGwuYS5hLmMpCnA9cS5hCm49cwptPWwuYgppZihwPT1udWxsP249PW51bGw6cD09
+PW4pbS5iPXEKZWxzZSBtLmI9bmV3IFAuQ3cocyxyKQptLmE9ITB9fSwKJFM6Mn0KUC5PTS5wcm90b3R5
+cGU9e30KUC5xaC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXt2YXIgdCxzLHI9dGhpcyxxPXt9LHA9
+bmV3IFAudnMoJC5YMyx1LmZKKQpxLmE9MAp0PUguTGgocikKcz10LkMoIn4oMSkiKS5iKG5ldyBQLkI1
+KHEscikpCnUuTS5iKG5ldyBQLlBJKHEscCkpClcuSkUoci5hLHIuYixzLCExLHQuZCkKcmV0dXJuIHB9
+fQpQLkI1LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe0guTGgodGhpcy5iKS5kLmIoYSk7Kyt0aGlz
+LmEuYX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIEguTGgodGhpcy5iKS5DKCJjOCgxKSIpfX0KUC5QSS5w
+cm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYi5ISCh0aGlzLmEuYSl9LAokUzowfQpQLk1PLnBy
+b3RvdHlwZT17fQpQLmtULnByb3RvdHlwZT17fQpQLnhJLnByb3RvdHlwZT17fQpQLkN3LnByb3RvdHlw
+ZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIEguZCh0aGlzLmEpfSwKJGlYUzoxfQpQLm0wLnByb3RvdHlw
+ZT17JGlKQjoxfQpQLnBLLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLmEscj1z
+LmEKcz1yPT1udWxsP3MuYT1uZXcgUC5uKCk6cgpyPXRoaXMuYgppZihyPT1udWxsKXRocm93IEguYihz
+KQp0PUguYihzKQp0LnN0YWNrPXIudygwKQp0aHJvdyB0fSwKJFM6MH0KUC5KaS5wcm90b3R5cGU9ewpi
+SDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1udWxsCnUuTS5iKGEpCnRyeXtpZihDLk5VPT09JC5YMyl7
+YS4kMCgpCnJldHVybn1QLlQ4KHEscSx0aGlzLGEsdS5IKX1jYXRjaChyKXt0PUguUnUocikKcz1ILnRz
+KHIpClAuTDIocSxxLHRoaXMsdCx1LmwuYihzKSl9fSwKRGw6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
+cixxPW51bGwKYy5DKCJ+KDApIikuYihhKQpjLmIoYikKdHJ5e2lmKEMuTlU9PT0kLlgzKXthLiQxKGIp
+CnJldHVybn1QLnl2KHEscSx0aGlzLGEsYix1LkgsYyl9Y2F0Y2gocil7dD1ILlJ1KHIpCnM9SC50cyhy
+KQpQLkwyKHEscSx0aGlzLHQsdS5sLmIocykpfX0sClJUOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBQ
+LmhqKHRoaXMsYi5DKCIwKCkiKS5iKGEpLGIpfSwKR1k6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLlZw
+KHRoaXMsdS5NLmIoYSkpfSwKUHk6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuT1IodGhpcyxiLkMo
+In4oMCkiKS5iKGEpLGIpfSwKcTpmdW5jdGlvbihhLGIpe3JldHVybn0sCnp6OmZ1bmN0aW9uKGEsYil7
+Yi5DKCIwKCkiKS5iKGEpCmlmKCQuWDM9PT1DLk5VKXJldHVybiBhLiQwKCkKcmV0dXJuIFAuVDgobnVs
+bCxudWxsLHRoaXMsYSxiKX0sCmJ2OmZ1bmN0aW9uKGEsYixjLGQpe2MuQygiQDwwPiIpLktxKGQpLkMo
+IjEoMikiKS5iKGEpCmQuYihiKQppZigkLlgzPT09Qy5OVSlyZXR1cm4gYS4kMShiKQpyZXR1cm4gUC55
+dihudWxsLG51bGwsdGhpcyxhLGIsYyxkKX0sCnJwOmZ1bmN0aW9uKGEsYixjLGQsZSxmKXtkLkMoIkA8
+MD4iKS5LcShlKS5LcShmKS5DKCIxKDIsMykiKS5iKGEpCmUuYihiKQpmLmIoYykKaWYoJC5YMz09PUMu
+TlUpcmV0dXJuIGEuJDIoYixjKQpyZXR1cm4gUC5ReChudWxsLG51bGwsdGhpcyxhLGIsYyxkLGUsZil9
+LApMajpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYi5DKCJAPDA+IikuS3EoYykuS3EoZCkuQygiMSgy
+LDMpIikuYihhKX19ClAuaGoucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hLnp6
+KHRoaXMuYix0aGlzLmMpfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jLkMoIjAoKSIpfX0KUC5W
+cC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmEuYkgodGhpcy5iKX0sCiRTOjJ9
+ClAuT1IucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCnJldHVybiB0aGlzLmEu
+RGwodGhpcy5iLHQuYihhKSx0KX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYy5DKCJ+KDApIil9
+fQpQLmI2LnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9bmV3IFAubG0odCx0
+LnIsSC5MaCh0KS5DKCJsbTwxPiIpKQpzLmM9dC5lCnJldHVybiBzfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHRoaXMuYX0sCnRnOmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZih0eXBlb2YgYj09InN0cmluZyIm
+JmIhPT0iX19wcm90b19fIil7dD10aGlzLmIKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdS5KLmIo
+dFtiXSkhPW51bGx9ZWxzZXtzPXRoaXMuUFIoYikKcmV0dXJuIHN9fSwKUFI6ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJuITEKcmV0dXJuIHRoaXMuREYodFt0aGlzLk4oYSldLGEp
+Pj0wfSwKaTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj10aGlzCkguTGgocikuZC5iKGIpCmlmKHR5cGVv
+ZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXt0PXIuYgpyZXR1cm4gci5iUSh0PT1udWxsP3Iu
+Yj1QLlQyKCk6dCxiKX1lbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGImMTA3Mzc0MTgyMyk9PT1i
+KXtzPXIuYwpyZXR1cm4gci5iUShzPT1udWxsP3IuYz1QLlQyKCk6cyxiKX1lbHNlIHJldHVybiByLkI3
+KGIpfSwKQjc6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9dGhpcwpILkxoKHEpLmQuYihhKQp0PXEuZApp
+Zih0PT1udWxsKXQ9cS5kPVAuVDIoKQpzPXEuTihhKQpyPXRbc10KaWYocj09bnVsbCl0W3NdPVtxLnlv
+KGEpXQplbHNle2lmKHEuREYocixhKT49MClyZXR1cm4hMQpyLnB1c2gocS55byhhKSl9cmV0dXJuITB9
+LApSOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwppZih0eXBlb2YgYj09InN0cmluZyImJmIhPT0iX19w
+cm90b19fIilyZXR1cm4gdC5MKHQuYixiKQplbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGImMTA3
+Mzc0MTgyMyk9PT1iKXJldHVybiB0LkwodC5jLGIpCmVsc2UgcmV0dXJuIHQucWcoYil9LApxZzpmdW5j
+dGlvbihhKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmQKaWYobz09bnVsbClyZXR1cm4hMQp0PXAuTihh
+KQpzPW9bdF0Kcj1wLkRGKHMsYSkKaWYocjwwKXJldHVybiExCnE9cy5zcGxpY2UociwxKVswXQppZigw
+PT09cy5sZW5ndGgpZGVsZXRlIG9bdF0KcC5HUyhxKQpyZXR1cm4hMH0sCmJROmZ1bmN0aW9uKGEsYil7
+SC5MaCh0aGlzKS5kLmIoYikKaWYodS5KLmIoYVtiXSkhPW51bGwpcmV0dXJuITEKYVtiXT10aGlzLnlv
+KGIpCnJldHVybiEwfSwKTDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuITEKdD11
+LkouYihhW2JdKQppZih0PT1udWxsKXJldHVybiExCnRoaXMuR1ModCkKZGVsZXRlIGFbYl0KcmV0dXJu
+ITB9LApTOmZ1bmN0aW9uKCl7dGhpcy5yPTEwNzM3NDE4MjMmdGhpcy5yKzF9LAp5bzpmdW5jdGlvbihh
+KXt2YXIgdCxzPXRoaXMscj1uZXcgUC5ibihILkxoKHMpLmQuYihhKSkKaWYocy5lPT1udWxsKXMuZT1z
+LmY9cgplbHNle3Q9cy5mCnIuYz10CnMuZj10LmI9cn0rK3MuYQpzLlMoKQpyZXR1cm4gcn0sCkdTOmZ1
+bmN0aW9uKGEpe3ZhciB0PXRoaXMscz1hLmMscj1hLmIKaWYocz09bnVsbCl0LmU9cgplbHNlIHMuYj1y
+CmlmKHI9PW51bGwpdC5mPXMKZWxzZSByLmM9czstLXQuYQp0LlMoKX0sCk46ZnVuY3Rpb24oYSl7cmV0
+dXJuIEouaGYoYSkmMTA3Mzc0MTgyM30sCkRGOmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZihhPT1udWxs
+KXJldHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKWlmKEouUk0oYVtzXS5hLGIpKXJldHVy
+biBzCnJldHVybi0xfX0KUC5ibi5wcm90b3R5cGU9e30KUC5sbS5wcm90b3R5cGU9ewpnbDpmdW5jdGlv
+bigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQuYQppZih0LmIhPT1z
+LnIpdGhyb3cgSC5iKFAuYTQocykpCmVsc2V7cz10LmMKaWYocz09bnVsbCl7dC5zaihudWxsKQpyZXR1
+cm4hMX1lbHNle3Quc2oodC4kdGkuZC5iKHMuYSkpCnQuYz10LmMuYgpyZXR1cm4hMH19fSwKc2o6ZnVu
+Y3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmQuYihhKX0sCiRpQW46MX0KUC5tVy5wcm90b3R5cGU9e30K
+UC5MVS5wcm90b3R5cGU9eyRpY1g6MSwkaXpNOjF9ClAubEQucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9u
+KGEpe3JldHVybiBuZXcgSC5hNyhhLHRoaXMuZ0EoYSksSC56SyhhKS5DKCJhNzxsRC5FPiIpKX0sCkU6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5xKGEsYil9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpI
+LnpLKGEpLkMoIn4obEQuRSkiKS5iKGIpCnQ9dGhpcy5nQShhKQpmb3Iocz0wO3M8dDsrK3Mpe2IuJDEo
+dGhpcy5xKGEscykpCmlmKHQhPT10aGlzLmdBKGEpKXRocm93IEguYihQLmE0KGEpKX19LApFMjpmdW5j
+dGlvbihhLGIsYyl7dmFyIHQ9SC56SyhhKQpyZXR1cm4gbmV3IEguQTgoYSx0LktxKGMpLkMoIjEobEQu
+RSkiKS5iKGIpLHQuQygiQDxsRC5FPiIpLktxKGMpLkMoIkE4PDEsMj4iKSl9LApkdTpmdW5jdGlvbihh
+LGIsYyxkKXt2YXIgdApILnpLKGEpLkMoImxELkUiKS5iKGQpClAuakIoYixjLHRoaXMuZ0EoYSkpCmZv
+cih0PWI7dDxjOysrdCl0aGlzLlkoYSx0LGQpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5XRShhLCJb
+IiwiXSIpfX0KUC5pbC5wcm90b3R5cGU9e30KUC5HQS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIp
+e3ZhciB0LHM9dGhpcy5hCmlmKCFzLmEpdGhpcy5iLmErPSIsICIKcy5hPSExCnM9dGhpcy5iCnQ9cy5h
+Kz1ILmQoYSkKcy5hPXQrIjogIgpzLmErPUguZChiKX0sCiRTOjF9ClAuWWsucHJvdG90eXBlPXsKSzpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMKSC5MaCh0aGlzKS5DKCJ+KFlrLkssWWsuVikiKS5iKGIpCmZvcih0
+PUouSVQodGhpcy5nVigpKTt0LkYoKTspe3M9dC5nbCgpCmIuJDIocyx0aGlzLnEoMCxzKSl9fSwKZ0E6
+ZnVuY3Rpb24oYSl7cmV0dXJuIEouSG0odGhpcy5nVigpKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAu
+bk8odGhpcyl9LAokaVowOjF9ClAuS1AucHJvdG90eXBlPXsKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9
+SC5MaCh0aGlzKQp0LmQuYihiKQp0LmNoWzFdLmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2Rp
+ZnkgdW5tb2RpZmlhYmxlIG1hcCIpKX19ClAuUG4ucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3Jl
+dHVybiB0aGlzLmEucSgwLGIpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5MaCh0aGlzKQp0aGlz
+LmEuWSgwLHQuZC5iKGIpLHQuY2hbMV0uYihjKSl9LApLOmZ1bmN0aW9uKGEsYil7dGhpcy5hLksoMCxI
+LkxoKHRoaXMpLkMoIn4oMSwyKSIpLmIoYikpfSwKZ0E6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJl
+dHVybiB0LmdBKHQpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gSi5qKHRoaXMuYSl9LAokaVowOjF9ClAu
+R2oucHJvdG90eXBlPXt9ClAubGYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5XRSh0
+aGlzLCJ7IiwifSIpfX0KUC5Wai5wcm90b3R5cGU9eyRpY1g6MSwkaXh1OjF9ClAuWHYucHJvdG90eXBl
+PXsKRlY6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD1KLklUKEguTGgodGhpcykuQygiY1g8MT4iKS5i
+KGIpKTt0LkYoKTspdGhpcy5pKDAsdC5nbCgpKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UodGhp
+cywieyIsIn0iKX0sCkg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPVAucmoodGhpcyx0aGlzLnIsSC5MaCh0
+aGlzKS5kKQppZighcy5GKCkpcmV0dXJuIiIKaWYoYj09PSIiKXt0PSIiCmRvIHQrPUguZChzLmQpCndo
+aWxlKHMuRigpKX1lbHNle3Q9SC5kKHMuZCkKZm9yKDtzLkYoKTspdD10K2IrSC5kKHMuZCl9cmV0dXJu
+IHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAokaWNYOjEsCiRpeHU6MX0KUC5uWS5wcm90b3R5cGU9e30K
+UC5XWS5wcm90b3R5cGU9e30KUC5SVS5wcm90b3R5cGU9e30KUC51dy5wcm90b3R5cGU9ewpxOmZ1bmN0
+aW9uKGEsYil7dmFyIHQscz10aGlzLmIKaWYocz09bnVsbClyZXR1cm4gdGhpcy5jLnEoMCxiKQplbHNl
+IGlmKHR5cGVvZiBiIT0ic3RyaW5nIilyZXR1cm4KZWxzZXt0PXNbYl0KcmV0dXJuIHR5cGVvZiB0PT0i
+dW5kZWZpbmVkIj90aGlzLmZiKGIpOnR9fSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYj09bnVs
+bD90aGlzLmMuYTp0aGlzLkNmKCkubGVuZ3RofSwKZ1Y6ZnVuY3Rpb24oKXtpZih0aGlzLmI9PW51bGwp
+e3ZhciB0PXRoaXMuYwpyZXR1cm4gbmV3IEguaTUodCxILkxoKHQpLkMoImk1PDE+IikpfXJldHVybiBu
+ZXcgUC5pOCh0aGlzKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscj10aGlzCmlmKHIuYj09bnVs
+bClyLmMuWSgwLGIsYykKZWxzZSBpZihyLng0KGIpKXt0PXIuYgp0W2JdPWMKcz1yLmEKaWYocz09bnVs
+bD90IT1udWxsOnMhPT10KXNbYl09bnVsbH1lbHNlIHIuWEsoKS5ZKDAsYixjKX0sCng0OmZ1bmN0aW9u
+KGEpe2lmKHRoaXMuYj09bnVsbClyZXR1cm4gdGhpcy5jLng0KGEpCnJldHVybiBPYmplY3QucHJvdG90
+eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcy5hLGEpfSwKSzpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
+cixxLHA9dGhpcwp1LmNBLmIoYikKaWYocC5iPT1udWxsKXJldHVybiBwLmMuSygwLGIpCnQ9cC5DZigp
+CmZvcihzPTA7czx0Lmxlbmd0aDsrK3Mpe3I9dFtzXQpxPXAuYltyXQppZih0eXBlb2YgcT09InVuZGVm
+aW5lZCIpe3E9UC5RZShwLmFbcl0pCnAuYltyXT1xfWIuJDIocixxKQppZih0IT09cC5jKXRocm93IEgu
+YihQLmE0KHApKX19LApDZjpmdW5jdGlvbigpe3ZhciB0PXUuai5iKHRoaXMuYykKaWYodD09bnVsbCl0
+PXRoaXMuYz1ILlZNKE9iamVjdC5rZXlzKHRoaXMuYSksdS5zKQpyZXR1cm4gdH0sClhLOmZ1bmN0aW9u
+KCl7dmFyIHQscyxyLHEscCxvPXRoaXMKaWYoby5iPT1udWxsKXJldHVybiBvLmMKdD1QLkZsKHUuTix1
+LnopCnM9by5DZigpCmZvcihyPTA7cT1zLmxlbmd0aCxyPHE7KytyKXtwPXNbcl0KdC5ZKDAscCxvLnEo
+MCxwKSl9aWYocT09PTApQy5ObS5pKHMsbnVsbCkKZWxzZSBDLk5tLnNBKHMsMCkKby5hPW8uYj1udWxs
+CnJldHVybiBvLmM9dH0sCmZiOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKCFPYmplY3QucHJvdG90eXBlLmhh
+c093blByb3BlcnR5LmNhbGwodGhpcy5hLGEpKXJldHVybgp0PVAuUWUodGhpcy5hW2FdKQpyZXR1cm4g
+dGhpcy5iW2FdPXR9fQpQLmk4LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpy
+ZXR1cm4gdC5nQSh0KX0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmEKaWYodC5iPT1udWxsKXQ9
+dC5nVigpLkUoMCxiKQplbHNle3Q9dC5DZigpCmlmKGI8MHx8Yj49dC5sZW5ndGgpcmV0dXJuIEguT0go
+dCxiKQp0PXRbYl19cmV0dXJuIHR9LApna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCmlmKHQuYj09
+bnVsbCl7dD10LmdWKCkKdD10Lmdreih0KX1lbHNle3Q9dC5DZigpCnQ9bmV3IEoubTEodCx0Lmxlbmd0
+aCxILnQ2KHQpLkMoIm0xPDE+IikpfXJldHVybiB0fX0KUC5DVi5wcm90b3R5cGU9ewp5cjpmdW5jdGlv
+bihhLGEwLGExKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYj0iSW52YWxp
+ZCBiYXNlNjQgZW5jb2RpbmcgbGVuZ3RoICIKYTE9UC5qQihhMCxhMSxhLmxlbmd0aCkKdD0kLlY3KCkK
+Zm9yKHM9YTAscj1zLHE9bnVsbCxwPS0xLG89LTEsbj0wO3M8YTE7cz1tKXttPXMrMQpsPUMueEIuVyhh
+LHMpCmlmKGw9PT0zNyl7az1tKzIKaWYoazw9YTEpe2o9SC5vbyhDLnhCLlcoYSxtKSkKaT1ILm9vKEMu
+eEIuVyhhLG0rMSkpCmg9aioxNitpLShpJjI1NikKaWYoaD09PTM3KWg9LTEKbT1rfWVsc2UgaD0tMX1l
+bHNlIGg9bAppZigwPD1oJiZoPD0xMjcpe2lmKGg8MHx8aD49dC5sZW5ndGgpcmV0dXJuIEguT0godCxo
+KQpnPXRbaF0KaWYoZz49MCl7aD1DLnhCLm0oIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVm
+Z2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8iLGcpCmlmKGg9PT1sKWNvbnRpbnVlCmw9aH1l
+bHNle2lmKGc9PT0tMSl7aWYocDwwKXtmPXE9PW51bGw/bnVsbDpxLmEubGVuZ3RoCmlmKGY9PW51bGwp
+Zj0wCnA9Zisocy1yKQpvPXN9KytuCmlmKGw9PT02MSljb250aW51ZX1sPWh9aWYoZyE9PS0yKXtpZihx
+PT1udWxsKXE9bmV3IFAuUm4oIiIpCnEuYSs9Qy54Qi5OaihhLHIscykKcS5hKz1ILkx3KGwpCnI9bQpj
+b250aW51ZX19dGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IGRhdGEiLGEscykpfWlmKHEhPW51
+bGwpe2Y9cS5hKz1DLnhCLk5qKGEscixhMSkKZT1mLmxlbmd0aAppZihwPj0wKVAueE0oYSxvLGExLHAs
+bixlKQplbHNle2Q9Qy5qbi56WShlLTEsNCkrMQppZihkPT09MSl0aHJvdyBILmIoUC5ycihiLGEsYTEp
+KQpmb3IoO2Q8NDspe2YrPSI9IgpxLmE9ZjsrK2R9fWY9cS5hCnJldHVybiBDLnhCLmk3KGEsYTAsYTEs
+Zi5jaGFyQ29kZUF0KDApPT0wP2Y6Zil9Yz1hMS1hMAppZihwPj0wKVAueE0oYSxvLGExLHAsbixjKQpl
+bHNle2Q9Qy5qbi56WShjLDQpCmlmKGQ9PT0xKXRocm93IEguYihQLnJyKGIsYSxhMSkpCmlmKGQ+MSlh
+PUMueEIuaTcoYSxhMSxhMSxkPT09Mj8iPT0iOiI9Iil9cmV0dXJuIGF9fQpQLlU4LnByb3RvdHlwZT17
+fQpQLlVrLnByb3RvdHlwZT17fQpQLndJLnByb3RvdHlwZT17fQpQLlppLnByb3RvdHlwZT17fQpQLmJ5
+LnByb3RvdHlwZT17CnBXOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAp1LmVwLmIoYykKdD1QLkJTKGIsdGhp
+cy5nSGUoKS5hKQpyZXR1cm4gdH0sCmdIZTpmdW5jdGlvbigpe3JldHVybiBDLkEzfX0KUC5NeC5wcm90
+b3R5cGU9e30KUC51NS5wcm90b3R5cGU9ewpnWkU6ZnVuY3Rpb24oKXtyZXR1cm4gQy5Ra319ClAuRTMu
+cHJvdG90eXBlPXsKV0o6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPVAuakIoMCxudWxsLGEubGVuZ3RoKSxx
+PXItMAppZihxPT09MClyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCkKdD1uZXcgVWludDhBcnJheShxKjMp
+CnM9bmV3IFAuUncodCkKaWYocy5HeChhLDAscikhPT1yKXMuTzYoSi5hNihhLHItMSksMCkKcmV0dXJu
+IG5ldyBVaW50OEFycmF5KHQuc3ViYXJyYXkoMCxILnJNKDAscy5iLHQubGVuZ3RoKSkpfX0KUC5Sdy5w
+cm90b3R5cGU9ewpPNjpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcyxyPXMuYyxxPXMuYixwPXErMSxv
+PXIubGVuZ3RoCmlmKChiJjY0NTEyKT09PTU2MzIwKXt0PTY1NTM2KygoYSYxMDIzKTw8MTApfGImMTAy
+MwpzLmI9cAppZihxPj1vKXJldHVybiBILk9IKHIscSkKcltxXT0yNDB8dD4+PjE4CnE9cy5iPXArMQpp
+ZihwPj1vKXJldHVybiBILk9IKHIscCkKcltwXT0xMjh8dD4+PjEyJjYzCnA9cy5iPXErMQppZihxPj1v
+KXJldHVybiBILk9IKHIscSkKcltxXT0xMjh8dD4+PjYmNjMKcy5iPXArMQppZihwPj1vKXJldHVybiBI
+Lk9IKHIscCkKcltwXT0xMjh8dCY2MwpyZXR1cm4hMH1lbHNle3MuYj1wCmlmKHE+PW8pcmV0dXJuIEgu
+T0gocixxKQpyW3FdPTIyNHxhPj4+MTIKcT1zLmI9cCsxCmlmKHA+PW8pcmV0dXJuIEguT0gocixwKQpy
+W3BdPTEyOHxhPj4+NiY2MwpzLmI9cSsxCmlmKHE+PW8pcmV0dXJuIEguT0gocixxKQpyW3FdPTEyOHxh
+JjYzCnJldHVybiExfX0sCkd4OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMK
+aWYoYiE9PWMmJihDLnhCLm0oYSxjLTEpJjY0NTEyKT09PTU1Mjk2KS0tYwpmb3IodD1tLmMscz10Lmxl
+bmd0aCxyPWI7cjxjOysrcil7cT1DLnhCLlcoYSxyKQppZihxPD0xMjcpe3A9bS5iCmlmKHA+PXMpYnJl
+YWsKbS5iPXArMQp0W3BdPXF9ZWxzZSBpZigocSY2NDUxMik9PT01NTI5Nil7aWYobS5iKzM+PXMpYnJl
+YWsKbz1yKzEKaWYobS5PNihxLEMueEIuVyhhLG8pKSlyPW99ZWxzZSBpZihxPD0yMDQ3KXtwPW0uYgpu
+PXArMQppZihuPj1zKWJyZWFrCm0uYj1uCmlmKHA+PXMpcmV0dXJuIEguT0godCxwKQp0W3BdPTE5Mnxx
+Pj4+NgptLmI9bisxCnRbbl09MTI4fHEmNjN9ZWxzZXtwPW0uYgppZihwKzI+PXMpYnJlYWsKbj1tLmI9
+cCsxCmlmKHA+PXMpcmV0dXJuIEguT0godCxwKQp0W3BdPTIyNHxxPj4+MTIKcD1tLmI9bisxCmlmKG4+
+PXMpcmV0dXJuIEguT0godCxuKQp0W25dPTEyOHxxPj4+NiY2MwptLmI9cCsxCmlmKHA+PXMpcmV0dXJu
+IEguT0godCxwKQp0W3BdPTEyOHxxJjYzfX1yZXR1cm4gcn19ClAuR1kucHJvdG90eXBlPXsKV0o6ZnVu
+Y3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsCnUuTC5iKGEpCnQ9UC5reSghMSxhLDAsbnVsbCkK
+aWYodCE9bnVsbClyZXR1cm4gdApzPVAuakIoMCxudWxsLEouSG0oYSkpCnI9UC53RyhhLDAscykKaWYo
+cj4wKXtxPVAuSE0oYSwwLHIpCmlmKHI9PT1zKXJldHVybiBxCnA9bmV3IFAuUm4ocSkKbz1yCm49ITF9
+ZWxzZXtvPTAKcD1udWxsCm49ITB9aWYocD09bnVsbClwPW5ldyBQLlJuKCIiKQptPW5ldyBQLmJ6KCEx
+LHApCm0uYz1uCm0uTUUoYSxvLHMpCmlmKG0uZT4wKXtILnZoKFAucnIoIlVuZmluaXNoZWQgVVRGLTgg
+b2N0ZXQgc2VxdWVuY2UiLGEscykpCnAuYSs9SC5Mdyg2NTUzMykKbS5mPW0uZT1tLmQ9MH1sPXAuYQpy
+ZXR1cm4gbC5jaGFyQ29kZUF0KDApPT0wP2w6bH19ClAuYnoucHJvdG90eXBlPXsKTUU6ZnVuY3Rpb24o
+YSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoPXRoaXMsZz0iQmFkIFVURi04IGVuY29k
+aW5nIDB4Igp1LkwuYihhKQp0PWguZApzPWguZQpyPWguZgpoLmY9aC5lPWguZD0wCiRsYWJlbDAkMDpm
+b3IocT1KLlU2KGEpLHA9aC5iLG89YjshMDtvPWopeyRsYWJlbDEkMTppZihzPjApe2Rve2lmKG89PT1j
+KWJyZWFrICRsYWJlbDAkMApuPXEucShhLG8pCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4u
+ek0oKQppZigobiYxOTIpIT09MTI4KXttPVAucnIoZytDLmpuLldaKG4sMTYpLGEsbykKdGhyb3cgSC5i
+KG0pfWVsc2V7dD0odDw8NnxuJjYzKT4+PjA7LS1zOysrb319d2hpbGUocz4wKQptPXItMQppZihtPDB8
+fG0+PTQpcmV0dXJuIEguT0goQy5HYixtKQppZih0PD1DLkdiW21dKXttPVAucnIoIk92ZXJsb25nIGVu
+Y29kaW5nIG9mIDB4IitDLmpuLldaKHQsMTYpLGEsby1yLTEpCnRocm93IEguYihtKX1pZih0PjExMTQx
+MTEpe209UC5ycigiQ2hhcmFjdGVyIG91dHNpZGUgdmFsaWQgVW5pY29kZSByYW5nZTogMHgiK0Muam4u
+V1oodCwxNiksYSxvLXItMSkKdGhyb3cgSC5iKG0pfWlmKCFoLmN8fHQhPT02NTI3OSlwLmErPUguTHco
+dCkKaC5jPSExfWZvcihtPW88YzttOyl7bD1QLndHKGEsbyxjKQppZihsPjApe2guYz0hMQprPW8rbApw
+LmErPVAuSE0oYSxvLGspCmlmKGs9PT1jKWJyZWFrfWVsc2Ugaz1vCmo9aysxCm49cS5xKGEsaykKaWYo
+dHlwZW9mIG4hPT0ibnVtYmVyIilyZXR1cm4gbi5KKCkKaWYobjwwKXtpPVAucnIoIk5lZ2F0aXZlIFVU
+Ri04IGNvZGUgdW5pdDogLTB4IitDLmpuLldaKC1uLDE2KSxhLGotMSkKdGhyb3cgSC5iKGkpfWVsc2V7
+aWYoKG4mMjI0KT09PTE5Mil7dD1uJjMxCnM9MQpyPTEKY29udGludWUgJGxhYmVsMCQwfWlmKChuJjI0
+MCk9PT0yMjQpe3Q9biYxNQpzPTIKcj0yCmNvbnRpbnVlICRsYWJlbDAkMH1pZigobiYyNDgpPT09MjQw
+JiZuPDI0NSl7dD1uJjcKcz0zCnI9Mwpjb250aW51ZSAkbGFiZWwwJDB9aT1QLnJyKGcrQy5qbi5XWihu
+LDE2KSxhLGotMSkKdGhyb3cgSC5iKGkpfX1icmVhayAkbGFiZWwwJDB9aWYocz4wKXtoLmQ9dApoLmU9
+cwpoLmY9cn19fQpQLldGLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCnUuZm8u
+YihhKQp0PXRoaXMuYgpzPXRoaXMuYQp0LmErPXMuYQpyPXQuYSs9SC5kKGEuYSkKdC5hPXIrIjogIgp0
+LmErPVAucChiKQpzLmE9IiwgIn0sCiRTOjE4fQpQLmEyLnByb3RvdHlwZT17fQpQLmlQLnByb3RvdHlw
+ZT17CkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4gYiBpbnN0YW5jZW9m
+IFAuaVAmJnRoaXMuYT09PWIuYSYmITB9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVy
+bih0XkMuam4ud0codCwzMCkpJjEwNzM3NDE4MjN9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz1Q
+LkdxKEgudEoodCkpLHI9UC5oMChILk5TKHQpKSxxPVAuaDAoSC5qQSh0KSkscD1QLmgwKEguS0wodCkp
+LG89UC5oMChILmNoKHQpKSxuPVAuaDAoSC5KZCh0KSksbT1QLlZ4KEgubzEodCkpLGw9cysiLSIrcisi
+LSIrcSsiICIrcCsiOiIrbysiOiIrbisiLiIrbQpyZXR1cm4gbH19ClAuQ1AucHJvdG90eXBlPXt9ClAu
+WFMucHJvdG90eXBlPXt9ClAuQzYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEK
+aWYodCE9bnVsbClyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDogIitQLnAodCkKcmV0dXJuIkFzc2VydGlv
+biBmYWlsZWQifX0KUC5uLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlRocm93IG9mIG51
+bGwuIn19ClAudS5wcm90b3R5cGU9ewpnWjpmdW5jdGlvbigpe3JldHVybiJJbnZhbGlkIGFyZ3VtZW50
+IisoIXRoaXMuYT8iKHMpIjoiIil9LApndTpmdW5jdGlvbigpe3JldHVybiIifSwKdzpmdW5jdGlvbihh
+KXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmMsbj1vIT1udWxsPyIgKCIrbysiKSI6IiIKbz1wLmQKdD1v
+PT1udWxsPyIiOiI6ICIrSC5kKG8pCnM9cC5nWigpK24rdAppZighcC5hKXJldHVybiBzCnI9cC5ndSgp
+CnE9UC5wKHAuYikKcmV0dXJuIHMrcisiOiAiK3F9fQpQLmJKLnByb3RvdHlwZT17CmdaOmZ1bmN0aW9u
+KCl7cmV0dXJuIlJhbmdlRXJyb3IifSwKZ3U6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcy5lCmlmKHI9
+PW51bGwpe3I9dGhpcy5mCnQ9ciE9bnVsbD8iOiBOb3QgbGVzcyB0aGFuIG9yIGVxdWFsIHRvICIrSC5k
+KHIpOiIifWVsc2V7cz10aGlzLmYKaWYocz09bnVsbCl0PSI6IE5vdCBncmVhdGVyIHRoYW4gb3IgZXF1
+YWwgdG8gIitILmQocikKZWxzZSBpZihzPnIpdD0iOiBOb3QgaW4gcmFuZ2UgIitILmQocikrIi4uIitI
+LmQocykrIiwgaW5jbHVzaXZlIgplbHNlIHQ9czxyPyI6IFZhbGlkIHZhbHVlIHJhbmdlIGlzIGVtcHR5
+IjoiOiBPbmx5IHZhbGlkIHZhbHVlIGlzICIrSC5kKHIpfXJldHVybiB0fX0KUC5lWS5wcm90b3R5cGU9
+ewpnWjpmdW5jdGlvbigpe3JldHVybiJSYW5nZUVycm9yIn0sCmd1OmZ1bmN0aW9uKCl7dmFyIHQscz1I
+LlNjKHRoaXMuYikKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5KKCkKaWYoczwwKXJldHVy
+biI6IGluZGV4IG11c3Qgbm90IGJlIG5lZ2F0aXZlIgp0PXRoaXMuZgppZih0PT09MClyZXR1cm4iOiBu
+byBpbmRpY2VzIGFyZSB2YWxpZCIKcmV0dXJuIjogaW5kZXggc2hvdWxkIGJlIGxlc3MgdGhhbiAiK0gu
+ZCh0KX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmZ9fQpQLm1wLnByb3RvdHlwZT17Cnc6ZnVu
+Y3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsPXRoaXMsaz17fSxqPW5ldyBQLlJuKCIiKQprLmE9
+IiIKZm9yKHQ9bC5jLHM9dC5sZW5ndGgscj0wLHE9IiIscD0iIjtyPHM7KytyLHA9IiwgIil7bz10W3Jd
+CmouYT1xK3AKcT1qLmErPVAucChvKQprLmE9IiwgIn1sLmQuSygwLG5ldyBQLldGKGssaikpCm49UC5w
+KGwuYSkKbT1qLncoMCkKdD0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciK0gu
+ZChsLmIuYSkrIidcblJlY2VpdmVyOiAiK24rIlxuQXJndW1lbnRzOiBbIittKyJdIgpyZXR1cm4gdH19
+ClAudWIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iVW5zdXBwb3J0ZWQgb3BlcmF0aW9u
+OiAiK3RoaXMuYX19ClAuZHMucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0
+dXJuIHQhPW51bGw/IlVuaW1wbGVtZW50ZWRFcnJvcjogIit0OiJVbmltcGxlbWVudGVkRXJyb3IifX0K
+UC5sai5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJCYWQgc3RhdGU6ICIrdGhpcy5hfX0K
+UC5VVi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQppZih0PT1udWxsKXJldHVy
+biJDb25jdXJyZW50IG1vZGlmaWNhdGlvbiBkdXJpbmcgaXRlcmF0aW9uLiIKcmV0dXJuIkNvbmN1cnJl
+bnQgbW9kaWZpY2F0aW9uIGR1cmluZyBpdGVyYXRpb246ICIrUC5wKHQpKyIuIn19ClAuazUucHJvdG90
+eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iT3V0IG9mIE1lbW9yeSJ9LAokaVhTOjF9ClAuS1kucHJv
+dG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iU3RhY2sgT3ZlcmZsb3cifSwKJGlYUzoxfQpQLmMu
+cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQ9PW51bGw/IlJlYWRp
+bmcgc3RhdGljIHZhcmlhYmxlIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24iOiJSZWFkaW5nIHN0YXRp
+YyB2YXJpYWJsZSAnIit0KyInIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24ifX0KUC5DRC5wcm90b3R5
+cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJFeGNlcHRpb246ICIrdGhpcy5hfX0KUC5hRS5wcm90b3R5
+cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoPXRoaXMuYSxnPWgh
+PW51bGwmJiIiIT09aD8iRm9ybWF0RXhjZXB0aW9uOiAiK0guZChoKToiRm9ybWF0RXhjZXB0aW9uIixm
+PXRoaXMuYyxlPXRoaXMuYgppZih0eXBlb2YgZT09InN0cmluZyIpe2lmKGYhPW51bGwpaD1mPDB8fGY+
+ZS5sZW5ndGgKZWxzZSBoPSExCmlmKGgpZj1udWxsCmlmKGY9PW51bGwpe3Q9ZS5sZW5ndGg+Nzg/Qy54
+Qi5OaihlLDAsNzUpKyIuLi4iOmUKcmV0dXJuIGcrIlxuIit0fWZvcihzPTEscj0wLHE9ITEscD0wO3A8
+ZjsrK3Ape289Qy54Qi5XKGUscCkKaWYobz09PTEwKXtpZihyIT09cHx8IXEpKytzCnI9cCsxCnE9ITF9
+ZWxzZSBpZihvPT09MTMpeysrcwpyPXArMQpxPSEwfX1nPXM+MT9nKygiIChhdCBsaW5lICIrcysiLCBj
+aGFyYWN0ZXIgIisoZi1yKzEpKyIpXG4iKTpnKygiIChhdCBjaGFyYWN0ZXIgIisoZisxKSsiKVxuIikK
+bj1lLmxlbmd0aApmb3IocD1mO3A8bjsrK3Ape289Qy54Qi5tKGUscCkKaWYobz09PTEwfHxvPT09MTMp
+e249cApicmVha319aWYobi1yPjc4KWlmKGYtcjw3NSl7bT1yKzc1Cmw9cgprPSIiCmo9Ii4uLiJ9ZWxz
+ZXtpZihuLWY8NzUpe2w9bi03NQptPW4Kaj0iIn1lbHNle2w9Zi0zNgptPWYrMzYKaj0iLi4uIn1rPSIu
+Li4ifWVsc2V7bT1uCmw9cgprPSIiCmo9IiJ9aT1DLnhCLk5qKGUsbCxtKQpyZXR1cm4gZytrK2kraisi
+XG4iK0MueEIuSXgoIiAiLGYtbCtrLmxlbmd0aCkrIl5cbiJ9ZWxzZSByZXR1cm4gZiE9bnVsbD9nKygi
+IChhdCBvZmZzZXQgIitILmQoZikrIikiKTpnfX0KUC5FSC5wcm90b3R5cGU9e30KUC5LTi5wcm90b3R5
+cGU9e30KUC5jWC5wcm90b3R5cGU9ewpldjpmdW5jdGlvbihhLGIpe3ZhciB0PUguTGgodGhpcykKcmV0
+dXJuIG5ldyBILlU1KHRoaXMsdC5DKCJhMihjWC5FKSIpLmIoYiksdC5DKCJVNTxjWC5FPiIpKX0sCmdB
+OmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5na3oodGhpcykKZm9yKHQ9MDtzLkYoKTspKyt0CnJldHVy
+biB0fSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiF0aGlzLmdreih0aGlzKS5GKCl9LApncjg6ZnVuY3Rp
+b24oYSl7dmFyIHQscz10aGlzLmdreih0aGlzKQppZighcy5GKCkpdGhyb3cgSC5iKEguV3AoKSkKdD1z
+LmdsKCkKaWYocy5GKCkpdGhyb3cgSC5iKEguZFUoKSkKcmV0dXJuIHR9LApFOmZ1bmN0aW9uKGEsYil7
+dmFyIHQscyxyClAuazEoYiwiaW5kZXgiKQpmb3IodD10aGlzLmdreih0aGlzKSxzPTA7dC5GKCk7KXty
+PXQuZ2woKQppZihiPT09cylyZXR1cm4gcjsrK3N9dGhyb3cgSC5iKFAuQ2YoYix0aGlzLCJpbmRleCIs
+bnVsbCxzKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLkVQKHRoaXMsIigiLCIpIil9fQpQLkFuLnBy
+b3RvdHlwZT17fQpQLnpNLnByb3RvdHlwZT17JGljWDoxfQpQLlowLnByb3RvdHlwZT17fQpQLmM4LnBy
+b3RvdHlwZT17CmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gUC5rLnByb3RvdHlwZS5naU8uY2FsbCh0aGlz
+LHRoaXMpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4ibnVsbCJ9fQpQLkZLLnByb3RvdHlwZT17fQpQLmsu
+cHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpQLmssJGlrOjEsCkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRo
+aXM9PT1ifSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBILmVRKHRoaXMpfSwKdzpmdW5jdGlvbihhKXty
+ZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5kKEguTSh0aGlzKSkrIicifSwKZTc6ZnVuY3Rpb24oYSxiKXt1
+Lm8uYihiKQp0aHJvdyBILmIoUC5scih0aGlzLGIuZ1dhKCksYi5nbmQoKSxiLmdWbSgpKSl9LAp0b1N0
+cmluZzpmdW5jdGlvbigpe3JldHVybiB0aGlzLncodGhpcyl9fQpQLk9kLnByb3RvdHlwZT17fQpQLmli
+LnByb3RvdHlwZT17JGlPZDoxfQpQLnh1LnByb3RvdHlwZT17fQpQLkd6LnByb3RvdHlwZT17fQpQLnFV
+LnByb3RvdHlwZT17JGl2WDoxfQpQLlJuLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0
+aGlzLmEubGVuZ3RofSwKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuY2hhckNvZGVB
+dCgwKT09MD90OnR9LAokaUJMOjF9ClAuR0QucHJvdG90eXBlPXt9ClAubjEucHJvdG90eXBlPXsKJDI6
+ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQp1LmYuYihhKQpILnkoYikKdD1KLnJZKGIpLk9ZKGIsIj0i
+KQppZih0PT09LTEpe2lmKGIhPT0iIilhLlkoMCxQLmt1KGIsMCxiLmxlbmd0aCx0aGlzLmEsITApLCIi
+KX1lbHNlIGlmKHQhPT0wKXtzPUMueEIuTmooYiwwLHQpCnI9Qy54Qi5HKGIsdCsxKQpxPXRoaXMuYQph
+LlkoMCxQLmt1KHMsMCxzLmxlbmd0aCxxLCEwKSxQLmt1KHIsMCxyLmxlbmd0aCxxLCEwKSl9cmV0dXJu
+IGF9LAokUzo0MH0KUC5jUy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3Rocm93IEguYihQLnJy
+KCJJbGxlZ2FsIElQdjQgYWRkcmVzcywgIithLHRoaXMuYSxiKSl9LAokUzo0M30KUC5WQy5wcm90b3R5
+cGU9ewokMjpmdW5jdGlvbihhLGIpe3Rocm93IEguYihQLnJyKCJJbGxlZ2FsIElQdjYgYWRkcmVzcywg
+IithLHRoaXMuYSxiKSl9LAokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy4kMihhLG51bGwpfSwKJFM6
+NDR9ClAudHAucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihiLWE+NCl0aGlzLmEu
+JDIoImFuIElQdjYgcGFydCBjYW4gb25seSBjb250YWluIGEgbWF4aW11bSBvZiA0IGhleCBkaWdpdHMi
+LGEpCnQ9UC5RQShDLnhCLk5qKHRoaXMuYixhLGIpLG51bGwsMTYpCmlmKHR5cGVvZiB0IT09Im51bWJl
+ciIpcmV0dXJuIHQuSigpCmlmKHQ8MHx8dD42NTUzNSl0aGlzLmEuJDIoImVhY2ggcGFydCBtdXN0IGJl
+IGluIHRoZSByYW5nZSBvZiBgMHgwLi4weEZGRkZgIixhKQpyZXR1cm4gdH0sCiRTOjE5fQpQLkRuLnBy
+b3RvdHlwZT17CmdrdTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmJ9LApnSmY6ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcy5jCmlmKHQ9PW51bGwpcmV0dXJuIiIKaWYoQy54Qi5uKHQsIlsiKSlyZXR1cm4gQy54Qi5O
+aih0LDEsdC5sZW5ndGgtMSkKcmV0dXJuIHR9LApndHA6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5kCmlm
+KHQ9PW51bGwpcmV0dXJuIFAud0sodGhpcy5hKQpyZXR1cm4gdH0sCmd0UDpmdW5jdGlvbigpe3ZhciB0
+PXRoaXMuZgpyZXR1cm4gdD09bnVsbD8iIjp0fSwKZ0thOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yCnJl
+dHVybiB0PT1udWxsPyIiOnR9LApubTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbD10
+aGlzCnUuWC5iKG51bGwpCnUuYi5iKGIpCnQ9bC5hCnM9dD09PSJmaWxlIgpyPWwuYgpxPWwuZApwPWwu
+YwppZighKHAhPW51bGwpKXA9ci5sZW5ndGghPT0wfHxxIT1udWxsfHxzPyIiOm51bGwKbz1sLmUKaWYo
+IXMpbj1wIT1udWxsJiZvLmxlbmd0aCE9PTAKZWxzZSBuPSEwCmlmKG4mJiFDLnhCLm4obywiLyIpKW89
+Ii8iK28KaWYoYiE9bnVsbCltPVAubGUobnVsbCwwLDAsYikKZWxzZSBtPWwuZgpyZXR1cm4gbmV3IFAu
+RG4odCxyLHAscSxvLG0sbC5yKX0sCmdGajpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcy54CmlmKHMhPW51
+bGwpcmV0dXJuIHMKdD10aGlzLmUKaWYodC5sZW5ndGghPT0wJiZDLnhCLlcodCwwKT09PTQ3KXQ9Qy54
+Qi5HKHQsMSkKcz10PT09IiI/Qy5kbjpQLkFGKG5ldyBILkE4KEguVk0odC5zcGxpdCgiLyIpLHUucyks
+dS5kTy5iKFAuUEgoKSksdS5kbyksdS5OKQp0aGlzLnNvNihzKQpyZXR1cm4gc30sCmdoWTpmdW5jdGlv
+bigpe3ZhciB0LHM9dGhpcwppZihzLlE9PW51bGwpe3Q9cy5mCnMuc1JIKG5ldyBQLkdqKFAuV1godD09
+bnVsbD8iIjp0KSx1LlQpKX1yZXR1cm4gcy5RfSwKSmg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxw
+LG8KZm9yKHQ9MCxzPTA7Qy54Qi5RaShiLCIuLi8iLHMpOyl7cys9MzsrK3R9cj1DLnhCLmNuKGEsIi8i
+KQp3aGlsZSghMCl7aWYoIShyPjAmJnQ+MCkpYnJlYWsKcT1DLnhCLlBrKGEsIi8iLHItMSkKaWYocTww
+KWJyZWFrCnA9ci1xCm89cCE9PTIKaWYoIW98fHA9PT0zKWlmKEMueEIubShhLHErMSk9PT00NilvPSFv
+fHxDLnhCLm0oYSxxKzIpPT09NDYKZWxzZSBvPSExCmVsc2Ugbz0hMQppZihvKWJyZWFrOy0tdApyPXF9
+cmV0dXJuIEMueEIuaTcoYSxyKzEsbnVsbCxDLnhCLkcoYixzLTMqdCkpfSwKWkk6ZnVuY3Rpb24oYSl7
+cmV0dXJuIHRoaXMubVMoUC5oSyhhKSl9LAptUzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixt
+LGwsaz10aGlzLGo9bnVsbAppZihhLmdGaSgpLmxlbmd0aCE9PTApe3Q9YS5nRmkoKQppZihhLmdjaigp
+KXtzPWEuZ2t1KCkKcj1hLmdKZihhKQpxPWEuZ3hBKCk/YS5ndHAoYSk6an1lbHNle3E9agpyPXEKcz0i
+In1wPVAueGUoYS5nSWkoYSkpCm89YS5nUUQoKT9hLmd0UCgpOmp9ZWxzZXt0PWsuYQppZihhLmdjaigp
+KXtzPWEuZ2t1KCkKcj1hLmdKZihhKQpxPVAud0IoYS5neEEoKT9hLmd0cChhKTpqLHQpCnA9UC54ZShh
+LmdJaShhKSkKbz1hLmdRRCgpP2EuZ3RQKCk6an1lbHNle3M9ay5iCnI9ay5jCnE9ay5kCmlmKGEuZ0lp
+KGEpPT09IiIpe3A9ay5lCm89YS5nUUQoKT9hLmd0UCgpOmsuZn1lbHNle2lmKGEuZ3RUKCkpcD1QLnhl
+KGEuZ0lpKGEpKQplbHNle249ay5lCmlmKG4ubGVuZ3RoPT09MClpZihyPT1udWxsKXA9dC5sZW5ndGg9
+PT0wP2EuZ0lpKGEpOlAueGUoYS5nSWkoYSkpCmVsc2UgcD1QLnhlKCIvIithLmdJaShhKSkKZWxzZXtt
+PWsuSmgobixhLmdJaShhKSkKbD10Lmxlbmd0aD09PTAKaWYoIWx8fHIhPW51bGx8fEMueEIubihuLCIv
+IikpcD1QLnhlKG0pCmVsc2UgcD1QLndGKG0sIWx8fHIhPW51bGwpfX1vPWEuZ1FEKCk/YS5ndFAoKTpq
+fX19cmV0dXJuIG5ldyBQLkRuKHQscyxyLHEscCxvLGEuZ1o4KCk/YS5nS2EoKTpqKX0sCmdjajpmdW5j
+dGlvbigpe3JldHVybiB0aGlzLmMhPW51bGx9LApneEE6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kIT1u
+dWxsfSwKZ1FEOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZiE9bnVsbH0sCmdaODpmdW5jdGlvbigpe3Jl
+dHVybiB0aGlzLnIhPW51bGx9LApndFQ6ZnVuY3Rpb24oKXtyZXR1cm4gQy54Qi5uKHRoaXMuZSwiLyIp
+fSwKdDQ6ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcyxxPXIuYQppZihxIT09IiImJnEhPT0iZmlsZSIp
+dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSAiK0guZChxKSsi
+IFVSSSIpKQpxPXIuZgppZigocT09bnVsbD8iIjpxKSE9PSIiKXRocm93IEguYihQLkw0KCJDYW5ub3Qg
+ZXh0cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgVVJJIHdpdGggYSBxdWVyeSBjb21wb25lbnQiKSkKcT1y
+LnIKaWYoKHE9PW51bGw/IiI6cSkhPT0iIil0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBm
+aWxlIHBhdGggZnJvbSBhIFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50IikpCnQ9JC53USgpCmlm
+KEgub1QodCkpcT1QLm1uKHIpCmVsc2V7aWYoci5jIT1udWxsJiZyLmdKZihyKSE9PSIiKUgudmgoUC5M
+NCgiQ2Fubm90IGV4dHJhY3QgYSBub24tV2luZG93cyBmaWxlIHBhdGggZnJvbSBhIGZpbGUgVVJJIHdp
+dGggYW4gYXV0aG9yaXR5IikpCnM9ci5nRmooKQpQLmtFKHMsITEpCnE9UC52ZyhDLnhCLm4oci5lLCIv
+Iik/Ii8iOiIiLHMsIi8iKQpxPXEuY2hhckNvZGVBdCgwKT09MD9xOnF9cmV0dXJuIHF9LAp3OmZ1bmN0
+aW9uKGEpe3ZhciB0LHMscixxPXRoaXMscD1xLnkKaWYocD09bnVsbCl7cD1xLmEKdD1wLmxlbmd0aCE9
+PTA/cCsiOiI6IiIKcz1xLmMKcj1zPT1udWxsCmlmKCFyfHxwPT09ImZpbGUiKXtwPXQrIi8vIgp0PXEu
+YgppZih0Lmxlbmd0aCE9PTApcD1wK3QrIkAiCmlmKCFyKXArPXMKdD1xLmQKaWYodCE9bnVsbClwPXAr
+IjoiK0guZCh0KX1lbHNlIHA9dApwKz1xLmUKdD1xLmYKaWYodCE9bnVsbClwPXArIj8iK3QKdD1xLnIK
+aWYodCE9bnVsbClwPXArIiMiK3QKcD1xLnk9cC5jaGFyQ29kZUF0KDApPT0wP3A6cH1yZXR1cm4gcH0s
+CkROOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXRoaXMKaWYoYj09bnVsbClyZXR1cm4hMQppZihyPT09
+YilyZXR1cm4hMAppZih1LkQuYyhiKSlpZihyLmE9PWIuZ0ZpKCkpaWYoci5jIT1udWxsPT09Yi5nY2oo
+KSlpZihyLmI9PWIuZ2t1KCkpaWYoci5nSmYocik9PWIuZ0pmKGIpKWlmKHIuZ3RwKHIpPT1iLmd0cChi
+KSlpZihyLmU9PT1iLmdJaShiKSl7dD1yLmYKcz10PT1udWxsCmlmKCFzPT09Yi5nUUQoKSl7aWYocyl0
+PSIiCmlmKHQ9PT1iLmd0UCgpKXt0PXIucgpzPXQ9PW51bGwKaWYoIXM9PT1iLmdaOCgpKXtpZihzKXQ9
+IiIKdD10PT09Yi5nS2EoKX1lbHNlIHQ9ITF9ZWxzZSB0PSExfWVsc2UgdD0hMX1lbHNlIHQ9ITEKZWxz
+ZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITEKcmV0
+dXJuIHR9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy56CnJldHVybiB0PT1udWxsP3RoaXMuej1D
+LnhCLmdpTyh0aGlzLncoMCkpOnR9LApzbzY6ZnVuY3Rpb24oYSl7dGhpcy54PXUuYS5iKGEpfSwKc1JI
+OmZ1bmN0aW9uKGEpe3RoaXMuUT11LmYuYihhKX0sCiRpaUQ6MSwKZ0ZpOmZ1bmN0aW9uKCl7cmV0dXJu
+IHRoaXMuYX0sCmdJaTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5lfX0KUC5lMS5wcm90b3R5cGU9ewok
+MTpmdW5jdGlvbihhKXt0aHJvdyBILmIoUC5ycigiSW52YWxpZCBwb3J0Iix0aGlzLmEsdGhpcy5iKzEp
+KX0sCiRTOjE0fQpQLk5ZLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PSJJbGxlZ2FsIHBh
+dGggY2hhcmFjdGVyICIKSC55KGEpCmlmKEouemwoYSwiLyIpKWlmKHRoaXMuYSl0aHJvdyBILmIoUC54
+WSh0K2EpKQplbHNlIHRocm93IEguYihQLkw0KHQrYSkpfSwKJFM6MTR9ClAuUloucHJvdG90eXBlPXsK
+JDE6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuZVAoQy5aSixhLEMueE0sITEpfSwKJFM6NH0KUC5NRS5wcm90
+b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYixzPXRoaXMuYQp0LmErPXMuYQpzLmE9
+IiYiCnM9dC5hKz1ILmQoUC5lUChDLkYzLGEsQy54TSwhMCkpCmlmKGIhPW51bGwmJmIubGVuZ3RoIT09
+MCl7dC5hPXMrIj0iCnQuYSs9SC5kKFAuZVAoQy5GMyxiLEMueE0sITApKX19LAokUzoyMn0KUC55NS5w
+cm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0LHMKSC55KGEpCmlmKGI9PW51bGx8fHR5cGVv
+ZiBiPT0ic3RyaW5nIil0aGlzLmEuJDIoYSxILnkoYikpCmVsc2UgZm9yKHQ9Si5JVCh1LlIuYihiKSks
+cz10aGlzLmE7dC5GKCk7KXMuJDIoYSxILnkodC5nbCgpKSl9LAokUzoxM30KUC5QRS5wcm90b3R5cGU9
+ewpnbFI6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1udWxsLG49cC5jCmlmKG4hPW51bGwp
+cmV0dXJuIG4Kbj1wLmIKaWYoMD49bi5sZW5ndGgpcmV0dXJuIEguT0gobiwwKQp0PXAuYQpuPW5bMF0r
+MQpzPUMueEIuWFUodCwiPyIsbikKcj10Lmxlbmd0aAppZihzPj0wKXtxPVAudU8odCxzKzEscixDLlZD
+LCExKQpyPXN9ZWxzZSBxPW8KcmV0dXJuIHAuYz1uZXcgUC5xZSgiZGF0YSIsbyxvLG8sUC51Tyh0LG4s
+cixDLldkLCExKSxxLG8pfSwKdzpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMuYgppZigwPj1zLmxlbmd0
+aClyZXR1cm4gSC5PSChzLDApCnQ9dGhpcy5hCnJldHVybiBzWzBdPT09LTE/ImRhdGE6Iit0OnR9fQpQ
+LnEzLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVWludDhBcnJheSg5Nil9LAok
+UzoyM30KUC55SS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYQppZihhPj10
+Lmxlbmd0aClyZXR1cm4gSC5PSCh0LGEpCnQ9dFthXQpKLkNNKHQsMCw5NixiKQpyZXR1cm4gdH0sCiRT
+OjI0fQpQLmM2LnByb3RvdHlwZT17CiQzOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQpmb3IodD1i
+Lmxlbmd0aCxzPWEubGVuZ3RoLHI9MDtyPHQ7KytyKXtxPUMueEIuVyhiLHIpXjk2CmlmKHE+PXMpcmV0
+dXJuIEguT0goYSxxKQphW3FdPWN9fX0KUC5xZC5wcm90b3R5cGU9ewokMzpmdW5jdGlvbihhLGIsYyl7
+dmFyIHQscyxyLHEKZm9yKHQ9Qy54Qi5XKGIsMCkscz1DLnhCLlcoYiwxKSxyPWEubGVuZ3RoO3Q8PXM7
+Kyt0KXtxPSh0Xjk2KT4+PjAKaWYocT49cilyZXR1cm4gSC5PSChhLHEpCmFbcV09Y319fQpQLlVmLnBy
+b3RvdHlwZT17CmdjajpmdW5jdGlvbigpe3JldHVybiB0aGlzLmM+MH0sCmd4QTpmdW5jdGlvbigpe3Zh
+ciB0LHMKaWYodGhpcy5jPjApe3Q9dGhpcy5kCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQu
+aCgpCnM9dGhpcy5lCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIEgucFkocykKcz10KzE8cwp0
+PXN9ZWxzZSB0PSExCnJldHVybiB0fSwKZ1FEOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5mCmlmKHR5cGVv
+ZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCnJldHVybiB0PHRoaXMucn0sCmdaODpmdW5jdGlvbigp
+e3JldHVybiB0aGlzLnI8dGhpcy5hLmxlbmd0aH0sCmdOdzpmdW5jdGlvbigpe3JldHVybiB0aGlzLmI9
+PT00JiZDLnhCLm4odGhpcy5hLCJmaWxlIil9LApndmg6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09
+NCYmQy54Qi5uKHRoaXMuYSwiaHR0cCIpfSwKZ3FCOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTUm
+JkMueEIubih0aGlzLmEsImh0dHBzIil9LApndFQ6ZnVuY3Rpb24oKXtyZXR1cm4gQy54Qi5RaSh0aGlz
+LmEsIi8iLHRoaXMuZSl9LApnRmk6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMscj0icGFja2FnZSIscT1z
+LmIKaWYocTw9MClyZXR1cm4iIgp0PXMueAppZih0IT1udWxsKXJldHVybiB0CmlmKHMuZ3ZoKCkpcT1z
+Lng9Imh0dHAiCmVsc2UgaWYocy5ncUIoKSl7cy54PSJodHRwcyIKcT0iaHR0cHMifWVsc2UgaWYocy5n
+TncoKSl7cy54PSJmaWxlIgpxPSJmaWxlIn1lbHNlIGlmKHE9PT03JiZDLnhCLm4ocy5hLHIpKXtzLng9
+cgpxPXJ9ZWxzZXtxPUMueEIuTmoocy5hLDAscSkKcy54PXF9cmV0dXJuIHF9LApna3U6ZnVuY3Rpb24o
+KXt2YXIgdD10aGlzLmMscz10aGlzLmIrMwpyZXR1cm4gdD5zP0MueEIuTmoodGhpcy5hLHMsdC0xKToi
+In0sCmdKZjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmMKcmV0dXJuIHQ+MD9DLnhCLk5qKHRoaXMuYSx0
+LHRoaXMuZCk6IiJ9LApndHA6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzCmlmKHMuZ3hBKCkpe3Q9cy5k
+CmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCnJldHVybiBQLlFBKEMueEIuTmoocy5h
+LHQrMSxzLmUpLG51bGwsbnVsbCl9aWYocy5ndmgoKSlyZXR1cm4gODAKaWYocy5ncUIoKSlyZXR1cm4g
+NDQzCnJldHVybiAwfSwKZ0lpOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLk5qKHRoaXMuYSx0aGlzLmUs
+dGhpcy5mKX0sCmd0UDpmdW5jdGlvbigpe3ZhciB0PXRoaXMuZixzPXRoaXMucgppZih0eXBlb2YgdCE9
+PSJudW1iZXIiKXJldHVybiB0LkooKQpyZXR1cm4gdDxzP0MueEIuTmoodGhpcy5hLHQrMSxzKToiIn0s
+CmdLYTpmdW5jdGlvbigpe3ZhciB0PXRoaXMucixzPXRoaXMuYQpyZXR1cm4gdDxzLmxlbmd0aD9DLnhC
+Lkcocyx0KzEpOiIifSwKZ0ZqOmZ1bmN0aW9uKCl7dmFyIHQscyxyPXRoaXMuZSxxPXRoaXMuZixwPXRo
+aXMuYQppZihDLnhCLlFpKHAsIi8iLHIpKXtpZih0eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiByLmgo
+KTsrK3J9aWYocj09cSlyZXR1cm4gQy5kbgp0PUguVk0oW10sdS5zKQpzPXIKd2hpbGUoITApe2lmKHR5
+cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMuSigpCmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJu
+IEgucFkocSkKaWYoIShzPHEpKWJyZWFrCmlmKEMueEIubShwLHMpPT09NDcpe0MuTm0uaSh0LEMueEIu
+TmoocCxyLHMpKQpyPXMrMX0rK3N9Qy5ObS5pKHQsQy54Qi5OaihwLHIscSkpCnJldHVybiBQLkFGKHQs
+dS5OKX0sCmdoWTpmdW5jdGlvbigpe3ZhciB0PXRoaXMuZgppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJl
+dHVybiB0LkooKQppZih0Pj10aGlzLnIpcmV0dXJuIEMuV08KcmV0dXJuIG5ldyBQLkdqKFAuV1godGhp
+cy5ndFAoKSksdS5UKX0sCmtYOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5kCmlmKHR5cGVvZiBzIT09
+Im51bWJlciIpcmV0dXJuIHMuaCgpCnQ9cysxCnJldHVybiB0K2EubGVuZ3RoPT09dGhpcy5lJiZDLnhC
+LlFpKHRoaXMuYSxhLHQpfSwKTjk6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5yLHI9dC5hCmlmKHM+
+PXIubGVuZ3RoKXJldHVybiB0CnJldHVybiBuZXcgUC5VZihDLnhCLk5qKHIsMCxzKSx0LmIsdC5jLHQu
+ZCx0LmUsdC5mLHMsdC54KX0sCm5tOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbSxsLGss
+aixpPXRoaXMsaD1udWxsCnUuWC5iKG51bGwpCnUuYi5iKGIpCnQ9aS5nRmkoKQpzPXQ9PT0iZmlsZSIK
+cj1pLmMKcT1yPjA/Qy54Qi5OaihpLmEsaS5iKzMscik6IiIKcD1pLmd4QSgpP2kuZ3RwKGkpOmgKcj1p
+LmMKaWYocj4wKW89Qy54Qi5OaihpLmEscixpLmQpCmVsc2Ugbz1xLmxlbmd0aCE9PTB8fHAhPW51bGx8
+fHM/IiI6aApyPWkuYQpuPWkuZgptPUMueEIuTmoocixpLmUsbikKaWYoIXMpbD1vIT1udWxsJiZtLmxl
+bmd0aCE9PTAKZWxzZSBsPSEwCmlmKGwmJiFDLnhCLm4obSwiLyIpKW09Ii8iK20KaWYoYiE9bnVsbClr
+PVAubGUoaCwwLDAsYikKZWxzZXtsPWkucgppZih0eXBlb2YgbiE9PSJudW1iZXIiKXJldHVybiBuLkoo
+KQprPW48bD9DLnhCLk5qKHIsbisxLGwpOmh9bj1pLnIKaj1uPHIubGVuZ3RoP0MueEIuRyhyLG4rMSk6
+aApyZXR1cm4gbmV3IFAuRG4odCxxLG8scCxtLGssail9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
+cy5tUyhQLmhLKGEpKX0sCm1TOmZ1bmN0aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBQLlVmKXJldHVybiB0
+aGlzLnUxKHRoaXMsYSkKcmV0dXJuIHRoaXMuUmUoKS5tUyhhKX0sCnUxOmZ1bmN0aW9uKGEsYil7dmFy
+IHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGU9Yi5iCmlmKGU+MClyZXR1cm4gYgp0PWIuYwpp
+Zih0PjApe3M9YS5iCmlmKHM8PTApcmV0dXJuIGIKaWYoYS5nTncoKSlyPWIuZSE9Yi5mCmVsc2UgaWYo
+YS5ndmgoKSlyPSFiLmtYKCI4MCIpCmVsc2Ugcj0hYS5ncUIoKXx8IWIua1goIjQ0MyIpCmlmKHIpe3E9
+cysxCnA9Qy54Qi5OaihhLmEsMCxxKStDLnhCLkcoYi5hLGUrMSkKZT1iLmQKaWYodHlwZW9mIGUhPT0i
+bnVtYmVyIilyZXR1cm4gZS5oKCkKbz1iLmUKaWYodHlwZW9mIG8hPT0ibnVtYmVyIilyZXR1cm4gby5o
+KCkKbj1iLmYKaWYodHlwZW9mIG4hPT0ibnVtYmVyIilyZXR1cm4gbi5oKCkKcmV0dXJuIG5ldyBQLlVm
+KHAscyx0K3EsZStxLG8rcSxuK3EsYi5yK3EsYS54KX1lbHNlIHJldHVybiB0aGlzLlJlKCkubVMoYil9
+bT1iLmUKZT1iLmYKaWYobT09ZSl7dD1iLnIKaWYodHlwZW9mIGUhPT0ibnVtYmVyIilyZXR1cm4gZS5K
+KCkKaWYoZTx0KXtzPWEuZgppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLkhOKCkKcT1zLWUK
+cmV0dXJuIG5ldyBQLlVmKEMueEIuTmooYS5hLDAscykrQy54Qi5HKGIuYSxlKSxhLmIsYS5jLGEuZCxh
+LmUsZStxLHQrcSxhLngpfWU9Yi5hCmlmKHQ8ZS5sZW5ndGgpe3M9YS5yCnJldHVybiBuZXcgUC5VZihD
+LnhCLk5qKGEuYSwwLHMpK0MueEIuRyhlLHQpLGEuYixhLmMsYS5kLGEuZSxhLmYsdCsocy10KSxhLngp
+fXJldHVybiBhLk45KCl9dD1iLmEKaWYoQy54Qi5RaSh0LCIvIixtKSl7cz1hLmUKaWYodHlwZW9mIHMh
+PT0ibnVtYmVyIilyZXR1cm4gcy5ITigpCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIEgucFko
+bSkKcT1zLW0KcD1DLnhCLk5qKGEuYSwwLHMpK0MueEIuRyh0LG0pCmlmKHR5cGVvZiBlIT09Im51bWJl
+ciIpcmV0dXJuIGUuaCgpCnJldHVybiBuZXcgUC5VZihwLGEuYixhLmMsYS5kLHMsZStxLGIucitxLGEu
+eCl9bD1hLmUKaz1hLmYKaWYobD09ayYmYS5jPjApe2Zvcig7Qy54Qi5RaSh0LCIuLi8iLG0pOyl7aWYo
+dHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gbS5oKCkKbSs9M31pZih0eXBlb2YgbCE9PSJudW1iZXIi
+KXJldHVybiBsLkhOKCkKaWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gSC5wWShtKQpxPWwtbSsx
+CnA9Qy54Qi5OaihhLmEsMCxsKSsiLyIrQy54Qi5HKHQsbSkKaWYodHlwZW9mIGUhPT0ibnVtYmVyIily
+ZXR1cm4gZS5oKCkKcmV0dXJuIG5ldyBQLlVmKHAsYS5iLGEuYyxhLmQsbCxlK3EsYi5yK3EsYS54KX1q
+PWEuYQpmb3IoaT1sO0MueEIuUWkoaiwiLi4vIixpKTspe2lmKHR5cGVvZiBpIT09Im51bWJlciIpcmV0
+dXJuIGkuaCgpCmkrPTN9aD0wCndoaWxlKCEwKXtpZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBt
+LmgoKQpnPW0rMwppZih0eXBlb2YgZSE9PSJudW1iZXIiKXJldHVybiBILnBZKGUpCmlmKCEoZzw9ZSYm
+Qy54Qi5RaSh0LCIuLi8iLG0pKSlicmVhazsrK2gKbT1nfWY9IiIKd2hpbGUoITApe2lmKHR5cGVvZiBr
+IT09Im51bWJlciIpcmV0dXJuIGsub3MoKQppZih0eXBlb2YgaSE9PSJudW1iZXIiKXJldHVybiBILnBZ
+KGkpCmlmKCEoaz5pKSlicmVhazstLWsKaWYoQy54Qi5tKGosayk9PT00Nyl7aWYoaD09PTApe2Y9Ii8i
+CmJyZWFrfS0taApmPSIvIn19aWYoaz09PWkmJmEuYjw9MCYmIUMueEIuUWkoaiwiLyIsbCkpe20tPWgq
+MwpmPSIifXE9ay1tK2YubGVuZ3RoCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGosMCxrKStmK0MueEIu
+Ryh0LG0pLGEuYixhLmMsYS5kLGwsZStxLGIucitxLGEueCl9LAp0NDpmdW5jdGlvbigpe3ZhciB0LHMs
+cixxLHA9dGhpcwppZihwLmI+PTAmJiFwLmdOdygpKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFj
+dCBhIGZpbGUgcGF0aCBmcm9tIGEgIitILmQocC5nRmkoKSkrIiBVUkkiKSkKdD1wLmYKcz1wLmEKaWYo
+dHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5KKCkKaWYodDxzLmxlbmd0aCl7aWYodDxwLnIpdGhy
+b3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBhIHF1
+ZXJ5IGNvbXBvbmVudCIpKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGgg
+ZnJvbSBhIFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50IikpfXI9JC53USgpCmlmKEgub1Qocikp
+dD1QLm1uKHApCmVsc2V7cT1wLmQKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShxKQpp
+ZihwLmM8cSlILnZoKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgbm9uLVdpbmRvd3MgZmlsZSBwYXRoIGZy
+b20gYSBmaWxlIFVSSSB3aXRoIGFuIGF1dGhvcml0eSIpKQp0PUMueEIuTmoocyxwLmUsdCl9cmV0dXJu
+IHR9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy55CnJldHVybiB0PT1udWxsP3RoaXMueT1DLnhC
+LmdpTyh0aGlzLmEpOnR9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKaWYodGhp
+cz09PWIpcmV0dXJuITAKcmV0dXJuIHUuRC5jKGIpJiZ0aGlzLmE9PT1iLncoMCl9LApSZTpmdW5jdGlv
+bigpe3ZhciB0PXRoaXMscz1udWxsLHI9dC5nRmkoKSxxPXQuZ2t1KCkscD10LmM+MD90LmdKZih0KTpz
+LG89dC5neEEoKT90Lmd0cCh0KTpzLG49dC5hLG09dC5mLGw9Qy54Qi5OaihuLHQuZSxtKSxrPXQucgpp
+Zih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLkooKQptPW08az90Lmd0UCgpOnMKcmV0dXJuIG5l
+dyBQLkRuKHIscSxwLG8sbCxtLGs8bi5sZW5ndGg/dC5nS2EoKTpzKX0sCnc6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHRoaXMuYX0sCiRpaUQ6MX0KUC5xZS5wcm90b3R5cGU9e30KVy5xRS5wcm90b3R5cGU9e30KVy5H
+aC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LAokaUdoOjF9ClcuZlku
+cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfX0KVy5uQi5wcm90b3R5cGU9
+eyRpbkI6MX0KVy5Bei5wcm90b3R5cGU9eyRpQXo6MX0KVy5RUC5wcm90b3R5cGU9eyRpUVA6MX0KVy5u
+eC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLm9KLnByb3RvdHlw
+ZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClcuaWQucHJvdG90eXBlPXt9ClcuUUYu
+cHJvdG90eXBlPXt9ClcuTmgucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEp
+fX0KVy5JQi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJSZWN0YW5nbGUgKCIrSC5kKGEu
+bGVmdCkrIiwgIitILmQoYS50b3ApKyIpICIrSC5kKGEud2lkdGgpKyIgeCAiK0guZChhLmhlaWdodCl9
+LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIHUucS5jKGIpJiZhLmxl
+ZnQ9PT1iLmxlZnQmJmEudG9wPT09Yi50b3AmJmEud2lkdGg9PT1iLndpZHRoJiZhLmhlaWdodD09PWIu
+aGVpZ2h0fSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBXLnJFKEMuQ0QuZ2lPKGEubGVmdCksQy5DRC5n
+aU8oYS50b3ApLEMuQ0QuZ2lPKGEud2lkdGgpLEMuQ0QuZ2lPKGEuaGVpZ2h0KSl9LAokaXRuOjF9Clcu
+bjcucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy53ei5wcm90b3R5
+cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXt2
+YXIgdApILlNjKGIpCnQ9dGhpcy5hCmlmKGI8MHx8Yj49dC5sZW5ndGgpcmV0dXJuIEguT0godCxiKQpy
+ZXR1cm4gdGhpcy4kdGkuZC5iKHRbYl0pfSwKWTpmdW5jdGlvbihhLGIsYyl7dGhpcy4kdGkuZC5iKGMp
+CnRocm93IEguYihQLkw0KCJDYW5ub3QgbW9kaWZ5IGxpc3QiKSl9fQpXLmN2LnByb3RvdHlwZT17CmdR
+ZzpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuaTcoYSl9LApnRDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3
+IFcuSTQoYSl9LApzRDpmdW5jdGlvbihhLGIpe3ZhciB0CnUuWC5iKGIpCnQ9dGhpcy5nRChhKQp0LlYx
+KDApCnQuRlYoMCxiKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubG9jYWxOYW1lfSwKdG46ZnVuY3Rp
+b24oYSl7dmFyIHQ9ISFhLnNjcm9sbEludG9WaWV3SWZOZWVkZWQKaWYodClhLnNjcm9sbEludG9WaWV3
+SWZOZWVkZWQoKQplbHNlIGEuc2Nyb2xsSW50b1ZpZXcoKX0sCnI2OmZ1bmN0aW9uKGEsYixjLGQpe3Zh
+ciB0LHMscixxCmlmKGM9PW51bGwpe2lmKGQ9PW51bGwpe3Q9JC5sdAppZih0PT1udWxsKXt0PUguVk0o
+W10sdS5rKQpzPW5ldyBXLnZEKHQpCkMuTm0uaSh0LFcuVHcobnVsbCkpCkMuTm0uaSh0LFcuQmwoKSkK
+JC5sdD1zCmQ9c31lbHNlIGQ9dH10PSQuRVUKaWYodD09bnVsbCl7dD1uZXcgVy5LbyhkKQokLkVVPXQK
+Yz10fWVsc2V7dC5hPWQKYz10fX1lbHNlIGlmKGQhPW51bGwpdGhyb3cgSC5iKFAueFkoInZhbGlkYXRv
+ciBjYW4gb25seSBiZSBwYXNzZWQgaWYgdHJlZVNhbml0aXplciBpcyBudWxsIikpCmlmKCQueG89PW51
+bGwpe3Q9ZG9jdW1lbnQKcz10LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxEb2N1bWVudCgiIikKJC54
+bz1zCiQuQk89cy5jcmVhdGVSYW5nZSgpCnM9JC54by5jcmVhdGVFbGVtZW50KCJiYXNlIikKdS5jUi5i
+KHMpCnMuaHJlZj10LmJhc2VVUkkKJC54by5oZWFkLmFwcGVuZENoaWxkKHMpfXQ9JC54bwppZih0LmJv
+ZHk9PW51bGwpe3M9dC5jcmVhdGVFbGVtZW50KCJib2R5IikKdC5ib2R5PXUuWS5iKHMpfXQ9JC54bwpp
+Zih1LlkuYyhhKSlyPXQuYm9keQplbHNle3I9dC5jcmVhdGVFbGVtZW50KGEudGFnTmFtZSkKJC54by5i
+b2R5LmFwcGVuZENoaWxkKHIpfWlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5S
+YW5nZS5wcm90b3R5cGUmJiFDLk5tLnRnKEMuU3EsYS50YWdOYW1lKSl7JC5CTy5zZWxlY3ROb2RlQ29u
+dGVudHMocikKcT0kLkJPLmNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudChiKX1lbHNle3IuaW5uZXJIVE1M
+PWIKcT0kLnhvLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpmb3IoO3Q9ci5maXJzdENoaWxkLHQhPW51
+bGw7KXEuYXBwZW5kQ2hpbGQodCl9dD0kLnhvLmJvZHkKaWYocj09bnVsbD90IT1udWxsOnIhPT10KUou
+THQocikKYy5QbihxKQpkb2N1bWVudC5hZG9wdE5vZGUocSkKcmV0dXJuIHF9LApBSDpmdW5jdGlvbihh
+LGIsYyl7cmV0dXJuIHRoaXMucjYoYSxiLGMsbnVsbCl9LApzaGY6ZnVuY3Rpb24oYSxiKXt0aGlzLllD
+KGEsYil9LApwazpmdW5jdGlvbihhLGIsYyl7YS50ZXh0Q29udGVudD1udWxsCmEuYXBwZW5kQ2hpbGQo
+dGhpcy5yNihhLGIsbnVsbCxjKSl9LApZQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnBrKGEsYixu
+dWxsKX0sCmdWbDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuQ3EoYSwiY2xpY2siLCExLHUuUSl9LAok
+aWN2OjEsCmduczpmdW5jdGlvbihhKXtyZXR1cm4gYS50YWdOYW1lfX0KVy5Ddi5wcm90b3R5cGU9ewok
+MTpmdW5jdGlvbihhKXtyZXR1cm4gdS5oLmModS5BLmIoYSkpfSwKJFM6MjV9ClcuZWEucHJvdG90eXBl
+PXskaWVhOjF9ClcuRDAucHJvdG90eXBlPXsKT246ZnVuY3Rpb24oYSxiLGMsZCl7dS5VLmIoYykKaWYo
+YyE9bnVsbCl0aGlzLnYoYSxiLGMsZCl9LApCOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gdGhpcy5Pbihh
+LGIsYyxudWxsKX0sCnY6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGEuYWRkRXZlbnRMaXN0ZW5lcihi
+LEgudFIodS5VLmIoYyksMSksZCl9LAokaUQwOjF9ClcuVDUucHJvdG90eXBlPXskaVQ1OjF9ClcuaDQu
+cHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5ici5wcm90b3R5cGU9
+ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLlZiLnByb3RvdHlwZT17fQpXLk83LnBy
+b3RvdHlwZT17CmVvOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBhLm9wZW4oYixjLCEwKX0sCiRpTzc6
+MX0KVy5iVS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYS5zZXRSZXF1ZXN0SGVhZGVy
+KEgueShhKSxILnkoYikpfSwKJFM6OX0KVy5oSC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
+dCxzLHIscSxwCnUucC5iKGEpCnQ9dGhpcy5hCnM9dC5zdGF0dXMKaWYodHlwZW9mIHMhPT0ibnVtYmVy
+IilyZXR1cm4gcy50QigpCnI9cz49MjAwJiZzPDMwMApxPXM+MzA3JiZzPDQwMApzPXJ8fHM9PT0wfHxz
+PT09MzA0fHxxCnA9dGhpcy5iCmlmKHMpcC5hTSgwLHQpCmVsc2UgcC5wbShhKX0sCiRTOjI3fQpXLndh
+LnByb3RvdHlwZT17fQpXLlNnLnByb3RvdHlwZT17JGlTZzoxfQpXLnU4LnByb3RvdHlwZT17CmdEcjpm
+dW5jdGlvbihhKXtpZigib3JpZ2luIiBpbiBhKXJldHVybiBhLm9yaWdpbgpyZXR1cm4gSC5kKGEucHJv
+dG9jb2wpKyIvLyIrSC5kKGEuaG9zdCl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LAok
+aXU4OjF9ClcuQWoucHJvdG90eXBlPXskaUFqOjF9ClcuZTcucHJvdG90eXBlPXsKZ3I4OmZ1bmN0aW9u
+KGEpe3ZhciB0PXRoaXMuYSxzPXQuY2hpbGROb2Rlcy5sZW5ndGgKaWYocz09PTApdGhyb3cgSC5iKFAu
+UFYoIk5vIGVsZW1lbnRzIikpCmlmKHM+MSl0aHJvdyBILmIoUC5QVigiTW9yZSB0aGFuIG9uZSBlbGVt
+ZW50IikpCnJldHVybiB0LmZpcnN0Q2hpbGR9LApGVjpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxCnUu
+ZWguYihiKQp0PWIuYQpzPXRoaXMuYQppZih0IT09cylmb3Iocj10LmNoaWxkTm9kZXMubGVuZ3RoLHE9
+MDtxPHI7KytxKXMuYXBwZW5kQ2hpbGQodC5maXJzdENoaWxkKQpyZXR1cm59LApZOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdCxzCnUuQS5iKGMpCnQ9dGhpcy5hCnM9dC5jaGlsZE5vZGVzCmlmKGI8MHx8Yj49cy5s
+ZW5ndGgpcmV0dXJuIEguT0gocyxiKQp0LnJlcGxhY2VDaGlsZChjLHNbYl0pfSwKZ2t6OmZ1bmN0aW9u
+KGEpe3ZhciB0PXRoaXMuYS5jaGlsZE5vZGVzCnJldHVybiBuZXcgVy5XOSh0LHQubGVuZ3RoLEguekso
+dCkuQygiVzk8R20uRT4iKSl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmNoaWxkTm9kZXMu
+bGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe3ZhciB0CkguU2MoYikKdD10aGlzLmEuY2hpbGROb2Rlcwpp
+ZihiPDB8fGI+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsYikKcmV0dXJuIHRbYl19fQpXLnVILnByb3Rv
+dHlwZT17CndnOmZ1bmN0aW9uKGEpe3ZhciB0PWEucGFyZW50Tm9kZQppZih0IT1udWxsKXQucmVtb3Zl
+Q2hpbGQoYSl9LApENDpmdW5jdGlvbihhKXt2YXIgdApmb3IoO3Q9YS5maXJzdENoaWxkLHQhPW51bGw7
+KWEucmVtb3ZlQ2hpbGQodCl9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0PWEubm9kZVZhbHVlCnJldHVybiB0
+PT1udWxsP3RoaXMuVShhKTp0fSwKJGl1SDoxfQpXLkJILnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEp
+e3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILlNjKGIpCmlmKGI+Pj4wIT09Ynx8Yj49
+YS5sZW5ndGgpdGhyb3cgSC5iKFAuQ2YoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LApZ
+OmZ1bmN0aW9uKGEsYixjKXt1LkEuYihjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVt
+ZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sCkU6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVu
+Z3RoKXJldHVybiBILk9IKGEsYikKcmV0dXJuIGFbYl19LAokaVhqOjEsCiRpY1g6MSwKJGl6TToxfQpX
+LlNOLnByb3RvdHlwZT17fQpXLmV3LnByb3RvdHlwZT17JGlldzoxfQpXLmxwLnByb3RvdHlwZT17CmdB
+OmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClcuVGIucHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24o
+YSxiLGMsZCl7dmFyIHQscwppZigiY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFu
+Z2UucHJvdG90eXBlKXJldHVybiB0aGlzLkRXKGEsYixjLGQpCnQ9Vy5VOSgiPHRhYmxlPiIrSC5kKGIp
+KyI8L3RhYmxlPiIsYyxkKQpzPWRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpzLnRvU3Ry
+aW5nCnQudG9TdHJpbmcKbmV3IFcuZTcocykuRlYoMCxuZXcgVy5lNyh0KSkKcmV0dXJuIHN9fQpXLkl2
+LnByb3RvdHlwZT17CnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxCmlmKCJjcmVhdGVDb250
+ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxi
+LGMsZCkKdD1kb2N1bWVudApzPXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnQ9Qy5JZS5yNih0LmNy
+ZWF0ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnQudG9TdHJpbmcKdD1uZXcgVy5lNyh0KQpyPXQuZ3I4
+KHQpCnIudG9TdHJpbmcKdD1uZXcgVy5lNyhyKQpxPXQuZ3I4KHQpCnMudG9TdHJpbmcKcS50b1N0cmlu
+ZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHEpKQpyZXR1cm4gc319ClcuQlQucHJvdG90eXBlPXsK
+cjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQi
+IGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1kb2N1bWVu
+dApzPXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnQ9Qy5JZS5yNih0LmNyZWF0ZUVsZW1lbnQoInRh
+YmxlIiksYixjLGQpCnQudG9TdHJpbmcKdD1uZXcgVy5lNyh0KQpyPXQuZ3I4KHQpCnMudG9TdHJpbmcK
+ci50b1N0cmluZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHIpKQpyZXR1cm4gc319ClcueVkucHJv
+dG90eXBlPXsKcGs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKYS50ZXh0Q29udGVudD1udWxsCnQ9YS5j
+b250ZW50CnQudG9TdHJpbmcKSi5iVCh0KQpzPXRoaXMucjYoYSxiLG51bGwsYykKYS5jb250ZW50LmFw
+cGVuZENoaWxkKHMpfSwKWUM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5wayhhLGIsbnVsbCl9LAok
+aXlZOjF9ClcudzYucHJvdG90eXBlPXt9ClcuSzUucHJvdG90eXBlPXsKZ21XOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhLmxvY2F0aW9ufSwKJGlLNToxLAokaXY2OjF9ClcuQ20ucHJvdG90eXBlPXskaUNtOjF9Clcu
+Q1EucHJvdG90eXBlPXskaUNROjF9ClcudzQucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4i
+UmVjdGFuZ2xlICgiK0guZChhLmxlZnQpKyIsICIrSC5kKGEudG9wKSsiKSAiK0guZChhLndpZHRoKSsi
+IHggIitILmQoYS5oZWlnaHQpfSwKRE46ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCnJl
+dHVybiB1LnEuYyhiKSYmYS5sZWZ0PT09Yi5sZWZ0JiZhLnRvcD09PWIudG9wJiZhLndpZHRoPT09Yi53
+aWR0aCYmYS5oZWlnaHQ9PT1iLmhlaWdodH0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gVy5yRShDLkNE
+LmdpTyhhLmxlZnQpLEMuQ0QuZ2lPKGEudG9wKSxDLkNELmdpTyhhLndpZHRoKSxDLkNELmdpTyhhLmhl
+aWdodCkpfX0KVy5yaC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApx
+OmZ1bmN0aW9uKGEsYil7SC5TYyhiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQ
+LkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7dS5B
+LmIoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlz
+dC4iKSl9LApFOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5PSChhLGIp
+CnJldHVybiBhW2JdfSwKJGlYajoxLAokaWNYOjEsCiRpek06MX0KVy5EOS5wcm90b3R5cGU9ewpLOmZ1
+bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscAp1LkUuYihiKQpmb3IodD10aGlzLmdWKCkscz10Lmxlbmd0
+aCxyPXRoaXMuYSxxPTA7cTx0Lmxlbmd0aDt0Lmxlbmd0aD09PXN8fCgwLEgubGspKHQpLCsrcSl7cD10
+W3FdCmIuJDIocCxyLmdldEF0dHJpYnV0ZShwKSl9fSwKZ1Y6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxw
+PXRoaXMuYS5hdHRyaWJ1dGVzLG89SC5WTShbXSx1LnMpCmZvcih0PXAubGVuZ3RoLHM9dS5oOSxyPTA7
+cjx0Oysrcil7aWYocj49cC5sZW5ndGgpcmV0dXJuIEguT0gocCxyKQpxPXMuYihwW3JdKQppZihxLm5h
+bWVzcGFjZVVSST09bnVsbClDLk5tLmkobyxxLm5hbWUpfXJldHVybiBvfX0KVy5pNy5wcm90b3R5cGU9
+ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5nZXRBdHRyaWJ1dGUoSC55KGIpKX0sClk6ZnVu
+Y3Rpb24oYSxiLGMpe3RoaXMuYS5zZXRBdHRyaWJ1dGUoYixjKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVy
+biB0aGlzLmdWKCkubGVuZ3RofX0KVy5TeS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJu
+IHRoaXMuYS5hLmdldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMuTyhILnkoYikpKX0sClk6ZnVuY3Rpb24o
+YSxiLGMpe3RoaXMuYS5hLnNldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMuTyhiKSxjKX0sCks6ZnVuY3Rp
+b24oYSxiKXt0aGlzLmEuSygwLG5ldyBXLktTKHRoaXMsdS5FLmIoYikpKX0sCmdWOmZ1bmN0aW9uKCl7
+dmFyIHQ9SC5WTShbXSx1LnMpCnRoaXMuYS5LKDAsbmV3IFcuQTModGhpcyx0KSkKcmV0dXJuIHR9LApn
+QTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nVigpLmxlbmd0aH0sCms6ZnVuY3Rpb24oYSl7dmFyIHQs
+cyxyPUguVk0oYS5zcGxpdCgiLSIpLHUucykKZm9yKHQ9MTt0PHIubGVuZ3RoOysrdCl7cz1yW3RdCmlm
+KHMubGVuZ3RoPjApQy5ObS5ZKHIsdCxzWzBdLnRvVXBwZXJDYXNlKCkrSi5LVihzLDEpKX1yZXR1cm4g
+Qy5ObS5IKHIsIiIpfSwKTzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwCmZvcih0PWEubGVuZ3RoLHM9
+MCxyPSIiO3M8dDsrK3Mpe3E9YVtzXQpwPXEudG9Mb3dlckNhc2UoKQpyPShxIT09cCYmcz4wP3IrIi0i
+OnIpK3B9cmV0dXJuIHIuY2hhckNvZGVBdCgwKT09MD9yOnJ9fQpXLktTLnByb3RvdHlwZT17CiQyOmZ1
+bmN0aW9uKGEsYil7aWYoSi5yWShhKS5uKGEsImRhdGEtIikpdGhpcy5iLiQyKHRoaXMuYS5rKEMueEIu
+RyhhLDUpKSxiKX0sCiRTOjl9ClcuQTMucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtpZihKLnJZ
+KGEpLm4oYSwiZGF0YS0iKSlDLk5tLmkodGhpcy5iLHRoaXMuYS5rKEMueEIuRyhhLDUpKSl9LAokUzo5
+fQpXLkk0LnByb3RvdHlwZT17ClA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPVAuTHModS5OKQpmb3Io
+dD10aGlzLmEuY2xhc3NOYW1lLnNwbGl0KCIgIikscz10Lmxlbmd0aCxyPTA7cjxzOysrcil7cT1KLlQw
+KHRbcl0pCmlmKHEubGVuZ3RoIT09MClwLmkoMCxxKX1yZXR1cm4gcH0sClg6ZnVuY3Rpb24oYSl7dGhp
+cy5hLmNsYXNzTmFtZT11LkMuYihhKS5IKDAsIiAiKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
+LmEuY2xhc3NMaXN0Lmxlbmd0aH0sClYxOmZ1bmN0aW9uKGEpe3RoaXMuYS5jbGFzc05hbWU9IiJ9LAp0
+ZzpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYS5jbGFzc0xpc3QuY29udGFpbnMoYikKcmV0dXJuIHR9
+LAppOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNzTGlzdCxzPXQuY29udGFpbnMoYikKdC5h
+ZGQoYikKcmV0dXJuIXN9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNzTGlzdCxzPXQu
+Y29udGFpbnMoYikKdC5yZW1vdmUoYikKcmV0dXJuIHN9LApGVjpmdW5jdGlvbihhLGIpe1cuVE4odGhp
+cy5hLHUuWC5iKGIpKX19ClcuRmsucHJvdG90eXBlPXt9ClcuUk8ucHJvdG90eXBlPXt9ClcuQ3EucHJv
+dG90eXBlPXt9ClcueEMucHJvdG90eXBlPXt9Clcudk4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7
+cmV0dXJuIHRoaXMuYS4kMSh1LkIuYihhKSl9LAokUzoyOH0KVy5KUS5wcm90b3R5cGU9ewpDWTpmdW5j
+dGlvbihhKXt2YXIgdAppZigkLm9yLmE9PT0wKXtmb3IodD0wO3Q8MjYyOysrdCkkLm9yLlkoMCxDLmNt
+W3RdLFcucFMoKSkKZm9yKHQ9MDt0PDEyOysrdCkkLm9yLlkoMCxDLkJJW3RdLFcuVjQoKSl9fSwKaTA6
+ZnVuY3Rpb24oYSl7cmV0dXJuICQuQU4oKS50ZygwLFcuclMoYSkpfSwKRWI6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0PSQub3IucSgwLEguZChXLnJTKGEpKSsiOjoiK2IpCmlmKHQ9PW51bGwpdD0kLm9yLnEoMCwi
+Kjo6IitiKQppZih0PT1udWxsKXJldHVybiExCnJldHVybiBILnhkKHQuJDQoYSxiLGMsdGhpcykpfSwK
+JGlrRjoxfQpXLkdtLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuVzkoYSx0
+aGlzLmdBKGEpLEgueksoYSkuQygiVzk8R20uRT4iKSl9fQpXLnZELnByb3RvdHlwZT17CmkwOmZ1bmN0
+aW9uKGEpe3JldHVybiBDLk5tLlZyKHRoaXMuYSxuZXcgVy5VdihhKSl9LApFYjpmdW5jdGlvbihhLGIs
+Yyl7cmV0dXJuIEMuTm0uVnIodGhpcy5hLG5ldyBXLkVnKGEsYixjKSl9LAokaWtGOjF9ClcuVXYucHJv
+dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuZS5iKGEpLmkwKHRoaXMuYSl9LAokUzoxNX0K
+Vy5FZy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5lLmIoYSkuRWIodGhpcy5hLHRo
+aXMuYix0aGlzLmMpfSwKJFM6MTV9ClcubTYucHJvdG90eXBlPXsKQ1k6ZnVuY3Rpb24oYSxiLGMsZCl7
+dmFyIHQscyxyCnRoaXMuYS5GVigwLGMpCnQ9Yi5ldigwLG5ldyBXLkVvKCkpCnM9Yi5ldigwLG5ldyBX
+LldrKCkpCnRoaXMuYi5GVigwLHQpCnI9dGhpcy5jCnIuRlYoMCxDLmRuKQpyLkZWKDAscyl9LAppMDpm
+dW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLnRnKDAsVy5yUyhhKSl9LApFYjpmdW5jdGlvbihhLGIsYyl7
+dmFyIHQ9dGhpcyxzPVcuclMoYSkscj10LmMKaWYoci50ZygwLEguZChzKSsiOjoiK2IpKXJldHVybiB0
+LmQuRHQoYykKZWxzZSBpZihyLnRnKDAsIio6OiIrYikpcmV0dXJuIHQuZC5EdChjKQplbHNle3I9dC5i
+CmlmKHIudGcoMCxILmQocykrIjo6IitiKSlyZXR1cm4hMAplbHNlIGlmKHIudGcoMCwiKjo6IitiKSly
+ZXR1cm4hMAplbHNlIGlmKHIudGcoMCxILmQocykrIjo6KiIpKXJldHVybiEwCmVsc2UgaWYoci50Zygw
+LCIqOjoqIikpcmV0dXJuITB9cmV0dXJuITF9LAokaWtGOjF9ClcuRW8ucHJvdG90eXBlPXsKJDE6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIUMuTm0udGcoQy5CSSxILnkoYSkpfSwKJFM6OH0KVy5Xay5wcm90b3R5cGU9
+ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gQy5ObS50ZyhDLkJJLEgueShhKSl9LAokUzo4fQpXLmN0LnBy
+b3RvdHlwZT17CkViOmZ1bmN0aW9uKGEsYixjKXtpZih0aGlzLmpGKGEsYixjKSlyZXR1cm4hMAppZihi
+PT09InRlbXBsYXRlIiYmYz09PSIiKXJldHVybiEwCmlmKGEuZ2V0QXR0cmlidXRlKCJ0ZW1wbGF0ZSIp
+PT09IiIpcmV0dXJuIHRoaXMuZS50ZygwLGIpCnJldHVybiExfX0KVy5JQS5wcm90b3R5cGU9ewokMTpm
+dW5jdGlvbihhKXtyZXR1cm4iVEVNUExBVEU6OiIrSC5kKEgueShhKSl9LAokUzo0fQpXLk93LnByb3Rv
+dHlwZT17CmkwOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKHUuZXcuYyhhKSlyZXR1cm4hMQp0PXUuZzcuYyhh
+KQppZih0JiZXLnJTKGEpPT09ImZvcmVpZ25PYmplY3QiKXJldHVybiExCmlmKHQpcmV0dXJuITAKcmV0
+dXJuITF9LApFYjpmdW5jdGlvbihhLGIsYyl7aWYoYj09PSJpcyJ8fEMueEIubihiLCJvbiIpKXJldHVy
+biExCnJldHVybiB0aGlzLmkwKGEpfSwKJGlrRjoxfQpXLlc5LnByb3RvdHlwZT17CkY6ZnVuY3Rpb24o
+KXt2YXIgdD10aGlzLHM9dC5jKzEscj10LmIKaWYoczxyKXt0LnNwKEoudzIodC5hLHMpKQp0LmM9cwpy
+ZXR1cm4hMH10LnNwKG51bGwpCnQuYz1yCnJldHVybiExfSwKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhp
+cy5kfSwKc3A6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmQuYihhKX0sCiRpQW46MX0KVy5kVy5w
+cm90b3R5cGU9ewpnbVc6ZnVuY3Rpb24oYSl7cmV0dXJuIFcuelgodGhpcy5hLmxvY2F0aW9uKX0sCiRp
+RDA6MSwKJGl2NjoxfQpXLkZiLnByb3RvdHlwZT17fQpXLmtGLnByb3RvdHlwZT17fQpXLm1rLnByb3Rv
+dHlwZT17JGl5MDoxfQpXLktvLnByb3RvdHlwZT17ClBuOmZ1bmN0aW9uKGEpe25ldyBXLmZtKHRoaXMp
+LiQyKGEsbnVsbCl9LApFUDpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpSi5MdChhKQplbHNlIGIucmVt
+b3ZlQ2hpbGQoYSl9LApJNDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbz0hMCxuPW51bGwsbT1u
+dWxsCnRyeXtuPUouaWcoYSkKbT1uLmEuZ2V0QXR0cmlidXRlKCJpcyIpCnUuaC5iKGEpCnQ9ZnVuY3Rp
+b24oYyl7aWYoIShjLmF0dHJpYnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXApKXJldHVybiB0cnVl
+CnZhciBsPWMuY2hpbGROb2RlcwppZihjLmxhc3RDaGlsZCYmYy5sYXN0Q2hpbGQhPT1sW2wubGVuZ3Ro
+LTFdKXJldHVybiB0cnVlCmlmKGMuY2hpbGRyZW4paWYoIShjLmNoaWxkcmVuIGluc3RhbmNlb2YgSFRN
+TENvbGxlY3Rpb258fGMuY2hpbGRyZW4gaW5zdGFuY2VvZiBOb2RlTGlzdCkpcmV0dXJuIHRydWUKdmFy
+IGs9MAppZihjLmNoaWxkcmVuKWs9Yy5jaGlsZHJlbi5sZW5ndGgKZm9yKHZhciBqPTA7ajxrO2orKyl7
+dmFyIGk9Yy5jaGlsZHJlbltqXQppZihpLmlkPT0nYXR0cmlidXRlcyd8fGkubmFtZT09J2F0dHJpYnV0
+ZXMnfHxpLmlkPT0nbGFzdENoaWxkJ3x8aS5uYW1lPT0nbGFzdENoaWxkJ3x8aS5pZD09J2NoaWxkcmVu
+J3x8aS5uYW1lPT0nY2hpbGRyZW4nKXJldHVybiB0cnVlfXJldHVybiBmYWxzZX0oYSkKbz1ILm9UKHQp
+PyEwOiEoYS5hdHRyaWJ1dGVzIGluc3RhbmNlb2YgTmFtZWROb2RlTWFwKX1jYXRjaChxKXtILlJ1KHEp
+fXM9ImVsZW1lbnQgdW5wcmludGFibGUiCnRyeXtzPUouaihhKX1jYXRjaChxKXtILlJ1KHEpfXRyeXty
+PVcuclMoYSkKdGhpcy5rUih1LmguYihhKSxiLG8scyxyLHUuRy5iKG4pLEgueShtKSl9Y2F0Y2gocSl7
+aWYoSC5SdShxKSBpbnN0YW5jZW9mIFAudSl0aHJvdyBxCmVsc2V7dGhpcy5FUChhLGIpCndpbmRvdwpw
+PSJSZW1vdmluZyBjb3JydXB0ZWQgZWxlbWVudCAiK0guZChzKQppZih0eXBlb2YgY29uc29sZSE9InVu
+ZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihwKX19fSwKa1I6ZnVuY3Rpb24oYSxiLGMsZCxlLGYs
+Zyl7dmFyIHQscyxyLHEscCxvLG49dGhpcwppZihjKXtuLkVQKGEsYikKd2luZG93CnQ9IlJlbW92aW5n
+IGVsZW1lbnQgZHVlIHRvIGNvcnJ1cHRlZCBhdHRyaWJ1dGVzIG9uIDwiK2QrIj4iCmlmKHR5cGVvZiBj
+b25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKHQpCnJldHVybn1pZighbi5hLmkw
+KGEpKXtuLkVQKGEsYikKd2luZG93CnQ9IlJlbW92aW5nIGRpc2FsbG93ZWQgZWxlbWVudCA8IitILmQo
+ZSkrIj4gZnJvbSAiK0guZChiKQppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNv
+bnNvbGUud2Fybih0KQpyZXR1cm59aWYoZyE9bnVsbClpZighbi5hLkViKGEsImlzIixnKSl7bi5FUChh
+LGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxvd2VkIHR5cGUgZXh0ZW5zaW9uIDwiK0guZChlKSsn
+IGlzPSInK2crJyI+JwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUu
+d2Fybih0KQpyZXR1cm59dD1mLmdWKCkKcz1ILlZNKHQuc2xpY2UoMCksSC50Nih0KS5DKCJqZDwxPiIp
+KQpmb3Iocj1mLmdWKCkubGVuZ3RoLTEsdD1mLmE7cj49MDstLXIpe2lmKHI+PXMubGVuZ3RoKXJldHVy
+biBILk9IKHMscikKcT1zW3JdCnA9bi5hCm89Si5jSChxKQpILnkocSkKaWYoIXAuRWIoYSxvLHQuZ2V0
+QXR0cmlidXRlKHEpKSl7d2luZG93CnA9IlJlbW92aW5nIGRpc2FsbG93ZWQgYXR0cmlidXRlIDwiK0gu
+ZChlKSsiICIrcSsnPSInK0guZCh0LmdldEF0dHJpYnV0ZShxKSkrJyI+JwppZih0eXBlb2YgY29uc29s
+ZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihwKQp0LnJlbW92ZUF0dHJpYnV0ZShxKX19
+aWYodS5hVy5jKGEpKW4uUG4oYS5jb250ZW50KX0sCiRpb246MX0KVy5mbS5wcm90b3R5cGU9ewokMjpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9dGhpcy5hCnN3aXRjaChhLm5vZGVUeXBlKXtjYXNlIDE6
+cC5JNChhLGIpCmJyZWFrCmNhc2UgODpjYXNlIDExOmNhc2UgMzpjYXNlIDQ6YnJlYWsKZGVmYXVsdDpw
+LkVQKGEsYil9dD1hLmxhc3RDaGlsZApmb3IocD11LkE7bnVsbCE9dDspe3M9bnVsbAp0cnl7cz10LnBy
+ZXZpb3VzU2libGluZ31jYXRjaChyKXtILlJ1KHIpCnE9cC5iKHQpCmEucmVtb3ZlQ2hpbGQocSkKdD1u
+dWxsCnM9YS5sYXN0Q2hpbGR9aWYodCE9bnVsbCl0aGlzLiQyKHQsYSkKdD1wLmIocyl9fSwKJFM6Mzl9
+ClcuTGUucHJvdG90eXBlPXt9ClcuSzcucHJvdG90eXBlPXt9ClcuckIucHJvdG90eXBlPXt9ClcuWFcu
+cHJvdG90eXBlPXt9Clcub2EucHJvdG90eXBlPXt9ClAuaUoucHJvdG90eXBlPXsKVkg6ZnVuY3Rpb24o
+YSl7dmFyIHQscz10aGlzLmEscj1zLmxlbmd0aApmb3IodD0wO3Q8cjsrK3QpaWYoc1t0XT09PWEpcmV0
+dXJuIHQKQy5ObS5pKHMsYSkKQy5ObS5pKHRoaXMuYixudWxsKQpyZXR1cm4gcn0sClB2OmZ1bmN0aW9u
+KGEpe3ZhciB0LHMscixxPXRoaXMscD17fQppZihhPT1udWxsKXJldHVybiBhCmlmKEgubChhKSlyZXR1
+cm4gYQppZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJl
+dHVybiBhCmlmKGEgaW5zdGFuY2VvZiBQLmlQKXJldHVybiBuZXcgRGF0ZShhLmEpCmlmKHUuZnYuYyhh
+KSl0aHJvdyBILmIoUC5TWSgic3RydWN0dXJlZCBjbG9uZSBvZiBSZWdFeHAiKSkKaWYodS5jOC5jKGEp
+KXJldHVybiBhCmlmKHUuZC5jKGEpKXJldHVybiBhCmlmKHUuSS5jKGEpKXJldHVybiBhCnQ9dS5kRC5j
+KGEpfHwhMQppZih0KXJldHVybiBhCmlmKHUuRy5jKGEpKXtzPXEuVkgoYSkKdD1xLmIKaWYocz49dC5s
+ZW5ndGgpcmV0dXJuIEguT0godCxzKQpyPXAuYT10W3NdCmlmKHIhPW51bGwpcmV0dXJuIHIKcj17fQpw
+LmE9cgpDLk5tLlkodCxzLHIpCmEuSygwLG5ldyBQLmxSKHAscSkpCnJldHVybiBwLmF9aWYodS5qLmMo
+YSkpe3M9cS5WSChhKQpwPXEuYgppZihzPj1wLmxlbmd0aClyZXR1cm4gSC5PSChwLHMpCnI9cFtzXQpp
+ZihyIT1udWxsKXJldHVybiByCnJldHVybiBxLmVrKGEscyl9aWYodS5lSC5jKGEpKXtzPXEuVkgoYSkK
+dD1xLmIKaWYocz49dC5sZW5ndGgpcmV0dXJuIEguT0godCxzKQpyPXAuYj10W3NdCmlmKHIhPW51bGwp
+cmV0dXJuIHIKcj17fQpwLmI9cgpDLk5tLlkodCxzLHIpCnEuaW0oYSxuZXcgUC5qZyhwLHEpKQpyZXR1
+cm4gcC5ifXRocm93IEguYihQLlNZKCJzdHJ1Y3R1cmVkIGNsb25lIG9mIG90aGVyIHR5cGUiKSl9LApl
+azpmdW5jdGlvbihhLGIpe3ZhciB0LHM9Si5VNihhKSxyPXMuZ0EoYSkscT1uZXcgQXJyYXkocikKQy5O
+bS5ZKHRoaXMuYixiLHEpCmZvcih0PTA7dDxyOysrdClDLk5tLlkocSx0LHRoaXMuUHYocy5xKGEsdCkp
+KQpyZXR1cm4gcX19ClAubFIucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuYVthXT10
+aGlzLmIuUHYoYil9LAokUzoxfQpQLmpnLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5h
+LmJbYV09dGhpcy5iLlB2KGIpfSwKJFM6MX0KUC5CZi5wcm90b3R5cGU9ewppbTpmdW5jdGlvbihhLGIp
+e3ZhciB0LHMscixxCnUuYjguYihiKQpmb3IodD1PYmplY3Qua2V5cyhhKSxzPXQubGVuZ3RoLHI9MDty
+PHM7KytyKXtxPXRbcl0KYi4kMihxLGFbcV0pfX19ClAuQXMucHJvdG90eXBlPXsKVDpmdW5jdGlvbihh
+KXt2YXIgdApILnkoYSkKdD0kLmhHKCkuYgppZih0eXBlb2YgYSE9InN0cmluZyIpSC52aChILnRMKGEp
+KQppZih0LnRlc3QoYSkpcmV0dXJuIGEKdGhyb3cgSC5iKFAuTDMoYSwidmFsdWUiLCJOb3QgYSB2YWxp
+ZCBjbGFzcyB0b2tlbiIpKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuUCgpLkgoMCwiICIpfSwK
+Z2t6OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuUCgpCnJldHVybiBQLnJqKHQsdC5yLEguTGgodCkuZCl9
+LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5QKCkuYX0sCnRnOmZ1bmN0aW9uKGEsYil7dGhpcy5U
+KGIpCnJldHVybiB0aGlzLlAoKS50ZygwLGIpfSwKaTpmdW5jdGlvbihhLGIpe3RoaXMuVChiKQpyZXR1
+cm4gSC54ZCh0aGlzLk9TKG5ldyBQLkdFKGIpKSl9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHQscwp0aGlz
+LlQoYikKdD10aGlzLlAoKQpzPXQuUigwLGIpCnRoaXMuWCh0KQpyZXR1cm4gc30sCkZWOmZ1bmN0aW9u
+KGEsYil7dGhpcy5PUyhuZXcgUC5ONyh0aGlzLHUuWC5iKGIpKSl9LApWMTpmdW5jdGlvbihhKXt0aGlz
+Lk9TKG5ldyBQLnVRKCkpfSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHQscwp1LmNoLmIoYSkKdD10aGlzLlAo
+KQpzPWEuJDEodCkKdGhpcy5YKHQpCnJldHVybiBzfX0KUC5HRS5wcm90b3R5cGU9ewokMTpmdW5jdGlv
+bihhKXtyZXR1cm4gdS5DLmIoYSkuaSgwLHRoaXMuYSl9LAokUzozMn0KUC5ONy5wcm90b3R5cGU9ewok
+MTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmIscz1ILnQ2KHQpCnJldHVybiB1LkMuYihhKS5GVigwLG5l
+dyBILkE4KHQscy5DKCJxVSgxKSIpLmIodGhpcy5hLmd1TSgpKSxzLkMoIkE4PDEscVU+IikpKX0sCiRT
+OjE2fQpQLnVRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3UuQy5iKGEpCmlmKGEuYT4wKXthLmI9
+YS5jPWEuZD1hLmU9YS5mPW51bGwKYS5hPTAKYS5TKCl9cmV0dXJufSwKJFM6MTZ9ClAuaEYucHJvdG90
+eXBlPXskaWhGOjF9ClAuUEMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5aLmIoYSkK
+dD1mdW5jdGlvbihiLGMsZCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGIoYyxkLHRoaXMsQXJyYXku
+cHJvdG90eXBlLnNsaWNlLmFwcGx5KGFyZ3VtZW50cykpfX0oUC5SNCxhLCExKQpQLkRtKHQsJC53KCks
+YSkKcmV0dXJuIHR9LAokUzozfQpQLlltLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBu
+ZXcgdGhpcy5hKGEpfSwKJFM6M30KUC5Oei5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4g
+bmV3IFAucjcoYSl9LAokUzozNH0KUC5ucC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4g
+bmV3IFAuVHooYSx1LmFtKX0sCiRTOjM1fQpQLlV0LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBuZXcgUC5FNChhKX0sCiRTOjM2fQpQLkU0LnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtp
+Zih0eXBlb2YgYiE9InN0cmluZyImJnR5cGVvZiBiIT0ibnVtYmVyIil0aHJvdyBILmIoUC54WSgicHJv
+cGVydHkgaXMgbm90IGEgU3RyaW5nIG9yIG51bSIpKQpyZXR1cm4gUC5MNyh0aGlzLmFbYl0pfSwKWTpm
+dW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGIhPSJzdHJpbmciJiZ0eXBlb2YgYiE9Im51bWJlciIpdGhy
+b3cgSC5iKFAueFkoInByb3BlcnR5IGlzIG5vdCBhIFN0cmluZyBvciBudW0iKSkKdGhpcy5hW2JdPVAu
+d1koYyl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFu
+Y2VvZiBQLkU0JiZ0aGlzLmE9PT1iLmF9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0LHMKdHJ5e3Q9U3RyaW5n
+KHRoaXMuYSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShzKQp0PXRoaXMueGIoMCkKcmV0dXJuIHR9fSwK
+Vjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYQppZihiPT1udWxsKXQ9bnVsbAplbHNle3Q9SC50
+NihiKQp0PVAuQ0gobmV3IEguQTgoYix0LkMoIkAoMSkiKS5iKFAuaUcoKSksdC5DKCJBODwxLEA+Iikp
+LCEwLHUueil9cmV0dXJuIFAuTDcoc1thXS5hcHBseShzLHQpKX0sCmdpTzpmdW5jdGlvbihhKXtyZXR1
+cm4gMH19ClAucjcucHJvdG90eXBlPXt9ClAuVHoucHJvdG90eXBlPXsKY1A6ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcyxzPWE8MHx8YT49dC5nQSh0KQppZihzKXRocm93IEguYihQLlRFKGEsMCx0LmdBKHQpLG51
+bGwsbnVsbCkpfSwKcTpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiPT0ibnVtYmVyIiYmYj09PUMuam4u
+eXUoYikpdGhpcy5jUChILlNjKGIpKQpyZXR1cm4gdGhpcy4kdGkuZC5iKHRoaXMuVXIoMCxiKSl9LApZ
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgdAp0aGlzLiR0aS5kLmIoYykKdD1DLmpuLnl1KGIpCmlmKGI9PT10
+KXRoaXMuY1AoYikKdGhpcy5lNCgwLGIsYyl9LApnQTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEubGVu
+Z3RoCmlmKHR5cGVvZiB0PT09Im51bWJlciImJnQ+Pj4wPT09dClyZXR1cm4gdAp0aHJvdyBILmIoUC5Q
+VigiQmFkIEpzQXJyYXkgbGVuZ3RoIikpfSwKJGljWDoxLAokaXpNOjF9ClAuY28ucHJvdG90eXBlPXt9
+ClAubmQucHJvdG90eXBlPXskaW5kOjF9ClAuS2UucHJvdG90eXBlPXsKUDpmdW5jdGlvbigpe3ZhciB0
+LHMscixxLHA9dGhpcy5hLmdldEF0dHJpYnV0ZSgiY2xhc3MiKSxvPVAuTHModS5OKQppZihwPT1udWxs
+KXJldHVybiBvCmZvcih0PXAuc3BsaXQoIiAiKSxzPXQubGVuZ3RoLHI9MDtyPHM7KytyKXtxPUouVDAo
+dFtyXSkKaWYocS5sZW5ndGghPT0wKW8uaSgwLHEpfXJldHVybiBvfSwKWDpmdW5jdGlvbihhKXt0aGlz
+LmEuc2V0QXR0cmlidXRlKCJjbGFzcyIsYS5IKDAsIiAiKSl9fQpQLmQ1LnByb3RvdHlwZT17CmdEOmZ1
+bmN0aW9uKGEpe3JldHVybiBuZXcgUC5LZShhKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMuWUMoYSxi
+KX0sCnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbwppZihkPT1udWxsKXt0PUguVk0o
+W10sdS5rKQpkPW5ldyBXLnZEKHQpCkMuTm0uaSh0LFcuVHcobnVsbCkpCkMuTm0uaSh0LFcuQmwoKSkK
+Qy5ObS5pKHQsbmV3IFcuT3coKSl9Yz1uZXcgVy5LbyhkKQpzPSc8c3ZnIHZlcnNpb249IjEuMSI+JytI
+LmQoYikrIjwvc3ZnPiIKdD1kb2N1bWVudApyPXQuYm9keQpxPShyJiZDLlJZKS5BSChyLHMsYykKcD10
+LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpxLnRvU3RyaW5nCnQ9bmV3IFcuZTcocSkKbz10LmdyOCh0
+KQpmb3IoO3Q9by5maXJzdENoaWxkLHQhPW51bGw7KXAuYXBwZW5kQ2hpbGQodCkKcmV0dXJuIHB9LApn
+Vmw6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBXLkNxKGEsImNsaWNrIiwhMSx1LlEpfSwKJGlkNToxfQpQ
+Lm42LnByb3RvdHlwZT17JGljWDoxLCRpek06MSwkaUFTOjF9ClUuZDIucHJvdG90eXBlPXt9ClUuU2Uu
+cHJvdG90eXBlPXt9ClUudUYucHJvdG90eXBlPXt9ClUuTWwucHJvdG90eXBlPXt9ClUueUQucHJvdG90
+eXBlPXt9ClUud2IucHJvdG90eXBlPXt9CkIuajgucHJvdG90eXBlPXt9CkIucXAucHJvdG90eXBlPXt9
+ClQuR1YucHJvdG90eXBlPXt9CkwuZS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
+cSxwLG8KdS5CLmIoYSkKdD13aW5kb3cubG9jYXRpb24ucGF0aG5hbWUKcz1MLkc2KHdpbmRvdy5sb2Nh
+dGlvbi5ocmVmKQpyPUwuYUsod2luZG93LmxvY2F0aW9uLmhyZWYpCkwuR2UoKQppZih0IT09Ii8iJiZ0
+IT09Si5UMChkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50KSlMLkc3KHQs
+cyxyLG5ldyBMLlZXKHQscyxyKSkKcT1KLnFGKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5hcHBseS1t
+aWdyYXRpb24iKSkKcD1xLiR0aQpvPXAuQygifigxKSIpLmIobmV3IEwub1ooKSkKdS5NLmIobnVsbCkK
+Vy5KRShxLmEscS5iLG8sITEscC5kKX0sCiRTOjE3fQpMLlZXLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
+KCl7TC5Gcih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzowfQpMLm9aLnByb3RvdHlwZT17CiQxOmZ1
+bmN0aW9uKGEpe3UuVi5iKGEpCkwudHkoIi9hcHBseS1taWdyYXRpb24iKS5XNyhuZXcgTC5qcigpLHUu
+UCkuT0EobmV3IEwucWwoKSl9LAokUzo1fQpMLmpyLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Zh
+ciB0CnUuci5iKGEpCnQ9ZG9jdW1lbnQuYm9keQp0LmNsYXNzTGlzdC5yZW1vdmUoInByb3Bvc2VkIikK
+dC5jbGFzc0xpc3QuYWRkKCJhcHBsaWVkIil9LAokUzo3fQpMLnFsLnByb3RvdHlwZT17CiQyOmZ1bmN0
+aW9uKGEsYil7TC5xSigiYXBwbHkgbWlncmF0aW9uIGVycm9yOiAiK0guZChhKSxiKQp3aW5kb3cuYWxl
+cnQoIkNvdWxkIG5vdCBhcHBseSBtaWdyYXRpb24gKCIrSC5kKGEpKyIpLiIpfSwKJEM6IiQyIiwKJFI6
+MiwKJFM6MX0KTC5MLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1LkIuYihhKQp0
+PXdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZQpzPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpCnI9TC5h
+Syh3aW5kb3cubG9jYXRpb24uaHJlZikKaWYodC5sZW5ndGg+MSlMLkc3KHQscyxyLG51bGwpCmVsc2V7
+TC5CRSh0LG5ldyBCLnFwKCIiLCIiLCIiLEMueEQpKQpMLkJYKCImbmJzcDsiLG51bGwpfX0sCiRTOjE3
+fQpMLld4LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPSJjb2xsYXBzZWQiCnUu
+Vi5iKGEpCnQ9dGhpcy5hCnM9Si5SRSh0KQpyPXRoaXMuYgppZighcy5nRCh0KS50ZygwLHEpKXtzLmdE
+KHQpLmkoMCxxKQpKLmRSKHIpLmkoMCxxKX1lbHNle3MuZ0QodCkuUigwLHEpCkouZFIocikuUigwLHEp
+fX0sCiRTOjV9CkwuQU8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9Si5xRih1LmguYihh
+KSkscz10LiR0aSxyPXMuQygifigxKSIpLmIobmV3IEwuZE4oKSkKdS5NLmIobnVsbCkKVy5KRSh0LmEs
+dC5iLHIsITEscy5kKX0sCiRTOjZ9CkwuZE4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQK
+dS5WLmIoYSkKdD1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJ0YWJsZVtkYXRhLXBhdGhdIikKdC50b1N0
+cmluZwpMLnQyKGEsdC5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyh0KSkuTygi
+cGF0aCIpKSl9LAokUzo1fQpMLkhvLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1
+LmguYihhKQp0PUoucUYoYSkKcz10LiR0aQpyPXMuQygifigxKSIpLmIobmV3IEwueHooYSx0aGlzLmEp
+KQp1Lk0uYihudWxsKQpXLkpFKHQuYSx0LmIsciwhMSxzLmQpfSwKJFM6Nn0KTC54ei5wcm90b3R5cGU9
+ewokMTpmdW5jdGlvbihhKXt2YXIgdAp1LlYuYihhKQp0PXRoaXMuYQpMLmhYKHRoaXMuYixQLlFBKHQu
+Z2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcodCkpLk8oIm9mZnNldCIpKSxudWxs
+LG51bGwpKX0sCiRTOjV9CkwuSUMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9Si5xRih1
+LmguYihhKSkscz10LiR0aQpzLkMoIn4oMSkiKS5iKEwuSDAoKSkKdS5NLmIobnVsbCkKVy5KRSh0LmEs
+dC5iLEwuSDAoKSwhMSxzLmQpfSwKJFM6Nn0KTC5MMS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2
+YXIgdAp1LnIuYihhKQp0PWEuc3RhdHVzCmlmKHQ9PT0yMDApcmV0dXJuIGEKZWxzZSB0aHJvdyBILmIo
+IlJlcXVlc3QgZmFpbGVkOyBzdGF0dXMgb2YgIitILmQodCkpfSwKJFM6NDF9CkwublQucHJvdG90eXBl
+PXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYS5hLHRoaXMuYix0aGlzLmMpfSwKJFM6MH0KTC5CWi5w
+cm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhpcy5hLmEsbnVsbCxudWxsKX0sCiRTOjB9Ckwu
+R0gucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dS5oLmIoYSkKJC56QigpLnRvU3RyaW5nCnUudi5i
+KCQub3coKS5xKDAsImhsanMiKSkuVjcoImhpZ2hsaWdodEJsb2NrIixbYV0pfSwKJFM6Nn0KTC5EVC5w
+cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdAp1LnIuYihhKQp0PWEuc3RhdHVzCmlmKHQ9PT0y
+MDApe0wuVDEoVS55dShDLkN0LnBXKDAsYS5yZXNwb25zZVRleHQsbnVsbCkpKQpMLnlYKCIuZWRpdC1w
+YW5lbCAucGFuZWwtY29udGVudCIpfWVsc2Ugd2luZG93LmFsZXJ0KCJSZXF1ZXN0IGZhaWxlZDsgc3Rh
+dHVzIG9mICIrSC5kKHQpKX0sCiRTOjd9CkwuZUgucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtM
+LnFKKCJsb2FkUmVnaW9uRXhwbGFuYXRpb246ICIrSC5kKGEpLGIpCndpbmRvdy5hbGVydCgiQ291bGQg
+bm90IGxvYWQgIitILmQodGhpcy5hKSsiICgiK0guZChhKSsiKS4iKX0sCiRDOiIkMiIsCiRSOjIsCiRT
+OjF9CkwuekQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMKdS5yLmIoYSkK
+dD1hLnN0YXR1cwppZih0PT09MjAwKXtzPXIuYQpMLkJFKHMsQi5ZZih1LmIuYihDLkN0LnBXKDAsYS5y
+ZXNwb25zZVRleHQsbnVsbCkpKSkKdD1yLmIKTC5mRyh0LHIuYykKTC5CWChDLnhCLnRnKHMsIj8iKT9D
+LnhCLk5qKHMsMCxDLnhCLk9ZKHMsIj8iKSk6cyx0KQp0PXIuZAppZih0IT1udWxsKXQuJDAoKX1lbHNl
+IHdpbmRvdy5hbGVydCgiUmVxdWVzdCBmYWlsZWQ7IHN0YXR1cyBvZiAiK0guZCh0KSl9LAokUzo3fQpM
+Lk9FLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7TC5xSigibG9hZEZpbGU6ICIrSC5kKGEpLGIp
+CndpbmRvdy5hbGVydCgiQ291bGQgbm90IGxvYWQgIit0aGlzLmErIiAoIitILmQoYSkrIikuIil9LAok
+QzoiJDIiLAokUjoyLAokUzoxfQpMLlRXLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMs
+cgp1LnIuYihhKQp0PWEuc3RhdHVzCmlmKHQ9PT0yMDApe3M9Qy5DdC5wVygwLGEucmVzcG9uc2VUZXh0
+LG51bGwpCnI9ZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLm5hdi10cmVlIikKSi5sNShyLCIiKQpMLnRY
+KHIsTC5tSyhzKSl9ZWxzZSB3aW5kb3cuYWxlcnQoIlJlcXVlc3QgZmFpbGVkOyBzdGF0dXMgb2YgIitI
+LmQodCkpfSwKJFM6N30KTC54ci5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe0wucUooImxvYWRO
+YXZpZ2F0aW9uVHJlZTogIitILmQoYSksYikKd2luZG93LmFsZXJ0KCJDb3VsZCBub3QgbG9hZCAiK3Ro
+aXMuYSsiICgiK0guZChhKSsiKS4iKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjF9CkwuRUUucHJvdG90eXBl
+PXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscwp1LlYuYihhKQp0PXRoaXMuYQpzPXRoaXMuYgpMLmFmKHdp
+bmRvdy5sb2NhdGlvbi5wYXRobmFtZSx0LHMsbmV3IEwuUUwodCxzKSkKTC5oWCh0aGlzLmMsdCl9LAok
+Uzo1fQpMLlFMLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7TC5Gcih3aW5kb3cubG9jYXRpb24ucGF0
+aG5hbWUsdGhpcy5hLHRoaXMuYil9LAokUzowfQpMLlZTLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
+e3ZhciB0LHM9InNlbGVjdGVkLWZpbGUiCnUuaC5iKGEpCmEudG9TdHJpbmcKdD1KLlJFKGEpCmlmKGEu
+Z2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcoYSkpLk8oIm5hbWUiKSk9PT10aGlz
+LmEuYSl0LmdEKGEpLmkoMCxzKQplbHNlIHQuZ0QoYSkuUigwLHMpfSwKJFM6Nn0KTC5YQS5wcm90b3R5
+cGU9ewpFYjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuITB9LAppMDpmdW5jdGlvbihhKXtyZXR1cm4hMH0s
+CiRpa0Y6MX0KTC5aWi5wcm90b3R5cGU9e30KTC55OC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0aGlzLmJ9fQpNLmxJLnByb3RvdHlwZT17CldPOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1udWxs
+Ck0uWUYoImFic29sdXRlIixILlZNKFtiLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsXSx1LnMp
+KQp0PXRoaXMuYQp0PXQuWXIoYik+MCYmIXQuaEsoYikKaWYodClyZXR1cm4gYgp0PUQuUlgoKQpyZXR1
+cm4gdGhpcy5xNygwLHQsYixzLHMscyxzLHMscyl9LAp0TTpmdW5jdGlvbihhKXt2YXIgdCxzLHI9WC5D
+TChhLHRoaXMuYSkKci5JVigpCnQ9ci5kCnM9dC5sZW5ndGgKaWYocz09PTApe3Q9ci5iCnJldHVybiB0
+PT1udWxsPyIuIjp0fWlmKHM9PT0xKXt0PXIuYgpyZXR1cm4gdD09bnVsbD8iLiI6dH1pZigwPj1zKXJl
+dHVybiBILk9IKHQsLTEpCnQucG9wKCkKQy5ObS5tdihyLmUpCnIuSVYoKQpyZXR1cm4gci53KDApfSwK
+cTc6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyxoLGkpe3ZhciB0PUguVk0oW2IsYyxkLGUsZixnLGgsaV0s
+dS5zKQpNLllGKCJqb2luIix0KQpyZXR1cm4gdGhpcy5JUChuZXcgSC5VNSh0LHUuYkIuYihuZXcgTS5N
+aSgpKSx1LmNjKSl9LApJUDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwKdS5YLmIoYSkK
+Zm9yKHQ9YS4kdGkscz10LkMoImEyKGNYLkUpIikuYihuZXcgTS5xNygpKSxyPWEuZ2t6KGEpLHQ9bmV3
+IEguU08ocixzLHQuQygiU088Y1guRT4iKSkscz10aGlzLmEscT0hMSxwPSExLG89IiI7dC5GKCk7KXtu
+PXIuZ2woKQppZihzLmhLKG4pJiZwKXttPVguQ0wobixzKQpsPW8uY2hhckNvZGVBdCgwKT09MD9vOm8K
+bz1DLnhCLk5qKGwsMCxzLlNwKGwsITApKQptLmI9bwppZihzLmRzKG8pKUMuTm0uWShtLmUsMCxzLmdt
+SSgpKQpvPW0udygwKX1lbHNlIGlmKHMuWXIobik+MCl7cD0hcy5oSyhuKQpvPUguZChuKX1lbHNle2lm
+KCEobi5sZW5ndGg+MCYmcy5VZChuWzBdKSkpaWYocSlvKz1zLmdtSSgpCm8rPUguZChuKX1xPXMuZHMo
+bil9cmV0dXJuIG8uY2hhckNvZGVBdCgwKT09MD9vOm99LApvNTpmdW5jdGlvbihhKXt2YXIgdAppZigh
+dGhpcy55MyhhKSlyZXR1cm4gYQp0PVguQ0woYSx0aGlzLmEpCnQuclIoKQpyZXR1cm4gdC53KDApfSwK
+eTM6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGsKYS50b1N0cmluZwp0PXRoaXMuYQpz
+PXQuWXIoYSkKaWYocyE9PTApe2lmKHQ9PT0kLktrKCkpZm9yKHI9MDtyPHM7KytyKWlmKEMueEIuVyhh
+LHIpPT09NDcpcmV0dXJuITAKcT1zCnA9NDd9ZWxzZXtxPTAKcD1udWxsfWZvcihvPW5ldyBILnFqKGEp
+LmEsbj1vLmxlbmd0aCxyPXEsbT1udWxsO3I8bjsrK3IsbT1wLHA9bCl7bD1DLnhCLm0obyxyKQppZih0
+LnI0KGwpKXtpZih0PT09JC5LaygpJiZsPT09NDcpcmV0dXJuITAKaWYocCE9bnVsbCYmdC5yNChwKSly
+ZXR1cm4hMAppZihwPT09NDYpaz1tPT1udWxsfHxtPT09NDZ8fHQucjQobSkKZWxzZSBrPSExCmlmKGsp
+cmV0dXJuITB9fWlmKHA9PW51bGwpcmV0dXJuITAKaWYodC5yNChwKSlyZXR1cm4hMAppZihwPT09NDYp
+dD1tPT1udWxsfHx0LnI0KG0pfHxtPT09NDYKZWxzZSB0PSExCmlmKHQpcmV0dXJuITAKcmV0dXJuITF9
+LApIUDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbz10aGlzLG49J1VuYWJsZSB0byBmaW5kIGEg
+cGF0aCB0byAiJwpiPW8uV08oMCxiKQp0PW8uYQppZih0LllyKGIpPD0wJiZ0LllyKGEpPjApcmV0dXJu
+IG8ubzUoYSkKaWYodC5ZcihhKTw9MHx8dC5oSyhhKSlhPW8uV08oMCxhKQppZih0LllyKGEpPD0wJiZ0
+LllyKGIpPjApdGhyb3cgSC5iKFguSlQobitILmQoYSkrJyIgZnJvbSAiJytILmQoYikrJyIuJykpCnM9
+WC5DTChiLHQpCnMuclIoKQpyPVguQ0woYSx0KQpyLnJSKCkKcT1zLmQKaWYocS5sZW5ndGg+MCYmSi5S
+TShxWzBdLCIuIikpcmV0dXJuIHIudygwKQpxPXMuYgpwPXIuYgppZihxIT1wKXE9cT09bnVsbHx8cD09
+bnVsbHx8IXQuTmMocSxwKQplbHNlIHE9ITEKaWYocSlyZXR1cm4gci53KDApCndoaWxlKCEwKXtxPXMu
+ZAppZihxLmxlbmd0aD4wKXtwPXIuZApxPXAubGVuZ3RoPjAmJnQuTmMocVswXSxwWzBdKX1lbHNlIHE9
+ITEKaWYoIXEpYnJlYWsKQy5ObS5XNChzLmQsMCkKQy5ObS5XNChzLmUsMSkKQy5ObS5XNChyLmQsMCkK
+Qy5ObS5XNChyLmUsMSl9cT1zLmQKaWYocS5sZW5ndGg+MCYmSi5STShxWzBdLCIuLiIpKXRocm93IEgu
+YihYLkpUKG4rSC5kKGEpKyciIGZyb20gIicrSC5kKGIpKyciLicpKQpxPXUuTgpDLk5tLlVHKHIuZCww
+LFAuTzgocy5kLmxlbmd0aCwiLi4iLHEpKQpDLk5tLlkoci5lLDAsIiIpCkMuTm0uVUcoci5lLDEsUC5P
+OChzLmQubGVuZ3RoLHQuZ21JKCkscSkpCnQ9ci5kCnE9dC5sZW5ndGgKaWYocT09PTApcmV0dXJuIi4i
+CmlmKHE+MSYmSi5STShDLk5tLmdyWih0KSwiLiIpKXt0PXIuZAppZigwPj10Lmxlbmd0aClyZXR1cm4g
+SC5PSCh0LC0xKQp0LnBvcCgpCnQ9ci5lCkMuTm0ubXYodCkKQy5ObS5tdih0KQpDLk5tLmkodCwiIil9
+ci5iPSIiCnIuSVYoKQpyZXR1cm4gci53KDApfX0KTS5NaS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihh
+KXtyZXR1cm4gSC55KGEpIT1udWxsfSwKJFM6OH0KTS5xNy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihh
+KXtyZXR1cm4gSC55KGEpIT09IiJ9LAokUzo4fQpNLk5vLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
+e0gueShhKQpyZXR1cm4gYT09bnVsbD8ibnVsbCI6JyInK2ErJyInfSwKJFM6NH0KQi5MdS5wcm90b3R5
+cGU9ewp4WjpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMuWXIoYSkKaWYocz4wKXJldHVybiBKLmxkKGEs
+MCxzKQppZih0aGlzLmhLKGEpKXtpZigwPj1hLmxlbmd0aClyZXR1cm4gSC5PSChhLDApCnQ9YVswXX1l
+bHNlIHQ9bnVsbApyZXR1cm4gdH0sCk5jOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9PWJ9fQpYLldELnBy
+b3RvdHlwZT17CklWOmZ1bmN0aW9uKCl7dmFyIHQscyxyPXRoaXMKd2hpbGUoITApe3Q9ci5kCmlmKCEo
+dC5sZW5ndGghPT0wJiZKLlJNKEMuTm0uZ3JaKHQpLCIiKSkpYnJlYWsKdD1yLmQKaWYoMD49dC5sZW5n
+dGgpcmV0dXJuIEguT0godCwtMSkKdC5wb3AoKQpDLk5tLm12KHIuZSl9dD1yLmUKcz10Lmxlbmd0aApp
+ZihzPjApQy5ObS5ZKHQscy0xLCIiKX0sCnJSOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbT10
+aGlzLGw9SC5WTShbXSx1LnMpCmZvcih0PW0uZCxzPXQubGVuZ3RoLHI9MCxxPTA7cTx0Lmxlbmd0aDt0
+Lmxlbmd0aD09PXN8fCgwLEgubGspKHQpLCsrcSl7cD10W3FdCm89Si5pYShwKQppZighKG8uRE4ocCwi
+LiIpfHxvLkROKHAsIiIpKSlpZihvLkROKHAsIi4uIikpaWYobC5sZW5ndGg+MClsLnBvcCgpCmVsc2Ug
+KytyCmVsc2UgQy5ObS5pKGwscCl9aWYobS5iPT1udWxsKUMuTm0uVUcobCwwLFAuTzgociwiLi4iLHUu
+TikpCmlmKGwubGVuZ3RoPT09MCYmbS5iPT1udWxsKUMuTm0uaShsLCIuIikKbj1QLmRIKGwubGVuZ3Ro
+LG5ldyBYLnFSKG0pLCEwLHUuTikKdD1tLmIKdD10IT1udWxsJiZsLmxlbmd0aD4wJiZtLmEuZHModCk/
+bS5hLmdtSSgpOiIiCkgudDYobikuZC5iKHQpCmlmKCEhbi5maXhlZCRsZW5ndGgpSC52aChQLkw0KCJp
+bnNlcnQiKSkKbi5zcGxpY2UoMCwwLHQpCm0uc25KKGwpCm0uc1BoKG4pCnQ9bS5iCmlmKHQhPW51bGwm
+Jm0uYT09PSQuS2soKSl7dC50b1N0cmluZwptLmI9SC55cyh0LCIvIiwiXFwiKX1tLklWKCl9LAp3OmZ1
+bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9ci5iCnE9cSE9bnVsbD9xOiIiCmZvcih0PTA7dDxyLmQu
+bGVuZ3RoOysrdCl7cz1yLmUKaWYodD49cy5sZW5ndGgpcmV0dXJuIEguT0gocyx0KQpzPXErSC5kKHNb
+dF0pCnE9ci5kCmlmKHQ+PXEubGVuZ3RoKXJldHVybiBILk9IKHEsdCkKcT1zK0guZChxW3RdKX1xKz1I
+LmQoQy5ObS5nclooci5lKSkKcmV0dXJuIHEuY2hhckNvZGVBdCgwKT09MD9xOnF9LApzbko6ZnVuY3Rp
+b24oYSl7dGhpcy5kPXUuYS5iKGEpfSwKc1BoOmZ1bmN0aW9uKGEpe3RoaXMuZT11LmEuYihhKX19Clgu
+cVIucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5hLmdtSSgpfSwKJFM6NDJ9
+ClguZHYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iUGF0aEV4Y2VwdGlvbjogIit0aGlz
+LmF9fQpPLnpMLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ29jKHRoaXMpfX0K
+RS5PRi5wcm90b3R5cGU9ewpVZDpmdW5jdGlvbihhKXtyZXR1cm4gQy54Qi50ZyhhLCIvIil9LApyNDpm
+dW5jdGlvbihhKXtyZXR1cm4gYT09PTQ3fSwKZHM6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5sZW5ndGgKcmV0
+dXJuIHQhPT0wJiZDLnhCLm0oYSx0LTEpIT09NDd9LApTcDpmdW5jdGlvbihhLGIpe2lmKGEubGVuZ3Ro
+IT09MCYmQy54Qi5XKGEsMCk9PT00NylyZXR1cm4gMQpyZXR1cm4gMH0sCllyOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0aGlzLlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuITF9LApnb2M6ZnVuY3Rpb24o
+KXtyZXR1cm4icG9zaXgifSwKZ21JOmZ1bmN0aW9uKCl7cmV0dXJuIi8ifX0KRi5ydS5wcm90b3R5cGU9
+ewpVZDpmdW5jdGlvbihhKXtyZXR1cm4gQy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1
+cm4gYT09PTQ3fSwKZHM6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5sZW5ndGgKaWYodD09PTApcmV0dXJuITEK
+aWYoQy54Qi5tKGEsdC0xKSE9PTQ3KXJldHVybiEwCnJldHVybiBDLnhCLlRjKGEsIjovLyIpJiZ0aGlz
+LllyKGEpPT09dH0sClNwOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscD1hLmxlbmd0aAppZihwPT09
+MClyZXR1cm4gMAppZihDLnhCLlcoYSwwKT09PTQ3KXJldHVybiAxCmZvcih0PTA7dDxwOysrdCl7cz1D
+LnhCLlcoYSx0KQppZihzPT09NDcpcmV0dXJuIDAKaWYocz09PTU4KXtpZih0PT09MClyZXR1cm4gMApy
+PUMueEIuWFUoYSwiLyIsQy54Qi5RaShhLCIvLyIsdCsxKT90KzM6dCkKaWYocjw9MClyZXR1cm4gcApp
+ZighYnx8cDxyKzMpcmV0dXJuIHIKaWYoIUMueEIubihhLCJmaWxlOi8vIikpcmV0dXJuIHIKaWYoIUIu
+WXUoYSxyKzEpKXJldHVybiByCnE9ciszCnJldHVybiBwPT09cT9xOnIrNH19cmV0dXJuIDB9LApZcjpm
+dW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxl
+bmd0aCE9PTAmJkMueEIuVyhhLDApPT09NDd9LApnb2M6ZnVuY3Rpb24oKXtyZXR1cm4idXJsIn0sCmdt
+STpmdW5jdGlvbigpe3JldHVybiIvIn19CkwuSVYucHJvdG90eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0
+dXJuIEMueEIudGcoYSwiLyIpfSwKcjQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGE9PT00N3x8YT09PTkyfSwK
+ZHM6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5sZW5ndGgKaWYodD09PTApcmV0dXJuITEKdD1DLnhCLm0oYSx0
+LTEpCnJldHVybiEodD09PTQ3fHx0PT09OTIpfSwKU3A6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9YS5s
+ZW5ndGgKaWYocj09PTApcmV0dXJuIDAKdD1DLnhCLlcoYSwwKQppZih0PT09NDcpcmV0dXJuIDEKaWYo
+dD09PTkyKXtpZihyPDJ8fEMueEIuVyhhLDEpIT09OTIpcmV0dXJuIDEKcz1DLnhCLlhVKGEsIlxcIiwy
+KQppZihzPjApe3M9Qy54Qi5YVShhLCJcXCIscysxKQppZihzPjApcmV0dXJuIHN9cmV0dXJuIHJ9aWYo
+cjwzKXJldHVybiAwCmlmKCFCLk9TKHQpKXJldHVybiAwCmlmKEMueEIuVyhhLDEpIT09NTgpcmV0dXJu
+IDAKcj1DLnhCLlcoYSwyKQppZighKHI9PT00N3x8cj09PTkyKSlyZXR1cm4gMApyZXR1cm4gM30sClly
+OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
+aXMuWXIoYSk9PT0xfSwKT3Q6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihhPT09YilyZXR1cm4hMAppZihh
+PT09NDcpcmV0dXJuIGI9PT05MgppZihhPT09OTIpcmV0dXJuIGI9PT00NwppZigoYV5iKSE9PTMyKXJl
+dHVybiExCnQ9YXwzMgpyZXR1cm4gdD49OTcmJnQ8PTEyMn0sCk5jOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cyxyCmlmKGE9PWIpcmV0dXJuITAKdD1hLmxlbmd0aAppZih0IT09Yi5sZW5ndGgpcmV0dXJuITEKZm9y
+KHM9Si5yWShiKSxyPTA7cjx0OysrcilpZighdGhpcy5PdChDLnhCLlcoYSxyKSxzLlcoYixyKSkpcmV0
+dXJuITEKcmV0dXJuITB9LApnb2M6ZnVuY3Rpb24oKXtyZXR1cm4id2luZG93cyJ9LApnbUk6ZnVuY3Rp
+b24oKXtyZXR1cm4iXFwifX07KGZ1bmN0aW9uIGFsaWFzZXMoKXt2YXIgdD1KLnZCLnByb3RvdHlwZQp0
+LlU9dC53CnQuU2o9dC5lNwp0PUouTUYucHJvdG90eXBlCnQudD10LncKdD1QLmNYLnByb3RvdHlwZQp0
+LkdHPXQuZXYKdD1QLmsucHJvdG90eXBlCnQueGI9dC53CnQ9Vy5jdi5wcm90b3R5cGUKdC5EVz10LnI2
+CnQ9Vy5tNi5wcm90b3R5cGUKdC5qRj10LkViCnQ9UC5FNC5wcm90b3R5cGUKdC5Vcj10LnEKdC5lND10
+Lll9KSgpOyhmdW5jdGlvbiBpbnN0YWxsVGVhck9mZnMoKXt2YXIgdD1odW5rSGVscGVycy5fc3RhdGlj
+XzEscz1odW5rSGVscGVycy5fc3RhdGljXzAscj1odW5rSGVscGVycy5pbnN0YWxsSW5zdGFuY2VUZWFy
+T2ZmLHE9aHVua0hlbHBlcnMuaW5zdGFsbFN0YXRpY1RlYXJPZmYscD1odW5rSGVscGVycy5faW5zdGFu
+Y2VfMXUKdChQLCJFWCIsIlpWIiwxMCkKdChQLCJ5dCIsIm9BIiwxMCkKdChQLCJxVyIsIkJ6IiwxMCkK
+cyhQLCJVSSIsImVOIiwyKQpyKFAuUGYucHJvdG90eXBlLCJnWUoiLDAsMSxudWxsLFsiJDIiLCIkMSJd
+LFsidzAiLCJwbSJdLDI5LDApCnQoUCwiUEgiLCJNdCIsNCkKcShXLCJwUyIsNCxudWxsLFsiJDQiXSxb
+InlXIl0sMTEsMCkKcShXLCJWNCIsNCxudWxsLFsiJDQiXSxbIlFXIl0sMTEsMCkKcChQLkFzLnByb3Rv
+dHlwZSwiZ3VNIiwiVCIsNCkKdChQLCJpRyIsIndZIiwzKQp0KFAsIncwIiwiTDciLDQ1KQpxKEwsIlhO
+IiwxLG51bGwsWyIkMiRyZWxhdGl2ZVRvIiwiJDEiXSxbInQyIixmdW5jdGlvbihhKXtyZXR1cm4gTC50
+MihhLG51bGwpfV0sNDYsMCkKdChMLCJIMCIsInVtIiwzMSl9KSgpOyhmdW5jdGlvbiBpbmhlcml0YW5j
+ZSgpe3ZhciB0PWh1bmtIZWxwZXJzLm1peGluLHM9aHVua0hlbHBlcnMuaW5oZXJpdCxyPWh1bmtIZWxw
+ZXJzLmluaGVyaXRNYW55CnMoUC5rLG51bGwpCnIoUC5rLFtILmVvLEoudkIsSi5tMSxQLm5ZLFAuY1gs
+SC5hNyxQLkFuLEguU1UsSC5SZSxILnd2LFAuUG4sSC5XVSxILkxJLEguVHAsSC5acixQLlhTLEguYnEs
+SC5YTyxQLllrLEguZGIsSC5ONixILlZSLEguRUssSC5QYixILnRRLEguU2QsSC5KYyxILkcsUC5XMyxQ
+LmloLFAuUGYsUC5GZSxQLnZzLFAuT00sUC5xaCxQLk1PLFAua1QsUC54SSxQLkN3LFAubTAsUC5YdixQ
+LmJuLFAubG0sUC5sRCxQLktQLFAubGYsUC5XWSxQLlVrLFAuUncsUC5ieixQLmEyLFAuaVAsUC5GSyxQ
+Lms1LFAuS1ksUC5DRCxQLmFFLFAuRUgsUC56TSxQLlowLFAuYzgsUC5PZCxQLmliLFAuR3osUC5xVSxQ
+LlJuLFAuR0QsUC5EbixQLlBFLFAuVWYsVy5pZCxXLkZrLFcuSlEsVy5HbSxXLnZELFcubTYsVy5PdyxX
+Llc5LFcuZFcsVy5GYixXLmtGLFcubWssVy5LbyxQLmlKLFAuRTQsUC5uNixVLmQyLFUuU2UsVS51RixV
+Lk1sLFUueUQsVS53YixCLmo4LEIucXAsVC5HVixMLlhBLEwuWlosTC55OCxNLmxJLE8uekwsWC5XRCxY
+LmR2XSkKcihKLnZCLFtKLnlFLEouWUUsSi5NRixKLmpkLEoucUksSi5EcixILkVULFcuRDAsVy5BeixX
+LkxlLFcuTmgsVy5JQixXLm43LFcuZWEsVy5icixXLlNnLFcudTgsVy5LNyxXLlhXLFAuaEZdKQpyKEou
+TUYsW0ouaUMsSi5rZCxKLmM1XSkKcyhKLlBvLEouamQpCnIoSi5xSSxbSi51cixKLlZBXSkKcyhQLkxV
+LFAublkpCnIoUC5MVSxbSC5YQyxXLnd6LFcuZTddKQpzKEgucWosSC5YQykKcihQLmNYLFtILmJRLEgu
+VTUsUC5tVyxILnVuXSkKcihILmJRLFtILmFMLEguaTUsUC54dV0pCnIoSC5hTCxbSC5uSCxILkE4LFAu
+aThdKQpzKEguU08sUC5BbikKcyhQLlJVLFAuUG4pCnMoUC5HaixQLlJVKQpzKEguUEQsUC5HaikKcyhI
+LkxQLEguV1UpCnIoSC5UcCxbSC5DaixILkFtLEgubGMsSC5kQyxILndOLEguVlgsUC50aCxQLmhhLFAu
+VnMsUC5GdCxQLnlILFAuV00sUC5TWCxQLkdzLFAuZGEsUC5vUSxQLnBWLFAuVTcsUC52cixQLnJILFAu
+S0YsUC5aTCxQLlJULFAualosUC5ycSxQLlJXLFAuQjUsUC5QSSxQLnBLLFAuaGosUC5WcCxQLk9SLFAu
+R0EsUC5XRixQLm4xLFAuY1MsUC5WQyxQLnRwLFAuZTEsUC5OWSxQLlJaLFAuTUUsUC55NSxQLnEzLFAu
+eUksUC5jNixQLnFkLFcuQ3YsVy5iVSxXLmhILFcuS1MsVy5BMyxXLnZOLFcuVXYsVy5FZyxXLkVvLFcu
+V2ssVy5JQSxXLmZtLFAubFIsUC5qZyxQLkdFLFAuTjcsUC51USxQLlBDLFAuWW0sUC5OeixQLm5wLFAu
+VXQsTC5lLEwuVlcsTC5vWixMLmpyLEwucWwsTC5MLEwuV3gsTC5BTyxMLmROLEwuSG8sTC54eixMLklD
+LEwuTDEsTC5uVCxMLkJaLEwuR0gsTC5EVCxMLmVILEwuekQsTC5PRSxMLlRXLEwueHIsTC5FRSxMLlFM
+LEwuVlMsTS5NaSxNLnE3LE0uTm8sWC5xUl0pCnIoUC5YUyxbSC5XMCxILmF6LEgudlYsSC5FcSxQLkM2
+LEgudTksUC5uLFAudSxQLm1wLFAudWIsUC5kcyxQLmxqLFAuVVYsUC5jXSkKcihILmxjLFtILnp4LEgu
+clRdKQpzKEgua1ksUC5DNikKcyhQLmlsLFAuWWspCnIoUC5pbCxbSC5ONSxQLnV3LFcuRDksVy5TeV0p
+CnMoSC5LVyxQLm1XKQpzKEguYjAsSC5FVCkKcihILmIwLFtILlJHLEguV0JdKQpzKEguVlAsSC5SRykK
+cyhILkRnLEguVlApCnMoSC5aRyxILldCKQpzKEguUGcsSC5aRykKcihILlBnLFtILnhqLEguZEUsSC5a
+QSxILndmLEguUHEsSC5lRSxILlY2XSkKcihILnU5LFtILmh6LEguaU1dKQpzKFAuWmYsUC5QZikKcyhQ
+LkppLFAubTApCnMoUC5iNixQLlh2KQpzKFAuVmosUC5XWSkKcihQLlVrLFtQLkNWLFAuWmksUC5ieV0p
+CnMoUC53SSxQLmtUKQpyKFAud0ksW1AuVTgsUC5NeCxQLkUzLFAuR1ldKQpzKFAudTUsUC5aaSkKcihQ
+LkZLLFtQLkNQLFAuS05dKQpyKFAudSxbUC5iSixQLmVZXSkKcyhQLnFlLFAuRG4pCnIoVy5EMCxbVy51
+SCxXLndhLFcuSzUsVy5DbV0pCnIoVy51SCxbVy5jdixXLm54LFcuUUYsVy5DUV0pCnIoVy5jdixbVy5x
+RSxQLmQ1XSkKcihXLnFFLFtXLkdoLFcuZlksVy5uQixXLlFQLFcuaDQsVy5TTixXLmxwLFcuVGIsVy5J
+dixXLkJULFcueVldKQpzKFcub0osVy5MZSkKcyhXLlQ1LFcuQXopCnMoVy5WYixXLlFGKQpzKFcuTzcs
+Vy53YSkKcihXLmVhLFtXLnc2LFcuZXddKQpzKFcuQWosVy53NikKcyhXLnJCLFcuSzcpCnMoVy5CSCxX
+LnJCKQpzKFcudzQsVy5JQikKcyhXLm9hLFcuWFcpCnMoVy5yaCxXLm9hKQpzKFcuaTcsVy5EOSkKcyhQ
+LkFzLFAuVmopCnIoUC5BcyxbVy5JNCxQLktlXSkKcyhXLlJPLFAucWgpCnMoVy5DcSxXLlJPKQpzKFcu
+eEMsUC5NTykKcyhXLmN0LFcubTYpCnMoUC5CZixQLmlKKQpyKFAuRTQsW1AucjcsUC5jb10pCnMoUC5U
+eixQLmNvKQpzKFAubmQsUC5kNSkKcyhCLkx1LE8uekwpCnIoQi5MdSxbRS5PRixGLnJ1LEwuSVZdKQp0
+KEguWEMsSC5SZSkKdChILlJHLFAubEQpCnQoSC5WUCxILlNVKQp0KEguV0IsUC5sRCkKdChILlpHLEgu
+U1UpCnQoUC5uWSxQLmxEKQp0KFAuV1ksUC5sZikKdChQLlJVLFAuS1ApCnQoVy5MZSxXLmlkKQp0KFcu
+SzcsUC5sRCkKdChXLnJCLFcuR20pCnQoVy5YVyxQLmxEKQp0KFcub2EsVy5HbSkKdChQLmNvLFAubEQp
+fSkoKQp2YXIgdj17dHlwZVVuaXZlcnNlOntlQzpuZXcgTWFwKCksdFI6e30sZVQ6e30sdFBWOnt9LHNF
+QTpbXX0sbWFuZ2xlZEdsb2JhbE5hbWVzOntLTjoiaW50IixDUDoiZG91YmxlIixGSzoibnVtIixxVToi
+U3RyaW5nIixhMjoiYm9vbCIsYzg6Ik51bGwiLHpNOiJMaXN0In0sbWFuZ2xlZE5hbWVzOnt9LGdldFR5
+cGVGcm9tTmFtZTpnZXRHbG9iYWxGcm9tTmFtZSxtZXRhZGF0YTpbXSx0eXBlczpbImM4KCkiLCJjOChA
+LEApIiwifigpIiwiQChAKSIsInFVKHFVKSIsImM4KEFqKSIsImM4KGN2KSIsImM4KE83KSIsImEyKHFV
+KSIsImM4KHFVLHFVKSIsIn4ofigpKSIsImEyKGN2LHFVLHFVLEpRKSIsImM4KEApIiwiYzgocVUsQCki
+LCJjOChxVSkiLCJhMihrRikiLCJ+KHh1PHFVPikiLCJjOChlYSkiLCJjOChHRCxAKSIsIktOKEtOLEtO
+KSIsImM4KH4oKSkiLCJjOChALEd6KSIsIn4ocVUscVUpIiwibjYoS04pIiwibjYoQCxAKSIsImEyKHVI
+KSIsImM4KEtOLEApIiwiYzgoZXcpIiwiQChlYSkiLCJ+KGtbR3pdKSIsImM4KEBbR3pdKSIsIn4oQWop
+IiwiYTIoeHU8cVU+KSIsInZzPEA+KEApIiwicjcoQCkiLCJUejxAPihAKSIsIkU0KEApIiwiQChxVSki
+LCJAKEAscVUpIiwifih1SCx1SCkiLCJaMDxxVSxxVT4oWjA8cVUscVU+LHFVKSIsIk83KE83KSIsInFV
+KEtOKSIsIn4ocVUsS04pIiwifihxVVtAXSkiLCJrKEApIiwifihBantyZWxhdGl2ZVRvOnFVfSkiLCJ+
+KEApIl0saW50ZXJjZXB0b3JzQnlUYWc6bnVsbCxsZWFmVGFnczpudWxsfQpILnhiKHYudHlwZVVuaXZl
+cnNlLEpTT04ucGFyc2UoJ3sicngiOiJlYSIsImU1IjoiZWEiLCJZMCI6ImQ1IiwiV3QiOiJkNSIsInYw
+IjoiZXciLCJNciI6InFFIiwiZUwiOiJxRSIsIkkwIjoidUgiLCJocyI6InVIIiwiWGciOiJRRiIsInlj
+IjoiQWoiLCJ5NCI6Inc2IiwiYVAiOiJDbSIsInhjIjoibngiLCJrSiI6Im54IiwielUiOiJEZyIsImRm
+IjoiRVQiLCJ5RSI6eyJhMiI6W119LCJZRSI6eyJjOCI6W119LCJNRiI6eyJ2bSI6W119LCJpQyI6eyJ2
+bSI6W119LCJrZCI6eyJ2bSI6W119LCJjNSI6eyJFSCI6W10sInZtIjpbXX0sImpkIjp7InpNIjpbIjEi
+XSwiY1giOlsiMSJdfSwiUG8iOnsiamQiOlsiMSJdLCJ6TSI6WyIxIl0sImNYIjpbIjEiXX0sIm0xIjp7
+IkFuIjpbIjEiXX0sInFJIjp7IkNQIjpbXSwiRksiOltdfSwidXIiOnsiS04iOltdLCJDUCI6W10sIkZL
+IjpbXX0sIlZBIjp7IkNQIjpbXSwiRksiOltdfSwiRHIiOnsicVUiOltdLCJ2WCI6W119LCJxaiI6eyJS
+ZSI6WyJLTiJdLCJsRCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJjWCI6WyJLTiJdLCJsRC5FIjoiS04iLCJS
+ZS5FIjoiS04ifSwiYlEiOnsiY1giOlsiMSJdfSwiYUwiOnsiY1giOlsiMSJdfSwibkgiOnsiYUwiOlsi
+MSJdLCJjWCI6WyIxIl0sImFMLkUiOiIxIiwiY1guRSI6IjEifSwiYTciOnsiQW4iOlsiMSJdfSwiQTgi
+OnsiYUwiOlsiMiJdLCJjWCI6WyIyIl0sImFMLkUiOiIyIiwiY1guRSI6IjIifSwiVTUiOnsiY1giOlsi
+MSJdLCJjWC5FIjoiMSJ9LCJTTyI6eyJBbiI6WyIxIl19LCJYQyI6eyJSZSI6WyIxIl0sImxEIjpbIjEi
+XSwiek0iOlsiMSJdLCJjWCI6WyIxIl19LCJ3diI6eyJHRCI6W119LCJQRCI6eyJHaiI6WyIxIiwiMiJd
+LCJSVSI6WyIxIiwiMiJdLCJQbiI6WyIxIiwiMiJdLCJLUCI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJd
+fSwiV1UiOnsiWjAiOlsiMSIsIjIiXX0sIkxQIjp7IldVIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19
+LCJMSSI6eyJ2USI6W119LCJXMCI6eyJYUyI6W119LCJheiI6eyJYUyI6W119LCJ2ViI6eyJYUyI6W119
+LCJYTyI6eyJHeiI6W119LCJUcCI6eyJFSCI6W119LCJsYyI6eyJFSCI6W119LCJ6eCI6eyJFSCI6W119
+LCJyVCI6eyJFSCI6W119LCJFcSI6eyJYUyI6W119LCJrWSI6eyJYUyI6W119LCJONSI6eyJGbyI6WyIx
+IiwiMiJdLCJZayI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdLCJZay5LIjoiMSIsIllrLlYiOiIyIn0s
+Imk1Ijp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiTjYiOnsiQW4iOlsiMSJdfSwiVlIiOnsid0wiOltd
+LCJ2WCI6W119LCJFSyI6eyJpYiI6W10sIk9kIjpbXX0sIktXIjp7ImNYIjpbImliIl0sImNYLkUiOiJp
+YiJ9LCJQYiI6eyJBbiI6WyJpYiJdfSwidFEiOnsiT2QiOltdfSwidW4iOnsiY1giOlsiT2QiXSwiY1gu
+RSI6Ik9kIn0sIlNkIjp7IkFuIjpbIk9kIl19LCJFVCI6eyJBUyI6W119LCJiMCI6eyJYaiI6WyJAIl0s
+IkVUIjpbXSwiQVMiOltdfSwiRGciOnsibEQiOlsiQ1AiXSwiWGoiOlsiQCJdLCJ6TSI6WyJDUCJdLCJF
+VCI6W10sIlNVIjpbIkNQIl0sIkFTIjpbXSwiY1giOlsiQ1AiXSwibEQuRSI6IkNQIn0sIlBnIjp7ImxE
+IjpbIktOIl0sInpNIjpbIktOIl0sIlhqIjpbIkAiXSwiRVQiOltdLCJTVSI6WyJLTiJdLCJBUyI6W10s
+ImNYIjpbIktOIl19LCJ4aiI6eyJsRCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJYaiI6WyJAIl0sIkVUIjpb
+XSwiU1UiOlsiS04iXSwiQVMiOltdLCJjWCI6WyJLTiJdLCJsRC5FIjoiS04ifSwiZEUiOnsibEQiOlsi
+S04iXSwiek0iOlsiS04iXSwiWGoiOlsiQCJdLCJFVCI6W10sIlNVIjpbIktOIl0sIkFTIjpbXSwiY1gi
+OlsiS04iXSwibEQuRSI6IktOIn0sIlpBIjp7ImxEIjpbIktOIl0sInpNIjpbIktOIl0sIlhqIjpbIkAi
+XSwiRVQiOltdLCJTVSI6WyJLTiJdLCJBUyI6W10sImNYIjpbIktOIl0sImxELkUiOiJLTiJ9LCJ3ZiI6
+eyJsRCI6WyJLTiJdLCJ6TSI6WyJLTiJdLCJYaiI6WyJAIl0sIkVUIjpbXSwiU1UiOlsiS04iXSwiQVMi
+OltdLCJjWCI6WyJLTiJdLCJsRC5FIjoiS04ifSwiUHEiOnsibEQiOlsiS04iXSwiek0iOlsiS04iXSwi
+WGoiOlsiQCJdLCJFVCI6W10sIlNVIjpbIktOIl0sIkFTIjpbXSwiY1giOlsiS04iXSwibEQuRSI6IktO
+In0sImVFIjp7ImxEIjpbIktOIl0sInpNIjpbIktOIl0sIlhqIjpbIkAiXSwiRVQiOltdLCJTVSI6WyJL
+TiJdLCJBUyI6W10sImNYIjpbIktOIl0sImxELkUiOiJLTiJ9LCJWNiI6eyJuNiI6W10sImxEIjpbIktO
+Il0sInpNIjpbIktOIl0sIlhqIjpbIkAiXSwiRVQiOltdLCJTVSI6WyJLTiJdLCJBUyI6W10sImNYIjpb
+IktOIl0sImxELkUiOiJLTiJ9LCJ1OSI6eyJYUyI6W119LCJoeiI6eyJYUyI6W119LCJpTSI6eyJYUyI6
+W119LCJaZiI6eyJQZiI6WyIxIl19LCJ2cyI6eyJiOCI6WyIxIl19LCJDdyI6eyJYUyI6W119LCJtMCI6
+eyJKQiI6W119LCJKaSI6eyJKQiI6W119LCJiNiI6eyJYdiI6WyIxIl0sInh1IjpbIjEiXSwiY1giOlsi
+MSJdfSwibG0iOnsiQW4iOlsiMSJdfSwibVciOnsiY1giOlsiMSJdfSwiTFUiOnsibEQiOlsiMSJdLCJ6
+TSI6WyIxIl0sImNYIjpbIjEiXX0sImlsIjp7IllrIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJZ
+ayI6eyJaMCI6WyIxIiwiMiJdfSwiUG4iOnsiWjAiOlsiMSIsIjIiXX0sIkdqIjp7IlJVIjpbIjEiLCIy
+Il0sIlBuIjpbIjEiLCIyIl0sIktQIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJWaiI6eyJsZiI6
+WyIxIl0sInh1IjpbIjEiXSwiY1giOlsiMSJdfSwiWHYiOnsieHUiOlsiMSJdLCJjWCI6WyIxIl19LCJ1
+dyI6eyJZayI6WyJxVSIsIkAiXSwiWjAiOlsicVUiLCJAIl0sIllrLksiOiJxVSIsIllrLlYiOiJAIn0s
+Imk4Ijp7ImFMIjpbInFVIl0sImNYIjpbInFVIl0sImFMLkUiOiJxVSIsImNYLkUiOiJxVSJ9LCJDViI6
+eyJVayI6WyJ6TTxLTj4iLCJxVSJdLCJVay5TIjoiek08S04+In0sIlU4Ijp7IndJIjpbInpNPEtOPiIs
+InFVIl19LCJaaSI6eyJVayI6WyJxVSIsInpNPEtOPiJdfSwiYnkiOnsiVWsiOlsiayIsInFVIl0sIlVr
+LlMiOiJrIn0sIk14Ijp7IndJIjpbInFVIiwiayJdfSwidTUiOnsiVWsiOlsicVUiLCJ6TTxLTj4iXSwi
+VWsuUyI6InFVIn0sIkUzIjp7IndJIjpbInFVIiwiek08S04+Il19LCJHWSI6eyJ3SSI6WyJ6TTxLTj4i
+LCJxVSJdfSwiQ1AiOnsiRksiOltdfSwiQzYiOnsiWFMiOltdfSwibiI6eyJYUyI6W119LCJ1Ijp7IlhT
+IjpbXX0sImJKIjp7IlhTIjpbXX0sImVZIjp7IlhTIjpbXX0sIm1wIjp7IlhTIjpbXX0sInViIjp7IlhT
+IjpbXX0sImRzIjp7IlhTIjpbXX0sImxqIjp7IlhTIjpbXX0sIlVWIjp7IlhTIjpbXX0sIms1Ijp7IlhT
+IjpbXX0sIktZIjp7IlhTIjpbXX0sImMiOnsiWFMiOltdfSwiS04iOnsiRksiOltdfSwiek0iOnsiY1gi
+OlsiMSJdfSwiaWIiOnsiT2QiOltdfSwieHUiOnsiY1giOlsiMSJdfSwicVUiOnsidlgiOltdfSwiUm4i
+OnsiQkwiOltdfSwiRG4iOnsiaUQiOltdfSwiVWYiOnsiaUQiOltdfSwicWUiOnsiaUQiOltdfSwicUUi
+OnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIkdoIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJm
+WSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwibkIiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0s
+IlFQIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJueCI6eyJ1SCI6W10sIkQwIjpbXX0sIlFGIjp7
+InVIIjpbXSwiRDAiOltdfSwiSUIiOnsidG4iOlsiRksiXX0sInd6Ijp7ImxEIjpbIjEiXSwiek0iOlsi
+MSJdLCJjWCI6WyIxIl0sImxELkUiOiIxIn0sImN2Ijp7InVIIjpbXSwiRDAiOltdfSwiVDUiOnsiQXoi
+OltdfSwiaDQiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlZiIjp7InVIIjpbXSwiRDAiOltdfSwi
+TzciOnsiRDAiOltdfSwid2EiOnsiRDAiOltdfSwiQWoiOnsiZWEiOltdfSwiZTciOnsibEQiOlsidUgi
+XSwiek0iOlsidUgiXSwiY1giOlsidUgiXSwibEQuRSI6InVIIn0sInVIIjp7IkQwIjpbXX0sIkJIIjp7
+IkdtIjpbInVIIl0sImxEIjpbInVIIl0sInpNIjpbInVIIl0sIlhqIjpbInVIIl0sImNYIjpbInVIIl0s
+ImxELkUiOiJ1SCIsIkdtLkUiOiJ1SCJ9LCJTTiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiZXci
+OnsiZWEiOltdfSwibHAiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlRiIjp7ImN2IjpbXSwidUgi
+OltdLCJEMCI6W119LCJJdiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiQlQiOnsiY3YiOltdLCJ1
+SCI6W10sIkQwIjpbXX0sInlZIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJ3NiI6eyJlYSI6W119
+LCJLNSI6eyJ2NiI6W10sIkQwIjpbXX0sIkNtIjp7IkQwIjpbXX0sIkNRIjp7InVIIjpbXSwiRDAiOltd
+fSwidzQiOnsidG4iOlsiRksiXX0sInJoIjp7IkdtIjpbInVIIl0sImxEIjpbInVIIl0sInpNIjpbInVI
+Il0sIlhqIjpbInVIIl0sImNYIjpbInVIIl0sImxELkUiOiJ1SCIsIkdtLkUiOiJ1SCJ9LCJEOSI6eyJZ
+ayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXX0sImk3Ijp7IllrIjpbInFVIiwicVUiXSwiWjAi
+OlsicVUiLCJxVSJdLCJZay5LIjoicVUiLCJZay5WIjoicVUifSwiU3kiOnsiWWsiOlsicVUiLCJxVSJd
+LCJaMCI6WyJxVSIsInFVIl0sIllrLksiOiJxVSIsIllrLlYiOiJxVSJ9LCJJNCI6eyJsZiI6WyJxVSJd
+LCJ4dSI6WyJxVSJdLCJjWCI6WyJxVSJdfSwiUk8iOnsicWgiOlsiMSJdfSwiQ3EiOnsiUk8iOlsiMSJd
+LCJxaCI6WyIxIl19LCJ4QyI6eyJNTyI6WyIxIl19LCJKUSI6eyJrRiI6W119LCJ2RCI6eyJrRiI6W119
+LCJtNiI6eyJrRiI6W119LCJjdCI6eyJrRiI6W119LCJPdyI6eyJrRiI6W119LCJXOSI6eyJBbiI6WyIx
+Il19LCJkVyI6eyJ2NiI6W10sIkQwIjpbXX0sIm1rIjp7InkwIjpbXX0sIktvIjp7Im9uIjpbXX0sIkFz
+Ijp7ImxmIjpbInFVIl0sInh1IjpbInFVIl0sImNYIjpbInFVIl19LCJyNyI6eyJFNCI6W119LCJUeiI6
+eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiRTQiOltdLCJjWCI6WyIxIl0sImxELkUiOiIxIn0sIm5kIjp7
+ImQ1IjpbXSwiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIktlIjp7ImxmIjpbInFVIl0sInh1IjpbInFV
+Il0sImNYIjpbInFVIl19LCJkNSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwibjYiOnsiek0iOlsi
+S04iXSwiQVMiOltdLCJjWCI6WyJLTiJdfSwiWEEiOnsia0YiOltdfSwiT0YiOnsiTHUiOltdfSwicnUi
+OnsiTHUiOltdfSwiSVYiOnsiTHUiOltdfX0nKSkKSC5GRih2LnR5cGVVbml2ZXJzZSxKU09OLnBhcnNl
+KCd7ImJRIjoxLCJYQyI6MSwiTU8iOjEsImtUIjoyLCJtVyI6MSwiTFUiOjEsImlsIjoyLCJWaiI6MSwi
+blkiOjEsIldZIjoxLCJjbyI6MX0nKSkKdmFyIHU9KGZ1bmN0aW9uIHJ0aWkoKXt2YXIgdD1ILk4wCnJl
+dHVybntpOnQoIkdoIiksbjp0KCJDdyIpLGNSOnQoIm5CIiksZDp0KCJBeiIpLFk6dCgiUVAiKSxnRjp0
+KCJQRDxHRCxAPiIpLGg6dCgiY3YiKSxiVTp0KCJYUyIpLEI6dCgiZWEiKSxhUzp0KCJEMCIpLGM4OnQo
+IlQ1IiksWjp0KCJFSCIpLGM6dCgiYjg8QD4iKSxyOnQoIk83IiksSTp0KCJTZyIpLG86dCgidlEiKSxl
+aDp0KCJjWDx1SD4iKSxYOnQoImNYPHFVPiIpLFI6dCgiY1g8QD4iKSxmQTp0KCJqZDxTZT4iKSx1OnQo
+ImpkPGo4PiIpLGJQOnQoImpkPHVGPiIpLGZoOnQoImpkPFpaPiIpLGs6dCgiamQ8a0Y+Iiksczp0KCJq
+ZDxxVT4iKSxoaDp0KCJqZDx5RD4iKSxhSjp0KCJqZDx3Yj4iKSxtOnQoImpkPEA+IiksdDp0KCJqZDxL
+Tj4iKSxlSDp0KCJ2bSIpLGc6dCgiYzUiKSxhVTp0KCJYajxAPiIpLGFtOnQoIlR6PEA+IiksZW86dCgi
+TjU8R0QsQD4iKSx2OnQoIkU0IiksZHo6dCgiaEYiKSxhOnQoInpNPHFVPiIpLGo6dCgiek08QD4iKSxM
+OnQoInpNPEtOPiIpLEY6dCgidTgiKSxmOnQoIlowPHFVLHFVPiIpLGI6dCgiWjA8cVUsQD4iKSxHOnQo
+IlowPEAsQD4iKSxkdjp0KCJBODxxVSxxVT4iKSxkbzp0KCJBODxxVSxAPiIpLFY6dCgiQWoiKSxkRDp0
+KCJFVCIpLGJtOnQoIlY2IiksQTp0KCJ1SCIpLGU6dCgia0YiKSxQOnQoImM4IiksSzp0KCJrIikscDp0
+KCJldyIpLHE6dCgidG48Rks+IiksZnY6dCgid0wiKSxldzp0KCJuZCIpLEM6dCgieHU8cVU+IiksbDp0
+KCJHeiIpLE46dCgicVUiKSxkRzp0KCJxVShxVSkiKSxnNzp0KCJkNSIpLGZvOnQoIkdEIiksYVc6dCgi
+eVkiKSx3OnQoIkFTIiksZ2M6dCgibjYiKSxhazp0KCJrZCIpLFQ6dCgiR2o8cVUscVU+IiksRDp0KCJp
+RCIpLGNjOnQoIlU1PHFVPiIpLGc0OnQoIks1IiksY2k6dCgidjYiKSxnMjp0KCJDbSIpLGJqOnQoIlpm
+PE83PiIpLGg5OnQoIkNRIiksYWM6dCgiZTciKSxROnQoIkNxPEFqPiIpLFM6dCgid3o8Y3Y+IikseDp0
+KCJGZTxALEA+IiksYW86dCgidnM8Tzc+IiksXzp0KCJ2czxAPiIpLGZKOnQoInZzPEtOPiIpLE86dCgi
+SlEiKSxKOnQoImJuIiksY0o6dCgiYTIiKSxhbDp0KCJhMihrKSIpLGJCOnQoImEyKHFVKSIpLGJmOnQo
+ImEyKEApIiksejp0KCJAIiksZk86dCgiQCgpIiksVTp0KCJAKGVhKSIpLHk6dCgiQChrKSIpLGVwOnQo
+IkAoayxrKSIpLFc6dCgiQChrLEd6KSIpLGNoOnQoIkAoeHU8cVU+KSIpLGRPOnQoIkAocVUpIiksYjg6
+dCgiQChALEApIiksZWc6dCgiS04iKSxIOnQoIn4iKSxNOnQoIn4oKSIpLGFuOnQoIn4oZXcpIiksRTp0
+KCJ+KHFVLHFVKSIpLGNBOnQoIn4ocVUsQCkiKX19KSgpOyhmdW5jdGlvbiBjb25zdGFudHMoKXt2YXIg
+dD1odW5rSGVscGVycy5tYWtlQ29uc3RMaXN0CkMuUlk9Vy5RUC5wcm90b3R5cGUKQy5CWj1XLlZiLnBy
+b3RvdHlwZQpDLkR0PVcuTzcucHJvdG90eXBlCkMuT2s9Si52Qi5wcm90b3R5cGUKQy5ObT1KLmpkLnBy
+b3RvdHlwZQpDLmpuPUoudXIucHJvdG90eXBlCkMuak49Si5ZRS5wcm90b3R5cGUKQy5DRD1KLnFJLnBy
+b3RvdHlwZQpDLnhCPUouRHIucHJvdG90eXBlCkMuREc9Si5jNS5wcm90b3R5cGUKQy5FeD1XLnU4LnBy
+b3RvdHlwZQpDLkx0PVcuU04ucHJvdG90eXBlCkMuWlE9Si5pQy5wcm90b3R5cGUKQy5JZT1XLlRiLnBy
+b3RvdHlwZQpDLnZCPUoua2QucHJvdG90eXBlCkMub2w9Vy5LNS5wcm90b3R5cGUKQy55OD1uZXcgUC5V
+OCgpCkMuaDk9bmV3IFAuQ1YoKQpDLk80PWZ1bmN0aW9uIGdldFRhZ0ZhbGxiYWNrKG8pIHsKICB2YXIg
+cyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTsKICByZXR1cm4gcy5zdWJzdHJpbmco
+OCwgcy5sZW5ndGggLSAxKTsKfQpDLllxPWZ1bmN0aW9uKCkgewogIHZhciB0b1N0cmluZ0Z1bmN0aW9u
+ID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKICBmdW5jdGlvbiBnZXRUYWcobykgewogICAgdmFy
+IHMgPSB0b1N0cmluZ0Z1bmN0aW9uLmNhbGwobyk7CiAgICByZXR1cm4gcy5zdWJzdHJpbmcoOCwgcy5s
+ZW5ndGggLSAxKTsKICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZyhvYmplY3QsIHRhZykgewogICAg
+aWYgKC9eSFRNTFtBLVpdLipFbGVtZW50JC8udGVzdCh0YWcpKSB7CiAgICAgIHZhciBuYW1lID0gdG9T
+dHJpbmdGdW5jdGlvbi5jYWxsKG9iamVjdCk7CiAgICAgIGlmIChuYW1lID09ICJbb2JqZWN0IE9iamVj
+dF0iKSByZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAgICB9CiAgfQogIGZ1
+bmN0aW9uIGdldFVua25vd25UYWdHZW5lcmljQnJvd3NlcihvYmplY3QsIHRhZykgewogICAgaWYgKHNl
+bGYuSFRNTEVsZW1lbnQgJiYgb2JqZWN0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHJldHVybiAiSFRN
+TEVsZW1lbnQiOwogICAgcmV0dXJuIGdldFVua25vd25UYWcob2JqZWN0LCB0YWcpOwogIH0KICBmdW5j
+dGlvbiBwcm90b3R5cGVGb3JUYWcodGFnKSB7CiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PSAidW5kZWZp
+bmVkIikgcmV0dXJuIG51bGw7CiAgICBpZiAodHlwZW9mIHdpbmRvd1t0YWddID09ICJ1bmRlZmluZWQi
+KSByZXR1cm4gbnVsbDsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYgKHR5
+cGVvZiBjb25zdHJ1Y3RvciAhPSAiZnVuY3Rpb24iKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBjb25z
+dHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQogIGZ1bmN0aW9uIGRpc2NyaW1pbmF0b3IodGFnKSB7IHJldHVy
+biBudWxsOyB9CiAgdmFyIGlzQnJvd3NlciA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9iamVjdCI7CiAg
+cmV0dXJuIHsKICAgIGdldFRhZzogZ2V0VGFnLAogICAgZ2V0VW5rbm93blRhZzogaXNCcm93c2VyID8g
+Z2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2VyIDogZ2V0VW5rbm93blRhZywKICAgIHByb3RvdHlwZUZv
+clRhZzogcHJvdG90eXBlRm9yVGFnLAogICAgZGlzY3JpbWluYXRvcjogZGlzY3JpbWluYXRvciB9Owp9
+CkMud2I9ZnVuY3Rpb24oZ2V0VGFnRmFsbGJhY2spIHsKICByZXR1cm4gZnVuY3Rpb24oaG9va3MpIHsK
+ICAgIGlmICh0eXBlb2YgbmF2aWdhdG9yICE9ICJvYmplY3QiKSByZXR1cm4gaG9va3M7CiAgICB2YXIg
+dWEgPSBuYXZpZ2F0b3IudXNlckFnZW50OwogICAgaWYgKHVhLmluZGV4T2YoIkR1bXBSZW5kZXJUcmVl
+IikgPj0gMCkgcmV0dXJuIGhvb2tzOwogICAgaWYgKHVhLmluZGV4T2YoIkNocm9tZSIpID49IDApIHsK
+ICAgICAgZnVuY3Rpb24gY29uZmlybShwKSB7CiAgICAgICAgcmV0dXJuIHR5cGVvZiB3aW5kb3cgPT0g
+Im9iamVjdCIgJiYgd2luZG93W3BdICYmIHdpbmRvd1twXS5uYW1lID09IHA7CiAgICAgIH0KICAgICAg
+aWYgKGNvbmZpcm0oIldpbmRvdyIpICYmIGNvbmZpcm0oIkhUTUxFbGVtZW50IikpIHJldHVybiBob29r
+czsKICAgIH0KICAgIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZhbGxiYWNrOwogIH07Cn0KQy5LVT1mdW5j
+dGlvbihob29rcykgewogIGlmICh0eXBlb2YgZGFydEV4cGVyaW1lbnRhbEZpeHVwR2V0VGFnICE9ICJm
+dW5jdGlvbiIpIHJldHVybiBob29rczsKICBob29rcy5nZXRUYWcgPSBkYXJ0RXhwZXJpbWVudGFsRml4
+dXBHZXRUYWcoaG9va3MuZ2V0VGFnKTsKfQpDLmZRPWZ1bmN0aW9uKGhvb2tzKSB7CiAgdmFyIGdldFRh
+ZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcHJvdG90eXBlRm9yVGFnID0gaG9va3MucHJvdG90eXBlRm9y
+VGFnOwogIGZ1bmN0aW9uIGdldFRhZ0ZpeGVkKG8pIHsKICAgIHZhciB0YWcgPSBnZXRUYWcobyk7CiAg
+ICBpZiAodGFnID09ICJEb2N1bWVudCIpIHsKICAgICAgaWYgKCEhby54bWxWZXJzaW9uKSByZXR1cm4g
+IiFEb2N1bWVudCI7CiAgICAgIHJldHVybiAiIUhUTUxEb2N1bWVudCI7CiAgICB9CiAgICByZXR1cm4g
+dGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdGaXhlZCh0YWcpIHsKICAgIGlmICh0YWcg
+PT0gIkRvY3VtZW50IikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gcHJvdG90eXBlRm9yVGFnKHRhZyk7
+CiAgfQogIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpeGVkOwogIGhvb2tzLnByb3RvdHlwZUZvclRhZyA9
+IHByb3RvdHlwZUZvclRhZ0ZpeGVkOwp9CkMuZGs9ZnVuY3Rpb24oaG9va3MpIHsKICB2YXIgdXNlckFn
+ZW50ID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IiA/IG5hdmlnYXRvci51c2VyQWdlbnQgOiAi
+IjsKICBpZiAodXNlckFnZW50LmluZGV4T2YoIkZpcmVmb3giKSA9PSAtMSkgcmV0dXJuIGhvb2tzOwog
+IHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAgIkJlZm9yZVVu
+bG9hZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJkIiwKICAgICJH
+ZW9HZW9sb2NhdGlvbiI6ICJHZW9sb2NhdGlvbiIsCiAgICAiTG9jYXRpb24iOiAiIUxvY2F0aW9uIiwK
+ICAgICJXb3JrZXJNZXNzYWdlRXZlbnQiOiAiTWVzc2FnZUV2ZW50IiwKICAgICJYTUxEb2N1bWVudCI6
+ICIhRG9jdW1lbnQifTsKICBmdW5jdGlvbiBnZXRUYWdGaXJlZm94KG8pIHsKICAgIHZhciB0YWcgPSBn
+ZXRUYWcobyk7CiAgICByZXR1cm4gcXVpY2tNYXBbdGFnXSB8fCB0YWc7CiAgfQogIGhvb2tzLmdldFRh
+ZyA9IGdldFRhZ0ZpcmVmb3g7Cn0KQy54aT1mdW5jdGlvbihob29rcykgewogIHZhciB1c2VyQWdlbnQg
+PSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJBZ2VudCA6ICIiOwog
+IGlmICh1c2VyQWdlbnQuaW5kZXhPZigiVHJpZGVudC8iKSA9PSAtMSkgcmV0dXJuIGhvb2tzOwogIHZh
+ciBnZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAgIkJlZm9yZVVubG9h
+ZEV2ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJkIiwKICAgICJIVE1M
+RERFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJIVE1MRFRFbGVtZW50IjogIkhUTUxFbGVtZW50
+IiwKICAgICJIVE1MUGhyYXNlRWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAiUG9zaXRpb24iOiAi
+R2VvcG9zaXRpb24iCiAgfTsKICBmdW5jdGlvbiBnZXRUYWdJRShvKSB7CiAgICB2YXIgdGFnID0gZ2V0
+VGFnKG8pOwogICAgdmFyIG5ld1RhZyA9IHF1aWNrTWFwW3RhZ107CiAgICBpZiAobmV3VGFnKSByZXR1
+cm4gbmV3VGFnOwogICAgaWYgKHRhZyA9PSAiT2JqZWN0IikgewogICAgICBpZiAod2luZG93LkRhdGFW
+aWV3ICYmIChvIGluc3RhbmNlb2Ygd2luZG93LkRhdGFWaWV3KSkgcmV0dXJuICJEYXRhVmlldyI7CiAg
+ICB9CiAgICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdJRSh0YWcpIHsK
+ICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYgKGNvbnN0cnVjdG9yID09IG51
+bGwpIHJldHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlwZTsKICB9CiAgaG9v
+a3MuZ2V0VGFnID0gZ2V0VGFnSUU7CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0gcHJvdG90eXBlRm9y
+VGFnSUU7Cn0KQy5pNz1mdW5jdGlvbihob29rcykgeyByZXR1cm4gaG9va3M7IH0KCkMuQ3Q9bmV3IFAu
+YnkoKQpDLkVxPW5ldyBQLms1KCkKQy54TT1uZXcgUC51NSgpCkMuUWs9bmV3IFAuRTMoKQpDLk5VPW5l
+dyBQLkppKCkKQy5BMz1uZXcgUC5NeChudWxsKQpDLkdiPUguVk0odChbMTI3LDIwNDcsNjU1MzUsMTEx
+NDExMV0pLHUudCkKQy5haz1ILlZNKHQoWzAsMCwzMjc3NiwzMzc5MiwxLDEwMjQwLDAsMF0pLHUudCkK
+Qy5jbT1ILlZNKHQoWyIqOjpjbGFzcyIsIio6OmRpciIsIio6OmRyYWdnYWJsZSIsIio6OmhpZGRlbiIs
+Iio6OmlkIiwiKjo6aW5lcnQiLCIqOjppdGVtcHJvcCIsIio6Oml0ZW1yZWYiLCIqOjppdGVtc2NvcGUi
+LCIqOjpsYW5nIiwiKjo6c3BlbGxjaGVjayIsIio6OnRpdGxlIiwiKjo6dHJhbnNsYXRlIiwiQTo6YWNj
+ZXNza2V5IiwiQTo6Y29vcmRzIiwiQTo6aHJlZmxhbmciLCJBOjpuYW1lIiwiQTo6c2hhcGUiLCJBOjp0
+YWJpbmRleCIsIkE6OnRhcmdldCIsIkE6OnR5cGUiLCJBUkVBOjphY2Nlc3NrZXkiLCJBUkVBOjphbHQi
+LCJBUkVBOjpjb29yZHMiLCJBUkVBOjpub2hyZWYiLCJBUkVBOjpzaGFwZSIsIkFSRUE6OnRhYmluZGV4
+IiwiQVJFQTo6dGFyZ2V0IiwiQVVESU86OmNvbnRyb2xzIiwiQVVESU86Omxvb3AiLCJBVURJTzo6bWVk
+aWFncm91cCIsIkFVRElPOjptdXRlZCIsIkFVRElPOjpwcmVsb2FkIiwiQkRPOjpkaXIiLCJCT0RZOjph
+bGluayIsIkJPRFk6OmJnY29sb3IiLCJCT0RZOjpsaW5rIiwiQk9EWTo6dGV4dCIsIkJPRFk6OnZsaW5r
+IiwiQlI6OmNsZWFyIiwiQlVUVE9OOjphY2Nlc3NrZXkiLCJCVVRUT046OmRpc2FibGVkIiwiQlVUVE9O
+OjpuYW1lIiwiQlVUVE9OOjp0YWJpbmRleCIsIkJVVFRPTjo6dHlwZSIsIkJVVFRPTjo6dmFsdWUiLCJD
+QU5WQVM6OmhlaWdodCIsIkNBTlZBUzo6d2lkdGgiLCJDQVBUSU9OOjphbGlnbiIsIkNPTDo6YWxpZ24i
+LCJDT0w6OmNoYXIiLCJDT0w6OmNoYXJvZmYiLCJDT0w6OnNwYW4iLCJDT0w6OnZhbGlnbiIsIkNPTDo6
+d2lkdGgiLCJDT0xHUk9VUDo6YWxpZ24iLCJDT0xHUk9VUDo6Y2hhciIsIkNPTEdST1VQOjpjaGFyb2Zm
+IiwiQ09MR1JPVVA6OnNwYW4iLCJDT0xHUk9VUDo6dmFsaWduIiwiQ09MR1JPVVA6OndpZHRoIiwiQ09N
+TUFORDo6Y2hlY2tlZCIsIkNPTU1BTkQ6OmNvbW1hbmQiLCJDT01NQU5EOjpkaXNhYmxlZCIsIkNPTU1B
+TkQ6OmxhYmVsIiwiQ09NTUFORDo6cmFkaW9ncm91cCIsIkNPTU1BTkQ6OnR5cGUiLCJEQVRBOjp2YWx1
+ZSIsIkRFTDo6ZGF0ZXRpbWUiLCJERVRBSUxTOjpvcGVuIiwiRElSOjpjb21wYWN0IiwiRElWOjphbGln
+biIsIkRMOjpjb21wYWN0IiwiRklFTERTRVQ6OmRpc2FibGVkIiwiRk9OVDo6Y29sb3IiLCJGT05UOjpm
+YWNlIiwiRk9OVDo6c2l6ZSIsIkZPUk06OmFjY2VwdCIsIkZPUk06OmF1dG9jb21wbGV0ZSIsIkZPUk06
+OmVuY3R5cGUiLCJGT1JNOjptZXRob2QiLCJGT1JNOjpuYW1lIiwiRk9STTo6bm92YWxpZGF0ZSIsIkZP
+Uk06OnRhcmdldCIsIkZSQU1FOjpuYW1lIiwiSDE6OmFsaWduIiwiSDI6OmFsaWduIiwiSDM6OmFsaWdu
+IiwiSDQ6OmFsaWduIiwiSDU6OmFsaWduIiwiSDY6OmFsaWduIiwiSFI6OmFsaWduIiwiSFI6Om5vc2hh
+ZGUiLCJIUjo6c2l6ZSIsIkhSOjp3aWR0aCIsIkhUTUw6OnZlcnNpb24iLCJJRlJBTUU6OmFsaWduIiwi
+SUZSQU1FOjpmcmFtZWJvcmRlciIsIklGUkFNRTo6aGVpZ2h0IiwiSUZSQU1FOjptYXJnaW5oZWlnaHQi
+LCJJRlJBTUU6Om1hcmdpbndpZHRoIiwiSUZSQU1FOjp3aWR0aCIsIklNRzo6YWxpZ24iLCJJTUc6OmFs
+dCIsIklNRzo6Ym9yZGVyIiwiSU1HOjpoZWlnaHQiLCJJTUc6OmhzcGFjZSIsIklNRzo6aXNtYXAiLCJJ
+TUc6Om5hbWUiLCJJTUc6OnVzZW1hcCIsIklNRzo6dnNwYWNlIiwiSU1HOjp3aWR0aCIsIklOUFVUOjph
+Y2NlcHQiLCJJTlBVVDo6YWNjZXNza2V5IiwiSU5QVVQ6OmFsaWduIiwiSU5QVVQ6OmFsdCIsIklOUFVU
+OjphdXRvY29tcGxldGUiLCJJTlBVVDo6YXV0b2ZvY3VzIiwiSU5QVVQ6OmNoZWNrZWQiLCJJTlBVVDo6
+ZGlzYWJsZWQiLCJJTlBVVDo6aW5wdXRtb2RlIiwiSU5QVVQ6OmlzbWFwIiwiSU5QVVQ6Omxpc3QiLCJJ
+TlBVVDo6bWF4IiwiSU5QVVQ6Om1heGxlbmd0aCIsIklOUFVUOjptaW4iLCJJTlBVVDo6bXVsdGlwbGUi
+LCJJTlBVVDo6bmFtZSIsIklOUFVUOjpwbGFjZWhvbGRlciIsIklOUFVUOjpyZWFkb25seSIsIklOUFVU
+OjpyZXF1aXJlZCIsIklOUFVUOjpzaXplIiwiSU5QVVQ6OnN0ZXAiLCJJTlBVVDo6dGFiaW5kZXgiLCJJ
+TlBVVDo6dHlwZSIsIklOUFVUOjp1c2VtYXAiLCJJTlBVVDo6dmFsdWUiLCJJTlM6OmRhdGV0aW1lIiwi
+S0VZR0VOOjpkaXNhYmxlZCIsIktFWUdFTjo6a2V5dHlwZSIsIktFWUdFTjo6bmFtZSIsIkxBQkVMOjph
+Y2Nlc3NrZXkiLCJMQUJFTDo6Zm9yIiwiTEVHRU5EOjphY2Nlc3NrZXkiLCJMRUdFTkQ6OmFsaWduIiwi
+TEk6OnR5cGUiLCJMSTo6dmFsdWUiLCJMSU5LOjpzaXplcyIsIk1BUDo6bmFtZSIsIk1FTlU6OmNvbXBh
+Y3QiLCJNRU5VOjpsYWJlbCIsIk1FTlU6OnR5cGUiLCJNRVRFUjo6aGlnaCIsIk1FVEVSOjpsb3ciLCJN
+RVRFUjo6bWF4IiwiTUVURVI6Om1pbiIsIk1FVEVSOjp2YWx1ZSIsIk9CSkVDVDo6dHlwZW11c3RtYXRj
+aCIsIk9MOjpjb21wYWN0IiwiT0w6OnJldmVyc2VkIiwiT0w6OnN0YXJ0IiwiT0w6OnR5cGUiLCJPUFRH
+Uk9VUDo6ZGlzYWJsZWQiLCJPUFRHUk9VUDo6bGFiZWwiLCJPUFRJT046OmRpc2FibGVkIiwiT1BUSU9O
+OjpsYWJlbCIsIk9QVElPTjo6c2VsZWN0ZWQiLCJPUFRJT046OnZhbHVlIiwiT1VUUFVUOjpmb3IiLCJP
+VVRQVVQ6Om5hbWUiLCJQOjphbGlnbiIsIlBSRTo6d2lkdGgiLCJQUk9HUkVTUzo6bWF4IiwiUFJPR1JF
+U1M6Om1pbiIsIlBST0dSRVNTOjp2YWx1ZSIsIlNFTEVDVDo6YXV0b2NvbXBsZXRlIiwiU0VMRUNUOjpk
+aXNhYmxlZCIsIlNFTEVDVDo6bXVsdGlwbGUiLCJTRUxFQ1Q6Om5hbWUiLCJTRUxFQ1Q6OnJlcXVpcmVk
+IiwiU0VMRUNUOjpzaXplIiwiU0VMRUNUOjp0YWJpbmRleCIsIlNPVVJDRTo6dHlwZSIsIlRBQkxFOjph
+bGlnbiIsIlRBQkxFOjpiZ2NvbG9yIiwiVEFCTEU6OmJvcmRlciIsIlRBQkxFOjpjZWxscGFkZGluZyIs
+IlRBQkxFOjpjZWxsc3BhY2luZyIsIlRBQkxFOjpmcmFtZSIsIlRBQkxFOjpydWxlcyIsIlRBQkxFOjpz
+dW1tYXJ5IiwiVEFCTEU6OndpZHRoIiwiVEJPRFk6OmFsaWduIiwiVEJPRFk6OmNoYXIiLCJUQk9EWTo6
+Y2hhcm9mZiIsIlRCT0RZOjp2YWxpZ24iLCJURDo6YWJiciIsIlREOjphbGlnbiIsIlREOjpheGlzIiwi
+VEQ6OmJnY29sb3IiLCJURDo6Y2hhciIsIlREOjpjaGFyb2ZmIiwiVEQ6OmNvbHNwYW4iLCJURDo6aGVh
+ZGVycyIsIlREOjpoZWlnaHQiLCJURDo6bm93cmFwIiwiVEQ6OnJvd3NwYW4iLCJURDo6c2NvcGUiLCJU
+RDo6dmFsaWduIiwiVEQ6OndpZHRoIiwiVEVYVEFSRUE6OmFjY2Vzc2tleSIsIlRFWFRBUkVBOjphdXRv
+Y29tcGxldGUiLCJURVhUQVJFQTo6Y29scyIsIlRFWFRBUkVBOjpkaXNhYmxlZCIsIlRFWFRBUkVBOjpp
+bnB1dG1vZGUiLCJURVhUQVJFQTo6bmFtZSIsIlRFWFRBUkVBOjpwbGFjZWhvbGRlciIsIlRFWFRBUkVB
+OjpyZWFkb25seSIsIlRFWFRBUkVBOjpyZXF1aXJlZCIsIlRFWFRBUkVBOjpyb3dzIiwiVEVYVEFSRUE6
+OnRhYmluZGV4IiwiVEVYVEFSRUE6OndyYXAiLCJURk9PVDo6YWxpZ24iLCJURk9PVDo6Y2hhciIsIlRG
+T09UOjpjaGFyb2ZmIiwiVEZPT1Q6OnZhbGlnbiIsIlRIOjphYmJyIiwiVEg6OmFsaWduIiwiVEg6OmF4
+aXMiLCJUSDo6Ymdjb2xvciIsIlRIOjpjaGFyIiwiVEg6OmNoYXJvZmYiLCJUSDo6Y29sc3BhbiIsIlRI
+OjpoZWFkZXJzIiwiVEg6OmhlaWdodCIsIlRIOjpub3dyYXAiLCJUSDo6cm93c3BhbiIsIlRIOjpzY29w
+ZSIsIlRIOjp2YWxpZ24iLCJUSDo6d2lkdGgiLCJUSEVBRDo6YWxpZ24iLCJUSEVBRDo6Y2hhciIsIlRI
+RUFEOjpjaGFyb2ZmIiwiVEhFQUQ6OnZhbGlnbiIsIlRSOjphbGlnbiIsIlRSOjpiZ2NvbG9yIiwiVFI6
+OmNoYXIiLCJUUjo6Y2hhcm9mZiIsIlRSOjp2YWxpZ24iLCJUUkFDSzo6ZGVmYXVsdCIsIlRSQUNLOjpr
+aW5kIiwiVFJBQ0s6OmxhYmVsIiwiVFJBQ0s6OnNyY2xhbmciLCJVTDo6Y29tcGFjdCIsIlVMOjp0eXBl
+IiwiVklERU86OmNvbnRyb2xzIiwiVklERU86OmhlaWdodCIsIlZJREVPOjpsb29wIiwiVklERU86Om1l
+ZGlhZ3JvdXAiLCJWSURFTzo6bXV0ZWQiLCJWSURFTzo6cHJlbG9hZCIsIlZJREVPOjp3aWR0aCJdKSx1
+LnMpCkMuVkM9SC5WTSh0KFswLDAsNjU0OTAsNDUwNTUsNjU1MzUsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1
+LnQpCkMubUs9SC5WTSh0KFswLDAsMjY2MjQsMTAyMyw2NTUzNCwyMDQ3LDY1NTM0LDIwNDddKSx1LnQp
+CkMuU3E9SC5WTSh0KFsiSEVBRCIsIkFSRUEiLCJCQVNFIiwiQkFTRUZPTlQiLCJCUiIsIkNPTCIsIkNP
+TEdST1VQIiwiRU1CRUQiLCJGUkFNRSIsIkZSQU1FU0VUIiwiSFIiLCJJTUFHRSIsIklNRyIsIklOUFVU
+IiwiSVNJTkRFWCIsIkxJTksiLCJNRVRBIiwiUEFSQU0iLCJTT1VSQ0UiLCJTVFlMRSIsIlRJVExFIiwi
+V0JSIl0pLHUucykKQy54RD1ILlZNKHQoW10pLHUudSkKQy5kbj1ILlZNKHQoW10pLHUucykKQy5oVT1I
+LlZNKHQoW10pLHUubSkKQy50bz1ILlZNKHQoWzAsMCwzMjcyMiwxMjI4Nyw2NTUzNCwzNDgxNSw2NTUz
+NCwxODQzMV0pLHUudCkKQy5GMz1ILlZNKHQoWzAsMCwyNDU3NiwxMDIzLDY1NTM0LDM0ODE1LDY1NTM0
+LDE4NDMxXSksdS50KQpDLmVhPUguVk0odChbMCwwLDMyNzU0LDExMjYzLDY1NTM0LDM0ODE1LDY1NTM0
+LDE4NDMxXSksdS50KQpDLlpKPUguVk0odChbMCwwLDMyNzIyLDEyMjg3LDY1NTM1LDM0ODE1LDY1NTM0
+LDE4NDMxXSksdS50KQpDLldkPUguVk0odChbMCwwLDY1NDkwLDEyMjg3LDY1NTM1LDM0ODE1LDY1NTM0
+LDE4NDMxXSksdS50KQpDLlF4PUguVk0odChbImJpbmQiLCJpZiIsInJlZiIsInJlcGVhdCIsInN5bnRh
+eCJdKSx1LnMpCkMuQkk9SC5WTSh0KFsiQTo6aHJlZiIsIkFSRUE6OmhyZWYiLCJCTE9DS1FVT1RFOjpj
+aXRlIiwiQk9EWTo6YmFja2dyb3VuZCIsIkNPTU1BTkQ6Omljb24iLCJERUw6OmNpdGUiLCJGT1JNOjph
+Y3Rpb24iLCJJTUc6OnNyYyIsIklOUFVUOjpzcmMiLCJJTlM6OmNpdGUiLCJROjpjaXRlIiwiVklERU86
+OnBvc3RlciJdKSx1LnMpCkMuV089bmV3IEguTFAoMCx7fSxDLmRuLEguTjAoIkxQPHFVLHFVPiIpKQpD
+LmlIPUguVk0odChbXSksSC5OMCgiamQ8R0Q+IikpCkMuQ009bmV3IEguTFAoMCx7fSxDLmlILEguTjAo
+IkxQPEdELEA+IikpCkMuWTI9bmV3IEwueTgoIk5hdmlnYXRpb25UcmVlTm9kZVR5cGUuZGlyZWN0b3J5
+IikKQy5yZj1uZXcgTC55OCgiTmF2aWdhdGlvblRyZWVOb2RlVHlwZS5maWxlIikKQy5UZT1uZXcgSC53
+digiY2FsbCIpfSkoKTsoZnVuY3Rpb24gc3RhdGljRmllbGRzKCl7JC55aj0wCiQubUo9bnVsbAokLlA0
+PW51bGwKJC5ORj1udWxsCiQuVFg9bnVsbAokLng3PW51bGwKJC5udz1udWxsCiQudnY9bnVsbAokLkJ2
+PW51bGwKJC5TNj1udWxsCiQuazg9bnVsbAokLm1nPW51bGwKJC5VRD0hMQokLlgzPUMuTlUKJC54Zz1b
+XQokLnhvPW51bGwKJC5CTz1udWxsCiQubHQ9bnVsbAokLkVVPW51bGwKJC5vcj1QLkZsKHUuTix1Llop
+CiQuSTY9bnVsbAokLkZmPW51bGx9KSgpOyhmdW5jdGlvbiBsYXp5SW5pdGlhbGl6ZXJzKCl7dmFyIHQ9
+aHVua0hlbHBlcnMubGF6eQp0KCQsImZhIiwidyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5ZZygiXyRkYXJ0
+X2RhcnRDbG9zdXJlIil9KQp0KCQsIlkyIiwiVU4iLGZ1bmN0aW9uKCl7cmV0dXJuIEguWWcoIl8kZGFy
+dF9qcyIpfSkKdCgkLCJVMiIsIlNuIixmdW5jdGlvbigpe3JldHVybiBILmNNKEguUzcoewp0b1N0cmlu
+ZzpmdW5jdGlvbigpe3JldHVybiIkcmVjZWl2ZXIkIn19KSl9KQp0KCQsInhxIiwibHEiLGZ1bmN0aW9u
+KCl7cmV0dXJuIEguY00oSC5TNyh7JG1ldGhvZCQ6bnVsbCwKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1
+cm4iJHJlY2VpdmVyJCJ9fSkpfSkKdCgkLCJSMSIsIk45IixmdW5jdGlvbigpe3JldHVybiBILmNNKEgu
+UzcobnVsbCkpfSkKdCgkLCJmTiIsImlJIixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7
+dmFyICRhcmd1bWVudHNFeHByJD0nJGFyZ3VtZW50cyQnCnRyeXtudWxsLiRtZXRob2QkKCRhcmd1bWVu
+dHNFeHByJCl9Y2F0Y2gocyl7cmV0dXJuIHMubWVzc2FnZX19KCkpfSkKdCgkLCJxaSIsIktmIixmdW5j
+dGlvbigpe3JldHVybiBILmNNKEguUzcodm9pZCAwKSl9KQp0KCQsInJaIiwiWmgiLGZ1bmN0aW9uKCl7
+cmV0dXJuIEguY00oZnVuY3Rpb24oKXt2YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJndW1lbnRzJCcKdHJ5
+eyh2b2lkIDApLiRtZXRob2QkKCRhcmd1bWVudHNFeHByJCl9Y2F0Y2gocyl7cmV0dXJuIHMubWVzc2Fn
+ZX19KCkpfSkKdCgkLCJrcSIsImNQIixmdW5jdGlvbigpe3JldHVybiBILmNNKEguTWoobnVsbCkpfSkK
+dCgkLCJ0dCIsImMzIixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7dHJ5e251bGwuJG1l
+dGhvZCR9Y2F0Y2gocyl7cmV0dXJuIHMubWVzc2FnZX19KCkpfSkKdCgkLCJkdCIsIkhLIixmdW5jdGlv
+bigpe3JldHVybiBILmNNKEguTWoodm9pZCAwKSl9KQp0KCQsIkE3IiwicjEiLGZ1bmN0aW9uKCl7cmV0
+dXJuIEguY00oZnVuY3Rpb24oKXt0cnl7KHZvaWQgMCkuJG1ldGhvZCR9Y2F0Y2gocyl7cmV0dXJuIHMu
+bWVzc2FnZX19KCkpfSkKdCgkLCJXYyIsInV0IixmdW5jdGlvbigpe3JldHVybiBQLk9qKCl9KQp0KCQs
+ImtoIiwicmYiLGZ1bmN0aW9uKCl7cmV0dXJuIFAuV0koKX0pCnQoJCwiYnQiLCJWNyIsZnVuY3Rpb24o
+KXtyZXR1cm4gSC5EUShILlhGKEguVk0oWy0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
 LC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
-LC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0xLC0yLC0yLC0yLC0yLC0yLDYyLC0yLDYyLC0yLDYz
-LDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYwLDYxLC0yLC0yLC0yLC0xLC0yLC0yLC0yLDAsMSwyLDMs
-NCw1LDYsNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMsMjQsMjUs
-LTIsLTIsLTIsLTIsNjMsLTIsMjYsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzks
-NDAsNDEsNDIsNDMsNDQsNDUsNDYsNDcsNDgsNDksNTAsNTEsLTIsLTIsLTIsLTIsLTJdLHUudCkpKX0p
-CnQoJCwiTTUiLCJ3USIsZnVuY3Rpb24oKXtyZXR1cm4gdHlwZW9mIHByb2Nlc3MhPSJ1bmRlZmluZWQi
-JiZPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwocHJvY2Vzcyk9PSJbb2JqZWN0IHByb2Nlc3Nd
-IiYmcHJvY2Vzcy5wbGF0Zm9ybT09IndpbjMyIn0pCnQoJCwibWYiLCJ6NCIsZnVuY3Rpb24oKXtyZXR1
-cm4gUC5udSgiXltcXC1cXC4wLTlBLVpfYS16fl0qJCIpfSkKdCgkLCJKRyIsInZaIixmdW5jdGlvbigp
-e3JldHVybiBQLnV4KCl9KQp0KCQsIlNDIiwiQU4iLGZ1bmN0aW9uKCl7cmV0dXJuIFAudE0oWyJBIiwi
-QUJCUiIsIkFDUk9OWU0iLCJBRERSRVNTIiwiQVJFQSIsIkFSVElDTEUiLCJBU0lERSIsIkFVRElPIiwi
-QiIsIkJESSIsIkJETyIsIkJJRyIsIkJMT0NLUVVPVEUiLCJCUiIsIkJVVFRPTiIsIkNBTlZBUyIsIkNB
-UFRJT04iLCJDRU5URVIiLCJDSVRFIiwiQ09ERSIsIkNPTCIsIkNPTEdST1VQIiwiQ09NTUFORCIsIkRB
-VEEiLCJEQVRBTElTVCIsIkREIiwiREVMIiwiREVUQUlMUyIsIkRGTiIsIkRJUiIsIkRJViIsIkRMIiwi
-RFQiLCJFTSIsIkZJRUxEU0VUIiwiRklHQ0FQVElPTiIsIkZJR1VSRSIsIkZPTlQiLCJGT09URVIiLCJG
-T1JNIiwiSDEiLCJIMiIsIkgzIiwiSDQiLCJINSIsIkg2IiwiSEVBREVSIiwiSEdST1VQIiwiSFIiLCJJ
-IiwiSUZSQU1FIiwiSU1HIiwiSU5QVVQiLCJJTlMiLCJLQkQiLCJMQUJFTCIsIkxFR0VORCIsIkxJIiwi
-TUFQIiwiTUFSSyIsIk1FTlUiLCJNRVRFUiIsIk5BViIsIk5PQlIiLCJPTCIsIk9QVEdST1VQIiwiT1BU
-SU9OIiwiT1VUUFVUIiwiUCIsIlBSRSIsIlBST0dSRVNTIiwiUSIsIlMiLCJTQU1QIiwiU0VDVElPTiIs
-IlNFTEVDVCIsIlNNQUxMIiwiU09VUkNFIiwiU1BBTiIsIlNUUklLRSIsIlNUUk9ORyIsIlNVQiIsIlNV
-TU1BUlkiLCJTVVAiLCJUQUJMRSIsIlRCT0RZIiwiVEQiLCJURVhUQVJFQSIsIlRGT09UIiwiVEgiLCJU
-SEVBRCIsIlRJTUUiLCJUUiIsIlRSQUNLIiwiVFQiLCJVIiwiVUwiLCJWQVIiLCJWSURFTyIsIldCUiJd
-LHUuTil9KQp0KCQsIlg0IiwiaEciLGZ1bmN0aW9uKCl7cmV0dXJuIFAubnUoIl5cXFMrJCIpfSkKdCgk
-LCJ3TyIsIm93IixmdW5jdGlvbigpe3JldHVybiB1LnUuYihQLk5EKHNlbGYpKX0pCnQoJCwia3QiLCJS
-OCIsZnVuY3Rpb24oKXtyZXR1cm4gSC5ZZygiXyRkYXJ0X2RhcnRPYmplY3QiKX0pCnQoJCwiSmUiLCJr
-SSIsZnVuY3Rpb24oKXtyZXR1cm4gZnVuY3Rpb24gRGFydE9iamVjdChhKXt0aGlzLm89YX19KQp0KCQs
-InF0IiwiekIiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBULkdWKCl9KQp0KCQsImZlIiwiS0ciLGZ1bmN0
-aW9uKCl7cmV0dXJuIG5ldyBMLlhBKCl9KQp0KCQsIm1NIiwiblUiLGZ1bmN0aW9uKCl7cmV0dXJuIG5l
-dyBNLmxJKCQuSGsoKSl9KQp0KCQsInlyIiwiYkQiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBFLk9GKFAu
-bnUoIi8iKSxQLm51KCJbXi9dJCIpLFAubnUoIl4vIikpfSkKdCgkLCJNayIsIktrIixmdW5jdGlvbigp
-e3JldHVybiBuZXcgTC5JVihQLm51KCJbL1xcXFxdIiksUC5udSgiW14vXFxcXF0kIiksUC5udSgiXihc
-XFxcXFxcXFteXFxcXF0rXFxcXFteXFxcXC9dK3xbYS16QS1aXTpbL1xcXFxdKSIpLFAubnUoIl5bL1xc
-XFxdKD8hWy9cXFxcXSkiKSl9KQp0KCQsImFrIiwiRWIiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBGLnJ1
-KFAubnUoIi8iKSxQLm51KCIoXlthLXpBLVpdWy0rLmEtekEtWlxcZF0qOi8vfFteL10pJCIpLFAubnUo
-IlthLXpBLVpdWy0rLmEtekEtWlxcZF0qOi8vW14vXSoiKSxQLm51KCJeLyIpKX0pCnQoJCwibHMiLCJI
-ayIsZnVuY3Rpb24oKXtyZXR1cm4gTy5SaCgpfSl9KSgpOyhmdW5jdGlvbiBuYXRpdmVTdXBwb3J0KCl7
-IWZ1bmN0aW9uKCl7dmFyIHQ9ZnVuY3Rpb24oYSl7dmFyIG49e30KblthXT0xCnJldHVybiBPYmplY3Qu
-a2V5cyhodW5rSGVscGVycy5jb252ZXJ0VG9GYXN0T2JqZWN0KG4pKVswXX0Kdi5nZXRJc29sYXRlVGFn
-PWZ1bmN0aW9uKGEpe3JldHVybiB0KCJfX19kYXJ0XyIrYSt2Lmlzb2xhdGVUYWcpfQp2YXIgcz0iX19f
-ZGFydF9pc29sYXRlX3RhZ3NfIgp2YXIgcj1PYmplY3Rbc118fChPYmplY3Rbc109T2JqZWN0LmNyZWF0
-ZShudWxsKSkKdmFyIHE9Il9aeFl4WCIKZm9yKHZhciBwPTA7O3ArKyl7dmFyIG89dChxKyJfIitwKyJf
-IikKaWYoIShvIGluIHIpKXtyW29dPTEKdi5pc29sYXRlVGFnPW8KYnJlYWt9fXYuZGlzcGF0Y2hQcm9w
-ZXJ0eU5hbWU9di5nZXRJc29sYXRlVGFnKCJkaXNwYXRjaF9yZWNvcmQiKX0oKQpodW5rSGVscGVycy5z
-ZXRPclVwZGF0ZUludGVyY2VwdG9yc0J5VGFnKHtET01FcnJvcjpKLnZCLERPTUltcGxlbWVudGF0aW9u
-OkoudkIsTWVkaWFFcnJvcjpKLnZCLE5hdmlnYXRvcjpKLnZCLE5hdmlnYXRvckNvbmN1cnJlbnRIYXJk
-d2FyZTpKLnZCLE5hdmlnYXRvclVzZXJNZWRpYUVycm9yOkoudkIsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6
-Si52QixQb3NpdGlvbkVycm9yOkoudkIsUmFuZ2U6Si52QixTUUxFcnJvcjpKLnZCLERhdGFWaWV3Okgu
-RVQsQXJyYXlCdWZmZXJWaWV3OkguRVQsRmxvYXQzMkFycmF5OkguRGcsRmxvYXQ2NEFycmF5OkguRGcs
-SW50MTZBcnJheTpILnhqLEludDMyQXJyYXk6SC5kRSxJbnQ4QXJyYXk6SC5aQSxVaW50MTZBcnJheTpI
-LndmLFVpbnQzMkFycmF5OkguUHEsVWludDhDbGFtcGVkQXJyYXk6SC5lRSxDYW52YXNQaXhlbEFycmF5
-OkguZUUsVWludDhBcnJheTpILlY2LEhUTUxBdWRpb0VsZW1lbnQ6Vy5xRSxIVE1MQlJFbGVtZW50Olcu
-cUUsSFRNTEJ1dHRvbkVsZW1lbnQ6Vy5xRSxIVE1MQ2FudmFzRWxlbWVudDpXLnFFLEhUTUxDb250ZW50
-RWxlbWVudDpXLnFFLEhUTUxETGlzdEVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUVsZW1lbnQ6Vy5xRSxIVE1M
-RGF0YUxpc3RFbGVtZW50OlcucUUsSFRNTERldGFpbHNFbGVtZW50OlcucUUsSFRNTERpYWxvZ0VsZW1l
-bnQ6Vy5xRSxIVE1MRGl2RWxlbWVudDpXLnFFLEhUTUxFbWJlZEVsZW1lbnQ6Vy5xRSxIVE1MRmllbGRT
-ZXRFbGVtZW50OlcucUUsSFRNTEhSRWxlbWVudDpXLnFFLEhUTUxIZWFkRWxlbWVudDpXLnFFLEhUTUxI
-ZWFkaW5nRWxlbWVudDpXLnFFLEhUTUxIdG1sRWxlbWVudDpXLnFFLEhUTUxJRnJhbWVFbGVtZW50Olcu
-cUUsSFRNTEltYWdlRWxlbWVudDpXLnFFLEhUTUxJbnB1dEVsZW1lbnQ6Vy5xRSxIVE1MTElFbGVtZW50
-OlcucUUsSFRNTExhYmVsRWxlbWVudDpXLnFFLEhUTUxMZWdlbmRFbGVtZW50OlcucUUsSFRNTExpbmtF
-bGVtZW50OlcucUUsSFRNTE1hcEVsZW1lbnQ6Vy5xRSxIVE1MTWVkaWFFbGVtZW50OlcucUUsSFRNTE1l
-bnVFbGVtZW50OlcucUUsSFRNTE1ldGFFbGVtZW50OlcucUUsSFRNTE1ldGVyRWxlbWVudDpXLnFFLEhU
-TUxNb2RFbGVtZW50OlcucUUsSFRNTE9MaXN0RWxlbWVudDpXLnFFLEhUTUxPYmplY3RFbGVtZW50Olcu
-cUUsSFRNTE9wdEdyb3VwRWxlbWVudDpXLnFFLEhUTUxPcHRpb25FbGVtZW50OlcucUUsSFRNTE91dHB1
-dEVsZW1lbnQ6Vy5xRSxIVE1MUGFyYW1FbGVtZW50OlcucUUsSFRNTFBpY3R1cmVFbGVtZW50OlcucUUs
-SFRNTFByZUVsZW1lbnQ6Vy5xRSxIVE1MUHJvZ3Jlc3NFbGVtZW50OlcucUUsSFRNTFF1b3RlRWxlbWVu
-dDpXLnFFLEhUTUxTY3JpcHRFbGVtZW50OlcucUUsSFRNTFNoYWRvd0VsZW1lbnQ6Vy5xRSxIVE1MU2xv
-dEVsZW1lbnQ6Vy5xRSxIVE1MU291cmNlRWxlbWVudDpXLnFFLEhUTUxTcGFuRWxlbWVudDpXLnFFLEhU
-TUxTdHlsZUVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVDYXB0aW9uRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNl
-bGxFbGVtZW50OlcucUUsSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlSGVhZGVy
-Q2VsbEVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVDb2xFbGVtZW50OlcucUUsSFRNTFRleHRBcmVhRWxlbWVu
-dDpXLnFFLEhUTUxUaW1lRWxlbWVudDpXLnFFLEhUTUxUaXRsZUVsZW1lbnQ6Vy5xRSxIVE1MVHJhY2tF
-bGVtZW50OlcucUUsSFRNTFVMaXN0RWxlbWVudDpXLnFFLEhUTUxVbmtub3duRWxlbWVudDpXLnFFLEhU
-TUxWaWRlb0VsZW1lbnQ6Vy5xRSxIVE1MRGlyZWN0b3J5RWxlbWVudDpXLnFFLEhUTUxGb250RWxlbWVu
-dDpXLnFFLEhUTUxGcmFtZUVsZW1lbnQ6Vy5xRSxIVE1MRnJhbWVTZXRFbGVtZW50OlcucUUsSFRNTE1h
-cnF1ZWVFbGVtZW50OlcucUUsSFRNTEVsZW1lbnQ6Vy5xRSxIVE1MQW5jaG9yRWxlbWVudDpXLkdoLEhU
-TUxBcmVhRWxlbWVudDpXLmZZLEhUTUxCYXNlRWxlbWVudDpXLm5CLEJsb2I6Vy5BeixIVE1MQm9keUVs
-ZW1lbnQ6Vy5RUCxDREFUQVNlY3Rpb246Vy5ueCxDaGFyYWN0ZXJEYXRhOlcubngsQ29tbWVudDpXLm54
-LFByb2Nlc3NpbmdJbnN0cnVjdGlvbjpXLm54LFRleHQ6Vy5ueCxDU1NTdHlsZURlY2xhcmF0aW9uOlcu
-b0osTVNTdHlsZUNTU1Byb3BlcnRpZXM6Vy5vSixDU1MyUHJvcGVydGllczpXLm9KLFhNTERvY3VtZW50
-OlcuUUYsRG9jdW1lbnQ6Vy5RRixET01FeGNlcHRpb246Vy5OaCxET01SZWN0UmVhZE9ubHk6Vy5JQixE
-T01Ub2tlbkxpc3Q6Vy5uNyxFbGVtZW50OlcuY3YsQWJvcnRQYXltZW50RXZlbnQ6Vy5lYSxBbmltYXRp
-b25FdmVudDpXLmVhLEFuaW1hdGlvblBsYXliYWNrRXZlbnQ6Vy5lYSxBcHBsaWNhdGlvbkNhY2hlRXJy
-b3JFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaENsaWNrRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hF
-dmVudDpXLmVhLEJhY2tncm91bmRGZXRjaEZhaWxFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaGVkRXZl
-bnQ6Vy5lYSxCZWZvcmVJbnN0YWxsUHJvbXB0RXZlbnQ6Vy5lYSxCZWZvcmVVbmxvYWRFdmVudDpXLmVh
-LEJsb2JFdmVudDpXLmVhLENhbk1ha2VQYXltZW50RXZlbnQ6Vy5lYSxDbGlwYm9hcmRFdmVudDpXLmVh
-LENsb3NlRXZlbnQ6Vy5lYSxDdXN0b21FdmVudDpXLmVhLERldmljZU1vdGlvbkV2ZW50OlcuZWEsRGV2
-aWNlT3JpZW50YXRpb25FdmVudDpXLmVhLEVycm9yRXZlbnQ6Vy5lYSxFeHRlbmRhYmxlRXZlbnQ6Vy5l
-YSxFeHRlbmRhYmxlTWVzc2FnZUV2ZW50OlcuZWEsRmV0Y2hFdmVudDpXLmVhLEZvbnRGYWNlU2V0TG9h
-ZEV2ZW50OlcuZWEsRm9yZWlnbkZldGNoRXZlbnQ6Vy5lYSxHYW1lcGFkRXZlbnQ6Vy5lYSxIYXNoQ2hh
-bmdlRXZlbnQ6Vy5lYSxJbnN0YWxsRXZlbnQ6Vy5lYSxNZWRpYUVuY3J5cHRlZEV2ZW50OlcuZWEsTWVk
-aWFLZXlNZXNzYWdlRXZlbnQ6Vy5lYSxNZWRpYVF1ZXJ5TGlzdEV2ZW50OlcuZWEsTWVkaWFTdHJlYW1F
-dmVudDpXLmVhLE1lZGlhU3RyZWFtVHJhY2tFdmVudDpXLmVhLE1lc3NhZ2VFdmVudDpXLmVhLE1JRElD
-b25uZWN0aW9uRXZlbnQ6Vy5lYSxNSURJTWVzc2FnZUV2ZW50OlcuZWEsTXV0YXRpb25FdmVudDpXLmVh
-LE5vdGlmaWNhdGlvbkV2ZW50OlcuZWEsUGFnZVRyYW5zaXRpb25FdmVudDpXLmVhLFBheW1lbnRSZXF1
-ZXN0RXZlbnQ6Vy5lYSxQYXltZW50UmVxdWVzdFVwZGF0ZUV2ZW50OlcuZWEsUG9wU3RhdGVFdmVudDpX
-LmVhLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25BdmFpbGFibGVFdmVudDpXLmVhLFByZXNlbnRhdGlvbkNv
-bm5lY3Rpb25DbG9zZUV2ZW50OlcuZWEsUHJvbWlzZVJlamVjdGlvbkV2ZW50OlcuZWEsUHVzaEV2ZW50
-OlcuZWEsUlRDRGF0YUNoYW5uZWxFdmVudDpXLmVhLFJUQ0RUTUZUb25lQ2hhbmdlRXZlbnQ6Vy5lYSxS
-VENQZWVyQ29ubmVjdGlvbkljZUV2ZW50OlcuZWEsUlRDVHJhY2tFdmVudDpXLmVhLFNlY3VyaXR5UG9s
-aWN5VmlvbGF0aW9uRXZlbnQ6Vy5lYSxTZW5zb3JFcnJvckV2ZW50OlcuZWEsU3BlZWNoUmVjb2duaXRp
-b25FcnJvcjpXLmVhLFNwZWVjaFJlY29nbml0aW9uRXZlbnQ6Vy5lYSxTcGVlY2hTeW50aGVzaXNFdmVu
-dDpXLmVhLFN0b3JhZ2VFdmVudDpXLmVhLFN5bmNFdmVudDpXLmVhLFRyYWNrRXZlbnQ6Vy5lYSxUcmFu
-c2l0aW9uRXZlbnQ6Vy5lYSxXZWJLaXRUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxWUkRldmljZUV2ZW50Olcu
-ZWEsVlJEaXNwbGF5RXZlbnQ6Vy5lYSxWUlNlc3Npb25FdmVudDpXLmVhLE1vam9JbnRlcmZhY2VSZXF1
-ZXN0RXZlbnQ6Vy5lYSxVU0JDb25uZWN0aW9uRXZlbnQ6Vy5lYSxJREJWZXJzaW9uQ2hhbmdlRXZlbnQ6
-Vy5lYSxBdWRpb1Byb2Nlc3NpbmdFdmVudDpXLmVhLE9mZmxpbmVBdWRpb0NvbXBsZXRpb25FdmVudDpX
-LmVhLFdlYkdMQ29udGV4dEV2ZW50OlcuZWEsRXZlbnQ6Vy5lYSxJbnB1dEV2ZW50OlcuZWEsRXZlbnRU
-YXJnZXQ6Vy5EMCxGaWxlOlcuVDUsSFRNTEZvcm1FbGVtZW50OlcuaDQsSGlzdG9yeTpXLmJyLEhUTUxE
-b2N1bWVudDpXLlZiLFhNTEh0dHBSZXF1ZXN0OlcuTzcsWE1MSHR0cFJlcXVlc3RFdmVudFRhcmdldDpX
-LndhLEltYWdlRGF0YTpXLlNnLExvY2F0aW9uOlcudTgsTW91c2VFdmVudDpXLkFqLERyYWdFdmVudDpX
-LkFqLFBvaW50ZXJFdmVudDpXLkFqLFdoZWVsRXZlbnQ6Vy5BaixEb2N1bWVudEZyYWdtZW50OlcudUgs
-U2hhZG93Um9vdDpXLnVILERvY3VtZW50VHlwZTpXLnVILE5vZGU6Vy51SCxOb2RlTGlzdDpXLkJILFJh
-ZGlvTm9kZUxpc3Q6Vy5CSCxIVE1MUGFyYWdyYXBoRWxlbWVudDpXLlNOLFByb2dyZXNzRXZlbnQ6Vy5l
-dyxSZXNvdXJjZVByb2dyZXNzRXZlbnQ6Vy5ldyxIVE1MU2VsZWN0RWxlbWVudDpXLmxwLEhUTUxUYWJs
-ZUVsZW1lbnQ6Vy5UYixIVE1MVGFibGVSb3dFbGVtZW50OlcuSXYsSFRNTFRhYmxlU2VjdGlvbkVsZW1l
-bnQ6Vy5CVCxIVE1MVGVtcGxhdGVFbGVtZW50OlcueVksQ29tcG9zaXRpb25FdmVudDpXLnc2LEZvY3Vz
-RXZlbnQ6Vy53NixLZXlib2FyZEV2ZW50OlcudzYsVGV4dEV2ZW50OlcudzYsVG91Y2hFdmVudDpXLnc2
-LFVJRXZlbnQ6Vy53NixXaW5kb3c6Vy5LNSxET01XaW5kb3c6Vy5LNSxEZWRpY2F0ZWRXb3JrZXJHbG9i
-YWxTY29wZTpXLkNtLFNlcnZpY2VXb3JrZXJHbG9iYWxTY29wZTpXLkNtLFNoYXJlZFdvcmtlckdsb2Jh
-bFNjb3BlOlcuQ20sV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxBdHRyOlcuQ1EsQ2xpZW50UmVjdDpXLnc0
-LERPTVJlY3Q6Vy53NCxOYW1lZE5vZGVNYXA6Vy5yaCxNb3pOYW1lZEF0dHJNYXA6Vy5yaCxJREJLZXlS
-YW5nZTpQLmhGLFNWR1NjcmlwdEVsZW1lbnQ6UC5uZCxTVkdBRWxlbWVudDpQLmQ1LFNWR0FuaW1hdGVF
-bGVtZW50OlAuZDUsU1ZHQW5pbWF0ZU1vdGlvbkVsZW1lbnQ6UC5kNSxTVkdBbmltYXRlVHJhbnNmb3Jt
-RWxlbWVudDpQLmQ1LFNWR0FuaW1hdGlvbkVsZW1lbnQ6UC5kNSxTVkdDaXJjbGVFbGVtZW50OlAuZDUs
-U1ZHQ2xpcFBhdGhFbGVtZW50OlAuZDUsU1ZHRGVmc0VsZW1lbnQ6UC5kNSxTVkdEZXNjRWxlbWVudDpQ
-LmQ1LFNWR0Rpc2NhcmRFbGVtZW50OlAuZDUsU1ZHRWxsaXBzZUVsZW1lbnQ6UC5kNSxTVkdGRUJsZW5k
-RWxlbWVudDpQLmQ1LFNWR0ZFQ29sb3JNYXRyaXhFbGVtZW50OlAuZDUsU1ZHRkVDb21wb25lbnRUcmFu
-c2ZlckVsZW1lbnQ6UC5kNSxTVkdGRUNvbXBvc2l0ZUVsZW1lbnQ6UC5kNSxTVkdGRUNvbnZvbHZlTWF0
-cml4RWxlbWVudDpQLmQ1LFNWR0ZFRGlmZnVzZUxpZ2h0aW5nRWxlbWVudDpQLmQ1LFNWR0ZFRGlzcGxh
-Y2VtZW50TWFwRWxlbWVudDpQLmQ1LFNWR0ZFRGlzdGFudExpZ2h0RWxlbWVudDpQLmQ1LFNWR0ZFRmxv
-b2RFbGVtZW50OlAuZDUsU1ZHRkVGdW5jQUVsZW1lbnQ6UC5kNSxTVkdGRUZ1bmNCRWxlbWVudDpQLmQ1
-LFNWR0ZFRnVuY0dFbGVtZW50OlAuZDUsU1ZHRkVGdW5jUkVsZW1lbnQ6UC5kNSxTVkdGRUdhdXNzaWFu
-Qmx1ckVsZW1lbnQ6UC5kNSxTVkdGRUltYWdlRWxlbWVudDpQLmQ1LFNWR0ZFTWVyZ2VFbGVtZW50OlAu
-ZDUsU1ZHRkVNZXJnZU5vZGVFbGVtZW50OlAuZDUsU1ZHRkVNb3JwaG9sb2d5RWxlbWVudDpQLmQ1LFNW
-R0ZFT2Zmc2V0RWxlbWVudDpQLmQ1LFNWR0ZFUG9pbnRMaWdodEVsZW1lbnQ6UC5kNSxTVkdGRVNwZWN1
-bGFyTGlnaHRpbmdFbGVtZW50OlAuZDUsU1ZHRkVTcG90TGlnaHRFbGVtZW50OlAuZDUsU1ZHRkVUaWxl
-RWxlbWVudDpQLmQ1LFNWR0ZFVHVyYnVsZW5jZUVsZW1lbnQ6UC5kNSxTVkdGaWx0ZXJFbGVtZW50OlAu
-ZDUsU1ZHRm9yZWlnbk9iamVjdEVsZW1lbnQ6UC5kNSxTVkdHRWxlbWVudDpQLmQ1LFNWR0dlb21ldHJ5
-RWxlbWVudDpQLmQ1LFNWR0dyYXBoaWNzRWxlbWVudDpQLmQ1LFNWR0ltYWdlRWxlbWVudDpQLmQ1LFNW
-R0xpbmVFbGVtZW50OlAuZDUsU1ZHTGluZWFyR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHTWFya2VyRWxl
-bWVudDpQLmQ1LFNWR01hc2tFbGVtZW50OlAuZDUsU1ZHTWV0YWRhdGFFbGVtZW50OlAuZDUsU1ZHUGF0
-aEVsZW1lbnQ6UC5kNSxTVkdQYXR0ZXJuRWxlbWVudDpQLmQ1LFNWR1BvbHlnb25FbGVtZW50OlAuZDUs
-U1ZHUG9seWxpbmVFbGVtZW50OlAuZDUsU1ZHUmFkaWFsR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHUmVj
-dEVsZW1lbnQ6UC5kNSxTVkdTZXRFbGVtZW50OlAuZDUsU1ZHU3RvcEVsZW1lbnQ6UC5kNSxTVkdTdHls
-ZUVsZW1lbnQ6UC5kNSxTVkdTVkdFbGVtZW50OlAuZDUsU1ZHU3dpdGNoRWxlbWVudDpQLmQ1LFNWR1N5
-bWJvbEVsZW1lbnQ6UC5kNSxTVkdUU3BhbkVsZW1lbnQ6UC5kNSxTVkdUZXh0Q29udGVudEVsZW1lbnQ6
-UC5kNSxTVkdUZXh0RWxlbWVudDpQLmQ1LFNWR1RleHRQYXRoRWxlbWVudDpQLmQ1LFNWR1RleHRQb3Np
-dGlvbmluZ0VsZW1lbnQ6UC5kNSxTVkdUaXRsZUVsZW1lbnQ6UC5kNSxTVkdVc2VFbGVtZW50OlAuZDUs
-U1ZHVmlld0VsZW1lbnQ6UC5kNSxTVkdHcmFkaWVudEVsZW1lbnQ6UC5kNSxTVkdDb21wb25lbnRUcmFu
-c2ZlckZ1bmN0aW9uRWxlbWVudDpQLmQ1LFNWR0ZFRHJvcFNoYWRvd0VsZW1lbnQ6UC5kNSxTVkdNUGF0
-aEVsZW1lbnQ6UC5kNSxTVkdFbGVtZW50OlAuZDV9KQpodW5rSGVscGVycy5zZXRPclVwZGF0ZUxlYWZU
-YWdzKHtET01FcnJvcjp0cnVlLERPTUltcGxlbWVudGF0aW9uOnRydWUsTWVkaWFFcnJvcjp0cnVlLE5h
-dmlnYXRvcjp0cnVlLE5hdmlnYXRvckNvbmN1cnJlbnRIYXJkd2FyZTp0cnVlLE5hdmlnYXRvclVzZXJN
-ZWRpYUVycm9yOnRydWUsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6dHJ1ZSxQb3NpdGlvbkVycm9yOnRydWUs
-UmFuZ2U6dHJ1ZSxTUUxFcnJvcjp0cnVlLERhdGFWaWV3OnRydWUsQXJyYXlCdWZmZXJWaWV3OmZhbHNl
-LEZsb2F0MzJBcnJheTp0cnVlLEZsb2F0NjRBcnJheTp0cnVlLEludDE2QXJyYXk6dHJ1ZSxJbnQzMkFy
-cmF5OnRydWUsSW50OEFycmF5OnRydWUsVWludDE2QXJyYXk6dHJ1ZSxVaW50MzJBcnJheTp0cnVlLFVp
-bnQ4Q2xhbXBlZEFycmF5OnRydWUsQ2FudmFzUGl4ZWxBcnJheTp0cnVlLFVpbnQ4QXJyYXk6ZmFsc2Us
-SFRNTEF1ZGlvRWxlbWVudDp0cnVlLEhUTUxCUkVsZW1lbnQ6dHJ1ZSxIVE1MQnV0dG9uRWxlbWVudDp0
-cnVlLEhUTUxDYW52YXNFbGVtZW50OnRydWUsSFRNTENvbnRlbnRFbGVtZW50OnRydWUsSFRNTERMaXN0
-RWxlbWVudDp0cnVlLEhUTUxEYXRhRWxlbWVudDp0cnVlLEhUTUxEYXRhTGlzdEVsZW1lbnQ6dHJ1ZSxI
-VE1MRGV0YWlsc0VsZW1lbnQ6dHJ1ZSxIVE1MRGlhbG9nRWxlbWVudDp0cnVlLEhUTUxEaXZFbGVtZW50
-OnRydWUsSFRNTEVtYmVkRWxlbWVudDp0cnVlLEhUTUxGaWVsZFNldEVsZW1lbnQ6dHJ1ZSxIVE1MSFJF
-bGVtZW50OnRydWUsSFRNTEhlYWRFbGVtZW50OnRydWUsSFRNTEhlYWRpbmdFbGVtZW50OnRydWUsSFRN
-TEh0bWxFbGVtZW50OnRydWUsSFRNTElGcmFtZUVsZW1lbnQ6dHJ1ZSxIVE1MSW1hZ2VFbGVtZW50OnRy
-dWUsSFRNTElucHV0RWxlbWVudDp0cnVlLEhUTUxMSUVsZW1lbnQ6dHJ1ZSxIVE1MTGFiZWxFbGVtZW50
-OnRydWUsSFRNTExlZ2VuZEVsZW1lbnQ6dHJ1ZSxIVE1MTGlua0VsZW1lbnQ6dHJ1ZSxIVE1MTWFwRWxl
-bWVudDp0cnVlLEhUTUxNZWRpYUVsZW1lbnQ6dHJ1ZSxIVE1MTWVudUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0
-YUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0ZXJFbGVtZW50OnRydWUsSFRNTE1vZEVsZW1lbnQ6dHJ1ZSxIVE1M
-T0xpc3RFbGVtZW50OnRydWUsSFRNTE9iamVjdEVsZW1lbnQ6dHJ1ZSxIVE1MT3B0R3JvdXBFbGVtZW50
-OnRydWUsSFRNTE9wdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MT3V0cHV0RWxlbWVudDp0cnVlLEhUTUxQYXJh
-bUVsZW1lbnQ6dHJ1ZSxIVE1MUGljdHVyZUVsZW1lbnQ6dHJ1ZSxIVE1MUHJlRWxlbWVudDp0cnVlLEhU
-TUxQcm9ncmVzc0VsZW1lbnQ6dHJ1ZSxIVE1MUXVvdGVFbGVtZW50OnRydWUsSFRNTFNjcmlwdEVsZW1l
-bnQ6dHJ1ZSxIVE1MU2hhZG93RWxlbWVudDp0cnVlLEhUTUxTbG90RWxlbWVudDp0cnVlLEhUTUxTb3Vy
-Y2VFbGVtZW50OnRydWUsSFRNTFNwYW5FbGVtZW50OnRydWUsSFRNTFN0eWxlRWxlbWVudDp0cnVlLEhU
-TUxUYWJsZUNhcHRpb25FbGVtZW50OnRydWUsSFRNTFRhYmxlQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFi
-bGVEYXRhQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVIZWFkZXJDZWxsRWxlbWVudDp0cnVlLEhUTUxU
-YWJsZUNvbEVsZW1lbnQ6dHJ1ZSxIVE1MVGV4dEFyZWFFbGVtZW50OnRydWUsSFRNTFRpbWVFbGVtZW50
-OnRydWUsSFRNTFRpdGxlRWxlbWVudDp0cnVlLEhUTUxUcmFja0VsZW1lbnQ6dHJ1ZSxIVE1MVUxpc3RF
-bGVtZW50OnRydWUsSFRNTFVua25vd25FbGVtZW50OnRydWUsSFRNTFZpZGVvRWxlbWVudDp0cnVlLEhU
-TUxEaXJlY3RvcnlFbGVtZW50OnRydWUsSFRNTEZvbnRFbGVtZW50OnRydWUsSFRNTEZyYW1lRWxlbWVu
-dDp0cnVlLEhUTUxGcmFtZVNldEVsZW1lbnQ6dHJ1ZSxIVE1MTWFycXVlZUVsZW1lbnQ6dHJ1ZSxIVE1M
-RWxlbWVudDpmYWxzZSxIVE1MQW5jaG9yRWxlbWVudDp0cnVlLEhUTUxBcmVhRWxlbWVudDp0cnVlLEhU
-TUxCYXNlRWxlbWVudDp0cnVlLEJsb2I6ZmFsc2UsSFRNTEJvZHlFbGVtZW50OnRydWUsQ0RBVEFTZWN0
-aW9uOnRydWUsQ2hhcmFjdGVyRGF0YTp0cnVlLENvbW1lbnQ6dHJ1ZSxQcm9jZXNzaW5nSW5zdHJ1Y3Rp
-b246dHJ1ZSxUZXh0OnRydWUsQ1NTU3R5bGVEZWNsYXJhdGlvbjp0cnVlLE1TU3R5bGVDU1NQcm9wZXJ0
-aWVzOnRydWUsQ1NTMlByb3BlcnRpZXM6dHJ1ZSxYTUxEb2N1bWVudDp0cnVlLERvY3VtZW50OmZhbHNl
-LERPTUV4Y2VwdGlvbjp0cnVlLERPTVJlY3RSZWFkT25seTpmYWxzZSxET01Ub2tlbkxpc3Q6dHJ1ZSxF
-bGVtZW50OmZhbHNlLEFib3J0UGF5bWVudEV2ZW50OnRydWUsQW5pbWF0aW9uRXZlbnQ6dHJ1ZSxBbmlt
-YXRpb25QbGF5YmFja0V2ZW50OnRydWUsQXBwbGljYXRpb25DYWNoZUVycm9yRXZlbnQ6dHJ1ZSxCYWNr
-Z3JvdW5kRmV0Y2hDbGlja0V2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoRXZlbnQ6dHJ1ZSxCYWNrZ3Jv
-dW5kRmV0Y2hGYWlsRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hlZEV2ZW50OnRydWUsQmVmb3JlSW5z
-dGFsbFByb21wdEV2ZW50OnRydWUsQmVmb3JlVW5sb2FkRXZlbnQ6dHJ1ZSxCbG9iRXZlbnQ6dHJ1ZSxD
-YW5NYWtlUGF5bWVudEV2ZW50OnRydWUsQ2xpcGJvYXJkRXZlbnQ6dHJ1ZSxDbG9zZUV2ZW50OnRydWUs
-Q3VzdG9tRXZlbnQ6dHJ1ZSxEZXZpY2VNb3Rpb25FdmVudDp0cnVlLERldmljZU9yaWVudGF0aW9uRXZl
-bnQ6dHJ1ZSxFcnJvckV2ZW50OnRydWUsRXh0ZW5kYWJsZUV2ZW50OnRydWUsRXh0ZW5kYWJsZU1lc3Nh
-Z2VFdmVudDp0cnVlLEZldGNoRXZlbnQ6dHJ1ZSxGb250RmFjZVNldExvYWRFdmVudDp0cnVlLEZvcmVp
-Z25GZXRjaEV2ZW50OnRydWUsR2FtZXBhZEV2ZW50OnRydWUsSGFzaENoYW5nZUV2ZW50OnRydWUsSW5z
-dGFsbEV2ZW50OnRydWUsTWVkaWFFbmNyeXB0ZWRFdmVudDp0cnVlLE1lZGlhS2V5TWVzc2FnZUV2ZW50
-OnRydWUsTWVkaWFRdWVyeUxpc3RFdmVudDp0cnVlLE1lZGlhU3RyZWFtRXZlbnQ6dHJ1ZSxNZWRpYVN0
-cmVhbVRyYWNrRXZlbnQ6dHJ1ZSxNZXNzYWdlRXZlbnQ6dHJ1ZSxNSURJQ29ubmVjdGlvbkV2ZW50OnRy
-dWUsTUlESU1lc3NhZ2VFdmVudDp0cnVlLE11dGF0aW9uRXZlbnQ6dHJ1ZSxOb3RpZmljYXRpb25FdmVu
-dDp0cnVlLFBhZ2VUcmFuc2l0aW9uRXZlbnQ6dHJ1ZSxQYXltZW50UmVxdWVzdEV2ZW50OnRydWUsUGF5
-bWVudFJlcXVlc3RVcGRhdGVFdmVudDp0cnVlLFBvcFN0YXRlRXZlbnQ6dHJ1ZSxQcmVzZW50YXRpb25D
-b25uZWN0aW9uQXZhaWxhYmxlRXZlbnQ6dHJ1ZSxQcmVzZW50YXRpb25Db25uZWN0aW9uQ2xvc2VFdmVu
-dDp0cnVlLFByb21pc2VSZWplY3Rpb25FdmVudDp0cnVlLFB1c2hFdmVudDp0cnVlLFJUQ0RhdGFDaGFu
-bmVsRXZlbnQ6dHJ1ZSxSVENEVE1GVG9uZUNoYW5nZUV2ZW50OnRydWUsUlRDUGVlckNvbm5lY3Rpb25J
-Y2VFdmVudDp0cnVlLFJUQ1RyYWNrRXZlbnQ6dHJ1ZSxTZWN1cml0eVBvbGljeVZpb2xhdGlvbkV2ZW50
-OnRydWUsU2Vuc29yRXJyb3JFdmVudDp0cnVlLFNwZWVjaFJlY29nbml0aW9uRXJyb3I6dHJ1ZSxTcGVl
-Y2hSZWNvZ25pdGlvbkV2ZW50OnRydWUsU3BlZWNoU3ludGhlc2lzRXZlbnQ6dHJ1ZSxTdG9yYWdlRXZl
-bnQ6dHJ1ZSxTeW5jRXZlbnQ6dHJ1ZSxUcmFja0V2ZW50OnRydWUsVHJhbnNpdGlvbkV2ZW50OnRydWUs
-V2ViS2l0VHJhbnNpdGlvbkV2ZW50OnRydWUsVlJEZXZpY2VFdmVudDp0cnVlLFZSRGlzcGxheUV2ZW50
-OnRydWUsVlJTZXNzaW9uRXZlbnQ6dHJ1ZSxNb2pvSW50ZXJmYWNlUmVxdWVzdEV2ZW50OnRydWUsVVNC
-Q29ubmVjdGlvbkV2ZW50OnRydWUsSURCVmVyc2lvbkNoYW5nZUV2ZW50OnRydWUsQXVkaW9Qcm9jZXNz
-aW5nRXZlbnQ6dHJ1ZSxPZmZsaW5lQXVkaW9Db21wbGV0aW9uRXZlbnQ6dHJ1ZSxXZWJHTENvbnRleHRF
-dmVudDp0cnVlLEV2ZW50OmZhbHNlLElucHV0RXZlbnQ6ZmFsc2UsRXZlbnRUYXJnZXQ6ZmFsc2UsRmls
-ZTp0cnVlLEhUTUxGb3JtRWxlbWVudDp0cnVlLEhpc3Rvcnk6dHJ1ZSxIVE1MRG9jdW1lbnQ6dHJ1ZSxY
-TUxIdHRwUmVxdWVzdDp0cnVlLFhNTEh0dHBSZXF1ZXN0RXZlbnRUYXJnZXQ6ZmFsc2UsSW1hZ2VEYXRh
-OnRydWUsTG9jYXRpb246dHJ1ZSxNb3VzZUV2ZW50OnRydWUsRHJhZ0V2ZW50OnRydWUsUG9pbnRlckV2
-ZW50OnRydWUsV2hlZWxFdmVudDp0cnVlLERvY3VtZW50RnJhZ21lbnQ6dHJ1ZSxTaGFkb3dSb290OnRy
-dWUsRG9jdW1lbnRUeXBlOnRydWUsTm9kZTpmYWxzZSxOb2RlTGlzdDp0cnVlLFJhZGlvTm9kZUxpc3Q6
-dHJ1ZSxIVE1MUGFyYWdyYXBoRWxlbWVudDp0cnVlLFByb2dyZXNzRXZlbnQ6dHJ1ZSxSZXNvdXJjZVBy
-b2dyZXNzRXZlbnQ6dHJ1ZSxIVE1MU2VsZWN0RWxlbWVudDp0cnVlLEhUTUxUYWJsZUVsZW1lbnQ6dHJ1
-ZSxIVE1MVGFibGVSb3dFbGVtZW50OnRydWUsSFRNTFRhYmxlU2VjdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1M
-VGVtcGxhdGVFbGVtZW50OnRydWUsQ29tcG9zaXRpb25FdmVudDp0cnVlLEZvY3VzRXZlbnQ6dHJ1ZSxL
-ZXlib2FyZEV2ZW50OnRydWUsVGV4dEV2ZW50OnRydWUsVG91Y2hFdmVudDp0cnVlLFVJRXZlbnQ6ZmFs
-c2UsV2luZG93OnRydWUsRE9NV2luZG93OnRydWUsRGVkaWNhdGVkV29ya2VyR2xvYmFsU2NvcGU6dHJ1
-ZSxTZXJ2aWNlV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxTaGFyZWRXb3JrZXJHbG9iYWxTY29wZTp0cnVl
-LFdvcmtlckdsb2JhbFNjb3BlOnRydWUsQXR0cjp0cnVlLENsaWVudFJlY3Q6dHJ1ZSxET01SZWN0OnRy
-dWUsTmFtZWROb2RlTWFwOnRydWUsTW96TmFtZWRBdHRyTWFwOnRydWUsSURCS2V5UmFuZ2U6dHJ1ZSxT
-VkdTY3JpcHRFbGVtZW50OnRydWUsU1ZHQUVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlRWxlbWVudDp0cnVl
-LFNWR0FuaW1hdGVNb3Rpb25FbGVtZW50OnRydWUsU1ZHQW5pbWF0ZVRyYW5zZm9ybUVsZW1lbnQ6dHJ1
-ZSxTVkdBbmltYXRpb25FbGVtZW50OnRydWUsU1ZHQ2lyY2xlRWxlbWVudDp0cnVlLFNWR0NsaXBQYXRo
-RWxlbWVudDp0cnVlLFNWR0RlZnNFbGVtZW50OnRydWUsU1ZHRGVzY0VsZW1lbnQ6dHJ1ZSxTVkdEaXNj
-YXJkRWxlbWVudDp0cnVlLFNWR0VsbGlwc2VFbGVtZW50OnRydWUsU1ZHRkVCbGVuZEVsZW1lbnQ6dHJ1
-ZSxTVkdGRUNvbG9yTWF0cml4RWxlbWVudDp0cnVlLFNWR0ZFQ29tcG9uZW50VHJhbnNmZXJFbGVtZW50
-OnRydWUsU1ZHRkVDb21wb3NpdGVFbGVtZW50OnRydWUsU1ZHRkVDb252b2x2ZU1hdHJpeEVsZW1lbnQ6
-dHJ1ZSxTVkdGRURpZmZ1c2VMaWdodGluZ0VsZW1lbnQ6dHJ1ZSxTVkdGRURpc3BsYWNlbWVudE1hcEVs
-ZW1lbnQ6dHJ1ZSxTVkdGRURpc3RhbnRMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRUZsb29kRWxlbWVudDp0
-cnVlLFNWR0ZFRnVuY0FFbGVtZW50OnRydWUsU1ZHRkVGdW5jQkVsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNH
-RWxlbWVudDp0cnVlLFNWR0ZFRnVuY1JFbGVtZW50OnRydWUsU1ZHRkVHYXVzc2lhbkJsdXJFbGVtZW50
-OnRydWUsU1ZHRkVJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1lcmdlRWxlbWVudDp0cnVlLFNWR0ZFTWVy
-Z2VOb2RlRWxlbWVudDp0cnVlLFNWR0ZFTW9ycGhvbG9neUVsZW1lbnQ6dHJ1ZSxTVkdGRU9mZnNldEVs
-ZW1lbnQ6dHJ1ZSxTVkdGRVBvaW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVTcGVjdWxhckxpZ2h0aW5n
-RWxlbWVudDp0cnVlLFNWR0ZFU3BvdExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFVGlsZUVsZW1lbnQ6dHJ1
-ZSxTVkdGRVR1cmJ1bGVuY2VFbGVtZW50OnRydWUsU1ZHRmlsdGVyRWxlbWVudDp0cnVlLFNWR0ZvcmVp
-Z25PYmplY3RFbGVtZW50OnRydWUsU1ZHR0VsZW1lbnQ6dHJ1ZSxTVkdHZW9tZXRyeUVsZW1lbnQ6dHJ1
-ZSxTVkdHcmFwaGljc0VsZW1lbnQ6dHJ1ZSxTVkdJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdMaW5lRWxlbWVu
-dDp0cnVlLFNWR0xpbmVhckdyYWRpZW50RWxlbWVudDp0cnVlLFNWR01hcmtlckVsZW1lbnQ6dHJ1ZSxT
-VkdNYXNrRWxlbWVudDp0cnVlLFNWR01ldGFkYXRhRWxlbWVudDp0cnVlLFNWR1BhdGhFbGVtZW50OnRy
-dWUsU1ZHUGF0dGVybkVsZW1lbnQ6dHJ1ZSxTVkdQb2x5Z29uRWxlbWVudDp0cnVlLFNWR1BvbHlsaW5l
-RWxlbWVudDp0cnVlLFNWR1JhZGlhbEdyYWRpZW50RWxlbWVudDp0cnVlLFNWR1JlY3RFbGVtZW50OnRy
-dWUsU1ZHU2V0RWxlbWVudDp0cnVlLFNWR1N0b3BFbGVtZW50OnRydWUsU1ZHU3R5bGVFbGVtZW50OnRy
-dWUsU1ZHU1ZHRWxlbWVudDp0cnVlLFNWR1N3aXRjaEVsZW1lbnQ6dHJ1ZSxTVkdTeW1ib2xFbGVtZW50
-OnRydWUsU1ZHVFNwYW5FbGVtZW50OnRydWUsU1ZHVGV4dENvbnRlbnRFbGVtZW50OnRydWUsU1ZHVGV4
-dEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0UGF0aEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0UG9zaXRpb25pbmdFbGVt
-ZW50OnRydWUsU1ZHVGl0bGVFbGVtZW50OnRydWUsU1ZHVXNlRWxlbWVudDp0cnVlLFNWR1ZpZXdFbGVt
-ZW50OnRydWUsU1ZHR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHQ29tcG9uZW50VHJhbnNmZXJGdW5jdGlv
-bkVsZW1lbnQ6dHJ1ZSxTVkdGRURyb3BTaGFkb3dFbGVtZW50OnRydWUsU1ZHTVBhdGhFbGVtZW50OnRy
-dWUsU1ZHRWxlbWVudDpmYWxzZX0pCkguYjAuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVy
-VmlldyIKSC5SRy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlZQLiRuYXRp
-dmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguRGcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9
-IkFycmF5QnVmZmVyVmlldyIKSC5XQi4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3
-IgpILlpHLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguUGcuJG5hdGl2ZVN1
-cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyJ9KSgpCmNvbnZlcnRBbGxUb0Zhc3RPYmplY3QodykK
-Y29udmVydFRvRmFzdE9iamVjdCgkKTsoZnVuY3Rpb24oYSl7aWYodHlwZW9mIGRvY3VtZW50PT09InVu
-ZGVmaW5lZCIpe2EobnVsbCkKcmV0dXJufWlmKHR5cGVvZiBkb2N1bWVudC5jdXJyZW50U2NyaXB0IT0n
-dW5kZWZpbmVkJyl7YShkb2N1bWVudC5jdXJyZW50U2NyaXB0KQpyZXR1cm59dmFyIHQ9ZG9jdW1lbnQu
-c2NyaXB0cwpmdW5jdGlvbiBvbkxvYWQoYil7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDsrK3IpdFtyXS5y
-ZW1vdmVFdmVudExpc3RlbmVyKCJsb2FkIixvbkxvYWQsZmFsc2UpCmEoYi50YXJnZXQpfWZvcih2YXIg
-cz0wO3M8dC5sZW5ndGg7KytzKXRbc10uYWRkRXZlbnRMaXN0ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNl
-KX0pKGZ1bmN0aW9uKGEpe3YuY3VycmVudFNjcmlwdD1hCmlmKHR5cGVvZiBkYXJ0TWFpblJ1bm5lcj09
-PSJmdW5jdGlvbiIpZGFydE1haW5SdW5uZXIoTC5JcSxbXSkKZWxzZSBMLklxKFtdKX0pfSkoKQovLyMg
-c291cmNlTWFwcGluZ1VSTD1taWdyYXRpb24uanMubWFwCg==
+LC0yLC0yLC0yLC0yLC0yLC0xLC0yLC0yLC0yLC0yLC0yLDYyLC0yLDYyLC0yLDYzLDUyLDUzLDU0LDU1
+LDU2LDU3LDU4LDU5LDYwLDYxLC0yLC0yLC0yLC0xLC0yLC0yLC0yLDAsMSwyLDMsNCw1LDYsNyw4LDks
+MTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMsMjQsMjUsLTIsLTIsLTIsLTIs
+NjMsLTIsMjYsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIsNDMs
+NDQsNDUsNDYsNDcsNDgsNDksNTAsNTEsLTIsLTIsLTIsLTIsLTJdLHUudCkpKX0pCnQoJCwiTTUiLCJ3
+USIsZnVuY3Rpb24oKXtyZXR1cm4gdHlwZW9mIHByb2Nlc3MhPSJ1bmRlZmluZWQiJiZPYmplY3QucHJv
+dG90eXBlLnRvU3RyaW5nLmNhbGwocHJvY2Vzcyk9PSJbb2JqZWN0IHByb2Nlc3NdIiYmcHJvY2Vzcy5w
+bGF0Zm9ybT09IndpbjMyIn0pCnQoJCwibWYiLCJ6NCIsZnVuY3Rpb24oKXtyZXR1cm4gUC5udSgiXltc
+XC1cXC4wLTlBLVpfYS16fl0qJCIpfSkKdCgkLCJKRyIsInZaIixmdW5jdGlvbigpe3JldHVybiBQLnV4
+KCl9KQp0KCQsIlNDIiwiQU4iLGZ1bmN0aW9uKCl7cmV0dXJuIFAudE0oWyJBIiwiQUJCUiIsIkFDUk9O
+WU0iLCJBRERSRVNTIiwiQVJFQSIsIkFSVElDTEUiLCJBU0lERSIsIkFVRElPIiwiQiIsIkJESSIsIkJE
+TyIsIkJJRyIsIkJMT0NLUVVPVEUiLCJCUiIsIkJVVFRPTiIsIkNBTlZBUyIsIkNBUFRJT04iLCJDRU5U
+RVIiLCJDSVRFIiwiQ09ERSIsIkNPTCIsIkNPTEdST1VQIiwiQ09NTUFORCIsIkRBVEEiLCJEQVRBTElT
+VCIsIkREIiwiREVMIiwiREVUQUlMUyIsIkRGTiIsIkRJUiIsIkRJViIsIkRMIiwiRFQiLCJFTSIsIkZJ
+RUxEU0VUIiwiRklHQ0FQVElPTiIsIkZJR1VSRSIsIkZPTlQiLCJGT09URVIiLCJGT1JNIiwiSDEiLCJI
+MiIsIkgzIiwiSDQiLCJINSIsIkg2IiwiSEVBREVSIiwiSEdST1VQIiwiSFIiLCJJIiwiSUZSQU1FIiwi
+SU1HIiwiSU5QVVQiLCJJTlMiLCJLQkQiLCJMQUJFTCIsIkxFR0VORCIsIkxJIiwiTUFQIiwiTUFSSyIs
+Ik1FTlUiLCJNRVRFUiIsIk5BViIsIk5PQlIiLCJPTCIsIk9QVEdST1VQIiwiT1BUSU9OIiwiT1VUUFVU
+IiwiUCIsIlBSRSIsIlBST0dSRVNTIiwiUSIsIlMiLCJTQU1QIiwiU0VDVElPTiIsIlNFTEVDVCIsIlNN
+QUxMIiwiU09VUkNFIiwiU1BBTiIsIlNUUklLRSIsIlNUUk9ORyIsIlNVQiIsIlNVTU1BUlkiLCJTVVAi
+LCJUQUJMRSIsIlRCT0RZIiwiVEQiLCJURVhUQVJFQSIsIlRGT09UIiwiVEgiLCJUSEVBRCIsIlRJTUUi
+LCJUUiIsIlRSQUNLIiwiVFQiLCJVIiwiVUwiLCJWQVIiLCJWSURFTyIsIldCUiJdLHUuTil9KQp0KCQs
+Ilg0IiwiaEciLGZ1bmN0aW9uKCl7cmV0dXJuIFAubnUoIl5cXFMrJCIpfSkKdCgkLCJ3TyIsIm93Iixm
+dW5jdGlvbigpe3JldHVybiB1LnYuYihQLk5EKHNlbGYpKX0pCnQoJCwia3QiLCJSOCIsZnVuY3Rpb24o
+KXtyZXR1cm4gSC5ZZygiXyRkYXJ0X2RhcnRPYmplY3QiKX0pCnQoJCwiZksiLCJrSSIsZnVuY3Rpb24o
+KXtyZXR1cm4gZnVuY3Rpb24gRGFydE9iamVjdChhKXt0aGlzLm89YX19KQp0KCQsInF0IiwiekIiLGZ1
+bmN0aW9uKCl7cmV0dXJuIG5ldyBULkdWKCl9KQp0KCQsImZlIiwiS0ciLGZ1bmN0aW9uKCl7cmV0dXJu
+IG5ldyBMLlhBKCl9KQp0KCQsIm1NIiwiblUiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBNLmxJKCQuSGso
+KSl9KQp0KCQsInlyIiwiYkQiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBFLk9GKFAubnUoIi8iKSxQLm51
+KCJbXi9dJCIpLFAubnUoIl4vIikpfSkKdCgkLCJNayIsIktrIixmdW5jdGlvbigpe3JldHVybiBuZXcg
+TC5JVihQLm51KCJbL1xcXFxdIiksUC5udSgiW14vXFxcXF0kIiksUC5udSgiXihcXFxcXFxcXFteXFxc
+XF0rXFxcXFteXFxcXC9dK3xbYS16QS1aXTpbL1xcXFxdKSIpLFAubnUoIl5bL1xcXFxdKD8hWy9cXFxc
+XSkiKSl9KQp0KCQsImFrIiwiRWIiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBGLnJ1KFAubnUoIi8iKSxQ
+Lm51KCIoXlthLXpBLVpdWy0rLmEtekEtWlxcZF0qOi8vfFteL10pJCIpLFAubnUoIlthLXpBLVpdWy0r
+LmEtekEtWlxcZF0qOi8vW14vXSoiKSxQLm51KCJeLyIpKX0pCnQoJCwibHMiLCJIayIsZnVuY3Rpb24o
+KXtyZXR1cm4gTy5SaCgpfSl9KSgpOyhmdW5jdGlvbiBuYXRpdmVTdXBwb3J0KCl7IWZ1bmN0aW9uKCl7
+dmFyIHQ9ZnVuY3Rpb24oYSl7dmFyIG49e30KblthXT0xCnJldHVybiBPYmplY3Qua2V5cyhodW5rSGVs
+cGVycy5jb252ZXJ0VG9GYXN0T2JqZWN0KG4pKVswXX0Kdi5nZXRJc29sYXRlVGFnPWZ1bmN0aW9uKGEp
+e3JldHVybiB0KCJfX19kYXJ0XyIrYSt2Lmlzb2xhdGVUYWcpfQp2YXIgcz0iX19fZGFydF9pc29sYXRl
+X3RhZ3NfIgp2YXIgcj1PYmplY3Rbc118fChPYmplY3Rbc109T2JqZWN0LmNyZWF0ZShudWxsKSkKdmFy
+IHE9Il9aeFl4WCIKZm9yKHZhciBwPTA7O3ArKyl7dmFyIG89dChxKyJfIitwKyJfIikKaWYoIShvIGlu
+IHIpKXtyW29dPTEKdi5pc29sYXRlVGFnPW8KYnJlYWt9fXYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWU9di5n
+ZXRJc29sYXRlVGFnKCJkaXNwYXRjaF9yZWNvcmQiKX0oKQpodW5rSGVscGVycy5zZXRPclVwZGF0ZUlu
+dGVyY2VwdG9yc0J5VGFnKHtET01FcnJvcjpKLnZCLERPTUltcGxlbWVudGF0aW9uOkoudkIsTWVkaWFF
+cnJvcjpKLnZCLE5hdmlnYXRvcjpKLnZCLE5hdmlnYXRvckNvbmN1cnJlbnRIYXJkd2FyZTpKLnZCLE5h
+dmlnYXRvclVzZXJNZWRpYUVycm9yOkoudkIsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6Si52QixQb3NpdGlv
+bkVycm9yOkoudkIsUmFuZ2U6Si52QixTUUxFcnJvcjpKLnZCLERhdGFWaWV3OkguRVQsQXJyYXlCdWZm
+ZXJWaWV3OkguRVQsRmxvYXQzMkFycmF5OkguRGcsRmxvYXQ2NEFycmF5OkguRGcsSW50MTZBcnJheTpI
+LnhqLEludDMyQXJyYXk6SC5kRSxJbnQ4QXJyYXk6SC5aQSxVaW50MTZBcnJheTpILndmLFVpbnQzMkFy
+cmF5OkguUHEsVWludDhDbGFtcGVkQXJyYXk6SC5lRSxDYW52YXNQaXhlbEFycmF5OkguZUUsVWludDhB
+cnJheTpILlY2LEhUTUxBdWRpb0VsZW1lbnQ6Vy5xRSxIVE1MQlJFbGVtZW50OlcucUUsSFRNTEJ1dHRv
+bkVsZW1lbnQ6Vy5xRSxIVE1MQ2FudmFzRWxlbWVudDpXLnFFLEhUTUxDb250ZW50RWxlbWVudDpXLnFF
+LEhUTUxETGlzdEVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUxpc3RFbGVt
+ZW50OlcucUUsSFRNTERldGFpbHNFbGVtZW50OlcucUUsSFRNTERpYWxvZ0VsZW1lbnQ6Vy5xRSxIVE1M
+RGl2RWxlbWVudDpXLnFFLEhUTUxFbWJlZEVsZW1lbnQ6Vy5xRSxIVE1MRmllbGRTZXRFbGVtZW50Olcu
+cUUsSFRNTEhSRWxlbWVudDpXLnFFLEhUTUxIZWFkRWxlbWVudDpXLnFFLEhUTUxIZWFkaW5nRWxlbWVu
+dDpXLnFFLEhUTUxIdG1sRWxlbWVudDpXLnFFLEhUTUxJRnJhbWVFbGVtZW50OlcucUUsSFRNTEltYWdl
+RWxlbWVudDpXLnFFLEhUTUxJbnB1dEVsZW1lbnQ6Vy5xRSxIVE1MTElFbGVtZW50OlcucUUsSFRNTExh
+YmVsRWxlbWVudDpXLnFFLEhUTUxMZWdlbmRFbGVtZW50OlcucUUsSFRNTExpbmtFbGVtZW50OlcucUUs
+SFRNTE1hcEVsZW1lbnQ6Vy5xRSxIVE1MTWVkaWFFbGVtZW50OlcucUUsSFRNTE1lbnVFbGVtZW50Olcu
+cUUsSFRNTE1ldGFFbGVtZW50OlcucUUsSFRNTE1ldGVyRWxlbWVudDpXLnFFLEhUTUxNb2RFbGVtZW50
+OlcucUUsSFRNTE9MaXN0RWxlbWVudDpXLnFFLEhUTUxPYmplY3RFbGVtZW50OlcucUUsSFRNTE9wdEdy
+b3VwRWxlbWVudDpXLnFFLEhUTUxPcHRpb25FbGVtZW50OlcucUUsSFRNTE91dHB1dEVsZW1lbnQ6Vy5x
+RSxIVE1MUGFyYW1FbGVtZW50OlcucUUsSFRNTFBpY3R1cmVFbGVtZW50OlcucUUsSFRNTFByZUVsZW1l
+bnQ6Vy5xRSxIVE1MUHJvZ3Jlc3NFbGVtZW50OlcucUUsSFRNTFF1b3RlRWxlbWVudDpXLnFFLEhUTUxT
+Y3JpcHRFbGVtZW50OlcucUUsSFRNTFNoYWRvd0VsZW1lbnQ6Vy5xRSxIVE1MU2xvdEVsZW1lbnQ6Vy5x
+RSxIVE1MU291cmNlRWxlbWVudDpXLnFFLEhUTUxTcGFuRWxlbWVudDpXLnFFLEhUTUxTdHlsZUVsZW1l
+bnQ6Vy5xRSxIVE1MVGFibGVDYXB0aW9uRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNlbGxFbGVtZW50Olcu
+cUUsSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlSGVhZGVyQ2VsbEVsZW1lbnQ6
+Vy5xRSxIVE1MVGFibGVDb2xFbGVtZW50OlcucUUsSFRNTFRleHRBcmVhRWxlbWVudDpXLnFFLEhUTUxU
+aW1lRWxlbWVudDpXLnFFLEhUTUxUaXRsZUVsZW1lbnQ6Vy5xRSxIVE1MVHJhY2tFbGVtZW50OlcucUUs
+SFRNTFVMaXN0RWxlbWVudDpXLnFFLEhUTUxVbmtub3duRWxlbWVudDpXLnFFLEhUTUxWaWRlb0VsZW1l
+bnQ6Vy5xRSxIVE1MRGlyZWN0b3J5RWxlbWVudDpXLnFFLEhUTUxGb250RWxlbWVudDpXLnFFLEhUTUxG
+cmFtZUVsZW1lbnQ6Vy5xRSxIVE1MRnJhbWVTZXRFbGVtZW50OlcucUUsSFRNTE1hcnF1ZWVFbGVtZW50
+OlcucUUsSFRNTEVsZW1lbnQ6Vy5xRSxIVE1MQW5jaG9yRWxlbWVudDpXLkdoLEhUTUxBcmVhRWxlbWVu
+dDpXLmZZLEhUTUxCYXNlRWxlbWVudDpXLm5CLEJsb2I6Vy5BeixIVE1MQm9keUVsZW1lbnQ6Vy5RUCxD
+REFUQVNlY3Rpb246Vy5ueCxDaGFyYWN0ZXJEYXRhOlcubngsQ29tbWVudDpXLm54LFByb2Nlc3NpbmdJ
+bnN0cnVjdGlvbjpXLm54LFRleHQ6Vy5ueCxDU1NTdHlsZURlY2xhcmF0aW9uOlcub0osTVNTdHlsZUNT
+U1Byb3BlcnRpZXM6Vy5vSixDU1MyUHJvcGVydGllczpXLm9KLFhNTERvY3VtZW50OlcuUUYsRG9jdW1l
+bnQ6Vy5RRixET01FeGNlcHRpb246Vy5OaCxET01SZWN0UmVhZE9ubHk6Vy5JQixET01Ub2tlbkxpc3Q6
+Vy5uNyxFbGVtZW50OlcuY3YsQWJvcnRQYXltZW50RXZlbnQ6Vy5lYSxBbmltYXRpb25FdmVudDpXLmVh
+LEFuaW1hdGlvblBsYXliYWNrRXZlbnQ6Vy5lYSxBcHBsaWNhdGlvbkNhY2hlRXJyb3JFdmVudDpXLmVh
+LEJhY2tncm91bmRGZXRjaENsaWNrRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hFdmVudDpXLmVhLEJh
+Y2tncm91bmRGZXRjaEZhaWxFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaGVkRXZlbnQ6Vy5lYSxCZWZv
+cmVJbnN0YWxsUHJvbXB0RXZlbnQ6Vy5lYSxCZWZvcmVVbmxvYWRFdmVudDpXLmVhLEJsb2JFdmVudDpX
+LmVhLENhbk1ha2VQYXltZW50RXZlbnQ6Vy5lYSxDbGlwYm9hcmRFdmVudDpXLmVhLENsb3NlRXZlbnQ6
+Vy5lYSxDdXN0b21FdmVudDpXLmVhLERldmljZU1vdGlvbkV2ZW50OlcuZWEsRGV2aWNlT3JpZW50YXRp
+b25FdmVudDpXLmVhLEVycm9yRXZlbnQ6Vy5lYSxFeHRlbmRhYmxlRXZlbnQ6Vy5lYSxFeHRlbmRhYmxl
+TWVzc2FnZUV2ZW50OlcuZWEsRmV0Y2hFdmVudDpXLmVhLEZvbnRGYWNlU2V0TG9hZEV2ZW50OlcuZWEs
+Rm9yZWlnbkZldGNoRXZlbnQ6Vy5lYSxHYW1lcGFkRXZlbnQ6Vy5lYSxIYXNoQ2hhbmdlRXZlbnQ6Vy5l
+YSxJbnN0YWxsRXZlbnQ6Vy5lYSxNZWRpYUVuY3J5cHRlZEV2ZW50OlcuZWEsTWVkaWFLZXlNZXNzYWdl
+RXZlbnQ6Vy5lYSxNZWRpYVF1ZXJ5TGlzdEV2ZW50OlcuZWEsTWVkaWFTdHJlYW1FdmVudDpXLmVhLE1l
+ZGlhU3RyZWFtVHJhY2tFdmVudDpXLmVhLE1lc3NhZ2VFdmVudDpXLmVhLE1JRElDb25uZWN0aW9uRXZl
+bnQ6Vy5lYSxNSURJTWVzc2FnZUV2ZW50OlcuZWEsTXV0YXRpb25FdmVudDpXLmVhLE5vdGlmaWNhdGlv
+bkV2ZW50OlcuZWEsUGFnZVRyYW5zaXRpb25FdmVudDpXLmVhLFBheW1lbnRSZXF1ZXN0RXZlbnQ6Vy5l
+YSxQYXltZW50UmVxdWVzdFVwZGF0ZUV2ZW50OlcuZWEsUG9wU3RhdGVFdmVudDpXLmVhLFByZXNlbnRh
+dGlvbkNvbm5lY3Rpb25BdmFpbGFibGVFdmVudDpXLmVhLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25DbG9z
+ZUV2ZW50OlcuZWEsUHJvbWlzZVJlamVjdGlvbkV2ZW50OlcuZWEsUHVzaEV2ZW50OlcuZWEsUlRDRGF0
+YUNoYW5uZWxFdmVudDpXLmVhLFJUQ0RUTUZUb25lQ2hhbmdlRXZlbnQ6Vy5lYSxSVENQZWVyQ29ubmVj
+dGlvbkljZUV2ZW50OlcuZWEsUlRDVHJhY2tFdmVudDpXLmVhLFNlY3VyaXR5UG9saWN5VmlvbGF0aW9u
+RXZlbnQ6Vy5lYSxTZW5zb3JFcnJvckV2ZW50OlcuZWEsU3BlZWNoUmVjb2duaXRpb25FcnJvcjpXLmVh
+LFNwZWVjaFJlY29nbml0aW9uRXZlbnQ6Vy5lYSxTcGVlY2hTeW50aGVzaXNFdmVudDpXLmVhLFN0b3Jh
+Z2VFdmVudDpXLmVhLFN5bmNFdmVudDpXLmVhLFRyYWNrRXZlbnQ6Vy5lYSxUcmFuc2l0aW9uRXZlbnQ6
+Vy5lYSxXZWJLaXRUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxWUkRldmljZUV2ZW50OlcuZWEsVlJEaXNwbGF5
+RXZlbnQ6Vy5lYSxWUlNlc3Npb25FdmVudDpXLmVhLE1vam9JbnRlcmZhY2VSZXF1ZXN0RXZlbnQ6Vy5l
+YSxVU0JDb25uZWN0aW9uRXZlbnQ6Vy5lYSxJREJWZXJzaW9uQ2hhbmdlRXZlbnQ6Vy5lYSxBdWRpb1By
+b2Nlc3NpbmdFdmVudDpXLmVhLE9mZmxpbmVBdWRpb0NvbXBsZXRpb25FdmVudDpXLmVhLFdlYkdMQ29u
+dGV4dEV2ZW50OlcuZWEsRXZlbnQ6Vy5lYSxJbnB1dEV2ZW50OlcuZWEsRXZlbnRUYXJnZXQ6Vy5EMCxG
+aWxlOlcuVDUsSFRNTEZvcm1FbGVtZW50OlcuaDQsSGlzdG9yeTpXLmJyLEhUTUxEb2N1bWVudDpXLlZi
+LFhNTEh0dHBSZXF1ZXN0OlcuTzcsWE1MSHR0cFJlcXVlc3RFdmVudFRhcmdldDpXLndhLEltYWdlRGF0
+YTpXLlNnLExvY2F0aW9uOlcudTgsTW91c2VFdmVudDpXLkFqLERyYWdFdmVudDpXLkFqLFBvaW50ZXJF
+dmVudDpXLkFqLFdoZWVsRXZlbnQ6Vy5BaixEb2N1bWVudEZyYWdtZW50OlcudUgsU2hhZG93Um9vdDpX
+LnVILERvY3VtZW50VHlwZTpXLnVILE5vZGU6Vy51SCxOb2RlTGlzdDpXLkJILFJhZGlvTm9kZUxpc3Q6
+Vy5CSCxIVE1MUGFyYWdyYXBoRWxlbWVudDpXLlNOLFByb2dyZXNzRXZlbnQ6Vy5ldyxSZXNvdXJjZVBy
+b2dyZXNzRXZlbnQ6Vy5ldyxIVE1MU2VsZWN0RWxlbWVudDpXLmxwLEhUTUxUYWJsZUVsZW1lbnQ6Vy5U
+YixIVE1MVGFibGVSb3dFbGVtZW50OlcuSXYsSFRNTFRhYmxlU2VjdGlvbkVsZW1lbnQ6Vy5CVCxIVE1M
+VGVtcGxhdGVFbGVtZW50OlcueVksQ29tcG9zaXRpb25FdmVudDpXLnc2LEZvY3VzRXZlbnQ6Vy53NixL
+ZXlib2FyZEV2ZW50OlcudzYsVGV4dEV2ZW50OlcudzYsVG91Y2hFdmVudDpXLnc2LFVJRXZlbnQ6Vy53
+NixXaW5kb3c6Vy5LNSxET01XaW5kb3c6Vy5LNSxEZWRpY2F0ZWRXb3JrZXJHbG9iYWxTY29wZTpXLkNt
+LFNlcnZpY2VXb3JrZXJHbG9iYWxTY29wZTpXLkNtLFNoYXJlZFdvcmtlckdsb2JhbFNjb3BlOlcuQ20s
+V29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxBdHRyOlcuQ1EsQ2xpZW50UmVjdDpXLnc0LERPTVJlY3Q6Vy53
+NCxOYW1lZE5vZGVNYXA6Vy5yaCxNb3pOYW1lZEF0dHJNYXA6Vy5yaCxJREJLZXlSYW5nZTpQLmhGLFNW
+R1NjcmlwdEVsZW1lbnQ6UC5uZCxTVkdBRWxlbWVudDpQLmQ1LFNWR0FuaW1hdGVFbGVtZW50OlAuZDUs
+U1ZHQW5pbWF0ZU1vdGlvbkVsZW1lbnQ6UC5kNSxTVkdBbmltYXRlVHJhbnNmb3JtRWxlbWVudDpQLmQ1
+LFNWR0FuaW1hdGlvbkVsZW1lbnQ6UC5kNSxTVkdDaXJjbGVFbGVtZW50OlAuZDUsU1ZHQ2xpcFBhdGhF
+bGVtZW50OlAuZDUsU1ZHRGVmc0VsZW1lbnQ6UC5kNSxTVkdEZXNjRWxlbWVudDpQLmQ1LFNWR0Rpc2Nh
+cmRFbGVtZW50OlAuZDUsU1ZHRWxsaXBzZUVsZW1lbnQ6UC5kNSxTVkdGRUJsZW5kRWxlbWVudDpQLmQ1
+LFNWR0ZFQ29sb3JNYXRyaXhFbGVtZW50OlAuZDUsU1ZHRkVDb21wb25lbnRUcmFuc2ZlckVsZW1lbnQ6
+UC5kNSxTVkdGRUNvbXBvc2l0ZUVsZW1lbnQ6UC5kNSxTVkdGRUNvbnZvbHZlTWF0cml4RWxlbWVudDpQ
+LmQ1LFNWR0ZFRGlmZnVzZUxpZ2h0aW5nRWxlbWVudDpQLmQ1LFNWR0ZFRGlzcGxhY2VtZW50TWFwRWxl
+bWVudDpQLmQ1LFNWR0ZFRGlzdGFudExpZ2h0RWxlbWVudDpQLmQ1LFNWR0ZFRmxvb2RFbGVtZW50OlAu
+ZDUsU1ZHRkVGdW5jQUVsZW1lbnQ6UC5kNSxTVkdGRUZ1bmNCRWxlbWVudDpQLmQ1LFNWR0ZFRnVuY0dF
+bGVtZW50OlAuZDUsU1ZHRkVGdW5jUkVsZW1lbnQ6UC5kNSxTVkdGRUdhdXNzaWFuQmx1ckVsZW1lbnQ6
+UC5kNSxTVkdGRUltYWdlRWxlbWVudDpQLmQ1LFNWR0ZFTWVyZ2VFbGVtZW50OlAuZDUsU1ZHRkVNZXJn
+ZU5vZGVFbGVtZW50OlAuZDUsU1ZHRkVNb3JwaG9sb2d5RWxlbWVudDpQLmQ1LFNWR0ZFT2Zmc2V0RWxl
+bWVudDpQLmQ1LFNWR0ZFUG9pbnRMaWdodEVsZW1lbnQ6UC5kNSxTVkdGRVNwZWN1bGFyTGlnaHRpbmdF
+bGVtZW50OlAuZDUsU1ZHRkVTcG90TGlnaHRFbGVtZW50OlAuZDUsU1ZHRkVUaWxlRWxlbWVudDpQLmQ1
+LFNWR0ZFVHVyYnVsZW5jZUVsZW1lbnQ6UC5kNSxTVkdGaWx0ZXJFbGVtZW50OlAuZDUsU1ZHRm9yZWln
+bk9iamVjdEVsZW1lbnQ6UC5kNSxTVkdHRWxlbWVudDpQLmQ1LFNWR0dlb21ldHJ5RWxlbWVudDpQLmQ1
+LFNWR0dyYXBoaWNzRWxlbWVudDpQLmQ1LFNWR0ltYWdlRWxlbWVudDpQLmQ1LFNWR0xpbmVFbGVtZW50
+OlAuZDUsU1ZHTGluZWFyR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHTWFya2VyRWxlbWVudDpQLmQ1LFNW
+R01hc2tFbGVtZW50OlAuZDUsU1ZHTWV0YWRhdGFFbGVtZW50OlAuZDUsU1ZHUGF0aEVsZW1lbnQ6UC5k
+NSxTVkdQYXR0ZXJuRWxlbWVudDpQLmQ1LFNWR1BvbHlnb25FbGVtZW50OlAuZDUsU1ZHUG9seWxpbmVF
+bGVtZW50OlAuZDUsU1ZHUmFkaWFsR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHUmVjdEVsZW1lbnQ6UC5k
+NSxTVkdTZXRFbGVtZW50OlAuZDUsU1ZHU3RvcEVsZW1lbnQ6UC5kNSxTVkdTdHlsZUVsZW1lbnQ6UC5k
+NSxTVkdTVkdFbGVtZW50OlAuZDUsU1ZHU3dpdGNoRWxlbWVudDpQLmQ1LFNWR1N5bWJvbEVsZW1lbnQ6
+UC5kNSxTVkdUU3BhbkVsZW1lbnQ6UC5kNSxTVkdUZXh0Q29udGVudEVsZW1lbnQ6UC5kNSxTVkdUZXh0
+RWxlbWVudDpQLmQ1LFNWR1RleHRQYXRoRWxlbWVudDpQLmQ1LFNWR1RleHRQb3NpdGlvbmluZ0VsZW1l
+bnQ6UC5kNSxTVkdUaXRsZUVsZW1lbnQ6UC5kNSxTVkdVc2VFbGVtZW50OlAuZDUsU1ZHVmlld0VsZW1l
+bnQ6UC5kNSxTVkdHcmFkaWVudEVsZW1lbnQ6UC5kNSxTVkdDb21wb25lbnRUcmFuc2ZlckZ1bmN0aW9u
+RWxlbWVudDpQLmQ1LFNWR0ZFRHJvcFNoYWRvd0VsZW1lbnQ6UC5kNSxTVkdNUGF0aEVsZW1lbnQ6UC5k
+NSxTVkdFbGVtZW50OlAuZDV9KQpodW5rSGVscGVycy5zZXRPclVwZGF0ZUxlYWZUYWdzKHtET01FcnJv
+cjp0cnVlLERPTUltcGxlbWVudGF0aW9uOnRydWUsTWVkaWFFcnJvcjp0cnVlLE5hdmlnYXRvcjp0cnVl
+LE5hdmlnYXRvckNvbmN1cnJlbnRIYXJkd2FyZTp0cnVlLE5hdmlnYXRvclVzZXJNZWRpYUVycm9yOnRy
+dWUsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6dHJ1ZSxQb3NpdGlvbkVycm9yOnRydWUsUmFuZ2U6dHJ1ZSxT
+UUxFcnJvcjp0cnVlLERhdGFWaWV3OnRydWUsQXJyYXlCdWZmZXJWaWV3OmZhbHNlLEZsb2F0MzJBcnJh
+eTp0cnVlLEZsb2F0NjRBcnJheTp0cnVlLEludDE2QXJyYXk6dHJ1ZSxJbnQzMkFycmF5OnRydWUsSW50
+OEFycmF5OnRydWUsVWludDE2QXJyYXk6dHJ1ZSxVaW50MzJBcnJheTp0cnVlLFVpbnQ4Q2xhbXBlZEFy
+cmF5OnRydWUsQ2FudmFzUGl4ZWxBcnJheTp0cnVlLFVpbnQ4QXJyYXk6ZmFsc2UsSFRNTEF1ZGlvRWxl
+bWVudDp0cnVlLEhUTUxCUkVsZW1lbnQ6dHJ1ZSxIVE1MQnV0dG9uRWxlbWVudDp0cnVlLEhUTUxDYW52
+YXNFbGVtZW50OnRydWUsSFRNTENvbnRlbnRFbGVtZW50OnRydWUsSFRNTERMaXN0RWxlbWVudDp0cnVl
+LEhUTUxEYXRhRWxlbWVudDp0cnVlLEhUTUxEYXRhTGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MRGV0YWlsc0Vs
+ZW1lbnQ6dHJ1ZSxIVE1MRGlhbG9nRWxlbWVudDp0cnVlLEhUTUxEaXZFbGVtZW50OnRydWUsSFRNTEVt
+YmVkRWxlbWVudDp0cnVlLEhUTUxGaWVsZFNldEVsZW1lbnQ6dHJ1ZSxIVE1MSFJFbGVtZW50OnRydWUs
+SFRNTEhlYWRFbGVtZW50OnRydWUsSFRNTEhlYWRpbmdFbGVtZW50OnRydWUsSFRNTEh0bWxFbGVtZW50
+OnRydWUsSFRNTElGcmFtZUVsZW1lbnQ6dHJ1ZSxIVE1MSW1hZ2VFbGVtZW50OnRydWUsSFRNTElucHV0
+RWxlbWVudDp0cnVlLEhUTUxMSUVsZW1lbnQ6dHJ1ZSxIVE1MTGFiZWxFbGVtZW50OnRydWUsSFRNTExl
+Z2VuZEVsZW1lbnQ6dHJ1ZSxIVE1MTGlua0VsZW1lbnQ6dHJ1ZSxIVE1MTWFwRWxlbWVudDp0cnVlLEhU
+TUxNZWRpYUVsZW1lbnQ6dHJ1ZSxIVE1MTWVudUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0YUVsZW1lbnQ6dHJ1
+ZSxIVE1MTWV0ZXJFbGVtZW50OnRydWUsSFRNTE1vZEVsZW1lbnQ6dHJ1ZSxIVE1MT0xpc3RFbGVtZW50
+OnRydWUsSFRNTE9iamVjdEVsZW1lbnQ6dHJ1ZSxIVE1MT3B0R3JvdXBFbGVtZW50OnRydWUsSFRNTE9w
+dGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MT3V0cHV0RWxlbWVudDp0cnVlLEhUTUxQYXJhbUVsZW1lbnQ6dHJ1
+ZSxIVE1MUGljdHVyZUVsZW1lbnQ6dHJ1ZSxIVE1MUHJlRWxlbWVudDp0cnVlLEhUTUxQcm9ncmVzc0Vs
+ZW1lbnQ6dHJ1ZSxIVE1MUXVvdGVFbGVtZW50OnRydWUsSFRNTFNjcmlwdEVsZW1lbnQ6dHJ1ZSxIVE1M
+U2hhZG93RWxlbWVudDp0cnVlLEhUTUxTbG90RWxlbWVudDp0cnVlLEhUTUxTb3VyY2VFbGVtZW50OnRy
+dWUsSFRNTFNwYW5FbGVtZW50OnRydWUsSFRNTFN0eWxlRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNhcHRp
+b25FbGVtZW50OnRydWUsSFRNTFRhYmxlQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVEYXRhQ2VsbEVs
+ZW1lbnQ6dHJ1ZSxIVE1MVGFibGVIZWFkZXJDZWxsRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNvbEVsZW1l
+bnQ6dHJ1ZSxIVE1MVGV4dEFyZWFFbGVtZW50OnRydWUsSFRNTFRpbWVFbGVtZW50OnRydWUsSFRNTFRp
+dGxlRWxlbWVudDp0cnVlLEhUTUxUcmFja0VsZW1lbnQ6dHJ1ZSxIVE1MVUxpc3RFbGVtZW50OnRydWUs
+SFRNTFVua25vd25FbGVtZW50OnRydWUsSFRNTFZpZGVvRWxlbWVudDp0cnVlLEhUTUxEaXJlY3RvcnlF
+bGVtZW50OnRydWUsSFRNTEZvbnRFbGVtZW50OnRydWUsSFRNTEZyYW1lRWxlbWVudDp0cnVlLEhUTUxG
+cmFtZVNldEVsZW1lbnQ6dHJ1ZSxIVE1MTWFycXVlZUVsZW1lbnQ6dHJ1ZSxIVE1MRWxlbWVudDpmYWxz
+ZSxIVE1MQW5jaG9yRWxlbWVudDp0cnVlLEhUTUxBcmVhRWxlbWVudDp0cnVlLEhUTUxCYXNlRWxlbWVu
+dDp0cnVlLEJsb2I6ZmFsc2UsSFRNTEJvZHlFbGVtZW50OnRydWUsQ0RBVEFTZWN0aW9uOnRydWUsQ2hh
+cmFjdGVyRGF0YTp0cnVlLENvbW1lbnQ6dHJ1ZSxQcm9jZXNzaW5nSW5zdHJ1Y3Rpb246dHJ1ZSxUZXh0
+OnRydWUsQ1NTU3R5bGVEZWNsYXJhdGlvbjp0cnVlLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOnRydWUsQ1NT
+MlByb3BlcnRpZXM6dHJ1ZSxYTUxEb2N1bWVudDp0cnVlLERvY3VtZW50OmZhbHNlLERPTUV4Y2VwdGlv
+bjp0cnVlLERPTVJlY3RSZWFkT25seTpmYWxzZSxET01Ub2tlbkxpc3Q6dHJ1ZSxFbGVtZW50OmZhbHNl
+LEFib3J0UGF5bWVudEV2ZW50OnRydWUsQW5pbWF0aW9uRXZlbnQ6dHJ1ZSxBbmltYXRpb25QbGF5YmFj
+a0V2ZW50OnRydWUsQXBwbGljYXRpb25DYWNoZUVycm9yRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hD
+bGlja0V2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hGYWls
+RXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hlZEV2ZW50OnRydWUsQmVmb3JlSW5zdGFsbFByb21wdEV2
+ZW50OnRydWUsQmVmb3JlVW5sb2FkRXZlbnQ6dHJ1ZSxCbG9iRXZlbnQ6dHJ1ZSxDYW5NYWtlUGF5bWVu
+dEV2ZW50OnRydWUsQ2xpcGJvYXJkRXZlbnQ6dHJ1ZSxDbG9zZUV2ZW50OnRydWUsQ3VzdG9tRXZlbnQ6
+dHJ1ZSxEZXZpY2VNb3Rpb25FdmVudDp0cnVlLERldmljZU9yaWVudGF0aW9uRXZlbnQ6dHJ1ZSxFcnJv
+ckV2ZW50OnRydWUsRXh0ZW5kYWJsZUV2ZW50OnRydWUsRXh0ZW5kYWJsZU1lc3NhZ2VFdmVudDp0cnVl
+LEZldGNoRXZlbnQ6dHJ1ZSxGb250RmFjZVNldExvYWRFdmVudDp0cnVlLEZvcmVpZ25GZXRjaEV2ZW50
+OnRydWUsR2FtZXBhZEV2ZW50OnRydWUsSGFzaENoYW5nZUV2ZW50OnRydWUsSW5zdGFsbEV2ZW50OnRy
+dWUsTWVkaWFFbmNyeXB0ZWRFdmVudDp0cnVlLE1lZGlhS2V5TWVzc2FnZUV2ZW50OnRydWUsTWVkaWFR
+dWVyeUxpc3RFdmVudDp0cnVlLE1lZGlhU3RyZWFtRXZlbnQ6dHJ1ZSxNZWRpYVN0cmVhbVRyYWNrRXZl
+bnQ6dHJ1ZSxNZXNzYWdlRXZlbnQ6dHJ1ZSxNSURJQ29ubmVjdGlvbkV2ZW50OnRydWUsTUlESU1lc3Nh
+Z2VFdmVudDp0cnVlLE11dGF0aW9uRXZlbnQ6dHJ1ZSxOb3RpZmljYXRpb25FdmVudDp0cnVlLFBhZ2VU
+cmFuc2l0aW9uRXZlbnQ6dHJ1ZSxQYXltZW50UmVxdWVzdEV2ZW50OnRydWUsUGF5bWVudFJlcXVlc3RV
+cGRhdGVFdmVudDp0cnVlLFBvcFN0YXRlRXZlbnQ6dHJ1ZSxQcmVzZW50YXRpb25Db25uZWN0aW9uQXZh
+aWxhYmxlRXZlbnQ6dHJ1ZSxQcmVzZW50YXRpb25Db25uZWN0aW9uQ2xvc2VFdmVudDp0cnVlLFByb21p
+c2VSZWplY3Rpb25FdmVudDp0cnVlLFB1c2hFdmVudDp0cnVlLFJUQ0RhdGFDaGFubmVsRXZlbnQ6dHJ1
+ZSxSVENEVE1GVG9uZUNoYW5nZUV2ZW50OnRydWUsUlRDUGVlckNvbm5lY3Rpb25JY2VFdmVudDp0cnVl
+LFJUQ1RyYWNrRXZlbnQ6dHJ1ZSxTZWN1cml0eVBvbGljeVZpb2xhdGlvbkV2ZW50OnRydWUsU2Vuc29y
+RXJyb3JFdmVudDp0cnVlLFNwZWVjaFJlY29nbml0aW9uRXJyb3I6dHJ1ZSxTcGVlY2hSZWNvZ25pdGlv
+bkV2ZW50OnRydWUsU3BlZWNoU3ludGhlc2lzRXZlbnQ6dHJ1ZSxTdG9yYWdlRXZlbnQ6dHJ1ZSxTeW5j
+RXZlbnQ6dHJ1ZSxUcmFja0V2ZW50OnRydWUsVHJhbnNpdGlvbkV2ZW50OnRydWUsV2ViS2l0VHJhbnNp
+dGlvbkV2ZW50OnRydWUsVlJEZXZpY2VFdmVudDp0cnVlLFZSRGlzcGxheUV2ZW50OnRydWUsVlJTZXNz
+aW9uRXZlbnQ6dHJ1ZSxNb2pvSW50ZXJmYWNlUmVxdWVzdEV2ZW50OnRydWUsVVNCQ29ubmVjdGlvbkV2
+ZW50OnRydWUsSURCVmVyc2lvbkNoYW5nZUV2ZW50OnRydWUsQXVkaW9Qcm9jZXNzaW5nRXZlbnQ6dHJ1
+ZSxPZmZsaW5lQXVkaW9Db21wbGV0aW9uRXZlbnQ6dHJ1ZSxXZWJHTENvbnRleHRFdmVudDp0cnVlLEV2
+ZW50OmZhbHNlLElucHV0RXZlbnQ6ZmFsc2UsRXZlbnRUYXJnZXQ6ZmFsc2UsRmlsZTp0cnVlLEhUTUxG
+b3JtRWxlbWVudDp0cnVlLEhpc3Rvcnk6dHJ1ZSxIVE1MRG9jdW1lbnQ6dHJ1ZSxYTUxIdHRwUmVxdWVz
+dDp0cnVlLFhNTEh0dHBSZXF1ZXN0RXZlbnRUYXJnZXQ6ZmFsc2UsSW1hZ2VEYXRhOnRydWUsTG9jYXRp
+b246dHJ1ZSxNb3VzZUV2ZW50OnRydWUsRHJhZ0V2ZW50OnRydWUsUG9pbnRlckV2ZW50OnRydWUsV2hl
+ZWxFdmVudDp0cnVlLERvY3VtZW50RnJhZ21lbnQ6dHJ1ZSxTaGFkb3dSb290OnRydWUsRG9jdW1lbnRU
+eXBlOnRydWUsTm9kZTpmYWxzZSxOb2RlTGlzdDp0cnVlLFJhZGlvTm9kZUxpc3Q6dHJ1ZSxIVE1MUGFy
+YWdyYXBoRWxlbWVudDp0cnVlLFByb2dyZXNzRXZlbnQ6dHJ1ZSxSZXNvdXJjZVByb2dyZXNzRXZlbnQ6
+dHJ1ZSxIVE1MU2VsZWN0RWxlbWVudDp0cnVlLEhUTUxUYWJsZUVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVS
+b3dFbGVtZW50OnRydWUsSFRNTFRhYmxlU2VjdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MVGVtcGxhdGVFbGVt
+ZW50OnRydWUsQ29tcG9zaXRpb25FdmVudDp0cnVlLEZvY3VzRXZlbnQ6dHJ1ZSxLZXlib2FyZEV2ZW50
+OnRydWUsVGV4dEV2ZW50OnRydWUsVG91Y2hFdmVudDp0cnVlLFVJRXZlbnQ6ZmFsc2UsV2luZG93OnRy
+dWUsRE9NV2luZG93OnRydWUsRGVkaWNhdGVkV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxTZXJ2aWNlV29y
+a2VyR2xvYmFsU2NvcGU6dHJ1ZSxTaGFyZWRXb3JrZXJHbG9iYWxTY29wZTp0cnVlLFdvcmtlckdsb2Jh
+bFNjb3BlOnRydWUsQXR0cjp0cnVlLENsaWVudFJlY3Q6dHJ1ZSxET01SZWN0OnRydWUsTmFtZWROb2Rl
+TWFwOnRydWUsTW96TmFtZWRBdHRyTWFwOnRydWUsSURCS2V5UmFuZ2U6dHJ1ZSxTVkdTY3JpcHRFbGVt
+ZW50OnRydWUsU1ZHQUVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVN
+b3Rpb25FbGVtZW50OnRydWUsU1ZHQW5pbWF0ZVRyYW5zZm9ybUVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRp
+b25FbGVtZW50OnRydWUsU1ZHQ2lyY2xlRWxlbWVudDp0cnVlLFNWR0NsaXBQYXRoRWxlbWVudDp0cnVl
+LFNWR0RlZnNFbGVtZW50OnRydWUsU1ZHRGVzY0VsZW1lbnQ6dHJ1ZSxTVkdEaXNjYXJkRWxlbWVudDp0
+cnVlLFNWR0VsbGlwc2VFbGVtZW50OnRydWUsU1ZHRkVCbGVuZEVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbG9y
+TWF0cml4RWxlbWVudDp0cnVlLFNWR0ZFQ29tcG9uZW50VHJhbnNmZXJFbGVtZW50OnRydWUsU1ZHRkVD
+b21wb3NpdGVFbGVtZW50OnRydWUsU1ZHRkVDb252b2x2ZU1hdHJpeEVsZW1lbnQ6dHJ1ZSxTVkdGRURp
+ZmZ1c2VMaWdodGluZ0VsZW1lbnQ6dHJ1ZSxTVkdGRURpc3BsYWNlbWVudE1hcEVsZW1lbnQ6dHJ1ZSxT
+VkdGRURpc3RhbnRMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRUZsb29kRWxlbWVudDp0cnVlLFNWR0ZFRnVu
+Y0FFbGVtZW50OnRydWUsU1ZHRkVGdW5jQkVsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNHRWxlbWVudDp0cnVl
+LFNWR0ZFRnVuY1JFbGVtZW50OnRydWUsU1ZHRkVHYXVzc2lhbkJsdXJFbGVtZW50OnRydWUsU1ZHRkVJ
+bWFnZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1lcmdlRWxlbWVudDp0cnVlLFNWR0ZFTWVyZ2VOb2RlRWxlbWVu
+dDp0cnVlLFNWR0ZFTW9ycGhvbG9neUVsZW1lbnQ6dHJ1ZSxTVkdGRU9mZnNldEVsZW1lbnQ6dHJ1ZSxT
+VkdGRVBvaW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVTcGVjdWxhckxpZ2h0aW5nRWxlbWVudDp0cnVl
+LFNWR0ZFU3BvdExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFVGlsZUVsZW1lbnQ6dHJ1ZSxTVkdGRVR1cmJ1
+bGVuY2VFbGVtZW50OnRydWUsU1ZHRmlsdGVyRWxlbWVudDp0cnVlLFNWR0ZvcmVpZ25PYmplY3RFbGVt
+ZW50OnRydWUsU1ZHR0VsZW1lbnQ6dHJ1ZSxTVkdHZW9tZXRyeUVsZW1lbnQ6dHJ1ZSxTVkdHcmFwaGlj
+c0VsZW1lbnQ6dHJ1ZSxTVkdJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdMaW5lRWxlbWVudDp0cnVlLFNWR0xp
+bmVhckdyYWRpZW50RWxlbWVudDp0cnVlLFNWR01hcmtlckVsZW1lbnQ6dHJ1ZSxTVkdNYXNrRWxlbWVu
+dDp0cnVlLFNWR01ldGFkYXRhRWxlbWVudDp0cnVlLFNWR1BhdGhFbGVtZW50OnRydWUsU1ZHUGF0dGVy
+bkVsZW1lbnQ6dHJ1ZSxTVkdQb2x5Z29uRWxlbWVudDp0cnVlLFNWR1BvbHlsaW5lRWxlbWVudDp0cnVl
+LFNWR1JhZGlhbEdyYWRpZW50RWxlbWVudDp0cnVlLFNWR1JlY3RFbGVtZW50OnRydWUsU1ZHU2V0RWxl
+bWVudDp0cnVlLFNWR1N0b3BFbGVtZW50OnRydWUsU1ZHU3R5bGVFbGVtZW50OnRydWUsU1ZHU1ZHRWxl
+bWVudDp0cnVlLFNWR1N3aXRjaEVsZW1lbnQ6dHJ1ZSxTVkdTeW1ib2xFbGVtZW50OnRydWUsU1ZHVFNw
+YW5FbGVtZW50OnRydWUsU1ZHVGV4dENvbnRlbnRFbGVtZW50OnRydWUsU1ZHVGV4dEVsZW1lbnQ6dHJ1
+ZSxTVkdUZXh0UGF0aEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0UG9zaXRpb25pbmdFbGVtZW50OnRydWUsU1ZH
+VGl0bGVFbGVtZW50OnRydWUsU1ZHVXNlRWxlbWVudDp0cnVlLFNWR1ZpZXdFbGVtZW50OnRydWUsU1ZH
+R3JhZGllbnRFbGVtZW50OnRydWUsU1ZHQ29tcG9uZW50VHJhbnNmZXJGdW5jdGlvbkVsZW1lbnQ6dHJ1
+ZSxTVkdGRURyb3BTaGFkb3dFbGVtZW50OnRydWUsU1ZHTVBhdGhFbGVtZW50OnRydWUsU1ZHRWxlbWVu
+dDpmYWxzZX0pCkguYjAuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5SRy4k
+bmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlZQLiRuYXRpdmVTdXBlcmNsYXNz
+VGFnPSJBcnJheUJ1ZmZlclZpZXciCkguRGcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVy
+VmlldyIKSC5XQi4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlpHLiRuYXRp
+dmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguUGcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9
+IkFycmF5QnVmZmVyVmlldyJ9KSgpCmNvbnZlcnRBbGxUb0Zhc3RPYmplY3QodykKY29udmVydFRvRmFz
+dE9iamVjdCgkKTsoZnVuY3Rpb24oYSl7aWYodHlwZW9mIGRvY3VtZW50PT09InVuZGVmaW5lZCIpe2Eo
+bnVsbCkKcmV0dXJufWlmKHR5cGVvZiBkb2N1bWVudC5jdXJyZW50U2NyaXB0IT0ndW5kZWZpbmVkJyl7
+YShkb2N1bWVudC5jdXJyZW50U2NyaXB0KQpyZXR1cm59dmFyIHQ9ZG9jdW1lbnQuc2NyaXB0cwpmdW5j
+dGlvbiBvbkxvYWQoYil7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDsrK3IpdFtyXS5yZW1vdmVFdmVudExp
+c3RlbmVyKCJsb2FkIixvbkxvYWQsZmFsc2UpCmEoYi50YXJnZXQpfWZvcih2YXIgcz0wO3M8dC5sZW5n
+dGg7KytzKXRbc10uYWRkRXZlbnRMaXN0ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNlKX0pKGZ1bmN0aW9u
+KGEpe3YuY3VycmVudFNjcmlwdD1hCmlmKHR5cGVvZiBkYXJ0TWFpblJ1bm5lcj09PSJmdW5jdGlvbiIp
+ZGFydE1haW5SdW5uZXIoTC5JcSxbXSkKZWxzZSBMLklxKFtdKX0pfSkoKQovLyMgc291cmNlTWFwcGlu
+Z1VSTD1taWdyYXRpb24uanMubWFwCg==
 ''';
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_renderer.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_renderer.dart
index f6f5d05..29267f3d 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_renderer.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/unit_renderer.dart
@@ -2,11 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:convert' show HtmlEscape, HtmlEscapeMode, jsonEncode, LineSplitter;
+import 'dart:convert' show HtmlEscape, HtmlEscapeMode, LineSplitter;
 
 import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/offset_mapper.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/web/file_details.dart';
 import 'package:path/path.dart' as path;
 
 /// Instrumentation display output for a library that was migrated to use
@@ -35,27 +36,21 @@
   path.Context get pathContext => migrationInfo.pathContext;
 
   /// Builds a JSON view of the instrumentation information in [unitInfo].
-  String render() {
-    // TODO(devoncarew): Both _computeNavigationContent() and
-    // _computeRegionContent() send html back to the client; convert this to
-    // instead sending data back (instead of presentation).
-    Map<String, dynamic> response = {
-      'regions': _computeRegionContent(unitInfo),
-      'navigationContent': _computeNavigationContent(),
-      'sourceCode': unitInfo.content,
-      'edits': _computeEditList(),
-    };
-    return jsonEncode(response);
+  FileDetails render() {
+    return FileDetails(
+        regions: _computeRegionContent(unitInfo),
+        navigationContent: _computeNavigationContent(),
+        sourceCode: unitInfo.content,
+        edits: _computeEditList());
   }
 
   /// Returns the list of edits, as JSON.
-  List<Map<String, dynamic>> _computeEditList() {
+  List<EditListItem> _computeEditList() {
     return unitInfo.fixRegions.map((RegionInfo region) {
-      return {
-        'line': region.lineNumber,
-        'explanation': region.explanation,
-        'offset': region.offset,
-      };
+      return EditListItem(
+          line: region.lineNumber,
+          explanation: region.explanation,
+          offset: region.offset);
     }).toList();
   }
 
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/file_details.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/file_details.dart
new file mode 100644
index 0000000..7d0276f
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/file_details.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+/// Information about an item that should show up in the "proposed edits" panel.
+class EditListItem {
+  /// Line number of this edit.
+  final int line;
+
+  /// Human-readable explanation of this edit.
+  final String explanation;
+
+  /// File offset of this edit
+  final int offset;
+
+  EditListItem(
+      {@required this.line, @required this.explanation, @required this.offset});
+
+  EditListItem.fromJson(dynamic json)
+      : line = json['line'],
+        explanation = json['explanation'],
+        offset = json['offset'];
+
+  Map<String, Object> toJson() =>
+      {'line': line, 'explanation': explanation, 'offset': offset};
+}
+
+/// Information about how a single file should be migrated.
+class FileDetails {
+  /// HTML representation of the source file with spans added to represent
+  /// added, removed, and unchanged file regions.
+  ///
+  /// TODO(paulberry): this should be replaced by a more neutral data structure.
+  final String regions;
+
+  /// HTML representation of the source file with links added to allow
+  /// navigation through source files.
+  ///
+  /// TODO(paulberry): this should be replaced by a more neutral data structure.
+  final String navigationContent;
+
+  /// Textual representation of the source file, including both added and
+  /// removed text.
+  final String sourceCode;
+
+  /// Items that should show up in the "proposed edits" panel for the file.
+  final List<EditListItem> edits;
+
+  FileDetails(
+      {@required this.regions,
+      @required this.navigationContent,
+      @required this.sourceCode,
+      @required this.edits});
+
+  FileDetails.empty()
+      : regions = '',
+        navigationContent = '',
+        sourceCode = '',
+        edits = const [];
+
+  FileDetails.fromJson(dynamic json)
+      : regions = json['regions'],
+        navigationContent = json['navigationContent'],
+        sourceCode = json['sourceCode'],
+        edits = [for (var edit in json['edits']) EditListItem.fromJson(edit)];
+
+  Map<String, Object> toJson() => {
+        'regions': regions,
+        'navigationContent': navigationContent,
+        'sourceCode': sourceCode,
+        'edits': [for (var edit in edits) edit.toJson()]
+      };
+}
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/migration.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/migration.dart
index 73e4329..e72631a 100644
--- a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/migration.dart
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/migration.dart
@@ -7,6 +7,8 @@
 import 'dart:html';
 
 import 'package:analysis_server/src/edit/nnbd_migration/web/edit_details.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/web/file_details.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/web/navigation_tree.dart';
 import 'package:path/path.dart' as _p;
 
 import 'highlight_js.dart';
@@ -50,11 +52,7 @@
       loadFile(path, offset, lineNumber);
     } else {
       // Blank out the page, for the index screen.
-      writeCodeAndRegions(path, {
-        'regions': '',
-        'navigationContent': '',
-        'edits': [],
-      });
+      writeCodeAndRegions(path, FileDetails.empty());
       updatePage('&nbsp;', null);
     }
   });
@@ -166,19 +164,26 @@
   event.preventDefault();
 }
 
-void handlePostLinkClick(MouseEvent event) {
+void handlePostLinkClick(MouseEvent event) async {
   String path = (event.currentTarget as Element).getAttribute('href');
 
-  // Directing the server to produce an edit; request it, then do work with the
-  // response.
-  doPost(path).catchError((e, st) {
-    logError('handlePostLinkClick: $e', st);
-
-    window.alert('Could not load $path ($e).');
-  });
-
   // Don't navigate on link click.
   event.preventDefault();
+
+  document.body.classes.add('rerunning');
+
+  try {
+    // Directing the server to produce an edit; request it, then do work with the
+    // response.
+    await doPost(path);
+    (document.window.location as Location).reload();
+  } catch (e, st) {
+    logError('handlePostLinkClick: $e', st);
+
+    window.alert('Could not load $path ($e).');
+  } finally {
+    document.body.classes.remove('rerunning');
+  }
 }
 
 void highlightAllCode() {
@@ -218,11 +223,7 @@
 }) {
   // Handle the case where we're requesting a directory.
   if (!path.endsWith('.dart')) {
-    writeCodeAndRegions(path, {
-      'regions': '',
-      'navigationContent': '',
-      'edits': [],
-    });
+    writeCodeAndRegions(path, FileDetails.empty());
     updatePage(path);
     if (callback != null) {
       callback();
@@ -238,7 +239,7 @@
   ).then((HttpRequest xhr) {
     if (xhr.status == 200) {
       Map<String, dynamic> response = jsonDecode(xhr.responseText);
-      writeCodeAndRegions(path, response);
+      writeCodeAndRegions(path, FileDetails.fromJson(response));
       maybeScrollToAndHighlight(offset, line);
       String filePathPart =
           path.contains('?') ? path.substring(0, path.indexOf('?')) : path;
@@ -269,7 +270,8 @@
       dynamic response = jsonDecode(xhr.responseText);
       var navTree = document.querySelector('.nav-tree');
       navTree.innerHtml = '';
-      writeNavigationSubtree(navTree, response);
+      writeNavigationSubtree(
+          navTree, NavigationTreeNode.listFromJson(response));
     } else {
       window.alert('Request failed; status of ${xhr.status}');
     }
@@ -433,7 +435,7 @@
 }
 
 /// Write the contents of the Edit List, from JSON data [editListData].
-void populateProposedEdits(String path, List<dynamic> edits) {
+void populateProposedEdits(String path, List<EditListItem> edits) {
   Element editListElement = document.querySelector('.edit-list .panel-content');
   editListElement.innerHtml = '';
 
@@ -446,14 +448,14 @@
   }
 
   Element list = editListElement.append(document.createElement('ul'));
-  for (Map<String, dynamic> edit in edits) {
+  for (var edit in edits) {
     Element item = list.append(document.createElement('li'));
     item.classes.add('edit');
     AnchorElement anchor = item.append(document.createElement('a'));
     anchor.classes.add('edit-link');
-    int offset = edit['offset'];
+    int offset = edit.offset;
     anchor.dataset['offset'] = '$offset';
-    int line = edit['line'];
+    int line = edit.line;
     anchor.dataset['line'] = '$line';
     anchor.append(Text('line $line'));
     anchor.onClick.listen((MouseEvent event) {
@@ -462,7 +464,7 @@
       });
       loadAndPopulateEditDetails(path, offset);
     });
-    item.append(Text(': ${edit['explanation']}'));
+    item.append(Text(': ${edit.explanation}'));
   }
 
   // Clear out any existing edit details.
@@ -527,42 +529,43 @@
 }
 
 /// Load data from [data] into the .code and the .regions divs.
-void writeCodeAndRegions(String path, Map<String, dynamic> data) {
+void writeCodeAndRegions(String path, FileDetails data) {
   Element regionsElement = document.querySelector('.regions');
   Element codeElement = document.querySelector('.code');
 
-  _PermissiveNodeValidator.setInnerHtml(regionsElement, data['regions']);
-  _PermissiveNodeValidator.setInnerHtml(codeElement, data['navigationContent']);
-  populateProposedEdits(path, data['edits']);
+  _PermissiveNodeValidator.setInnerHtml(regionsElement, data.regions);
+  _PermissiveNodeValidator.setInnerHtml(codeElement, data.navigationContent);
+  populateProposedEdits(path, data.edits);
 
   highlightAllCode();
   addClickHandlers('.code');
   addClickHandlers('.regions');
 }
 
-void writeNavigationSubtree(Element parentElement, dynamic tree) {
+void writeNavigationSubtree(
+    Element parentElement, List<NavigationTreeNode> tree) {
   Element ul = parentElement.append(document.createElement('ul'));
   for (var entity in tree) {
     Element li = ul.append(document.createElement('li'));
-    if (entity['type'] == 'directory') {
+    if (entity.type == NavigationTreeNodeType.directory) {
       li.classes.add('dir');
       Element arrow = li.append(document.createElement('span'));
       arrow.classes.add('arrow');
       arrow.innerHtml = '&#x25BC;';
       Element icon = li.append(document.createElement('span'));
       icon.innerHtml = '&#x1F4C1;';
-      li.append(Text(entity['name']));
-      writeNavigationSubtree(li, entity['subtree']);
+      li.append(Text(entity.name));
+      writeNavigationSubtree(li, entity.subtree);
       addArrowClickHandler(arrow);
     } else {
       li.innerHtml = '&#x1F4C4;';
       Element a = li.append(document.createElement('a'));
       a.classes.add('nav-link');
-      a.dataset['name'] = entity['path'];
-      a.setAttribute('href', entity['href']);
-      a.append(Text(entity['name']));
+      a.dataset['name'] = entity.path;
+      a.setAttribute('href', entity.href);
+      a.append(Text(entity.name));
       a.onClick.listen(handleNavLinkClick);
-      int editCount = entity['editCount'];
+      int editCount = entity.editCount;
       if (editCount > 0) {
         Element editsBadge = li.append(document.createElement('span'));
         editsBadge.classes.add('edit-count');
diff --git a/pkg/analysis_server/lib/src/edit/nnbd_migration/web/navigation_tree.dart b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/navigation_tree.dart
new file mode 100644
index 0000000..096574d
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/nnbd_migration/web/navigation_tree.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+/// Information about a node in the migration tool's navigation tree.
+class NavigationTreeNode {
+  /// Type of the node.
+  final NavigationTreeNodeType type;
+
+  /// Name of the node.
+  final String name;
+
+  /// If this is a directory node, list of nodes nested under this one.
+  /// Otherwise `null`.
+  final List<NavigationTreeNode> subtree;
+
+  /// If this is a file node, full path to the file.  Otherwise `null`.
+  final String path;
+
+  /// If this is a file node, href that should be used if the file is clicked
+  /// on, otherwise `null`.
+  final String href;
+
+  /// If this is a file node, number of edits that were made in the file,
+  /// otherwise `null`.
+  final int editCount;
+
+  /// Creates a navigation tree node representing a directory.
+  NavigationTreeNode.directory({@required this.name, @required this.subtree})
+      : type = NavigationTreeNodeType.directory,
+        path = null,
+        href = null,
+        editCount = null;
+
+  /// Creates a navigation tree node representing a file.
+  NavigationTreeNode.file(
+      {@required this.name,
+      @required this.path,
+      @required this.href,
+      @required this.editCount})
+      : type = NavigationTreeNodeType.file,
+        subtree = null;
+
+  NavigationTreeNode.fromJson(dynamic json)
+      : type = _decodeType(json['type']),
+        name = json['name'],
+        subtree = listFromJsonOrNull(json['subtree']),
+        path = json['path'],
+        href = json['href'],
+        editCount = json['editCount'];
+
+  Map<String, Object> toJson() => {
+        'type': _encodeType(type),
+        'name': name,
+        if (subtree != null) 'subtree': listToJson(subtree),
+        if (path != null) 'path': path,
+        if (href != null) 'href': href,
+        if (editCount != null) 'editCount': editCount
+      };
+
+  /// Deserializes a list of navigation tree nodes from a JSON list.
+  static List<NavigationTreeNode> listFromJson(dynamic json) =>
+      [for (var node in json) NavigationTreeNode.fromJson(node)];
+
+  /// Deserializes a list of navigation tree nodes from a possibly null JSON
+  /// list.  If the argument is `null`, `null` is returned.
+  static List<NavigationTreeNode> listFromJsonOrNull(dynamic json) =>
+      json == null ? null : listFromJson(json);
+
+  /// Serializes a list of navigation tree nodes into JSON.
+  static List<Map<String, Object>> listToJson(List<NavigationTreeNode> nodes) =>
+      [for (var node in nodes) node.toJson()];
+
+  static NavigationTreeNodeType _decodeType(String json) {
+    switch (json) {
+      case 'directory':
+        return NavigationTreeNodeType.directory;
+      case 'file':
+        return NavigationTreeNodeType.file;
+      default:
+        throw StateError('Unrecognized navigation tree node type: $json');
+    }
+  }
+
+  static String _encodeType(NavigationTreeNodeType type) {
+    switch (type) {
+      case NavigationTreeNodeType.directory:
+        return 'directory';
+      case NavigationTreeNodeType.file:
+        return 'file';
+    }
+    throw StateError('Unrecognized navigation tree node type: $type');
+  }
+}
+
+/// Enum representing the different types of [NavigationTreeNode]s.
+enum NavigationTreeNodeType {
+  directory,
+  file,
+}
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
index cc5a8d8..bc67bd5 100644
--- a/pkg/analysis_server/lib/src/edit/preview/dart_file_page.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/dart_file_page.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:convert';
+
 import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/unit_renderer.dart';
 import 'package:analysis_server/src/edit/preview/preview_page.dart';
@@ -28,6 +30,6 @@
   Future<void> generatePage(Map<String, String> params) async {
     UnitRenderer renderer =
         UnitRenderer(unitInfo, site.migrationInfo, site.pathMapper);
-    buf.write(renderer.render());
+    buf.write(jsonEncode(renderer.render().toJson()));
   }
 }
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
index b0002cb..a554c67 100644
--- a/pkg/analysis_server/lib/src/edit/preview/http_preview_server.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/http_preview_server.dart
@@ -26,17 +26,17 @@
   /// The state of the migration being previewed.
   final MigrationState migrationState;
 
-  /// An object that can handle GET requests.
-  AbstractGetHandler getHandler;
-
-  /// An object that can handle POST requests.
-  AbstractPostHandler postHandler;
+  /// The [PreviewSite] that can handle GET and POST requests.
+  PreviewSite previewSite;
 
   /// Future that is completed with the HTTP server once it is running.
   Future<HttpServer> _serverFuture;
 
+  // A function which allows the migration to be rerun, taking changed paths.
+  final Future<MigrationState> Function(List<String>) rerunFunction;
+
   /// Initialize a newly created HTTP server.
-  HttpPreviewServer(this.migrationState);
+  HttpPreviewServer(this.migrationState, this.rerunFunction);
 
   /// Return the port this server is bound to.
   Future<int> get boundPort async {
@@ -73,14 +73,14 @@
 
   /// Handle a GET request received by the HTTP server.
   Future<void> _handleGetRequest(HttpRequest request) async {
-    getHandler ??= PreviewSite(migrationState);
-    await getHandler.handleGetRequest(request);
+    previewSite ??= PreviewSite(migrationState, rerunFunction);
+    await previewSite.handleGetRequest(request);
   }
 
   /// Handle a POST request received by the HTTP server.
   Future<void> _handlePostRequest(HttpRequest request) async {
-    postHandler ??= PreviewSite(migrationState);
-    await postHandler.handlePostRequest(request);
+    previewSite ??= PreviewSite(migrationState, rerunFunction);
+    await previewSite.handlePostRequest(request);
   }
 
   /// Attach a listener to a newly created HTTP server.
diff --git a/pkg/analysis_server/lib/src/edit/preview/navigation_tree_page.dart b/pkg/analysis_server/lib/src/edit/preview/navigation_tree_page.dart
index 7a8d2f1..9cfc42e 100644
--- a/pkg/analysis_server/lib/src/edit/preview/navigation_tree_page.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/navigation_tree_page.dart
@@ -2,7 +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';
+
 import 'package:analysis_server/src/edit/nnbd_migration/navigation_tree_renderer.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/web/navigation_tree.dart';
 import 'package:analysis_server/src/edit/preview/preview_page.dart';
 import 'package:analysis_server/src/edit/preview/preview_site.dart';
 
@@ -22,6 +25,6 @@
   @override
   Future<void> generatePage(Map<String, String> params) async {
     var renderer = NavigationTreeRenderer(site.migrationInfo, site.pathMapper);
-    buf.write(renderer.render());
+    buf.write(jsonEncode(NavigationTreeNode.listToJson(renderer.render())));
   }
 }
diff --git a/pkg/analysis_server/lib/src/edit/preview/preview_site.dart b/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
index 302c5ee..60efa22 100644
--- a/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
+++ b/pkg/analysis_server/lib/src/edit/preview/preview_site.dart
@@ -36,33 +36,20 @@
   static const applyMigrationPath = '/apply-migration';
 
   /// The state of the migration being previewed.
-  final MigrationState migrationState;
+  MigrationState migrationState;
 
   /// A table mapping the paths of files to the information about the
   /// compilation units at those paths.
   final Map<String, UnitInfo> unitInfoMap = {};
 
+  // A function provided by DartFix to rerun the migration.
+  final Future<MigrationState> Function(List<String>) rerunFunction;
+
   /// Initialize a newly created site to serve a preview of the results of an
   /// NNBD migration.
-  PreviewSite(this.migrationState) : 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;
-      }
-    }
+  PreviewSite(this.migrationState, this.rerunFunction)
+      : super('NNBD Migration Preview') {
+    reset();
   }
 
   /// Return the information about the migration that will be used to serve up
@@ -158,7 +145,7 @@
         respondOk(request);
         return;
       } else if (uri.queryParameters.containsKey('replacement')) {
-        performEdit(uri);
+        await performEdit(uri);
 
         respondOk(request);
         return;
@@ -187,7 +174,7 @@
   }
 
   /// Perform the edit indicated by the [uri].
-  void performEdit(Uri uri) {
+  Future<void> performEdit(Uri uri) async {
     //
     // Update the code on disk.
     //
@@ -200,19 +187,34 @@
     String oldContent = file.readAsStringSync();
     String newContent = oldContent.replaceRange(offset, end, replacement);
     file.writeAsStringSync(newContent);
-    //
-    // Update the graph by adding or removing an edge.
-    //
-    int length = end - offset;
-    if (length == 0) {
-      throw UnsupportedError('Implement insertions');
-    } else {
-      throw UnsupportedError('Implement removals');
+    await rerunMigration([path]);
+  }
+
+  Future<void> rerunMigration(List<String> changedPaths) async {
+    migrationState = await rerunFunction(changedPaths);
+    reset();
+  }
+
+  void reset() {
+    unitInfoMap.clear();
+    Set<UnitInfo> unitInfos = migrationInfo.units;
+    ResourceProvider provider = pathMapper.provider;
+    for (UnitInfo unit in unitInfos) {
+      unitInfoMap[unit.path] = unit;
     }
-    //
-    // Refresh the state of the migration.
-    //
-    //migrationState.refresh();
+    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
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index e3c4e69..5e20c2b 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:analysis_server/src/provisional/completion/completion_core.dart';
+import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -16,10 +17,8 @@
 
 export 'package:analyzer_plugin/utilities/completion/relevance.dart';
 
-/// An object used to produce completions
-/// at a specific location within a Dart file.
-///
-/// Clients may implement this class when implementing plugins.
+/// An object that contributes results for the `completion.getSuggestions`
+/// request results.
 abstract class DartCompletionContributor {
   /// Return a [Future] that completes with a list of suggestions
   /// for the given completion [request].
@@ -31,10 +30,18 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class DartCompletionRequest extends CompletionRequest {
+  /// Return the type imposed on the target's `containingNode` based on its
+  /// context, or `null` if the context does not impose any type.
+  DartType get contextType;
+
   /// Return the expression to the right of the "dot" or "dot dot",
   /// or `null` if this is not a "dot" completion (e.g. `foo.b`).
   Expression get dotTarget;
 
+  /// Return the object used to compute the values of the features used to
+  /// compute relevance scores for suggestions.
+  FeatureComputer get featureComputer;
+
   /// Return the feature set that was used to analyze the compilation unit in
   /// which suggestions are being made.
   FeatureSet get featureSet;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index a0bacfb..d403ef5 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -16,6 +16,7 @@
 import 'package:analysis_server/src/services/completion/dart/completion_ranking.dart';
 import 'package:analysis_server/src/services/completion/dart/contribution_sorter.dart';
 import 'package:analysis_server/src/services/completion/dart/extension_member_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
 import 'package:analysis_server/src/services/completion/dart/field_formal_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/inherited_reference_contributor.dart';
@@ -211,7 +212,7 @@
                 stackTrace));
         await contributionSorter.sort(dartRequest, suggestions);
       }
-    } else {
+    } else if (!request.useNewRelevance) {
       await contributionSorter.sort(dartRequest, suggestions);
     }
     performance.logElapseTime(SORT_TAG);
@@ -370,6 +371,15 @@
 
   OpType _opType;
 
+  @override
+  final FeatureComputer featureComputer;
+
+  /// A flag indicating whether the [_contextType] has been computed.
+  bool _hasComputedContextType = false;
+
+  /// The context type associated with the target's `containingNode`.
+  DartType _contextType;
+
   final CompletionRequest _originalRequest;
 
   final CompletionPerformance performance;
@@ -383,11 +393,22 @@
       this.offset,
       CompilationUnit unit,
       this._originalRequest,
-      this.performance) {
+      this.performance)
+      : featureComputer =
+            FeatureComputer(result.typeSystem, result.typeProvider) {
     _updateTargets(unit);
   }
 
   @override
+  DartType get contextType {
+    if (!_hasComputedContextType) {
+      _contextType = featureComputer.computeContextType(target.containingNode);
+      _hasComputedContextType = true;
+    }
+    return _contextType;
+  }
+
+  @override
   FeatureSet get featureSet =>
       result.session.analysisContext.analysisOptions.contextFeatures;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index 901d588..93f984f 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -14,10 +14,11 @@
 import 'package:analyzer/src/dart/element/type.dart';
 
 /// Convert a relevance score (assumed to be between `0.0` and `1.0` inclusive)
-/// to a relevance value between `0` and `1000`.
-int toRelevance(double score) {
-  if (score < 0.0) {
-    return 0;
+/// to a relevance value between `0` and `1000`. If the score is outside that
+/// range, return the [defaultValue].
+int toRelevance(double score, int defaultValue) {
+  if (score < 0.0 || score > 1.0) {
+    return defaultValue;
   }
   return (score * 1000).truncate();
 }
@@ -58,8 +59,6 @@
   /// Return the type imposed on the given [node] based on its context, or
   /// `null` if the context does not impose any type.
   DartType computeContextType(AstNode node) {
-    // This method is only visible for the metrics computation and might be made
-    // private at some future date.
     var type = node.parent?.accept(_ContextTypeVisitor(typeProvider, node));
     if (type == null || type.isDynamic) {
       return null;
@@ -70,12 +69,9 @@
   /// Return the value of the _context type_ feature for an element with the
   /// given [elementType] when completing in a location with the given
   /// [contextType].
-  double contextTypeFeature(AstNode node, DartType elementType) {
-    if (elementType == null) {
-      return -1.0;
-    }
-    var contextType = computeContextType(node);
-    if (contextType == null) {
+  double contextTypeFeature(DartType contextType, DartType elementType) {
+    if (contextType == null || elementType == null) {
+      // Disable the feature if we don't have both types.
       return -1.0;
     }
     if (elementType == contextType) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
index e703015..f88d1ae7 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
@@ -4,34 +4,34 @@
 
 import 'dart:async';
 
+import 'package:analysis_server/src/protocol_server.dart'
+    show CompletionSuggestion;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.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/dart/element/visitor.dart';
 
-import '../../../protocol_server.dart' show CompletionSuggestion;
-
-/// A contributor for calculating static member invocation / access suggestions
-/// `completion.getSuggestions` request results.
+/// A contributor that produces suggestions based on the static members of a
+/// given class, enum, or extension. More concretely, this class produces
+/// suggestions for expressions of the form `C.^`, where `C` is the name of a
+/// class, enum, or extension.
 class StaticMemberContributor extends DartCompletionContributor {
   @override
   Future<List<CompletionSuggestion>> computeSuggestions(
       DartCompletionRequest request) async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     Expression targetId = request.dotTarget;
     if (targetId is Identifier && !request.target.isCascade) {
       Element elem = targetId.staticElement;
       if (elem is ClassElement || elem is ExtensionElement) {
-        LibraryElement containingLibrary = request.libraryElement;
-        // Gracefully degrade if the library could not be determined
-        // e.g. detached part file or source change
-        if (containingLibrary == null) {
+        if (request.libraryElement == null) {
+          // Gracefully degrade if the library could not be determined, such as
+          // a detached part file or source change.
           return const <CompletionSuggestion>[];
         }
-
-        _SuggestionBuilder builder = _SuggestionBuilder(containingLibrary);
+        _SuggestionBuilder builder = _SuggestionBuilder(request);
         elem.accept(builder);
         return builder.suggestions;
       }
@@ -40,16 +40,17 @@
   }
 }
 
-/// This class visits elements in a class and provides suggestions based upon
-/// the visible static members in that class.
-class _SuggestionBuilder extends GeneralizingElementVisitor<void> {
-  /// The library containing the unit in which the completion is requested.
-  final LibraryElement containingLibrary;
+/// This class visits elements in a class or extension and provides suggestions
+/// based on the visible static members in that class.
+class _SuggestionBuilder extends SimpleElementVisitor<void> {
+  /// Information about the completion being requested.
+  final DartCompletionRequest request;
 
   /// A collection of completion suggestions.
   final List<CompletionSuggestion> suggestions = <CompletionSuggestion>[];
 
-  _SuggestionBuilder(this.containingLibrary);
+  /// Initialize a newly created suggestion builder.
+  _SuggestionBuilder(this.request);
 
   @override
   void visitClassElement(ClassElement element) {
@@ -58,12 +59,7 @@
 
   @override
   void visitConstructorElement(ConstructorElement element) {
-    _addSuggestion(element);
-  }
-
-  @override
-  void visitElement(Element element) {
-    // ignored
+    _addSuggestion(element, element.returnType);
   }
 
   @override
@@ -74,34 +70,34 @@
   @override
   void visitFieldElement(FieldElement element) {
     if (element.isStatic) {
-      _addSuggestion(element);
+      _addSuggestion(element, element.type);
     }
   }
 
   @override
   void visitMethodElement(MethodElement element) {
     if (element.isStatic && !element.isOperator) {
-      _addSuggestion(element);
+      _addSuggestion(element, element.returnType);
     }
   }
 
   @override
   void visitPropertyAccessorElement(PropertyAccessorElement element) {
     if (element.isStatic) {
-      _addSuggestion(element);
+      _addSuggestion(element, element.returnType);
     }
   }
 
-  /// Add a suggestion based upon the given element.
-  void _addSuggestion(Element element) {
+  /// Add a suggestion based on the given [element].
+  void _addSuggestion(Element element, DartType elementType) {
     if (element.isPrivate) {
-      if (element.library != containingLibrary) {
-        // Do not suggest private members for imported libraries
+      if (element.library != request.libraryElement) {
+        // Don't suggest private members for imported libraries.
         return;
       }
     }
     if (element.isSynthetic) {
-      if ((element is PropertyAccessorElement) ||
+      if (element is PropertyAccessorElement ||
           element is FieldElement && !_isSpecialEnumField(element)) {
         return;
       }
@@ -110,21 +106,25 @@
     if (completion == null || completion.isEmpty) {
       return;
     }
+    var relevance = DART_RELEVANCE_DEFAULT;
+    if (request.useNewRelevance) {
+      var contextType = request.featureComputer
+          .contextTypeFeature(request.contextType, elementType);
+      relevance = toRelevance(contextType, 500);
+    }
     CompletionSuggestion suggestion =
-        createSuggestion(element, completion: completion);
+        createSuggestion(element, completion: completion, relevance: relevance);
     if (suggestion != null) {
       suggestions.add(suggestion);
     }
   }
 
-  /// Determine if the given element is one of the synthetic enum accessors
+  /// Determine whether the [element] is one of the synthetic enum accessors
   /// for which we should generate a suggestion.
   bool _isSpecialEnumField(FieldElement element) {
     Element parent = element.enclosingElement;
     if (parent is ClassElement && parent.isEnum) {
-      if (element.name == 'values') {
-        return true;
-      }
+      return element.name == 'values';
     }
     return false;
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index 5325ebd..096051b 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -5,6 +5,8 @@
 import 'dart:async';
 import 'dart:collection';
 
+import 'package:analysis_server/src/protocol_server.dart'
+    show CompletionSuggestion, CompletionSuggestionKind;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
@@ -15,11 +17,11 @@
 import 'package:analyzer_plugin/src/utilities/visitors/local_declaration_visitor.dart';
 import 'package:meta/meta.dart';
 
-import '../../../protocol_server.dart'
-    show CompletionSuggestion, CompletionSuggestionKind;
-
-/// A contributor for calculating instance invocation / access suggestions
-/// `completion.getSuggestions` request results.
+/// A contributor that produces suggestions based on the instance members of a
+/// given type, whether declared by that type directly or inherited from a
+/// superinterface. More concretely, this class produces suggestions for
+/// expressions of the form `o.^`, where `o` is an expression denoting an
+/// instance of a type.
 class TypeMemberContributor extends DartCompletionContributor {
   @override
   Future<List<CompletionSuggestion>> computeSuggestions(
@@ -257,8 +259,7 @@
     if (superclassConstraints != null) {
       types.addAll(superclassConstraints);
     }
-    var featureComputer =
-        FeatureComputer(request.result.typeSystem, request.result.typeProvider);
+    var featureComputer = request.featureComputer;
     for (InterfaceType targetType in types) {
       var inheritanceDistance = featureComputer.inheritanceDistanceFeature(
           type.element, targetType.element);
@@ -270,7 +271,7 @@
           int relevance;
           if (request.useNewRelevance) {
             var contextType = featureComputer.contextTypeFeature(
-                request.target.containingNode, method.returnType);
+                request.contextType, method.returnType);
             var startsWithDollar =
                 featureComputer.startsWithDollarFeature(method.name);
             var superMatches = featureComputer.superMatchesFeature(
@@ -297,7 +298,7 @@
               int relevance;
               if (request.useNewRelevance) {
                 var contextType = featureComputer.contextTypeFeature(
-                    request.target.containingNode, variable.type);
+                    request.contextType, variable.type);
                 var startsWithDollar = featureComputer
                     .startsWithDollarFeature(propertyAccessor.name);
                 var superMatches = featureComputer.superMatchesFeature(
@@ -316,8 +317,8 @@
                 : propertyAccessor.parameters[0].type;
             int relevance;
             if (request.useNewRelevance) {
-              var contextType = featureComputer.contextTypeFeature(
-                  request.target.containingNode, type);
+              var contextType =
+                  featureComputer.contextTypeFeature(request.contextType, type);
               var startsWithDollar = featureComputer
                   .startsWithDollarFeature(propertyAccessor.name);
               var superMatches = featureComputer.superMatchesFeature(
@@ -352,9 +353,10 @@
       @required double inheritanceDistance,
       @required double startsWithDollar,
       @required double superMatches}) {
-    return toRelevance(weightedAverage(
+    var score = weightedAverage(
         [contextType, inheritanceDistance, startsWithDollar, superMatches],
-        [1.0, 1.0, 0.5, 1.0]));
+        [1.0, 1.0, 0.5, 1.0]);
+    return toRelevance(score, 500);
   }
 
   /// Get a list of [InterfaceType]s that should be searched to find the
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/inline_typedef.dart b/pkg/analysis_server/lib/src/services/correction/dart/inline_typedef.dart
index a1534d0..fdb48cc 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/inline_typedef.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/inline_typedef.dart
@@ -28,20 +28,19 @@
     TypeAnnotation returnType;
     TypeParameterList typeParameters;
     List<FormalParameter> parameters;
-    if (node is FunctionTypeAlias) {
-      var typedef = node as FunctionTypeAlias;
-      returnType = typedef.returnType;
-      name = typedef.name.name;
-      typeParameters = typedef.typeParameters;
-      parameters = typedef.parameters.parameters;
-    } else if (node is GenericTypeAlias) {
-      var typedef = node as GenericTypeAlias;
-      if (typedef.typeParameters != null) {
+    var parent = node.parent;
+    if (parent is FunctionTypeAlias) {
+      returnType = parent.returnType;
+      name = parent.name.name;
+      typeParameters = parent.typeParameters;
+      parameters = parent.parameters.parameters;
+    } else if (parent is GenericTypeAlias) {
+      if (parent.typeParameters != null) {
         return;
       }
-      var functionType = typedef.functionType;
+      var functionType = parent.functionType;
       returnType = functionType.returnType;
-      name = typedef.name.name;
+      name = parent.name.name;
       typeParameters = functionType.typeParameters;
       parameters = functionType.parameters.parameters;
     } else {
@@ -57,7 +56,7 @@
     // Build the edit.
     //
     await builder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addDeletion(utils.getLinesRange(range.node(node)));
+      builder.addDeletion(utils.getLinesRange(range.node(parent)));
       builder.addReplacement(range.node(finder.reference),
           (DartEditBuilder builder) {
         if (returnType != null) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart
new file mode 100644
index 0000000..f21548a
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_interpolation.dart
@@ -0,0 +1,190 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+import 'package:meta/meta.dart';
+
+class ReplaceWithInterpolation extends CorrectionProducer {
+  @override
+  FixKind get fixKind => DartFixKind.REPLACE_WITH_INTERPOLATION;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    //
+    // Validate the fix.
+    //
+    BinaryExpression binary;
+    var parent = node.parent;
+    while (_isStringConcatenation(parent)) {
+      binary = parent;
+      parent = parent.parent;
+    }
+    if (binary == null) {
+      return;
+    }
+    //
+    // Extract the information needed to build the edit.
+    //
+    var components = <AstNode>[];
+    var style = _extractComponentsInto(binary, components);
+    if (style.isInvalid || style.isUnknown || style.isRaw) {
+      return;
+    }
+    var interpolation = _mergeComponents(style, components);
+    //
+    // Build the edit.
+    //
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleReplacement(range.node(binary), interpolation);
+    });
+  }
+
+  _StringStyle _extractComponentsInto(
+      Expression expression, List<AstNode> components) {
+    if (expression is SingleStringLiteral) {
+      components.add(expression);
+      return _StringStyle(
+        multiline: expression.isMultiline,
+        raw: expression.isRaw,
+        singleQuoted: expression.isSingleQuoted,
+      );
+    } else if (expression is AdjacentStrings) {
+      var style = _StringStyle.unknown;
+      for (var string in expression.strings) {
+        if (style.isUnknown) {
+          style = _extractComponentsInto(string, components);
+        } else {
+          var currentStyle = _extractComponentsInto(string, components);
+          if (style != currentStyle) {
+            style = _StringStyle.invalid;
+          }
+        }
+      }
+      return style;
+    } else if (expression is BinaryExpression &&
+        _isStringConcatenation(expression)) {
+      var leftStyle =
+          _extractComponentsInto(expression.leftOperand, components);
+      var rightStyle =
+          _extractComponentsInto(expression.rightOperand, components);
+      if (leftStyle.isUnknown) {
+        return rightStyle;
+      } else if (rightStyle.isUnknown) {
+        return leftStyle;
+      }
+      return leftStyle == rightStyle ? leftStyle : _StringStyle.invalid;
+    } else if (expression is MethodInvocation &&
+        expression.methodName.name == 'toString') {
+      return _extractComponentsInto(expression.target, components);
+    } else if (expression is ParenthesizedExpression) {
+      return _extractComponentsInto(expression.expression, components);
+    }
+    components.add(expression);
+    return _StringStyle.unknown;
+  }
+
+  bool _isStringConcatenation(AstNode node) =>
+      node is BinaryExpression &&
+      node.operator.type == TokenType.PLUS &&
+      node.leftOperand.staticType.isDartCoreString &&
+      node.rightOperand.staticType.isDartCoreString;
+
+  String _mergeComponents(_StringStyle style, List<AstNode> components) {
+    var quotes = style.quotes;
+    var buffer = StringBuffer();
+    buffer.write(quotes);
+    for (int i = 0; i < components.length; i++) {
+      var component = components[i];
+      if (component is SimpleStringLiteral) {
+        var contents = utils.getRangeText(range.startOffsetEndOffset(
+            component.contentsOffset, component.contentsEnd));
+        buffer.write(contents);
+      } else if (component is SimpleIdentifier) {
+        if (_nextStartsWithLetter(components, i)) {
+          buffer.write(r'${');
+          buffer.write(component.name);
+          buffer.write('}');
+        } else {
+          buffer.write(r'$');
+          buffer.write(component.name);
+        }
+      } else {
+        buffer.write(r'${');
+        buffer.write(utils.getNodeText(component));
+        buffer.write('}');
+      }
+    }
+    buffer.write(quotes);
+    return buffer.toString();
+  }
+
+  /// Return `true` if the component after [index] in the list of [components]
+  /// is one that would begin with a letter when written into the resulting
+  /// string.
+  bool _nextStartsWithLetter(List<AstNode> components, int index) {
+    bool startsWithLetter(String string) =>
+        string.startsWith(RegExp('[a-zA-Z]'));
+
+    if (index + 1 >= components.length) {
+      return false;
+    }
+    var next = components[index + 1];
+    if (next is SimpleStringLiteral) {
+      return startsWithLetter(next.value);
+    } else if (next is StringInterpolation) {
+      return startsWithLetter((next.elements[0] as InterpolationString).value);
+    }
+    return false;
+  }
+}
+
+class _StringStyle {
+  static _StringStyle invalid = _StringStyle._(-2);
+
+  static _StringStyle unknown = _StringStyle._(-1);
+
+  static int multilineBit = 4;
+  static int rawBit = 2;
+  static int singleQuotedBit = 1;
+
+  final int state;
+
+  factory _StringStyle(
+      {@required bool multiline,
+      @required bool raw,
+      @required bool singleQuoted}) {
+    return _StringStyle._((multiline ? multilineBit : 0) +
+        (raw ? rawBit : 0) +
+        (singleQuoted ? singleQuotedBit : 0));
+  }
+
+  _StringStyle._(this.state);
+
+  @override
+  int get hashCode => state;
+
+  bool get isInvalid => state == -2;
+
+  bool get isRaw => state & rawBit != 0;
+
+  bool get isUnknown => state == -1;
+
+  String get quotes {
+    if (state & singleQuotedBit != 0) {
+      return (state & multilineBit != 0) ? "'''" : "'";
+    }
+    return (state & multilineBit != 0) ? '"""' : '"';
+  }
+
+  @override
+  bool operator ==(Object other) {
+    return other is _StringStyle && state == other.state;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/wrap_in_text.dart b/pkg/analysis_server/lib/src/services/correction/dart/wrap_in_text.dart
new file mode 100644
index 0000000..7f26c42
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/wrap_in_text.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class WrapInText extends CorrectionProducer {
+  @override
+  FixKind get fixKind => DartFixKind.WRAP_IN_TEXT;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    //
+    // Extract the information needed to build the edit.
+    //
+    var value = _findStringToWrap(node);
+    if (value == null) {
+      return;
+    }
+    var parameter = (value.parent as Expression).staticParameterElement;
+    if (parameter == null || !flutter.isWidget(parameter.type.element)) {
+      return;
+    }
+    //
+    // Extract the information needed to build the edit.
+    //
+    var literalSource = utils.getNodeText(value);
+    //
+    // Build the edit.
+    //
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleReplacement(range.node(value), 'Text($literalSource)');
+    });
+  }
+
+  /// Return the expression that should be wrapped in an invocation of the
+  /// constructor for `Text`.
+  Expression _findStringToWrap(AstNode node) {
+    if (node is SimpleIdentifier) {
+      var label = node.parent;
+      if (label is Label) {
+        var namedExpression = label.parent;
+        if (namedExpression is NamedExpression) {
+          var expression = namedExpression.expression;
+          if (expression.staticType.isDartCoreString) {
+            return expression;
+          }
+        }
+      }
+    }
+    return null;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 2b76ff0..35e0a65 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -289,6 +289,7 @@
   static const REMOVE_ARGUMENT =
       FixKind('REMOVE_ARGUMENT', 50, 'Remove argument');
   static const REMOVE_AWAIT = FixKind('REMOVE_AWAIT', 50, 'Remove await');
+  static const REMOVE_CONST = FixKind('REMOVE_CONST', 50, 'Remove const');
   static const REMOVE_DEAD_CODE =
       FixKind('REMOVE_DEAD_CODE', 50, 'Remove dead code');
   static const REMOVE_DUPLICATE_CASE =
@@ -380,6 +381,8 @@
       FixKind('REPLACE_WITH_EXTENSION_NAME', 50, "Replace with '{0}'");
   static const REPLACE_WITH_IDENTIFIER =
       FixKind('REPLACE_WITH_IDENTIFIER', 50, 'Replace with identifier');
+  static const REPLACE_WITH_INTERPOLATION =
+      FixKind('REPLACE_WITH_INTERPOLATION', 50, 'Replace with interpolation');
   static const REPLACE_WITH_IS_EMPTY =
       FixKind('REPLACE_WITH_IS_EMPTY', 50, "Replace with 'isEmpty'");
   static const REPLACE_WITH_IS_NOT_EMPTY =
@@ -413,6 +416,8 @@
       FixKind('USE_RETHROW', 50, 'Replace throw with rethrow');
   static const WRAP_IN_FUTURE =
       FixKind('WRAP_IN_FUTURE', 50, "Wrap in 'Future.value'");
+  static const WRAP_IN_TEXT =
+      FixKind('WRAP_IN_TEXT', 50, "Wrap in a 'Text' widget");
 }
 
 /// An enumeration of quick fix kinds for the errors found in an Android
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 5e9f9df..906e521 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -26,7 +26,9 @@
 import 'package:analysis_server/src/services/correction/dart/remove_unused.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unused_local_variable.dart';
 import 'package:analysis_server/src/services/correction/dart/replace_with_eight_digit_hex.dart';
+import 'package:analysis_server/src/services/correction/dart/replace_with_interpolation.dart';
 import 'package:analysis_server/src/services/correction/dart/wrap_in_future.dart';
+import 'package:analysis_server/src/services/correction/dart/wrap_in_text.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/levenshtein.dart';
@@ -495,6 +497,9 @@
       await _addFix_createClass();
       await _addFix_createMixin();
     }
+    if (errorCode == CompileTimeErrorCode.CONST_WITH_NON_CONST) {
+      await _addFix_removeConstKeyword(DartFixKind.REMOVE_CONST);
+    }
     if (errorCode == StaticTypeWarningCode.UNDEFINED_FUNCTION) {
       await _addFix_createClass();
       await _addFix_importLibrary_withExtension();
@@ -729,7 +734,7 @@
         await _addFix_removeInterpolationBraces();
       }
       if (name == LintNames.unnecessary_const) {
-        await _addFix_removeConstKeyword();
+        await _addFix_removeConstKeyword(DartFixKind.REMOVE_UNNECESSARY_CONST);
       }
       if (name == LintNames.unnecessary_lambdas) {
         await _addFix_replaceWithTearOff();
@@ -2109,6 +2114,9 @@
     // prepare target ClassDeclaration
     var targetDeclarationResult =
         await sessionHelper.getElementDeclaration(targetClassElement);
+    if (targetDeclarationResult == null) {
+      return;
+    }
     if (targetDeclarationResult.node is! ClassOrMixinDeclaration) {
       return;
     }
@@ -3319,7 +3327,7 @@
     }
   }
 
-  Future<void> _addFix_removeConstKeyword() async {
+  Future<void> _addFix_removeConstKeyword(FixKind kind) async {
     final expression = node;
     if (expression is InstanceCreationExpression) {
       final constToken = expression.keyword;
@@ -3327,14 +3335,14 @@
       await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
         builder.addDeletion(range.startStart(constToken, constToken.next));
       });
-      _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_UNNECESSARY_CONST);
+      _addFixFromBuilder(changeBuilder, kind);
     } else if (expression is TypedLiteralImpl) {
       final constToken = expression.constKeyword;
       var changeBuilder = _newDartChangeBuilder();
       await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
         builder.addDeletion(range.startStart(constToken, constToken.next));
       });
-      _addFixFromBuilder(changeBuilder, DartFixKind.REMOVE_UNNECESSARY_CONST);
+      _addFixFromBuilder(changeBuilder, kind);
     }
   }
 
@@ -4485,6 +4493,8 @@
       await compute(RemoveUnusedField());
     } else if (errorCode == HintCode.UNUSED_LOCAL_VARIABLE) {
       await compute(RemoveUnusedLocalVariable());
+    } else if (errorCode == StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE) {
+      await compute(WrapInText());
     } else if (errorCode == StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION) {
       await compute(RemoveDeadIfNull());
     } else if (errorCode ==
@@ -4507,6 +4517,8 @@
         await compute(ConvertToSetLiteral());
       } else if (name == LintNames.prefer_contains) {
         await compute(ConvertToContains());
+      } else if (name == LintNames.prefer_interpolation_to_compose_strings) {
+        await compute(ReplaceWithInterpolation());
       } else if (name == LintNames.prefer_iterable_whereType) {
         await compute(ConvertToWhereType());
       } else if (name == LintNames.prefer_null_aware_operators) {
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index 6546d87..549d182 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -14,13 +14,13 @@
       'avoid_annotating_with_dynamic';
   static const String avoid_empty_else = 'avoid_empty_else';
   static const String avoid_init_to_null = 'avoid_init_to_null';
+  static const String avoid_private_typedef_functions =
+      'avoid_private_typedef_functions';
   static const String avoid_redundant_argument_values =
       'avoid_redundant_argument_values';
   static const String avoid_relative_lib_imports = 'avoid_relative_lib_imports';
   static const String avoid_return_types_on_setters =
       'avoid_return_types_on_setters';
-  static const String avoid_private_typedef_functions =
-      'avoid_private_typedef_functions';
   static const String avoid_returning_null_for_future =
       'avoid_returning_null_for_future';
   static const String avoid_types_on_closure_parameters =
@@ -44,9 +44,9 @@
   static const String prefer_collection_literals = 'prefer_collection_literals';
   static const String prefer_conditional_assignment =
       'prefer_conditional_assignment';
-  static const String prefer_contains = 'prefer_contains';
   static const String prefer_const_constructors = 'prefer_const_constructors';
   static const String prefer_const_declarations = 'prefer_const_declarations';
+  static const String prefer_contains = 'prefer_contains';
   static const String prefer_equal_for_default_values =
       'prefer_equal_for_default_values';
   static const String prefer_expression_function_bodies =
@@ -62,6 +62,8 @@
   static const String prefer_if_null_operators = 'prefer_if_null_operators';
   static const String prefer_inlined_adds = 'prefer_inlined_adds';
   static const String prefer_int_literals = 'prefer_int_literals';
+  static const String prefer_interpolation_to_compose_strings =
+      'prefer_interpolation_to_compose_strings';
   static const String prefer_is_empty = 'prefer_is_empty';
   static const String prefer_is_not_empty = 'prefer_is_not_empty';
   static const String prefer_iterable_whereType = 'prefer_iterable_whereType';
diff --git a/pkg/analysis_server/test/client/relevance/type_member_relevance_test.dart b/pkg/analysis_server/test/client/relevance/type_member_relevance_test.dart
index 22a526f..7d1c53e 100644
--- a/pkg/analysis_server/test/client/relevance/type_member_relevance_test.dart
+++ b/pkg/analysis_server/test/client/relevance/type_member_relevance_test.dart
@@ -24,7 +24,48 @@
   @override
   bool get supportsAvailableSuggestions => true;
 
-  Future<void> test_type_member_relevance() async {
+  /// Assert that all of the given completions were produced and that the
+  /// suggestions are ordered in decreasing order based on relevance scores.
+  void assertOrder(List<CompletionSuggestion> suggestions) {
+    var length = suggestions.length;
+    expect(length, greaterThan(1),
+        reason: 'Test must specify more than one suggestion');
+    var previous = suggestions[0];
+    for (int i = 1; i < length; i++) {
+      var current = suggestions[i];
+      expect(current.relevance, lessThan(previous.relevance));
+      previous = current;
+    }
+  }
+
+  Future<void> test_contextType() async {
+    await addTestFile(r'''
+class A {}
+class B extends A {}
+class C extends B {}
+class D {}
+
+class E {
+  A a() {}
+  B b() {}
+  C c() {}
+  D d() {}
+}
+
+void f(B b) {}
+void g(E e) {
+  f(e.^);
+}
+''');
+    assertOrder([
+      suggestionWith(completion: 'b'), // same
+      suggestionWith(completion: 'c'), // subtype
+      suggestionWith(completion: 'd'), // unrelated
+      suggestionWith(completion: 'a'), // supertype
+    ]);
+  }
+
+  Future<void> test_inheritanceDepth() async {
     await addTestFile('''
 class A {
   void a() { }
@@ -34,22 +75,50 @@
   void b() { }
 }
 
-void main() {
-  var b = B();
+void f(B b) {
   b.^
 }
 ''');
+    assertOrder([
+      suggestionWith(completion: 'b'),
+      suggestionWith(completion: 'a'),
+      suggestionWith(completion: 'hashCode'),
+    ]);
+  }
 
-    expect(
-        suggestionWith(
-                completion: 'b',
-                element: ElementKind.METHOD,
-                kind: CompletionSuggestionKind.INVOCATION)
-            .relevance,
-        greaterThan(suggestionWith(
-                completion: 'a',
-                element: ElementKind.METHOD,
-                kind: CompletionSuggestionKind.INVOCATION)
-            .relevance));
+  Future<void> test_startsWithDollar() async {
+    await addTestFile(r'''
+class A {
+  void a() { }
+  void $b() { }
+}
+
+void f(A a) {
+  a.^
+}
+''');
+    assertOrder([
+      suggestionWith(completion: 'a'),
+      suggestionWith(completion: r'$b'),
+    ]);
+  }
+
+  Future<void> test_superMatches() async {
+    await addTestFile('''
+class A {
+  void a() { }
+  void b() { }
+}
+
+class B extends A {
+  void b() {
+    super.^
+  }
+}
+''');
+    assertOrder([
+      suggestionWith(completion: 'b'),
+      suggestionWith(completion: 'a'),
+    ]);
   }
 }
diff --git a/pkg/analysis_server/test/domain_edit_dartfix_test.dart b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
index c4f1364..c1b942b 100644
--- a/pkg/analysis_server/test/domain_edit_dartfix_test.dart
+++ b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
@@ -171,17 +171,8 @@
 }
 ''');
     createProject();
-    EditDartfixResult result =
-        await performFix(includedFixes: ['non-nullable']);
-    expect(result.suggestions.length, greaterThanOrEqualTo(1));
-    expect(result.hasErrors, isFalse);
-    expectEdits(result.edits, '''
-int f(int? i) => 0;
-int g(int? i) => f(i);
-void test() {
-  g(null);
-}
-''');
+    expectLater(() async => await performFix(includedFixes: ['non-nullable']),
+        throwsA(TypeMatcher<StateError>()));
   }
 
   Future<void> test_nonNullable_analysisOptions_created() async {
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/material.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/material.dart
index bf5fbc5..466ed8e 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/material.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/material.dart
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-export 'widgets.dart';
 export 'src/material/app_bar.dart';
 export 'src/material/icons.dart';
 export 'src/material/scaffold.dart';
+export 'widgets.dart';
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/alignment.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/alignment.dart
index 43da0ff..48d3c6d 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/alignment.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/alignment.dart
@@ -6,21 +6,6 @@
 
 import 'basic_types.dart';
 
-/// Base class for [Alignment] that allows for text-direction aware
-/// resolution.
-///
-/// A property or argument of this type accepts classes created either with [new
-/// Alignment] and its variants, or [new AlignmentDirectional].
-///
-/// To convert an [AlignmentGeometry] object of indeterminate type into an
-/// [Alignment] object, call the [resolve] method.
-@immutable
-abstract class AlignmentGeometry {
-  /// Abstract const constructor. This constructor enables subclasses to provide
-  /// const constructors so that they can be used in const expressions.
-  const AlignmentGeometry();
-}
-
 /// A point within a rectangle.
 ///
 /// `Alignment(0.0, 0.0)` represents the center of the rectangle. The distance
@@ -62,30 +47,6 @@
 ///  * [AlignmentGeometry], which is an abstract type that is agnostic as to
 ///    whether the horizontal direction depends on the [TextDirection].
 class Alignment extends AlignmentGeometry {
-  /// Creates an alignment.
-  ///
-  /// The [x] and [y] arguments must not be null.
-  const Alignment(this.x, this.y)
-      : assert(x != null),
-        assert(y != null);
-
-  /// The distance fraction in the horizontal direction.
-  ///
-  /// A value of -1.0 corresponds to the leftmost edge. A value of 1.0
-  /// corresponds to the rightmost edge. Values are not limited to that range;
-  /// values less than -1.0 represent positions to the left of the left edge,
-  /// and values greater than 1.0 represent positions to the right of the right
-  /// edge.
-  final double x;
-
-  /// The distance fraction in the vertical direction.
-  ///
-  /// A value of -1.0 corresponds to the topmost edge. A value of 1.0
-  /// corresponds to the bottommost edge. Values are not limited to that range;
-  /// values less than -1.0 represent positions above the top, and values
-  /// greater than 1.0 represent positions below the bottom.
-  final double y;
-
   /// The top left corner.
   static const Alignment topLeft = Alignment(-1.0, -1.0);
 
@@ -112,6 +73,30 @@
 
   /// The bottom right corner.
   static const Alignment bottomRight = Alignment(1.0, 1.0);
+
+  /// The distance fraction in the horizontal direction.
+  ///
+  /// A value of -1.0 corresponds to the leftmost edge. A value of 1.0
+  /// corresponds to the rightmost edge. Values are not limited to that range;
+  /// values less than -1.0 represent positions to the left of the left edge,
+  /// and values greater than 1.0 represent positions to the right of the right
+  /// edge.
+  final double x;
+
+  /// The distance fraction in the vertical direction.
+  ///
+  /// A value of -1.0 corresponds to the topmost edge. A value of 1.0
+  /// corresponds to the bottommost edge. Values are not limited to that range;
+  /// values less than -1.0 represent positions above the top, and values
+  /// greater than 1.0 represent positions below the bottom.
+  final double y;
+
+  /// Creates an alignment.
+  ///
+  /// The [x] and [y] arguments must not be null.
+  const Alignment(this.x, this.y)
+      : assert(x != null),
+        assert(y != null);
 }
 
 /// An offset that's expressed as a fraction of a [Size], but whose horizontal
@@ -126,37 +111,6 @@
 ///  * [Alignment], a variant that is defined in physical terms (i.e.
 ///    whose horizontal component does not depend on the text direction).
 class AlignmentDirectional extends AlignmentGeometry {
-  /// Creates a directional alignment.
-  ///
-  /// The [start] and [y] arguments must not be null.
-  const AlignmentDirectional(this.start, this.y)
-      : assert(start != null),
-        assert(y != null);
-
-  /// The distance fraction in the horizontal direction.
-  ///
-  /// A value of -1.0 corresponds to the edge on the "start" side, which is the
-  /// left side in [TextDirection.ltr] contexts and the right side in
-  /// [TextDirection.rtl] contexts. A value of 1.0 corresponds to the opposite
-  /// edge, the "end" side. Values are not limited to that range; values less
-  /// than -1.0 represent positions beyond the start edge, and values greater than
-  /// 1.0 represent positions beyond the end edge.
-  ///
-  /// This value is normalized into an [Alignment.x] value by the [resolve]
-  /// method.
-  final double start;
-
-  /// The distance fraction in the vertical direction.
-  ///
-  /// A value of -1.0 corresponds to the topmost edge. A value of 1.0
-  /// corresponds to the bottommost edge. Values are not limited to that range;
-  /// values less than -1.0 represent positions above the top, and values
-  /// greater than 1.0 represent positions below the bottom.
-  ///
-  /// This value is passed through to [Alignment.y] unmodified by the
-  /// [resolve] method.
-  final double y;
-
   /// The top corner on the "start" side.
   static const AlignmentDirectional topStart = AlignmentDirectional(-1.0, -1.0);
 
@@ -195,6 +149,52 @@
 
   /// The bottom corner on the "end" side.
   static const AlignmentDirectional bottomEnd = AlignmentDirectional(1.0, 1.0);
+
+  /// The distance fraction in the horizontal direction.
+  ///
+  /// A value of -1.0 corresponds to the edge on the "start" side, which is the
+  /// left side in [TextDirection.ltr] contexts and the right side in
+  /// [TextDirection.rtl] contexts. A value of 1.0 corresponds to the opposite
+  /// edge, the "end" side. Values are not limited to that range; values less
+  /// than -1.0 represent positions beyond the start edge, and values greater than
+  /// 1.0 represent positions beyond the end edge.
+  ///
+  /// This value is normalized into an [Alignment.x] value by the [resolve]
+  /// method.
+  final double start;
+
+  /// The distance fraction in the vertical direction.
+  ///
+  /// A value of -1.0 corresponds to the topmost edge. A value of 1.0
+  /// corresponds to the bottommost edge. Values are not limited to that range;
+  /// values less than -1.0 represent positions above the top, and values
+  /// greater than 1.0 represent positions below the bottom.
+  ///
+  /// This value is passed through to [Alignment.y] unmodified by the
+  /// [resolve] method.
+  final double y;
+
+  /// Creates a directional alignment.
+  ///
+  /// The [start] and [y] arguments must not be null.
+  const AlignmentDirectional(this.start, this.y)
+      : assert(start != null),
+        assert(y != null);
+}
+
+/// Base class for [Alignment] that allows for text-direction aware
+/// resolution.
+///
+/// A property or argument of this type accepts classes created either with [new
+/// Alignment] and its variants, or [new AlignmentDirectional].
+///
+/// To convert an [AlignmentGeometry] object of indeterminate type into an
+/// [Alignment] object, call the [resolve] method.
+@immutable
+abstract class AlignmentGeometry {
+  /// Abstract const constructor. This constructor enables subclasses to provide
+  /// const constructors so that they can be used in const expressions.
+  const AlignmentGeometry();
 }
 
 /// The vertical alignment of text within an input box.
@@ -213,16 +213,6 @@
 ///  * [InputDecorator.textAlignVertical], which defines the alignment of
 ///    prefix, input, and suffix within an [InputDecorator].
 class TextAlignVertical {
-  /// Creates a TextAlignVertical from any y value between -1.0 and 1.0.
-  const TextAlignVertical({
-    @required this.y,
-  })  : assert(y != null),
-        assert(y >= -1.0 && y <= 1.0);
-
-  /// A value ranging from -1.0 to 1.0 that defines the topmost and bottommost
-  /// locations of the top and bottom of the input box.
-  final double y;
-
   /// Aligns a TextField's input Text with the topmost location within a
   /// TextField's input box.
   static const TextAlignVertical top = TextAlignVertical(y: -1.0);
@@ -234,6 +224,16 @@
   /// TextField.
   static const TextAlignVertical bottom = TextAlignVertical(y: 1.0);
 
+  /// A value ranging from -1.0 to 1.0 that defines the topmost and bottommost
+  /// locations of the top and bottom of the input box.
+  final double y;
+
+  /// Creates a TextAlignVertical from any y value between -1.0 and 1.0.
+  const TextAlignVertical({
+    @required this.y,
+  })  : assert(y != null),
+        assert(y >= -1.0 && y <= 1.0);
+
   @override
   String toString() {
     return '$runtimeType(y: $y)';
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/border_radius.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/border_radius.dart
index f2d0952..1f8d05d 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/border_radius.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/border_radius.dart
@@ -6,21 +6,6 @@
 
 import 'basic_types.dart';
 
-/// Base class for [BorderRadius] that allows for text-direction aware resolution.
-///
-/// A property or argument of this type accepts classes created either with [new
-/// BorderRadius.only] and its variants, or [new BorderRadiusDirectional.only]
-/// and its variants.
-///
-/// To convert a [BorderRadiusGeometry] object of indeterminate type into a
-/// [BorderRadius] object, call the [resolve] method.
-@immutable
-abstract class BorderRadiusGeometry {
-  /// Abstract const constructor. This constructor enables subclasses to provide
-  /// const constructors so that they can be used in const expressions.
-  const BorderRadiusGeometry();
-}
-
 /// An immutable set of radii for each corner of a rectangle.
 ///
 /// Used by [BoxDecoration] when the shape is a [BoxShape.rectangle].
@@ -31,6 +16,21 @@
 /// [BorderRadiusDirectional], which is expressed in terms that are relative to
 /// a [TextDirection] (typically obtained from the ambient [Directionality]).
 class BorderRadius extends BorderRadiusGeometry {
+  /// A border radius with all zero radii.
+  static const BorderRadius zero = BorderRadius.all(Radius.zero);
+
+  /// The top-left [Radius].
+  final Radius topLeft;
+
+  /// The top-right [Radius].
+  final Radius topRight;
+
+  /// The bottom-left [Radius].
+  final Radius bottomLeft;
+
+  /// The bottom-right [Radius].
+  final Radius bottomRight;
+
   /// Creates a border radius where all radii are [radius].
   const BorderRadius.all(Radius radius)
       : this.only(
@@ -46,18 +46,6 @@
           Radius.circular(radius),
         );
 
-  /// Creates a vertically symmetric border radius where the top and bottom
-  /// sides of the rectangle have the same radii.
-  const BorderRadius.vertical({
-    Radius top = Radius.zero,
-    Radius bottom = Radius.zero,
-  }) : this.only(
-          topLeft: top,
-          topRight: top,
-          bottomLeft: bottom,
-          bottomRight: bottom,
-        );
-
   /// Creates a horizontally symmetrical border radius where the left and right
   /// sides of the rectangle have the same radii.
   const BorderRadius.horizontal({
@@ -79,20 +67,17 @@
     this.bottomRight = Radius.zero,
   });
 
-  /// A border radius with all zero radii.
-  static const BorderRadius zero = BorderRadius.all(Radius.zero);
-
-  /// The top-left [Radius].
-  final Radius topLeft;
-
-  /// The top-right [Radius].
-  final Radius topRight;
-
-  /// The bottom-left [Radius].
-  final Radius bottomLeft;
-
-  /// The bottom-right [Radius].
-  final Radius bottomRight;
+  /// Creates a vertically symmetric border radius where the top and bottom
+  /// sides of the rectangle have the same radii.
+  const BorderRadius.vertical({
+    Radius top = Radius.zero,
+    Radius bottom = Radius.zero,
+  }) : this.only(
+          topLeft: top,
+          topRight: top,
+          bottomLeft: bottom,
+          bottomRight: bottom,
+        );
 }
 
 /// An immutable set of radii for each corner of a rectangle, but with the
@@ -108,6 +93,25 @@
 ///  * [BorderRadius], a variant that uses physical labels (`topLeft` and
 ///    `topRight` instead of `topStart` and `topEnd`).
 class BorderRadiusDirectional extends BorderRadiusGeometry {
+  /// A border radius with all zero radii.
+  ///
+  /// Consider using [EdgeInsets.zero] instead, since that object has the same
+  /// effect, but will be cheaper to [resolve].
+  static const BorderRadiusDirectional zero =
+      BorderRadiusDirectional.all(Radius.zero);
+
+  /// The top-start [Radius].
+  final Radius topStart;
+
+  /// The top-end [Radius].
+  final Radius topEnd;
+
+  /// The bottom-start [Radius].
+  final Radius bottomStart;
+
+  /// The bottom-end [Radius].
+  final Radius bottomEnd;
+
   /// Creates a border radius where all radii are [radius].
   const BorderRadiusDirectional.all(Radius radius)
       : this.only(
@@ -123,18 +127,6 @@
           Radius.circular(radius),
         );
 
-  /// Creates a vertically symmetric border radius where the top and bottom
-  /// sides of the rectangle have the same radii.
-  const BorderRadiusDirectional.vertical({
-    Radius top = Radius.zero,
-    Radius bottom = Radius.zero,
-  }) : this.only(
-          topStart: top,
-          topEnd: top,
-          bottomStart: bottom,
-          bottomEnd: bottom,
-        );
-
   /// Creates a horizontally symmetrical border radius where the start and end
   /// sides of the rectangle have the same radii.
   const BorderRadiusDirectional.horizontal({
@@ -156,22 +148,30 @@
     this.bottomEnd = Radius.zero,
   });
 
-  /// A border radius with all zero radii.
-  ///
-  /// Consider using [EdgeInsets.zero] instead, since that object has the same
-  /// effect, but will be cheaper to [resolve].
-  static const BorderRadiusDirectional zero =
-      BorderRadiusDirectional.all(Radius.zero);
+  /// Creates a vertically symmetric border radius where the top and bottom
+  /// sides of the rectangle have the same radii.
+  const BorderRadiusDirectional.vertical({
+    Radius top = Radius.zero,
+    Radius bottom = Radius.zero,
+  }) : this.only(
+          topStart: top,
+          topEnd: top,
+          bottomStart: bottom,
+          bottomEnd: bottom,
+        );
+}
 
-  /// The top-start [Radius].
-  final Radius topStart;
-
-  /// The top-end [Radius].
-  final Radius topEnd;
-
-  /// The bottom-start [Radius].
-  final Radius bottomStart;
-
-  /// The bottom-end [Radius].
-  final Radius bottomEnd;
+/// Base class for [BorderRadius] that allows for text-direction aware resolution.
+///
+/// A property or argument of this type accepts classes created either with [new
+/// BorderRadius.only] and its variants, or [new BorderRadiusDirectional.only]
+/// and its variants.
+///
+/// To convert a [BorderRadiusGeometry] object of indeterminate type into a
+/// [BorderRadius] object, call the [resolve] method.
+@immutable
+abstract class BorderRadiusGeometry {
+  /// Abstract const constructor. This constructor enables subclasses to provide
+  /// const constructors so that they can be used in const expressions.
+  const BorderRadiusGeometry();
 }
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/borders.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/borders.dart
index 8c9e028..8711555 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/borders.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/borders.dart
@@ -6,17 +6,6 @@
 
 import 'basic_types.dart';
 
-/// The style of line to draw for a [BorderSide] in a [Border].
-enum BorderStyle {
-  /// Skip the border.
-  none,
-
-  /// Draw the border as a solid line.
-  solid,
-
-  // if you add more, think about how they will lerp
-}
-
 /// A side of a border of a box.
 ///
 /// A [Border] consists of four [BorderSide] objects: [Border.top],
@@ -55,17 +44,9 @@
 ///    of which are also [BorderSide] objects.
 @immutable
 class BorderSide {
-  /// Creates the side of a border.
-  ///
-  /// By default, the border is 1.0 logical pixels wide and solid black.
-  const BorderSide({
-    this.color = const Color(0xFF000000),
-    this.width = 1.0,
-    this.style = BorderStyle.solid,
-  })  : assert(color != null),
-        assert(width != null),
-        assert(width >= 0.0),
-        assert(style != null);
+  /// A hairline black border that is not rendered.
+  static const BorderSide none =
+      BorderSide(width: 0.0, style: BorderStyle.none);
 
   /// The color of this side of the border.
   final Color color;
@@ -87,9 +68,17 @@
   /// painting the border, but the border still has a [width].
   final BorderStyle style;
 
-  /// A hairline black border that is not rendered.
-  static const BorderSide none =
-      BorderSide(width: 0.0, style: BorderStyle.none);
+  /// Creates the side of a border.
+  ///
+  /// By default, the border is 1.0 logical pixels wide and solid black.
+  const BorderSide({
+    this.color = const Color(0xFF000000),
+    this.width = 1.0,
+    this.style = BorderStyle.solid,
+  })  : assert(color != null),
+        assert(width != null),
+        assert(width >= 0.0),
+        assert(style != null);
 
   /// Creates a copy of this border but with the given fields replaced with the new values.
   BorderSide copyWith({
@@ -106,6 +95,17 @@
   }
 }
 
+/// The style of line to draw for a [BorderSide] in a [Border].
+enum BorderStyle {
+  /// Skip the border.
+  none,
+
+  /// Draw the border as a solid line.
+  solid,
+
+  // if you add more, think about how they will lerp
+}
+
 /// Base class for shape outlines.
 ///
 /// This class handles how to add multiple borders together. Subclasses define
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/box_border.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/box_border.dart
index b2bc66c..d9b0420 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/box_border.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/box_border.dart
@@ -6,66 +6,6 @@
 import 'border_radius.dart';
 import 'borders.dart';
 
-/// The shape to use when rendering a [Border] or [BoxDecoration].
-///
-/// Consider using [ShapeBorder] subclasses directly (with [ShapeDecoration]),
-/// instead of using [BoxShape] and [Border], if the shapes will need to be
-/// interpolated or animated. The [Border] class cannot interpolate between
-/// different shapes.
-enum BoxShape {
-  /// An axis-aligned, 2D rectangle. May have rounded corners (described by a
-  /// [BorderRadius]). The edges of the rectangle will match the edges of the box
-  /// into which the [Border] or [BoxDecoration] is painted.
-  ///
-  /// See also:
-  ///
-  ///  * [RoundedRectangleBorder], the equivalent [ShapeBorder].
-  rectangle,
-
-  /// A circle centered in the middle of the box into which the [Border] or
-  /// [BoxDecoration] is painted. The diameter of the circle is the shortest
-  /// dimension of the box, either the width or the height, such that the circle
-  /// touches the edges of the box.
-  ///
-  /// See also:
-  ///
-  ///  * [CircleBorder], the equivalent [ShapeBorder].
-  circle,
-
-  // Don't add more, instead create a new ShapeBorder.
-}
-
-/// Base class for box borders that can paint as rectangles, circles, or rounded
-/// rectangles.
-///
-/// This class is extended by [Border] and [BorderDirectional] to provide
-/// concrete versions of four-sided borders using different conventions for
-/// specifying the sides.
-///
-/// The only API difference that this class introduces over [ShapeBorder] is
-/// that its [paint] method takes additional arguments.
-///
-/// See also:
-///
-///  * [BorderSide], which is used to describe each side of the box.
-///  * [RoundedRectangleBorder], another way of describing a box's border.
-///  * [CircleBorder], another way of describing a circle border.
-///  * [BoxDecoration], which uses a [BoxBorder] to describe its borders.
-abstract class BoxBorder extends ShapeBorder {
-  /// Abstract const constructor. This constructor enables subclasses to provide
-  /// const constructors so that they can be used in const expressions.
-  const BoxBorder();
-
-  /// The top side of this border.
-  ///
-  /// This getter is available on both [Border] and [BorderDirectional]. If
-  /// [isUniform] is true, then this is the same style as all the other sides.
-  BorderSide get top;
-
-  /// The bottom side of this border.
-  BorderSide get bottom;
-}
-
 /// A border of a box, comprised of four sides: top, right, bottom, left.
 ///
 /// The sides are represented by [BorderSide] objects.
@@ -128,6 +68,18 @@
 ///  * [Theme], from the material layer, which can be queried to obtain appropriate colors
 ///    to use for borders in a material app, as shown in the "divider" sample above.
 class Border extends BoxBorder {
+  @override
+  final BorderSide top;
+
+  /// The right side of this border.
+  final BorderSide right;
+
+  @override
+  final BorderSide bottom;
+
+  /// The left side of this border.
+  final BorderSide left;
+
   /// Creates a border.
   ///
   /// All the sides of the border default to [BorderSide.none].
@@ -143,16 +95,6 @@
         assert(bottom != null),
         assert(left != null);
 
-  /// Creates a border whose sides are all the same.
-  ///
-  /// The `side` argument must not be null.
-  const Border.fromBorderSide(BorderSide side)
-      : assert(side != null),
-        top = side,
-        right = side,
-        bottom = side,
-        left = side;
-
   /// A uniform border with all sides the same color and width.
   ///
   /// The sides default to black solid borders, one logical pixel wide.
@@ -166,17 +108,15 @@
     return Border.fromBorderSide(side);
   }
 
-  @override
-  final BorderSide top;
-
-  /// The right side of this border.
-  final BorderSide right;
-
-  @override
-  final BorderSide bottom;
-
-  /// The left side of this border.
-  final BorderSide left;
+  /// Creates a border whose sides are all the same.
+  ///
+  /// The `side` argument must not be null.
+  const Border.fromBorderSide(BorderSide side)
+      : assert(side != null),
+        top = side,
+        right = side,
+        bottom = side,
+        left = side;
 }
 
 /// A border of a box, comprised of four sides, the lateral sides of which
@@ -199,25 +139,6 @@
 ///  * [Theme], from the material layer, which can be queried to obtain appropriate colors
 ///    to use for borders in a material app, as shown in the "divider" sample above.
 class BorderDirectional extends BoxBorder {
-  /// Creates a border.
-  ///
-  /// The [start] and [end] sides represent the horizontal sides; the start side
-  /// is on the leading edge given the reading direction, and the end side is on
-  /// the trailing edge. They are resolved during [paint].
-  ///
-  /// All the sides of the border default to [BorderSide.none].
-  ///
-  /// The arguments must not be null.
-  const BorderDirectional({
-    this.top = BorderSide.none,
-    this.start = BorderSide.none,
-    this.end = BorderSide.none,
-    this.bottom = BorderSide.none,
-  })  : assert(top != null),
-        assert(start != null),
-        assert(end != null),
-        assert(bottom != null);
-
   @override
   final BorderSide top;
 
@@ -243,4 +164,83 @@
 
   @override
   final BorderSide bottom;
+
+  /// Creates a border.
+  ///
+  /// The [start] and [end] sides represent the horizontal sides; the start side
+  /// is on the leading edge given the reading direction, and the end side is on
+  /// the trailing edge. They are resolved during [paint].
+  ///
+  /// All the sides of the border default to [BorderSide.none].
+  ///
+  /// The arguments must not be null.
+  const BorderDirectional({
+    this.top = BorderSide.none,
+    this.start = BorderSide.none,
+    this.end = BorderSide.none,
+    this.bottom = BorderSide.none,
+  })  : assert(top != null),
+        assert(start != null),
+        assert(end != null),
+        assert(bottom != null);
+}
+
+/// Base class for box borders that can paint as rectangles, circles, or rounded
+/// rectangles.
+///
+/// This class is extended by [Border] and [BorderDirectional] to provide
+/// concrete versions of four-sided borders using different conventions for
+/// specifying the sides.
+///
+/// The only API difference that this class introduces over [ShapeBorder] is
+/// that its [paint] method takes additional arguments.
+///
+/// See also:
+///
+///  * [BorderSide], which is used to describe each side of the box.
+///  * [RoundedRectangleBorder], another way of describing a box's border.
+///  * [CircleBorder], another way of describing a circle border.
+///  * [BoxDecoration], which uses a [BoxBorder] to describe its borders.
+abstract class BoxBorder extends ShapeBorder {
+  /// Abstract const constructor. This constructor enables subclasses to provide
+  /// const constructors so that they can be used in const expressions.
+  const BoxBorder();
+
+  /// The bottom side of this border.
+  BorderSide get bottom;
+
+  /// The top side of this border.
+  ///
+  /// This getter is available on both [Border] and [BorderDirectional]. If
+  /// [isUniform] is true, then this is the same style as all the other sides.
+  BorderSide get top;
+}
+
+/// The shape to use when rendering a [Border] or [BoxDecoration].
+///
+/// Consider using [ShapeBorder] subclasses directly (with [ShapeDecoration]),
+/// instead of using [BoxShape] and [Border], if the shapes will need to be
+/// interpolated or animated. The [Border] class cannot interpolate between
+/// different shapes.
+enum BoxShape {
+  /// An axis-aligned, 2D rectangle. May have rounded corners (described by a
+  /// [BorderRadius]). The edges of the rectangle will match the edges of the box
+  /// into which the [Border] or [BoxDecoration] is painted.
+  ///
+  /// See also:
+  ///
+  ///  * [RoundedRectangleBorder], the equivalent [ShapeBorder].
+  rectangle,
+
+  /// A circle centered in the middle of the box into which the [Border] or
+  /// [BoxDecoration] is painted. The diameter of the circle is the shortest
+  /// dimension of the box, either the width or the height, such that the circle
+  /// touches the edges of the box.
+  ///
+  /// See also:
+  ///
+  ///  * [CircleBorder], the equivalent [ShapeBorder].
+  circle,
+
+  // Don't add more, instead create a new ShapeBorder.
 }
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/decoration.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/decoration.dart
index 6f18ea0..6995507 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/decoration.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/painting/decoration.dart
@@ -21,6 +21,9 @@
   /// const constructors so that they can be used in const expressions.
   const Decoration();
 
+  /// Whether this decoration is complex enough to benefit from caching its painting.
+  bool get isComplex => false;
+
   /// Returns the insets to apply when using this decoration on a box
   /// that has contents, so that the contents do not overlap the edges
   /// of the decoration. For example, if the decoration draws a frame
@@ -41,7 +44,4 @@
   /// example, [BorderDirectional] will return an [EdgeInsetsDirectional] for
   /// its [padding].)
   EdgeInsetsGeometry get padding => EdgeInsets.zero;
-
-  /// Whether this decoration is complex enough to benefit from caching its painting.
-  bool get isComplex => false;
 }
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/async.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/async.dart
index 081022b..f5b17e0 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/async.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/async.dart
@@ -4,14 +4,14 @@
 
 import 'framework.dart';
 
-class AsyncSnapshot<T> {}
-
 typedef AsyncWidgetBuilder<T> = Widget Function(
     BuildContext context, AsyncSnapshot<T> snapshot);
 
+class AsyncSnapshot<T> {}
+
 class StreamBuilder<T> {
-  const StreamBuilder(
-      {Key key, this.initialData, Stream<T> stream, @required this.builder});
   final T initialData;
   final AsyncWidgetBuilder<T> builder;
+  const StreamBuilder(
+      {Key key, this.initialData, Stream<T> stream, @required this.builder});
 }
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/framework.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/framework.dart
index a52fa57..3bc94fd7 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/framework.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/framework.dart
@@ -13,6 +13,16 @@
   Widget get widget;
 }
 
+abstract class RenderObjectWidget extends Widget {
+  const RenderObjectWidget({Key key}) : super(key: key);
+}
+
+abstract class SingleChildRenderObjectWidget extends RenderObjectWidget {
+  final Widget child;
+
+  const SingleChildRenderObjectWidget({Key key, this.child}) : super(key: key);
+}
+
 abstract class State<T extends StatefulWidget> {
   BuildContext get context => null;
 
@@ -44,13 +54,3 @@
 
   void debugFillProperties(DiagnosticPropertiesBuilder properties) {}
 }
-
-abstract class SingleChildRenderObjectWidget extends RenderObjectWidget {
-  final Widget child;
-
-  const SingleChildRenderObjectWidget({Key key, this.child}) : super(key: key);
-}
-
-abstract class RenderObjectWidget extends Widget {
-  const RenderObjectWidget({Key key}) : super(key: key);
-}
diff --git a/pkg/analysis_server/test/mock_packages/ui/lib/geometry.dart b/pkg/analysis_server/test/mock_packages/ui/lib/geometry.dart
index 7cbc6e0..cf0281b 100644
--- a/pkg/analysis_server/test/mock_packages/ui/lib/geometry.dart
+++ b/pkg/analysis_server/test/mock_packages/ui/lib/geometry.dart
@@ -6,11 +6,10 @@
 
 /// A radius for either circular or elliptical shapes.
 class Radius {
-  /// Constructs a circular radius. [x] and [y] will have the same radius value.
-  const Radius.circular(double radius) : this.elliptical(radius, radius);
-
-  /// Constructs an elliptical radius with the given radii.
-  const Radius.elliptical(this.x, this.y);
+  /// A radius with [x] and [y] values set to zero.
+  ///
+  /// You can use [Radius.zero] with [RRect] to have right-angle corners.
+  static const Radius zero = Radius.circular(0.0);
 
   /// The radius value on the horizontal axis.
   final double x;
@@ -18,8 +17,9 @@
   /// The radius value on the vertical axis.
   final double y;
 
-  /// A radius with [x] and [y] values set to zero.
-  ///
-  /// You can use [Radius.zero] with [RRect] to have right-angle corners.
-  static const Radius zero = Radius.circular(0.0);
+  /// Constructs a circular radius. [x] and [y] will have the same radius value.
+  const Radius.circular(double radius) : this.elliptical(radius, radius);
+
+  /// Constructs an elliptical radius with the given radii.
+  const Radius.elliptical(this.x, this.y);
 }
diff --git a/pkg/analysis_server/test/mock_packages/ui/lib/painting.dart b/pkg/analysis_server/test/mock_packages/ui/lib/painting.dart
index 2009ca0..a6b686a 100644
--- a/pkg/analysis_server/test/mock_packages/ui/lib/painting.dart
+++ b/pkg/analysis_server/test/mock_packages/ui/lib/painting.dart
@@ -4,180 +4,6 @@
 
 part of dart.ui;
 
-/// An immutable 32 bit color value in ARGB format.
-///
-/// Consider the light teal of the Flutter logo. It is fully opaque, with a red
-/// channel value of 0x42 (66), a green channel value of 0xA5 (165), and a blue
-/// channel value of 0xF5 (245). In the common "hash syntax" for color values,
-/// it would be described as `#42A5F5`.
-///
-/// Here are some ways it could be constructed:
-///
-/// ```dart
-/// Color c = const Color(0xFF42A5F5);
-/// Color c = const Color.fromARGB(0xFF, 0x42, 0xA5, 0xF5);
-/// Color c = const Color.fromARGB(255, 66, 165, 245);
-/// Color c = const Color.fromRGBO(66, 165, 245, 1.0);
-/// ```
-///
-/// If you are having a problem with `Color` wherein it seems your color is just
-/// not painting, check to make sure you are specifying the full 8 hexadecimal
-/// digits. If you only specify six, then the leading two digits are assumed to
-/// be zero, which means fully-transparent:
-///
-/// ```dart
-/// Color c1 = const Color(0xFFFFFF); // fully transparent white (invisible)
-/// Color c2 = const Color(0xFFFFFFFF); // fully opaque white (visible)
-/// ```
-///
-/// See also:
-///
-///  * [Colors](https://docs.flutter.io/flutter/material/Colors-class.html), which
-///    defines the colors found in the Material Design specification.
-class Color {
-  /// Construct a color from the lower 32 bits of an [int].
-  ///
-  /// The bits are interpreted as follows:
-  ///
-  /// * Bits 24-31 are the alpha value.
-  /// * Bits 16-23 are the red value.
-  /// * Bits 8-15 are the green value.
-  /// * Bits 0-7 are the blue value.
-  ///
-  /// In other words, if AA is the alpha value in hex, RR the red value in hex,
-  /// GG the green value in hex, and BB the blue value in hex, a color can be
-  /// expressed as `const Color(0xAARRGGBB)`.
-  ///
-  /// For example, to get a fully opaque orange, you would use `const
-  /// Color(0xFFFF9000)` (`FF` for the alpha, `FF` for the red, `90` for the
-  /// green, and `00` for the blue).
-  @pragma('vm:entry-point')
-  const Color(int value) : value = value & 0xFFFFFFFF;
-
-  /// Construct a color from the lower 8 bits of four integers.
-  ///
-  /// * `a` is the alpha value, with 0 being transparent and 255 being fully
-  ///   opaque.
-  /// * `r` is [red], from 0 to 255.
-  /// * `g` is [green], from 0 to 255.
-  /// * `b` is [blue], from 0 to 255.
-  ///
-  /// Out of range values are brought into range using modulo 255.
-  ///
-  /// See also [fromRGBO], which takes the alpha value as a floating point
-  /// value.
-  const Color.fromARGB(int a, int r, int g, int b)
-      : value = (((a & 0xff) << 24) |
-                ((r & 0xff) << 16) |
-                ((g & 0xff) << 8) |
-                ((b & 0xff) << 0)) &
-            0xFFFFFFFF;
-
-  /// Create a color from red, green, blue, and opacity, similar to `rgba()` in CSS.
-  ///
-  /// * `r` is [red], from 0 to 255.
-  /// * `g` is [green], from 0 to 255.
-  /// * `b` is [blue], from 0 to 255.
-  /// * `opacity` is alpha channel of this color as a double, with 0.0 being
-  ///   transparent and 1.0 being fully opaque.
-  ///
-  /// Out of range values are brought into range using modulo 255.
-  ///
-  /// See also [fromARGB], which takes the opacity as an integer value.
-  const Color.fromRGBO(int r, int g, int b, double opacity)
-      : value = ((((opacity * 0xff ~/ 1) & 0xff) << 24) |
-                ((r & 0xff) << 16) |
-                ((g & 0xff) << 8) |
-                ((b & 0xff) << 0)) &
-            0xFFFFFFFF;
-
-  /// A 32 bit value representing this color.
-  ///
-  /// The bits are assigned as follows:
-  ///
-  /// * Bits 24-31 are the alpha value.
-  /// * Bits 16-23 are the red value.
-  /// * Bits 8-15 are the green value.
-  /// * Bits 0-7 are the blue value.
-  final int value;
-
-  /// The alpha channel of this color in an 8 bit value.
-  ///
-  /// A value of 0 means this color is fully transparent. A value of 255 means
-  /// this color is fully opaque.
-  int get alpha => (0xff000000 & value) >> 24;
-
-  /// The alpha channel of this color as a double.
-  ///
-  /// A value of 0.0 means this color is fully transparent. A value of 1.0 means
-  /// this color is fully opaque.
-  double get opacity => alpha / 0xFF;
-
-  /// The red channel of this color in an 8 bit value.
-  int get red => (0x00ff0000 & value) >> 16;
-
-  /// The green channel of this color in an 8 bit value.
-  int get green => (0x0000ff00 & value) >> 8;
-
-  /// The blue channel of this color in an 8 bit value.
-  int get blue => (0x000000ff & value) >> 0;
-
-  /// Returns a new color that matches this color with the alpha channel
-  /// replaced with `a` (which ranges from 0 to 255).
-  ///
-  /// Out of range values will have unexpected effects.
-  Color withAlpha(int a) {
-    return Color.fromARGB(a, red, green, blue);
-  }
-
-  /// Returns a new color that matches this color with the alpha channel
-  /// replaced with the given `opacity` (which ranges from 0.0 to 1.0).
-  ///
-  /// Out of range values will have unexpected effects.
-  Color withOpacity(double opacity) {
-    assert(opacity >= 0.0 && opacity <= 1.0);
-    return withAlpha((255.0 * opacity).round());
-  }
-
-  /// Returns a new color that matches this color with the red channel replaced
-  /// with `r` (which ranges from 0 to 255).
-  ///
-  /// Out of range values will have unexpected effects.
-  Color withRed(int r) {
-    return Color.fromARGB(alpha, r, green, blue);
-  }
-
-  /// Returns a new color that matches this color with the green channel
-  /// replaced with `g` (which ranges from 0 to 255).
-  ///
-  /// Out of range values will have unexpected effects.
-  Color withGreen(int g) {
-    return Color.fromARGB(alpha, red, g, blue);
-  }
-
-  /// Returns a new color that matches this color with the blue channel replaced
-  /// with `b` (which ranges from 0 to 255).
-  ///
-  /// Out of range values will have unexpected effects.
-  Color withBlue(int b) {
-    return Color.fromARGB(alpha, red, green, b);
-  }
-
-  @override
-  bool operator ==(dynamic other) {
-    if (identical(this, other)) return true;
-    if (other.runtimeType != runtimeType) return false;
-    final Color typedOther = other;
-    return value == typedOther.value;
-  }
-
-  @override
-  int get hashCode => value.hashCode;
-
-  @override
-  String toString() => 'Color(0x${value.toRadixString(16).padLeft(8, '0')})';
-}
-
 /// Algorithms to use when painting on the canvas.
 ///
 /// When drawing a shape or image onto a canvas, different algorithms can be
@@ -648,3 +474,177 @@
   ///    related effect.
   luminosity,
 }
+
+/// An immutable 32 bit color value in ARGB format.
+///
+/// Consider the light teal of the Flutter logo. It is fully opaque, with a red
+/// channel value of 0x42 (66), a green channel value of 0xA5 (165), and a blue
+/// channel value of 0xF5 (245). In the common "hash syntax" for color values,
+/// it would be described as `#42A5F5`.
+///
+/// Here are some ways it could be constructed:
+///
+/// ```dart
+/// Color c = const Color(0xFF42A5F5);
+/// Color c = const Color.fromARGB(0xFF, 0x42, 0xA5, 0xF5);
+/// Color c = const Color.fromARGB(255, 66, 165, 245);
+/// Color c = const Color.fromRGBO(66, 165, 245, 1.0);
+/// ```
+///
+/// If you are having a problem with `Color` wherein it seems your color is just
+/// not painting, check to make sure you are specifying the full 8 hexadecimal
+/// digits. If you only specify six, then the leading two digits are assumed to
+/// be zero, which means fully-transparent:
+///
+/// ```dart
+/// Color c1 = const Color(0xFFFFFF); // fully transparent white (invisible)
+/// Color c2 = const Color(0xFFFFFFFF); // fully opaque white (visible)
+/// ```
+///
+/// See also:
+///
+///  * [Colors](https://docs.flutter.io/flutter/material/Colors-class.html), which
+///    defines the colors found in the Material Design specification.
+class Color {
+  /// A 32 bit value representing this color.
+  ///
+  /// The bits are assigned as follows:
+  ///
+  /// * Bits 24-31 are the alpha value.
+  /// * Bits 16-23 are the red value.
+  /// * Bits 8-15 are the green value.
+  /// * Bits 0-7 are the blue value.
+  final int value;
+
+  /// Construct a color from the lower 32 bits of an [int].
+  ///
+  /// The bits are interpreted as follows:
+  ///
+  /// * Bits 24-31 are the alpha value.
+  /// * Bits 16-23 are the red value.
+  /// * Bits 8-15 are the green value.
+  /// * Bits 0-7 are the blue value.
+  ///
+  /// In other words, if AA is the alpha value in hex, RR the red value in hex,
+  /// GG the green value in hex, and BB the blue value in hex, a color can be
+  /// expressed as `const Color(0xAARRGGBB)`.
+  ///
+  /// For example, to get a fully opaque orange, you would use `const
+  /// Color(0xFFFF9000)` (`FF` for the alpha, `FF` for the red, `90` for the
+  /// green, and `00` for the blue).
+  @pragma('vm:entry-point')
+  const Color(int value) : value = value & 0xFFFFFFFF;
+
+  /// Construct a color from the lower 8 bits of four integers.
+  ///
+  /// * `a` is the alpha value, with 0 being transparent and 255 being fully
+  ///   opaque.
+  /// * `r` is [red], from 0 to 255.
+  /// * `g` is [green], from 0 to 255.
+  /// * `b` is [blue], from 0 to 255.
+  ///
+  /// Out of range values are brought into range using modulo 255.
+  ///
+  /// See also [fromRGBO], which takes the alpha value as a floating point
+  /// value.
+  const Color.fromARGB(int a, int r, int g, int b)
+      : value = (((a & 0xff) << 24) |
+                ((r & 0xff) << 16) |
+                ((g & 0xff) << 8) |
+                ((b & 0xff) << 0)) &
+            0xFFFFFFFF;
+
+  /// Create a color from red, green, blue, and opacity, similar to `rgba()` in CSS.
+  ///
+  /// * `r` is [red], from 0 to 255.
+  /// * `g` is [green], from 0 to 255.
+  /// * `b` is [blue], from 0 to 255.
+  /// * `opacity` is alpha channel of this color as a double, with 0.0 being
+  ///   transparent and 1.0 being fully opaque.
+  ///
+  /// Out of range values are brought into range using modulo 255.
+  ///
+  /// See also [fromARGB], which takes the opacity as an integer value.
+  const Color.fromRGBO(int r, int g, int b, double opacity)
+      : value = ((((opacity * 0xff ~/ 1) & 0xff) << 24) |
+                ((r & 0xff) << 16) |
+                ((g & 0xff) << 8) |
+                ((b & 0xff) << 0)) &
+            0xFFFFFFFF;
+
+  /// The alpha channel of this color in an 8 bit value.
+  ///
+  /// A value of 0 means this color is fully transparent. A value of 255 means
+  /// this color is fully opaque.
+  int get alpha => (0xff000000 & value) >> 24;
+
+  /// The blue channel of this color in an 8 bit value.
+  int get blue => (0x000000ff & value) >> 0;
+
+  /// The green channel of this color in an 8 bit value.
+  int get green => (0x0000ff00 & value) >> 8;
+
+  @override
+  int get hashCode => value.hashCode;
+
+  /// The alpha channel of this color as a double.
+  ///
+  /// A value of 0.0 means this color is fully transparent. A value of 1.0 means
+  /// this color is fully opaque.
+  double get opacity => alpha / 0xFF;
+
+  /// The red channel of this color in an 8 bit value.
+  int get red => (0x00ff0000 & value) >> 16;
+
+  @override
+  bool operator ==(dynamic other) {
+    if (identical(this, other)) return true;
+    if (other.runtimeType != runtimeType) return false;
+    final Color typedOther = other;
+    return value == typedOther.value;
+  }
+
+  @override
+  String toString() => 'Color(0x${value.toRadixString(16).padLeft(8, '0')})';
+
+  /// Returns a new color that matches this color with the alpha channel
+  /// replaced with `a` (which ranges from 0 to 255).
+  ///
+  /// Out of range values will have unexpected effects.
+  Color withAlpha(int a) {
+    return Color.fromARGB(a, red, green, blue);
+  }
+
+  /// Returns a new color that matches this color with the blue channel replaced
+  /// with `b` (which ranges from 0 to 255).
+  ///
+  /// Out of range values will have unexpected effects.
+  Color withBlue(int b) {
+    return Color.fromARGB(alpha, red, green, b);
+  }
+
+  /// Returns a new color that matches this color with the green channel
+  /// replaced with `g` (which ranges from 0 to 255).
+  ///
+  /// Out of range values will have unexpected effects.
+  Color withGreen(int g) {
+    return Color.fromARGB(alpha, red, g, blue);
+  }
+
+  /// Returns a new color that matches this color with the alpha channel
+  /// replaced with the given `opacity` (which ranges from 0.0 to 1.0).
+  ///
+  /// Out of range values will have unexpected effects.
+  Color withOpacity(double opacity) {
+    assert(opacity >= 0.0 && opacity <= 1.0);
+    return withAlpha((255.0 * opacity).round());
+  }
+
+  /// Returns a new color that matches this color with the red channel replaced
+  /// with `r` (which ranges from 0 to 255).
+  ///
+  /// Out of range values will have unexpected effects.
+  Color withRed(int r) {
+    return Color.fromARGB(alpha, r, green, blue);
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_ranking_internal_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_ranking_internal_test.dart
index 77d58d3..1510b22 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_ranking_internal_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_ranking_internal_test.dart
@@ -11,14 +11,6 @@
 import 'package:mockito/mockito.dart';
 import 'package:test/test.dart';
 
-class MockCompletionRequest extends Mock implements DartCompletionRequest {}
-
-class MockCompletionTarget extends Mock implements CompletionTarget {}
-
-class MockAstNode extends Mock implements AstNode {}
-
-class MockToken extends Mock implements Token {}
-
 void main() {
   group('getCursorToken', () {
     MockCompletionRequest request;
@@ -267,3 +259,11 @@
         equals(true));
   });
 }
+
+class MockAstNode extends Mock implements AstNode {}
+
+class MockCompletionRequest extends Mock implements DartCompletionRequest {}
+
+class MockCompletionTarget extends Mock implements CompletionTarget {}
+
+class MockToken extends Mock implements Token {}
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 40cafbf..d98d3a3 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
@@ -9,10 +9,6 @@
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
-final directory = path.join(File.fromUri(Platform.script).parent.path, '..',
-    '..', '..', '..', 'language_model', 'lexeme');
-const expectedLookback = 100;
-
 void main() {
   if (sizeOf<IntPtr>() == 4) {
     // We don't yet support running tflite on 32-bit systems.
@@ -75,6 +71,11 @@
   });
 }
 
+const expectedLookback = 100;
+
+final directory = path.join(File.fromUri(Platform.script).parent.path, '..',
+    '..', '..', '..', 'language_model', 'lexeme');
+
 /// Tokenizes the input string.
 ///
 /// The input is split by word boundaries and trimmed of whitespace.
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 ca2f5f1..544d429 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
@@ -58,6 +58,34 @@
         equals("the default constructor of 'C'"));
   }
 
+  Future<void> test_classField() async {
+    addTestFile(r'''
+class C {
+  int i;
+}
+''');
+    var result = await resolveTestFile();
+    ClassDeclaration class_ = result.unit.declarations.single;
+    FieldDeclaration fieldDeclaration = class_.members.single;
+    var field = fieldDeclaration.fields.variables[0];
+    expect(InfoBuilder.buildEnclosingMemberDescription(field),
+        equals("the field 'C.i'"));
+  }
+
+  Future<void> test_classField_from_type() async {
+    addTestFile(r'''
+class C {
+  int i;
+}
+''');
+    var result = await resolveTestFile();
+    ClassDeclaration class_ = result.unit.declarations.single;
+    FieldDeclaration fieldDeclaration = class_.members.single;
+    var type = fieldDeclaration.fields.type;
+    expect(InfoBuilder.buildEnclosingMemberDescription(type),
+        equals("the field 'C.i'"));
+  }
+
   Future<void> test_classGetter() async {
     addTestFile(r'''
 class C {
@@ -178,6 +206,30 @@
     expect(InfoBuilder.buildEnclosingMemberDescription(setter),
         equals("the setter 'aaa='"));
   }
+
+  Future<void> test_topLevelVariable() async {
+    addTestFile(r'''
+int i;
+''');
+    var result = await resolveTestFile();
+    TopLevelVariableDeclaration topLevelVariableDeclaration =
+        result.unit.declarations.single;
+    var variable = topLevelVariableDeclaration.variables.variables[0];
+    expect(InfoBuilder.buildEnclosingMemberDescription(variable),
+        equals("the variable 'i'"));
+  }
+
+  Future<void> test_topLevelVariable_from_type() async {
+    addTestFile(r'''
+int i;
+''');
+    var result = await resolveTestFile();
+    TopLevelVariableDeclaration topLevelVariableDeclaration =
+        result.unit.declarations.single;
+    var type = topLevelVariableDeclaration.variables.type;
+    expect(InfoBuilder.buildEnclosingMemberDescription(type),
+        equals("the variable 'i'"));
+  }
 }
 
 @reflectiveTest
@@ -1804,6 +1856,85 @@
     assertTraceEntry(unit, entries[1], 'f', unit.content.indexOf('int?'));
   }
 
+  Future<void> test_trace_nullCheck_notNullableReason() async {
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+void f(int i) { // f
+  assert(i != null);
+}
+void g(int i) { // g
+  f(i); // call f
+}
+void h(int/*?*/ i) {
+  g(i);
+}
+''', migratedContent: '''
+void f(int i) { // f
+  assert(i != null);
+}
+void g(int i) { // g
+  f(i); // call f
+}
+void h(int?/*?*/ i) {
+  g(i!);
+}
+''');
+    var region = unit.regions
+        .where((regionInfo) => regionInfo.offset == unit.content.indexOf('!)'))
+        .single;
+    expect(region.traces, hasLength(2));
+    // Trace 0 is the nullability reason; we don't care about that right now.
+    // Trace 1 is the non-nullability reason.
+    var trace = region.traces[1];
+    expect(trace.description, 'Non-nullability reason');
+    var entries = trace.entries;
+    expect(entries, hasLength(5));
+    // Entry 0 is the nullability of g's argument
+    assertTraceEntry(
+        unit, entries[0], 'g', unit.content.indexOf('int i) { // g'));
+    // Entry 1 is the edge from g's argument to f's argument, due to g's call to
+    // f.
+    assertTraceEntry(
+        unit, entries[1], 'g', unit.content.indexOf('i); // call f'));
+    // Entry 2 is the nullability of f's argument
+    assertTraceEntry(
+        unit, entries[2], 'f', unit.content.indexOf('int i) { // f'));
+    // Entry 3 is the edge f's argument to never, due to the assert.
+    assertTraceEntry(unit, entries[3], 'f', unit.content.indexOf('assert'));
+    // Entry 4 is the "never" node.
+    // TODO(paulberry): this node provides no additional useful information and
+    // shouldn't be included in the trace.
+    expect(entries[4].description, 'never');
+    expect(entries[4].function, null);
+    expect(entries[4].target, null);
+  }
+
+  Future<void> test_trace_substitutionNode() async {
+    UnitInfo unit = await buildInfoForSingleTestFile('''
+class C<T extends Object/*!*/> {}
+
+C<int /*?*/ > c;
+
+Map<int, String> x = {};
+String/*!*/ y = x[0];
+''', migratedContent: '''
+class C<T extends Object/*!*/> {}
+
+C<int? /*?*/ >? c;
+
+Map<int, String> x = {};
+String/*!*/ y = x[0]!;
+''');
+    var region = unit.regions
+        .where((regionInfo) => regionInfo.offset == unit.content.indexOf('!;'))
+        .single;
+    // The "why nullable" node associated with adding the `!` is a substitution
+    // node, and we don't currently generate a trace for a substitution node.
+    // TODO(paulberry): fix this.
+    // We do, however, generate a trace for "why not nullable".
+    expect(region.traces, hasLength(1));
+    expect(region.traces[0].description, 'Non-nullability reason');
+  }
+
   Future<void> test_uninitializedField() async {
     UnitInfo unit = await buildInfoForSingleTestFile('''
 class C {
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/instrumentation_renderer_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/instrumentation_renderer_test.dart
index 15d9cc8..a680df94 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/instrumentation_renderer_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/instrumentation_renderer_test.dart
@@ -30,6 +30,13 @@
     return instrumentationRenderer.render();
   }
 
+  Future<void> test_appliedStyle() async {
+    var renderedView = await renderViewForTestFiles(
+        {convertPath('/project/lib/a.dart'): 'int a = null;'},
+        applied: true);
+    expect(renderedView, contains('<body class="applied">'));
+  }
+
   Future<void> test_navigation_containsRoot() async {
     var renderedView = await renderViewForTestFiles(
         {convertPath('/project/lib/a.dart'): 'int a = null;'});
@@ -43,11 +50,4 @@
         applied: false);
     expect(renderedView, contains('<body class="proposed">'));
   }
-
-  Future<void> test_appliedStyle() async {
-    var renderedView = await renderViewForTestFiles(
-        {convertPath('/project/lib/a.dart'): 'int a = null;'},
-        applied: true);
-    expect(renderedView, contains('<body class="applied">'));
-  }
 }
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/navigation_tree_renderer_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/navigation_tree_renderer_test.dart
index 371d79c..c4b308e 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/navigation_tree_renderer_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/navigation_tree_renderer_test.dart
@@ -2,11 +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 jsonDecode;
-
 import 'package:analysis_server/src/edit/nnbd_migration/migration_info.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/navigation_tree_renderer.dart';
 import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/web/navigation_tree.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -14,83 +13,17 @@
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(JsonMapTypeMatcherTest);
     defineReflectiveTests(NavigationTreeRendererTest);
   });
 }
 
-const isJsonMap = TypeMatcher<Map<String, dynamic>>();
-
-@reflectiveTest
-class JsonMapTypeMatcherTest {
-  void test_containing_doesNotMatch_invalidMatchers() {
-    expect(
-        isJsonMap.containing({'a': isJsonMap}).matches({
-          'a': [1, 2, 3]
-        }, {}),
-        isFalse);
-  }
-
-  void test_containing_doesNotMatch_invalidMatchers_list() {
-    expect(
-        isJsonMap.containing({
-          'a': isJsonMap.containing({
-            'b': [1, 2, 3]
-          })
-        }).matches({
-          'a': {
-            'b': [1, 2, 3, 4]
-          }
-        }, {}),
-        isFalse);
-  }
-
-  void test_containing_doesNotMatch_invalidValues() {
-    expect(isJsonMap.containing({'a': 1}).matches({'a': 2}, {}), isFalse);
-  }
-
-  void test_containing_matches_validMatchers() {
-    expect(
-        isJsonMap.containing({'a': isJsonMap}).matches(
-            {'a': <String, dynamic>{}}, {}),
-        isTrue);
-  }
-
-  void test_containing_matches_validMatchers_list() {
-    expect(
-        isJsonMap.containing({
-          'a': isJsonMap.containing({
-            'b': [1, 2, 3]
-          })
-        }).matches({
-          'a': {
-            'b': [1, 2, 3]
-          }
-        }, {}),
-        isTrue);
-  }
-
-  void test_containing_matches_validValues() {
-    expect(isJsonMap.containing({'a': 1}).matches({'a': 1}, {}), isTrue);
-  }
-
-  void test_isJsonMap_doesNotMatch_nonMaps() {
-    expect(isJsonMap.matches([], {}), isFalse);
-  }
-
-  void test_isJsonMap_doesNotMatch_nonStringKeyedMaps() {
-    expect(isJsonMap.matches(<int, int>{}, {}), isFalse);
-  }
-
-  void test_isJsonMap_matchesStringKeyedMaps() {
-    expect(isJsonMap.matches(<String, dynamic>{}, {}), isTrue);
-  }
-}
+const isNavigationTreeNode = TypeMatcher<NavigationTreeNode>();
 
 @reflectiveTest
 class NavigationTreeRendererTest extends NnbdMigrationTestBase {
   /// Render the navigation tree view for [files].
-  Future<String> renderNavigationTree(Map<String, String> files) async {
+  Future<List<NavigationTreeNode>> renderNavigationTree(
+      Map<String, String> files) async {
     var packageRoot = convertPath('/project');
     await buildInfoForTestFiles(files, includedRoot: packageRoot);
     MigrationInfo migrationInfo =
@@ -100,190 +33,173 @@
   }
 
   Future<void> test_containsEditCounts() async {
-    var response = jsonDecode(await renderNavigationTree({
+    var response = await renderNavigationTree({
       convertPath('/project/lib/a.dart'): 'int a = 1;',
       convertPath('/project/lib/b.dart'): 'int b = null;',
       convertPath('/project/lib/c.dart'): 'int c = null;\nint d = null;',
-    }));
+    });
 
     var libNode = response[0];
     expect(
         libNode,
-        isJsonMap.containing({
-          'subtree': [
-            isJsonMap.containing({'editCount': 0}),
-            isJsonMap.containing({'editCount': 1}),
-            isJsonMap.containing({'editCount': 2})
-          ]
-        }));
+        isNavigationTreeNode.havingSubtree([
+          isNavigationTreeNode.havingEditCount(0),
+          isNavigationTreeNode.havingEditCount(1),
+          isNavigationTreeNode.havingEditCount(2)
+        ]));
   }
 
   Future<void> test_containsHrefs() async {
-    var response = jsonDecode(await renderNavigationTree({
+    var response = await renderNavigationTree({
       convertPath('/project/lib/a.dart'): 'int a = null;',
       convertPath('/project/lib/src/b.dart'): 'int b = null;',
       convertPath('/project/tool.dart'): 'int c = null;',
-    }));
+    });
 
     var libNode = response[0];
     expect(
         libNode,
-        isJsonMap.containing({
-          'name': 'lib',
-          'subtree': [
-            isJsonMap.containing({
-              'name': 'src',
-              'subtree': [
-                isJsonMap.containing({'href': '/project/lib/src/b.dart'})
-              ]
-            }),
-            isJsonMap.containing({'href': '/project/lib/a.dart'})
-          ]
-        }));
+        isNavigationTreeNode.named('lib').havingSubtree([
+          isNavigationTreeNode.named('src').havingSubtree(
+              [isNavigationTreeNode.havingHref('/project/lib/src/b.dart')]),
+          isNavigationTreeNode.havingHref('/project/lib/a.dart')
+        ]));
 
     var toolNode = response[1];
-    expect(toolNode['href'], '/project/tool.dart');
+    expect(toolNode.href, '/project/tool.dart');
   }
 
   Future<void> test_containsMultipleLinks_multipleDepths() async {
-    var response = jsonDecode(await renderNavigationTree({
+    var response = await renderNavigationTree({
       convertPath('/project/lib/a.dart'): 'int a = null;',
       convertPath('/project/lib/src/b.dart'): 'int b = null;',
       convertPath('/project/tool.dart'): 'int c = null;',
-    }));
+    });
     expect(response, hasLength(2));
 
     var libNode = response[0];
     expect(
         libNode,
-        isJsonMap.containing({
-          'name': 'lib',
-          'subtree': [
-            isJsonMap.containing({
-              'name': 'src',
-              'subtree': [
-                isJsonMap.containing({'name': 'b.dart'})
-              ]
-            }),
-            isJsonMap.containing({'name': 'a.dart'})
-          ]
-        }));
+        isNavigationTreeNode.named('lib').havingSubtree([
+          isNavigationTreeNode
+              .named('src')
+              .havingSubtree([isNavigationTreeNode.named('b.dart')]),
+          isNavigationTreeNode.named('a.dart')
+        ]));
 
     var toolNode = response[1];
-    expect(toolNode['name'], 'tool.dart');
+    expect(toolNode.name, 'tool.dart');
   }
 
   Future<void> test_containsMultipleLinks_multipleRoots() async {
-    var response = jsonDecode(await renderNavigationTree({
+    var response = await renderNavigationTree({
       convertPath('/project/bin/bin.dart'): 'int c = null;',
       convertPath('/project/lib/a.dart'): 'int a = null;',
-    }));
+    });
     expect(response, hasLength(2));
 
     var binNode = response[0];
-    expect(binNode['type'], equals('directory'));
-    expect(binNode['name'], equals('bin'));
-    expect(binNode['subtree'], hasLength(1));
+    expect(binNode.type, equals(NavigationTreeNodeType.directory));
+    expect(binNode.name, equals('bin'));
+    expect(binNode.subtree, hasLength(1));
 
     var libNode = response[1];
-    expect(libNode['type'], equals('directory'));
-    expect(libNode['name'], equals('lib'));
-    expect(libNode['subtree'], hasLength(1));
+    expect(libNode.type, equals(NavigationTreeNodeType.directory));
+    expect(libNode.name, equals('lib'));
+    expect(libNode.subtree, hasLength(1));
   }
 
   Future<void> test_containsMultipleLinks_sameDepth() async {
-    var response = jsonDecode(await renderNavigationTree({
+    var response = await renderNavigationTree({
       convertPath('/project/lib/a.dart'): 'int a = null;',
       convertPath('/project/lib/b.dart'): 'int b = null;',
-    }));
+    });
     expect(response, hasLength(1));
 
     var libNode = response[0];
     expect(
         libNode,
-        isJsonMap.containing({
-          'name': 'lib',
-          'subtree': [
-            isJsonMap.containing({
-              'name': 'a.dart',
-              'path': convertPath('lib/a.dart'),
-              'href': '/project/lib/a.dart'
-            }),
-            isJsonMap.containing({
-              'name': 'b.dart',
-              'path': convertPath('lib/b.dart'),
-              'href': '/project/lib/b.dart'
-            })
-          ]
-        }));
+        isNavigationTreeNode.named('lib').havingSubtree([
+          isNavigationTreeNode
+              .named('a.dart')
+              .havingPath(convertPath('lib/a.dart'))
+              .havingHref('/project/lib/a.dart'),
+          isNavigationTreeNode
+              .named('b.dart')
+              .havingPath(convertPath('lib/b.dart'))
+              .havingHref('/project/lib/b.dart')
+        ]));
   }
 
   Future<void> test_containsPaths() async {
-    var response = jsonDecode(await renderNavigationTree({
+    var response = await renderNavigationTree({
       convertPath('/project/lib/a.dart'): 'int a = null;',
       convertPath('/project/lib/src/b.dart'): 'int b = null;',
       convertPath('/project/tool.dart'): 'int c = null;',
-    }));
+    });
 
     var libNode = response[0];
     expect(
         libNode,
-        isJsonMap.containing({
-          'name': 'lib',
-          'subtree': [
-            isJsonMap.containing({
-              'name': 'src',
-              'subtree': [
-                isJsonMap.containing({'path': convertPath('lib/src/b.dart')})
-              ]
-            }),
-            isJsonMap.containing({'path': convertPath('lib/a.dart')})
-          ]
-        }));
+        isNavigationTreeNode.named('lib').havingSubtree([
+          isNavigationTreeNode.named('src').havingSubtree(
+              [isNavigationTreeNode.havingPath(convertPath('lib/src/b.dart'))]),
+          isNavigationTreeNode.havingPath(convertPath('lib/a.dart'))
+        ]));
 
     var toolNode = response[1];
-    expect(toolNode['path'], 'tool.dart');
+    expect(toolNode.path, 'tool.dart');
   }
 
   Future<void> test_containsSingleLink_deep() async {
-    var response = jsonDecode(await renderNavigationTree({
+    var response = await renderNavigationTree({
       convertPath('/project/lib/src/a.dart'): 'int a = null;',
-    }));
+    });
     expect(response, hasLength(1));
 
     var libNode = response[0];
     expect(
         libNode,
-        isJsonMap.containing({
-          'name': 'lib',
-          'subtree': [
-            isJsonMap.containing({
-              'name': 'src',
-              'subtree': [
-                isJsonMap.containing({
-                  'name': 'a.dart',
-                  'path': convertPath('lib/src/a.dart'),
-                  'href': '/project/lib/src/a.dart'
-                })
-              ]
-            })
-          ]
-        }));
+        isNavigationTreeNode.named('lib').havingSubtree([
+          isNavigationTreeNode.named('src').havingSubtree([
+            isNavigationTreeNode
+                .named('a.dart')
+                .havingPath(convertPath('lib/src/a.dart'))
+                .havingHref('/project/lib/src/a.dart')
+          ])
+        ]));
   }
 
   Future<void> test_containsSingleLink_shallow() async {
-    var response = jsonDecode(await renderNavigationTree({
+    var response = await renderNavigationTree({
       convertPath('/project/a.dart'): 'int a = null;',
-    }));
+    });
     expect(response, hasLength(1));
 
     var aNode = response[0];
-    expect(aNode['name'], 'a.dart');
-    expect(aNode['path'], 'a.dart');
-    expect(aNode['href'], '/project/a.dart');
+    expect(aNode.name, 'a.dart');
+    expect(aNode.path, 'a.dart');
+    expect(aNode.href, '/project/a.dart');
   }
 }
 
+extension on TypeMatcher<NavigationTreeNode> {
+  TypeMatcher<NavigationTreeNode> havingSubtree(dynamic matcher) =>
+      having((node) => node.subtree, 'subtree', matcher);
+
+  TypeMatcher<NavigationTreeNode> havingEditCount(dynamic matcher) =>
+      having((node) => node.editCount, 'editCount', matcher);
+
+  TypeMatcher<NavigationTreeNode> named(dynamic matcher) =>
+      having((node) => node.name, 'name', matcher);
+
+  TypeMatcher<NavigationTreeNode> havingHref(dynamic matcher) =>
+      having((node) => node.href, 'href', matcher);
+
+  TypeMatcher<NavigationTreeNode> havingPath(dynamic matcher) =>
+      having((node) => node.path, 'path', matcher);
+}
+
 extension _E<T, U> on TypeMatcher<Map<T, U>> {
   TypeMatcher<Map<T, U>> containing(Map<T, dynamic> matchers) {
     var result = this;
diff --git a/pkg/analysis_server/test/src/edit/nnbd_migration/unit_renderer_test.dart b/pkg/analysis_server/test/src/edit/nnbd_migration/unit_renderer_test.dart
index d2832d6..b719f79 100644
--- a/pkg/analysis_server/test/src/edit/nnbd_migration/unit_renderer_test.dart
+++ b/pkg/analysis_server/test/src/edit/nnbd_migration/unit_renderer_test.dart
@@ -2,11 +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 jsonDecode;
-
 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/nnbd_migration/unit_renderer.dart';
+import 'package:analysis_server/src/edit/nnbd_migration/web/file_details.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -22,12 +21,12 @@
 class UnitRendererTest extends NnbdMigrationTestBase {
   /// Render [libraryInfo], using a [MigrationInfo] which knows only about this
   /// library.
-  List<String> renderUnits() {
+  List<FileDetails> renderUnits() {
     String packageRoot = convertPath('/package');
     MigrationInfo migrationInfo =
         MigrationInfo(infos, {}, resourceProvider.pathContext, packageRoot);
 
-    List<String> contents = [];
+    List<FileDetails> contents = [];
     for (UnitInfo unitInfo in infos) {
       contents.add(
           UnitRenderer(unitInfo, migrationInfo, PathMapper(resourceProvider))
@@ -44,9 +43,8 @@
 int? a = null;
 bool b = a!.isEven;
 ''');
-    var outputJson = renderUnits()[0];
-    var output = jsonDecode(outputJson);
-    var editList = output['edits'];
+    var output = renderUnits()[0];
+    var editList = output.edits;
     expect(editList, hasLength(2));
   }
 
@@ -58,16 +56,15 @@
 int? a = null;
 bool b = a!.isEven;
 ''');
-    var outputJson = renderUnits()[0];
-    var editList = jsonDecode(outputJson);
-    expect(editList['edits'], hasLength(2));
-    expect(editList['edits'][0]['line'], equals(1));
-    expect(editList['edits'][0]['offset'], equals(3));
-    expect(editList['edits'][0]['explanation'],
+    var output = renderUnits()[0];
+    expect(output.edits, hasLength(2));
+    expect(output.edits[0].line, equals(1));
+    expect(output.edits[0].offset, equals(3));
+    expect(output.edits[0].explanation,
         equals("Changed type 'int' to be nullable"));
-    expect(editList['edits'][1]['line'], equals(2));
-    expect(editList['edits'][1]['offset'], equals(25));
-    expect(editList['edits'][1]['explanation'],
+    expect(output.edits[1].line, equals(2));
+    expect(output.edits[1].offset, equals(25));
+    expect(output.edits[1].explanation,
         equals('Added a non-null assertion to nullable expression'));
   }
 
@@ -123,10 +120,9 @@
 
 List<int?> x = [null];
 ''', removeViaComments: false);
-    var outputJson = renderUnits()[0];
-    var output = jsonDecode(outputJson);
+    var output = renderUnits()[0];
     // Strip out URLs and span IDs; they're not being tested here.
-    var navContent = output['navigationContent']
+    var navContent = output.navigationContent
         .replaceAll(RegExp('href="[^"]*"'), 'href="..."')
         .replaceAll(RegExp('id="[^"]*"'), 'id="..."');
     expect(navContent, '''
@@ -146,12 +142,10 @@
   Future<void> test_navContentContainsEscapedHtml() async {
     await buildInfoForSingleTestFile('List<String> a = null;',
         migratedContent: 'List<String>? a = null;');
-    var outputJson = renderUnits()[0];
-
-    var output = jsonDecode(outputJson);
+    var output = renderUnits()[0];
     // Strip out URLs which will change; not being tested here.
-    var navContent = output['navigationContent']
-        .replaceAll(RegExp('href=".*?"'), 'href="..."');
+    var navContent =
+        output.navigationContent.replaceAll(RegExp('href=".*?"'), 'href="..."');
     expect(
         navContent,
         contains(r'<a href="..." class="nav-link">List</a>'
@@ -162,9 +156,8 @@
   Future<void> test_outputContainsModifiedAndUnmodifiedRegions() async {
     await buildInfoForSingleTestFile('int a = null;',
         migratedContent: 'int? a = null;');
-    var outputJson = renderUnits()[0];
-    var output = jsonDecode(outputJson);
-    var regions = _stripDataAttributes(output['regions']);
+    var output = renderUnits()[0];
+    var regions = _stripDataAttributes(output.regions);
     expect(regions,
         contains('int<span class="region added-region">?</span> a = null;'));
   }
@@ -187,9 +180,9 @@
     };
     var packageRoot = convertPath('/project');
     await buildInfoForTestFiles(files, includedRoot: packageRoot);
-    var outputJson = renderUnits();
-    expect(jsonDecode(outputJson[0])['sourceCode'], contains('int?'));
-    expect(jsonDecode(outputJson[1])['sourceCode'], contains('int?'));
+    var output = renderUnits();
+    expect(output[0].sourceCode, contains('int?'));
+    expect(output[1].sourceCode, contains('int?'));
   }
 
   Future<void> test_reference_to_sdk_file_with_parts() async {
@@ -211,17 +204,15 @@
   Future<void> test_regionsContainsEscapedHtml_ampersand() async {
     await buildInfoForSingleTestFile('bool a = true && false;',
         migratedContent: 'bool a = true && false;');
-    var outputJson = renderUnits()[0];
-    var output = jsonDecode(outputJson);
-    expect(output['regions'], contains('bool a = true &amp;&amp; false;'));
+    var output = renderUnits()[0];
+    expect(output.regions, contains('bool a = true &amp;&amp; false;'));
   }
 
   Future<void> test_regionsContainsEscapedHtml_betweenRegions() async {
     await buildInfoForSingleTestFile('List<String> a = null;',
         migratedContent: 'List<String>? a = null;');
-    var outputJson = renderUnits()[0];
-    var output = jsonDecode(outputJson);
-    var regions = _stripDataAttributes(output['regions']);
+    var output = renderUnits()[0];
+    var regions = _stripDataAttributes(output.regions);
     expect(
         regions,
         contains('List&lt;String&gt;'
@@ -231,9 +222,8 @@
   Future<void> test_regionsContainsEscapedHtml_region() async {
     await buildInfoForSingleTestFile('f(List<String> a) => a.join(",");',
         migratedContent: 'f(List<String> a) => a.join(",");');
-    var outputJson = renderUnits()[0];
-    var output = jsonDecode(outputJson);
-    var regions = _stripDataAttributes(output['regions']);
+    var output = renderUnits()[0];
+    var regions = _stripDataAttributes(output.regions);
     expect(
         regions,
         contains(
diff --git a/pkg/analysis_server/test/src/edit/preview/preview_site_test.dart b/pkg/analysis_server/test/src/edit/preview/preview_site_test.dart
index f21fd48..8d51c29 100644
--- a/pkg/analysis_server/test/src/edit/preview/preview_site_test.dart
+++ b/pkg/analysis_server/test/src/edit/preview/preview_site_test.dart
@@ -8,10 +8,10 @@
 import 'package:analysis_server/src/edit/nnbd_migration/path_mapper.dart';
 import 'package:analysis_server/src/edit/preview/preview_site.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 
 void main() {
   defineReflectiveSuite(() {
@@ -32,7 +32,7 @@
     state = MigrationState(null, null, dartfixListener, null, null);
     state.pathMapper = PathMapper(resourceProvider);
     state.migrationInfo = migrationInfo;
-    site = PreviewSite(state);
+    site = PreviewSite(state, (_) => null);
   }
 
   void test_applyChangesEmpty() {
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 ff6b144..eec3b63 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
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -363,6 +364,38 @@
     await assertNoFix();
   }
 
+  Future<void> test_inPart_imported() async {
+    addSource('/home/test/lib/a.dart', '''
+part of lib;
+class A {}
+''');
+
+    await resolveTestUnit('''
+import 'package:test/a.dart';
+
+main(A a) {
+  int v = a.test;
+  print(v);
+}
+''');
+    await assertNoFix(errorFilter: (e) {
+      return e.errorCode == StaticTypeWarningCode.UNDEFINED_GETTER;
+    });
+  }
+
+  Future<void> test_inPart_self() async {
+    await resolveTestUnit('''
+part of lib;
+class A {
+}
+main(A a) {
+  int v = a.test;
+  print(v);
+}
+''');
+    await assertNoFix();
+  }
+
   Future<void> test_inSDK() async {
     await resolveTestUnit('''
 main(List p) {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
index 8df95c5..e2f4017 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
@@ -161,6 +161,32 @@
 ''');
   }
 
+  Future<void> test_withClass_catchClause() async {
+    addSource('/home/test/lib/lib.dart', '''
+class Test {}
+''');
+    await resolveTestUnit('''
+void f() {
+  try {
+    print(1);
+  } on Test {
+    print(2);
+  }
+}
+''');
+    await assertHasFix('''
+import 'package:test/lib.dart';
+
+void f() {
+  try {
+    print(1);
+  } on Test {
+    print(2);
+  }
+}
+''');
+  }
+
   Future<void> test_withClass_hasOtherLibraryWithPrefix() async {
     addSource('/home/test/lib/a.dart', '''
 library a;
@@ -495,32 +521,6 @@
     });
   }
 
-  Future<void> test_withClass_catchClause() async {
-    addSource('/home/test/lib/lib.dart', '''
-class Test {}
-''');
-    await resolveTestUnit('''
-void f() {
-  try {
-    print(1);
-  } on Test {
-    print(2);
-  }
-}
-''');
-    await assertHasFix('''
-import 'package:test/lib.dart';
-
-void f() {
-  try {
-    print(1);
-  } on Test {
-    print(2);
-  }
-}
-''');
-  }
-
   Future<void> test_withTopLevelVariable() async {
     addSource('/home/test/lib/lib.dart', '''
 library lib;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_const_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_const_test.dart
new file mode 100644
index 0000000..0e0d309
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_const_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveConstTest);
+  });
+}
+
+@reflectiveTest
+class RemoveConstTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_CONST;
+
+  Future<void> test_const_with_non_const() async {
+    await resolveTestUnit('''
+class A {
+  A();
+}
+void f() {
+  var a = const A();
+  print(a);
+}
+''');
+    await assertHasFix('''
+class A {
+  A();
+}
+void f() {
+  var a = A();
+  print(a);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_interpolation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_interpolation_test.dart
new file mode 100644
index 0000000..191e1bb
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_interpolation_test.dart
@@ -0,0 +1,191 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReplaceWithInterpolationTest);
+  });
+}
+
+@reflectiveTest
+class ReplaceWithInterpolationTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REPLACE_WITH_INTERPOLATION;
+
+  @override
+  String get lintCode => LintNames.prefer_interpolation_to_compose_strings;
+
+  Future<void> test_stringLiteral_binaryExpression_stringConcatenation() async {
+    await resolveTestUnit('''
+var b = ['b', 'c'];
+var c = 'a' + b[0] + b[1];
+''');
+    await assertHasFix(r'''
+var b = ['b', 'c'];
+var c = 'a${b[0]}${b[1]}';
+''');
+  }
+
+  Future<void> test_stringLiteral_expression_toString() async {
+    await resolveTestUnit('''
+var b = [1];
+var c = 'a' + b[0].toString();
+''');
+    await assertHasFix(r'''
+var b = [1];
+var c = 'a${b[0]}';
+''');
+  }
+
+  Future<void> test_stringLiteral_indexExpression() async {
+    await resolveTestUnit('''
+var b = ['b'];
+var c = 'a' + b[0];
+''');
+    await assertHasFix(r'''
+var b = ['b'];
+var c = 'a${b[0]}';
+''');
+  }
+
+  Future<void> test_stringLiteral_parenthesizedExpression() async {
+    await resolveTestUnit('''
+var b = ['b'];
+var c = 'a' + (b[0]);
+''');
+    await assertHasFix(r'''
+var b = ['b'];
+var c = 'a${b[0]}';
+''');
+  }
+
+  Future<void> test_stringLiteral_parenthesizedExpression_toString() async {
+    await resolveTestUnit('''
+var a = 1;
+var b = 2;
+var c = 'a' + (a + b).toString();
+''');
+    await assertHasFix(r'''
+var a = 1;
+var b = 2;
+var c = 'a${a + b}';
+''');
+  }
+
+  Future<void> test_stringLiteral_variable_notRaw_double_multi() async {
+    await resolveTestUnit('''
+var b = 'b';
+var c = """a""" + b;
+''');
+    await assertHasFix(r'''
+var b = 'b';
+var c = """a$b""";
+''');
+  }
+
+  Future<void> test_stringLiteral_variable_notRaw_double_notMulti() async {
+    await resolveTestUnit('''
+var b = 'b';
+var c = "a" + b;
+''');
+    await assertHasFix(r'''
+var b = 'b';
+var c = "a$b";
+''');
+  }
+
+  Future<void> test_stringLiteral_variable_notRaw_single_multi() async {
+    await resolveTestUnit("""
+var b = 'b';
+var c = '''a''' + b;
+""");
+    await assertHasFix(r"""
+var b = 'b';
+var c = '''a$b''';
+""");
+  }
+
+  Future<void> test_stringLiteral_variable_notRaw_single_notMulti() async {
+    await resolveTestUnit('''
+var b = 'b';
+var c = 'a' + b;
+''');
+    await assertHasFix(r'''
+var b = 'b';
+var c = 'a$b';
+''');
+  }
+
+  Future<void> test_stringLiteral_variable_raw_single_notMulti() async {
+    await resolveTestUnit('''
+var b = 'b';
+var c = r'a' + b;
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_stringLiteral_variable_withEscapes() async {
+    await resolveTestUnit(r'''
+var b = 'b';
+var c = '\$a' + b;
+''');
+    await assertHasFix(r'''
+var b = 'b';
+var c = '\$a$b';
+''');
+  }
+
+  Future<void> test_variable_adjacentStrings() async {
+    await resolveTestUnit('''
+var a = 'a';
+var c = a + 'b' 'c';
+''');
+    await assertHasFix(r'''
+var a = 'a';
+var c = '${a}bc';
+''');
+  }
+
+  Future<void> test_variable_stringLiteral_noRuntogther() async {
+    await resolveTestUnit('''
+var a = 'a';
+var c = a + ' b';
+''');
+    await assertHasFix(r'''
+var a = 'a';
+var c = '$a b';
+''');
+  }
+
+  Future<void> test_variable_stringLiteral_runtogther() async {
+    await resolveTestUnit('''
+var a = 'a';
+var c = a + 'b';
+''');
+    await assertHasFix(r'''
+var a = 'a';
+var c = '${a}b';
+''');
+  }
+
+  Future<void> test_variable_stringLiteral_variable() async {
+    await resolveTestUnit('''
+var a = 'a';
+var z = 'z';
+var c = a + '...' + z;
+''');
+    await assertHasFix(r'''
+var a = 'a';
+var z = 'z';
+var c = '$a...$z';
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 3b49d2a..9fdf630 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -93,6 +93,7 @@
 import 'remove_annotation_test.dart' as remove_annotation;
 import 'remove_argument_test.dart' as remove_argument;
 import 'remove_await_test.dart' as remove_await;
+import 'remove_const_test.dart' as remove_const;
 import 'remove_dead_code_test.dart' as remove_dead_code;
 import 'remove_duplicate_case_test.dart' as remove_duplicate_case;
 import 'remove_empty_catch_test.dart' as remove_empty_catch;
@@ -137,6 +138,7 @@
 import 'replace_with_eight_digit_hex_test.dart' as replace_with_eight_digit_hex;
 import 'replace_with_extension_name_test.dart' as replace_with_extension_name;
 import 'replace_with_identifier_test.dart' as replace_with_identifier;
+import 'replace_with_interpolation_test.dart' as replace_with_interpolation;
 import 'replace_with_is_empty_test.dart' as replace_with_is_empty;
 import 'replace_with_is_not_empty_test.dart' as replace_with_is_not_empty;
 import 'replace_with_null_aware_test.dart' as replace_with_null_aware;
@@ -152,6 +154,7 @@
 import 'use_not_eq_null_test.dart' as use_not_eq_null;
 import 'use_rethrow_test.dart' as use_rethrow;
 import 'wrap_in_future_test.dart' as wrap_in_future;
+import 'wrap_in_text_test.dart' as wrap_in_text;
 
 void main() {
   defineReflectiveSuite(() {
@@ -233,6 +236,7 @@
     remove_annotation.main();
     remove_argument.main();
     remove_await.main();
+    remove_const.main();
     remove_dead_code.main();
     remove_duplicate_case.main();
     remove_empty_catch.main();
@@ -273,6 +277,7 @@
     replace_with_eight_digit_hex.main();
     replace_with_extension_name.main();
     replace_with_identifier.main();
+    replace_with_interpolation.main();
     replace_with_is_empty.main();
     replace_with_is_not_empty.main();
     replace_with_null_aware.main();
@@ -287,5 +292,6 @@
     use_not_eq_null.main();
     use_rethrow.main();
     wrap_in_future.main();
+    wrap_in_text.main();
   }, name: 'fix');
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/wrap_in_text_test.dart b/pkg/analysis_server/test/src/services/correction/fix/wrap_in_text_test.dart
new file mode 100644
index 0000000..a04df7c
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/wrap_in_text_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(WrapInTextTest);
+  });
+}
+
+@reflectiveTest
+class WrapInTextTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.WRAP_IN_TEXT;
+
+  @override
+  void setUp() {
+    super.setUp();
+    addFlutterPackage();
+  }
+
+  Future<void> test_literal() async {
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+Widget f() => Center(child: 'aaa');
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+Widget f() => Center(child: Text('aaa'));
+''');
+  }
+
+  Future<void> test_notString() async {
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+Widget center(int i) => Center(child: i);
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_notWidget() async {
+    await resolveTestUnit('''
+void f(int i) {
+  f('a');
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_variable() async {
+    await resolveTestUnit('''
+import 'package:flutter/material.dart';
+Widget center(String s) => Center(child: s);
+''');
+    await assertHasFix('''
+import 'package:flutter/material.dart';
+Widget center(String s) => Center(child: Text(s));
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart b/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart
index b0163d8..fb4c0c5 100644
--- a/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart
+++ b/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart
@@ -7,6 +7,41 @@
 import '../../../tool/completion_metrics/metrics_util.dart';
 
 void main() {
+  group('ArithmeticMeanComputer', () {
+    test('empty', () {
+      var computer = ArithmeticMeanComputer('empty');
+      expect(computer.sum, equals(0));
+      expect(computer.count, equals(0));
+    });
+
+    test('clear', () {
+      var computer = ArithmeticMeanComputer('name');
+      computer.addValue(5);
+      computer.addValue(5);
+      computer.addValue(5);
+
+      expect(computer.sum, equals(15));
+      expect(computer.count, equals(3));
+      computer.clear();
+
+      expect(computer.sum, equals(0));
+      expect(computer.count, equals(0));
+    });
+
+    test('mean', () {
+      var computer = ArithmeticMeanComputer('name');
+      computer.addValue(1);
+      computer.addValue(2);
+      computer.addValue(3);
+      computer.addValue(4);
+      computer.addValue(5);
+
+      expect(computer.sum, equals(15));
+      expect(computer.count, equals(5));
+      expect(computer.mean, equals(15 / 5));
+    });
+  });
+
   group('Counter', () {
     test('empty', () {
       var counter = Counter('empty');
diff --git a/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart b/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart
index 9a3d26f..7ead849 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/dart_test.dart
@@ -28,10 +28,10 @@
   });
 }
 
+ast.ArrayType _array(String name) => ast.ArrayType(_simple(name));
+
 ast.Type _simple(String name) =>
     ast.Type(ast.Token(ast.TokenType.IDENTIFIER, name), []);
 
-ast.ArrayType _array(String name) => ast.ArrayType(_simple(name));
-
 ast.UnionType _union(List<String> names) =>
     ast.UnionType(names.map(_simple).toList());
diff --git a/pkg/analysis_server/test/tool/lsp_spec/matchers.dart b/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
index 41b0a46..9744f04 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
@@ -7,18 +7,66 @@
 
 import '../../../tool/lsp_spec/typescript_parser.dart';
 
+Matcher isArrayOf(Matcher matcher) => ArrayTypeMatcher(wrapMatcher(matcher));
+
+Matcher isMapOf(Matcher indexMatcher, Matcher valueMatcher) =>
+    MapTypeMatcher(wrapMatcher(indexMatcher), wrapMatcher(valueMatcher));
+
+Matcher isResponseError(ErrorCodes code) => const TypeMatcher<ResponseError>()
+    .having((e) => e.code, 'code', equals(code));
+
 Matcher isSimpleType(String name) => SimpleTypeMatcher(name);
 
+class ArrayTypeMatcher extends Matcher {
+  final Matcher _elementTypeMatcher;
+  const ArrayTypeMatcher(this._elementTypeMatcher);
+
+  @override
+  Description describe(Description description) =>
+      description.add('an array of ').addDescriptionOf(_elementTypeMatcher);
+
+  @override
+  Description describeMismatch(
+      item, Description mismatchDescription, Map matchState, bool verbose) {
+    if (item is ArrayType) {
+      return _elementTypeMatcher.describeMismatch(
+          item, mismatchDescription, matchState, verbose);
+    } else {
+      return mismatchDescription.add('is not an ArrayType');
+    }
+  }
+
+  @override
+  bool matches(item, Map matchState) {
+    return item is ArrayType &&
+        _elementTypeMatcher.matches(item.elementType, matchState);
+  }
+}
+
+class MapTypeMatcher extends Matcher {
+  final Matcher _indexMatcher, _valueMatcher;
+  const MapTypeMatcher(this._indexMatcher, this._valueMatcher);
+
+  @override
+  Description describe(Description description) => description
+      .add('a MapType where index is ')
+      .addDescriptionOf(_indexMatcher)
+      .add(' and value is ')
+      .addDescriptionOf(_valueMatcher);
+
+  @override
+  bool matches(item, Map matchState) {
+    return item is MapType &&
+        _indexMatcher.matches(item.indexType, matchState) &&
+        _valueMatcher.matches(item.valueType, matchState);
+  }
+}
+
 class SimpleTypeMatcher extends Matcher {
   final String _expectedName;
   const SimpleTypeMatcher(this._expectedName);
 
   @override
-  bool matches(item, Map matchState) {
-    return item is Type && item.name == _expectedName;
-  }
-
-  @override
   Description describe(Description description) =>
       description.add('a type with the name $_expectedName');
 
@@ -33,57 +81,9 @@
       return mismatchDescription.add('is not a Type');
     }
   }
-}
-
-Matcher isArrayOf(Matcher matcher) => ArrayTypeMatcher(wrapMatcher(matcher));
-
-class ArrayTypeMatcher extends Matcher {
-  final Matcher _elementTypeMatcher;
-  const ArrayTypeMatcher(this._elementTypeMatcher);
 
   @override
   bool matches(item, Map matchState) {
-    return item is ArrayType &&
-        _elementTypeMatcher.matches(item.elementType, matchState);
-  }
-
-  @override
-  Description describe(Description description) =>
-      description.add('an array of ').addDescriptionOf(_elementTypeMatcher);
-
-  @override
-  Description describeMismatch(
-      item, Description mismatchDescription, Map matchState, bool verbose) {
-    if (item is ArrayType) {
-      return _elementTypeMatcher.describeMismatch(
-          item, mismatchDescription, matchState, verbose);
-    } else {
-      return mismatchDescription.add('is not an ArrayType');
-    }
+    return item is Type && item.name == _expectedName;
   }
 }
-
-Matcher isMapOf(Matcher indexMatcher, Matcher valueMatcher) =>
-    MapTypeMatcher(wrapMatcher(indexMatcher), wrapMatcher(valueMatcher));
-
-class MapTypeMatcher extends Matcher {
-  final Matcher _indexMatcher, _valueMatcher;
-  const MapTypeMatcher(this._indexMatcher, this._valueMatcher);
-
-  @override
-  bool matches(item, Map matchState) {
-    return item is MapType &&
-        _indexMatcher.matches(item.indexType, matchState) &&
-        _valueMatcher.matches(item.valueType, matchState);
-  }
-
-  @override
-  Description describe(Description description) => description
-      .add('a MapType where index is ')
-      .addDescriptionOf(_indexMatcher)
-      .add(' and value is ')
-      .addDescriptionOf(_valueMatcher);
-}
-
-Matcher isResponseError(ErrorCodes code) => const TypeMatcher<ResponseError>()
-    .having((e) => e.code, 'code', equals(code));
diff --git a/pkg/analysis_server/test/tool/test_all.dart b/pkg/analysis_server/test/tool/test_all.dart
index 659a796..8d2910e 100644
--- a/pkg/analysis_server/test/tool/test_all.dart
+++ b/pkg/analysis_server/test/tool/test_all.dart
@@ -4,8 +4,8 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'lsp_spec/test_all.dart' as lsp_spec;
 import 'completion_metrics/test_all.dart' as completion_metrics;
+import 'lsp_spec/test_all.dart' as lsp_spec;
 
 void main() {
   defineReflectiveSuite(() {
diff --git a/pkg/analysis_server/tool/completion_metrics/code_metrics.dart b/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
new file mode 100644
index 0000000..fdb4ec0
--- /dev/null
+++ b/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
@@ -0,0 +1,1501 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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' as io;
+
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/diagnostic/diagnostic.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:args/args.dart';
+
+/// Compute and print lexical and semantic information about a package.
+Future<void> main(List<String> args) async {
+  ArgParser parser = createArgParser();
+  ArgResults result = parser.parse(args);
+
+  if (validArguments(parser, result)) {
+    var out = io.stdout;
+    var rootPath = result.rest[0];
+    out.writeln('Analyzing root: "$rootPath"');
+
+    var computer = CodeShapeMetricsComputer();
+    var stopwatch = Stopwatch();
+    stopwatch.start();
+    await computer.compute(rootPath);
+    stopwatch.stop();
+    var duration = Duration(milliseconds: stopwatch.elapsedMilliseconds);
+    out.writeln('  Analysis performed in $duration');
+    computer.writeResults(out);
+    await out.flush();
+  }
+  io.exit(0);
+}
+
+/// Create a parser that can be used to parse the command-line arguments.
+ArgParser createArgParser() {
+  ArgParser parser = ArgParser();
+  parser.addOption(
+    'help',
+    abbr: 'h',
+    help: 'Print this help message.',
+  );
+  return parser;
+}
+
+/// Print usage information for this tool.
+void printUsage(ArgParser parser, {String error}) {
+  if (error != null) {
+    print(error);
+    print('');
+  }
+  print('usage: dart code_metrics.dart [options] packagePath');
+  print('');
+  print('Compute and print lexical and semantic information about a package.');
+  print('');
+  print(parser.usage);
+}
+
+/// Return `true` if the command-line arguments (represented by the [result] and
+/// parsed by the [parser]) are valid.
+bool validArguments(ArgParser parser, ArgResults result) {
+  if (result.wasParsed('help')) {
+    printUsage(parser);
+    return false;
+  } else if (result.rest.length != 1) {
+    printUsage(parser, error: 'No package path specified.');
+    return false;
+  }
+  var rootPath = result.rest[0];
+  if (!io.Directory(rootPath).existsSync()) {
+    printUsage(parser, error: 'The directory "$rootPath" does not exist.');
+    return false;
+  }
+  return true;
+}
+
+/// An object that records the data used to compute the metrics.
+class CodeShapeData {
+  /// A table mapping the name of a node class to the number of instances of
+  /// that class that were visited.
+  Map<String, int> nodeData = {};
+
+  /// A table mapping the name of a node class and the name of the node's
+  /// parent's class to the number of instances of the node class that had a
+  /// parent of the parent class.
+  Map<String, Map<String, int>> parentData = {};
+
+  /// A table mapping the name of a node class, the name of a property of that
+  /// node, and the class of the property's value to number of instances of the
+  /// node class that had a value of the property class for the property.
+  Map<String, Map<String, Map<String, int>>> childData = {};
+
+  /// A table mapping the name of a node class, the name of a list-valued
+  /// property of that node, and the length of the list to number of instances
+  /// of the node class that had a value of that length for the property.
+  Map<String, Map<String, Map<int, int>>> lengthData = {};
+
+  /// Information about children of nodes that were not correctly recorded.
+  Set<String> missedChildren = {};
+
+  /// Initialize a newly created set of relevance data to be empty.
+  CodeShapeData();
+
+  /// Record that an element of the given [node] was found in the given
+  /// [context].
+  void recordNode(String nodeClassName, String property, AstNode node) {
+    var childClass = node?.runtimeType?.toString() ?? 'null';
+    if (childClass.endsWith('Impl')) {
+      childClass = childClass.substring(0, childClass.length - 4);
+    }
+    _recordChildData(nodeClassName, property, childClass);
+  }
+
+  /// Record that a node that is an instance of the [nodeClassName] was visited.
+  void recordNodeClass(String nodeClassName) {
+    nodeData[nodeClassName] = (nodeData[nodeClassName] ?? 0) + 1;
+  }
+
+  void recordNodeList(String nodeClassName, String property, NodeList list) {
+    _recordListLength(nodeClassName, property, list);
+    for (var element in list) {
+      recordNode(nodeClassName, property, element);
+    }
+  }
+
+  void recordParentClass(String nodeClassName, String parentClassName) {
+    var classMap = parentData.putIfAbsent(nodeClassName, () => {});
+    classMap[parentClassName] = (classMap[parentClassName] ?? 0) + 1;
+  }
+
+  void recordToken(String nodeClassName, String property, Token token) {
+    var lexeme = token?.lexeme ?? 'null';
+    _recordChildData(nodeClassName, property, lexeme);
+  }
+
+  void _recordChildData(
+      String nodeClassName, String property, String childValue) {
+    var classMap = childData.putIfAbsent(nodeClassName, () => {});
+    var propertyMap = classMap.putIfAbsent(property, () => {});
+    propertyMap[childValue] = (propertyMap[childValue] ?? 0) + 1;
+  }
+
+  /// Record that an element of the given [node] was found in the given
+  /// [context].
+  void _recordListLength(String nodeClassName, String property, NodeList list) {
+    var classMap = lengthData.putIfAbsent(nodeClassName, () => {});
+    var propertyMap = classMap.putIfAbsent(property, () => {});
+    var length = list.length;
+    propertyMap[length] = (propertyMap[length] ?? 0) + 1;
+  }
+}
+
+/// An object that visits a compilation unit in order to record the data used to
+/// compute the metrics.
+class CodeShapeDataCollector extends RecursiveAstVisitor<void> {
+  /// The data being collected.
+  final CodeShapeData data;
+
+  /// Initialize a newly created collector to add data points to the given
+  /// [data].
+  CodeShapeDataCollector(this.data);
+
+  @override
+  void visitAdjacentStrings(AdjacentStrings node) {
+    _visitChildren(node, {
+      'strings': node.strings,
+    });
+    super.visitAdjacentStrings(node);
+  }
+
+  @override
+  void visitAnnotation(Annotation node) {
+    _visitChildren(node, {
+      'name': node.name,
+      'constructorName': node.constructorName,
+      'arguments': node.arguments,
+    });
+    super.visitAnnotation(node);
+  }
+
+  @override
+  void visitArgumentList(ArgumentList node) {
+    _visitChildren(node, {
+      'arguments': node.arguments,
+    });
+    super.visitArgumentList(node);
+  }
+
+  @override
+  void visitAsExpression(AsExpression node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+      'type': node.type,
+    });
+    super.visitAsExpression(node);
+  }
+
+  @override
+  void visitAssertInitializer(AssertInitializer node) {
+    _visitChildren(node, {
+      'condition': node.condition,
+      'message': node.message,
+    });
+    super.visitAssertInitializer(node);
+  }
+
+  @override
+  void visitAssertStatement(AssertStatement node) {
+    _visitChildren(node, {
+      'condition': node.condition,
+      'message': node.message,
+    });
+    super.visitAssertStatement(node);
+  }
+
+  @override
+  void visitAssignmentExpression(AssignmentExpression node) {
+    _visitChildren(node, {
+      'leftHandSide': node.leftHandSide,
+      'operator': node.operator,
+      'rightHandSide': node.rightHandSide,
+    });
+    super.visitAssignmentExpression(node);
+  }
+
+  @override
+  void visitAwaitExpression(AwaitExpression node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+    });
+    super.visitAwaitExpression(node);
+  }
+
+  @override
+  void visitBinaryExpression(BinaryExpression node) {
+    _visitChildren(node, {
+      'leftOperand': node.leftOperand,
+      'operator': node.operator,
+      'rightOperand': node.rightOperand,
+    });
+    super.visitBinaryExpression(node);
+  }
+
+  @override
+  void visitBlock(Block node) {
+    _visitChildren(node, {
+      'statement': node.statements,
+    });
+    super.visitBlock(node);
+  }
+
+  @override
+  void visitBlockFunctionBody(BlockFunctionBody node) {
+    _visitChildren(node, {
+      'keyword': node.keyword,
+      'star': node.star,
+      'block': node.block,
+    });
+    super.visitBlockFunctionBody(node);
+  }
+
+  @override
+  void visitBooleanLiteral(BooleanLiteral node) {
+    _visitChildren(node, {
+      'literal': node.literal,
+    });
+    super.visitBooleanLiteral(node);
+  }
+
+  @override
+  void visitBreakStatement(BreakStatement node) {
+    _visitChildren(node, {
+      'label': node.label,
+    });
+    super.visitBreakStatement(node);
+  }
+
+  @override
+  void visitCascadeExpression(CascadeExpression node) {
+    _visitChildren(node, {
+      'target': node.target,
+      'cascadeSections': node.cascadeSections,
+    });
+    super.visitCascadeExpression(node);
+  }
+
+  @override
+  void visitCatchClause(CatchClause node) {
+    _visitChildren(node, {
+      'exceptionType': node.exceptionType,
+      'exceptionParameter': node.exceptionParameter,
+      'stackTraceParameter': node.stackTraceParameter,
+      'body': node.body,
+    });
+    super.visitCatchClause(node);
+  }
+
+  @override
+  void visitClassDeclaration(ClassDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'abstractKeyword': node.abstractKeyword,
+      'name': node.name,
+      'typeParameters': node.typeParameters,
+      'extendsClause': node.extendsClause,
+      'withClause': node.withClause,
+      'implementsClause': node.implementsClause,
+      'nativeClause': node.nativeClause,
+      'members': node.members,
+    });
+    super.visitClassDeclaration(node);
+  }
+
+  @override
+  void visitClassTypeAlias(ClassTypeAlias node) {
+    _visitChildren(node, {
+      'abstractKeyword': node.abstractKeyword,
+      'name': node.name,
+      'typeParameters': node.typeParameters,
+      'superclass': node.superclass,
+      'withClause': node.withClause,
+      'implementsClause': node.implementsClause,
+    });
+    super.visitClassTypeAlias(node);
+  }
+
+  @override
+  void visitComment(Comment node) {
+    _visitChildren(node, {'references': node.references});
+    super.visitComment(node);
+  }
+
+  @override
+  void visitCommentReference(CommentReference node) {
+    _visitChildren(node, {
+      'newKeyword': node.newKeyword,
+      'identifier': node.identifier,
+    });
+    super.visitCommentReference(node);
+  }
+
+  @override
+  void visitCompilationUnit(CompilationUnit node) {
+    _visitChildren(node, {
+      'scriptTag': node.scriptTag,
+      'directives': node.directives,
+      'declarations': node.declarations,
+    });
+    super.visitCompilationUnit(node);
+  }
+
+  @override
+  void visitConditionalExpression(ConditionalExpression node) {
+    _visitChildren(node, {
+      'condition': node.condition,
+      'thenExpression': node.thenExpression,
+      'elseExpression': node.elseExpression,
+    });
+    super.visitConditionalExpression(node);
+  }
+
+  @override
+  void visitConfiguration(Configuration node) {
+    _visitChildren(node, {
+      'name': node.name,
+      'value': node.value,
+      'uri': node.uri,
+    });
+    super.visitConfiguration(node);
+  }
+
+  @override
+  void visitConstructorDeclaration(ConstructorDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'externalKeyword': node.externalKeyword,
+      'constKeyword': node.constKeyword,
+      'factoryKeyword': node.factoryKeyword,
+      'returnType': node.returnType,
+      'name': node.name,
+      'parameters': node.parameters,
+      'initializers': node.initializers,
+      'redirectedConstructor': node.redirectedConstructor,
+      'body': node.body,
+    });
+    super.visitConstructorDeclaration(node);
+  }
+
+  @override
+  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    _visitChildren(node, {
+      'thisKeyword': node.thisKeyword,
+      'fieldName': node.fieldName,
+      'expression': node.expression,
+    });
+    super.visitConstructorFieldInitializer(node);
+  }
+
+  @override
+  void visitConstructorName(ConstructorName node) {
+    _visitChildren(node, {
+      'type': node.type,
+      'name': node.name,
+    });
+    super.visitConstructorName(node);
+  }
+
+  @override
+  void visitContinueStatement(ContinueStatement node) {
+    _visitChildren(node, {
+      'label': node.label,
+    });
+    super.visitContinueStatement(node);
+  }
+
+  @override
+  void visitDeclaredIdentifier(DeclaredIdentifier node) {
+    _visitChildren(node, {
+      'keyword': node.keyword,
+      'type': node.type,
+      'identifier': node.identifier,
+    });
+    super.visitDeclaredIdentifier(node);
+  }
+
+  @override
+  void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    _visitChildren(node, {
+      'parameter': node.parameter,
+      'defaultValue': node.defaultValue,
+    });
+    super.visitDefaultFormalParameter(node);
+  }
+
+  @override
+  void visitDoStatement(DoStatement node) {
+    _visitChildren(node, {
+      'body': node.body,
+      'condition': node.condition,
+    });
+    super.visitDoStatement(node);
+  }
+
+  @override
+  void visitDottedName(DottedName node) {
+    _visitChildren(node, {
+      'components': node.components,
+    });
+    super.visitDottedName(node);
+  }
+
+  @override
+  void visitDoubleLiteral(DoubleLiteral node) {
+    _visitChildren(node, {});
+    super.visitDoubleLiteral(node);
+  }
+
+  @override
+  void visitEmptyFunctionBody(EmptyFunctionBody node) {
+    _visitChildren(node, {});
+    super.visitEmptyFunctionBody(node);
+  }
+
+  @override
+  void visitEmptyStatement(EmptyStatement node) {
+    _visitChildren(node, {});
+    super.visitEmptyStatement(node);
+  }
+
+  @override
+  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'name': node.name,
+    });
+    super.visitEnumConstantDeclaration(node);
+  }
+
+  @override
+  void visitEnumDeclaration(EnumDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'name': node.name,
+      'constants': node.constants,
+    });
+    super.visitEnumDeclaration(node);
+  }
+
+  @override
+  void visitExportDirective(ExportDirective node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'uri': node.uri,
+      'configurations': node.configurations,
+      'combinators': node.combinators,
+    });
+    super.visitExportDirective(node);
+  }
+
+  @override
+  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    _visitChildren(node, {
+      'keyword': node.keyword,
+      'star': node.star,
+      'expression': node.expression,
+    });
+    super.visitExpressionFunctionBody(node);
+  }
+
+  @override
+  void visitExpressionStatement(ExpressionStatement node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+    });
+    super.visitExpressionStatement(node);
+  }
+
+  @override
+  void visitExtendsClause(ExtendsClause node) {
+    _visitChildren(node, {
+      'superclass': node.superclass,
+    });
+    super.visitExtendsClause(node);
+  }
+
+  @override
+  void visitExtensionDeclaration(ExtensionDeclaration node) {
+    _visitChildren(node, {
+      'name': node.name,
+      'typeParameters': node.typeParameters,
+      'extendedType': node.extendedType,
+      'member': node.members,
+    });
+    super.visitExtensionDeclaration(node);
+  }
+
+  @override
+  void visitExtensionOverride(ExtensionOverride node) {
+    _visitChildren(node, {
+      'extensionName': node.extensionName,
+      'typeArguments': node.typeArguments,
+      'argumentList': node.argumentList,
+    });
+    super.visitExtensionOverride(node);
+  }
+
+  @override
+  void visitFieldDeclaration(FieldDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'covariantKeyword': node.covariantKeyword,
+      'staticKeyword': node.staticKeyword,
+      'fields': node.fields,
+    });
+    super.visitFieldDeclaration(node);
+  }
+
+  @override
+  void visitFieldFormalParameter(FieldFormalParameter node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'keyword': node.keyword,
+      'type': node.type,
+      'thisKeyword': node.thisKeyword,
+      'identifier': node.identifier,
+      'typeParameters': node.typeParameters,
+      'parameters': node.parameters,
+      'question': node.question,
+    });
+    super.visitFieldFormalParameter(node);
+  }
+
+  @override
+  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+    _visitChildren(node, {
+      'loopVariable': node.loopVariable,
+      'iterable': node.iterable,
+    });
+    super.visitForEachPartsWithDeclaration(node);
+  }
+
+  @override
+  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+    _visitChildren(node, {
+      'identifier': node.identifier,
+      'iterable': node.iterable,
+    });
+    super.visitForEachPartsWithIdentifier(node);
+  }
+
+  @override
+  void visitForElement(ForElement node) {
+    _visitChildren(node, {
+      'awaitKeyword': node.awaitKeyword,
+      'forLoopParts': node.forLoopParts,
+      'body': node.body,
+    });
+    super.visitForElement(node);
+  }
+
+  @override
+  void visitFormalParameterList(FormalParameterList node) {
+    _visitChildren(node, {
+      'parameters': node.parameters,
+    });
+    super.visitFormalParameterList(node);
+  }
+
+  @override
+  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
+    _visitChildren(node, {
+      'variables': node.variables,
+      'condition': node.condition,
+      'updater': node.updaters,
+    });
+    super.visitForPartsWithDeclarations(node);
+  }
+
+  @override
+  void visitForPartsWithExpression(ForPartsWithExpression node) {
+    _visitChildren(node, {
+      'initialization': node.initialization,
+      'condition': node.condition,
+      'updater': node.updaters,
+    });
+    super.visitForPartsWithExpression(node);
+  }
+
+  @override
+  void visitForStatement(ForStatement node) {
+    _visitChildren(node, {
+      'awaitKeyword': node.awaitKeyword,
+      'forLoopParts': node.forLoopParts,
+      'body': node.body,
+    });
+    super.visitForStatement(node);
+  }
+
+  @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'externalKeyword': node.externalKeyword,
+      'propertyKeyword': node.propertyKeyword,
+      'name': node.name,
+      'functionExpression': node.functionExpression,
+      'returnType': node.returnType,
+    });
+    super.visitFunctionDeclaration(node);
+  }
+
+  @override
+  void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
+    _visitChildren(node, {
+      'functionDeclaration': node.functionDeclaration,
+    });
+    super.visitFunctionDeclarationStatement(node);
+  }
+
+  @override
+  void visitFunctionExpression(FunctionExpression node) {
+    _visitChildren(node, {
+      'typeParameters': node.typeParameters,
+      'parameters': node.parameters,
+      'body': node.body,
+    });
+    super.visitFunctionExpression(node);
+  }
+
+  @override
+  void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    _visitChildren(node, {
+      'function': node.function,
+      'typeArguments': node.typeArguments,
+      'argumentList': node.argumentList,
+    });
+    super.visitFunctionExpressionInvocation(node);
+  }
+
+  @override
+  void visitFunctionTypeAlias(FunctionTypeAlias node) {
+    _visitChildren(node, {
+      'returnType': node.returnType,
+      'typeParameters': node.typeParameters,
+      'parameters': node.parameters,
+    });
+    super.visitFunctionTypeAlias(node);
+  }
+
+  @override
+  void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
+    _visitChildren(node, {
+      'covariantKeyword': node.covariantKeyword,
+      'returnType': node.returnType,
+      'identifier': node.identifier,
+      'typeParameters': node.typeParameters,
+      'parameters': node.parameters,
+      'question': node.question,
+    });
+    super.visitFunctionTypedFormalParameter(node);
+  }
+
+  @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    _visitChildren(node, {
+      'returnType': node.returnType,
+      'typeParameters': node.typeParameters,
+      'parameters': node.parameters,
+      'question': node.question,
+    });
+    super.visitGenericFunctionType(node);
+  }
+
+  @override
+  void visitGenericTypeAlias(GenericTypeAlias node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'name': node.name,
+      'typeParameters': node.typeParameters,
+      'functionType': node.functionType,
+    });
+    super.visitGenericTypeAlias(node);
+  }
+
+  @override
+  void visitHideCombinator(HideCombinator node) {
+    _visitChildren(node, {
+      'hiddenNames': node.hiddenNames,
+    });
+    super.visitHideCombinator(node);
+  }
+
+  @override
+  void visitIfElement(IfElement node) {
+    _visitChildren(node, {
+      'condition': node.condition,
+      'thenElement': node.thenElement,
+      'elseElement': node.elseElement,
+    });
+    super.visitIfElement(node);
+  }
+
+  @override
+  void visitIfStatement(IfStatement node) {
+    _visitChildren(node, {
+      'condition': node.condition,
+      'thenStatement': node.thenStatement,
+      'elseStatement': node.elseStatement,
+    });
+    super.visitIfStatement(node);
+  }
+
+  @override
+  void visitImplementsClause(ImplementsClause node) {
+    _visitChildren(node, {
+      'interfaces': node.interfaces,
+    });
+    super.visitImplementsClause(node);
+  }
+
+  @override
+  void visitImportDirective(ImportDirective node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'uri': node.uri,
+      'deferredKeyword': node.deferredKeyword,
+      'asKeyword': node.asKeyword,
+      'prefix': node.prefix,
+      'configurations': node.configurations,
+      'combinators': node.combinators,
+    });
+    super.visitImportDirective(node);
+  }
+
+  @override
+  void visitIndexExpression(IndexExpression node) {
+    _visitChildren(node, {
+      'target': node.target,
+      'index': node.index,
+    });
+    super.visitIndexExpression(node);
+  }
+
+  @override
+  void visitInstanceCreationExpression(InstanceCreationExpression node) {
+    _visitChildren(node, {
+      'keyword': node.keyword,
+      'constructorName': node.constructorName,
+      'argumentList': node.argumentList,
+    });
+    super.visitInstanceCreationExpression(node);
+  }
+
+  @override
+  void visitIntegerLiteral(IntegerLiteral node) {
+    var value = node.value;
+    if (value == -1 || value == 0 || value == 1) {
+      _visitChildren(node, {
+        'literal': node.literal,
+      });
+    } else {
+      _visitChildren(node, {});
+    }
+    super.visitIntegerLiteral(node);
+  }
+
+  @override
+  void visitInterpolationExpression(InterpolationExpression node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+    });
+    super.visitInterpolationExpression(node);
+  }
+
+  @override
+  void visitInterpolationString(InterpolationString node) {
+    _visitChildren(node, {});
+    super.visitInterpolationString(node);
+  }
+
+  @override
+  void visitIsExpression(IsExpression node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+      'type': node.type,
+    });
+    super.visitIsExpression(node);
+  }
+
+  @override
+  void visitLabel(Label node) {
+    _visitChildren(node, {
+      'label': node.label,
+    });
+    super.visitLabel(node);
+  }
+
+  @override
+  void visitLabeledStatement(LabeledStatement node) {
+    _visitChildren(node, {
+      'statement': node.statement,
+    });
+    super.visitLabeledStatement(node);
+  }
+
+  @override
+  void visitLibraryDirective(LibraryDirective node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'name': node.name,
+    });
+    super.visitLibraryDirective(node);
+  }
+
+  @override
+  void visitLibraryIdentifier(LibraryIdentifier node) {
+    _visitChildren(node, {
+      'components': node.components,
+    });
+    super.visitLibraryIdentifier(node);
+  }
+
+  @override
+  void visitListLiteral(ListLiteral node) {
+    _visitChildren(node, {
+      'typeArguments': node.typeArguments,
+      'elements': node.elements,
+    });
+    super.visitListLiteral(node);
+  }
+
+  @override
+  void visitMapLiteralEntry(MapLiteralEntry node) {
+    _visitChildren(node, {
+      'key': node.key,
+      'value': node.value,
+    });
+    super.visitMapLiteralEntry(node);
+  }
+
+  @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'externalKeyword': node.externalKeyword,
+      'modifierKeyword': node.modifierKeyword,
+      'returnType': node.returnType,
+      'name': node.name,
+      'operatorKeyword': node.operatorKeyword,
+      'typeParameters': node.typeParameters,
+      'parameters': node.parameters,
+      'body': node.body,
+    });
+    super.visitMethodDeclaration(node);
+  }
+
+  @override
+  void visitMethodInvocation(MethodInvocation node) {
+    _visitChildren(node, {
+      'target': node.target,
+      'methodName': node.methodName,
+      'typeArguments': node.typeArguments,
+      'argumentList': node.argumentList,
+    });
+    super.visitMethodInvocation(node);
+  }
+
+  @override
+  void visitMixinDeclaration(MixinDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'name': node.name,
+      'onClause': node.onClause,
+      'implementsClause': node.implementsClause,
+      'members': node.members,
+    });
+    super.visitMixinDeclaration(node);
+  }
+
+  @override
+  void visitNamedExpression(NamedExpression node) {
+    _visitChildren(node, {
+      'name': node.name,
+      'expression': node.expression,
+    });
+    super.visitNamedExpression(node);
+  }
+
+  @override
+  void visitNativeClause(NativeClause node) {
+    _visitChildren(node, {
+      'name': node.name,
+    });
+    super.visitNativeClause(node);
+  }
+
+  @override
+  void visitNativeFunctionBody(NativeFunctionBody node) {
+    _visitChildren(node, {});
+    super.visitNativeFunctionBody(node);
+  }
+
+  @override
+  void visitNullLiteral(NullLiteral node) {
+    _visitChildren(node, {});
+    super.visitNullLiteral(node);
+  }
+
+  @override
+  void visitOnClause(OnClause node) {
+    _visitChildren(node, {
+      'superclassConstraints': node.superclassConstraints,
+    });
+    super.visitOnClause(node);
+  }
+
+  @override
+  void visitParenthesizedExpression(ParenthesizedExpression node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+    });
+    super.visitParenthesizedExpression(node);
+  }
+
+  @override
+  void visitPartDirective(PartDirective node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'uri': node.uri,
+    });
+    super.visitPartDirective(node);
+  }
+
+  @override
+  void visitPartOfDirective(PartOfDirective node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'libraryName': node.libraryName,
+      'uri': node.uri,
+    });
+    super.visitPartOfDirective(node);
+  }
+
+  @override
+  void visitPostfixExpression(PostfixExpression node) {
+    _visitChildren(node, {
+      'operand': node.operand,
+      'operator': node.operator,
+    });
+    super.visitPostfixExpression(node);
+  }
+
+  @override
+  void visitPrefixedIdentifier(PrefixedIdentifier node) {
+    _visitChildren(node, {
+      'prefix': node.prefix,
+      'identifier': node.identifier,
+    });
+    super.visitPrefixedIdentifier(node);
+  }
+
+  @override
+  void visitPrefixExpression(PrefixExpression node) {
+    _visitChildren(node, {
+      'operator': node.operator,
+      'operand': node.operand,
+    });
+    super.visitPrefixExpression(node);
+  }
+
+  @override
+  void visitPropertyAccess(PropertyAccess node) {
+    _visitChildren(node, {
+      'target': node.target,
+      'propertyName': node.propertyName,
+    });
+    super.visitPropertyAccess(node);
+  }
+
+  @override
+  void visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    _visitChildren(node, {
+      'constructorName': node.constructorName,
+      'argumentList': node.argumentList,
+    });
+    super.visitRedirectingConstructorInvocation(node);
+  }
+
+  @override
+  void visitRethrowExpression(RethrowExpression node) {
+    _visitChildren(node, {});
+    super.visitRethrowExpression(node);
+  }
+
+  @override
+  void visitReturnStatement(ReturnStatement node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+    });
+    super.visitReturnStatement(node);
+  }
+
+  @override
+  void visitScriptTag(ScriptTag node) {
+    _visitChildren(node, {});
+    super.visitScriptTag(node);
+  }
+
+  @override
+  void visitSetOrMapLiteral(SetOrMapLiteral node) {
+    _visitChildren(node, {
+      'typeArguments': node.typeArguments,
+      'elements': node.elements,
+    });
+    super.visitSetOrMapLiteral(node);
+  }
+
+  @override
+  void visitShowCombinator(ShowCombinator node) {
+    _visitChildren(node, {
+      'shownNames': node.shownNames,
+    });
+    super.visitShowCombinator(node);
+  }
+
+  @override
+  void visitSimpleFormalParameter(SimpleFormalParameter node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'covariantKeyword': node.covariantKeyword,
+      'keyword': node.keyword,
+      'type': node.type,
+      'identifier': node.identifier,
+    });
+    super.visitSimpleFormalParameter(node);
+  }
+
+  @override
+  void visitSimpleStringLiteral(SimpleStringLiteral node) {
+    _visitChildren(node, {});
+    super.visitSimpleStringLiteral(node);
+  }
+
+  @override
+  void visitSpreadElement(SpreadElement node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+    });
+    super.visitSpreadElement(node);
+  }
+
+  @override
+  void visitStringInterpolation(StringInterpolation node) {
+    _visitChildren(node, {
+      'elements': node.elements,
+    });
+    super.visitStringInterpolation(node);
+  }
+
+  @override
+  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    _visitChildren(node, {
+      'constructorName': node.constructorName,
+      'argumentList': node.argumentList,
+    });
+    super.visitSuperConstructorInvocation(node);
+  }
+
+  @override
+  void visitSuperExpression(SuperExpression node) {
+    _visitChildren(node, {});
+    super.visitSuperExpression(node);
+  }
+
+  @override
+  void visitSwitchCase(SwitchCase node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+      'statements': node.statements,
+    });
+    super.visitSwitchCase(node);
+  }
+
+  @override
+  void visitSwitchDefault(SwitchDefault node) {
+    _visitChildren(node, {
+      'statements': node.statements,
+    });
+    super.visitSwitchDefault(node);
+  }
+
+  @override
+  void visitSwitchStatement(SwitchStatement node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+      'members': node.members,
+    });
+    super.visitSwitchStatement(node);
+  }
+
+  @override
+  void visitSymbolLiteral(SymbolLiteral node) {
+    _visitChildren(node, {});
+    super.visitSymbolLiteral(node);
+  }
+
+  @override
+  void visitThisExpression(ThisExpression node) {
+    _visitChildren(node, {});
+    super.visitThisExpression(node);
+  }
+
+  @override
+  void visitThrowExpression(ThrowExpression node) {
+    _visitChildren(node, {
+      'expression': node.expression,
+    });
+    super.visitThrowExpression(node);
+  }
+
+  @override
+  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'variables': node.variables,
+    });
+    super.visitTopLevelVariableDeclaration(node);
+  }
+
+  @override
+  void visitTryStatement(TryStatement node) {
+    _visitChildren(node, {
+      'body': node.body,
+      'catchClauses': node.catchClauses,
+      'finallyBlock': node.finallyBlock,
+    });
+    super.visitTryStatement(node);
+  }
+
+  @override
+  void visitTypeArgumentList(TypeArgumentList node) {
+    _visitChildren(node, {
+      'arguments': node.arguments,
+    });
+    super.visitTypeArgumentList(node);
+  }
+
+  @override
+  void visitTypeName(TypeName node) {
+    _visitChildren(node, {
+      'name': node.name,
+      'typeArguments': node.typeArguments,
+      'question': node.question,
+    });
+    super.visitTypeName(node);
+  }
+
+  @override
+  void visitTypeParameter(TypeParameter node) {
+    _visitChildren(node, {
+      'name': node.name,
+      'bound': node.bound,
+    });
+    super.visitTypeParameter(node);
+  }
+
+  @override
+  void visitTypeParameterList(TypeParameterList node) {
+    _visitChildren(node, {'typeParameters': node.typeParameters});
+    super.visitTypeParameterList(node);
+  }
+
+  @override
+  void visitVariableDeclaration(VariableDeclaration node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'name': node.name,
+      'initializer': node.initializer,
+    });
+    super.visitVariableDeclaration(node);
+  }
+
+  @override
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    _visitChildren(node, {
+      'documentationComment': node.documentationComment,
+      'metadata': node.metadata,
+      'type': node.type,
+      'variables': node.variables,
+    });
+    super.visitVariableDeclarationList(node);
+  }
+
+  @override
+  void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    _visitChildren(node, {
+      'variables': node.variables,
+    });
+    super.visitVariableDeclarationStatement(node);
+  }
+
+  @override
+  void visitWhileStatement(WhileStatement node) {
+    _visitChildren(node, {
+      'condition': node.condition,
+      'body': node.body,
+    });
+    super.visitWhileStatement(node);
+  }
+
+  @override
+  void visitWithClause(WithClause node) {
+    _visitChildren(node, {
+      'mixinTypes': node.mixinTypes,
+    });
+    super.visitWithClause(node);
+  }
+
+  @override
+  void visitYieldStatement(YieldStatement node) {
+    _visitChildren(node, {
+      'star': node.star,
+      'expression': node.expression,
+    });
+    super.visitYieldStatement(node);
+  }
+
+  String _className(AstNode node) {
+    var className = node.runtimeType.toString();
+    if (className.endsWith('Impl')) {
+      className = className.substring(0, className.length - 4);
+    }
+    return className;
+  }
+
+  /// Visit the children of a node. The node is an instance of the class named
+  /// [parentClass] and the children are in the [childMap], keyed by the name of
+  /// the child property.
+  void _visitChildren(AstNode node, Map<String, Object> childMap) {
+    var nodeClassName = _className(node);
+
+    data.recordNodeClass(nodeClassName);
+
+    var parent = node.parent;
+    if (parent != null) {
+      data.recordParentClass(nodeClassName, _className(parent));
+    }
+
+    var visitChildren = <AstNode>[];
+    for (var entry in childMap.entries) {
+      var property = entry.key;
+      var child = entry.value;
+      if (child is AstNode) {
+        data.recordNode(nodeClassName, property, child);
+        visitChildren.add(child);
+      } else if (child is NodeList) {
+        data.recordNodeList(nodeClassName, property, child);
+        visitChildren.addAll(child);
+      } else if (child is Token || child == null) {
+        data.recordToken(nodeClassName, property, child);
+      } else {
+        throw ArgumentError('Unknown class of child: ${child.runtimeType}');
+      }
+    }
+    // Validate that all AST node children were included in the [childMap].
+    for (var entity in node.childEntities) {
+      if (entity is AstNode && !visitChildren.contains(entity)) {
+        data.missedChildren.add('$nodeClassName (${entity.runtimeType})');
+      }
+    }
+  }
+}
+
+/// An object used to compute metrics for a single file or directory.
+class CodeShapeMetricsComputer {
+  /// The metrics data that was computed.
+  final CodeShapeData data = CodeShapeData();
+
+  /// Initialize a newly created metrics computer that can compute the metrics
+  /// in one or more files and directories.
+  CodeShapeMetricsComputer();
+
+  /// Compute the metrics for the file(s) in the [rootPath].
+  void compute(String rootPath) async {
+    final collection = AnalysisContextCollection(
+      includedPaths: [rootPath],
+      resourceProvider: PhysicalResourceProvider.INSTANCE,
+    );
+    final collector = CodeShapeDataCollector(data);
+
+    for (var context in collection.contexts) {
+      for (var filePath in context.contextRoot.analyzedFiles()) {
+        if (AnalysisEngine.isDartFileName(filePath)) {
+          try {
+            ResolvedUnitResult resolvedUnitResult =
+                await context.currentSession.getResolvedUnit(filePath);
+            //
+            // Check for errors that cause the file to be skipped.
+            //
+            if (resolvedUnitResult.state != ResultState.VALID) {
+              print('File $filePath skipped because it could not be analyzed.');
+              print('');
+              continue;
+            } else if (hasError(resolvedUnitResult)) {
+              print('File $filePath skipped due to errors:');
+              for (var error in resolvedUnitResult.errors) {
+                print('  ${error.toString()}');
+              }
+              print('');
+              continue;
+            }
+
+            resolvedUnitResult.unit.accept(collector);
+          } catch (exception) {
+            print('Exception caught analyzing: "$filePath"');
+            print(exception.toString());
+          }
+        }
+      }
+    }
+  }
+
+  /// Write a report of the metrics that were computed to the [sink].
+  void writeResults(StringSink sink) {
+    // Write error information.
+    _writeMissedChildren(sink);
+
+    // Write normal information.
+    _writeChildData(sink);
+  }
+
+  /// Convert the contents of a single [map] into the values for each row in the
+  /// column occupied by the map.
+  List<String> _convertMap<T extends Object>(String context, Map<T, int> map) {
+    var columns = <String>[];
+    if (map == null) {
+      return columns;
+    }
+    var entries = map.entries.toList()
+      ..sort((first, second) {
+        return second.value.compareTo(first.value);
+      });
+    var total = 0;
+    for (var entry in entries) {
+      total += entry.value;
+    }
+    columns.add('$context ($total)');
+    for (var entry in entries) {
+      var value = entry.value;
+      var percent = _formatPercent(value, total);
+      columns.add('  $percent%: ${entry.key} ($value)');
+    }
+    return columns;
+  }
+
+  /// Compute and format a percentage for the fraction [value] / [total].
+  String _formatPercent(int value, int total) {
+    var percent = ((value / total) * 100).toStringAsFixed(1);
+    if (percent.length == 3) {
+      percent = '  $percent';
+    } else if (percent.length == 4) {
+      percent = ' $percent';
+    }
+    return percent;
+  }
+
+  /// Write the child data to the [sink].
+  void _writeChildData(StringSink sink) {
+    sink.writeln('');
+    sink.writeln('Child data');
+
+    // TODO(brianwilkerson) This misses all node kinds for which zero instances
+    //  were visited.
+    var nodeData = data.nodeData;
+    var parentData = data.parentData;
+    var childData = data.childData;
+    var lengthData = data.lengthData;
+    var nodeClasses = nodeData.keys.toList()..sort();
+    for (var nodeClass in nodeClasses) {
+      var count = nodeData[nodeClass];
+      sink.writeln();
+      sink.writeln('$nodeClass ($count)');
+
+      var parentMap = parentData[nodeClass];
+      if (parentMap != null) {
+        var lines = _convertMap('parent', parentMap);
+        for (var line in lines) {
+          sink.writeln('  $line');
+        }
+      }
+
+      var childMap = childData[nodeClass] ?? {};
+      var listMap = lengthData[nodeClass] ?? {};
+      var childNames = {...childMap.keys, ...listMap.keys}.toList()..sort();
+      for (var childName in childNames) {
+        var listLengths = listMap[childName];
+        if (listLengths != null) {
+          var lines = _convertMap(childName, listLengths);
+          for (var line in lines) {
+            sink.writeln('  $line');
+          }
+        }
+
+        var childTypes = childMap[childName];
+        if (childTypes != null) {
+          var lines = _convertMap(childName, childTypes);
+          for (var line in lines) {
+            sink.writeln('  $line');
+          }
+        }
+      }
+    }
+  }
+
+  /// Write a report of the metrics that were computed to the [sink].
+  void _writeMissedChildren(StringSink sink) {
+    var missedChildren = data.missedChildren;
+    if (missedChildren.isNotEmpty) {
+      sink.writeln();
+      sink.writeln('Missed children in the following classes:');
+      for (var nodeClass in missedChildren.toList()..sort()) {
+        sink.writeln('  $nodeClass');
+      }
+    }
+  }
+
+  /// Return `true` if the [result] contains an error.
+  static bool hasError(ResolvedUnitResult result) {
+    for (var error in result.errors) {
+      if (error.severity == Severity.error) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
index 75e5568..d0cf42f 100644
--- a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
@@ -39,7 +39,8 @@
   stopwatch.stop();
 
   var duration = Duration(milliseconds: stopwatch.elapsedMilliseconds);
-  print('\nMetrics computed in $duration');
+  print('');
+  print('Metrics computed in $duration');
   return io.exit(code);
 }
 
@@ -96,6 +97,44 @@
   return true;
 }
 
+/// A wrapper for the collection of [Counter] and [MeanReciprocalRankComputer]
+/// objects for a run of [CompletionMetricsComputer].
+class CompletionMetrics {
+  /// The name associated with this set of metrics.
+  final String name;
+
+  Counter completionCounter = Counter('successful/ unsuccessful completions');
+
+  Counter completionMissedTokenCounter =
+      Counter('unsuccessful completion token counter');
+
+  Counter completionKindCounter =
+      Counter('unsuccessful completion kind counter');
+
+  Counter completionElementKindCounter =
+      Counter('unsuccessful completion element kind counter');
+
+  ArithmeticMeanComputer meanCompletionMS =
+      ArithmeticMeanComputer('ms per completion');
+
+  MeanReciprocalRankComputer mrrComputer =
+      MeanReciprocalRankComputer('successful/ unsuccessful completions');
+
+  MeanReciprocalRankComputer successfulMrrComputer =
+      MeanReciprocalRankComputer('successful completions');
+
+  MeanReciprocalRankComputer instanceMemberMrrComputer =
+      MeanReciprocalRankComputer('instance member completions');
+
+  MeanReciprocalRankComputer staticMemberMrrComputer =
+      MeanReciprocalRankComputer('static member completions');
+
+  MeanReciprocalRankComputer nonTypeMemberMrrComputer =
+      MeanReciprocalRankComputer('non-type member completions');
+
+  CompletionMetrics(this.name);
+}
+
 /// This is the main metrics computer class for code completions. After the
 /// object is constructed, [computeCompletionMetrics] is executed to do analysis
 /// and print a summary of the metrics gathered from the completion tests.
@@ -129,7 +168,7 @@
 
     var roots = _computeRootPaths(_rootPath, corpus);
     for (var root in roots) {
-      print('Analyzing root: \"$root\"');
+      print('Analyzing root: "$root"');
       final collection = AnalysisContextCollection(
         includedPaths: [root],
         resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -178,6 +217,7 @@
                 var suggestions = await _computeCompletionSuggestions(
                     _resolvedUnitResult,
                     expectedCompletion.offset,
+                    metricsOldMode,
                     declarationsTracker,
                     false);
 
@@ -188,6 +228,7 @@
                 suggestions = await _computeCompletionSuggestions(
                     _resolvedUnitResult,
                     expectedCompletion.offset,
+                    metricsNewMode,
                     declarationsTracker,
                     true);
 
@@ -203,8 +244,8 @@
         }
       }
     }
-    printAndClearComputers(metricsOldMode);
-    printAndClearComputers(metricsNewMode);
+    printMetrics(metricsOldMode);
+    printMetrics(metricsNewMode);
     return resultCode;
   }
 
@@ -214,15 +255,19 @@
 
     var place = placementInSuggestionList(suggestions, expectedCompletion);
 
-    metrics.mRRComputer.addRank(place.rank);
+    metrics.mrrComputer.addRank(place.rank);
 
     if (place.denominator != 0) {
+      metrics.successfulMrrComputer.addRank(place.rank);
       metrics.completionCounter.count('successful');
 
-      if (isTypeMember(expectedCompletion.syntacticEntity)) {
-        metrics.typeMemberMRRComputer.addRank(place.rank);
+      var element = getElement(expectedCompletion.syntacticEntity);
+      if (isInstanceMember(element)) {
+        metrics.instanceMemberMrrComputer.addRank(place.rank);
+      } else if (isStaticMember(element)) {
+        metrics.staticMemberMrrComputer.addRank(place.rank);
       } else {
-        metrics.nonTypeMemberMRRComputer.addRank(place.rank);
+        metrics.nonTypeMemberMrrComputer.addRank(place.rank);
       }
     } else {
       metrics.completionCounter.count('unsuccessful');
@@ -234,18 +279,21 @@
 
       if (_verbose) {
         // The format "/file/path/foo.dart:3:4" makes for easier input
-        // with the Files dialog in IntelliJ
-        print(
-            '$currentFilePath:${expectedCompletion.lineNumber}:${expectedCompletion.columnNumber}');
-        print(
-            '\tdid not include the expected completion: \"${expectedCompletion.completion}\", completion kind: ${expectedCompletion.kind.toString()}, element kind: ${expectedCompletion.elementKind.toString()}');
+        // with the Files dialog in IntelliJ.
+        var lineNumber = expectedCompletion.lineNumber;
+        var columnNumber = expectedCompletion.columnNumber;
+        print('$currentFilePath:$lineNumber:$columnNumber');
+        print('  missing completion: "${expectedCompletion.completion}"');
+        print('  completion kind: ${expectedCompletion.kind}');
+        print('  element kind: ${expectedCompletion.elementKind}');
         print('');
       }
     }
   }
 
-  void printAndClearComputers(CompletionMetrics metrics) {
-    print('\n\n');
+  void printMetrics(CompletionMetrics metrics) {
+    print('');
+    print('');
     print('====================');
     print('Completion metrics for ${metrics.name}:');
     if (_verbose) {
@@ -259,30 +307,31 @@
       print('');
     }
 
-    metrics.mRRComputer.printMean();
+    metrics.mrrComputer.printMean();
     print('');
 
-    metrics.typeMemberMRRComputer.printMean();
+    metrics.successfulMrrComputer.printMean();
     print('');
 
-    metrics.nonTypeMemberMRRComputer.printMean();
+    metrics.instanceMemberMrrComputer.printMean();
+    print('');
+
+    metrics.staticMemberMrrComputer.printMean();
+    print('');
+
+    metrics.nonTypeMemberMrrComputer.printMean();
     print('');
 
     print('Summary for $_rootPath:');
+    metrics.meanCompletionMS.printMean();
     metrics.completionCounter.printCounterValues();
     print('====================');
-
-    metrics.completionMissedTokenCounter.clear();
-    metrics.completionKindCounter.clear();
-    metrics.completionElementKindCounter.clear();
-    metrics.completionCounter.clear();
-    metrics.mRRComputer.clear();
-    metrics.typeMemberMRRComputer.clear();
-    metrics.nonTypeMemberMRRComputer.clear();
   }
 
   Future<List<CompletionSuggestion>> _computeCompletionSuggestions(
-      ResolvedUnitResult resolvedUnitResult, int offset,
+      ResolvedUnitResult resolvedUnitResult,
+      int offset,
+      CompletionMetrics metrics,
       [DeclarationsTracker declarationsTracker,
       bool useNewRelevance = false]) async {
     var completionRequestImpl = CompletionRequestImpl(
@@ -292,6 +341,8 @@
       CompletionPerformance(),
     );
 
+    var stopwatch = Stopwatch()..start();
+
     // This gets all of the suggestions with relevances.
     var suggestions =
         await DartCompletionManager().computeSuggestions(completionRequestImpl);
@@ -318,13 +369,15 @@
             false));
       }
     }
+    stopwatch.stop();
+    metrics.meanCompletionMS.addValue(stopwatch.elapsedMilliseconds);
 
     suggestions.sort(completionComparator);
     return suggestions;
   }
 
   /// Given some [ResolvedUnitResult] return the first error of high severity
-  /// if such an error exists, null otherwise.
+  /// if such an error exists, `null` otherwise.
   static err.AnalysisError getFirstErrorOrNull(
       ResolvedUnitResult resolvedUnitResult) {
     for (var error in resolvedUnitResult.errors) {
@@ -361,24 +414,3 @@
     return roots;
   }
 }
-
-/// A wrapper for the collection of [Counter] and [MeanReciprocalRankComputer]
-/// objects for a run of [CompletionMetricsComputer].
-class CompletionMetrics {
-  final String name;
-
-  CompletionMetrics(this.name);
-
-  var completionCounter = Counter('successful/ unsuccessful completions');
-  var completionMissedTokenCounter =
-      Counter('unsuccessful completion token counter');
-  var completionKindCounter = Counter('unsuccessful completion kind counter');
-  var completionElementKindCounter =
-      Counter('unsuccessful completion element kind counter');
-  var mRRComputer =
-      MeanReciprocalRankComputer('successful/ unsuccessful completions');
-  var typeMemberMRRComputer =
-      MeanReciprocalRankComputer('type member completions');
-  var nonTypeMemberMRRComputer =
-      MeanReciprocalRankComputer('non-type member completions');
-}
diff --git a/pkg/analysis_server/tool/completion_metrics/metrics_util.dart b/pkg/analysis_server/tool/completion_metrics/metrics_util.dart
index 9e62c61..2a75fee 100644
--- a/pkg/analysis_server/tool/completion_metrics/metrics_util.dart
+++ b/pkg/analysis_server/tool/completion_metrics/metrics_util.dart
@@ -5,6 +5,31 @@
 import 'package:analysis_server/src/status/pages.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
 
+/// https://en.wikipedia.org/wiki/Average#Arithmetic_mean
+class ArithmeticMeanComputer {
+  final String name;
+  num sum = 0;
+  int count = 0;
+
+  ArithmeticMeanComputer(this.name);
+
+  num get mean => sum / count;
+
+  void addValue(num val) {
+    sum += val;
+    count++;
+  }
+
+  void clear() {
+    sum = 0;
+    count = 0;
+  }
+
+  void printMean() {
+    print('Mean \'$name\' ${mean.toStringAsFixed(6)} (total = $count)');
+  }
+}
+
 /// A simple counter class.  A [String] name is passed to name the counter. Each
 /// time something is counted, a non-null, non-empty [String] key is passed to
 /// [count] to increment the amount from zero. [printCounterValues] is provided
@@ -66,6 +91,14 @@
   final List<int> ranks = [];
   MeanReciprocalRankComputer(this.name);
 
+  int get rankCount => ranks.length;
+
+  void addRank(int rank) {
+    ranks.add(rank);
+  }
+
+  void clear() => ranks.clear();
+
   double getMRR([int maxRank = 0]) {
     if (ranks.isEmpty || maxRank < 0) {
       return 0;
@@ -85,14 +118,6 @@
     return sum / rankCount;
   }
 
-  int get rankCount => ranks.length;
-
-  void addRank(int rank) {
-    ranks.add(rank);
-  }
-
-  void clear() => ranks.clear();
-
   void printMean() {
     var mrrVal = getMRR();
     print('Mean Reciprocal Rank \'$name\' (total = $rankCount)');
diff --git a/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart b/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart
index 8827b91..92f4e26 100644
--- a/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart
@@ -141,6 +141,9 @@
   /// target type and the member type.
   Map<int, Map<int, int>> distanceByDepthMap = {};
 
+  /// A table mapping counter names to counts.
+  Map<String, int> simpleCounts = {};
+
   /// A table mapping distances from an identifier to the nearest previous token
   /// with the same lexeme to the number of times that distance was found.
   Map<int, int> tokenDistances = {};
@@ -163,6 +166,11 @@
     _addToMap(distanceByDepthMap, distanceByDepthMap);
   }
 
+  /// Increment the count associated with the given [name] by one.
+  void incrementCount(String name) {
+    simpleCounts[name] = (simpleCounts[name] ?? 0) + 1;
+  }
+
   /// Record that a reference to an element was found and that the distance
   /// between that reference and the declaration site is the given [distance].
   /// The [descriptor] is used to describe the kind of distance being measured.
@@ -1619,6 +1627,14 @@
     return -1;
   }
 
+  void _recordContextType(DartType type) {
+    if (type == null) {
+      data.incrementCount('has no context type');
+    } else {
+      data.incrementCount('has context type');
+    }
+  }
+
   /// Record information about the given [node] occurring in the given
   /// [context].
   void _recordDataForNode(String context, AstNode node,
@@ -1627,6 +1643,17 @@
     _recordReferenceDepth(node);
     _recordTokenDistance(node);
     _recordTokenType(context, node, allowedKeywords: allowedKeywords);
+    if (node != null) {
+      var contextType = featureComputer.computeContextType(node);
+      _recordContextType(contextType);
+      if (contextType != null) {
+        DartType elementType = _returnType(_leftMostElement(node));
+        if (elementType != null) {
+          _recordTypeRelationships(
+              'matches context type', contextType, elementType);
+        }
+      }
+    }
   }
 
   /// Record the [distance] from a reference to the declaration. The kind of
@@ -2036,6 +2063,8 @@
     }
 
     sink.writeln('');
+    _writeCounts(sink, data.simpleCounts);
+    sink.writeln('');
     _writeSideBySide(sink, [data.byTokenType, data.byElementKind],
         ['Token Types', 'Element Kinds']);
     sink.writeln('');
@@ -2186,6 +2215,14 @@
     }
   }
 
+  /// Write a [contextMap] containing one kind of metric data to the [sink].
+  void _writeCounts(StringSink sink, Map<String, int> countsMap) {
+    var names = countsMap.keys.toList()..sort();
+    for (var name in names) {
+      sink.writeln('$name = ${countsMap[name]}');
+    }
+  }
+
   /// Write the given [matrix] to the [sink]. The keys of the outer map will be
   /// the row titles; the keys of the inner map will be the column titles.
   void _writeMatrix(StringSink sink, Map<int, Map<int, int>> matrix) {
diff --git a/pkg/analysis_server/tool/completion_metrics/utils.dart b/pkg/analysis_server/tool/completion_metrics/utils.dart
index 33c100c..f9920c7 100644
--- a/pkg/analysis_server/tool/completion_metrics/utils.dart
+++ b/pkg/analysis_server/tool/completion_metrics/utils.dart
@@ -3,19 +3,39 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/element/element.dart';
 
-bool isTypeMember(SimpleIdentifier node) {
-  if (node == null || node is! SimpleIdentifier || node.staticElement == null) {
-    return false;
+/// Return the element associated with the syntactic [entity], or `null` if
+/// there is no such element.
+Element getElement(SyntacticEntity entity) {
+  if (entity is SimpleIdentifier) {
+    return entity.staticElement;
   }
-  var element = node.staticElement;
-  if (_isStatic(element)) {
-    return false;
-  }
-  return element.enclosingElement is ClassElement;
+  return null;
 }
 
+/// Return `true` if the [element] is an instance member of a class or
+/// extension.
+bool isInstanceMember(Element element) {
+  if (element == null || _isStatic(element)) {
+    return false;
+  }
+  var parent = element.enclosingElement;
+  return parent is ClassElement || parent is ExtensionElement;
+}
+
+/// Return `true` if the [element] is an static member of a class or extension.
+bool isStaticMember(Element element) {
+  if (element == null || !_isStatic(element)) {
+    return false;
+  }
+  var parent = element.enclosingElement;
+  return parent is ClassElement || parent is ExtensionElement;
+}
+
+/// Return `true` if the [element] is static (either top-level or a static
+/// member of a class or extension).
 bool _isStatic(Element element) {
   if (element is ClassMemberElement) {
     return element.isStatic;
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 3ebb54c..3c9248b 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -837,10 +837,14 @@
 ///      | identifier
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class CascadeExpression implements Expression {
+abstract class CascadeExpression
+    implements Expression, NullShortableExpression {
   /// Return the cascade sections sharing the common target.
   NodeList<Expression> get cascadeSections;
 
+  /// Whether this cascade is null aware (as opposed to non-null).
+  bool get isNullAware;
+
   /// Return the target of the cascade sections.
   Expression get target;
 
@@ -3727,7 +3731,8 @@
 ///        ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class MethodInvocation implements InvocationExpression {
+abstract class MethodInvocation
+    implements NullShortableExpression, InvocationExpression {
   /// Set the list of arguments to the method to the given [argumentList].
   set argumentList(ArgumentList argumentList);
 
@@ -4190,7 +4195,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class PostfixExpression
-    implements Expression, MethodReferenceExpression {
+    implements Expression, NullShortableExpression, MethodReferenceExpression {
   /// Return the expression computing the operand for the operator.
   Expression get operand;
 
@@ -4250,7 +4255,7 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class PrefixExpression
-    implements Expression, MethodReferenceExpression {
+    implements Expression, NullShortableExpression, MethodReferenceExpression {
   /// Return the expression computing the operand for the operator.
   Expression get operand;
 
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 76ae5b2..81f3c23 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -1048,7 +1048,7 @@
   List<NamespaceCombinator> get combinators;
 
   /// Return the library that is exported from this library by this export
-  /// directive.
+  /// directive, or `null` if the URI has invalid syntax or cannot be resolved.
   LibraryElement get exportedLibrary;
 }
 
@@ -1246,7 +1246,7 @@
   List<NamespaceCombinator> get combinators;
 
   /// Return the library that is imported into this library by this import
-  /// directive.
+  /// directive, or `null` if the URI has invalid syntax or cannot be resolved.
   LibraryElement get importedLibrary;
 
   /// Return `true` if this import is for a deferred library.
diff --git a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
index 9692a26..87ec58a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
@@ -34,10 +34,18 @@
   }
 
   /// Return the declaration of the [element], or `null` is the [element]
-  /// is synthetic.
+  /// is synthetic, or is declared in a file that is not a part of a library.
   Future<ElementDeclarationResult> getElementDeclaration(
       Element element) async {
     var libraryPath = element.library.source.fullName;
+
+    // This should not happen in valid code, but sometimes we treat a file
+    // with a `part of` directive as a library, because there is no library
+    // that contains this part, or because it is imported as a library.
+    if (isPart(libraryPath)) {
+      return null;
+    }
+
     var resolvedLibrary = await _getResolvedLibrary(libraryPath);
     return resolvedLibrary.getElementDeclaration(element);
   }
@@ -67,6 +75,11 @@
     }
   }
 
+  /// Return `true` if the file with the [path] is a part.
+  bool isPart(String path) {
+    return session.getFile(path).isPart;
+  }
+
   /// Return a newly resolved, or cached library with the given [path].
   Future<ResolvedLibraryResult> _getResolvedLibrary(String path) async {
     var result = _resolvedLibraries[path];
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index a5a7761..5d2bfe9 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -1199,6 +1199,7 @@
 ///        '[ ' expression '] '
 ///      | identifier
 class CascadeExpressionImpl extends ExpressionImpl
+    with NullShortableExpressionImpl
     implements CascadeExpression {
   /// The target of the cascade sections.
   ExpressionImpl _target;
@@ -1229,6 +1230,11 @@
   Token get endToken => _cascadeSections.endToken;
 
   @override
+  bool get isNullAware {
+    return target.endToken.next.type == TokenType.QUESTION_PERIOD_PERIOD;
+  }
+
+  @override
   Precedence get precedence => Precedence.cascade;
 
   @override
@@ -1240,6 +1246,9 @@
   }
 
   @override
+  AstNode get _nullShortingExtensionCandidate => null;
+
+  @override
   E accept<E>(AstVisitor<E> visitor) => visitor.visitCascadeExpression(this);
 
   @override
@@ -1247,6 +1256,11 @@
     _target?.accept(visitor);
     _cascadeSections.accept(visitor);
   }
+
+  @override
+  bool _extendsNullShorting(Expression descendant) {
+    return _cascadeSections.contains(descendant);
+  }
 }
 
 /// A catch clause within a try statement.
@@ -5862,12 +5876,16 @@
   bool get isCascaded => period != null;
 
   @override
-  bool get isNullAware =>
-      question != null ||
-      leftBracket.type == TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET ||
-      (leftBracket.type == TokenType.OPEN_SQUARE_BRACKET &&
-          period != null &&
-          period.type == TokenType.QUESTION_PERIOD_PERIOD);
+  bool get isNullAware {
+    if (isCascaded) {
+      return _ancestorCascade.isNullAware;
+    }
+    return question != null ||
+        leftBracket.type == TokenType.QUESTION_PERIOD_OPEN_SQUARE_BRACKET ||
+        (leftBracket.type == TokenType.OPEN_SQUARE_BRACKET &&
+            period != null &&
+            period.type == TokenType.QUESTION_PERIOD_PERIOD);
+  }
 
   @override
   Precedence get precedence => Precedence.postfix;
@@ -5875,14 +5893,7 @@
   @override
   Expression get realTarget {
     if (isCascaded) {
-      AstNode ancestor = parent;
-      while (ancestor is! CascadeExpression) {
-        if (ancestor == null) {
-          return _target;
-        }
-        ancestor = ancestor.parent;
-      }
-      return (ancestor as CascadeExpression).target;
+      return _ancestorCascade.target;
     }
     return _target;
   }
@@ -5895,6 +5906,18 @@
     _target = _becomeParentOf(expression as ExpressionImpl);
   }
 
+  /// Return the cascade that contains this [IndexExpression].
+  ///
+  /// We expect that [isCascaded] is `true`.
+  CascadeExpression get _ancestorCascade {
+    assert(isCascaded);
+    for (var ancestor = parent;; ancestor = ancestor.parent) {
+      if (ancestor is CascadeExpression) {
+        return ancestor;
+      }
+    }
+  }
+
   @override
   AstNode get _nullShortingExtensionCandidate => parent;
 
@@ -7037,10 +7060,14 @@
           operator.type == TokenType.QUESTION_PERIOD_PERIOD);
 
   @override
-  bool get isNullAware =>
-      operator != null &&
-      (operator.type == TokenType.QUESTION_PERIOD ||
-          operator.type == TokenType.QUESTION_PERIOD_PERIOD);
+  bool get isNullAware {
+    if (isCascaded) {
+      return _ancestorCascade.isNullAware;
+    }
+    return operator != null &&
+        (operator.type == TokenType.QUESTION_PERIOD ||
+            operator.type == TokenType.QUESTION_PERIOD_PERIOD);
+  }
 
   @override
   SimpleIdentifier get methodName => _methodName;
@@ -7072,14 +7099,7 @@
   @override
   Expression get realTarget {
     if (isCascaded) {
-      AstNode ancestor = parent;
-      while (ancestor is! CascadeExpression) {
-        if (ancestor == null) {
-          return _target;
-        }
-        ancestor = ancestor.parent;
-      }
-      return (ancestor as CascadeExpression).target;
+      return _ancestorCascade.target;
     }
     return _target;
   }
@@ -7092,6 +7112,18 @@
     _target = _becomeParentOf(expression as ExpressionImpl);
   }
 
+  /// Return the cascade that contains this [IndexExpression].
+  ///
+  /// We expect that [isCascaded] is `true`.
+  CascadeExpression get _ancestorCascade {
+    assert(isCascaded);
+    for (var ancestor = parent;; ancestor = ancestor.parent) {
+      if (ancestor is CascadeExpression) {
+        return ancestor;
+      }
+    }
+  }
+
   @override
   AstNode get _nullShortingExtensionCandidate => parent;
 
@@ -8028,6 +8060,7 @@
 ///    postfixExpression ::=
 ///        [Expression] [Token]
 class PostfixExpressionImpl extends ExpressionImpl
+    with NullShortableExpressionImpl
     implements PostfixExpression {
   /// The expression computing the operand for the operator.
   ExpressionImpl _operand;
@@ -8068,6 +8101,9 @@
   @override
   Precedence get precedence => Precedence.postfix;
 
+  @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 operand will be
@@ -8090,6 +8126,9 @@
   void visitChildren(AstVisitor visitor) {
     _operand?.accept(visitor);
   }
+
+  @override
+  bool _extendsNullShorting(Expression child) => identical(child, operand);
 }
 
 /// An identifier that is prefixed or an access to an object property where the
@@ -8189,7 +8228,9 @@
 ///
 ///    prefixExpression ::=
 ///        [Token] [Expression]
-class PrefixExpressionImpl extends ExpressionImpl implements PrefixExpression {
+class PrefixExpressionImpl extends ExpressionImpl
+    with NullShortableExpressionImpl
+    implements PrefixExpression {
   /// The prefix operator being applied to the operand.
   @override
   Token operator;
@@ -8229,6 +8270,9 @@
   @override
   Precedence get precedence => Precedence.prefix;
 
+  @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 operand will be
@@ -8251,6 +8295,9 @@
   void visitChildren(AstVisitor visitor) {
     _operand?.accept(visitor);
   }
+
+  @override
+  bool _extendsNullShorting(Expression child) => identical(child, operand);
 }
 
 /// The access of a property of an object.
@@ -8306,10 +8353,14 @@
           operator.type == TokenType.QUESTION_PERIOD_PERIOD);
 
   @override
-  bool get isNullAware =>
-      operator != null &&
-      (operator.type == TokenType.QUESTION_PERIOD ||
-          operator.type == TokenType.QUESTION_PERIOD_PERIOD);
+  bool get isNullAware {
+    if (isCascaded) {
+      return _ancestorCascade.isNullAware;
+    }
+    return operator != null &&
+        (operator.type == TokenType.QUESTION_PERIOD ||
+            operator.type == TokenType.QUESTION_PERIOD_PERIOD);
+  }
 
   @override
   Precedence get precedence => Precedence.postfix;
@@ -8325,14 +8376,7 @@
   @override
   Expression get realTarget {
     if (isCascaded) {
-      AstNode ancestor = parent;
-      while (ancestor is! CascadeExpression) {
-        if (ancestor == null) {
-          return _target;
-        }
-        ancestor = ancestor.parent;
-      }
-      return (ancestor as CascadeExpression).target;
+      return _ancestorCascade.target;
     }
     return _target;
   }
@@ -8345,6 +8389,18 @@
     _target = _becomeParentOf(expression as ExpressionImpl);
   }
 
+  /// Return the cascade that contains this [IndexExpression].
+  ///
+  /// We expect that [isCascaded] is `true`.
+  CascadeExpression get _ancestorCascade {
+    assert(isCascaded);
+    for (var ancestor = parent;; ancestor = ancestor.parent) {
+      if (ancestor is CascadeExpression) {
+        return ancestor;
+      }
+    }
+  }
+
   @override
   AstNode get _nullShortingExtensionCandidate => parent;
 
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 6512d66..3c58f20 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -418,41 +418,6 @@
     }
   }
 
-  /// Evaluate a call to fromEnvironment() on the bool, int, or String class.
-  /// The [environmentValue] is the value fetched from the environment. The
-  /// [builtInDefaultValue] is the value that should be used as the default if
-  /// no "defaultValue" argument appears in [namedArgumentValues]. The
-  /// [namedArgumentValues] are the values of the named parameters passed to
-  /// fromEnvironment(). Return a [DartObjectImpl] object corresponding to the
-  /// evaluated result.
-  DartObjectImpl computeValueFromEnvironment(
-      DartObject environmentValue,
-      DartObjectImpl builtInDefaultValue,
-      Map<String, DartObjectImpl> namedArgumentValues) {
-    DartObjectImpl value = environmentValue as DartObjectImpl;
-    if (value.isUnknown || value.isNull) {
-      // The name either doesn't exist in the environment or we couldn't parse
-      // the corresponding value.
-      // If the code supplied an explicit default, use it.
-      if (namedArgumentValues.containsKey(_DEFAULT_VALUE_PARAM)) {
-        value = namedArgumentValues[_DEFAULT_VALUE_PARAM];
-      } else if (value.isNull) {
-        // The code didn't supply an explicit default.
-        // The name exists in the environment but we couldn't parse the
-        // corresponding value.
-        // So use the built-in default value, because this is what the VM does.
-        value = builtInDefaultValue;
-      } else {
-        // The code didn't supply an explicit default.
-        // The name doesn't exist in the environment.
-        // The VM would use the built-in default value, but we don't want to do
-        // that for analysis because it's likely to lead to cascading errors.
-        // So just leave [value] in the unknown state.
-      }
-    }
-    return value;
-  }
-
   DartObjectImpl evaluateConstructorCall(
       AstNode node,
       List<Expression> arguments,
@@ -527,44 +492,19 @@
         String variableName =
             argumentCount < 1 ? null : argumentValues[0].toStringValue();
         if (definingClass == typeProvider.boolType) {
-          DartObject valueFromEnvironment;
-          valueFromEnvironment =
-              _fromEnvironmentEvaluator.getBool(variableName);
-          return computeValueFromEnvironment(
-            valueFromEnvironment,
-            DartObjectImpl(
-              typeSystem,
-              typeProvider.boolType,
-              BoolState.FALSE_STATE,
-            ),
-            namedValues,
-          );
+          return _fromEnvironmentEvaluator.getBool2(
+              variableName, namedValues, constructor);
         } else if (definingClass == typeProvider.intType) {
-          DartObject valueFromEnvironment;
-          valueFromEnvironment = _fromEnvironmentEvaluator.getInt(variableName);
-          return computeValueFromEnvironment(
-            valueFromEnvironment,
-            DartObjectImpl(
-              typeSystem,
-              typeProvider.nullType,
-              NullState.NULL_STATE,
-            ),
-            namedValues,
-          );
+          return _fromEnvironmentEvaluator.getInt2(
+              variableName, namedValues, constructor);
         } else if (definingClass == typeProvider.stringType) {
-          DartObject valueFromEnvironment;
-          valueFromEnvironment =
-              _fromEnvironmentEvaluator.getString(variableName);
-          return computeValueFromEnvironment(
-            valueFromEnvironment,
-            DartObjectImpl(
-              typeSystem,
-              typeProvider.nullType,
-              NullState.NULL_STATE,
-            ),
-            namedValues,
-          );
+          return _fromEnvironmentEvaluator.getString2(
+              variableName, namedValues, constructor);
         }
+      } else if (constructor.name == 'hasEnvironment' &&
+          definingClass == typeProvider.boolType) {
+        var name = argumentCount < 1 ? null : argumentValues[0].toStringValue();
+        return _fromEnvironmentEvaluator.hasEnvironment(name);
       } else if (constructor.name == "" &&
           definingClass == typeProvider.symbolType &&
           argumentCount == 1) {
@@ -1579,7 +1519,9 @@
   /// failed.
   bool _addElementsToMap(
       Map<DartObjectImpl, DartObjectImpl> map, CollectionElement element) {
-    if (element is IfElement) {
+    if (element is ForElement) {
+      _error(element, null);
+    } else if (element is IfElement) {
       bool conditionValue = _evaluateCondition(element.condition);
       if (conditionValue == null) {
         return true;
@@ -1614,7 +1556,9 @@
   /// the given [set]. Return `true` if the evaluation of one or more of the
   /// elements failed.
   bool _addElementsToSet(Set<DartObject> set, CollectionElement element) {
-    if (element is IfElement) {
+    if (element is ForElement) {
+      _error(element, null);
+    } else if (element is IfElement) {
       bool conditionValue = _evaluateCondition(element.condition);
       if (conditionValue == null) {
         return true;
@@ -1816,27 +1760,6 @@
   }
 }
 
-/// A visitor to find if a type contains any [TypeParameterType]s.
-///
-/// To find the result, check [result] on this instance after visiting the tree.
-/// The actual value returned by the visit methods is merely used so that
-/// [RecursiveTypeVisitor] stops visiting the type once the first type parameter
-/// type is found.
-class _ReferencesTypeParameterVisitor extends RecursiveTypeVisitor {
-  /// The result of whether any type parameters were found.
-  bool result = false;
-
-  @override
-  bool visitTypeParameterType(_) {
-    result = true;
-    // Stop visiting at this point.
-    return false;
-  }
-
-  @override
-  bool defaultDartType(_) => true; // Continue visiting in this case.
-}
-
 /// A utility class that contains methods for manipulating instances of a Dart
 /// class and for collecting errors during evaluation.
 class DartObjectComputer {
@@ -2332,3 +2255,24 @@
     return value.toString();
   }
 }
+
+/// A visitor to find if a type contains any [TypeParameterType]s.
+///
+/// To find the result, check [result] on this instance after visiting the tree.
+/// The actual value returned by the visit methods is merely used so that
+/// [RecursiveTypeVisitor] stops visiting the type once the first type parameter
+/// type is found.
+class _ReferencesTypeParameterVisitor extends RecursiveTypeVisitor {
+  /// The result of whether any type parameters were found.
+  bool result = false;
+
+  @override
+  bool defaultDartType(_) => true;
+
+  @override
+  bool visitTypeParameterType(_) {
+    result = true;
+    // Stop visiting at this point.
+    return false;
+  } // Continue visiting in this case.
+}
diff --git a/pkg/analyzer/lib/src/dart/constant/from_environment_evaluator.dart b/pkg/analyzer/lib/src/dart/constant/from_environment_evaluator.dart
index 92534ce..a16a260 100644
--- a/pkg/analyzer/lib/src/dart/constant/from_environment_evaluator.dart
+++ b/pkg/analyzer/lib/src/dart/constant/from_environment_evaluator.dart
@@ -4,10 +4,14 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/constant/value.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
 import 'package:analyzer/src/generated/type_system.dart';
 
 class FromEnvironmentEvaluator {
+  /// Parameter to "fromEnvironment" methods that denotes the default value.
+  static const String _defaultValue = 'defaultValue';
+
   final TypeSystemImpl _typeSystem;
   final DeclaredVariables _declaredVariables;
 
@@ -17,6 +21,7 @@
   /// 'boolean' value. If the variable is not defined (or [name] is `null`), a
   /// DartObject representing "unknown" is returned. If the value cannot be
   /// parsed as a boolean, a DartObject representing 'null' is returned.
+  @Deprecated("Clients don't need this functionality")
   DartObject getBool(String name) {
     String value = _declaredVariables.get(name);
     if (value == null) {
@@ -46,10 +51,44 @@
     );
   }
 
+  /// Return the value of the variable with the given [name] interpreted as a
+  /// 'boolean' value. If the variable is not defined, or the value cannot be
+  /// parsed as a boolean, return the default value from [namedValues]. If no
+  /// default value, return the default value of the default value from
+  /// the [constructor], possibly a [DartObject] representing 'null'.
+  DartObject getBool2(
+    String name,
+    Map<String, DartObjectImpl> namedValues,
+    ConstructorElement constructor,
+  ) {
+    var str = _declaredVariables.get(name);
+    if (str == 'true') {
+      return DartObjectImpl(
+        _typeSystem,
+        _typeSystem.typeProvider.boolType,
+        BoolState.TRUE_STATE,
+      );
+    }
+    if (str == 'false') {
+      return DartObjectImpl(
+        _typeSystem,
+        _typeSystem.typeProvider.boolType,
+        BoolState.FALSE_STATE,
+      );
+    }
+
+    if (namedValues.containsKey(_defaultValue)) {
+      return namedValues[_defaultValue];
+    }
+
+    return _defaultValueDefaultValue(constructor);
+  }
+
   /// Return the value of the variable with the given [name] interpreted as an
   /// integer value. If the variable is not defined (or [name] is `null`), a
   /// DartObject representing "unknown" is returned. If the value cannot be
   /// parsed as an integer, a DartObject representing 'null' is returned.
+  @Deprecated("Clients don't need this functionality")
   DartObject getInt(String name) {
     String value = _declaredVariables.get(name);
     if (value == null) {
@@ -76,11 +115,54 @@
     );
   }
 
+  /// Return the value of the variable with the given [name] interpreted as an
+  /// integer value. If the variable is not defined, or the value cannot be
+  /// parsed as an integer, return the default value from [namedValues]. If no
+  /// default value, return the default value of the default value from
+  /// the [constructor], possibly a [DartObject] representing 'null'.
+  DartObject getInt2(
+    String name,
+    Map<String, DartObjectImpl> namedValues,
+    ConstructorElement constructor,
+  ) {
+    var str = _declaredVariables.get(name);
+    if (str != null) {
+      try {
+        var value = int.parse(str);
+        return DartObjectImpl(
+          _typeSystem,
+          _typeSystem.typeProvider.intType,
+          IntState(value),
+        );
+      } on FormatException {
+        // fallthrough
+      }
+    }
+
+    if (namedValues.containsKey(_defaultValue)) {
+      return namedValues[_defaultValue];
+    }
+
+    var defaultDefault = _defaultValueDefaultValue(constructor);
+
+    // TODO(scheglov) Remove after https://github.com/dart-lang/sdk/issues/40678
+    if (defaultDefault.isNull) {
+      return DartObjectImpl(
+        _typeSystem,
+        _typeSystem.typeProvider.intType,
+        IntState.UNKNOWN_VALUE,
+      );
+    }
+
+    return defaultDefault;
+  }
+
   /// Return the value of the variable with the given [name] interpreted as a
   /// String value, or `null` if the variable is not defined. Return the value
   /// of the variable with the given name interpreted as a String value. If the
   /// variable is not defined (or [name] is `null`), a DartObject representing
   /// "unknown" is returned.
+  @Deprecated("Clients don't need this functionality")
   DartObject getString(String name) {
     String value = _declaredVariables.get(name);
     if (value == null) {
@@ -96,4 +178,56 @@
       StringState(value),
     );
   }
+
+  /// Return the value of the variable with the given [name] interpreted as a
+  /// string value. If the variable is not defined, or the value cannot be
+  /// parsed as a boolean, return the default value from [namedValues]. If no
+  /// default value, return the default value of the default value from
+  /// the [constructor], possibly a [DartObject] representing 'null'.
+  DartObject getString2(
+    String name,
+    Map<String, DartObjectImpl> namedValues,
+    ConstructorElement constructor,
+  ) {
+    String str = _declaredVariables.get(name);
+    if (str != null) {
+      return DartObjectImpl(
+        _typeSystem,
+        _typeSystem.typeProvider.stringType,
+        StringState(str),
+      );
+    }
+
+    if (namedValues.containsKey(_defaultValue)) {
+      return namedValues[_defaultValue];
+    }
+
+    var defaultDefault = _defaultValueDefaultValue(constructor);
+
+    // TODO(scheglov) Remove after https://github.com/dart-lang/sdk/issues/40678
+    if (defaultDefault.isNull) {
+      return DartObjectImpl(
+        _typeSystem,
+        _typeSystem.typeProvider.stringType,
+        StringState.UNKNOWN_VALUE,
+      );
+    }
+
+    return defaultDefault;
+  }
+
+  DartObject hasEnvironment(String name) {
+    var value = _declaredVariables.get(name) != null;
+    return DartObjectImpl(
+      _typeSystem,
+      _typeSystem.typeProvider.boolType,
+      BoolState(value),
+    );
+  }
+
+  static DartObject _defaultValueDefaultValue(ConstructorElement constructor) {
+    return constructor.parameters
+        .singleWhere((parameter) => parameter.name == _defaultValue)
+        .computeConstantValue();
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/error/lint_codes.dart b/pkg/analyzer/lib/src/dart/error/lint_codes.dart
index 53e09ad..0a3659c 100644
--- a/pkg/analyzer/lib/src/dart/error/lint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/lint_codes.dart
@@ -36,6 +36,5 @@
   String get uniqueName => "LintCode.$name";
 
   @override
-  String get url =>
-      'https://dart-lang.github.io/linter/lints/${name.toLowerCase()}.html';
+  String get url => 'https://dart-lang.github.io/linter/lints/$name.html';
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
index 8f7dd08..b87deb7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
@@ -72,7 +72,6 @@
 
     var returnType = _inferenceHelper.computeInvokeReturnType(
       node.staticInvokeType,
-      isNullAware: false,
     );
     _inferenceHelper.recordStaticType(node, returnType);
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
index 779d22a..a917c05 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
@@ -44,20 +44,13 @@
 
   /// Compute the return type of the method or function represented by the given
   /// type that is being invoked.
-  DartType computeInvokeReturnType(DartType type,
-      {@required bool isNullAware}) {
-    TypeImpl returnType;
+  DartType computeInvokeReturnType(DartType type) {
     if (type is FunctionType) {
-      returnType = type.returnType ?? DynamicTypeImpl.instance;
+      // TODO(scheglov) https://github.com/dart-lang/sdk/issues/41065
+      return type.returnType ?? DynamicTypeImpl.instance;
     } else {
-      returnType = DynamicTypeImpl.instance;
+      return DynamicTypeImpl.instance;
     }
-
-    if (isNullAware && _typeSystem.isNonNullableByDefault) {
-      returnType = _typeSystem.makeNullable(returnType);
-    }
-
-    return returnType;
   }
 
   FunctionType inferArgumentTypesForGeneric(AstNode inferenceNode,
@@ -273,10 +266,7 @@
     node.typeArgumentTypes = _typeArgumentTypes;
     node.staticInvokeType = _invokeType;
 
-    var returnType = computeInvokeReturnType(
-      _invokeType,
-      isNullAware: node.isNullAware,
-    );
+    var returnType = computeInvokeReturnType(_invokeType);
     recordStaticType(node, returnType);
   }
 
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 359d327..6736d8d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -300,8 +300,6 @@
     if (!inferred) {
       DartType staticStaticType = _inferenceHelper.computeInvokeReturnType(
         node.staticInvokeType,
-        isNullAware:
-            _migratableAstInfoProvider.isMethodInvocationNullAware(node),
       );
       _inferenceHelper.recordStaticType(node, staticStaticType);
     }
diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
index 0d5cb00..5917ebc 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -95,12 +95,11 @@
       FunctionType propertyType = element.type;
       if (propertyType != null) {
         return _resolver.inferenceHelper.computeInvokeReturnType(
-            propertyType.returnType,
-            isNullAware: false);
+          propertyType.returnType,
+        );
       }
     } else if (element is ExecutableElement) {
-      return _resolver.inferenceHelper
-          .computeInvokeReturnType(element.type, isNullAware: false);
+      return _resolver.inferenceHelper.computeInvokeReturnType(element.type);
     }
     return DynamicTypeImpl.instance;
   }
@@ -188,6 +187,7 @@
     }
 
     _inferenceHelper.recordStaticType(node, receiverType);
+    _resolver.nullShortingTermination(node);
   }
 
   void _resolveNullCheck(PostfixExpressionImpl node) {
@@ -204,9 +204,7 @@
     operand.accept(_resolver);
     operand = node.operand;
 
-    var operandType = getReadType(
-      operand,
-    );
+    var operandType = getReadType(operand);
 
     var type = _typeSystem.promoteToNonNull(operandType);
     _inferenceHelper.recordStaticType(node, type);
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index 46e6e28..24eaae3 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -95,12 +95,11 @@
       FunctionType propertyType = element.type;
       if (propertyType != null) {
         return _resolver.inferenceHelper.computeInvokeReturnType(
-            propertyType.returnType,
-            isNullAware: false);
+          propertyType.returnType,
+        );
       }
     } else if (element is ExecutableElement) {
-      return _resolver.inferenceHelper
-          .computeInvokeReturnType(element.type, isNullAware: false);
+      return _resolver.inferenceHelper.computeInvokeReturnType(element.type);
     }
     return DynamicTypeImpl.instance;
   }
@@ -248,6 +247,7 @@
       }
       _recordStaticType(node, staticType);
     }
+    _resolver.nullShortingTermination(node);
   }
 
   void _resolveNegation(PrefixExpressionImpl node) {
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 2d2182c..3242a16 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -879,7 +879,7 @@
     if (node.isNullAware) {
       _checkForUnnecessaryNullAware(
         node.realTarget,
-        node.period ?? node.leftBracket,
+        node.question ?? node.period ?? node.leftBracket,
       );
     }
     super.visitIndexExpression(node);
@@ -3681,11 +3681,17 @@
         LibraryElement library = type.element.library;
         if (library != _currentLibrary) {
           for (PropertyAccessorElement accessor in type.accessors) {
+            if (accessor.isStatic) {
+              continue;
+            }
             if (isConflictingName(accessor.name, library, mixinType)) {
               return;
             }
           }
           for (MethodElement method in type.methods) {
+            if (method.isStatic) {
+              continue;
+            }
             if (isConflictingName(method.name, library, mixinType)) {
               return;
             }
@@ -4637,6 +4643,12 @@
       return;
     }
 
+    // Ignore if the constructor is external. See
+    // https://github.com/dart-lang/language/issues/869.
+    if (constructor.externalKeyword != null) {
+      return;
+    }
+
     // Ignore if the constructor has either an implicit super constructor
     // invocation or a redirecting constructor invocation.
     for (ConstructorInitializer constructorInitializer
@@ -4687,8 +4699,13 @@
     }
 
     ErrorCode errorCode;
+    Token endToken = operator;
     List<Object> arguments = const [];
-    if (operator.type == TokenType.QUESTION_PERIOD) {
+    if (operator.type == TokenType.QUESTION) {
+      errorCode = StaticWarningCode.INVALID_NULL_AWARE_OPERATOR;
+      endToken = operator.next;
+      arguments = ['?[', '['];
+    } else if (operator.type == TokenType.QUESTION_PERIOD) {
       errorCode = StaticWarningCode.INVALID_NULL_AWARE_OPERATOR;
       arguments = [operator.lexeme, '.'];
     } else if (operator.type == TokenType.QUESTION_PERIOD_PERIOD) {
@@ -4707,7 +4724,12 @@
     }
 
     if (_typeSystem.isStrictlyNonNullable(target.staticType)) {
-      _errorReporter.reportErrorForToken(errorCode, operator, arguments);
+      _errorReporter.reportErrorForOffset(
+        errorCode,
+        operator.offset,
+        endToken.end - operator.offset,
+        arguments,
+      );
     }
   }
 
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 02015c3..3c731ff 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -724,7 +724,19 @@
   @override
   void visitCascadeExpression(CascadeExpression node) {
     InferenceContext.setTypeFromNode(node.target, node);
-    super.visitCascadeExpression(node);
+    node.target.accept(this);
+
+    if (node.isNullAware && _isNonNullableByDefault) {
+      _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
+      _unfinishedNullShorts.add(node.nullShortingTermination);
+    }
+
+    node.cascadeSections.accept(this);
+
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
+
+    nullShortingTermination(node);
   }
 
   @override
@@ -1358,11 +1370,14 @@
 
   @override
   void visitMethodInvocation(MethodInvocation node) {
-    //
-    // We visit the target and argument list, but do not visit the method name
-    // because it needs to be visited in the context of the invocation.
-    //
     node.target?.accept(this);
+
+    if (_migratableAstInfoProvider.isMethodInvocationNullAware(node) &&
+        _isNonNullableByDefault) {
+      _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
+      _unfinishedNullShorts.add(node.nullShortingTermination);
+    }
+
     node.typeArguments?.accept(this);
     node.accept(elementResolver);
 
diff --git a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
index 2f012c8..4cc3de6 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -163,8 +163,11 @@
           identifier3(propertyName));
 
   static CascadeExpression cascadeExpression(Expression target,
-          [List<Expression> cascadeSections]) =>
-      astFactory.cascadeExpression(target, cascadeSections);
+      [List<Expression> cascadeSections]) {
+    var cascade = astFactory.cascadeExpression(target, cascadeSections);
+    cascade.target.endToken.next = cascadeSections.first.beginToken;
+    return cascade;
+  }
 
   static CatchClause catchClause(String exceptionParameter,
           [List<Statement> statements]) =>
diff --git a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
index 6b19881..fd7b111 100644
--- a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
@@ -572,6 +572,7 @@
   void visitIndexExpression(IndexExpression node) {
     node.target?.accept(this);
     _token(node.period);
+    _token(node.question);
     _token(node.leftBracket);
     node.index.accept(this);
     _token(node.rightBracket);
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index d46db5f..e1a6501 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -37,10 +37,14 @@
 
 DartType getReadType(Expression expression) {
   if (expression is IndexExpression) {
-    var staticElement = expression.auxiliaryElements?.staticElement;
-    return staticElement == null
-        ? DynamicTypeImpl.instance
-        : staticElement.returnType;
+    var aux = expression.auxiliaryElements;
+    if (aux != null) {
+      var staticElement = aux.staticElement;
+      return staticElement == null
+          ? DynamicTypeImpl.instance
+          : staticElement.returnType;
+    }
+    return expression.staticType;
   }
   {
     Element setter;
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 92374b8..9d1f9f9 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -254,6 +254,8 @@
   external const factory bool.fromEnvironment(String name,
       {bool defaultValue: false});
 
+  external const factory bool.hasEnvironment(String name);
+
   bool operator &(bool other);
   bool operator |(bool other);
   bool operator ^(bool other);
diff --git a/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart b/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart
index 3204b56..5ff1042 100644
--- a/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart
+++ b/pkg/analyzer/test/dart/analysis/from_environment_evaluator_test.dart
@@ -30,6 +30,7 @@
     typeSystem = analysisContext.typeSystemLegacy;
   }
 
+  @deprecated
   void test_getBool_false() {
     String variableName = "var";
     var variables = FromEnvironmentEvaluator(
@@ -41,6 +42,7 @@
     expect(object.toBoolValue(), false);
   }
 
+  @deprecated
   void test_getBool_invalid() {
     String variableName = "var";
     var variables = FromEnvironmentEvaluator(
@@ -52,6 +54,7 @@
     );
   }
 
+  @deprecated
   void test_getBool_true() {
     String variableName = "var";
     var variables = FromEnvironmentEvaluator(
@@ -63,6 +66,7 @@
     expect(object.toBoolValue(), true);
   }
 
+  @deprecated
   void test_getBool_undefined() {
     String variableName = "var";
     var variables = FromEnvironmentEvaluator(
@@ -75,6 +79,7 @@
     );
   }
 
+  @deprecated
   void test_getInt_invalid() {
     String variableName = "var";
     var variables = FromEnvironmentEvaluator(
@@ -86,6 +91,7 @@
     );
   }
 
+  @deprecated
   void test_getInt_undefined() {
     String variableName = "var";
     var variables = FromEnvironmentEvaluator(
@@ -98,6 +104,7 @@
     );
   }
 
+  @deprecated
   void test_getInt_valid() {
     String variableName = "var";
     var variables = FromEnvironmentEvaluator(
@@ -109,6 +116,7 @@
     expect(object.toIntValue(), 23);
   }
 
+  @deprecated
   void test_getString_defined() {
     String variableName = "var";
     String value = "value";
@@ -121,6 +129,7 @@
     expect(object.toStringValue(), value);
   }
 
+  @deprecated
   void test_getString_undefined() {
     String variableName = "var";
     var variables = FromEnvironmentEvaluator(
diff --git a/pkg/analyzer/test/dart/ast/ast_test.dart b/pkg/analyzer/test/dart/ast/ast_test.dart
index bbdf072..a01453f 100644
--- a/pkg/analyzer/test/dart/ast/ast_test.dart
+++ b/pkg/analyzer/test/dart/ast/ast_test.dart
@@ -338,6 +338,10 @@
         AstTestFactory.nullLiteral(),
         TokenType.PERIOD_PERIOD,
         TokenType.OPEN_SQUARE_BRACKET);
+    AstTestFactory.cascadeExpression(
+      AstTestFactory.nullLiteral(),
+      [expression],
+    );
     expect(expression.isNullAware, isFalse);
   }
 
@@ -347,6 +351,10 @@
         AstTestFactory.nullLiteral(),
         TokenType.QUESTION_PERIOD_PERIOD,
         TokenType.OPEN_SQUARE_BRACKET);
+    AstTestFactory.cascadeExpression(
+      AstTestFactory.nullLiteral(),
+      [expression],
+    );
     expect(expression.isNullAware, isTrue);
   }
 
@@ -416,18 +424,32 @@
 @reflectiveTest
 class MethodInvocationTest extends ParserTestCase {
   void test_isNullAware_cascade() {
-    final invocation = AstTestFactory.methodInvocation3(
-        AstTestFactory.nullLiteral(), 'foo', null, [], TokenType.PERIOD_PERIOD);
+    var invocation = astFactory.methodInvocation(
+      null,
+      TokenFactory.tokenFromType(TokenType.PERIOD_PERIOD),
+      AstTestFactory.identifier3('foo'),
+      null,
+      AstTestFactory.argumentList(),
+    );
+    AstTestFactory.cascadeExpression(
+      AstTestFactory.nullLiteral(),
+      [invocation],
+    );
     expect(invocation.isNullAware, isFalse);
   }
 
   void test_isNullAware_cascade_true() {
-    final invocation = AstTestFactory.methodInvocation3(
-        AstTestFactory.nullLiteral(),
-        'foo',
-        null,
-        [],
-        TokenType.QUESTION_PERIOD_PERIOD);
+    var invocation = astFactory.methodInvocation(
+      null,
+      TokenFactory.tokenFromType(TokenType.QUESTION_PERIOD_PERIOD),
+      AstTestFactory.identifier3('foo'),
+      null,
+      AstTestFactory.argumentList(),
+    );
+    AstTestFactory.cascadeExpression(
+      AstTestFactory.nullLiteral(),
+      [invocation],
+    );
     expect(invocation.isNullAware, isTrue);
   }
 
@@ -805,12 +827,20 @@
   void test_isNullAware_cascade() {
     final invocation = AstTestFactory.propertyAccess2(
         AstTestFactory.nullLiteral(), 'foo', TokenType.PERIOD_PERIOD);
+    AstTestFactory.cascadeExpression(
+      AstTestFactory.nullLiteral(),
+      [invocation],
+    );
     expect(invocation.isNullAware, isFalse);
   }
 
   void test_isNullAware_cascade_true() {
     final invocation = AstTestFactory.propertyAccess2(
-        AstTestFactory.nullLiteral(), 'foo', TokenType.QUESTION_PERIOD_PERIOD);
+        null, 'foo', TokenType.QUESTION_PERIOD_PERIOD);
+    AstTestFactory.cascadeExpression(
+      AstTestFactory.nullLiteral(),
+      [invocation],
+    );
     expect(invocation.isNullAware, isTrue);
   }
 
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index e088422..9b6b82f 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -1599,40 +1599,6 @@
     ]);
   }
 
-  test_noDefaultSuperConstructorExplicit() async {
-    await assertErrorsInCode(r'''
-class A {
-  A(p);
-}
-class B extends A {
-  B() {}
-}
-''', [
-      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, 42, 1),
-    ]);
-  }
-
-  test_noDefaultSuperConstructorImplicit_superHasParameters() async {
-    await assertErrorsInCode(r'''
-class A {
-  A(p);
-}
-class B extends A {
-}
-''', [
-      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 26, 1),
-    ]);
-  }
-
-  test_noDefaultSuperConstructorImplicit_superOnlyNamed() async {
-    await assertErrorsInCode(r'''
-class A { A.named() {} }
-class B extends A {}
-''', [
-      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 31, 1),
-    ]);
-  }
-
   test_nonConstantAnnotationConstructor_named() async {
     await assertErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/id_tests/inheritance_test.dart b/pkg/analyzer/test/id_tests/inheritance_test.dart
index ad273d5..2f2c9e6 100644
--- a/pkg/analyzer/test/id_tests/inheritance_test.dart
+++ b/pkg/analyzer/test/id_tests/inheritance_test.dart
@@ -89,11 +89,15 @@
           if (element.isSetter) {
             setterNames.add(Name(element, isSetter: true));
           }
-          var getter = element.correspondingGetter;
+          var getter = element.declaration.correspondingGetter != null
+              ? element.correspondingGetter
+              : null;
           if (getter != null) {
             getterNames.add(Name(getter));
           }
-          var setter = element.correspondingSetter;
+          var setter = element.declaration.correspondingSetter != null
+              ? element.correspondingSetter
+              : null;
           if (setter != null) {
             setterNames.add(Name(setter, isSetter: true));
           }
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 7181255..0c8d536 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -108,6 +108,91 @@
     expect(result, isNull);
   }
 
+  test_visitInstanceCreationExpression_bool_fromEnvironment() async {
+    await resolveTestCode('''
+const a = bool.fromEnvironment('a');
+const b = bool.fromEnvironment('b', defaultValue: true);
+''');
+    expect(
+      _evaluateConstant('a'),
+      _boolValue(false),
+    );
+    expect(
+      _evaluateConstant('a', declaredVariables: {'a': 'true'}),
+      _boolValue(true),
+    );
+
+    expect(
+      _evaluateConstant(
+        'b',
+        declaredVariables: {'b': 'bbb'},
+        lexicalEnvironment: {'defaultValue': _boolValue(true)},
+      ),
+      _boolValue(true),
+    );
+  }
+
+  test_visitInstanceCreationExpression_bool_hasEnvironment() async {
+    await resolveTestCode('''
+const a = bool.hasEnvironment('a');
+''');
+    expect(
+      _evaluateConstant('a'),
+      _boolValue(false),
+    );
+
+    expect(
+      _evaluateConstant('a', declaredVariables: {'a': '42'}),
+      _boolValue(true),
+    );
+  }
+
+  test_visitInstanceCreationExpression_int_fromEnvironment() async {
+    await resolveTestCode('''
+const a = int.fromEnvironment('a');
+const b = int.fromEnvironment('b', defaultValue: 42);
+''');
+    expect(
+      _evaluateConstant('a'),
+      _intValue(0),
+    );
+    expect(
+      _evaluateConstant('a', declaredVariables: {'a': '5'}),
+      _intValue(5),
+    );
+
+    expect(
+      _evaluateConstant(
+        'b',
+        declaredVariables: {'b': 'bbb'},
+        lexicalEnvironment: {'defaultValue': _intValue(42)},
+      ),
+      _intValue(42),
+    );
+  }
+
+  test_visitInstanceCreationExpression_string_fromEnvironment() async {
+    await resolveTestCode('''
+const a = String.fromEnvironment('a');
+''');
+    expect(
+      _evaluateConstant('a'),
+      DartObjectImpl(
+        typeSystem,
+        typeProvider.stringType,
+        StringState(''),
+      ),
+    );
+    expect(
+      _evaluateConstant('a', declaredVariables: {'a': 'test'}),
+      DartObjectImpl(
+        typeSystem,
+        typeProvider.stringType,
+        StringState('test'),
+      ),
+    );
+  }
+
   test_visitIntegerLiteral() async {
     await resolveTestCode('''
 const double d = 3;
@@ -187,12 +272,38 @@
     expect(result.type, typeProvider.intType);
     expect(result.toIntValue(), 3);
   }
+
+  DartObjectImpl _boolValue(bool value) {
+    if (identical(value, false)) {
+      return DartObjectImpl(
+        typeSystem,
+        typeProvider.boolType,
+        BoolState.FALSE_STATE,
+      );
+    } else if (identical(value, true)) {
+      return DartObjectImpl(
+        typeSystem,
+        typeProvider.boolType,
+        BoolState.TRUE_STATE,
+      );
+    }
+    fail("Invalid boolean value used in test");
+  }
+
+  DartObjectImpl _intValue(int value) {
+    return DartObjectImpl(
+      typeSystem,
+      typeProvider.intType,
+      IntState(value),
+    );
+  }
 }
 
 class ConstantVisitorTestSupport extends DriverResolutionTest {
   DartObjectImpl _evaluateConstant(
     String name, {
     List<ErrorCode> errorCodes,
+    Map<String, String> declaredVariables = const {},
     Map<String, DartObjectImpl> lexicalEnvironment,
   }) {
     var options = driver.analysisOptions as AnalysisOptionsImpl;
@@ -210,7 +321,7 @@
       ConstantVisitor(
         ConstantEvaluationEngine(
           typeProvider,
-          DeclaredVariables(),
+          DeclaredVariables.fromMap(declaredVariables),
           experimentStatus: options.experimentStatus,
           typeSystem: this.result.typeSystem,
         ),
diff --git a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
index 7d0756e..80d9ab1 100644
--- a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
@@ -247,14 +247,14 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  test_cascade_read_nullable() async {
+  test_read_cascade_nullShorting() async {
     await assertNoErrorsInCode(r'''
 class A {
   bool operator[](int index) => false;
 }
 
 main(A? a) {
-  a?..[0];
+  a?..[0]..[1];
 }
 ''');
 
@@ -264,8 +264,17 @@
       findNode.index('..[0]'),
       readElement: indexElement,
       writeElement: null,
-      type: 'bool?',
+      type: 'bool',
     );
+
+    assertIndexExpression(
+      findNode.index('..[1]'),
+      readElement: indexElement,
+      writeElement: null,
+      type: 'bool',
+    );
+
+    assertType(findNode.cascade('a?'), 'A?');
   }
 
   test_read_nullable() async {
@@ -392,6 +401,36 @@
     );
   }
 
+  test_write_cascade_nullShorting() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  void operator[]=(int index, A a) {}
+}
+
+main(A? a) {
+  a?..[0] = a..[1] = a;
+}
+''');
+
+    var indexEqElement = findElement.method('[]=');
+
+    assertIndexExpression(
+      findNode.index('..[0]'),
+      readElement: null,
+      writeElement: indexEqElement,
+      type: null,
+    );
+
+    assertIndexExpression(
+      findNode.index('..[1]'),
+      readElement: null,
+      writeElement: indexEqElement,
+      type: null,
+    );
+
+    assertType(findNode.cascade('a?'), 'A?');
+  }
+
   test_write_nullable() async {
     await assertNoErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 17fa5b2..9e13317 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -1765,6 +1765,95 @@
     );
   }
 
+  test_hasReceiver_interfaceQ_nullShorting() async {
+    await assertNoErrorsInCode(r'''
+class C {
+  C foo() => throw 0;
+  C bar() => throw 0;
+}
+
+void testShort(C? c) {
+  c?.foo().bar();
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('c?.foo()'),
+      element: findElement.method('foo'),
+      typeArgumentTypes: [],
+      invokeType: 'C Function()',
+      type: 'C',
+    );
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('bar();'),
+      element: findElement.method('bar'),
+      typeArgumentTypes: [],
+      invokeType: 'C Function()',
+      type: 'C?',
+    );
+  }
+
+  test_nullShorting_cascade_firstMethodInvocation() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int foo() => 0;
+  int bar() => 0;
+}
+
+main(A? a) {
+  a?..foo()..bar();
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('..foo()'),
+      element: findElement.method('foo'),
+      typeArgumentTypes: [],
+      invokeType: 'int Function()',
+      type: 'int',
+    );
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('..bar()'),
+      element: findElement.method('bar'),
+      typeArgumentTypes: [],
+      invokeType: 'int Function()',
+      type: 'int',
+    );
+
+    assertType(findNode.cascade('a?'), 'A?');
+  }
+
+  test_nullShorting_cascade_firstPropertyAccess() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int get foo => 0;
+  int bar() => 0;
+}
+
+main(A? a) {
+  a?..foo..bar();
+}
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('..foo'),
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('..bar()'),
+      element: findElement.method('bar'),
+      typeArgumentTypes: [],
+      invokeType: 'int Function()',
+      type: 'int',
+    );
+
+    assertType(findNode.cascade('a?'), 'A?');
+  }
+
   test_hasReceiver_interfaceTypeQ_defined() async {
     await assertErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
index 566e341..e80dec7 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -119,6 +119,24 @@
     assertType(findNode.simple('x; // ref'), 'Object');
   }
 
+  test_inc_nullShorting() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int foo = 0;
+}
+
+f(A? a) {
+  a?.foo++;
+}
+''');
+
+    assertPostfixExpression(
+      findNode.postfix('foo++'),
+      element: numElement.getMethod('+'),
+      type: 'int?',
+    );
+  }
+
   test_nullCheck() async {
     await assertNoErrorsInCode(r'''
 f(int? x) {
@@ -141,6 +159,31 @@
 ''');
   }
 
+  test_nullCheck_indexExpression() async {
+    await assertNoErrorsInCode(r'''
+main(Map<String, int> a) {
+  int v = a['foo']!;
+  v;
+}
+''');
+
+    assertIndexExpression(
+      findNode.index('a['),
+      readElement: elementMatcher(
+        mapElement.getMethod('[]'),
+        substitution: {'K': 'String', 'V': 'int'},
+      ),
+      writeElement: null,
+      type: 'int?',
+    );
+
+    assertPostfixExpression(
+      findNode.postfix(']!'),
+      element: null,
+      type: 'int',
+    );
+  }
+
   test_nullCheck_null() async {
     await assertNoErrorsInCode('''
 main(Null x) {
diff --git a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
index 2b57c92..1ca28c5 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
@@ -207,4 +207,22 @@
 
     assertType(findNode.simple('x;'), 'A');
   }
+
+  test_plusPlus_nullShorting() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int foo = 0;
+}
+
+f(A? a) {
+  ++a?.foo;
+}
+''');
+
+    assertPrefixExpression(
+      findNode.prefix('++a'),
+      element: numElement.getMethod('+'),
+      type: 'int?',
+    );
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
index 0f92987..9bceab5 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -67,4 +67,31 @@
     assertElement(identifier, findElement.getter('a'));
     assertType(identifier, 'A?');
   }
+
+  test_nullShorting_cascade() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  int get foo => 0;
+  int get bar => 0;
+}
+
+main(A? a) {
+  a?..foo..bar;
+}
+''');
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('..foo'),
+      element: findElement.getter('foo'),
+      type: 'int',
+    );
+
+    assertPropertyAccess2(
+      findNode.propertyAccess('..bar'),
+      element: findElement.getter('bar'),
+      type: 'int',
+    );
+
+    assertType(findNode.cascade('a?'), 'A?');
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 0a7b1c4..d851422 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -535,6 +535,15 @@
     assertType(access, expectedType);
   }
 
+  void assertPropertyAccess2(
+    PropertyAccess node, {
+    @required Object element,
+    @required String type,
+  }) {
+    assertElement(node.propertyName.staticElement, element);
+    assertType(node.staticType, type);
+  }
+
   void assertSimpleIdentifier(
     SimpleIdentifier node, {
     @required Object element,
diff --git a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
index 0409d70..60527d0 100644
--- a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
@@ -166,7 +166,7 @@
   test_fromEnvironment_assertInitializer() async {
     await assertNoErrorsInCode('''
 class A {
-  const A(int x) : assert(x > 5);
+  const A(int x) : assert(x >= 0);
 }
 
 main() {
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_null_aware_operator_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_null_aware_operator_test.dart
index 2b84cb3..4e2bdb7 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_null_aware_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_null_aware_operator_test.dart
@@ -71,6 +71,7 @@
 import 'a.dart';
 
 f() {
+  x?[0];
   x?.[0];
   x?..[0];
 }
@@ -80,18 +81,21 @@
   test_index_nonNullable() async {
     await assertErrorsInCode('''
 f(List<int> x) {
+  x?[0];
   x?.[0];
   x?..[0];
 }
 ''', [
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 20, 3),
-      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 30, 3),
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 20, 2),
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 29, 3),
+      error(StaticWarningCode.INVALID_NULL_AWARE_OPERATOR, 39, 3),
     ]);
   }
 
   test_index_nullable() async {
     await assertNoErrorsInCode('''
 f(List<int>? x) {
+  x?[0];
   x?.[0];
   x?..[0];
 }
diff --git a/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
new file mode 100644
index 0000000..069da67
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. 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(NoDefaultSuperConstructorTest);
+  });
+}
+
+@reflectiveTest
+class NoDefaultSuperConstructorTest extends DriverResolutionTest {
+  test_explicitDefaultSuperConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A();
+}
+class B extends A {
+  B() {}
+}
+''');
+  }
+
+  test_implicitDefaultSuperConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A {
+}
+class B extends A {
+  B() {}
+}
+''');
+  }
+
+  test_missingDefaultSuperConstructor_explicitConstructor() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(p);
+}
+class B extends A {
+  B() {}
+}
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT, 42, 1),
+    ]);
+  }
+
+  test_missingDefaultSuperConstructor_externalConstructor() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(p);
+}
+class B extends A {
+  external B();
+}
+''');
+  }
+
+  test_missingDefaultSuperConstructor_implicitConstructor() async {
+    await assertErrorsInCode(r'''
+class A {
+  A(p);
+}
+class B extends A {
+}
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 26, 1),
+    ]);
+  }
+
+  test_missingDefaultSuperConstructor_onlyNamedSuperConstructor() async {
+    await assertErrorsInCode(r'''
+class A { A.named() {} }
+class B extends A {}
+''', [
+      error(CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_IMPLICIT, 31, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
index d19a13c..2b69d39 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
@@ -19,6 +19,15 @@
 
 @reflectiveTest
 class NonConstantSetElementTest extends DriverResolutionTest {
+  test_const_forElement() async {
+    await assertErrorsInCode(r'''
+const Set set = {};
+var v = const {for (final x in set) x};
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 35, 22),
+    ]);
+  }
+
   test_const_ifElement_thenElseFalse_finalElse() async {
     await assertErrorsInCode(
         '''
diff --git a/pkg/analyzer/test/src/diagnostics/non_generative_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/non_generative_constructor_test.dart
index 80d6611..fd89b22 100644
--- a/pkg/analyzer/test/src/diagnostics/non_generative_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_generative_constructor_test.dart
@@ -40,6 +40,18 @@
 ''');
   }
 
+  test_generative_external() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A.named() {}
+  factory A() => throw 0;
+}
+class B extends A {
+  external B();
+}
+''');
+  }
+
   test_implicit() async {
     await assertErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/private_collision_in_mixin_application_test.dart b/pkg/analyzer/test/src/diagnostics/private_collision_in_mixin_application_test.dart
index 3aede55..689ae85 100644
--- a/pkg/analyzer/test/src/diagnostics/private_collision_in_mixin_application_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/private_collision_in_mixin_application_test.dart
@@ -71,6 +71,42 @@
     ]);
   }
 
+  test_class_staticAndInstanceElement() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  static void _foo() {}
+}
+
+class B {
+  void _foo() {}
+}
+''');
+
+    await assertNoErrorsInCode('''
+import 'a.dart';
+
+class C extends Object with A, B {}
+''');
+  }
+
+  test_class_staticElements() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  static void _foo() {}
+}
+
+class B {
+  static void _foo() {}
+}
+''');
+
+    await assertNoErrorsInCode('''
+import 'a.dart';
+
+class C extends Object with A, B {}
+''');
+  }
+
   test_class_superclassAndMixin_getter2() async {
     newFile('/test/lib/a.dart', content: r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
index c21f0a5..2946765 100644
--- a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
@@ -48,8 +48,8 @@
       error(StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, 0, 3),
       error(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 25, 1,
           contextMessages: [
-            message('/sdk/lib/core/core.dart', 2090, 3),
-            message('/sdk/lib/core/core.dart', 2090, 3)
+            message('/sdk/lib/core/core.dart', 2150, 3),
+            message('/sdk/lib/core/core.dart', 2150, 3)
           ]),
     ]);
   }
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 1d56343..523f762 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -289,6 +289,7 @@
 import 'new_with_non_type_test.dart' as new_with_non_type;
 import 'new_with_undefined_constructor_test.dart'
     as new_with_undefined_constructor;
+import 'no_default_super_constructor_test.dart' as no_default_super_constructor;
 import 'non_abstract_class_inherits_abstract_member_test.dart'
     as non_abstract_class_inherits_abstract_member;
 import 'non_bool_condition_test.dart' as non_bool_condition;
@@ -697,6 +698,7 @@
     must_call_super.main();
     new_with_non_type.main();
     new_with_undefined_constructor.main();
+    no_default_super_constructor.main();
     non_abstract_class_inherits_abstract_member.main();
     non_bool_condition.main();
     non_bool_negation_expression.main();
diff --git a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
index 1e73007d..94e0f48 100644
--- a/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
+++ b/pkg/analyzer/test/src/lint/linter/linter_context_impl_test.dart
@@ -259,6 +259,15 @@
     expect(result.value, isNull);
   }
 
+  test_hasError_mapLiteral_forElement() async {
+    await resolve('''
+var x = const {for (var i = 0; i < 4; i++) i: 0};
+''');
+    var result = _evaluateX();
+    expect(result.errors, isNotEmpty);
+    expect(result.value, isNull);
+  }
+
   test_hasError_methodInvocation() async {
     await resolve('''
 var x = 42.abs();
@@ -268,6 +277,15 @@
     expect(result.value, isNull);
   }
 
+  test_hasError_setLiteral_forElement() async {
+    await resolve('''
+var x = const {for (var i = 0; i < 4; i++) i};
+''');
+    var result = _evaluateX();
+    expect(result.errors, isNotEmpty);
+    expect(result.value, isNull);
+  }
+
   test_hasValue_binaryExpression() async {
     await resolve('''
 var x = 1 + 2;
diff --git a/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart b/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart
index 384f2dc..6d415cf 100644
--- a/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_text_printer_integration_test.dart
@@ -7,8 +7,8 @@
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:test/test.dart';
 
-import '../dart/ast/parse_base.dart';
 import '../../utils/package_root.dart' as package_root;
+import '../dart/ast/parse_base.dart';
 import 'ast_text_printer_test.dart';
 
 main() {
@@ -34,20 +34,6 @@
     test(relPath, () {
       var code = file.readAsStringSync();
       assertParseCodeAndPrintAst(base, code, mightHasParseErrors: true);
-    }, skip: tempSkipped(file));
+    });
   }
 }
-
-dynamic tempSkipped(File file) {
-  const String prefix = "front_end/parser_testcases";
-  String uriString = file.uri.toString();
-  if (uriString.endsWith("$prefix/nnbd/issue_40267_case_02.dart") ||
-      uriString.endsWith("$prefix/nnbd/issue_40267_case_05.dart") ||
-      uriString.endsWith("$prefix/nnbd/issue_40267_lookup_plus_plus.dart") ||
-      uriString.endsWith("$prefix/nnbd/issue_40267_lookup_plus.dart") ||
-      uriString.endsWith("$prefix/nnbd/issue_40267_plus_plus_lookup.dart")) {
-    return "Temporarily skipped because of "
-        "https://dart-review.googlesource.com/c/sdk/+/135903";
-  }
-  return false;
-}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 83ce20d..6501af7 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -1305,7 +1305,8 @@
     }
 
     for (var import in resolvedUnit.libraryElement.imports) {
-      if (import.importedLibrary.source.uri == uri) {
+      var importedLibrary = import.importedLibrary;
+      if (importedLibrary != null && importedLibrary.source.uri == uri) {
         return ImportLibraryElementResultImpl(import.prefix?.name);
       }
     }
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
index 3e3a002..6f04e0f 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
@@ -70,6 +70,19 @@
     );
   }
 
+  Future<void> test_withoutPrefix_hasInvalidImport() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import ':[invalidUri]';
+import 'package:test/a.dart';
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+    );
+  }
+
   Future<void> test_withoutPrefix_referencedNames_sameElements() async {
     newFile('/home/test/lib/a.dart', content: r'''
 class A {}
diff --git a/pkg/async_helper/lib/async_minitest.dart b/pkg/async_helper/lib/async_minitest.dart
index 3f1b6d8..cf60812 100644
--- a/pkg/async_helper/lib/async_minitest.dart
+++ b/pkg/async_helper/lib/async_minitest.dart
@@ -58,7 +58,7 @@
   _popName(oldName);
 }
 
-void expect(dynamic value, dynamic matcher, {String reason}) {
+void expect(dynamic value, dynamic matcher, {String reason = ""}) {
   Matcher m;
   if (matcher is _Matcher) {
     m = matcher.call;
@@ -195,6 +195,14 @@
       Expect.isTrue(fn(v), description);
     };
 
+Matcher anyOf(List<String> expected) => (dynamic actual) {
+      for (var string in expected) {
+        if (actual == string) return;
+      }
+
+      Expect.fail("Expected $actual to be one of $expected.");
+    };
+
 void isTrue(dynamic v) {
   Expect.isTrue(v);
 }
@@ -207,10 +215,6 @@
   Expect.isNull(o);
 }
 
-bool isStateError(dynamic o) {
-  Expect.type<StateError>(o);
-}
-
 void _checkThrow<T>(dynamic v, void onError(error)) {
   if (v is Future) {
     asyncStart();
@@ -292,7 +296,11 @@
   _checkThrow<ArgumentError>(v, (_) {});
 }
 
-String fail(String message) {
+void throwsStateError(dynamic v) {
+  _checkThrow<StateError>(v, (_) {});
+}
+
+void fail(String message) {
   Expect.fail("$message");
 }
 
@@ -302,7 +310,9 @@
 bool _initializedTestNameCallback = false;
 
 /// The current combined name of the nesting [group] or [test].
-String _currentName = null;
+// TODO(rnystrom): Type this "String?" when this library does not need to be
+// NNBD agnostic.
+dynamic _currentName = null;
 
 String _pushName(String newName) {
   // Look up the current test name from the zone created for the test.
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index 4f3613f..0fab620 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -1167,22 +1167,19 @@
       if (line == null) exit(0);
       List<String> testArgs = splitLine(line, windows: Platform.isWindows);
 
-      // Merge experiment flags from the batch and the test arguments.
+      // Ignore experiment flags given to the batch runner.
       //
       // Batch arguments are provided when the batch compiler is created, and
       // contain flags that are generally enabled for all tests. Tests
       // may have more specific flags that could conflict with the batch flags.
-      // For example, the compiler might be setup to run the non-nullable
+      // For example, the batch runner might be setup to run the non-nullable
       // experiment, but the test may enable more experiments.
       //
       // At this time we are only aware of these kind of conflicts with
-      // experiment flags, so we handle those directly. We know that if the
-      // batch compiler has an experiment flag, the test itself will
-      // have it too (either identical or more accurate when the test requires
-      // additional experiments).
-      bool hasExperiment(List<String> list) =>
-          list.any((a) => a.startsWith('--enable-experiment'));
-      assert(!hasExperiment(batchArguments) || hasExperiment(testArgs));
+      // experiment flags, so we handle those directly. Currently the test
+      // runner passes experiment flags on both the batch runner and the test
+      // itself, so it is safe to ignore the flag that was given to the batch
+      // runner.
       List<String> args = [
         for (var arg in batchArguments)
           if (!arg.startsWith('--enable-experiment')) arg,
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 34edd57..644e4cb 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -98,8 +98,7 @@
   RETHROW_OUTSIDE_CATCH,
   RETURN_IN_GENERATIVE_CONSTRUCTOR,
   RETURN_IN_GENERATOR,
-  RUNTIME_TYPE_TO_STRING_OBJECT,
-  RUNTIME_TYPE_TO_STRING_SUBTYPE,
+  RUNTIME_TYPE_TO_STRING,
   STRING_EXPECTED,
   UNDEFINED_GETTER,
   UNDEFINED_INSTANCE_GETTER_BUT_SETTER,
@@ -613,25 +612,15 @@
           "more code and prevents the compiler from doing some optimizations.",
           howToFix: "Consider removing this 'noSuchMethod' implementation."),
 
-      MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT: const MessageTemplate(
-          MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT,
+      MessageKind.RUNTIME_TYPE_TO_STRING: const MessageTemplate(
+          MessageKind.RUNTIME_TYPE_TO_STRING,
           "Using '.runtimeType.toString()' causes the compiler to generate "
-          "more code because it needs to preserve type arguments on all "
+          "more code because it needs to preserve type arguments on "
           "generic classes, even if they are not necessary elsewhere.",
           howToFix: "If used only for debugging, consider using option "
               "${Flags.laxRuntimeTypeToString} to reduce the code size "
               "impact."),
 
-      MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE: const MessageTemplate(
-          MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE,
-          "Using '.runtimeType.toString()' here causes the compiler to "
-          "generate more code because it needs to preserve type arguments on "
-          "all generic subtypes of '#{receiverType}', even if they are not "
-          "necessary elsewhere.",
-          howToFix: "If used only for debugging, consider using option "
-              "${Flags.laxRuntimeTypeToString} to reduce the code size "
-              "impact."),
-
       MessageKind.NON_NATIVE_EXTERNAL: const MessageTemplate(
           MessageKind.NON_NATIVE_EXTERNAL,
           "Only external js-interop functions are supported.",
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index a7a5404..6e0ebab 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -130,7 +130,7 @@
   @override
   String toString() => toStructuredText();
 
-  String toStructuredText({bool printLegacyStars = false}) =>
+  String toStructuredText({bool printLegacyStars = true}) =>
       _DartTypeToStringVisitor(printLegacyStars).run(this);
 }
 
@@ -1089,50 +1089,21 @@
       return _mapped(type, type);
     }
 
-    List<FunctionTypeVariable> normalizableVariables = [];
-    for (int i = 0; i < newTypeVariables.length; i++) {
-      FunctionTypeVariable t = newTypeVariables[i];
-      if (identical(t, type.typeVariables[i])) continue;
-      DartType bound = t.bound;
-      if (bound is NeverType) {
-        normalizableVariables.add(t);
-      }
-    }
-
     return _mapped(
         type,
-        dartTypes.subst(
-            List<DartType>.filled(
-                normalizableVariables.length, dartTypes.neverType()),
-            normalizableVariables,
-            dartTypes.functionType(
-                newReturnType,
-                newParameterTypes,
-                newOptionalParameterTypes,
-                type.namedParameters,
-                newNamedParameterTypes,
-                newTypeVariables)));
+        dartTypes.functionType(
+            newReturnType,
+            newParameterTypes,
+            newOptionalParameterTypes,
+            type.namedParameters,
+            newNamedParameterTypes,
+            newTypeVariables));
   }
 
   List<FunctionTypeVariable> _handleFunctionTypeVariables(
       List<FunctionTypeVariable> variables, A argument) {
     if (variables.isEmpty) return variables;
 
-    // Are the function type variables being substituted (i.e. generic function
-    // type instantiation).
-    // TODO(sra): This should happen only from via
-    // [FunctionType.instantiate]. Perhaps it would be handled better there.
-    int count = 0;
-    for (int i = 0; i < variables.length; i++) {
-      FunctionTypeVariable variable = variables[i];
-      if (variable !=
-          substituteFunctionTypeVariable(variable, argument, false)) {
-        count++;
-      }
-    }
-    if (count == variables.length) return const <FunctionTypeVariable>[];
-    assert(count == 0, 'Generic function type instantiation is all-or-none');
-
     // Type variables may depend on each other. Consider:
     //
     //     <A extends List<B>,
@@ -1707,13 +1678,11 @@
   DartType interfaceType(ClassEntity element, List<DartType> typeArguments) =>
       InterfaceType._(element, typeArguments);
 
-  // Since all [TypeVariableType] bounds come from the CFE, we assume that no
-  // bound will ever be `Never` (or else the CFE would have already normalized
-  // the type variable to `Never`). Therefore, we can skip normalization.
+  // TODO(fishythefish): Normalize `T extends Never` to `Never`.
   TypeVariableType typeVariableType(TypeVariableEntity element) =>
       TypeVariableType._(element);
 
-  // We normalize when we substitute function types.
+  // See [functionType] for normalization.
   DartType functionTypeVariable(int index) => FunctionTypeVariable._(index);
 
   DartType neverType() => const NeverType._();
@@ -1727,14 +1696,29 @@
   AnyType anyType() => const AnyType._();
 
   FunctionType functionType(
-          DartType returnType,
-          List<DartType> parameterTypes,
-          List<DartType> optionalParameterTypes,
-          List<String> namedParameters,
-          List<DartType> namedParameterTypes,
-          List<FunctionTypeVariable> typeVariables) =>
-      FunctionType._(returnType, parameterTypes, optionalParameterTypes,
-          namedParameters, namedParameterTypes, typeVariables);
+      DartType returnType,
+      List<DartType> parameterTypes,
+      List<DartType> optionalParameterTypes,
+      List<String> namedParameters,
+      List<DartType> namedParameterTypes,
+      List<FunctionTypeVariable> typeVariables) {
+    FunctionType type = FunctionType._(
+        returnType,
+        parameterTypes,
+        optionalParameterTypes,
+        namedParameters,
+        namedParameterTypes,
+        typeVariables);
+    List<FunctionTypeVariable> normalizableVariables = typeVariables
+        .where((FunctionTypeVariable t) => t.bound is NeverType)
+        .toList();
+    return normalizableVariables.isEmpty
+        ? type
+        : subst(
+            List<DartType>.filled(normalizableVariables.length, neverType()),
+            normalizableVariables,
+            type);
+  }
 
   DartType futureOrType(DartType typeArgument) {
     DartType result;
@@ -1770,7 +1754,17 @@
   }
 
   DartType instantiate(FunctionType t, List<DartType> arguments) {
-    return subst(arguments, t.typeVariables, t);
+    assert(arguments.length == t.typeVariables.length,
+        'Generic function type instantiation is all-or-none');
+    DartType _subst(DartType type) => subst(arguments, t.typeVariables, type);
+    DartType returnType = _subst(t.returnType);
+    List<DartType> parameterTypes = t.parameterTypes.map(_subst).toList();
+    List<DartType> optionalParameterTypes =
+        t.optionalParameterTypes.map(_subst).toList();
+    List<DartType> namedParameterTypes =
+        t.namedParameterTypes.map(_subst).toList();
+    return functionType(returnType, parameterTypes, optionalParameterTypes,
+        t.namedParameters, namedParameterTypes, const []);
   }
 
   /// Returns `true` if every type argument of [t] is a top type.
diff --git a/pkg/compiler/lib/src/ir/constants.dart b/pkg/compiler/lib/src/ir/constants.dart
index 959ee45..768b8e1 100644
--- a/pkg/compiler/lib/src/ir/constants.dart
+++ b/pkg/compiler/lib/src/ir/constants.dart
@@ -81,11 +81,6 @@
 
   ErrorReporter(this._reportError);
 
-  // TODO(johnniwinther,dmitryas): Remove the getter when the NNBD error
-  // reporting is enabled by default.
-  @override
-  bool get performNnbdChecks => false;
-
   @override
   void reportInvalidExpression(ir.InvalidExpression node) {
     // Ignore.
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index 7893f77..c3afdfa 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -97,8 +97,6 @@
       // variables.
       return _dartTypes.dynamicType();
     }
-    // We assume the incoming type is already normalized, so the bound is not
-    // `Never`. Attempting to check the bound here will overflow the stack.
     return _convertNullability(
         _dartTypes.typeVariableType(elementMap.getTypeVariable(node.parameter)),
         node.nullability);
diff --git a/pkg/compiler/lib/src/js_backend/resolution_listener.dart b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
index f9244e9..9c2eed4 100644
--- a/pkg/compiler/lib/src/js_backend/resolution_listener.dart
+++ b/pkg/compiler/lib/src/js_backend/resolution_listener.dart
@@ -270,7 +270,7 @@
           ..addAll(functionType.optionalParameterTypes)
           ..addAll(functionType.namedParameterTypes);
         for (var type in allParameterTypes) {
-          if (type is FunctionType) {
+          if (type.withoutNullability is FunctionType) {
             var closureConverter = _commonElements.closureConverter;
             worldImpact.registerStaticUse(
                 new StaticUse.implicitInvoke(closureConverter));
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index f0f376a..8927b66 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -305,6 +305,7 @@
 
                 assert(substitution != null);
                 for (DartType argument in substitution.arguments) {
+                  argument = argument.withoutNullability;
                   if (argument is InterfaceType) {
                     computeChecks(argument.element);
                   }
@@ -328,6 +329,7 @@
 
               assert(substitution != null);
               for (DartType argument in substitution.arguments) {
+                argument = argument.withoutNullability;
                 if (argument is InterfaceType) {
                   computeChecks(argument.element);
                 }
@@ -730,6 +732,7 @@
     bool isFunctionChecked = false;
 
     void processCheckedType(DartType t) {
+      t = t.withoutNullability;
       if (t is FunctionType) {
         checkedFunctionTypes.add(t);
       } else if (t is InterfaceType) {
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index 7b3745f..62a9699f 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -1107,9 +1107,7 @@
     void checkFunction(Entity function, FunctionType type) {
       for (FunctionTypeVariable typeVariable in type.typeVariables) {
         DartType bound = typeVariable.bound;
-        if (bound is! DynamicType &&
-            bound is! VoidType &&
-            bound != closedWorld.commonElements.objectType) {
+        if (!closedWorld.dartTypes.isTopType(bound)) {
           potentiallyNeedTypeArguments(function);
           break;
         }
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index 5d22abe..4187979 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -619,9 +619,7 @@
               .map<TypeVariableType>((ir.TypeParameter typeParameter) {
             return elementMap
                 .getDartType(new ir.TypeParameterType(
-                    typeParameter,
-                    ir.TypeParameterType.computeNullabilityFromBound(
-                        typeParameter)))
+                    typeParameter, ir.Nullability.nonNullable))
                 .withoutNullability;
           }).toList();
         }
@@ -781,8 +779,8 @@
     return typeParameters
         .map<TypeVariableType>((ir.TypeParameter typeParameter) {
       return elementMap
-          .getDartType(new ir.TypeParameterType(typeParameter,
-              ir.TypeParameterType.computeNullabilityFromBound(typeParameter)))
+          .getDartType(new ir.TypeParameterType(
+              typeParameter, ir.Nullability.nonNullable))
           .withoutNullability;
     }).toList();
   }
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 1c49912..ce1b97f 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -1233,14 +1233,17 @@
           isExternal: isExternal, isConst: node.isConst);
     } else if (node is ir.Procedure) {
       functionNode = node.function;
-      bool isFromEnvironment = isExternal &&
-          name.text == 'fromEnvironment' &&
-          const ['int', 'bool', 'String'].contains(enclosingClass.name);
+      // TODO(sigmund): Check more strictly than just the class name.
+      bool isEnvironmentConstructor = isExternal &&
+          (name.text == 'fromEnvironment' &&
+                  const ['int', 'bool', 'String']
+                      .contains(enclosingClass.name) ||
+              name.text == 'hasEnvironment' && enclosingClass.name == 'bool');
       constructor = createFactoryConstructor(enclosingClass, name,
           getParameterStructure(functionNode, includeTypeParameters: false),
           isExternal: isExternal,
           isConst: node.isConst,
-          isFromEnvironmentConstructor: isFromEnvironment);
+          isFromEnvironmentConstructor: isEnvironmentConstructor);
     } else {
       // TODO(johnniwinther): Convert `node.location` to a [SourceSpan].
       throw failedAt(
@@ -1566,6 +1569,8 @@
         isExternal: isExternal, isConst: isConst);
   }
 
+  // TODO(dart2js-team): Rename isFromEnvironmentConstructor to
+  // isEnvironmentConstructor: Here, and everywhere in the compiler.
   IndexedConstructor createFactoryConstructor(ClassEntity enclosingClass,
       Name name, ParameterStructure parameterStructure,
       {bool isExternal, bool isConst, bool isFromEnvironmentConstructor}) {
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 669f45e..517787b 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -764,9 +764,7 @@
               .map<TypeVariableType>((ir.TypeParameter typeParameter) {
             return elementMap
                 .getDartType(new ir.TypeParameterType(
-                    typeParameter,
-                    ir.TypeParameterType.computeNullabilityFromBound(
-                        typeParameter)))
+                    typeParameter, ir.Nullability.nonNullable))
                 .withoutNullability;
           }).toList();
         }
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index 5d0a9bf..21e7bb6 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -666,15 +666,8 @@
       switch (kind) {
         case RuntimeTypeUseKind.string:
           if (!_options.laxRuntimeTypeToString) {
-            if (receiverDartType == commonElements.objectType) {
-              reporter.reportHintMessage(computeSourceSpanFromTreeNode(node),
-                  MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT);
-            } else {
-              reporter.reportHintMessage(
-                  computeSourceSpanFromTreeNode(node),
-                  MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE,
-                  {'receiverType': '${receiverDartType}.'});
-            }
+            reporter.reportHintMessage(computeSourceSpanFromTreeNode(node),
+                MessageKind.RUNTIME_TYPE_TO_STRING);
           }
           break;
         case RuntimeTypeUseKind.equals:
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 21fc93c..d628cc7 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -781,12 +781,12 @@
   /// Models the behavior of having instances of [type] escape from Dart code
   /// into native code.
   void _escape(DartType type, bool isJsInterop) {
+    type = type.withoutNullability;
     if (type is FunctionType) {
-      FunctionType functionType = type;
       // A function might be called from native code, passing us novel
       // parameters.
-      _escape(functionType.returnType, isJsInterop);
-      for (DartType parameter in functionType.parameterTypes) {
+      _escape(type.returnType, isJsInterop);
+      for (DartType parameter in type.parameterTypes) {
         _capture(parameter, isJsInterop);
       }
     }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 534cce1..f3c8578 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -1508,16 +1508,11 @@
       ir.FunctionNode function = getFunctionNode(_elementMap, method);
       for (ir.TypeParameter typeParameter in function.typeParameters) {
         Local local = _localsMap.getLocalTypeVariable(
-            new ir.TypeParameterType(
-                typeParameter,
-                ir.TypeParameterType.computeNullabilityFromBound(
-                    typeParameter)),
+            new ir.TypeParameterType(typeParameter, ir.Nullability.nonNullable),
             _elementMap);
         HInstruction newParameter = localsHandler.directLocals[local];
         DartType bound = _getDartTypeIfValid(typeParameter.bound);
-        if (bound is! DynamicType &&
-            bound is! VoidType &&
-            bound != _commonElements.objectType) {
+        if (!dartTypes.isTopType(bound)) {
           registry.registerTypeUse(TypeUse.typeVariableBoundCheck(bound));
           if (options.useNewRti) {
             // TODO(sigmund): method name here is not minified, should it be?
@@ -5041,6 +5036,7 @@
 
     // The allocation effects include the declared type if it is native (which
     // includes js interop types).
+    type = type.withoutNullability;
     if (type is InterfaceType && _nativeData.isNativeClass(type.element)) {
       nativeBehavior.typesInstantiated.add(type);
     }
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index cddfa66..695aca3 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -1410,9 +1410,7 @@
     // available.
     assert(type is! TypeVariableType);
     assert(closedWorld.dartTypes.treatAsRawType(type) || type is FunctionType);
-    if (type is DynamicType) return this;
-    if (type is VoidType) return this;
-    if (type == closedWorld.commonElements.objectType) return this;
+    if (closedWorld.dartTypes.isTopType(type)) return this;
     if (type is FunctionType || type is FutureOrType) {
       return new HTypeConversion(type, kind,
           closedWorld.abstractValueDomain.dynamicType, this, sourceInformation);
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index 89bec4e..f7269a3 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -52,9 +52,8 @@
   AbstractValue trustTypeMask(DartType type) {
     if (type == null) return null;
     type = builder.localsHandler.substInContext(type);
-    if (type is DynamicType) return null;
+    if (_closedWorld.dartTypes.isTopType(type)) return null;
     if (type is! InterfaceType) return null;
-    if (type == _closedWorld.commonElements.objectType) return null;
     // The type element is either a class or the void element.
     ClassEntity element = (type as InterfaceType).element;
     return _abstractValueDomain.createNullableSubtype(element);
@@ -466,9 +465,7 @@
   HInstruction buildAsCheck(HInstruction original, DartType type,
       {bool isTypeError, SourceInformation sourceInformation}) {
     if (type == null) return original;
-    if (type is DynamicType) return original;
-    if (type is VoidType) return original;
-    if (type == _closedWorld.commonElements.objectType) return original;
+    if (_closedWorld.dartTypes.isTopType(type)) return original;
 
     HInstruction reifiedType = analyzeTypeArgumentNewRti(
         type, builder.sourceElement,
diff --git a/pkg/compiler/lib/src/tracer.dart b/pkg/compiler/lib/src/tracer.dart
index f7add43..e42352b 100644
--- a/pkg/compiler/lib/src/tracer.dart
+++ b/pkg/compiler/lib/src/tracer.dart
@@ -12,9 +12,9 @@
 
 /// If non-null, we only trace methods whose name match the regexp defined by
 /// the given pattern.
-String get TRACE_FILTER_PATTERN => TRACE_FILTER_PATTERN_FROM_ENVIRONMENT == ''
-    ? TRACE_FILTER_PATTERN_FOR_TEST
-    : null;
+String get TRACE_FILTER_PATTERN => TRACE_FILTER_PATTERN_FROM_ENVIRONMENT != ''
+    ? TRACE_FILTER_PATTERN_FROM_ENVIRONMENT
+    : TRACE_FILTER_PATTERN_FOR_TEST;
 
 const String TRACE_FILTER_PATTERN_FROM_ENVIRONMENT =
     // TODO(sigmund): remove `?? ''` once #40678 is backported.
diff --git a/pkg/dartdev/lib/src/commands/test.dart b/pkg/dartdev/lib/src/commands/test.dart
index da85674..a9ffa42 100644
--- a/pkg/dartdev/lib/src/commands/test.dart
+++ b/pkg/dartdev/lib/src/commands/test.dart
@@ -50,7 +50,7 @@
 In order to run tests, you need to add a dependency on package:test in your
 pubspec.yaml file:
 
-${ansi.emphasized('dev_dependencies:\n  test: ^1.0.0')}
+${ansi.emphasized('dev_dependencies:\n  test: any')}
 
 See https://pub.dev/packages/test#-installing-tab- for more information on
 adding package:test, and https://dart.dev/guides/testing for general
diff --git a/pkg/dartdev/test/commands/migrate_test.dart b/pkg/dartdev/test/commands/migrate_test.dart
index 513ddc3..a3b0c79 100644
--- a/pkg/dartdev/test/commands/migrate_test.dart
+++ b/pkg/dartdev/test/commands/migrate_test.dart
@@ -7,6 +7,10 @@
 
 import '../utils.dart';
 
+// TODO(jcollins-g): Set to true and/or remove when when NNBD is enabled in the
+//  SDK running this test.
+bool _nnbdIsEnabled = false;
+
 void main() {
   group('migrate', defineMigrateTests);
 }
@@ -30,24 +34,34 @@
 
   test('directory implicit', () {
     p = project(mainSrc: 'int get foo => 1;\n');
-    var result =
-        p.runSync('migrate', ['--no-web-preview'], workingDir: p.dirPath);
-    expect(result.exitCode, 0);
-    expect(result.stderr, isEmpty);
+    var result = p.runSync(
+        'migrate',
+        [
+          '--no-web-preview',
+          '--server-path=${p.absolutePathToAnalysisServerFile}'
+        ],
+        workingDir: p.dirPath);
+    expect(result.exitCode, _nnbdIsEnabled ? 0 : 2);
+    expect(result.stderr, _nnbdIsEnabled ? isEmpty : isNotEmpty);
     expect(result.stdout, contains('Generating migration suggestions'));
   });
 
   test('directory explicit', () {
     p = project(mainSrc: 'int get foo => 1;\n');
-    var result = p.runSync('migrate', ['--no-web-preview', p.dirPath]);
-    expect(result.exitCode, 0);
-    expect(result.stderr, isEmpty);
+    var result = p.runSync('migrate', [
+      '--no-web-preview',
+      '--server-path=${p.absolutePathToAnalysisServerFile}',
+      p.dirPath
+    ]);
+    expect(result.exitCode, _nnbdIsEnabled ? 0 : 2);
+    expect(result.stderr, _nnbdIsEnabled ? isEmpty : isNotEmpty);
     expect(result.stdout, contains('Generating migration suggestions'));
   });
 
   test('bad directory', () {
     p = project(mainSrc: 'int get foo => 1;\n');
-    var result = p.runSync('migrate', ['foo_bar_dir']);
+    var result = p.runSync('migrate',
+        ['--server-path=${p.absolutePathToAnalysisServerFile}', 'foo_bar_dir']);
     expect(result.exitCode, 64);
     expect(result.stderr,
         contains('not found; please provide a path to a package or directory'));
diff --git a/pkg/dartdev/test/commands/test_test.dart b/pkg/dartdev/test/commands/test_test.dart
index e1e9b5c..1b390ff 100644
--- a/pkg/dartdev/test/commands/test_test.dart
+++ b/pkg/dartdev/test/commands/test_test.dart
@@ -43,6 +43,12 @@
         'In order to run tests, you need to add a dependency on package:test',
       ),
     );
+    expect(
+      result.stdout,
+      contains(
+        'dev_dependencies:\n  test: any',
+      ),
+    );
   }, skip: 'https://github.com/dart-lang/sdk/issues/40854');
 
   test('has dependency', () {
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index f852731..2a354ea 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -63,18 +63,34 @@
     );
   }
 
-  /// The path relative from `Directory.current.path` to `dartdev.dart` is
-  /// different when executing these tests locally versus on the Dart
-  /// buildbots, this if-else captures this change and branches for each case.
-  String get absolutePathToDartdevFile {
-    var dartdevFilePathOnBots = path.absolute(path.join(
-        Directory.current.path, 'pkg', 'dartdev', 'bin', 'dartdev.dart'));
-    if (File(dartdevFilePathOnBots).existsSync()) {
-      return dartdevFilePathOnBots;
-    } else {
-      return path
-          .absolute(path.join(Directory.current.path, 'bin', 'dartdev.dart'));
+  String _sdkRootPath;
+
+  /// Return the root of the SDK.
+  String get sdkRootPath {
+    if (_sdkRootPath == null) {
+      // Assumes the script importing this one is somewhere under the SDK.
+      String current = path.canonicalize(Platform.script.toFilePath());
+      do {
+        String tryDir = path.dirname(current);
+        if (File(path.join(tryDir, 'pkg', 'dartdev', 'bin', 'dartdev.dart'))
+            .existsSync()) {
+          _sdkRootPath = tryDir;
+          return _sdkRootPath;
+        }
+        current = tryDir;
+      } while (path.dirname(current) != current);
+      throw StateError('can not find SDK repository root');
     }
+    return _sdkRootPath;
+  }
+
+  String get absolutePathToDartdevFile {
+    return path.join(sdkRootPath, 'pkg', 'dartdev', 'bin', 'dartdev.dart');
+  }
+
+  String get absolutePathToAnalysisServerFile {
+    return path.join(
+        sdkRootPath, 'pkg', 'analysis_server', 'bin', 'server.dart');
   }
 
   File findFile(String name) {
diff --git a/pkg/dartfix/lib/src/migrate/migrate.dart b/pkg/dartfix/lib/src/migrate/migrate.dart
index 621a03e..f833994 100644
--- a/pkg/dartfix/lib/src/migrate/migrate.dart
+++ b/pkg/dartfix/lib/src/migrate/migrate.dart
@@ -12,6 +12,7 @@
 import 'package:args/command_runner.dart';
 import 'package:cli_util/cli_logging.dart';
 import 'package:path/path.dart' as path;
+import 'package:nnbd_migration/src/messages.dart';
 
 import '../util.dart';
 import 'apply.dart';
@@ -430,6 +431,18 @@
   void onAnalysisErrors(AnalysisErrorsParams event) {
     _analysisErrorsController.add(event);
   }
+
+  @override
+  void onServerError(ServerErrorParams event) {
+    stderr.writeln('encountered error: ${event.message}');
+
+    for (String fatal in [migratedAlready, nnbdExperimentOff, sdkNnbdOff]) {
+      if (event.message.contains(fatal)) {
+        server.kill();
+        exit(2);
+      }
+    }
+  }
 }
 
 class _ServerListener with ServerListener {
diff --git a/pkg/dev_compiler/test/sourcemap/testing.json b/pkg/dev_compiler/test/sourcemap/testing.json
index 6048d69..03c2722 100644
--- a/pkg/dev_compiler/test/sourcemap/testing.json
+++ b/pkg/dev_compiler/test/sourcemap/testing.json
@@ -5,19 +5,6 @@
   "packages": "../../../../.packages",
   "suites": [
     {
-      "name": "sourcemaps_ddc",
-      "kind": "Chain",
-      "source": "sourcemaps_ddc_suite.dart",
-      "path": "testfiles",
-      "status": "sourcemaps_ddc.status",
-      "pattern": [
-        "\\.dart$",
-        "\\.unformatteddart$"
-      ],
-      "exclude": [
-      ]
-    },
-    {
       "name": "sourcemaps_ddk",
       "kind": "Chain",
       "source": "sourcemaps_ddk_suite.dart",
@@ -41,18 +28,6 @@
       ],
       "exclude": [
       ]
-    },
-    {
-      "name": "stacktrace_ddc",
-      "kind": "Chain",
-      "source": "stacktrace_ddc_suite.dart",
-      "path": "stacktrace_testfiles",
-      "status": "stacktrace_ddc.status",
-      "pattern": [
-        "\\.dart$"
-      ],
-      "exclude": [
-      ]
     }
   ]
 }
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index cb9e036..0e993bc 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -647,8 +647,7 @@
   }
 
   /// Checks that `Sub` is a subtype of `Super` at compile time and run time.
-  static bool subtype<Sub extends Super, Super>() {
-    List<Super> list = <Sub>[];
+  static void subtype<Sub extends Super, Super>() {
     _subtypeAtRuntime<Sub, Super>();
   }
 
@@ -657,14 +656,14 @@
   /// This is similar to [subtype] but without the `Sub extends Super` generic
   /// constraint, so a compiler is less likely to optimize away the `is` check
   /// because the types appear to be unrelated.
-  static bool _subtypeAtRuntime<Sub, Super>() {
+  static void _subtypeAtRuntime<Sub, Super>() {
     if (<Sub>[] is! List<Super>) {
       fail("$Sub is not a subtype of $Super");
     }
   }
 
   /// Checks that `Sub` is not a subtype of `Super` at run time.
-  static bool notSubtype<Sub, Super>() {
+  static void notSubtype<Sub, Super>() {
     if (<Sub>[] is List<Super>) {
       fail("$Sub is a subtype of $Super");
     }
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 07bb9a3..0ffeb41 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -226,10 +226,6 @@
   /// 'non-nullable' is enabled.
   NnbdMode nnbdMode = NnbdMode.Weak;
 
-  /// Whether nnbd checks are performed when experiment 'non-nullable' is
-  /// enabled.
-  bool performNnbdChecks = false;
-
   /// The current sdk version string, e.g. "2.6.0-edge.sha1hash".
   /// For instance used for language versioning (specifying the maximum
   /// version).
@@ -290,7 +286,6 @@
     if (bytecode != other.bytecode) return false;
     if (writeFileOnCrashReport != other.writeFileOnCrashReport) return false;
     if (nnbdMode != other.nnbdMode) return false;
-    if (performNnbdChecks != other.performNnbdChecks) return false;
     if (currentSdkVersion != other.currentSdkVersion) return false;
 
     return true;
diff --git a/pkg/front_end/lib/src/base/command_line_options.dart b/pkg/front_end/lib/src/base/command_line_options.dart
index e29ac5a..c5bfc09 100644
--- a/pkg/front_end/lib/src/base/command_line_options.dart
+++ b/pkg/front_end/lib/src/base/command_line_options.dart
@@ -9,7 +9,6 @@
   static const String nnbdAgnosticMode = "--nnbd-agnostic";
 
   static const String forceLateLowering = "--force-late-lowering";
-  static const String forceNnbdChecks = "--force-nnbd-checks";
   static const String forceNoExplicitGetterCalls =
       "--force-no-explicit-getter-calls";
 
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index a65e500..f199738 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -169,8 +169,6 @@
 
   bool get throwOnWarningsForDebugging => _raw.throwOnWarningsForDebugging;
 
-  bool get performNnbdChecks => _raw.performNnbdChecks;
-
   NnbdMode get nnbdMode => _raw.nnbdMode;
 
   /// The entry-points provided to the compiler.
diff --git a/pkg/front_end/lib/src/fasta/builder/builtin_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/builtin_type_builder.dart
index 277ead6..daecfe9 100644
--- a/pkg/front_end/lib/src/fasta/builder/builtin_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builtin_type_builder.dart
@@ -20,7 +20,8 @@
       : super(null, 0, name, compilationUnit, charOffset);
 
   DartType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     // TODO(dmitryas): Use [nullabilityBuilder].
     return type;
   }
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index e3baafe..263bfc1 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -130,7 +130,7 @@
 
   bool get isAbstract;
 
-  bool get hasConstConstructor;
+  bool get declaresConstConstructor;
 
   bool get isMixin;
 
@@ -193,7 +193,8 @@
   InterfaceType rawType(Nullability nullability);
 
   List<DartType> buildTypeArguments(
-      LibraryBuilder library, List<TypeBuilder> arguments);
+      LibraryBuilder library, List<TypeBuilder> arguments,
+      [bool notInstanceContext]);
 
   Supertype buildSupertype(LibraryBuilder library, List<TypeBuilder> arguments);
 
@@ -374,7 +375,8 @@
     return isMixinApplication && !isNamedMixinApplication;
   }
 
-  bool get hasConstConstructor => (modifiers & hasConstConstructorMask) != 0;
+  bool get declaresConstConstructor =>
+      (modifiers & declaresConstConstructorMask) != 0;
 
   @override
   List<ConstructorReferenceBuilder> get constructorReferences => null;
@@ -582,7 +584,8 @@
 
   @override
   List<DartType> buildTypeArguments(
-      LibraryBuilder library, List<TypeBuilder> arguments) {
+      LibraryBuilder library, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     if (arguments == null && typeVariables == null) {
       return <DartType>[];
     }
@@ -621,11 +624,12 @@
 
   @override
   InterfaceType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     return buildTypesWithBuiltArguments(
         library,
         nullabilityBuilder.build(library),
-        buildTypeArguments(library, arguments));
+        buildTypeArguments(library, arguments, notInstanceContext));
   }
 
   @override
@@ -757,21 +761,23 @@
             SubtypeCheckMode.ignoringNullabilities,
             allowSuperBounded: false)
         ?.toSet();
-    Set<TypeArgumentIssue> nnbdIssues =
-        library.isNonNullableByDefault && library.loader.performNnbdChecks
-            ? findTypeArgumentIssues(
-                    new InterfaceType(supertype.classNode, library.nonNullable,
-                        supertype.typeArguments),
-                    typeEnvironment,
-                    SubtypeCheckMode.withNullabilities,
-                    allowSuperBounded: false)
-                ?.toSet()
-            : null;
+    Set<TypeArgumentIssue> nnbdIssues = library.isNonNullableByDefault
+        ? findTypeArgumentIssues(
+                new InterfaceType(supertype.classNode, library.nonNullable,
+                    supertype.typeArguments),
+                typeEnvironment,
+                SubtypeCheckMode.withNullabilities,
+                allowSuperBounded: false)
+            ?.toSet()
+        : null;
     if (legacyIssues != null || nnbdIssues != null) {
       Set<TypeArgumentIssue> mergedIssues = legacyIssues ?? {};
       if (nnbdIssues != null) {
-        mergedIssues.addAll(nnbdIssues.where(
-            (issue) => legacyIssues == null || !legacyIssues.contains(issue)));
+        nnbdIssues = nnbdIssues
+            .where((issue) =>
+                legacyIssues == null || !legacyIssues.contains(issue))
+            .toSet();
+        mergedIssues.addAll(nnbdIssues);
       }
       for (TypeArgumentIssue issue in mergedIssues) {
         DartType argument = issue.argument;
@@ -846,18 +852,20 @@
               SubtypeCheckMode.ignoringNullabilities,
               allowSuperBounded: true)
           ?.toSet();
-      Set<TypeArgumentIssue> nnbdIssues =
-          library.isNonNullableByDefault && library.loader.performNnbdChecks
-              ? findTypeArgumentIssues(parameter.bound, typeEnvironment,
-                      SubtypeCheckMode.withNullabilities,
-                      allowSuperBounded: true)
-                  ?.toSet()
-              : null;
+      Set<TypeArgumentIssue> nnbdIssues = library.isNonNullableByDefault
+          ? findTypeArgumentIssues(parameter.bound, typeEnvironment,
+                  SubtypeCheckMode.withNullabilities,
+                  allowSuperBounded: true)
+              ?.toSet()
+          : null;
       if (legacyIssues != null || nnbdIssues != null) {
         Set<TypeArgumentIssue> mergedIssues = legacyIssues ?? {};
         if (nnbdIssues != null) {
-          mergedIssues.addAll(nnbdIssues.where((issue) =>
-              legacyIssues == null || !legacyIssues.contains(issue)));
+          nnbdIssues = nnbdIssues
+              .where((issue) =>
+                  legacyIssues == null || !legacyIssues.contains(issue))
+              .toSet();
+          mergedIssues.addAll(nnbdIssues);
         }
         for (TypeArgumentIssue issue in mergedIssues) {
           DartType argument = issue.argument;
@@ -1326,15 +1334,10 @@
               !types.isSubtypeOfKernel(
                   supertype, subtype, SubtypeCheckMode.ignoringNullabilities));
       Loader loader = library.loader;
-      bool performNnbdChecks = loader is SourceLoader &&
-          library.isNonNullableByDefault &&
-          loader.performNnbdChecks;
       bool nnbdWeakMode =
           loader is SourceLoader && loader.nnbdMode == NnbdMode.Weak;
-      bool isError =
-          isErrorInNnbdOptedOutMode || performNnbdChecks && !nnbdWeakMode;
-      bool isWarning =
-          !isErrorInNnbdOptedOutMode && performNnbdChecks && nnbdWeakMode;
+      bool isError = isErrorInNnbdOptedOutMode || !nnbdWeakMode;
+      bool isWarning = !isErrorInNnbdOptedOutMode && nnbdWeakMode;
       assert(
           !isError || !isWarning,
           "A compile-time problem can't be an error and a warning "
@@ -1826,9 +1829,7 @@
               redirectionTarget.charOffset,
               noLength);
           hasProblem = true;
-        } else if (library.isNonNullableByDefault &&
-            loader is SourceLoader &&
-            loader.performNnbdChecks) {
+        } else if (library.isNonNullableByDefault && loader is SourceLoader) {
           if (!typeEnvironment.isSubtypeOf(typeArgument, typeParameterBound,
               SubtypeCheckMode.withNullabilities)) {
             if (loader.nnbdMode == NnbdMode.Weak) {
@@ -1911,9 +1912,7 @@
               redirecteeType, factoryType, library.isNonNullableByDefault),
           factory.redirectionTarget.charOffset,
           noLength);
-    } else if (library.isNonNullableByDefault &&
-        loader is SourceLoader &&
-        loader.performNnbdChecks) {
+    } else if (library.isNonNullableByDefault && loader is SourceLoader) {
       if (!typeEnvironment.isSubtypeOf(
           redirecteeType, factoryType, SubtypeCheckMode.withNullabilities)) {
         if (loader.nnbdMode == NnbdMode.Weak) {
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 4641c67..ae18cd7 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -225,7 +225,7 @@
       ..registerInitializedField(members["_name"])
       ..registerInitializedField(members["index"])
       ..registerInitializedField(valuesBuilder);
-    ProcedureBuilder toStringBuilder = new ProcedureBuilderImpl(
+    ProcedureBuilder toStringBuilder = new SourceProcedureBuilder(
         null,
         0,
         stringType,
@@ -337,7 +337,8 @@
   TypeBuilder get mixedInType => null;
 
   InterfaceType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     return rawType(nullabilityBuilder.build(library));
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
index d908710..77ebc088 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -74,7 +74,8 @@
 
   @override
   DartType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     throw new UnsupportedError("ExtensionBuilder.buildType is not supported.");
   }
 
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 02883c3..7211b30 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -16,8 +16,7 @@
 import '../fasta_codes.dart' show messageInternalProblemAlreadyInitialized;
 
 import '../kernel/body_builder.dart' show BodyBuilder;
-import '../kernel/class_hierarchy_builder.dart'
-    show ClassHierarchyBuilder, ClassMember;
+import '../kernel/class_hierarchy_builder.dart';
 import '../kernel/kernel_builder.dart' show ImplicitFieldType;
 import '../kernel/late_lowering.dart' as late_lowering;
 
@@ -175,6 +174,25 @@
     }
   }
 
+  bool _typeEnsured = false;
+  Set<ClassMember> _overrideDependencies;
+
+  void registerOverrideDependency(ClassMember overriddenMember) {
+    _overrideDependencies ??= {};
+    _overrideDependencies.add(overriddenMember);
+  }
+
+  void _ensureType(ClassHierarchyBuilder hierarchy) {
+    if (_typeEnsured) return;
+    if (_overrideDependencies != null) {
+      hierarchy.inferFieldType(this, _overrideDependencies);
+      _overrideDependencies = null;
+    } else {
+      inferType();
+    }
+    _typeEnsured = true;
+  }
+
   SourceLibraryBuilder get library => super.library;
 
   Member get member => _fieldEncoding.field;
@@ -253,7 +271,10 @@
 
   void build(SourceLibraryBuilder libraryBuilder) {
     if (type != null) {
-      fieldType = type.build(libraryBuilder, null, isStatic);
+      // notInstanceContext is set to true for extension fields as they
+      // ultimately become static.
+      fieldType =
+          type.build(libraryBuilder, null, isStatic || isExtensionMember);
     }
     _fieldEncoding.build(libraryBuilder, this);
   }
@@ -273,7 +294,7 @@
             (isFinal &&
                 !isStatic &&
                 isClassMember &&
-                classBuilder.hasConstConstructor)) &&
+                classBuilder.declaresConstConstructor)) &&
         constInitializerToken != null) {
       Scope scope = classBuilder?.scope ?? library.scope;
       BodyBuilder bodyBuilder = library.loader
@@ -581,12 +602,12 @@
 
   @override
   List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
-      <ClassMember>[new SourceFieldMember(fieldBuilder)];
+      <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: false)];
 
   @override
   List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) =>
       fieldBuilder.isAssignable
-          ? <ClassMember>[new SourceFieldMember(fieldBuilder)]
+          ? <ClassMember>[new SourceFieldMember(fieldBuilder, forSetter: true)]
           : const <ClassMember>[];
 }
 
@@ -594,7 +615,30 @@
   @override
   final SourceFieldBuilder memberBuilder;
 
-  SourceFieldMember(this.memberBuilder);
+  @override
+  final bool forSetter;
+
+  SourceFieldMember(this.memberBuilder, {this.forSetter})
+      : assert(forSetter != null);
+
+  @override
+  void inferType(ClassHierarchyBuilder hierarchy) {
+    memberBuilder._ensureType(hierarchy);
+  }
+
+  @override
+  void registerOverrideDependency(ClassMember overriddenMember) {
+    memberBuilder.registerOverrideDependency(overriddenMember);
+  }
+
+  @override
+  Member getMember(ClassHierarchyBuilder hierarchy) {
+    memberBuilder._ensureType(hierarchy);
+    return memberBuilder.member;
+  }
+
+  @override
+  bool get isSourceDeclaration => true;
 
   @override
   bool get isProperty => true;
@@ -921,10 +965,12 @@
   List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) {
     List<ClassMember> list = <ClassMember>[];
     if (_lateIsSetField != null) {
-      list.add(new _LateFieldClassMember(fieldBuilder, _lateIsSetField));
+      list.add(new _LateFieldClassMember(fieldBuilder, _lateIsSetField,
+          forSetter: true));
     }
     if (_lateSetter != null) {
-      list.add(new _LateFieldClassMember(fieldBuilder, _lateSetter));
+      list.add(new _LateFieldClassMember(fieldBuilder, _lateSetter,
+          forSetter: true));
     }
     return list;
   }
@@ -1073,9 +1119,29 @@
 
   final Member _member;
 
-  _LateFieldClassMember(this.fieldBuilder, this._member);
+  @override
+  final bool forSetter;
 
-  Member getMember(ClassHierarchyBuilder hierarchy) => _member;
+  _LateFieldClassMember(this.fieldBuilder, this._member,
+      {this.forSetter: false});
+
+  Member getMember(ClassHierarchyBuilder hierarchy) {
+    fieldBuilder._ensureType(hierarchy);
+    return _member;
+  }
+
+  @override
+  void inferType(ClassHierarchyBuilder hierarchy) {
+    fieldBuilder._ensureType(hierarchy);
+  }
+
+  @override
+  void registerOverrideDependency(ClassMember overriddenMember) {
+    fieldBuilder.registerOverrideDependency(overriddenMember);
+  }
+
+  @override
+  bool get isSourceDeclaration => true;
 
   @override
   bool get isProperty => isField || isGetter || isSetter;
@@ -1168,5 +1234,38 @@
   }
 
   @override
-  String toString() => '_ClassMember($fieldBuilder,$_member)';
+  bool get needsComputation => false;
+
+  @override
+  bool get isSynthesized => false;
+
+  @override
+  bool get isInheritableConflict => false;
+
+  @override
+  ClassMember withParent(ClassBuilder classBuilder) =>
+      throw new UnsupportedError("$runtimeType.withParent");
+
+  @override
+  bool get hasDeclarations => false;
+
+  @override
+  List<ClassMember> get declarations =>
+      throw new UnsupportedError("$runtimeType.declarations");
+
+  @override
+  ClassMember get abstract => this;
+
+  @override
+  ClassMember get concrete => this;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return false;
+  }
+
+  @override
+  String toString() =>
+      '_ClassMember($fieldBuilder,$_member,forSetter=${forSetter})';
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index 1d4511b..d06e553 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -14,6 +14,7 @@
     show FormalParameterKind;
 
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' show Token;
+import 'package:front_end/src/fasta/builder/procedure_builder.dart';
 
 import 'package:kernel/ast.dart'
     show DynamicType, Expression, VariableDeclaration;
@@ -111,10 +112,11 @@
   String get fullNameForErrors => name;
 
   VariableDeclaration build(
-      SourceLibraryBuilder library, int functionNestingLevel) {
+      SourceLibraryBuilder library, int functionNestingLevel,
+      [bool notInstanceContext]) {
     if (variable == null) {
       variable = new VariableDeclarationImpl(name, functionNestingLevel,
-          type: type?.build(library),
+          type: type?.build(library, null, notInstanceContext),
           isFinal: isFinal,
           isConst: isConst,
           isFieldFormal: isInitializingFormal,
@@ -170,8 +172,9 @@
     // needed to generated noSuchMethod forwarders.
     bool isConstConstructorParameter = false;
     if (parent is ConstructorBuilder) {
-      ConstructorBuilder constructorBuilder = parent;
-      isConstConstructorParameter = constructorBuilder.constructor.isConst;
+      isConstConstructorParameter = parent.isConst;
+    } else if (parent is ProcedureBuilder) {
+      isConstConstructorParameter = parent.isFactory && parent.isConst;
     }
     if ((isConstConstructorParameter || parent.isClassInstanceMember) &&
         initializerToken != null) {
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 4152697..ece6278 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -373,7 +373,8 @@
     }
     if (formals != null) {
       for (FormalParameterBuilder formal in formals) {
-        VariableDeclaration parameter = formal.build(library, 0);
+        VariableDeclaration parameter = formal.build(
+            library, 0, !isConstructor && !isDeclarationInstanceMember);
         if (needsCheckVisitor != null) {
           if (parameter.type.accept(needsCheckVisitor)) {
             parameter.isGenericCovariantImpl = true;
@@ -389,8 +390,7 @@
           result.requiredParameterCount++;
         }
 
-        if (library.isNonNullableByDefault &&
-            library.loader.target.performNnbdChecks) {
+        if (library.isNonNullableByDefault) {
           // Required named parameters can't have default values.
           if (formal.isNamedRequired && formal.initializerToken != null) {
             if (library.loader.nnbdMode == NnbdMode.Weak) {
@@ -427,7 +427,8 @@
       result.requiredParameterCount = 1;
     }
     if (returnType != null) {
-      result.returnType = returnType.build(library);
+      result.returnType = returnType.build(
+          library, null, !isConstructor && !isDeclarationInstanceMember);
     }
     if (!isConstructor && !isDeclarationInstanceMember) {
       List<TypeParameter> typeParameters;
diff --git a/pkg/front_end/lib/src/fasta/builder/invalid_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/invalid_type_declaration_builder.dart
index 0f9683b..d101dfa 100644
--- a/pkg/front_end/lib/src/fasta/builder/invalid_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/invalid_type_declaration_builder.dart
@@ -29,7 +29,8 @@
       : super(null, 0, name, null, message.charOffset, message.uri);
 
   DartType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     return buildTypesWithBuiltArguments(library, null, null);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 1f05a75..995d801 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -296,15 +296,17 @@
         exportScope.lookupLocalMember(name, setter: member.isSetter);
     if (existing == member) {
       return false;
-    } else if (existing != null) {
-      Builder result = computeAmbiguousDeclaration(
-          name, existing, member, charOffset,
-          isExport: true);
-      exportScope.addLocalMember(name, result, setter: member.isSetter);
-      return result != existing;
     } else {
-      exportScope.addLocalMember(name, member, setter: member.isSetter);
-      return true;
+      if (existing != null) {
+        Builder result = computeAmbiguousDeclaration(
+            name, existing, member, charOffset,
+            isExport: true);
+        exportScope.addLocalMember(name, result, setter: member.isSetter);
+        return result != existing;
+      } else {
+        exportScope.addLocalMember(name, member, setter: member.isSetter);
+        return true;
+      }
     }
   }
 
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 e55bb78..6761a6d 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -254,5 +254,37 @@
   }
 
   @override
-  String toString() => '$runtimeType($fullName)';
+  bool get needsComputation => false;
+
+  @override
+  bool get isSynthesized => false;
+
+  @override
+  bool get isInheritableConflict => false;
+
+  @override
+  ClassMember withParent(ClassBuilder classBuilder) =>
+      throw new UnsupportedError("$runtimeType.withParent");
+
+  @override
+  bool get hasDeclarations => false;
+
+  @override
+  List<ClassMember> get declarations =>
+      throw new UnsupportedError("$runtimeType.declarations");
+
+  @override
+  ClassMember get abstract => this;
+
+  @override
+  ClassMember get concrete => this;
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return false;
+  }
+
+  @override
+  String toString() => '$runtimeType($fullName,forSetter=${forSetter})';
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index d4601f5..620deab 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -252,7 +252,8 @@
       }
     }
 
-    return declaration.buildType(library, nullabilityBuilder, arguments);
+    return declaration.buildType(
+        library, nullabilityBuilder, arguments, notInstanceContext);
   }
 
   Supertype buildSupertype(
diff --git a/pkg/front_end/lib/src/fasta/builder/never_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/never_type_builder.dart
index b9ed5f6..850f31e 100644
--- a/pkg/front_end/lib/src/fasta/builder/never_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/never_type_builder.dart
@@ -19,7 +19,8 @@
   String get debugName => "NeverTypeBuilder";
 
   DartType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     return type.withNullability(nullabilityBuilder.build(library));
   }
 
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 e2ee021..f2ad0cd 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -9,7 +9,7 @@
 
 import 'package:kernel/type_algebra.dart';
 
-import '../kernel/class_hierarchy_builder.dart' show ClassMember;
+import '../kernel/class_hierarchy_builder.dart';
 import '../kernel/redirecting_factory_body.dart' show RedirectingFactoryBody;
 
 import '../loader.dart' show Loader;
@@ -56,10 +56,9 @@
   bool get isExtensionMethod;
 }
 
-class ProcedureBuilderImpl extends FunctionBuilderImpl
+abstract class ProcedureBuilderImpl extends FunctionBuilderImpl
     implements ProcedureBuilder {
   final Procedure _procedure;
-  final Procedure _tearOffReferenceFrom;
 
   @override
   final int charOpenParenOffset;
@@ -76,18 +75,6 @@
   @override
   Procedure get actualProcedure => _procedure;
 
-  /// If this is an extension instance method then [_extensionTearOff] holds
-  /// the synthetically created tear off function.
-  Procedure _extensionTearOff;
-
-  /// If this is an extension instance method then
-  /// [_extensionTearOffParameterMap] holds a map from the parameters of
-  /// the methods to the parameter of the closure returned in the tear-off.
-  ///
-  /// This map is used to set the default values on the closure parameters when
-  /// these have been built.
-  Map<VariableDeclaration, VariableDeclaration> _extensionTearOffParameterMap;
-
   ProcedureBuilderImpl(
       List<MetadataBuilder> metadata,
       int modifiers,
@@ -102,7 +89,6 @@
       this.charOpenParenOffset,
       int charEndOffset,
       Procedure referenceFrom,
-      this._tearOffReferenceFrom,
       [String nativeMethodName])
       : _procedure = new Procedure(null, kind, null,
             fileUri: compilationUnit.fileUri,
@@ -115,49 +101,6 @@
             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
@@ -203,6 +146,164 @@
   }
 
   @override
+  Procedure get procedure => isPatch ? origin.procedure : _procedure;
+
+  @override
+  Member get member => procedure;
+
+  @override
+  void becomeNative(Loader loader) {
+    _procedure.isExternal = true;
+    super.becomeNative(loader);
+  }
+
+  @override
+  void applyPatch(Builder patch) {
+    if (patch is ProcedureBuilderImpl) {
+      if (checkPatch(patch)) {
+        patch.actualOrigin = this;
+        dataForTesting?.patchForTesting = patch;
+      }
+    } else {
+      reportPatchMismatch(patch);
+    }
+  }
+
+  @override
+  int finishPatch() {
+    if (!isPatch) return 0;
+
+    // TODO(ahe): restore file-offset once we track both origin and patch file
+    // URIs. See https://github.com/dart-lang/sdk/issues/31579
+    origin.procedure.fileUri = fileUri;
+    origin.procedure.startFileOffset = _procedure.startFileOffset;
+    origin.procedure.fileOffset = _procedure.fileOffset;
+    origin.procedure.fileEndOffset = _procedure.fileEndOffset;
+    origin.procedure.annotations
+        .forEach((m) => m.fileOffset = _procedure.fileOffset);
+
+    origin.procedure.isAbstract = _procedure.isAbstract;
+    origin.procedure.isExternal = _procedure.isExternal;
+    origin.procedure.function = _procedure.function;
+    origin.procedure.function.parent = origin.procedure;
+    return 1;
+  }
+}
+
+class SourceProcedureBuilder extends ProcedureBuilderImpl {
+  final Procedure _tearOffReferenceFrom;
+
+  /// If this is an extension instance method then [_extensionTearOff] holds
+  /// the synthetically created tear off function.
+  Procedure _extensionTearOff;
+
+  /// If this is an extension instance method then
+  /// [_extensionTearOffParameterMap] holds a map from the parameters of
+  /// the methods to the parameter of the closure returned in the tear-off.
+  ///
+  /// This map is used to set the default values on the closure parameters when
+  /// these have been built.
+  Map<VariableDeclaration, VariableDeclaration> _extensionTearOffParameterMap;
+
+  SourceProcedureBuilder(
+      List<MetadataBuilder> metadata,
+      int modifiers,
+      TypeBuilder returnType,
+      String name,
+      List<TypeVariableBuilder> typeVariables,
+      List<FormalParameterBuilder> formals,
+      ProcedureKind kind,
+      SourceLibraryBuilder compilationUnit,
+      int startCharOffset,
+      int charOffset,
+      int charOpenParenOffset,
+      int charEndOffset,
+      Procedure referenceFrom,
+      this._tearOffReferenceFrom,
+      [String nativeMethodName])
+      : super(
+            metadata,
+            modifiers,
+            returnType,
+            name,
+            typeVariables,
+            formals,
+            kind,
+            compilationUnit,
+            startCharOffset,
+            charOffset,
+            charOpenParenOffset,
+            charEndOffset,
+            referenceFrom,
+            nativeMethodName);
+
+  bool _typeEnsured = false;
+  Set<ClassMember> _overrideDependencies;
+
+  void registerOverrideDependency(ClassMember overriddenMember) {
+    _overrideDependencies ??= {};
+    _overrideDependencies.add(overriddenMember);
+  }
+
+  void _ensureTypes(ClassHierarchyBuilder hierarchy) {
+    if (_typeEnsured) return;
+    if (_overrideDependencies != null) {
+      if (isGetter) {
+        hierarchy.inferGetterType(this, _overrideDependencies);
+      } else if (isSetter) {
+        hierarchy.inferSetterType(this, _overrideDependencies);
+      } else {
+        hierarchy.inferMethodType(this, _overrideDependencies);
+      }
+      _overrideDependencies = null;
+    }
+    _typeEnsured = true;
+  }
+
+  @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
   void buildMembers(
       LibraryBuilder library, void Function(Member, BuiltMemberKind) f) {
     Member member = build(library);
@@ -436,17 +537,6 @@
     _extensionTearOff.function.parent = _extensionTearOff;
   }
 
-  @override
-  VariableDeclaration getExtensionTearOffParameter(int index) {
-    if (_extensionTearOffParameterMap != null) {
-      return _extensionTearOffParameterMap[getFormalParameter(index)];
-    }
-    return null;
-  }
-
-  @override
-  Procedure get procedure => isPatch ? origin.procedure : _procedure;
-
   Procedure get extensionTearOff {
     if (isExtensionInstanceMember && kind == ProcedureKind.Method) {
       _extensionTearOff ??= new Procedure(null, ProcedureKind.Method, null,
@@ -459,44 +549,11 @@
   }
 
   @override
-  Member get member => procedure;
-
-  @override
-  int finishPatch() {
-    if (!isPatch) return 0;
-
-    // TODO(ahe): restore file-offset once we track both origin and patch file
-    // URIs. See https://github.com/dart-lang/sdk/issues/31579
-    origin.procedure.fileUri = fileUri;
-    origin.procedure.startFileOffset = _procedure.startFileOffset;
-    origin.procedure.fileOffset = _procedure.fileOffset;
-    origin.procedure.fileEndOffset = _procedure.fileEndOffset;
-    origin.procedure.annotations
-        .forEach((m) => m.fileOffset = _procedure.fileOffset);
-
-    origin.procedure.isAbstract = _procedure.isAbstract;
-    origin.procedure.isExternal = _procedure.isExternal;
-    origin.procedure.function = _procedure.function;
-    origin.procedure.function.parent = origin.procedure;
-    return 1;
-  }
-
-  @override
-  void becomeNative(Loader loader) {
-    _procedure.isExternal = true;
-    super.becomeNative(loader);
-  }
-
-  @override
-  void applyPatch(Builder patch) {
-    if (patch is ProcedureBuilderImpl) {
-      if (checkPatch(patch)) {
-        patch.actualOrigin = this;
-        dataForTesting?.patchForTesting = patch;
-      }
-    } else {
-      reportPatchMismatch(patch);
+  VariableDeclaration getExtensionTearOffParameter(int index) {
+    if (_extensionTearOffParameterMap != null) {
+      return _extensionTearOffParameterMap[getFormalParameter(index)];
     }
+    return null;
   }
 
   @override
@@ -508,25 +565,6 @@
   List<ClassMember> get localSetters => isSetter
       ? <ClassMember>[new SourceProcedureMember(this)]
       : const <ClassMember>[];
-}
-
-class SourceProcedureMember extends BuilderClassMember {
-  @override
-  final ProcedureBuilderImpl memberBuilder;
-
-  SourceProcedureMember(this.memberBuilder);
-
-  @override
-  bool get isProperty =>
-      memberBuilder.kind == ProcedureKind.Getter ||
-      memberBuilder.kind == ProcedureKind.Setter;
-
-  @override
-  bool get isFunction => !isProperty;
-
-  List<FormalParameterBuilder> get formals => memberBuilder.formals;
-
-  TypeBuilder get returnType => memberBuilder.returnType;
 
   static const int inferredTypesFromMethod = 3;
   static const int inferredTypesFromField = 3;
@@ -544,6 +582,53 @@
   /// setters, and in setter type inference to favor types from setters over
   /// types from getters.
   int hadTypesInferredFrom = 0;
+}
+
+class SourceProcedureMember extends BuilderClassMember {
+  @override
+  final SourceProcedureBuilder memberBuilder;
+
+  SourceProcedureMember(this.memberBuilder);
+
+  @override
+  bool get isSourceDeclaration => true;
+
+  int get hadTypesInferredFrom => memberBuilder.hadTypesInferredFrom;
+
+  void set hadTypesInferredFrom(int value) {
+    memberBuilder.hadTypesInferredFrom = value;
+  }
+
+  @override
+  void inferType(ClassHierarchyBuilder hierarchy) {
+    memberBuilder._ensureTypes(hierarchy);
+  }
+
+  @override
+  void registerOverrideDependency(ClassMember overriddenMember) {
+    memberBuilder.registerOverrideDependency(overriddenMember);
+  }
+
+  @override
+  Member getMember(ClassHierarchyBuilder hierarchy) {
+    memberBuilder._ensureTypes(hierarchy);
+    return memberBuilder.member;
+  }
+
+  @override
+  bool get forSetter => isSetter;
+
+  @override
+  bool get isProperty =>
+      memberBuilder.kind == ProcedureKind.Getter ||
+      memberBuilder.kind == ProcedureKind.Setter;
+
+  @override
+  bool get isFunction => !isProperty;
+
+  List<FormalParameterBuilder> get formals => memberBuilder.formals;
+
+  TypeBuilder get returnType => memberBuilder.returnType;
 
   @override
   bool get hasExplicitReturnType {
@@ -573,7 +658,6 @@
       int charOpenParenOffset,
       int charEndOffset,
       Procedure referenceFrom,
-      Procedure tearOffReferenceFrom,
       [String nativeMethodName,
       this.redirectionTarget])
       : super(
@@ -590,10 +674,18 @@
             charOpenParenOffset,
             charEndOffset,
             referenceFrom,
-            tearOffReferenceFrom,
             nativeMethodName);
 
   @override
+  Member get readTarget => null;
+
+  @override
+  Member get writeTarget => null;
+
+  @override
+  Member get invokeTarget => procedure;
+
+  @override
   Statement get body => bodyInternal;
 
   @override
@@ -638,9 +730,20 @@
   }
 
   @override
-  Procedure build(SourceLibraryBuilder library) {
-    Procedure result = super.build(library);
-    result.isRedirectingFactoryConstructor = true;
+  Procedure build(SourceLibraryBuilder libraryBuilder) {
+    // TODO(ahe): I think we may call this twice on parts. Investigate.
+    if (_procedure.name == null) {
+      _procedure.function = buildFunction(libraryBuilder);
+      _procedure.function.parent = _procedure;
+      _procedure.function.fileOffset = charOpenParenOffset;
+      _procedure.function.fileEndOffset = _procedure.fileEndOffset;
+      _procedure.isAbstract = isAbstract;
+      _procedure.isExternal = isExternal;
+      _procedure.isConst = isConst;
+      _procedure.isStatic = isStatic;
+      _procedure.name = new Name(name, libraryBuilder.library);
+    }
+    _procedure.isRedirectingFactoryConstructor = true;
     if (redirectionTarget.typeArguments != null) {
       typeArguments =
           new List<DartType>(redirectionTarget.typeArguments.length);
@@ -648,10 +751,18 @@
         typeArguments[i] = redirectionTarget.typeArguments[i].build(library);
       }
     }
-    return result;
+    return _procedure;
   }
 
   @override
+  List<ClassMember> get localMembers =>
+      throw new UnsupportedError('${runtimeType}.localMembers');
+
+  @override
+  List<ClassMember> get localSetters =>
+      throw new UnsupportedError('${runtimeType}.localSetters');
+
+  @override
   int finishPatch() {
     if (!isPatch) return 0;
 
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
index 184af64..6cc686b 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -186,7 +186,8 @@
   }
 
   List<DartType> buildTypeArguments(
-      LibraryBuilder library, List<TypeBuilder> arguments) {
+      LibraryBuilder library, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     if (arguments == null && typeVariables == null) {
       return <DartType>[];
     }
@@ -236,7 +237,8 @@
 
   @override
   DartType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     DartType thisType = buildThisType(library);
     if (thisType is InvalidType) return thisType;
     // TODO(dmitryas): Remove the following comment when FutureOr has its own
diff --git a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
index bc26462..a8c16a1 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
@@ -23,7 +23,8 @@
   int get typeVariablesCount => 0;
 
   DartType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments);
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
+      [bool notInstanceContext]);
 
   /// [arguments] have already been built.
   DartType buildTypesWithBuiltArguments(LibraryBuilder library,
diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
index 277e05c..4ca6ab8 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
@@ -76,7 +76,8 @@
   }
 
   DartType buildType(LibraryBuilder library,
-      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments) {
+      NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     if (arguments != null) {
       int charOffset = -1; // TODO(ahe): Provide these.
       Uri fileUri = null; // TODO(ahe): Provide these.
@@ -135,8 +136,9 @@
   void finish(
       LibraryBuilder library, ClassBuilder object, TypeBuilder dynamicType) {
     if (isPatch) return;
+    // TODO(jensj): Provide correct notInstanceContext.
     DartType objectType =
-        object.buildType(library, library.nullableBuilder, null);
+        object.buildType(library, library.nullableBuilder, null, null);
     parameter.bound ??= bound?.build(library) ?? objectType;
     // If defaultType is not set, initialize it to dynamic, unless the bound is
     // explicitly specified as Object, in which case defaultType should also be
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
index 04f75bc..23ca352 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
@@ -88,7 +88,8 @@
 
   @override
   List<DartType> buildTypeArguments(
-      LibraryBuilder library, List<TypeBuilder> arguments) {
+      LibraryBuilder library, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     // For performance reasons, [typeVariables] aren't restored from [target].
     // So, if [arguments] is null, the default types should be retrieved from
     // [cls.typeParameters].
@@ -106,7 +107,7 @@
     List<DartType> result =
         new List<DartType>.filled(arguments.length, null, growable: true);
     for (int i = 0; i < result.length; ++i) {
-      result[i] = arguments[i].build(library);
+      result[i] = arguments[i].build(library, null, notInstanceContext);
     }
     return result;
   }
@@ -116,7 +117,7 @@
   bool get isMixinApplication => cls.isMixinApplication;
 
   @override
-  bool get hasConstConstructor => cls.hasConstConstructor;
+  bool get declaresConstConstructor => cls.hasConstConstructor;
 
   TypeBuilder get mixedInType {
     return computeTypeBuilder(library, cls.mixedInType);
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 1604ace..bd23030 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
@@ -11,7 +11,8 @@
 import '../builder/member_builder.dart';
 import '../builder/library_builder.dart';
 
-import '../kernel/class_hierarchy_builder.dart' show ClassMember;
+import '../kernel/class_hierarchy_builder.dart'
+    show ClassHierarchyBuilder, ClassMember;
 import '../kernel/kernel_builder.dart'
     show isRedirectingGenerativeConstructorImplementation;
 
@@ -132,12 +133,12 @@
   @override
   List<ClassMember> get localMembers => isSetter
       ? const <ClassMember>[]
-      : <ClassMember>[new DillClassMember(this)];
+      : <ClassMember>[new DillClassMember(this, forSetter: false)];
 
   @override
   List<ClassMember> get localSetters =>
       isSetter || member is Field && member.hasSetter
-          ? <ClassMember>[new DillClassMember(this)]
+          ? <ClassMember>[new DillClassMember(this, forSetter: true)]
           : const <ClassMember>[];
 }
 
@@ -145,7 +146,14 @@
   @override
   final DillMemberBuilder memberBuilder;
 
-  DillClassMember(this.memberBuilder);
+  @override
+  final bool forSetter;
+
+  DillClassMember(this.memberBuilder, {this.forSetter})
+      : assert(forSetter != null);
+
+  @override
+  bool get isSourceDeclaration => false;
 
   @override
   bool get isProperty =>
@@ -162,7 +170,17 @@
   @override
   bool hasExplicitlyTypedFormalParameter(int index) => true;
 
-  String toString() => 'DillClassMember($memberBuilder)';
+  @override
+  void inferType(ClassHierarchyBuilder hierarchy) {
+    // Do nothing; this is only for source members.
+  }
+
+  @override
+  void registerOverrideDependency(ClassMember overriddenMember) {
+    // Do nothing; this is only for source members.
+  }
+
+  String toString() => 'DillClassMember($memberBuilder,forSetter=${forSetter})';
 }
 
 int computeModifiers(Member member) {
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
index 5849465..f13acd1 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
@@ -51,7 +51,8 @@
 
   @override
   List<DartType> buildTypeArguments(
-      LibraryBuilder library, List<TypeBuilder> arguments) {
+      LibraryBuilder library, List<TypeBuilder> arguments,
+      [bool notInstanceContext]) {
     // For performance reasons, [typeVariables] aren't restored from [target].
     // So, if [arguments] is null, the default types should be retrieved from
     // [cls.typeParameters].
diff --git a/pkg/front_end/lib/src/fasta/export.dart b/pkg/front_end/lib/src/fasta/export.dart
index 3c264c9..e57cf8d 100644
--- a/pkg/front_end/lib/src/fasta/export.dart
+++ b/pkg/front_end/lib/src/fasta/export.dart
@@ -8,6 +8,7 @@
 import 'builder/library_builder.dart';
 
 import 'combinator.dart' show Combinator;
+import 'fasta_codes.dart';
 
 class Export {
   /// The library that is exporting [exported];
@@ -31,6 +32,18 @@
         if (combinator.isHide && combinator.names.contains(name)) return false;
       }
     }
-    return exporter.addToExportScope(name, member, charOffset);
+    bool changed = exporter.addToExportScope(name, member, charOffset);
+    if (changed) {
+      if (exporter.isNonNullableByDefault) {
+        // TODO(johnniwinther): Add a common interface for exportable builders.
+        Builder memberLibrary = member.parent;
+        if (memberLibrary is LibraryBuilder &&
+            !memberLibrary.isNonNullableByDefault) {
+          exporter.addProblem(
+              messageExportOptOutFromOptIn, charOffset, noLength, fileUri);
+        }
+      }
+    }
+    return changed;
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index dc0344c..074cc5b 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -414,9 +414,7 @@
       }
     }
     userCode.loader.buildersCreatedWithReferences.clear();
-    userCode.loader.builderHierarchy.nodes.clear();
-    userCode.loader.builderHierarchy.overrideChecks.clear();
-    userCode.loader.builderHierarchy.delayedSignatureComputations.clear();
+    userCode.loader.builderHierarchy.clear();
     userCode.loader.referenceFromIndex = null;
     convertedLibraries = null;
     experimentalInvalidation = null;
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 b3f2461..ec3c6e9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -6,8 +6,6 @@
 
 import 'dart:core' hide MapEntry;
 
-import 'package:kernel/type_algebra.dart' show containsTypeVariable, substitute;
-
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
@@ -641,8 +639,9 @@
           (expression is! ReadOnlyAccessGenerator ||
               expression is TypeUseGenerator ||
               expression is ParenthesizedExpressionGenerator)) {
-        push(wrapInProblem(
-            toValue(expression), fasta.messageExpressionNotMetadata, noLength));
+        Expression value = toValue(expression);
+        push(wrapInProblem(value, fasta.messageExpressionNotMetadata,
+            value.fileOffset, noLength));
       } else {
         push(toValue(expression));
       }
@@ -860,8 +859,8 @@
     } else {
       Expression value = toValue(node);
       if (!forest.isThrow(node)) {
-        value =
-            wrapInProblem(value, fasta.messageExpectedAnInitializer, noLength);
+        value = wrapInProblem(value, fasta.messageExpectedAnInitializer,
+            value.fileOffset, noLength);
       }
       initializers = <Initializer>[
         buildInvalidInitializer(node, token.charOffset)
@@ -1877,7 +1876,7 @@
             ? ConstantContext.inferred
             : !member.isStatic &&
                     classBuilder != null &&
-                    classBuilder.hasConstConstructor
+                    classBuilder.declaresConstConstructor
                 ? ConstantContext.required
                 : ConstantContext.none;
       }
@@ -3343,8 +3342,8 @@
           name?.name, libraryBuilder, offsetForToken(nameToken), uri)
         ..hasDeclaredInitializer = (initializerStart != null);
     }
-    VariableDeclaration variable =
-        parameter.build(libraryBuilder, functionNestingLevel);
+    VariableDeclaration variable = parameter.build(
+        libraryBuilder, functionNestingLevel, !isDeclarationInstanceContext);
     Expression initializer = name?.initializer;
     if (initializer != null) {
       if (member is RedirectingFactoryBuilder) {
@@ -3679,8 +3678,9 @@
       push(generator.buildPrefixIncrement(incrementOperator(token),
           offset: token.charOffset));
     } else {
+      Expression value = toValue(generator);
       push(wrapInProblem(
-          toValue(generator), fasta.messageNotAnLvalue, noLength));
+          value, fasta.messageNotAnLvalue, value.fileOffset, noLength));
     }
   }
 
@@ -3692,8 +3692,9 @@
       push(new DelayedPostfixIncrement(
           this, token, generator, incrementOperator(token)));
     } else {
+      Expression value = toValue(generator);
       push(wrapInProblem(
-          toValue(generator), fasta.messageNotAnLvalue, noLength));
+          value, fasta.messageNotAnLvalue, value.fileOffset, noLength));
     }
   }
 
@@ -3919,8 +3920,7 @@
       }
     }
     if (function.namedParameters.isNotEmpty) {
-      if (libraryBuilder.isNonNullableByDefault &&
-          libraryBuilder.loader.performNnbdChecks) {
+      if (libraryBuilder.isNonNullableByDefault) {
         Set<String> argumentNames = new Set.from(named.map((a) => a.name));
         for (VariableDeclaration parameter in function.namedParameters) {
           if (parameter.isRequired && !argumentNames.contains(parameter.name)) {
@@ -3987,8 +3987,7 @@
       }
     }
     if (function.namedParameters.isNotEmpty) {
-      if (libraryBuilder.isNonNullableByDefault &&
-          libraryBuilder.loader.performNnbdChecks) {
+      if (libraryBuilder.isNonNullableByDefault) {
         Set<String> argumentNames = new Set.from(named.map((a) => a.name));
         for (NamedType parameter in function.namedParameters) {
           if (parameter.isRequired && !argumentNames.contains(parameter.name)) {
@@ -4463,53 +4462,6 @@
     enterFunction();
   }
 
-  _checkTypeParameters(FunctionNode function) {
-    if (member == null) return;
-    if (!member.isStatic) return;
-    List<TypeParameter> typeParameters;
-    if (member.parent is ClassBuilder) {
-      ClassBuilder enclosingClassBuilder = member.parent;
-      typeParameters = enclosingClassBuilder.cls.typeParameters;
-    } else if (member.parent is ExtensionBuilder) {
-      ExtensionBuilder enclosingExtensionBuilder = member.parent;
-      typeParameters = enclosingExtensionBuilder.extension.typeParameters;
-    }
-    if (typeParameters != null && typeParameters.isNotEmpty) {
-      Map<TypeParameter, DartType> substitution;
-      DartType removeTypeVariables(DartType type, int offset) {
-        if (substitution == null) {
-          substitution = <TypeParameter, DartType>{};
-          for (TypeParameter parameter in typeParameters) {
-            substitution[parameter] = const DynamicType();
-          }
-        }
-        libraryBuilder.addProblem(fasta.messageNonInstanceTypeVariableUse,
-            offset, noLength, member.fileUri);
-        return substitute(type, substitution);
-      }
-
-      Set<TypeParameter> set = typeParameters.toSet();
-      for (VariableDeclaration parameter in function.positionalParameters) {
-        parameter.fileOffset;
-        if (containsTypeVariable(parameter.type, set)) {
-          parameter.type =
-              removeTypeVariables(parameter.type, parameter.fileOffset);
-        }
-      }
-      for (VariableDeclaration parameter in function.namedParameters) {
-        if (containsTypeVariable(parameter.type, set)) {
-          parameter.type =
-              removeTypeVariables(parameter.type, parameter.fileOffset);
-        }
-      }
-      if (containsTypeVariable(function.returnType, set)) {
-        // TODO(CFE Team): The offset here doesn't actually point to the type.
-        function.returnType =
-            removeTypeVariables(function.returnType, function.fileOffset);
-      }
-    }
-  }
-
   void pushNamedFunction(Token token, bool isFunctionExpression) {
     Statement body = popStatement();
     AsyncMarker asyncModifier = pop();
@@ -4524,9 +4476,14 @@
     if (!isFunctionExpression) {
       annotations = pop(); // Metadata.
     }
-    FunctionNode function = formals.buildFunctionNode(libraryBuilder,
-        returnType, typeParameters, asyncModifier, body, token.charOffset);
-    _checkTypeParameters(function);
+    FunctionNode function = formals.buildFunctionNode(
+        libraryBuilder,
+        returnType,
+        typeParameters,
+        asyncModifier,
+        body,
+        token.charOffset,
+        !isDeclarationInstanceContext);
 
     if (declaration is FunctionDeclaration) {
       VariableDeclaration variable = declaration.variable;
@@ -4611,10 +4568,15 @@
     FormalParameters formals = pop();
     exitFunction();
     List<TypeVariableBuilder> typeParameters = pop();
-    FunctionNode function = formals.buildFunctionNode(libraryBuilder, null,
-        typeParameters, asyncModifier, body, token.charOffset)
+    FunctionNode function = formals.buildFunctionNode(
+        libraryBuilder,
+        null,
+        typeParameters,
+        asyncModifier,
+        body,
+        token.charOffset,
+        !isDeclarationInstanceContext)
       ..fileOffset = beginToken.charOffset;
-    _checkTypeParameters(function);
 
     Expression result;
     if (constantContext != ConstantContext.none) {
@@ -5465,16 +5427,16 @@
   }
 
   @override
-  Expression wrapInProblem(Expression expression, Message message, int length,
+  Expression wrapInProblem(
+      Expression expression, Message message, int fileOffset, int length,
       {List<LocatedMessage> context}) {
-    int charOffset = expression.fileOffset;
     Severity severity = message.code.severity;
     if (severity == Severity.error) {
       return wrapInLocatedProblem(
-          expression, message.withLocation(uri, charOffset, length),
+          expression, message.withLocation(uri, fileOffset, length),
           context: context);
     } else {
-      addProblem(message, charOffset, length, context: context);
+      addProblem(message, fileOffset, length, context: context);
       return expression;
     }
   }
@@ -5761,7 +5723,9 @@
       TypeVariableBuilder typeParameterBuilder = builder.declaration;
       TypeParameter typeParameter = typeParameterBuilder.parameter;
       LocatedMessage message;
-      if (!isDeclarationInstanceContext &&
+      bool extensionField =
+          (member?.isExtensionMember ?? false) && member.isField;
+      if ((extensionField || !isDeclarationInstanceContext) &&
           (typeParameter.parent is Class ||
               typeParameter.parent is Extension)) {
         message = fasta.messageTypeVariableInStaticContext.withLocation(
@@ -6163,11 +6127,12 @@
       List<TypeVariableBuilder> typeParameters,
       AsyncMarker asyncModifier,
       Statement body,
-      int fileEndOffset) {
+      int fileEndOffset,
+      bool notInstanceContext) {
     FunctionType type = toFunctionType(
             returnType, const NullabilityBuilder.omitted(), typeParameters)
         .builder
-        .build(library);
+        .build(library, null, notInstanceContext);
     List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
     List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
     if (parameters != null) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 2436056..773fff0 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
@@ -82,6 +82,8 @@
 
 import 'types.dart' show Types;
 
+const bool useConsolidated = true;
+
 const DebugLogger debug =
     const bool.fromEnvironment("debug.hierarchy") ? const DebugLogger() : null;
 
@@ -95,10 +97,101 @@
   return ClassHierarchy.compareNames(a.name, b.name);
 }
 
+int compareClassMembers(ClassMember a, ClassMember b) {
+  if (a.forSetter == b.forSetter) {
+    return compareDeclarations(a, b);
+  } else if (a.forSetter) {
+    return 1;
+  } else {
+    return -1;
+  }
+}
+
 bool isNameVisibleIn(Name name, LibraryBuilder libraryBuilder) {
   return !name.isPrivate || name.library == libraryBuilder.library;
 }
 
+class Tuple {
+  final Name name;
+  ClassMember declaredMember;
+  ClassMember declaredSetter;
+  ClassMember extendedMember;
+  ClassMember extendedSetter;
+  List<ClassMember> implementedMembers;
+  List<ClassMember> implementedSetters;
+
+  Tuple.declareMember(this.declaredMember)
+      : assert(!declaredMember.forSetter),
+        this.name = declaredMember.name;
+
+  Tuple.extendMember(this.extendedMember)
+      : assert(!extendedMember.forSetter),
+        this.name = extendedMember.name;
+
+  Tuple.implementMember(ClassMember implementedMember)
+      : assert(!implementedMember.forSetter),
+        this.name = implementedMember.name,
+        implementedMembers = <ClassMember>[implementedMember];
+
+  Tuple.declareSetter(this.declaredSetter)
+      : assert(declaredSetter.forSetter),
+        this.name = declaredSetter.name;
+
+  Tuple.extendSetter(this.extendedSetter)
+      : assert(extendedSetter.forSetter),
+        this.name = extendedSetter.name;
+
+  Tuple.implementSetter(ClassMember implementedSetter)
+      : assert(implementedSetter.forSetter),
+        this.name = implementedSetter.name,
+        implementedSetters = <ClassMember>[implementedSetter];
+
+  @override
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    String comma = '';
+    sb.write('Tuple(');
+    if (declaredMember != null) {
+      sb.write(comma);
+      sb.write('declaredMember=');
+      sb.write(declaredMember);
+      comma = ',';
+    }
+    if (declaredSetter != null) {
+      sb.write(comma);
+      sb.write('declaredSetter=');
+      sb.write(declaredSetter);
+      comma = ',';
+    }
+    if (extendedMember != null) {
+      sb.write(comma);
+      sb.write('extendedMember=');
+      sb.write(extendedMember);
+      comma = ',';
+    }
+    if (extendedSetter != null) {
+      sb.write(comma);
+      sb.write('extendedSetter=');
+      sb.write(extendedSetter);
+      comma = ',';
+    }
+    if (implementedMembers != null) {
+      sb.write(comma);
+      sb.write('implementedMembers=');
+      sb.write(implementedMembers);
+      comma = ',';
+    }
+    if (implementedSetters != null) {
+      sb.write(comma);
+      sb.write('implementedSetters=');
+      sb.write(implementedSetters);
+      comma = ',';
+    }
+    sb.write(')');
+    return sb.toString();
+  }
+}
+
 abstract class ClassMember {
   Name get name;
   bool get isStatic;
@@ -108,6 +201,8 @@
   bool get isGetter;
   bool get isFinal;
   bool get isConst;
+  bool get forSetter;
+  bool get isSourceDeclaration;
 
   /// Returns `true` if this member is a regular method or operator.
   bool get isFunction;
@@ -125,6 +220,20 @@
   bool get isAbstract;
   bool get hasExplicitReturnType;
   bool hasExplicitlyTypedFormalParameter(int index);
+
+  bool get needsComputation;
+  bool get isSynthesized;
+  bool get isInheritableConflict;
+  ClassMember withParent(ClassBuilder classBuilder);
+  bool get hasDeclarations;
+  List<ClassMember> get declarations;
+  ClassMember get abstract;
+  ClassMember get concrete;
+
+  bool operator ==(Object other);
+
+  void inferType(ClassHierarchyBuilder hierarchy);
+  void registerOverrideDependency(ClassMember overriddenMember);
 }
 
 /// Returns true if [a] is a class member conflict with [b].  [a] is assumed to
@@ -204,6 +313,9 @@
 class ClassHierarchyBuilder {
   final Map<Class, ClassHierarchyNode> nodes = <Class, ClassHierarchyNode>{};
 
+  final Map<ClassBuilder, Map<Class, Substitution>> substitutions =
+      <ClassBuilder, Map<Class, Substitution>>{};
+
   final ClassBuilder objectClassBuilder;
 
   final Loader loader;
@@ -218,12 +330,12 @@
 
   final Class nullClass;
 
-  final List<DelayedSignatureComputation> delayedSignatureComputations =
-      <DelayedSignatureComputation>[];
+  final List<DelayedTypeComputation> _delayedTypeComputations =
+      <DelayedTypeComputation>[];
 
-  final List<DelayedOverrideCheck> overrideChecks = <DelayedOverrideCheck>[];
+  final List<DelayedOverrideCheck> _overrideChecks = <DelayedOverrideCheck>[];
 
-  final List<DelayedMember> delayedMemberChecks = <DelayedMember>[];
+  final List<ClassMember> _delayedMemberChecks = <ClassMember>[];
 
   final CoreTypes coreTypes;
 
@@ -238,9 +350,88 @@
     types = new Types(this);
   }
 
+  void clear() {
+    nodes.clear();
+    substitutions.clear();
+    _overrideChecks.clear();
+    _delayedTypeComputations.clear();
+  }
+
+  void registerDelayedTypeComputation(DelayedTypeComputation computation) {
+    _delayedTypeComputations.add(computation);
+  }
+
+  void registerOverrideCheck(
+      ClassBuilder classBuilder, ClassMember a, ClassMember b) {
+    _overrideChecks.add(new DelayedOverrideCheck(classBuilder, a, b));
+  }
+
+  void registerMemberCheck(ClassMember member) {
+    _delayedMemberChecks.add(member);
+  }
+
+  List<DelayedTypeComputation> takeDelayedTypeComputations() {
+    List<DelayedTypeComputation> list = _delayedTypeComputations.toList();
+    _delayedTypeComputations.clear();
+    return list;
+  }
+
+  List<DelayedOverrideCheck> takeDelayedOverrideChecks() {
+    List<DelayedOverrideCheck> list = _overrideChecks.toList();
+    _overrideChecks.clear();
+    return list;
+  }
+
+  List<ClassMember> takeDelayedMemberChecks() {
+    List<ClassMember> list = _delayedMemberChecks.toList();
+    _delayedMemberChecks.clear();
+    return list;
+  }
+
+  void inferFieldType(SourceFieldBuilder declaredMember,
+      Iterable<ClassMember> overriddenMembers) {
+    ClassHierarchyNodeBuilder.inferFieldType(
+        this,
+        declaredMember.classBuilder,
+        substitutions[declaredMember.classBuilder],
+        declaredMember,
+        overriddenMembers);
+  }
+
+  void inferGetterType(SourceProcedureBuilder declaredMember,
+      Iterable<ClassMember> overriddenMembers) {
+    ClassHierarchyNodeBuilder.inferGetterType(
+        this,
+        declaredMember.classBuilder,
+        substitutions[declaredMember.classBuilder],
+        declaredMember,
+        overriddenMembers);
+  }
+
+  void inferSetterType(SourceProcedureBuilder declaredMember,
+      Iterable<ClassMember> overriddenMembers) {
+    ClassHierarchyNodeBuilder.inferSetterType(
+        this,
+        declaredMember.classBuilder,
+        substitutions[declaredMember.classBuilder],
+        declaredMember,
+        overriddenMembers);
+  }
+
+  void inferMethodType(SourceProcedureBuilder declaredMember,
+      Iterable<ClassMember> overriddenMembers) {
+    ClassHierarchyNodeBuilder.inferMethodType(
+        this,
+        declaredMember.classBuilder,
+        substitutions[declaredMember.classBuilder],
+        declaredMember,
+        overriddenMembers);
+  }
+
   ClassHierarchyNode getNodeFromClassBuilder(ClassBuilder classBuilder) {
-    return nodes[classBuilder.cls] ??=
-        new ClassHierarchyNodeBuilder(this, classBuilder).build();
+    return nodes[classBuilder.cls] ??= new ClassHierarchyNodeBuilder(
+            this, classBuilder, substitutions[classBuilder] ??= {})
+        .build();
   }
 
   ClassHierarchyNode getNodeFromTypeBuilder(TypeBuilder type) {
@@ -398,11 +589,7 @@
           library.fileUri);
       return null;
     }
-    if (declaration is DelayedMember) {
-      return declaration.check(this);
-    } else {
-      return declaration.getMember(this);
-    }
+    return declaration.getMember(this);
   }
 
   static ClassHierarchyBuilder build(ClassBuilder objectClass,
@@ -412,22 +599,26 @@
     for (int i = 0; i < classes.length; i++) {
       ClassBuilder classBuilder = classes[i];
       if (!classBuilder.isPatch) {
-        hierarchy.nodes[classBuilder.cls] =
-            new ClassHierarchyNodeBuilder(hierarchy, classBuilder).build();
+        hierarchy.nodes[classBuilder.cls] = new ClassHierarchyNodeBuilder(
+                hierarchy,
+                classBuilder,
+                hierarchy.substitutions[classBuilder] ??= {})
+            .build();
       } else {
         // TODO(ahe): Merge the injected members of patch into the hierarchy
         // node of `cls.origin`.
       }
     }
-
-    List<DelayedSignatureComputation> signatureComputations =
-        hierarchy.delayedSignatureComputations.toList();
-    hierarchy.delayedSignatureComputations.clear();
-    for (int i = 0; i < signatureComputations.length; i++) {
-      signatureComputations[i].computeSignature(hierarchy);
-    }
     return hierarchy;
   }
+
+  void computeTypes() {
+    List<DelayedTypeComputation> typeComputations =
+        takeDelayedTypeComputations();
+    for (int i = 0; i < typeComputations.length; i++) {
+      typeComputations[i].compute(this);
+    }
+  }
 }
 
 class ClassHierarchyNodeBuilder {
@@ -439,169 +630,18 @@
 
   List<ClassMember> abstractMembers = null;
 
-  ClassHierarchyNodeBuilder(this.hierarchy, this.classBuilder);
+  final Map<Class, Substitution> substitutions;
+
+  ClassHierarchyNodeBuilder(
+      this.hierarchy, this.classBuilder, this.substitutions);
 
   ClassBuilder get objectClass => hierarchy.objectClassBuilder;
 
   bool get shouldModifyKernel =>
       classBuilder.library.loader == hierarchy.loader;
 
-  final Map<Class, Substitution> substitutions = <Class, Substitution>{};
-
-  /// When merging `aList` and `bList`, [a] (from `aList`) and [b] (from
-  /// `bList`) each have the same name.
-  ///
-  /// If [mergeKind] is `MergeKind.superclass`, [a] should override [b].
-  ///
-  /// If [mergeKind] is `MergeKind.interfaces`, we need to record them and
-  /// solve the conflict later.
-  ///
-  /// If [mergeKind] is `MergeKind.supertypes`, [a] should implement [b], and
-  /// [b] is implicitly abstract.
-  ClassMember handleMergeConflict(
-      ClassMember a, ClassMember b, MergeKind mergeKind) {
-    debug?.log("handleMergeConflict: ${a.fullName} ${b.fullName} ${mergeKind}");
-    // TODO(ahe): Enable this optimization, but be careful about abstract
-    // methods overriding concrete methods.
-    // if (cls is DillClassBuilder) return a;
-    if (a == b) return a;
-    if (a.isDuplicate || b.isDuplicate) {
-      // Don't check overrides involving duplicated members.
-      return a;
-    }
-    ClassMember result = checkInheritanceConflict(a, b);
-    if (result != null) return result;
-    assert(a.isProperty == b.isProperty,
-        "Unexpected member combination: $a vs $b");
-    result = a;
-    switch (mergeKind) {
-      case MergeKind.superclassMembers:
-      case MergeKind.superclassSetters:
-        // [a] is a method declared in [cls]. This means it defines the
-        // interface of this class regardless if its abstract.
-        debug?.log("superclass: checkValidOverride("
-            "${classBuilder.fullNameForErrors}, "
-            "${a.fullName}, ${b.fullName})");
-        checkValidOverride(
-            a, AbstractMemberOverridingImplementation.selectAbstract(b));
-
-        if (a.isAbstract) {
-          if (b.isAbstract) {
-            recordAbstractMember(a);
-          } else {
-            if (!classBuilder.isAbstract) {
-              // The interface of this class is [a]. But the implementation is
-              // [b]. So [b] must implement [a], unless [cls] is abstract.
-              checkValidOverride(b, a);
-            }
-            ClassMember concrete =
-                AbstractMemberOverridingImplementation.selectConcrete(b);
-            result = new AbstractMemberOverridingImplementation(
-                classBuilder,
-                a,
-                concrete,
-                a.isProperty,
-                mergeKind.forSetters,
-                shouldModifyKernel,
-                concrete.isAbstract,
-                concrete.name);
-            hierarchy.delayedMemberChecks.add(result);
-          }
-        } else if (classBuilder.isMixinApplication &&
-            a.classBuilder != classBuilder) {
-          result = InheritedImplementationInterfaceConflict.combined(
-              classBuilder, a, b, mergeKind.forSetters, shouldModifyKernel,
-              isInheritableConflict: false);
-          if (result is DelayedMember) {
-            hierarchy.delayedMemberChecks.add(result);
-          }
-        }
-
-        if (result.name == noSuchMethodName &&
-            !result.isObjectMember(objectClass)) {
-          hasNoSuchMethod = true;
-        }
-        break;
-
-      case MergeKind.membersWithSetters:
-      case MergeKind.settersWithMembers:
-        if (a.classBuilder == classBuilder && b.classBuilder != classBuilder) {
-          if (a is SourceFieldMember) {
-            if (a.isFinal && b.isSetter) {
-              hierarchy.overrideChecks
-                  .add(new DelayedOverrideCheck(classBuilder, a, b));
-            } else {
-              hierarchy.delayedSignatureComputations
-                  .add(new DelayedFieldTypeInference(this, a, b));
-              // TODO(johnniwinther): Only add override check if field type
-              // inference needs it.
-              hierarchy.overrideChecks
-                  .add(new DelayedOverrideCheck(classBuilder, a, b));
-            }
-          } else if (a is SourceProcedureMember) {
-            hierarchy.delayedSignatureComputations
-                .add(new DelayedMethodTypeInference(this, a, b));
-            // TODO(johnniwinther): Only add override check if method type
-            // inference needs it.
-            hierarchy.overrideChecks
-                .add(new DelayedOverrideCheck(classBuilder, a, b));
-          }
-        }
-        break;
-
-      case MergeKind.interfacesMembers:
-        result = InterfaceConflict.combined(
-            classBuilder, a, b, false, shouldModifyKernel);
-        break;
-
-      case MergeKind.interfacesSetters:
-        result = InterfaceConflict.combined(
-            classBuilder, a, b, true, shouldModifyKernel);
-        break;
-
-      case MergeKind.supertypesMembers:
-      case MergeKind.supertypesSetters:
-        // [b] is inherited from an interface so it is implicitly abstract.
-
-        a = AbstractMemberOverridingImplementation.selectAbstract(a);
-        b = AbstractMemberOverridingImplementation.selectAbstract(b);
-
-        // If [a] is declared in this class, it defines the interface.
-        if (a.classBuilder == classBuilder) {
-          debug?.log("supertypes: checkValidOverride("
-              "${classBuilder.fullNameForErrors}, "
-              "${a.fullName}, ${b.fullName})");
-          if (a is! DelayedMember) {
-            checkValidOverride(a, b);
-          }
-          if (a is DelayedMember) {
-            if (b is DelayedMember) {
-              b.addAllDeclarationsTo(a.declarations);
-            } else {
-              addDeclarationIfDifferent(b, a.declarations);
-            }
-          }
-        } else {
-          if (a.isAbstract) {
-            result = InterfaceConflict.combined(
-                classBuilder, a, b, mergeKind.forSetters, shouldModifyKernel);
-          } else {
-            result = InheritedImplementationInterfaceConflict.combined(
-                classBuilder, a, b, mergeKind.forSetters, shouldModifyKernel);
-          }
-          debug?.log("supertypes: ${result}");
-          if (result is DelayedMember) {
-            hierarchy.delayedMemberChecks.add(result);
-          }
-        }
-        break;
-    }
-
-    return result;
-  }
-
   ClassMember checkInheritanceConflict(ClassMember a, ClassMember b) {
-    if (a is DelayedMember) {
+    if (a.hasDeclarations) {
       ClassMember result;
       for (int i = 0; i < a.declarations.length; i++) {
         ClassMember d = checkInheritanceConflict(a.declarations[i], b);
@@ -609,7 +649,7 @@
       }
       return result;
     }
-    if (b is DelayedMember) {
+    if (b.hasDeclarations) {
       ClassMember result;
       for (int i = 0; i < b.declarations.length; i++) {
         ClassMember d = checkInheritanceConflict(a, b.declarations[i]);
@@ -624,476 +664,562 @@
     return null;
   }
 
-  bool inferMethodTypes(
-      ClassHierarchyBuilder hierarchy, SourceProcedureMember a, ClassMember b) {
-    debug
-        ?.log("Trying to infer types for ${a.fullName} based on ${b.fullName}");
-    if (b is DelayedMember) {
-      bool hasSameSignature = true;
-      List<ClassMember> declarations = b.declarations;
-      for (int i = 0; i < declarations.length; i++) {
-        if (!inferMethodTypes(hierarchy, a, declarations[i])) {
-          hasSameSignature = false;
+  static void inferMethodType(
+      ClassHierarchyBuilder hierarchy,
+      ClassBuilder classBuilder,
+      Map<Class, Substitution> substitutions,
+      SourceProcedureBuilder declaredMember,
+      Iterable<ClassMember> overriddenMembers) {
+    assert(!declaredMember.isGetter && !declaredMember.isSetter);
+    Procedure declaredProcedure = declaredMember.member;
+    FunctionNode declaredFunction = declaredProcedure.function;
+    List<TypeParameter> declaredTypeParameters =
+        declaredFunction.typeParameters;
+    List<VariableDeclaration> declaredPositional =
+        declaredFunction.positionalParameters;
+    List<VariableDeclaration> declaredNamed = declaredFunction.namedParameters;
+    if (declaredMember.classBuilder == classBuilder &&
+        (declaredMember.returnType == null ||
+            declaredMember.formals != null &&
+                declaredMember.formals
+                    .any((parameter) => parameter.type == null))) {
+      for (ClassMember overriddenMember
+          in toSet(declaredMember.classBuilder, overriddenMembers)) {
+        assert(useConsolidated || !overriddenMember.hasDeclarations);
+        int hadTypesInferredFrom = declaredMember.hadTypesInferredFrom;
+        Member bMember = overriddenMember.getMember(hierarchy);
+        Substitution bSubstitution;
+        if (classBuilder.cls != bMember.enclosingClass) {
+          assert(
+              substitutions.containsKey(bMember.enclosingClass),
+              "No substitution found for '${classBuilder.fullNameForErrors}' "
+              "as instance of '${bMember.enclosingClass.name}'. Substitutions "
+              "available for: ${substitutions.keys}");
+          bSubstitution = substitutions[bMember.enclosingClass];
+          debug?.log("${classBuilder.fullNameForErrors} -> "
+              "${bMember.enclosingClass.name} $bSubstitution");
         }
-      }
-      return hasSameSignature;
-    }
-    if (a.isGetter) {
-      return inferGetterType(hierarchy, a, b);
-    } else if (a.isSetter) {
-      return inferSetterType(hierarchy, a, b);
-    }
-    int hadTypesInferredFrom = a.hadTypesInferredFrom;
-    ClassBuilder bClassBuilder = b.classBuilder;
-    Substitution bSubstitution;
-    if (classBuilder != bClassBuilder) {
-      assert(
-          substitutions.containsKey(bClassBuilder.cls),
-          "No substitution found for '${classBuilder.fullNameForErrors}' as "
-          "instance of '${bClassBuilder.fullNameForErrors}'. Substitutions "
-          "available for: ${substitutions.keys}");
-      bSubstitution = substitutions[bClassBuilder.cls];
-      debug?.log("${classBuilder.fullNameForErrors} -> "
-          "${bClassBuilder.fullNameForErrors} $bSubstitution");
-    }
-    Procedure aProcedure = a.getMember(hierarchy);
-    Member bMember = b.getMember(hierarchy);
-    if (bMember is! Procedure) {
-      debug?.log("Giving up 1");
-      return false;
-    }
-    Procedure bProcedure = bMember;
-    FunctionNode aFunction = aProcedure.function;
-    FunctionNode bFunction = bProcedure.function;
+        if (bMember is! Procedure) {
+          debug?.log("Giving up 1");
+          continue;
+        }
+        Procedure bProcedure = bMember;
+        FunctionNode bFunction = bProcedure.function;
 
-    List<TypeParameter> aTypeParameters = aFunction.typeParameters;
-    List<TypeParameter> bTypeParameters = bFunction.typeParameters;
-    int typeParameterCount = aTypeParameters.length;
-    if (typeParameterCount != bTypeParameters.length) {
-      debug?.log("Giving up 2");
-      return false;
-    }
-    Substitution substitution;
-    if (typeParameterCount != 0) {
-      for (int i = 0; i < typeParameterCount; i++) {
-        copyTypeParameterCovariance(
-            a.classBuilder, aTypeParameters[i], bTypeParameters[i]);
-      }
-      List<DartType> types = new List<DartType>(typeParameterCount);
-      for (int i = 0; i < typeParameterCount; i++) {
-        types[i] = new TypeParameterType.forAlphaRenaming(
-            bTypeParameters[i], aTypeParameters[i]);
-      }
-      substitution = Substitution.fromPairs(bTypeParameters, types);
-      for (int i = 0; i < typeParameterCount; i++) {
-        DartType aBound = aTypeParameters[i].bound;
-        DartType bBound = substitution.substituteType(bTypeParameters[i].bound);
-        if (!hierarchy.types
-            .isSameTypeKernel(aBound, bBound)
-            .isSubtypeWhenUsingNullabilities()) {
-          debug?.log("Giving up 3");
-          return false;
+        List<TypeParameter> bTypeParameters = bFunction.typeParameters;
+        int typeParameterCount = declaredTypeParameters.length;
+        if (typeParameterCount != bTypeParameters.length) {
+          debug?.log("Giving up 2");
+          continue;
+        }
+        Substitution substitution;
+        if (typeParameterCount != 0) {
+          List<DartType> types = new List<DartType>(typeParameterCount);
+          for (int i = 0; i < typeParameterCount; i++) {
+            types[i] = new TypeParameterType.forAlphaRenaming(
+                bTypeParameters[i], declaredTypeParameters[i]);
+          }
+          substitution = Substitution.fromPairs(bTypeParameters, types);
+          for (int i = 0; i < typeParameterCount; i++) {
+            DartType aBound = declaredTypeParameters[i].bound;
+            DartType bBound =
+                substitution.substituteType(bTypeParameters[i].bound);
+            if (!hierarchy.types
+                .isSameTypeKernel(aBound, bBound)
+                .isSubtypeWhenUsingNullabilities()) {
+              debug?.log("Giving up 3");
+              continue;
+            }
+          }
+        }
+
+        DartType bReturnType = bFunction.returnType;
+        if (bSubstitution != null) {
+          bReturnType = bSubstitution.substituteType(bReturnType);
+        }
+        if (substitution != null) {
+          bReturnType = substitution.substituteType(bReturnType);
+        }
+        if (declaredFunction.requiredParameterCount >
+            bFunction.requiredParameterCount) {
+          debug?.log("Giving up 4");
+          continue;
+        }
+        List<VariableDeclaration> bPositional = bFunction.positionalParameters;
+        if (declaredPositional.length < bPositional.length) {
+          debug?.log("Giving up 5");
+          continue;
+        }
+
+        if (declaredMember.classBuilder == classBuilder &&
+            declaredMember.returnType == null) {
+          inferReturnType(
+              classBuilder,
+              declaredMember,
+              declaredMember.member.function,
+              bReturnType,
+              hadTypesInferredFrom,
+              SourceProcedureBuilder.inferredTypesFromMethod,
+              hierarchy);
+        } else {
+          debug?.log("Giving up 6");
+        }
+
+        for (int i = 0; i < bPositional.length; i++) {
+          VariableDeclaration bParameter = bPositional[i];
+          if (declaredMember.classBuilder == classBuilder &&
+              declaredMember.formals[i].type == null) {
+            DartType bType = bParameter.type;
+            if (bSubstitution != null) {
+              bType = bSubstitution.substituteType(bType);
+            }
+            if (substitution != null) {
+              bType = substitution.substituteType(bType);
+            }
+            if (hierarchy.coreTypes.objectClass.enclosingLibrary
+                    .isNonNullableByDefault &&
+                !declaredMember.classBuilder.library.isNonNullableByDefault &&
+                bProcedure == hierarchy.coreTypes.objectEquals) {
+              // In legacy code we special case `Object.==` to infer `dynamic`
+              // instead `Object!`.
+              bType = const DynamicType();
+            }
+            inferParameterType(
+                classBuilder,
+                declaredMember,
+                declaredMember.formals[i],
+                bType,
+                hadTypesInferredFrom,
+                SourceProcedureBuilder.inferredTypesFromMethod,
+                hierarchy);
+          } else {
+            debug?.log("Giving up 8");
+          }
+        }
+
+        List<VariableDeclaration> bNamed = bFunction.namedParameters;
+        named:
+        if (declaredNamed.isNotEmpty || bNamed.isNotEmpty) {
+          if (declaredPositional.length != bPositional.length) {
+            debug?.log("Giving up 9");
+            break named;
+          }
+          if (declaredFunction.requiredParameterCount !=
+              bFunction.requiredParameterCount) {
+            debug?.log("Giving up 10");
+            break named;
+          }
+
+          declaredNamed = declaredNamed.toList()..sort(compareNamedParameters);
+          bNamed = bNamed.toList()..sort(compareNamedParameters);
+          int aCount = 0;
+          for (int bCount = 0; bCount < bNamed.length; bCount++) {
+            String name = bNamed[bCount].name;
+            for (; aCount < declaredNamed.length; aCount++) {
+              if (declaredNamed[aCount].name == name) break;
+            }
+            if (aCount == declaredNamed.length) {
+              debug?.log("Giving up 11");
+              break named;
+            }
+            FormalParameterBuilder parameter;
+            for (int i = declaredPositional.length;
+                i < declaredMember.formals.length;
+                ++i) {
+              if (declaredMember.formals[i].name == name) {
+                parameter = declaredMember.formals[i];
+                break;
+              }
+            }
+            VariableDeclaration bParameter = bNamed[bCount];
+
+            if (declaredMember.classBuilder == classBuilder &&
+                parameter.type == null) {
+              DartType bType = bParameter.type;
+              if (bSubstitution != null) {
+                bType = bSubstitution.substituteType(bType);
+              }
+              if (substitution != null) {
+                bType = substitution.substituteType(bType);
+              }
+              inferParameterType(
+                  classBuilder,
+                  declaredMember,
+                  parameter,
+                  bType,
+                  hadTypesInferredFrom,
+                  SourceProcedureBuilder.inferredTypesFromMethod,
+                  hierarchy);
+            } else {
+              debug?.log("Giving up 12");
+            }
+          }
         }
       }
     }
+  }
 
-    DartType bReturnType = bFunction.returnType;
-    if (bSubstitution != null) {
-      bReturnType = bSubstitution.substituteType(bReturnType);
-    }
-    if (substitution != null) {
-      bReturnType = substitution.substituteType(bReturnType);
-    }
-    bool hasSameSignature = true;
-    if (aFunction.requiredParameterCount > bFunction.requiredParameterCount) {
-      debug?.log("Giving up 4");
-      return false;
-    }
-    List<VariableDeclaration> aPositional = aFunction.positionalParameters;
-    List<VariableDeclaration> bPositional = bFunction.positionalParameters;
-    if (aPositional.length < bPositional.length) {
-      debug?.log("Giving up 5");
-      return false;
-    }
+  void inferMethodSignature(ClassHierarchyBuilder hierarchy,
+      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
+    assert(!declaredMember.isGetter && !declaredMember.isSetter);
+    // Trigger computation of method type.
+    Procedure declaredProcedure = declaredMember.getMember(hierarchy);
+    FunctionNode declaredFunction = declaredProcedure.function;
+    List<TypeParameter> declaredTypeParameters =
+        declaredFunction.typeParameters;
+    List<VariableDeclaration> declaredPositional =
+        declaredFunction.positionalParameters;
+    List<VariableDeclaration> declaredNamed = declaredFunction.namedParameters;
+    for (ClassMember overriddenMember
+        in toSet(declaredMember.classBuilder, overriddenMembers)) {
+      assert(useConsolidated || !overriddenMember.hasDeclarations);
+      Member bMember = overriddenMember.getMember(hierarchy);
+      if (bMember is! Procedure) {
+        debug?.log("Giving up 1");
+        continue;
+      }
+      Procedure bProcedure = bMember;
+      FunctionNode bFunction = bProcedure.function;
 
-    if (a.classBuilder == classBuilder && a.returnType == null) {
-      hasSameSignature = inferReturnType(
-          classBuilder,
-          a,
-          bReturnType,
-          hadTypesInferredFrom,
-          SourceProcedureMember.inferredTypesFromMethod,
-          hierarchy);
-    } else {
-      debug?.log("Giving up 6");
-      hasSameSignature = false;
-    }
+      List<TypeParameter> bTypeParameters = bFunction.typeParameters;
+      int typeParameterCount = declaredTypeParameters.length;
+      if (typeParameterCount != bTypeParameters.length) {
+        debug?.log("Giving up 2");
+        continue;
+      }
+      if (typeParameterCount != 0) {
+        for (int i = 0; i < typeParameterCount; i++) {
+          copyTypeParameterCovariance(declaredMember.classBuilder,
+              declaredTypeParameters[i], bTypeParameters[i]);
+        }
+      }
 
-    for (int i = 0; i < bPositional.length; i++) {
-      VariableDeclaration aParameter = aPositional[i];
-      VariableDeclaration bParameter = bPositional[i];
-      copyParameterCovariance(a.classBuilder, aParameter, bParameter);
-      if (a.classBuilder == classBuilder && a.formals[i].type == null) {
-        DartType bType = bParameter.type;
+      if (declaredFunction.requiredParameterCount >
+          bFunction.requiredParameterCount) {
+        debug?.log("Giving up 4");
+        continue;
+      }
+      List<VariableDeclaration> bPositional = bFunction.positionalParameters;
+      if (declaredPositional.length < bPositional.length) {
+        debug?.log("Giving up 5");
+        continue;
+      }
+
+      for (int i = 0; i < bPositional.length; i++) {
+        VariableDeclaration aParameter = declaredPositional[i];
+        VariableDeclaration bParameter = bPositional[i];
+        copyParameterCovariance(
+            declaredMember.classBuilder, aParameter, bParameter);
+      }
+
+      List<VariableDeclaration> bNamed = bFunction.namedParameters;
+      named:
+      if (declaredNamed.isNotEmpty || bNamed.isNotEmpty) {
+        if (declaredPositional.length != bPositional.length) {
+          debug?.log("Giving up 9");
+          break named;
+        }
+        if (declaredFunction.requiredParameterCount !=
+            bFunction.requiredParameterCount) {
+          debug?.log("Giving up 10");
+          break named;
+        }
+
+        declaredNamed = declaredNamed.toList()..sort(compareNamedParameters);
+        bNamed = bNamed.toList()..sort(compareNamedParameters);
+        int aCount = 0;
+        for (int bCount = 0; bCount < bNamed.length; bCount++) {
+          String name = bNamed[bCount].name;
+          for (; aCount < declaredNamed.length; aCount++) {
+            if (declaredNamed[aCount].name == name) break;
+          }
+          if (aCount == declaredNamed.length) {
+            debug?.log("Giving up 11");
+            break named;
+          }
+          VariableDeclaration aParameter = declaredNamed[aCount];
+          VariableDeclaration bParameter = bNamed[bCount];
+          copyParameterCovariance(
+              declaredMember.classBuilder, aParameter, bParameter);
+        }
+      }
+    }
+  }
+
+  void inferGetterSignature(ClassHierarchyBuilder hierarchy,
+      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
+    assert(declaredMember.isGetter);
+    // Trigger computation of the getter type.
+    declaredMember.getMember(hierarchy);
+    // Otherwise nothing to do. Getters have no variance.
+  }
+
+  void inferSetterSignature(ClassHierarchyBuilder hierarchy,
+      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
+    assert(declaredMember.isSetter);
+    // Trigger computation of the getter type.
+    Procedure declaredSetter = declaredMember.getMember(hierarchy);
+    VariableDeclaration setterParameter =
+        declaredSetter.function.positionalParameters.single;
+    for (ClassMember overriddenMember
+        in toSet(declaredMember.classBuilder, overriddenMembers)) {
+      Member bTarget = overriddenMember.getMember(hierarchy);
+      if (bTarget is Field) {
+        copyParameterCovarianceFromField(
+            declaredMember.classBuilder, setterParameter, bTarget);
+      } else if (bTarget is Procedure) {
+        if (overriddenMember.isSetter) {
+          VariableDeclaration bParameter =
+              bTarget.function.positionalParameters.single;
+          copyParameterCovariance(
+              declaredMember.classBuilder, setterParameter, bParameter);
+        } else if (overriddenMember.isGetter) {
+          // No variance to copy from getter.
+        } else {
+          debug?.log("Giving up (not accessor: ${bTarget.kind})");
+          continue;
+        }
+      } else {
+        debug?.log("Giving up (not field/procedure: ${bTarget.runtimeType})");
+        return;
+      }
+    }
+  }
+
+  static void inferGetterType(
+      ClassHierarchyBuilder hierarchy,
+      ClassBuilder classBuilder,
+      Map<Class, Substitution> substitutions,
+      SourceProcedureBuilder declaredMember,
+      Iterable<ClassMember> overriddenMembers) {
+    assert(declaredMember.isGetter);
+    if (declaredMember.classBuilder == classBuilder &&
+        declaredMember.returnType == null) {
+      for (ClassMember overriddenMember
+          in toSet(declaredMember.classBuilder, overriddenMembers)) {
+        int hadTypesInferredFrom = declaredMember.hadTypesInferredFrom;
+        Member bTarget = overriddenMember.getMember(hierarchy);
+        Substitution bSubstitution;
+        if (classBuilder.cls != bTarget.enclosingClass) {
+          assert(
+              substitutions.containsKey(bTarget.enclosingClass),
+              "No substitution found for '${classBuilder.fullNameForErrors}' "
+              "as instance of '${bTarget.enclosingClass.name}'. Substitutions "
+              "available for: ${substitutions.keys}");
+          bSubstitution = substitutions[bTarget.enclosingClass];
+        }
+        DartType bType;
+        int inferTypesFrom;
+        if (bTarget is Field) {
+          bType = bTarget.type;
+          assert(bType is! ImplicitFieldType);
+          inferTypesFrom = SourceProcedureBuilder.inferredTypesFromField;
+        } else if (bTarget is Procedure) {
+          if (bTarget.kind == ProcedureKind.Setter) {
+            VariableDeclaration bParameter =
+                bTarget.function.positionalParameters.single;
+            bType = bParameter.type;
+            inferTypesFrom = SourceProcedureBuilder.inferredTypesFromSetter;
+          } else if (bTarget.kind == ProcedureKind.Getter) {
+            bType = bTarget.function.returnType;
+            inferTypesFrom = SourceProcedureBuilder.inferredTypesFromGetter;
+          } else {
+            debug?.log("Giving up (not accessor: ${bTarget.kind})");
+            continue;
+          }
+        } else {
+          debug?.log("Giving up (not field/procedure: ${bTarget.runtimeType})");
+          continue;
+        }
         if (bSubstitution != null) {
           bType = bSubstitution.substituteType(bType);
         }
-        if (substitution != null) {
-          bType = substitution.substituteType(bType);
-        }
-        if (hierarchy.coreTypes.objectClass.enclosingLibrary
-                .isNonNullableByDefault &&
-            !a.classBuilder.library.isNonNullableByDefault &&
-            bProcedure == hierarchy.coreTypes.objectEquals) {
-          // In legacy code we special case `Object.==` to infer `dynamic`
-          // instead `Object!`.
-          bType = const DynamicType();
-        }
-        hasSameSignature &= inferParameterType(
+        inferReturnType(
             classBuilder,
-            a,
-            a.formals[i],
+            declaredMember,
+            declaredMember.member.function,
             bType,
             hadTypesInferredFrom,
-            SourceProcedureMember.inferredTypesFromMethod,
+            inferTypesFrom,
             hierarchy);
-      } else {
-        debug?.log("Giving up 8");
-        hasSameSignature = false;
       }
     }
-
-    List<VariableDeclaration> aNamed = aFunction.namedParameters;
-    List<VariableDeclaration> bNamed = bFunction.namedParameters;
-    named:
-    if (aNamed.isNotEmpty || bNamed.isNotEmpty) {
-      if (aPositional.length != bPositional.length) {
-        debug?.log("Giving up 9");
-        hasSameSignature = false;
-        break named;
-      }
-      if (aFunction.requiredParameterCount !=
-          bFunction.requiredParameterCount) {
-        debug?.log("Giving up 10");
-        hasSameSignature = false;
-        break named;
-      }
-
-      aNamed = aNamed.toList()..sort(compareNamedParameters);
-      bNamed = bNamed.toList()..sort(compareNamedParameters);
-      int aCount = 0;
-      for (int bCount = 0; bCount < bNamed.length; bCount++) {
-        String name = bNamed[bCount].name;
-        for (; aCount < aNamed.length; aCount++) {
-          if (aNamed[aCount].name == name) break;
-        }
-        if (aCount == aNamed.length) {
-          debug?.log("Giving up 11");
-          hasSameSignature = false;
-          break named;
-        }
-        FormalParameterBuilder parameter;
-        for (int i = aPositional.length; i < a.formals.length; ++i) {
-          if (a.formals[i].name == name) {
-            parameter = a.formals[i];
-            break;
-          }
-        }
-        VariableDeclaration aParameter = aNamed[aCount];
-        VariableDeclaration bParameter = bNamed[bCount];
-        copyParameterCovariance(a.classBuilder, aParameter, bParameter);
-
-        if (a.classBuilder == classBuilder && parameter.type == null) {
-          DartType bType = bParameter.type;
-          if (bSubstitution != null) {
-            bType = bSubstitution.substituteType(bType);
-          }
-          if (substitution != null) {
-            bType = substitution.substituteType(bType);
-          }
-          hasSameSignature &= inferParameterType(
-              classBuilder,
-              a,
-              parameter,
-              bType,
-              hadTypesInferredFrom,
-              SourceProcedureMember.inferredTypesFromMethod,
-              hierarchy);
-        } else {
-          debug?.log("Giving up 12");
-          hasSameSignature = false;
-        }
-      }
-    }
-    debug?.log("Inferring types for ${a.fullName} based on ${b.fullName} " +
-        (hasSameSignature ? "succeeded." : "failed."));
-    return hasSameSignature;
-  }
-
-  bool inferGetterType(
-      ClassHierarchyBuilder hierarchy, SourceProcedureMember a, ClassMember b) {
-    debug?.log(
-        "Inferring getter types for ${a.fullName} based on ${b.fullName}");
-    int hadTypesInferredFrom = a.hadTypesInferredFrom;
-    ClassBuilder bClassBuilder = b.classBuilder;
-    Substitution bSubstitution;
-    if (classBuilder != bClassBuilder) {
-      assert(
-          substitutions.containsKey(bClassBuilder.cls),
-          "No substitution found for '${classBuilder.fullNameForErrors}' as "
-          "instance of '${bClassBuilder.fullNameForErrors}'. Substitutions "
-          "available for: ${substitutions.keys}");
-      bSubstitution = substitutions[bClassBuilder.cls];
-      debug?.log("${classBuilder.fullNameForErrors} -> "
-          "${bClassBuilder.fullNameForErrors} $bSubstitution");
-    }
-    Member bTarget = b.getMember(hierarchy);
-    DartType bType;
-    int inferTypesFrom;
-    if (bTarget is Field) {
-      bType = bTarget.type;
-      if (bType is ImplicitFieldType) {
-        debug?.log("Giving up (type may be inferred)");
-        return false;
-      }
-      inferTypesFrom = SourceProcedureMember.inferredTypesFromField;
-    } else if (bTarget is Procedure) {
-      if (b.isSetter) {
-        VariableDeclaration bParameter =
-            bTarget.function.positionalParameters.single;
-        bType = bParameter.type;
-        if (!b.hasExplicitlyTypedFormalParameter(0)) {
-          debug?.log("Giving up (type may be inferred)");
-          return false;
-        }
-        inferTypesFrom = SourceProcedureMember.inferredTypesFromSetter;
-      } else if (b.isGetter) {
-        bType = bTarget.function.returnType;
-        if (!b.hasExplicitReturnType) {
-          debug?.log("Giving up (return type may be inferred)");
-          return false;
-        }
-        inferTypesFrom = SourceProcedureMember.inferredTypesFromGetter;
-      } else {
-        debug?.log("Giving up (not accessor: ${bTarget.kind})");
-        return false;
-      }
-    } else {
-      debug?.log("Giving up (not field/procedure: ${bTarget.runtimeType})");
-      return false;
-    }
-    if (a.classBuilder == classBuilder && a.returnType == null) {
-      if (bSubstitution != null) {
-        bType = bSubstitution.substituteType(bType);
-      }
-      return inferReturnType(classBuilder, a, bType, hadTypesInferredFrom,
-          inferTypesFrom, hierarchy);
-    }
-    return false;
-  }
-
-  bool inferSetterType(
-      ClassHierarchyBuilder hierarchy, SourceProcedureMember a, ClassMember b) {
-    debug?.log(
-        "Inferring setter types for ${a.fullName} based on ${b.fullName}");
-    int hadTypesInferredFrom = a.hadTypesInferredFrom;
-    ClassBuilder bClassBuilder = b.classBuilder;
-    Substitution bSubstitution;
-    if (classBuilder != bClassBuilder) {
-      assert(
-          substitutions.containsKey(bClassBuilder.cls),
-          "No substitution found for '${classBuilder.fullNameForErrors}' as "
-          "instance of '${bClassBuilder.fullNameForErrors}'. Substitutions "
-          "available for: ${substitutions.keys}");
-      bSubstitution = substitutions[bClassBuilder.cls];
-      debug?.log("${classBuilder.fullNameForErrors} -> "
-          "${bClassBuilder.fullNameForErrors} $bSubstitution");
-    }
-    Member bTarget = b.getMember(hierarchy);
-    Procedure aProcedure = a.getMember(hierarchy);
-    VariableDeclaration aParameter =
-        aProcedure.function.positionalParameters.single;
-    DartType bType;
-    int inferTypesFrom;
-    if (bTarget is Field) {
-      bType = bTarget.type;
-      copyParameterCovarianceFromField(a.classBuilder, aParameter, bTarget);
-      if (bType is ImplicitFieldType) {
-        debug?.log("Giving up (type may be inferred)");
-        return false;
-      }
-      inferTypesFrom = SourceProcedureMember.inferredTypesFromField;
-    } else if (bTarget is Procedure) {
-      if (b.isSetter) {
-        VariableDeclaration bParameter =
-            bTarget.function.positionalParameters.single;
-        bType = bParameter.type;
-        copyParameterCovariance(a.classBuilder, aParameter, bParameter);
-        if (!b.hasExplicitlyTypedFormalParameter(0)) {
-          debug?.log("Giving up (type may be inferred)");
-          return false;
-        }
-        inferTypesFrom = SourceProcedureMember.inferredTypesFromSetter;
-      } else if (b.isGetter) {
-        bType = bTarget.function.returnType;
-        if (!b.hasExplicitReturnType) {
-          debug?.log("Giving up (return type may be inferred)");
-          return false;
-        }
-        inferTypesFrom = SourceProcedureMember.inferredTypesFromGetter;
-      } else {
-        debug?.log("Giving up (not accessor: ${bTarget.kind})");
-        return false;
-      }
-    } else {
-      debug?.log("Giving up (not field/procedure: ${bTarget.runtimeType})");
-      return false;
-    }
-    FormalParameterBuilder parameter = a.formals.first;
-    if (a.classBuilder == classBuilder && parameter.type == null) {
-      if (bSubstitution != null) {
-        bType = bSubstitution.substituteType(bType);
-      }
-      return inferParameterType(classBuilder, a, parameter, bType,
-          hadTypesInferredFrom, inferTypesFrom, hierarchy);
-    }
-    return false;
-  }
-
-  void checkValidOverride(ClassMember a, ClassMember b) {
-    debug?.log(
-        "checkValidOverride(${a.fullName}, ${b.fullName}) ${a.runtimeType}");
-    if (a is SourceProcedureMember) {
-      // TODO(johnniwinther): Only add override check if method type
-      // inference needs it.
-      hierarchy.delayedSignatureComputations
-          .add(new DelayedMethodTypeInference(this, a, b));
-    } else if (a.isField) {
-      // TODO(johnniwinther): Only add override check if field type
-      // inference needs it.
-      hierarchy.delayedSignatureComputations
-          .add(new DelayedFieldTypeInference(this, a, b));
-    }
-    // TODO(johnniwinther): Only add override check if needed.
-
-    if (b is DelayedMember) {
-      for (int i = 0; i < b.declarations.length; i++) {
-        hierarchy.overrideChecks
-            .add(new DelayedOverrideCheck(classBuilder, a, b.declarations[i]));
-      }
-    } else {
-      hierarchy.overrideChecks
-          .add(new DelayedOverrideCheck(classBuilder, a, b));
-    }
   }
 
-  /// Infers the field type of [a] based on [b]. Returns `true` if the type of
-  /// [a] is known to be a valid override of [b], meaning that no additional
-  /// override checks are needed.
-  bool inferFieldTypes(
-      ClassHierarchyBuilder hierarchy, ClassMember a, ClassMember b) {
-    debug?.log("Trying to infer field types for ${a.fullName} "
-        "based on ${b.fullName}");
-    if (b is DelayedMember) {
-      bool hasSameSignature = true;
-      List<ClassMember> declarations = b.declarations;
-      for (int i = 0; i < declarations.length; i++) {
-        if (!inferFieldTypes(hierarchy, a, declarations[i])) {
-          hasSameSignature = false;
+  static void inferSetterType(
+      ClassHierarchyBuilder hierarchy,
+      ClassBuilder classBuilder,
+      Map<Class, Substitution> substitutions,
+      SourceProcedureBuilder declaredMember,
+      Iterable<ClassMember> overriddenMembers) {
+    assert(declaredMember.isSetter);
+    FormalParameterBuilder parameter = declaredMember.formals.first;
+    if (declaredMember.classBuilder == classBuilder && parameter.type == null) {
+      for (ClassMember overriddenMember
+          in toSet(declaredMember.classBuilder, overriddenMembers)) {
+        int hadTypesInferredFrom = declaredMember.hadTypesInferredFrom;
+        Member bTarget = overriddenMember.getMember(hierarchy);
+        Substitution bSubstitution;
+        if (classBuilder.cls != bTarget.enclosingClass) {
+          assert(
+              substitutions.containsKey(bTarget.enclosingClass),
+              "No substitution found for '${classBuilder.fullNameForErrors}' "
+              "as instance of '${bTarget.enclosingClass.name}'. Substitutions "
+              "available for: ${substitutions.keys}");
+          bSubstitution = substitutions[bTarget.enclosingClass];
         }
-      }
-      return hasSameSignature;
-    }
-    Member bTarget = b.getMember(hierarchy);
-    DartType inheritedType;
-    if (bTarget is Procedure) {
-      if (bTarget.isSetter) {
-        VariableDeclaration parameter =
-            bTarget.function.positionalParameters.single;
-        // inheritedType = parameter.type;
-        copyFieldCovarianceFromParameter(
-            a.classBuilder, a.getMember(hierarchy), parameter);
-        if (!b.hasExplicitlyTypedFormalParameter(0)) {
-          debug?.log("Giving up (type may be inferred)");
-          return false;
-        }
-      } else if (bTarget.isGetter) {
-        if (!b.hasExplicitReturnType) return false;
-        inheritedType = bTarget.function.returnType;
-      }
-    } else if (bTarget is Field) {
-      copyFieldCovariance(a.classBuilder, a.getMember(hierarchy), bTarget);
-      inheritedType = bTarget.type;
-    }
-    if (inheritedType == null) {
-      debug?.log("Giving up (inheritedType == null)\n${StackTrace.current}");
-      return false;
-    }
-    ClassBuilder aClassBuilder = a.classBuilder;
-    Substitution aSubstitution;
-    if (classBuilder != aClassBuilder) {
-      assert(
-          substitutions.containsKey(aClassBuilder.cls),
-          "${classBuilder.fullNameForErrors} "
-          "${aClassBuilder.fullNameForErrors}");
-      aSubstitution = substitutions[aClassBuilder.cls];
-      debug?.log("${classBuilder.fullNameForErrors} -> "
-          "${aClassBuilder.fullNameForErrors} $aSubstitution");
-    }
-    ClassBuilder bClassBuilder = b.classBuilder;
-    Substitution bSubstitution;
-    if (classBuilder != bClassBuilder) {
-      assert(
-          substitutions.containsKey(bClassBuilder.cls),
-          "${classBuilder.fullNameForErrors} "
-          "${bClassBuilder.fullNameForErrors}");
-      bSubstitution = substitutions[bClassBuilder.cls];
-      debug?.log("${classBuilder.fullNameForErrors} -> "
-          "${bClassBuilder.fullNameForErrors} $bSubstitution");
-    }
-    if (inheritedType is! ImplicitFieldType) {
-      if (bSubstitution != null) {
-        inheritedType = bSubstitution.substituteType(inheritedType);
-      }
-      if (!a.classBuilder.library.isNonNullableByDefault) {
-        inheritedType = legacyErasure(hierarchy.coreTypes, inheritedType);
-      }
-    }
-
-    Field aField = a.getMember(hierarchy);
-    DartType declaredType = aField.type;
-    if (aSubstitution != null) {
-      declaredType = aSubstitution.substituteType(declaredType);
-    }
-    if (declaredType == inheritedType) return true;
-
-    bool isValidOverride = false;
-    if (a is SourceFieldMember) {
-      if (a.classBuilder == classBuilder && a.type == null) {
-        DartType declaredType = a.fieldType;
-        if (declaredType is ImplicitFieldType) {
-          if (inheritedType is ImplicitFieldType) {
-            declaredType.addOverride(inheritedType);
+        DartType bType;
+        int inferTypesFrom;
+        if (bTarget is Field) {
+          bType = bTarget.type;
+          assert(bType is! ImplicitFieldType);
+          inferTypesFrom = SourceProcedureBuilder.inferredTypesFromField;
+        } else if (bTarget is Procedure) {
+          if (overriddenMember.isSetter) {
+            VariableDeclaration bParameter =
+                bTarget.function.positionalParameters.single;
+            bType = bParameter.type;
+            inferTypesFrom = SourceProcedureBuilder.inferredTypesFromSetter;
+          } else if (overriddenMember.isGetter) {
+            bType = bTarget.function.returnType;
+            inferTypesFrom = SourceProcedureBuilder.inferredTypesFromGetter;
           } else {
-            // The concrete type has already been inferred.
-            a.hadTypesInferred = true;
-            a.fieldType = inheritedType;
-            isValidOverride = true;
-          }
-        } else if (a.hadTypesInferred) {
-          if (inheritedType is! ImplicitFieldType) {
-            // A different type has already been inferred.
-            reportCantInferFieldType(classBuilder, a);
-            a.fieldType = const InvalidType();
+            debug?.log("Giving up (not accessor: ${bTarget.kind})");
+            continue;
           }
         } else {
-          isValidOverride = true;
-          a.hadTypesInferred = true;
-          a.fieldType = inheritedType;
+          debug?.log("Giving up (not field/procedure: ${bTarget.runtimeType})");
+          continue;
         }
+        if (bSubstitution != null) {
+          bType = bSubstitution.substituteType(bType);
+        }
+        inferParameterType(classBuilder, declaredMember, parameter, bType,
+            hadTypesInferredFrom, inferTypesFrom, hierarchy);
       }
     }
-    return isValidOverride;
+  }
+
+  /// Infers the field type of [declaredMember] based on [overriddenMembers].
+  static void inferFieldType(
+      ClassHierarchyBuilder hierarchy,
+      ClassBuilder classBuilder,
+      Map<Class, Substitution> substitutions,
+      SourceFieldBuilder fieldBuilder,
+      Iterable<ClassMember> overriddenMembers) {
+    if (fieldBuilder.classBuilder == classBuilder &&
+        fieldBuilder.type == null) {
+      DartType inferredType;
+
+      void inferFrom(ClassMember overriddenMember) {
+        if (inferredType is InvalidType) return;
+
+        assert(useConsolidated || !overriddenMember.hasDeclarations);
+        Member bTarget = overriddenMember.getMember(hierarchy);
+        DartType inheritedType;
+        if (bTarget is Procedure) {
+          if (bTarget.isSetter) {
+            VariableDeclaration parameter =
+                bTarget.function.positionalParameters.single;
+            inheritedType = parameter.type;
+          } else if (bTarget.isGetter) {
+            inheritedType = bTarget.function.returnType;
+          }
+        } else if (bTarget is Field) {
+          inheritedType = bTarget.type;
+        }
+        if (inheritedType == null) {
+          debug
+              ?.log("Giving up (inheritedType == null)\n${StackTrace.current}");
+          return;
+        }
+        Substitution bSubstitution;
+        if (classBuilder.cls != bTarget.enclosingClass) {
+          assert(
+              substitutions.containsKey(bTarget.enclosingClass),
+              "${classBuilder.fullNameForErrors} "
+              "${bTarget.enclosingClass.name}");
+          bSubstitution = substitutions[bTarget.enclosingClass];
+          debug?.log("${classBuilder.fullNameForErrors} -> "
+              "${bTarget.enclosingClass.name} $bSubstitution");
+        }
+        assert(inheritedType is! ImplicitFieldType);
+        if (bSubstitution != null) {
+          inheritedType = bSubstitution.substituteType(inheritedType);
+        }
+        if (!classBuilder.library.isNonNullableByDefault) {
+          inheritedType = legacyErasure(hierarchy.coreTypes, inheritedType);
+        }
+
+        if (inferredType == null) {
+          inferredType = inheritedType;
+        } else {
+          if (classBuilder.library.isNonNullableByDefault) {
+            DartType topMerge =
+                nnbdTopMerge(hierarchy.coreTypes, inferredType, inheritedType);
+            if (topMerge != null) {
+              inferredType = topMerge;
+              return;
+            }
+          }
+          if (inferredType != inheritedType) {
+            inferredType = const InvalidType();
+            // A different type has already been inferred.
+            reportCantInferFieldType(classBuilder, fieldBuilder);
+          }
+        }
+      }
+
+      overriddenMembers = toSet(classBuilder, overriddenMembers);
+      if (fieldBuilder.isAssignable) {
+        // The field type must be inferred from both getters and setters.
+        for (ClassMember overriddenMember in overriddenMembers) {
+          inferFrom(overriddenMember);
+        }
+      } else {
+        // The field type must be inferred from getters first.
+        for (ClassMember overriddenMember in overriddenMembers) {
+          if (!overriddenMember.forSetter) {
+            inferFrom(overriddenMember);
+          }
+        }
+        if (inferredType == null) {
+          // The field type must be inferred from setters if no type was
+          // inferred from getters.
+          for (ClassMember overriddenMember in overriddenMembers) {
+            if (overriddenMember.forSetter) {
+              inferFrom(overriddenMember);
+            }
+          }
+        }
+      }
+
+      inferredType ??= const DynamicType();
+      fieldBuilder.fieldType = inferredType;
+    }
+  }
+
+  /// Infers the field signature of [declaredMember] based on
+  /// [overriddenMembers].
+  void inferFieldSignature(ClassHierarchyBuilder hierarchy,
+      ClassMember declaredMember, Iterable<ClassMember> overriddenMembers) {
+    Field declaredField = declaredMember.getMember(hierarchy);
+    for (ClassMember overriddenMember
+        in toSet(declaredMember.classBuilder, overriddenMembers)) {
+      assert(useConsolidated || !overriddenMember.hasDeclarations);
+      Member bTarget = overriddenMember.getMember(hierarchy);
+      if (bTarget is Procedure) {
+        if (bTarget.isSetter) {
+          VariableDeclaration parameter =
+              bTarget.function.positionalParameters.single;
+          copyFieldCovarianceFromParameter(
+              declaredMember.classBuilder, declaredField, parameter);
+        }
+      } else if (bTarget is Field) {
+        copyFieldCovariance(
+            declaredMember.classBuilder, declaredField, bTarget);
+      }
+    }
   }
 
   void copyParameterCovariance(Builder parent, VariableDeclaration aParameter,
@@ -1167,7 +1293,7 @@
       } else {
         classBuilder.addProblem(messageInheritedMembersConflict,
             classBuilder.charOffset, classBuilder.fullNameForErrors.length,
-            context: inheritedConflictContext(a, b));
+            context: _inheritedConflictContext(a, b));
       }
     } else if (a.isStatic != b.isStatic) {
       ClassMember staticMember;
@@ -1213,85 +1339,10 @@
     }
   }
 
-  /// When merging `aList` and `bList`, [member] was only found in `aList`.
-  ///
-  /// If [mergeKind] is `MergeKind.superclass` [member] is declared in current
-  /// class, and isn't overriding a method from the superclass.
-  ///
-  /// If [mergeKind] is `MergeKind.interfaces`, [member] is ignored for now.
-  ///
-  /// If [mergeKind] is `MergeKind.supertypes`, [member] isn't
-  /// implementing/overriding anything.
-  ClassMember handleOnlyA(ClassMember member, MergeKind mergeKind) {
-    if (mergeKind.betweenInterfaces) {
-      return member;
-    }
-    // TODO(ahe): Enable this optimization:
-    // if (cls is DillClassBuilder) return;
-    // assert(mergeKind.betweenInterfaces ||
-    //    member is! InterfaceConflict);
-    if ((mergeKind.fromSuperclass) && member.isAbstract) {
-      recordAbstractMember(member);
-    }
-    return member;
-  }
-
-  /// When merging `aList` and `bList`, [member] was only found in `bList`.
-  ///
-  /// If [mergeKind] is `MergeKind.superclass` [member] is being inherited from
-  /// a superclass.
-  ///
-  /// If [mergeKind] is `MergeKind.interfaces`, [member] is ignored for now.
-  ///
-  /// If [mergeKind] is `MergeKind.supertypes`, [member] is implicitly
-  /// abstract, and not implemented.
-  ClassMember handleOnlyB(ClassMember member, MergeKind mergeKind) {
-    if (mergeKind.betweenInterfaces) {
-      return member;
-    }
-    // TODO(ahe): Enable this optimization:
-    // if (cls is DillClassBuilder) return member;
-    if (mergeKind.fromInterfaces ||
-        (mergeKind.fromSuperclass && member.isAbstract)) {
-      if (isNameVisibleIn(member.name, classBuilder.library)) {
-        recordAbstractMember(member);
-      }
-    }
-    if (mergeKind.fromSuperclass &&
-        member.name == noSuchMethodName &&
-        !member.isObjectMember(objectClass)) {
-      hasNoSuchMethod = true;
-    }
-    if (!mergeKind.forMembersVsSetters &&
-        member is DelayedMember &&
-        member.isInheritableConflict) {
-      DelayedMember delayedMember = member;
-      member = delayedMember.withParent(classBuilder);
-      hierarchy.delayedMemberChecks.add(member);
-    }
-    if (mergeKind.intoCurrentClass) {
-      if (member.classBuilder.library.isNonNullableByDefault &&
-          !classBuilder.library.isNonNullableByDefault) {
-        if (member is! DelayedMember) {
-          member = new InterfaceConflict(
-              classBuilder,
-              [member],
-              member.isProperty,
-              mergeKind.forSetters,
-              shouldModifyKernel,
-              member.isAbstract,
-              member.name,
-              isImplicitlyAbstract: member.isAbstract);
-          hierarchy.delayedMemberChecks.add(member);
-        }
-      }
-    }
-    return member;
-  }
-
   void recordAbstractMember(ClassMember member) {
     abstractMembers ??= <ClassMember>[];
-    if (member is DelayedMember) {
+    if (member.hasDeclarations &&
+        (!useConsolidated || classBuilder == member.classBuilder)) {
       abstractMembers.addAll(member.declarations);
     } else {
       abstractMembers.add(member);
@@ -1328,53 +1379,101 @@
       }
     }
 
-    /// Members (excluding setters) declared in [cls].
-    List<ClassMember> localMembers = <ClassMember>[];
-
-    /// Setters declared in [cls].
-    List<ClassMember> localSetters = <ClassMember>[];
+    Map<Name, Tuple> memberMap = {};
 
     for (MemberBuilder memberBuilder in scope.localMembers) {
-      localMembers.addAll(memberBuilder.localMembers);
-      localSetters.addAll(memberBuilder.localSetters);
+      for (ClassMember classMember in memberBuilder.localMembers) {
+        Tuple tuple = memberMap[classMember.name];
+        if (tuple == null) {
+          memberMap[classMember.name] = new Tuple.declareMember(classMember);
+        } else {
+          tuple.declaredMember = classMember;
+        }
+      }
+      for (ClassMember classMember in memberBuilder.localSetters) {
+        Tuple tuple = memberMap[classMember.name];
+        if (tuple == null) {
+          memberMap[classMember.name] = new Tuple.declareSetter(classMember);
+        } else {
+          tuple.declaredSetter = classMember;
+        }
+      }
     }
 
     for (MemberBuilder memberBuilder in scope.localSetters) {
-      localMembers.addAll(memberBuilder.localMembers);
-      localSetters.addAll(memberBuilder.localSetters);
+      for (ClassMember classMember in memberBuilder.localMembers) {
+        Tuple tuple = memberMap[classMember.name];
+        if (tuple == null) {
+          memberMap[classMember.name] = new Tuple.declareMember(classMember);
+        } else {
+          tuple.declaredMember = classMember;
+        }
+      }
+      for (ClassMember classMember in memberBuilder.localSetters) {
+        Tuple tuple = memberMap[classMember.name];
+        if (tuple == null) {
+          memberMap[classMember.name] = new Tuple.declareSetter(classMember);
+        } else {
+          tuple.declaredSetter = classMember;
+        }
+      }
     }
 
-    localMembers.sort(compareDeclarations);
-    localSetters.sort(compareDeclarations);
-
-    /// Members (excluding setters) declared in [cls] or its superclasses. This
-    /// includes static methods of [cls], but not its superclasses.
-    List<ClassMember> classMembers;
-
-    /// Setters declared in [cls] or its superclasses. This includes static
-    /// setters of [cls], but not its superclasses.
-    List<ClassMember> classSetters;
-
-    /// Members (excluding setters) inherited from interfaces. This contains no
-    /// static members. Is null if no interfaces are implemented by this class
-    /// or its superclasses.
-    List<ClassMember> interfaceMembers;
-
-    /// Setters inherited from interfaces. This contains no static setters. Is
-    /// null if no interfaces are implemented by this class or its
-    /// superclasses.
-    List<ClassMember> interfaceSetters;
-
     List<Supertype> superclasses;
 
     List<Supertype> interfaces;
 
     int maxInheritancePath;
 
+    void extend(Map<Name, ClassMember> superClassMembers) {
+      if (superClassMembers == null) return;
+      for (Name name in superClassMembers.keys) {
+        ClassMember superClassMember = superClassMembers[name];
+        Tuple tuple = memberMap[name];
+        if (tuple != null) {
+          if (superClassMember.forSetter) {
+            tuple.extendedSetter = superClassMember;
+          } else {
+            tuple.extendedMember = superClassMember;
+          }
+        } else {
+          if (superClassMember.forSetter) {
+            memberMap[name] = new Tuple.extendSetter(superClassMember);
+          } else {
+            memberMap[name] = new Tuple.extendMember(superClassMember);
+          }
+        }
+      }
+    }
+
+    void implement(Map<Name, ClassMember> superInterfaceMembers) {
+      if (superInterfaceMembers == null) return;
+      for (Name name in superInterfaceMembers.keys) {
+        ClassMember superInterfaceMember = superInterfaceMembers[name];
+        Tuple tuple = memberMap[name];
+        if (tuple != null) {
+          if (superInterfaceMember.forSetter) {
+            (tuple.implementedSetters ??= <ClassMember>[])
+                .add(superInterfaceMember);
+          } else {
+            (tuple.implementedMembers ??= <ClassMember>[])
+                .add(superInterfaceMember);
+          }
+        } else {
+          if (superInterfaceMember.forSetter) {
+            memberMap[superInterfaceMember.name] =
+                new Tuple.implementSetter(superInterfaceMember);
+          } else {
+            memberMap[superInterfaceMember.name] =
+                new Tuple.implementMember(superInterfaceMember);
+          }
+        }
+      }
+    }
+
+    bool hasInterfaces = false;
     if (supernode == null) {
       // This should be Object.
-      classMembers = localMembers;
-      classSetters = localSetters;
       superclasses = new List<Supertype>(0);
       interfaces = new List<Supertype>(0);
       maxInheritancePath = 0;
@@ -1418,16 +1517,31 @@
         superclassInterfaces = substSupertypes(supertype, superclassInterfaces);
       }
 
-      classMembers = merge(
-          localMembers, supernode.classMembers, MergeKind.superclassMembers);
-      classSetters = merge(
-          localSetters, supernode.classSetters, MergeKind.superclassSetters);
+      extend(supernode.classMemberMap);
+      extend(supernode.classSetterMap);
+
+      if (supernode.interfaceMemberMap != null ||
+          supernode.interfaceSetterMap != null) {
+        hasInterfaces = true;
+      }
+
+      implement(supernode.interfaceMemberMap);
+      implement(supernode.interfaceSetterMap);
 
       if (directInterfaceBuilders != null) {
-        MergeResult result =
-            mergeInterfaces(supernode, directInterfaceBuilders);
-        interfaceMembers = result.mergedMembers;
-        interfaceSetters = result.mergedSetters;
+        for (int i = 0; i < directInterfaceBuilders.length; i++) {
+          ClassHierarchyNode interfaceNode =
+              hierarchy.getNodeFromTypeBuilder(directInterfaceBuilders[i]);
+          if (interfaceNode != null) {
+            hasInterfaces = true;
+
+            implement(interfaceNode.interfaceMemberMap ??
+                interfaceNode.classMemberMap);
+            implement(interfaceNode.interfaceSetterMap ??
+                interfaceNode.classSetterMap);
+          }
+        }
+
         interfaces = <Supertype>[];
         if (superclassInterfaces != null) {
           for (int i = 0; i < superclassInterfaces.length; i++) {
@@ -1465,38 +1579,369 @@
           }
         }
       } else {
-        interfaceMembers = supernode.interfaceMembers;
-        interfaceSetters = supernode.interfaceSetters;
         interfaces = superclassInterfaces;
       }
+    }
 
-      // Check if local members conflict with inherited setters. This check has
-      // already been performed in the superclass, so we only need to check the
-      // local members. These checks have to occur late to enable inferring
-      // types between setters and getters, or from a setter to a final field.
-      merge(localMembers, classSetters, MergeKind.membersWithSetters);
+    /// Members (excluding setters) declared in [cls] or its superclasses. This
+    /// includes static methods of [cls], but not its superclasses.
+    Map<Name, ClassMember> classMemberMap = {};
 
-      // Check if local setters conflict with inherited members. As above, we
-      // only need to check the local setters.
-      merge(localSetters, classMembers, MergeKind.settersWithMembers);
+    /// Setters declared in [cls] or its superclasses. This includes static
+    /// setters of [cls], but not its superclasses.
+    Map<Name, ClassMember> classSetterMap = {};
 
-      if (interfaceMembers != null) {
-        interfaceMembers =
-            merge(classMembers, interfaceMembers, MergeKind.supertypesMembers);
+    /// Members (excluding setters) inherited from interfaces. This contains no
+    /// static members. If no interfaces are implemented by this class or its
+    /// superclasses this is identical to [classMemberMap] and we do not store
+    /// it in the [ClassHierarchyNode].
+    Map<Name, ClassMember> interfaceMemberMap = {};
 
-        // Check if class setters conflict with members inherited from
-        // interfaces.
-        merge(classSetters, interfaceMembers, MergeKind.settersWithMembers);
-      }
-      if (interfaceSetters != null) {
-        interfaceSetters =
-            merge(classSetters, interfaceSetters, MergeKind.supertypesSetters);
+    /// Setters inherited from interfaces. This contains no static setters. If
+    /// no interfaces are implemented by this class or its superclasses this is
+    /// identical to [classSetterMap] and we do not store it in the
+    /// [ClassHierarchyNode].
+    Map<Name, ClassMember> interfaceSetterMap = {};
 
-        // Check if class members conflict with setters inherited from
-        // interfaces.
-        merge(classMembers, interfaceSetters, MergeKind.membersWithSetters);
+    Map<ClassMember, Set<ClassMember>> overrideDependencies = {};
+
+    // TODO(johnniwinther): Make these non-local and ensure that each
+    // underlying declaration has only on delayed type, signature, and
+    // override computation. Currently fields get one as a getter and as a
+    // setter.
+
+    void registerOverrideDependency(
+        ClassMember member, ClassMember overriddenMember) {
+      if (classBuilder == member.classBuilder && member.isSourceDeclaration) {
+        Set<ClassMember> dependencies =
+            overrideDependencies[member] ??= <ClassMember>{};
+        dependencies.add(overriddenMember);
+        member.registerOverrideDependency(overriddenMember);
       }
     }
+
+    void registerOverrideCheck(
+        ClassMember member, ClassMember overriddenMember) {
+      if (overriddenMember.hasDeclarations &&
+          (!useConsolidated || classBuilder == overriddenMember.classBuilder)) {
+        for (int i = 0; i < overriddenMember.declarations.length; i++) {
+          hierarchy.registerOverrideCheck(
+              classBuilder, member, overriddenMember.declarations[i]);
+        }
+      } else {
+        hierarchy.registerOverrideCheck(classBuilder, member, overriddenMember);
+      }
+    }
+
+    memberMap.forEach((Name name, Tuple tuple) {
+      ClassMember computeClassMember(ClassMember declaredMember,
+          ClassMember extendedMember, bool forSetter) {
+        if (declaredMember != null) {
+          if (extendedMember != null && !extendedMember.isStatic) {
+            if (declaredMember == extendedMember) return declaredMember;
+            if (declaredMember.isDuplicate || extendedMember.isDuplicate) {
+              // Don't check overrides involving duplicated members.
+              return declaredMember;
+            }
+            ClassMember result =
+                checkInheritanceConflict(declaredMember, extendedMember);
+            if (result != null) return result;
+            assert(
+                declaredMember.isProperty == extendedMember.isProperty,
+                "Unexpected member combination: "
+                "$declaredMember vs $extendedMember");
+            result = declaredMember;
+
+            // [declaredMember] is a method declared in [cls]. This means it
+            // defines the interface of this class regardless if its abstract.
+            registerOverrideDependency(declaredMember, extendedMember.abstract);
+            registerOverrideCheck(declaredMember, extendedMember.abstract);
+
+            if (declaredMember.isAbstract) {
+              if (extendedMember.isAbstract) {
+                recordAbstractMember(declaredMember);
+              } else {
+                if (!classBuilder.isAbstract) {
+                  // The interface of this class is [declaredMember]. But the
+                  // implementation is [extendedMember]. So [extendedMember]
+                  // must implement [declaredMember], unless [cls] is abstract.
+                  registerOverrideCheck(extendedMember, declaredMember);
+                }
+                ClassMember concrete = extendedMember.concrete;
+                result = new AbstractMemberOverridingImplementation(
+                    classBuilder,
+                    declaredMember,
+                    concrete,
+                    declaredMember.isProperty,
+                    forSetter,
+                    shouldModifyKernel,
+                    concrete.isAbstract,
+                    concrete.name);
+                hierarchy.registerMemberCheck(result);
+              }
+            } else if (classBuilder.isMixinApplication &&
+                declaredMember.classBuilder != classBuilder) {
+              result = InheritedImplementationInterfaceConflict.combined(
+                  classBuilder,
+                  declaredMember,
+                  extendedMember,
+                  forSetter,
+                  shouldModifyKernel,
+                  isInheritableConflict: false);
+              if (result.needsComputation) {
+                hierarchy.registerMemberCheck(result);
+              }
+            }
+
+            if (result.name == noSuchMethodName &&
+                !result.isObjectMember(objectClass)) {
+              hasNoSuchMethod = true;
+            }
+            return result;
+          } else {
+            if (declaredMember.isAbstract) {
+              recordAbstractMember(declaredMember);
+            }
+            return declaredMember;
+          }
+        } else if (extendedMember != null && !extendedMember.isStatic) {
+          if (extendedMember.isAbstract) {
+            if (isNameVisibleIn(extendedMember.name, classBuilder.library)) {
+              recordAbstractMember(extendedMember);
+            }
+          }
+          if (extendedMember.name == noSuchMethodName &&
+              !extendedMember.isObjectMember(objectClass)) {
+            hasNoSuchMethod = true;
+          }
+          if (extendedMember.isInheritableConflict) {
+            extendedMember = extendedMember.withParent(classBuilder);
+            hierarchy.registerMemberCheck(extendedMember);
+          }
+          if (extendedMember.classBuilder.library.isNonNullableByDefault &&
+              !classBuilder.library.isNonNullableByDefault) {
+            if (!extendedMember.isSynthesized) {
+              extendedMember = new InterfaceConflict(
+                  classBuilder,
+                  [extendedMember],
+                  extendedMember.isProperty,
+                  forSetter,
+                  shouldModifyKernel,
+                  extendedMember.isAbstract,
+                  extendedMember.name,
+                  isImplicitlyAbstract: extendedMember.isAbstract);
+              hierarchy.registerMemberCheck(extendedMember);
+            }
+          }
+          return extendedMember;
+        }
+        return null;
+      }
+
+      ClassMember computeInterfaceMember(ClassMember classMember,
+          List<ClassMember> implementedMembers, bool forSetter) {
+        ClassMember interfaceMember;
+        if (implementedMembers != null) {
+          for (ClassMember member in implementedMembers) {
+            if (member.isStatic) continue;
+            if (interfaceMember == null) {
+              interfaceMember = member;
+            } else {
+              ClassMember handleMergeConflict(ClassMember a, ClassMember b) {
+                if (a == b) return a;
+                if (a.isDuplicate || b.isDuplicate) {
+                  // Don't check overrides involving duplicated members.
+                  return a;
+                }
+                ClassMember result = checkInheritanceConflict(a, b);
+                if (result != null) return result;
+                assert(a.isProperty == b.isProperty,
+                    "Unexpected member combination: $a vs $b");
+                result = a;
+                result = InterfaceConflict.combined(
+                    classBuilder, a, b, forSetter, shouldModifyKernel);
+                return result;
+              }
+
+              interfaceMember = handleMergeConflict(interfaceMember, member);
+            }
+          }
+        }
+        if (hasInterfaces) {
+          if (interfaceMember != null) {
+            if (classMember != null) {
+              if (classMember == interfaceMember) return classMember;
+              if (classMember.isDuplicate || interfaceMember.isDuplicate) {
+                // Don't check overrides involving duplicated members.
+                return classMember;
+              }
+              ClassMember result =
+                  checkInheritanceConflict(classMember, interfaceMember);
+              if (result != null) return result;
+              assert(
+                  classMember.isProperty == interfaceMember.isProperty,
+                  "Unexpected member combination: "
+                  "$classMember vs $interfaceMember");
+              result = classMember;
+
+              // [interfaceMember] is inherited from an interface so it is
+              // implicitly abstract.
+              classMember = classMember.abstract;
+              interfaceMember = interfaceMember.abstract;
+
+              // If [classMember] is declared in this class, it defines the
+              // interface.
+              if (classMember.classBuilder == classBuilder) {
+                if (!classMember.isSynthesized) {
+                  registerOverrideDependency(classMember, interfaceMember);
+                  registerOverrideCheck(classMember, interfaceMember);
+                }
+                if (classMember.hasDeclarations) {
+                  if (interfaceMember.hasDeclarations &&
+                      (!useConsolidated ||
+                          interfaceMember.classBuilder == classBuilder)) {
+                    addAllDeclarationsTo(
+                        interfaceMember, classMember.declarations);
+                  } else {
+                    addDeclarationIfDifferent(
+                        interfaceMember, classMember.declarations);
+                  }
+                }
+              } else {
+                if (classMember.isAbstract) {
+                  result = InterfaceConflict.combined(classBuilder, classMember,
+                      interfaceMember, forSetter, shouldModifyKernel);
+                } else {
+                  result = InheritedImplementationInterfaceConflict.combined(
+                      classBuilder,
+                      classMember,
+                      interfaceMember,
+                      forSetter,
+                      shouldModifyKernel);
+                }
+                if (result.needsComputation) {
+                  hierarchy.registerMemberCheck(result);
+                }
+              }
+
+              return result;
+            } else {
+              if (isNameVisibleIn(interfaceMember.name, classBuilder.library)) {
+                recordAbstractMember(interfaceMember);
+              }
+              if (interfaceMember.isInheritableConflict) {
+                interfaceMember = interfaceMember.withParent(classBuilder);
+                hierarchy.registerMemberCheck(interfaceMember);
+              }
+              if (interfaceMember.classBuilder.library.isNonNullableByDefault &&
+                  !classBuilder.library.isNonNullableByDefault) {
+                if (!interfaceMember.isSynthesized) {
+                  interfaceMember = new InterfaceConflict(
+                      classBuilder,
+                      [interfaceMember],
+                      interfaceMember.isProperty,
+                      forSetter,
+                      shouldModifyKernel,
+                      interfaceMember.isAbstract,
+                      interfaceMember.name,
+                      isImplicitlyAbstract: interfaceMember.isAbstract);
+                  hierarchy.registerMemberCheck(interfaceMember);
+                }
+              }
+              return interfaceMember;
+            }
+          } else if (classMember != null) {
+            return classMember;
+          }
+        }
+        return interfaceMember;
+      }
+
+      void checkMemberVsSetter(
+          ClassMember member, ClassMember overriddenMember) {
+        if (overriddenMember.isStatic) return;
+        if (member == overriddenMember) return;
+        if (member.isDuplicate || overriddenMember.isDuplicate) {
+          // Don't check overrides involving duplicated members.
+          return;
+        }
+        ClassMember result = checkInheritanceConflict(member, overriddenMember);
+        if (result != null) return;
+        assert(member.isProperty == overriddenMember.isProperty,
+            "Unexpected member combination: $member vs $overriddenMember");
+        if (member.classBuilder == classBuilder &&
+            overriddenMember.classBuilder != classBuilder) {
+          if (member is SourceFieldMember) {
+            if (member.isFinal && overriddenMember.isSetter) {
+              registerOverrideDependency(member, overriddenMember);
+              hierarchy.registerOverrideCheck(
+                  classBuilder, member, overriddenMember);
+            } else {
+              registerOverrideDependency(member, overriddenMember);
+              hierarchy.registerOverrideCheck(
+                  classBuilder, member, overriddenMember);
+            }
+          } else if (member is SourceProcedureMember) {
+            registerOverrideDependency(member, overriddenMember);
+            hierarchy.registerOverrideCheck(
+                classBuilder, member, overriddenMember);
+          }
+        }
+      }
+
+      ClassMember classMember =
+          computeClassMember(tuple.declaredMember, tuple.extendedMember, false);
+      ClassMember interfaceMember =
+          computeInterfaceMember(classMember, tuple.implementedMembers, false);
+      ClassMember classSetter =
+          computeClassMember(tuple.declaredSetter, tuple.extendedSetter, true);
+      ClassMember interfaceSetter =
+          computeInterfaceMember(classSetter, tuple.implementedSetters, true);
+
+      if (tuple.declaredMember != null && classSetter != null) {
+        checkMemberVsSetter(tuple.declaredMember, classSetter);
+      }
+      if (tuple.declaredSetter != null && classMember != null) {
+        checkMemberVsSetter(tuple.declaredSetter, classMember);
+      }
+      if (classMember != null && interfaceSetter != null) {
+        checkMemberVsSetter(classMember, interfaceSetter);
+      }
+      if (classSetter != null && interfaceMember != null) {
+        checkMemberVsSetter(classSetter, interfaceMember);
+      }
+
+      if (classMember != null) {
+        classMemberMap[name] = classMember;
+      }
+      if (interfaceMember != null) {
+        interfaceMemberMap[name] = interfaceMember;
+      }
+      if (classSetter != null) {
+        classSetterMap[name] = classSetter;
+      }
+      if (interfaceSetter != null) {
+        interfaceSetterMap[name] = interfaceSetter;
+      }
+    });
+
+    overrideDependencies
+        .forEach((ClassMember member, Set<ClassMember> overriddenMembers) {
+      assert(
+          member == memberMap[member.name].declaredMember ||
+              member == memberMap[member.name].declaredSetter,
+          "Unexpected method type inference for ${memberMap[member.name]}: "
+          "${member} -> ${overriddenMembers}");
+      DelayedTypeComputation computation =
+          new DelayedTypeComputation(this, member, overriddenMembers);
+      hierarchy.registerDelayedTypeComputation(computation);
+    });
+
+    if (!hasInterfaces) {
+      interfaceMemberMap = null;
+      interfaceSetterMap = null;
+    }
+
     if (abstractMembers != null && !classBuilder.isAbstract) {
       if (!hasNoSuchMethod) {
         reportMissingMembers();
@@ -1507,10 +1952,10 @@
 
     return new ClassHierarchyNode(
       classBuilder,
-      classMembers,
-      classSetters,
-      interfaceMembers,
-      interfaceSetters,
+      classMemberMap,
+      classSetterMap,
+      interfaceMemberMap,
+      interfaceSetterMap,
       superclasses,
       interfaces,
       maxInheritancePath,
@@ -1657,59 +2102,6 @@
     return null;
   }
 
-  MergeResult mergeInterfaces(
-      ClassHierarchyNode supernode, List<TypeBuilder> interfaceBuilders) {
-    debug?.log("mergeInterfaces($classBuilder (${this.classBuilder}) "
-        "${supernode.interfaces} ${interfaceBuilders}");
-    List<List<ClassMember>> memberLists =
-        new List<List<ClassMember>>(interfaceBuilders.length + 1);
-    List<List<ClassMember>> setterLists =
-        new List<List<ClassMember>>(interfaceBuilders.length + 1);
-    memberLists[0] = supernode.interfaceMembers;
-    setterLists[0] = supernode.interfaceSetters;
-    for (int i = 0; i < interfaceBuilders.length; i++) {
-      ClassHierarchyNode interfaceNode =
-          hierarchy.getNodeFromTypeBuilder(interfaceBuilders[i]);
-      if (interfaceNode == null) {
-        memberLists[i + 1] = null;
-        setterLists[i + 1] = null;
-      } else {
-        memberLists[i + 1] =
-            interfaceNode.interfaceMembers ?? interfaceNode.classMembers;
-        setterLists[i + 1] =
-            interfaceNode.interfaceSetters ?? interfaceNode.classSetters;
-      }
-    }
-    return new MergeResult(mergeLists(memberLists, MergeKind.interfacesMembers),
-        mergeLists(setterLists, MergeKind.interfacesSetters));
-  }
-
-  List<ClassMember> mergeLists(
-      List<List<ClassMember>> input, MergeKind mergeKind) {
-    // This is a k-way merge sort (where k is `input.length + 1`). We merge the
-    // lists pairwise, which reduces the number of lists to merge by half on
-    // each iteration. Consequently, we perform O(log k) merges.
-    while (input.length > 1) {
-      List<List<ClassMember>> output = <List<ClassMember>>[];
-      for (int i = 0; i < input.length - 1; i += 2) {
-        List<ClassMember> first = input[i];
-        List<ClassMember> second = input[i + 1];
-        if (first == null) {
-          output.add(second);
-        } else if (second == null) {
-          output.add(first);
-        } else {
-          output.add(merge(first, second, mergeKind));
-        }
-      }
-      if (input.length.isOdd) {
-        output.add(input.last);
-      }
-      input = output;
-    }
-    return input.single;
-  }
-
   void reportMissingMembers() {
     Map<String, LocatedMessage> contextMap = <String, LocatedMessage>{};
     for (int i = 0; i < abstractMembers.length; i++) {
@@ -1743,87 +2135,6 @@
     // TODO(ahe): Implement this.
   }
 
-  List<ClassMember> merge(
-      List<ClassMember> aList, List<ClassMember> bList, MergeKind mergeKind) {
-    bool changed = false;
-    final List<ClassMember> result = new List<ClassMember>.filled(
-        aList.length + bList.length, null,
-        growable: true);
-    int storeIndex = 0;
-    int i = 0;
-    int j = 0;
-    while (i < aList.length && j < bList.length) {
-      final ClassMember a = aList[i];
-      final ClassMember b = bList[j];
-      if (mergeKind.betweenInterfaces && a.isStatic) {
-        i++;
-        continue;
-      }
-      if (b.isStatic) {
-        j++;
-        continue;
-      }
-      final int compare = compareDeclarations(a, b);
-      if (compare == 0) {
-        result[storeIndex++] = handleMergeConflict(a, b, mergeKind);
-        changed = true;
-        i++;
-        j++;
-      } else if (compare < 0) {
-        ClassMember member = handleOnlyA(a, mergeKind);
-        result[storeIndex++] = member;
-        if (!identical(member, a)) {
-          changed = true;
-        }
-        i++;
-      } else {
-        ClassMember member = handleOnlyB(b, mergeKind);
-        result[storeIndex++] = member;
-        if (!identical(member, b)) {
-          changed = true;
-        }
-        j++;
-      }
-    }
-    while (i < aList.length) {
-      final ClassMember a = aList[i];
-      if (!mergeKind.betweenInterfaces || !a.isStatic) {
-        ClassMember member = handleOnlyA(a, mergeKind);
-        result[storeIndex++] = member;
-        if (!identical(member, a)) {
-          changed = true;
-        }
-      }
-      i++;
-    }
-    while (j < bList.length) {
-      final ClassMember b = bList[j];
-      if (!b.isStatic) {
-        ClassMember member = handleOnlyB(b, mergeKind);
-        result[storeIndex++] = member;
-        if (!identical(member, b)) {
-          changed = true;
-        }
-      }
-      j++;
-    }
-    if (!changed && aList.isEmpty && storeIndex == bList.length) {
-      assert(
-          _equalsList(result, bList, storeIndex),
-          "List mismatch: Expected: ${bList}, "
-          "actual ${result.sublist(0, storeIndex)}");
-      return bList;
-    }
-    if (!changed && bList.isEmpty && storeIndex == aList.length) {
-      assert(
-          _equalsList(result, aList, storeIndex),
-          "List mismatch: Expected: ${aList}, "
-          "actual ${result.sublist(0, storeIndex)}");
-      return aList;
-    }
-    return result..length = storeIndex;
-  }
-
   void inferMixinApplication() {
     Class cls = classBuilder.cls;
     Supertype mixedInType = cls.mixedInType;
@@ -1872,10 +2183,10 @@
 
   /// All the members of this class including [classMembers] of its
   /// superclasses. The members are sorted by [compareDeclarations].
-  final List<ClassMember> classMembers;
+  final Map<Name, ClassMember> classMemberMap;
 
   /// Similar to [classMembers] but for setters.
-  final List<ClassMember> classSetters;
+  final Map<Name, ClassMember> classSetterMap;
 
   /// All the interface members of this class including [interfaceMembers] of
   /// its supertypes. The members are sorted by [compareDeclarations].
@@ -1884,12 +2195,12 @@
   /// from interfaces.
   ///
   /// This may be null, in which case [classMembers] is the interface members.
-  final List<ClassMember> interfaceMembers;
+  final Map<Name, ClassMember> interfaceMemberMap;
 
   /// Similar to [interfaceMembers] but for setters.
   ///
   /// This may be null, in which case [classSetters] is the interface setters.
-  final List<ClassMember> interfaceSetters;
+  final Map<Name, ClassMember> interfaceSetterMap;
 
   /// All superclasses of [classBuilder] excluding itself. The classes are
   /// sorted by depth from the root (Object) in ascending order.
@@ -1908,10 +2219,10 @@
 
   ClassHierarchyNode(
       this.classBuilder,
-      this.classMembers,
-      this.classSetters,
-      this.interfaceMembers,
-      this.interfaceSetters,
+      this.classMemberMap,
+      this.classSetterMap,
+      this.interfaceMemberMap,
+      this.interfaceSetterMap,
       this.superclasses,
       this.interfaces,
       this.maxInheritancePath,
@@ -1964,13 +2275,13 @@
       }
       sb.writeln();
     }
-    printMembers(classMembers, sb, "classMembers");
-    printMembers(classSetters, sb, "classSetters");
-    if (interfaceMembers != null) {
-      printMembers(interfaceMembers, sb, "interfaceMembers");
+    printMemberMap(classMemberMap, sb, "classMembers");
+    printMemberMap(classSetterMap, sb, "classSetters");
+    if (interfaceMemberMap != null) {
+      printMemberMap(interfaceMemberMap, sb, "interfaceMembers");
     }
-    if (interfaceSetters != null) {
-      printMembers(interfaceSetters, sb, "interfaceSetters");
+    if (interfaceSetterMap != null) {
+      printMemberMap(interfaceSetterMap, sb, "interfaceSetters");
     }
     return "$sb";
   }
@@ -1990,12 +2301,17 @@
     }
   }
 
+  void printMemberMap(
+      Map<Name, ClassMember> memberMap, StringBuffer sb, String heading) {
+    List<ClassMember> members = memberMap.values.toList();
+    members.sort(compareDeclarations);
+    printMembers(members, sb, heading);
+  }
+
   ClassMember getInterfaceMember(Name name, bool isSetter) {
-    return findMember(
-        name,
-        isSetter
-            ? interfaceSetters ?? classSetters
-            : interfaceMembers ?? classMembers);
+    return isSetter
+        ? (interfaceSetterMap ?? classSetterMap)[name]
+        : (interfaceMemberMap ?? classMemberMap)[name];
   }
 
   ClassMember findMember(Name name, List<ClassMember> declarations) {
@@ -2023,7 +2339,7 @@
   }
 
   ClassMember getDispatchTarget(Name name, bool isSetter) {
-    return findMember(name, isSetter ? classSetters : classMembers);
+    return isSetter ? classSetterMap[name] : classMemberMap[name];
   }
 
   static int compareMaxInheritancePath(
@@ -2032,88 +2348,7 @@
   }
 }
 
-class MergeResult {
-  final List<ClassMember> mergedMembers;
-
-  final List<ClassMember> mergedSetters;
-
-  MergeResult(this.mergedMembers, this.mergedSetters);
-}
-
-class MergeKind {
-  final String name;
-
-  final bool forSetters;
-
-  final bool betweenInterfaces;
-
-  final bool fromSuperclass;
-
-  final bool fromInterfaces;
-
-  final bool forMembersVsSetters;
-
-  final bool intoCurrentClass;
-
-  const MergeKind(this.name,
-      {this.forSetters: false,
-      this.betweenInterfaces: false,
-      this.fromSuperclass: false,
-      this.fromInterfaces: false,
-      this.forMembersVsSetters: false,
-      this.intoCurrentClass: false});
-
-  String toString() => 'MergeKind($name)';
-
-  /// Merging superclass members with the current class.
-  static const MergeKind superclassMembers = const MergeKind(
-      'Merging superclass members with the current class.',
-      fromSuperclass: true,
-      intoCurrentClass: true);
-
-  /// Merging superclass setters with the current class.
-  static const MergeKind superclassSetters = const MergeKind(
-      'Merging superclass setters with the current class.',
-      fromSuperclass: true,
-      intoCurrentClass: true,
-      forSetters: true);
-
-  /// Merging members of two interfaces.
-  static const MergeKind interfacesMembers = const MergeKind(
-      'Merging members of two interfaces.',
-      betweenInterfaces: true);
-
-  /// Merging setters of two interfaces.
-  static const MergeKind interfacesSetters = const MergeKind(
-      'Merging setters of two interfaces.',
-      betweenInterfaces: true,
-      forSetters: true);
-
-  /// Merging class members with interface members.
-  static const MergeKind supertypesMembers = const MergeKind(
-      'Merging class members with interface members.',
-      fromInterfaces: true,
-      intoCurrentClass: true);
-
-  /// Merging class setters with interface setters.
-  static const MergeKind supertypesSetters = const MergeKind(
-      'Merging class setters with interface setters.',
-      fromInterfaces: true,
-      intoCurrentClass: true,
-      forSetters: true);
-
-  /// Merging members with inherited setters.
-  static const MergeKind membersWithSetters = const MergeKind(
-      'Merging members with inherited setters.',
-      forMembersVsSetters: true);
-
-  /// Merging setters with inherited members.
-  static const MergeKind settersWithMembers = const MergeKind(
-      'Merging setters with inherited members.',
-      forMembersVsSetters: true);
-}
-
-List<LocatedMessage> inheritedConflictContext(ClassMember a, ClassMember b) {
+List<LocatedMessage> _inheritedConflictContext(ClassMember a, ClassMember b) {
   int length = a.fullNameForErrors.length;
   // TODO(ahe): Delete this method when it isn't used by [InterfaceResolver].
   int compare = "${a.fileUri}".compareTo("${b.fileUri}");
@@ -2260,18 +2495,17 @@
         if (a.isGetter && !a.hasExplicitReturnType) {
           int inferTypesFrom;
           DartType type;
-          if (b.isGetter) {
-            Procedure bTarget = bMember;
-            type = bTarget.function.returnType;
-            inferTypesFrom = SourceProcedureMember.inferredTypesFromGetter;
-          } else if (b.isSetter) {
-            Procedure bTarget = bMember;
-            type = bTarget.function.positionalParameters.single.type;
-            inferTypesFrom = SourceProcedureMember.inferredTypesFromSetter;
-          } else if (b.isField) {
-            Field bTarget = bMember;
-            type = bTarget.type;
-            inferTypesFrom = SourceProcedureMember.inferredTypesFromField;
+          if (bMember is Field) {
+            type = bMember.type;
+            inferTypesFrom = SourceProcedureBuilder.inferredTypesFromField;
+          } else if (bMember is Procedure) {
+            if (bMember.kind == ProcedureKind.Getter) {
+              type = bMember.function.returnType;
+              inferTypesFrom = SourceProcedureBuilder.inferredTypesFromGetter;
+            } else if (bMember.kind == ProcedureKind.Setter) {
+              type = bMember.function.positionalParameters.single.type;
+              inferTypesFrom = SourceProcedureBuilder.inferredTypesFromSetter;
+            }
           }
           if (type != null) {
             type = Substitution.fromInterfaceType(
@@ -2281,24 +2515,29 @@
                         bMember.enclosingClass,
                         classBuilder.library.library))
                 .substituteType(type);
-            inferReturnType(classBuilder, a, type, a.hadTypesInferredFrom,
-                inferTypesFrom, hierarchy);
+            inferReturnType(
+                classBuilder,
+                a.memberBuilder,
+                a.memberBuilder.member.function,
+                type,
+                a.hadTypesInferredFrom,
+                inferTypesFrom,
+                hierarchy);
           }
         } else if (a.isSetter && !a.hasExplicitlyTypedFormalParameter(0)) {
           int inferTypesFrom;
           DartType type;
-          if (b.isGetter) {
-            Procedure bTarget = bMember;
-            type = bTarget.function.returnType;
-            inferTypesFrom = SourceProcedureMember.inferredTypesFromGetter;
-          } else if (b.isSetter) {
-            Procedure bTarget = bMember;
-            type = bTarget.function.positionalParameters.single.type;
-            inferTypesFrom = SourceProcedureMember.inferredTypesFromSetter;
-          } else if (b.isField) {
-            Field bTarget = bMember;
-            type = bTarget.type;
-            inferTypesFrom = SourceProcedureMember.inferredTypesFromField;
+          if (bMember is Field) {
+            type = bMember.type;
+            inferTypesFrom = SourceProcedureBuilder.inferredTypesFromField;
+          } else if (bMember is Procedure) {
+            if (bMember.kind == ProcedureKind.Getter) {
+              type = bMember.function.returnType;
+              inferTypesFrom = SourceProcedureBuilder.inferredTypesFromGetter;
+            } else if (bMember.kind == ProcedureKind.Setter) {
+              type = bMember.function.positionalParameters.single.type;
+              inferTypesFrom = SourceProcedureBuilder.inferredTypesFromSetter;
+            }
           }
           if (type != null) {
             type = Substitution.fromInterfaceType(
@@ -2308,54 +2547,10 @@
                         bMember.enclosingClass,
                         classBuilder.library.library))
                 .substituteType(type);
-            inferParameterType(classBuilder, a, a.formals.single, type,
-                a.hadTypesInferredFrom, inferTypesFrom, hierarchy);
+            inferParameterType(classBuilder, a.memberBuilder, a.formals.single,
+                type, a.hadTypesInferredFrom, inferTypesFrom, hierarchy);
           }
         }
-      } else if (a is SourceFieldMember && a.type == null) {
-        DartType type;
-        if (b.isGetter) {
-          Procedure bTarget = bMember;
-          type = bTarget.function.returnType;
-        } else if (b.isSetter) {
-          Procedure bTarget = bMember;
-          type = bTarget.function.positionalParameters.single.type;
-        } else if (b.isField) {
-          Field bTarget = bMember;
-          type = bTarget.type;
-        }
-        if (type != null) {
-          type = Substitution.fromInterfaceType(
-                  hierarchy.getKernelTypeAsInstanceOf(
-                      hierarchy.coreTypes.thisInterfaceType(
-                          classBuilder.cls, classBuilder.library.nonNullable),
-                      bMember.enclosingClass,
-                      classBuilder.library.library))
-              .substituteType(type);
-          if (!a.classBuilder.library.isNonNullableByDefault) {
-            type = legacyErasure(hierarchy.coreTypes, type);
-          }
-          if (type != a.fieldType) {
-            if (a.hadTypesInferred) {
-              if (b.isSetter &&
-                  (!a.isAssignable ||
-                      hierarchy.types.isSubtypeOfKernel(
-                          type,
-                          a.fieldType,
-                          classBuilder.library.isNonNullableByDefault
-                              ? SubtypeCheckMode.withNullabilities
-                              : SubtypeCheckMode.ignoringNullabilities))) {
-                type = a.fieldType;
-              } else {
-                reportCantInferFieldType(classBuilder, a);
-                type = const InvalidType();
-              }
-            }
-            debug?.log("Inferred type ${type} for ${a.fullName}");
-            a.fieldType = type;
-          }
-        }
-        a.hadTypesInferred = true;
       }
     }
 
@@ -2363,32 +2558,37 @@
   }
 }
 
-abstract class DelayedSignatureComputation {
-  void computeSignature(ClassHierarchyBuilder hierarchy);
-}
-
-class DelayedMethodTypeInference implements DelayedSignatureComputation {
+class DelayedTypeComputation {
   final ClassHierarchyNodeBuilder builder;
-  final SourceProcedureMember a;
-  final ClassMember b;
+  final ClassMember declaredMember;
+  final Set<ClassMember> overriddenMembers;
+  bool _computed = false;
 
-  DelayedMethodTypeInference(this.builder, this.a, this.b);
+  DelayedTypeComputation(
+      this.builder, this.declaredMember, this.overriddenMembers)
+      : assert(declaredMember.isSourceDeclaration);
 
-  void computeSignature(ClassHierarchyBuilder hierarchy) {
-    builder.inferMethodTypes(hierarchy, a, b);
+  void compute(ClassHierarchyBuilder hierarchy) {
+    if (_computed) return;
+    declaredMember.inferType(hierarchy);
+    _computed = true;
+    if (declaredMember.isField) {
+      builder.inferFieldSignature(hierarchy, declaredMember, overriddenMembers);
+    } else if (declaredMember.isGetter) {
+      builder.inferGetterSignature(
+          hierarchy, declaredMember, overriddenMembers);
+    } else if (declaredMember.isSetter) {
+      builder.inferSetterSignature(
+          hierarchy, declaredMember, overriddenMembers);
+    } else {
+      builder.inferMethodSignature(
+          hierarchy, declaredMember, overriddenMembers);
+    }
   }
-}
 
-class DelayedFieldTypeInference implements DelayedSignatureComputation {
-  final ClassHierarchyNodeBuilder builder;
-  final ClassMember a;
-  final ClassMember b;
-
-  DelayedFieldTypeInference(this.builder, this.a, this.b);
-
-  void computeSignature(ClassHierarchyBuilder hierarchy) {
-    builder.inferFieldTypes(hierarchy, a, b);
-  }
+  @override
+  String toString() => 'DelayedTypeComputation('
+      '${builder.classBuilder.name},$declaredMember,$overriddenMembers)';
 }
 
 abstract class DelayedMember implements ClassMember {
@@ -2396,6 +2596,8 @@
   @override
   final ClassBuilder classBuilder;
 
+  bool get hasDeclarations => true;
+
   /// Conflicting declarations.
   final List<ClassMember> declarations;
 
@@ -2414,6 +2616,18 @@
       this.isSetter, this.modifyKernel, this.isExplicitlyAbstract, this.name);
 
   @override
+  bool get isSourceDeclaration => false;
+
+  @override
+  bool get needsComputation => true;
+
+  @override
+  bool get isSynthesized => true;
+
+  @override
+  bool get forSetter => isSetter;
+
+  @override
   bool get isFunction => !isProperty;
 
   @override
@@ -2427,18 +2641,15 @@
   bool get isAssignable => false;
   bool get isDuplicate => false;
 
-  void addAllDeclarationsTo(List<ClassMember> declarations) {
-    for (int i = 0; i < this.declarations.length; i++) {
-      addDeclarationIfDifferent(this.declarations[i], declarations);
-    }
-    assert(declarations.toSet().length == declarations.length);
-  }
-
-  Member check(ClassHierarchyBuilder hierarchy);
-
   DelayedMember withParent(ClassBuilder parent);
 
   @override
+  ClassMember get abstract => this;
+
+  @override
+  ClassMember get concrete => this;
+
+  @override
   Uri get fileUri => classBuilder.fileUri;
 
   @override
@@ -2457,13 +2668,48 @@
 
   @override
   bool get hasExplicitReturnType {
-    throw new UnsupportedError("${runtimeType}.hasExplicitReturnType");
+    return true;
   }
 
   @override
   bool hasExplicitlyTypedFormalParameter(int index) {
-    throw new UnsupportedError(
-        "${runtimeType}.hasExplicitlyTypedFormalParameter");
+    return true;
+  }
+
+  @override
+  void inferType(ClassHierarchyBuilder hierarchy) {
+    // Do nothing; this is only for declared members.
+  }
+
+  @override
+  void registerOverrideDependency(ClassMember overriddenMember) {
+    // Do nothing; this is only for declared members.
+  }
+
+  @override
+  int get hashCode {
+    int hash = classBuilder.hashCode * 13 +
+        isSetter.hashCode * 17 +
+        isProperty.hashCode * 19 +
+        modifyKernel.hashCode * 23 +
+        name.hashCode * 29;
+    for (ClassMember declaration in declarations) {
+      hash ^= declaration.hashCode;
+    }
+    return hash;
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return other is DelayedMember &&
+        classBuilder == other.classBuilder &&
+        isSetter == other.isSetter &&
+        isProperty == other.isProperty &&
+        modifyKernel == other.modifyKernel &&
+        name == other.name &&
+        declarations.length == other.declarations.length &&
+        _equalsList(declarations, other.declarations, declarations.length);
   }
 }
 
@@ -2501,10 +2747,18 @@
   }
 
   @override
-  Member getMember(ClassHierarchyBuilder hierarchy) => check(hierarchy);
+  int get hashCode => super.hashCode + isInheritableConflict.hashCode * 11;
 
   @override
-  Member check(ClassHierarchyBuilder hierarchy) {
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return super == other &&
+        other is InheritedImplementationInterfaceConflict &&
+        isInheritableConflict == other.isInheritableConflict;
+  }
+
+  @override
+  Member getMember(ClassHierarchyBuilder hierarchy) {
     if (combinedMemberSignatureResult != null) {
       return combinedMemberSignatureResult;
     }
@@ -2518,7 +2772,7 @@
     }
     return combinedMemberSignatureResult = new InterfaceConflict(classBuilder,
             declarations, isProperty, isSetter, modifyKernel, isAbstract, name)
-        .check(hierarchy);
+        .getMember(hierarchy);
   }
 
   @override
@@ -2545,13 +2799,13 @@
     assert(concreteImplementation.isProperty == other.isProperty,
         "Unexpected member combination: $concreteImplementation vs $other");
     List<ClassMember> declarations = <ClassMember>[];
-    if (concreteImplementation is DelayedMember) {
-      concreteImplementation.addAllDeclarationsTo(declarations);
+    if (concreteImplementation.hasDeclarations) {
+      addAllDeclarationsTo(concreteImplementation, declarations);
     } else {
       declarations.add(concreteImplementation);
     }
-    if (other is DelayedMember) {
-      other.addAllDeclarationsTo(declarations);
+    if (other.hasDeclarations) {
+      addAllDeclarationsTo(other, declarations);
     } else {
       addDeclarationIfDifferent(other, declarations);
     }
@@ -2601,6 +2855,24 @@
         "[${declarations.join(', ')}])";
   }
 
+  @override
+  int get hashCode {
+    int hash = super.hashCode;
+    hash ^= isImplicitlyAbstract.hashCode;
+    for (ClassMember declaration in declarations) {
+      hash ^= declaration.hashCode;
+    }
+    return hash;
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return super == other &&
+        other is InterfaceConflict &&
+        isImplicitlyAbstract == other.isImplicitlyAbstract;
+  }
+
   DartType computeMemberType(
       ClassHierarchyBuilder hierarchy, DartType thisType, Member member) {
     DartType type;
@@ -2639,10 +2911,7 @@
   }
 
   @override
-  Member getMember(ClassHierarchyBuilder hierarchy) => check(hierarchy);
-
-  @override
-  Member check(ClassHierarchyBuilder hierarchy) {
+  Member getMember(ClassHierarchyBuilder hierarchy) {
     if (combinedMemberSignatureResult != null) {
       return combinedMemberSignatureResult;
     }
@@ -2803,13 +3072,13 @@
     assert(a.isProperty == b.isProperty,
         "Unexpected member combination: $a vs $b");
     List<ClassMember> declarations = <ClassMember>[];
-    if (a is DelayedMember) {
-      a.addAllDeclarationsTo(declarations);
+    if (a.hasDeclarations) {
+      addAllDeclarationsTo(a, declarations);
     } else {
       declarations.add(a);
     }
-    if (b is DelayedMember) {
-      b.addAllDeclarationsTo(declarations);
+    if (b.hasDeclarations) {
+      addAllDeclarationsTo(b, declarations);
     } else {
       addDeclarationIfDifferent(b, declarations);
     }
@@ -2826,6 +3095,14 @@
           declarations.first.name);
     }
   }
+
+  @override
+  ClassMember get concrete {
+    if (isAbstract) {
+      return declarations.first.concrete;
+    }
+    return this;
+  }
 }
 
 class AbstractMemberOverridingImplementation extends DelayedMember {
@@ -2849,28 +3126,30 @@
 
   ClassMember get abstractMember => declarations[1];
 
+  bool _isChecked = false;
+
   @override
-  Member getMember(ClassHierarchyBuilder hierarchy) =>
-      abstractMember.getMember(hierarchy);
+  Member getMember(ClassHierarchyBuilder hierarchy) {
+    if (!_isChecked) {
+      _isChecked = true;
+      if (!classBuilder.isAbstract &&
+          !hierarchy.nodes[classBuilder.cls].hasNoSuchMethod) {
+        new DelayedOverrideCheck(
+                classBuilder, concreteImplementation, abstractMember)
+            .check(hierarchy);
+      }
 
-  Member check(ClassHierarchyBuilder hierarchy) {
-    if (!classBuilder.isAbstract &&
-        !hierarchy.nodes[classBuilder.cls].hasNoSuchMethod) {
-      new DelayedOverrideCheck(
-              classBuilder, concreteImplementation, abstractMember)
-          .check(hierarchy);
-    }
-
-    ProcedureKind kind = ProcedureKind.Method;
-    if (abstractMember.isProperty) {
-      kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
-    }
-    if (modifyKernel) {
-      // This call will add a body to the abstract method if needed for
-      // isGenericCovariantImpl checks.
-      new ForwardingNode(hierarchy, classBuilder, abstractMember, 1,
-              declarations, kind, null)
-          .finalize();
+      ProcedureKind kind = ProcedureKind.Method;
+      if (abstractMember.isProperty) {
+        kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
+      }
+      if (modifyKernel) {
+        // This call will add a body to the abstract method if needed for
+        // isGenericCovariantImpl checks.
+        new ForwardingNode(hierarchy, classBuilder, abstractMember, 1,
+                declarations, kind, null)
+            .finalize();
+      }
     }
     return abstractMember.getMember(hierarchy);
   }
@@ -2897,23 +3176,17 @@
         "[${declarations.join(', ')}])";
   }
 
-  static ClassMember selectAbstract(ClassMember declaration) {
-    if (declaration is AbstractMemberOverridingImplementation) {
-      return declaration.abstractMember;
-    } else {
-      return declaration;
-    }
+  @override
+  bool operator ==(Object other) {
+    if (identical(this, other)) return true;
+    return super == other && other is AbstractMemberOverridingImplementation;
   }
 
-  static ClassMember selectConcrete(ClassMember declaration) {
-    if (declaration is AbstractMemberOverridingImplementation) {
-      return declaration.concreteImplementation;
-    } else if (declaration is InterfaceConflict && !declaration.isAbstract) {
-      return selectConcrete(declaration.declarations.first);
-    } else {
-      return declaration;
-    }
-  }
+  @override
+  ClassMember get abstract => abstractMember;
+
+  @override
+  ClassMember get concrete => concreteImplementation;
 }
 
 void addDeclarationIfDifferent(
@@ -2924,21 +3197,29 @@
   declarations.add(declaration);
 }
 
+void addAllDeclarationsTo(ClassMember member, List<ClassMember> declarations) {
+  assert(member.hasDeclarations);
+  for (int i = 0; i < member.declarations.length; i++) {
+    addDeclarationIfDifferent(member.declarations[i], declarations);
+  }
+  assert(declarations.toSet().length == declarations.length);
+}
+
 int compareNamedParameters(VariableDeclaration a, VariableDeclaration b) {
   return a.name.compareTo(b.name);
 }
 
 bool inferParameterType(
     ClassBuilder classBuilder,
-    SourceProcedureMember memberBuilder,
+    SourceProcedureBuilder memberBuilder,
     FormalParameterBuilder parameterBuilder,
     DartType type,
     int hadTypesInferredFrom,
     int inferTypesFrom,
     ClassHierarchyBuilder hierarchy) {
-  if ((hadTypesInferredFrom & SourceProcedureMember.inferredTypesFromSetter) !=
+  if ((hadTypesInferredFrom & SourceProcedureBuilder.inferredTypesFromSetter) !=
           0 &&
-      (inferTypesFrom & SourceProcedureMember.inferredTypesFromSetter) == 0) {
+      (inferTypesFrom & SourceProcedureBuilder.inferredTypesFromSetter) == 0) {
     // Parameter type already inferred from setter; disregard getters.
     return false;
   }
@@ -2999,29 +3280,28 @@
 
 bool inferReturnType(
     ClassBuilder classBuilder,
-    SourceProcedureMember procedureBuilder,
+    SourceProcedureBuilder procedureBuilder,
+    FunctionNode function,
     DartType type,
     int hadTypesInferredFrom,
     int inferTypesFrom,
     ClassHierarchyBuilder hierarchy) {
-  if ((hadTypesInferredFrom & SourceProcedureMember.inferredTypesFromGetter) !=
+  if ((hadTypesInferredFrom & SourceProcedureBuilder.inferredTypesFromGetter) !=
           0 &&
-      (inferTypesFrom & SourceProcedureMember.inferredTypesFromGetter) == 0) {
+      (inferTypesFrom & SourceProcedureBuilder.inferredTypesFromGetter) == 0) {
     // Return type already inferred from getter; disregard setters.
     return false;
   }
 
-  Procedure procedure = procedureBuilder.getMember(hierarchy);
-
   if (classBuilder.library.isNonNullableByDefault) {
     if ((hadTypesInferredFrom & inferTypesFrom) != 0) {
       type = nnbdTopMerge(
           hierarchy.coreTypes,
-          norm(hierarchy.coreTypes, procedure.function.returnType),
+          norm(hierarchy.coreTypes, function.returnType),
           norm(hierarchy.coreTypes, type));
       if (type != null) {
         // The nnbd top merge exists so [type] is the inferred type.
-        procedure.function.returnType = type;
+        function.returnType = type;
         return false;
       }
       // The nnbd top merge doesn't exist. An error will be reported below.
@@ -3029,34 +3309,33 @@
   } else {
     type = legacyErasure(hierarchy.coreTypes, type);
     if ((hadTypesInferredFrom & inferTypesFrom) != 0) {
-      if (procedure.function.returnType is DynamicType &&
+      if (function.returnType is DynamicType &&
           type == hierarchy.coreTypes.objectLegacyRawType) {
         return false;
       } else if (type is DynamicType &&
-          procedure.function.returnType ==
-              hierarchy.coreTypes.objectLegacyRawType) {
-        procedure.function.returnType = const DynamicType();
+          function.returnType == hierarchy.coreTypes.objectLegacyRawType) {
+        function.returnType = const DynamicType();
         return false;
       }
     }
   }
 
   if ((hadTypesInferredFrom & inferTypesFrom) != 0) {
-    if (type == procedure.function.returnType) {
+    if (type == function.returnType) {
       return true;
     }
     reportCantInferReturnType(classBuilder, procedureBuilder, hierarchy);
-    procedure.function.returnType = const InvalidType();
+    function.returnType = const InvalidType();
     return false;
   } else {
     procedureBuilder.hadTypesInferredFrom |= inferTypesFrom;
-    procedure.function.returnType = type;
+    function.returnType = type;
     return true;
   }
 }
 
-void reportCantInferReturnType(
-    ClassBuilder cls, ClassMember member, ClassHierarchyBuilder hierarchy) {
+void reportCantInferReturnType(ClassBuilder cls, SourceProcedureBuilder member,
+    ClassHierarchyBuilder hierarchy) {
   String name = member.fullNameForErrors;
   List<LocatedMessage> context;
   // // TODO(ahe): The following is for debugging, but could be cleaned up and
@@ -3114,7 +3393,7 @@
       context: context);
 }
 
-void reportCantInferFieldType(ClassBuilder cls, ClassMember member) {
+void reportCantInferFieldType(ClassBuilder cls, SourceFieldBuilder member) {
   String name = member.fullNameForErrors;
   cls.addProblem(
       templateCantInferTypeDueToInconsistentOverrides.withArguments(name),
@@ -3133,7 +3412,7 @@
 }
 
 /// Returns `true` if the first [length] elements of [a] and [b] are the same.
-bool _equalsList(List<ClassMember> a, List<ClassMember> b, int length) {
+bool _equalsList<T>(List<T> a, List<T> b, int length) {
   if (a.length < length || b.length < length) return false;
   for (int index = 0; index < length; index++) {
     if (a[index] != b[index]) {
@@ -3142,3 +3421,22 @@
   }
   return true;
 }
+
+Set<ClassMember> toSet(
+    ClassBuilder classBuilder, Iterable<ClassMember> members) {
+  Set<ClassMember> result = <ClassMember>{};
+  _toSet(classBuilder, members, result);
+  return result;
+}
+
+void _toSet(ClassBuilder classBuilder, Iterable<ClassMember> members,
+    Set<ClassMember> result) {
+  for (ClassMember member in members) {
+    if (member.hasDeclarations &&
+        (!useConsolidated || classBuilder == member.classBuilder)) {
+      _toSet(classBuilder, member.declarations, result);
+    } else {
+      result.add(member);
+    }
+  }
+}
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 7a764d6..742cd7e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -572,9 +572,7 @@
   SwitchStatement visitSwitchStatement(SwitchStatement node) {
     SwitchStatement result = super.visitSwitchStatement(node);
     Library library = constantEvaluator.libraryOf(node);
-    if (library != null &&
-        library.isNonNullableByDefault &&
-        constantEvaluator.errorReporter.performNnbdChecks) {
+    if (library != null && library.isNonNullableByDefault) {
       for (SwitchCase switchCase in node.cases) {
         for (Expression caseExpression in switchCase.expressions) {
           if (caseExpression is ConstantExpression) {
@@ -1845,25 +1843,34 @@
     return reportInvalid(node, 'Variable get of a non-const variable.');
   }
 
+  /// Computes the constant for [expression] defined in the context of [member].
+  ///
+  /// This compute the constant as seen in the current evaluation mode even when
+  /// the constant is defined in a library compiled with the agnostic evaluation
+  /// mode.
+  Constant _evaluateExpressionInContext(Member member, Expression expression) {
+    StaticTypeContext oldStaticTypeContext = _staticTypeContext;
+    _staticTypeContext = new StaticTypeContext(member, typeEnvironment);
+    Constant constant = runInsideContext(member, () {
+      Constant constant = _evaluateSubexpression(expression);
+      if (_staticTypeContext.nonNullableByDefaultCompiledMode ==
+              NonNullableByDefaultCompiledMode.Agnostic &&
+          evaluationMode == EvaluationMode.weak) {
+        constant = _weakener.visitConstant(constant) ?? constant;
+      }
+      return constant;
+    });
+    _staticTypeContext = oldStaticTypeContext;
+    return constant;
+  }
+
   @override
   Constant visitStaticGet(StaticGet node) {
     return withNewEnvironment(() {
       final Member target = node.target;
       if (target is Field) {
         if (target.isConst) {
-          StaticTypeContext oldStaticTypeContext = _staticTypeContext;
-          _staticTypeContext = new StaticTypeContext(target, typeEnvironment);
-          Constant constant = runInsideContext(target, () {
-            Constant constant = _evaluateSubexpression(target.initializer);
-            if (_staticTypeContext.nonNullableByDefaultCompiledMode ==
-                    NonNullableByDefaultCompiledMode.Agnostic &&
-                evaluationMode == EvaluationMode.weak) {
-              constant = _weakener.visitConstant(constant) ?? constant;
-            }
-            return constant;
-          });
-          _staticTypeContext = oldStaticTypeContext;
-          return constant;
+          return _evaluateExpressionInContext(target, target.initializer);
         }
         return report(
             node,
@@ -1934,6 +1941,77 @@
     return canonicalize(new StringConstant(concatenated.single.toString()));
   }
 
+  Constant _getFromEnvironmentDefaultValue(Procedure target) {
+    VariableDeclaration variable = target.function.namedParameters
+        .singleWhere((v) => v.name == 'defaultValue');
+    return variable.initializer != null
+        ? _evaluateExpressionInContext(target, variable.initializer)
+        : nullConstant;
+  }
+
+  Constant _handleFromEnvironment(
+      Procedure target, StringConstant name, Map<String, Constant> named) {
+    String value = environmentDefines[name.value];
+    Constant defaultValue = named["defaultValue"];
+    if (target.enclosingClass == coreTypes.boolClass) {
+      Constant boolConstant;
+      if (value == "true") {
+        boolConstant = trueConstant;
+      } else if (value == "false") {
+        boolConstant = falseConstant;
+      } else if (defaultValue != null) {
+        if (defaultValue is BoolConstant) {
+          boolConstant = makeBoolConstant(defaultValue.value);
+        } else if (defaultValue is NullConstant) {
+          boolConstant = nullConstant;
+        } else {
+          boolConstant = falseConstant;
+        }
+      } else {
+        boolConstant = _getFromEnvironmentDefaultValue(target);
+      }
+      return boolConstant;
+    } else if (target.enclosingClass == coreTypes.intClass) {
+      int intValue = value != null ? int.tryParse(value) : null;
+      Constant intConstant;
+      if (intValue != null) {
+        bool negated = value.startsWith('-');
+        intConstant = intFolder.makeIntConstant(intValue, unsigned: !negated);
+      } else if (defaultValue != null) {
+        if (intFolder.isInt(defaultValue)) {
+          intConstant = defaultValue;
+        } else {
+          intConstant = nullConstant;
+        }
+      } else {
+        intConstant = _getFromEnvironmentDefaultValue(target);
+      }
+      return canonicalize(intConstant);
+    } else if (target.enclosingClass == coreTypes.stringClass) {
+      Constant stringConstant;
+      if (value != null) {
+        stringConstant = canonicalize(new StringConstant(value));
+      } else if (defaultValue != null) {
+        if (defaultValue is StringConstant) {
+          stringConstant = defaultValue;
+        } else {
+          stringConstant = nullConstant;
+        }
+      } else {
+        stringConstant = _getFromEnvironmentDefaultValue(target);
+      }
+      return stringConstant;
+    }
+    throw new UnsupportedError(
+        'Unexpected fromEnvironment constructor: $target');
+  }
+
+  Constant _handleHasEnvironment(StringConstant name) {
+    return environmentDefines.containsKey(name.value)
+        ? trueConstant
+        : falseConstant;
+  }
+
   @override
   Constant visitStaticInvocation(StaticInvocation node) {
     final Procedure target = node.target;
@@ -1949,45 +2027,18 @@
     }
     if (target.kind == ProcedureKind.Factory) {
       if (target.isConst &&
-          target.name.name == "fromEnvironment" &&
           target.enclosingLibrary == coreTypes.coreLibrary &&
-          positionals.length == 1) {
+          positionals.length == 1 &&
+          (target.name.name == "fromEnvironment" ||
+              target.name.name == "hasEnvironment")) {
         if (environmentDefines != null) {
           // Evaluate environment constant.
           Constant name = positionals.single;
           if (name is StringConstant) {
-            String value = environmentDefines[name.value];
-            Constant defaultValue = named["defaultValue"];
-
-            if (target.enclosingClass == coreTypes.boolClass) {
-              Constant boolConstant = value == "true"
-                  ? trueConstant
-                  : value == "false"
-                      ? falseConstant
-                      : defaultValue is BoolConstant
-                          ? makeBoolConstant(defaultValue.value)
-                          : defaultValue is NullConstant
-                              ? nullConstant
-                              : falseConstant;
-              return boolConstant;
-            } else if (target.enclosingClass == coreTypes.intClass) {
-              int intValue = value != null ? int.tryParse(value) : null;
-              Constant intConstant;
-              if (intValue != null) {
-                bool negated = value.startsWith('-');
-                intConstant =
-                    intFolder.makeIntConstant(intValue, unsigned: !negated);
-              } else if (intFolder.isInt(defaultValue)) {
-                intConstant = defaultValue;
-              } else {
-                intConstant = nullConstant;
-              }
-              return canonicalize(intConstant);
-            } else if (target.enclosingClass == coreTypes.stringClass) {
-              value ??=
-                  defaultValue is StringConstant ? defaultValue.value : null;
-              if (value == null) return nullConstant;
-              return canonicalize(new StringConstant(value));
+            if (target.name.name == "fromEnvironment") {
+              return _handleFromEnvironment(target, name, named);
+            } else {
+              return _handleHasEnvironment(name);
             }
           } else if (name is NullConstant) {
             return report(node, messageConstEvalNullValue);
@@ -2488,20 +2539,13 @@
 abstract class ErrorReporter {
   const ErrorReporter();
 
-  // TODO(johnniwinther,dmitryas): Remove the getter when the NNBD error
-  // reporting is enabled by default.
-  bool get performNnbdChecks;
-
   void report(LocatedMessage message, List<LocatedMessage> context);
 
   void reportInvalidExpression(InvalidExpression node);
 }
 
 class SimpleErrorReporter implements ErrorReporter {
-  @override
-  final bool performNnbdChecks;
-
-  const SimpleErrorReporter(this.performNnbdChecks);
+  const SimpleErrorReporter();
 
   @override
   void report(LocatedMessage message, List<LocatedMessage> context) {
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 b3d936d..8e68472 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
@@ -7,6 +7,7 @@
         Arguments,
         Class,
         DartType,
+        DynamicType,
         Expression,
         Field,
         FunctionNode,
@@ -216,6 +217,15 @@
           interfacePositionalParameters[parameterIndex];
       DartType parameterType = substitution.substituteType(parameter.type);
       DartType type = initialType(_combinedMemberIndex, parameterType);
+      if (parameterIndex == 0 &&
+          hierarchy
+              .coreTypes.objectClass.enclosingLibrary.isNonNullableByDefault &&
+          !classBuilder.library.isNonNullableByDefault &&
+          interfaceMember == hierarchy.coreTypes.objectEquals) {
+        // In legacy code we special case `Object.==` to infer `dynamic`
+        // instead `Object!`.
+        type = const DynamicType();
+      }
       bool isGenericCovariantImpl =
           parameter.isGenericCovariantImpl || needsCheck(parameter.type);
       bool isCovariant = parameter.isCovariant;
@@ -237,8 +247,19 @@
         if (otherParameter.isCovariant) {
           isCovariant = true;
         }
-        type = mergeTypes(candidateIndex, type,
-            substitutions[candidateIndex].substituteType(otherParameter.type));
+        DartType candidateType =
+            substitutions[candidateIndex].substituteType(otherParameter.type);
+        if (parameterIndex == 0 &&
+            hierarchy.coreTypes.objectClass.enclosingLibrary
+                .isNonNullableByDefault &&
+            !classBuilder.library.isNonNullableByDefault &&
+            otherMember == hierarchy.coreTypes.objectEquals) {
+          // In legacy code we special case `Object.==` to infer `dynamic`
+          // instead `Object!`.
+          candidateType = const DynamicType();
+        }
+
+        type = mergeTypes(candidateIndex, type, candidateType);
       }
       if (isGenericCovariantImpl) {
         if (!superParameter.isGenericCovariantImpl) {
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 9cf058f..5082f41 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -735,14 +735,14 @@
             inferred: true);
       }
     }
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (node.target == inferrer.coreTypes.listDefaultConstructor) {
         if (inferrer.nnbdMode == NnbdMode.Weak) {
           inferrer.library.addProblem(messageDefaultListConstructorWarning,
               node.fileOffset, noLength, inferrer.helper.uri);
         } else {
-          resultNode = inferrer.helper.wrapInProblem(
-              node, messageDefaultListConstructorError, noLength);
+          resultNode = inferrer.helper.wrapInProblem(node,
+              messageDefaultListConstructorError, node.fileOffset, noLength);
         }
       }
     }
@@ -2344,7 +2344,7 @@
         node.arguments,
         typeContext,
         isExpressionInvocation: true);
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (receiverType is! DynamicType &&
           receiverType is! InvalidType &&
           isPotentiallyNullable(
@@ -2362,6 +2362,7 @@
                   invocationResult.expression..fileOffset = node.fileOffset,
                   templateNullableExpressionCallError.withArguments(
                       receiverType, inferrer.isNonNullableByDefault),
+                  node.fileOffset,
                   noLength));
         }
       }
@@ -3587,7 +3588,7 @@
           ..fileOffset = fileOffset;
       }
     }
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (leftType is! DynamicType &&
           isPotentiallyNullable(leftType, inferrer.coreTypes.futureOrClass)) {
         if (inferrer.nnbdMode == NnbdMode.Weak) {
@@ -3605,6 +3606,7 @@
                       binaryName.name,
                       leftType,
                       inferrer.isNonNullableByDefault),
+                  binary.fileOffset,
                   binaryName.name.length));
         }
       }
@@ -3675,7 +3677,7 @@
           ..fileOffset = fileOffset;
       }
     }
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (expressionType is! DynamicType &&
           isPotentiallyNullable(
               expressionType, inferrer.coreTypes.futureOrClass)) {
@@ -3696,6 +3698,7 @@
                       unaryName.name,
                       expressionType,
                       inferrer.isNonNullableByDefault),
+                  unary.fileOffset,
                   unaryName == unaryMinusName ? 1 : unaryName.name.length));
         }
       }
@@ -3755,7 +3758,7 @@
           ..fileOffset = fileOffset;
       }
     }
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (receiverType is! DynamicType &&
           receiverType is! InvalidType &&
           isPotentiallyNullable(
@@ -3777,6 +3780,7 @@
                       indexGetName.name,
                       receiverType,
                       inferrer.isNonNullableByDefault),
+                  read.fileOffset,
                   noLength));
         }
       }
@@ -3818,7 +3822,7 @@
           writeTarget.member)
         ..fileOffset = fileOffset;
     }
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (receiverType is! DynamicType &&
           isPotentiallyNullable(
               receiverType, inferrer.coreTypes.futureOrClass)) {
@@ -3835,6 +3839,7 @@
               write,
               templateNullableOperatorCallError.withArguments(indexSetName.name,
                   receiverType, inferrer.isNonNullableByDefault),
+              write.fileOffset,
               noLength);
         }
       }
@@ -3940,7 +3945,7 @@
         return inferrer.instantiateTearOff(readType, typeContext, read);
       }
     }
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (receiverType is! DynamicType &&
           receiverType is! InvalidType &&
           isPotentiallyNullable(
@@ -3964,6 +3969,7 @@
                       propertyName.name,
                       receiverType,
                       inferrer.isNonNullableByDefault),
+                  read.fileOffset,
                   propertyName.name.length));
         }
       }
@@ -4026,7 +4032,7 @@
       write = new PropertySet(receiver, propertyName, value, writeTarget.member)
         ..fileOffset = fileOffset;
     }
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (receiverType is! DynamicType &&
           isPotentiallyNullable(
               receiverType, inferrer.coreTypes.futureOrClass)) {
@@ -4045,6 +4051,7 @@
                   propertyName.name,
                   receiverType,
                   inferrer.isNonNullableByDefault),
+              write.fileOffset,
               propertyName.name.length);
         }
       }
@@ -5170,23 +5177,21 @@
         DartType caseExpressionType = caseExpressionResult.inferredType;
 
         if (inferrer.library.isNonNullableByDefault) {
-          if (inferrer.performNnbdChecks) {
-            if (!inferrer.typeSchemaEnvironment.isSubtypeOf(caseExpressionType,
-                expressionType, SubtypeCheckMode.withNullabilities)) {
-              inferrer.helper.addProblem(
-                  templateSwitchExpressionNotSubtype.withArguments(
-                      caseExpressionType,
-                      expressionType,
-                      inferrer.isNonNullableByDefault),
-                  caseExpression.fileOffset,
-                  noLength,
-                  context: [
-                    messageSwitchExpressionNotAssignableCause.withLocation(
-                        inferrer.uriForInstrumentation,
-                        node.expression.fileOffset,
-                        noLength)
-                  ]);
-            }
+          if (!inferrer.typeSchemaEnvironment.isSubtypeOf(caseExpressionType,
+              expressionType, SubtypeCheckMode.withNullabilities)) {
+            inferrer.helper.addProblem(
+                templateSwitchExpressionNotSubtype.withArguments(
+                    caseExpressionType,
+                    expressionType,
+                    inferrer.isNonNullableByDefault),
+                caseExpression.fileOffset,
+                noLength,
+                context: [
+                  messageSwitchExpressionNotAssignableCause.withLocation(
+                      inferrer.uriForInstrumentation,
+                      node.expression.fileOffset,
+                      noLength)
+                ]);
           }
         } else {
           // Check whether the expression type is assignable to the case
@@ -5214,7 +5219,7 @@
         switchCase.body = bodyResult.statement..parent = switchCase;
       }
 
-      if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+      if (inferrer.isNonNullableByDefault) {
         // The last case block is allowed to complete normally.
         if (caseIndex < node.cases.length - 1 &&
             inferrer.flowAnalysis.isReachable) {
@@ -5247,7 +5252,7 @@
         isVoidAllowed: false);
     node.expression = expressionResult.expression..parent = node;
     inferrer.flowAnalysis.handleExit();
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (!inferrer.isAssignable(
           inferrer.typeSchemaEnvironment.objectNonNullableRawType,
           expressionResult.inferredType,
@@ -5528,7 +5533,7 @@
     bool isUnassigned = !inferrer.flowAnalysis.isAssigned(variable);
     if (isUnassigned) {
       inferrer.dataForTesting?.flowAnalysisResult?.unassignedNodes?.add(node);
-      if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+      if (inferrer.isNonNullableByDefault) {
         // Synthetic variables, local functions, and variables with
         // invalid types aren't checked.
         // TODO(dmitryas): Report errors on definitely unassigned late
@@ -5553,6 +5558,7 @@
                     node,
                     templateNonNullableNotAssignedError
                         .withArguments(node.variable.name),
+                    node.fileOffset,
                     node.variable.name.length));
           }
         }
@@ -5788,7 +5794,7 @@
 
   void reportNonNullableInNullAwareWarningIfNeeded(
       DartType operandType, String operationName, int offset) {
-    if (inferrer.isNonNullableByDefault && inferrer.performNnbdChecks) {
+    if (inferrer.isNonNullableByDefault) {
       if (operandType is! InvalidType &&
           !isPotentiallyNullable(
               operandType, inferrer.coreTypes.futureOrClass)) {
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 b70d248..b17364e3 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -15,7 +15,7 @@
 import '../combinator.dart' as fasta;
 
 export 'class_hierarchy_builder.dart'
-    show ClassHierarchyBuilder, DelayedMember, DelayedOverrideCheck;
+    show ClassHierarchyBuilder, ClassMember, DelayedOverrideCheck;
 
 export 'implicit_field_type.dart' show ImplicitFieldType;
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
index e42aa40..61f54880 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
@@ -10,8 +10,6 @@
 
 import '../loader.dart' show Loader;
 
-import '../source/source_loader.dart';
-
 import 'constant_evaluator.dart' show ErrorReporter;
 
 class KernelConstantErrorReporter extends ErrorReporter {
@@ -19,11 +17,6 @@
 
   KernelConstantErrorReporter(this.loader);
 
-  bool get performNnbdChecks {
-    Loader loader = this.loader;
-    return loader is SourceLoader && loader.performNnbdChecks;
-  }
-
   @override
   void report(LocatedMessage message, List<LocatedMessage> context) {
     loader.addProblem(
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 c31cb69..b8f1156 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -862,8 +862,7 @@
           nonFinalFields.clear();
         }
         SourceLibraryBuilder library = builder.library;
-        if (library.isNonNullableByDefault &&
-            library.loader.performNnbdChecks) {
+        if (library.isNonNullableByDefault) {
           if (constructor.isConst && lateFinalFields.isNotEmpty) {
             if (library.loader.nnbdMode == NnbdMode.Weak) {
               builder.addProblem(messageConstConstructorLateFinalFieldWarning,
@@ -950,8 +949,7 @@
                   fieldBuilder.field.type, loader.coreTypes.futureOrClass) &&
               (cls.constructors.isNotEmpty || cls.isMixinDeclaration)) {
             SourceLibraryBuilder library = builder.library;
-            if (library.isNonNullableByDefault &&
-                library.loader.performNnbdChecks) {
+            if (library.isNonNullableByDefault) {
               if (library.loader.nnbdMode == NnbdMode.Weak) {
                 library.addProblem(
                     templateFieldNonNullableWithoutInitializerWarning
@@ -1009,8 +1007,7 @@
               isPotentiallyNonNullable(
                   fieldBuilder.field.type, loader.coreTypes.futureOrClass)) {
             SourceLibraryBuilder library = builder.library;
-            if (library.isNonNullableByDefault &&
-                library.loader.performNnbdChecks) {
+            if (library.isNonNullableByDefault) {
               if (library.loader.nnbdMode == NnbdMode.Weak) {
                 library.addProblem(
                     templateFieldNonNullableNotInitializedByConstructorWarning
diff --git a/pkg/front_end/lib/src/fasta/modifier.dart b/pkg/front_end/lib/src/fasta/modifier.dart
index b8796c0..0d6a2b1 100644
--- a/pkg/front_end/lib/src/fasta/modifier.dart
+++ b/pkg/front_end/lib/src/fasta/modifier.dart
@@ -46,9 +46,9 @@
 /// Not a modifier, used by formal parameters to track if they are initializing.
 const int initializingFormalMask = hasInitializerMask << 1;
 
-/// Not a modifier, used by classes to track if the class has a const
+/// Not a modifier, used by classes to track if the class declares a const
 /// constructor.
-const int hasConstConstructorMask = initializingFormalMask << 1;
+const int declaresConstConstructorMask = initializingFormalMask << 1;
 
 /// Not a real modifier, and by setting it to zero, it is automatically ignored
 /// by [Modifier.validate] below.
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 b2a1e9e..43d78d8 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -575,8 +575,7 @@
     final int startCharOffset =
         metadata == null ? beginToken.charOffset : metadata.first.charOffset;
 
-    if (libraryBuilder.isNonNullableByDefault &&
-        libraryBuilder.loader.performNnbdChecks) {
+    if (libraryBuilder.isNonNullableByDefault) {
       String classNameForErrors = "${name}";
       TypeBuilder supertypeForErrors = supertype is MixinApplicationBuilder
           ? supertype.supertype
@@ -697,8 +696,7 @@
       }
     }
 
-    if (libraryBuilder.isNonNullableByDefault &&
-        libraryBuilder.loader.performNnbdChecks) {
+    if (libraryBuilder.isNonNullableByDefault) {
       String classNameForErrors = "${name}";
       if (supertypeConstraints != null) {
         for (TypeBuilder supertype in supertypeConstraints) {
@@ -1235,8 +1233,7 @@
       return;
     }
 
-    if (libraryBuilder.isNonNullableByDefault &&
-        libraryBuilder.loader.performNnbdChecks) {
+    if (libraryBuilder.isNonNullableByDefault) {
       String classNameForErrors = "${name}";
       MixinApplicationBuilder mixinApplicationBuilder = mixinApplication;
       TypeBuilder supertype = mixinApplicationBuilder.supertype;
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 575cd9b..a3b5e82 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
@@ -171,7 +171,7 @@
         referencesFromIndexed = referencesFromIndexed,
         super(metadata, modifiers, name, typeVariables, supertype, interfaces,
             onTypes, scope, constructors, parent, nameOffset) {
-    actualCls.hasConstConstructor = hasConstConstructor;
+    actualCls.hasConstConstructor = declaresConstConstructor;
   }
 
   @override
@@ -339,6 +339,9 @@
     DillMemberBuilder memberBuilder = new DillMemberBuilder(constructor, this);
     memberBuilder.next = constructorScopeBuilder[name];
     constructorScopeBuilder.addMember(name, memberBuilder);
+    if (constructor.isConst) {
+      cls.hasConstConstructor = true;
+    }
   }
 
   @override
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 8f4d344..d355d3e 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
@@ -146,7 +146,7 @@
         abstractMask,
         constMask,
         finalMask,
-        hasConstConstructorMask,
+        declaresConstConstructorMask,
         hasInitializerMask,
         initializingFormalMask,
         lateMask,
@@ -1418,8 +1418,8 @@
       isMixinDeclaration = true;
       modifiers = (modifiers & ~mixinDeclarationMask) | abstractMask;
     }
-    if (declaration.hasConstConstructor) {
-      modifiers |= hasConstConstructorMask;
+    if (declaration.declaresConstConstructor) {
+      modifiers |= declaresConstConstructorMask;
     }
     Class referencesFromClass;
     if (referencesFrom != null) {
@@ -2061,7 +2061,7 @@
       addNativeMethod(constructorBuilder);
     }
     if (constructorBuilder.isConst) {
-      currentTypeParameterScopeBuilder?.hasConstConstructor = true;
+      currentTypeParameterScopeBuilder?.declaresConstConstructor = true;
       // const constructors will have their initializers compiled and written
       // into the outline.
       constructorBuilder.beginInitializers =
@@ -2108,7 +2108,7 @@
         if (currentTypeParameterScopeBuilder.kind ==
             TypeParameterScopeKind.extensionDeclaration) {
           bool extensionIsStatic = (modifiers & staticMask) != 0;
-          String nameToLookup = ProcedureBuilderImpl.createProcedureName(
+          String nameToLookup = SourceProcedureBuilder.createProcedureName(
               true,
               extensionIsStatic,
               kind,
@@ -2123,7 +2123,7 @@
           }
           if (kind == ProcedureKind.Method) {
             String tearOffNameToLookup =
-                ProcedureBuilderImpl.createProcedureName(
+                SourceProcedureBuilder.createProcedureName(
                     true,
                     false,
                     ProcedureKind.Getter,
@@ -2142,7 +2142,7 @@
         }
       }
     }
-    ProcedureBuilder procedureBuilder = new ProcedureBuilderImpl(
+    ProcedureBuilder procedureBuilder = new SourceProcedureBuilder(
         metadata,
         modifiers,
         returnType,
@@ -2220,11 +2220,10 @@
           charOpenParenOffset,
           charEndOffset,
           referenceFrom,
-          null,
           nativeMethodName,
           redirectionTarget);
     } else {
-      procedureBuilder = new ProcedureBuilderImpl(
+      procedureBuilder = new SourceProcedureBuilder(
           metadata,
           staticMask | modifiers,
           returnType,
@@ -3028,7 +3027,7 @@
 
     // Check that the field has an initializer if its type is potentially
     // non-nullable.
-    if (isNonNullableByDefault && loader.performNnbdChecks) {
+    if (isNonNullableByDefault) {
       // Only static and top-level fields are checked here.  Instance fields are
       // checked elsewhere.
       DartType fieldType = fieldBuilder.field.type;
@@ -3062,9 +3061,7 @@
 
   void checkInitializersInFormals(
       List<FormalParameterBuilder> formals, TypeEnvironment typeEnvironment) {
-    bool performInitializerChecks =
-        isNonNullableByDefault && loader.performNnbdChecks;
-    if (!performInitializerChecks) return;
+    if (!isNonNullableByDefault) return;
 
     for (FormalParameterBuilder formal in formals) {
       bool isOptionalPositional = formal.isOptional && formal.isPositional;
@@ -3129,17 +3126,19 @@
               typeEnvironment, SubtypeCheckMode.ignoringNullabilities,
               allowSuperBounded: true)
           ?.toSet();
-      Set<TypeArgumentIssue> nnbdIssues =
-          isNonNullableByDefault && loader.performNnbdChecks
-              ? findTypeArgumentIssues(returnType, typeEnvironment,
-                      SubtypeCheckMode.withNullabilities)
-                  ?.toSet()
-              : null;
+      Set<TypeArgumentIssue> nnbdIssues = isNonNullableByDefault
+          ? findTypeArgumentIssues(returnType, typeEnvironment,
+                  SubtypeCheckMode.withNullabilities)
+              ?.toSet()
+          : null;
       if (legacyIssues != null || nnbdIssues != null) {
         Set<TypeArgumentIssue> mergedIssues = legacyIssues ?? {};
         if (nnbdIssues != null) {
-          mergedIssues.addAll(nnbdIssues.where((issue) =>
-              legacyIssues == null || !legacyIssues.contains(issue)));
+          nnbdIssues = nnbdIssues
+              .where((issue) =>
+                  legacyIssues == null || !legacyIssues.contains(issue))
+              .toSet();
+          mergedIssues.addAll(nnbdIssues);
         }
         int offset = fileOffset;
         for (TypeArgumentIssue issue in mergedIssues) {
@@ -3229,13 +3228,12 @@
             type, typeEnvironment, SubtypeCheckMode.ignoringNullabilities,
             allowSuperBounded: allowSuperBounded)
         ?.toSet();
-    Set<TypeArgumentIssue> nnbdIssues =
-        isNonNullableByDefault && loader.performNnbdChecks
-            ? findTypeArgumentIssues(
-                    type, typeEnvironment, SubtypeCheckMode.withNullabilities,
-                    allowSuperBounded: allowSuperBounded)
-                ?.toSet()
-            : null;
+    Set<TypeArgumentIssue> nnbdIssues = isNonNullableByDefault
+        ? findTypeArgumentIssues(
+                type, typeEnvironment, SubtypeCheckMode.withNullabilities,
+                allowSuperBounded: allowSuperBounded)
+            ?.toSet()
+        : null;
     if (legacyIssues != null) {
       reportTypeArgumentIssues(legacyIssues, fileUri, offset,
           inferred: inferred);
@@ -3305,12 +3303,11 @@
             typeEnvironment,
             SubtypeCheckMode.ignoringNullabilities)
         ?.toSet();
-    Set<TypeArgumentIssue> nnbdIssues =
-        isNonNullableByDefault && loader.performNnbdChecks
-            ? findTypeArgumentIssuesForInvocation(parameters, arguments,
-                    typeEnvironment, SubtypeCheckMode.withNullabilities)
-                ?.toSet()
-            : null;
+    Set<TypeArgumentIssue> nnbdIssues = isNonNullableByDefault
+        ? findTypeArgumentIssuesForInvocation(parameters, arguments,
+                typeEnvironment, SubtypeCheckMode.withNullabilities)
+            ?.toSet()
+        : null;
     if (legacyIssues != null) {
       DartType targetReceiver;
       if (klass != null) {
@@ -3331,7 +3328,8 @@
       }
       String targetName = node.target.name.name;
       if (legacyIssues != null) {
-        nnbdIssues = nnbdIssues.where((issue) => !legacyIssues.contains(issue));
+        nnbdIssues =
+            nnbdIssues.where((issue) => !legacyIssues.contains(issue)).toSet();
       }
       reportTypeArgumentIssues(nnbdIssues, fileUri, node.fileOffset,
           typeArgumentsInfo: typeArgumentsInfo,
@@ -3397,15 +3395,14 @@
             typeEnvironment,
             SubtypeCheckMode.ignoringNullabilities)
         ?.toSet();
-    Set<TypeArgumentIssue> nnbdIssues =
-        isNonNullableByDefault && loader.performNnbdChecks
-            ? findTypeArgumentIssuesForInvocation(
-                    instantiatedMethodParameters,
-                    arguments.types,
-                    typeEnvironment,
-                    SubtypeCheckMode.withNullabilities)
-                ?.toSet()
-            : null;
+    Set<TypeArgumentIssue> nnbdIssues = isNonNullableByDefault
+        ? findTypeArgumentIssuesForInvocation(
+                instantiatedMethodParameters,
+                arguments.types,
+                typeEnvironment,
+                SubtypeCheckMode.withNullabilities)
+            ?.toSet()
+        : null;
     if (legacyIssues != null) {
       reportTypeArgumentIssues(legacyIssues, fileUri, offset,
           typeArgumentsInfo: getTypeArgumentsInfo(arguments),
@@ -3414,7 +3411,8 @@
     }
     if (nnbdIssues != null) {
       if (legacyIssues != null) {
-        nnbdIssues = nnbdIssues.where((issue) => !legacyIssues.contains(issue));
+        nnbdIssues =
+            nnbdIssues.where((issue) => !legacyIssues.contains(issue)).toSet();
       }
       reportTypeArgumentIssues(nnbdIssues, fileUri, offset,
           typeArgumentsInfo: getTypeArgumentsInfo(arguments),
@@ -3550,7 +3548,7 @@
   /// with a synthesized parameter of this type.
   TypeBuilder _extensionThisType;
 
-  bool hasConstConstructor = false;
+  bool declaresConstConstructor = false;
 
   TypeParameterScopeBuilder(
       this._kind,
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 b3b0a5f..de1fdb5 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -106,7 +106,7 @@
         templateUntranslatableUri;
 
 import '../kernel/kernel_builder.dart'
-    show ClassHierarchyBuilder, DelayedMember, DelayedOverrideCheck;
+    show ClassHierarchyBuilder, ClassMember, DelayedOverrideCheck;
 
 import '../kernel/kernel_target.dart' show KernelTarget;
 
@@ -192,8 +192,6 @@
 
   NnbdMode get nnbdMode => target.context.options.nnbdMode;
 
-  bool get performNnbdChecks => target.context.options.performNnbdChecks;
-
   CoreTypes get coreTypes {
     assert(_coreTypes != null, "CoreTypes has not been computed.");
     return _coreTypes;
@@ -383,7 +381,7 @@
               "debugExpression in $enclosingClass");
       }
     }
-    ProcedureBuilder builder = new ProcedureBuilderImpl(
+    ProcedureBuilder builder = new SourceProcedureBuilder(
         null,
         0,
         null,
@@ -989,8 +987,7 @@
 
   void checkOverrides(List<SourceClassBuilder> sourceClasses) {
     List<DelayedOverrideCheck> overrideChecks =
-        builderHierarchy.overrideChecks.toList();
-    builderHierarchy.overrideChecks.clear();
+        builderHierarchy.takeDelayedOverrideChecks();
     for (int i = 0; i < overrideChecks.length; i++) {
       overrideChecks[i].check(builderHierarchy);
     }
@@ -1001,12 +998,11 @@
   }
 
   void checkAbstractMembers(List<SourceClassBuilder> sourceClasses) {
-    List<DelayedMember> delayedMemberChecks =
-        builderHierarchy.delayedMemberChecks.toList();
-    builderHierarchy.delayedMemberChecks.clear();
+    List<ClassMember> delayedMemberChecks =
+        builderHierarchy.takeDelayedMemberChecks();
     Set<Class> changedClasses = new Set<Class>();
     for (int i = 0; i < delayedMemberChecks.length; i++) {
-      delayedMemberChecks[i].check(builderHierarchy);
+      delayedMemberChecks[i].getMember(builderHierarchy);
       changedClasses.add(delayedMemberChecks[i].classBuilder.cls);
     }
     ticker.logMs(
@@ -1094,6 +1090,8 @@
     /// might be subject to type inference, and records dependencies between
     /// them.
     typeInferenceEngine.prepareTopLevel(coreTypes, hierarchy);
+    builderHierarchy.computeTypes();
+
     List<FieldBuilder> allImplicitlyTypedFields = <FieldBuilder>[];
     for (LibraryBuilder library in builders.values) {
       if (library.loader == this) {
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 6f4c2f2..00c4bef 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -53,7 +53,6 @@
   bool enableTripleShift;
   bool enableVariance;
   bool enableNonfunctionTypeAliases;
-  bool performNnbdChecks;
 
   TargetImplementation(Ticker ticker, this.uriTranslator, this.backendTarget)
       : assert(ticker != null),
@@ -69,7 +68,6 @@
             .isExperimentEnabled(ExperimentalFlag.variance),
         enableNonfunctionTypeAliases = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.nonfunctionTypeAliases),
-        performNnbdChecks = CompilerContext.current.options.performNnbdChecks,
         super(ticker);
 
   /// Creates a [LibraryBuilder] corresponding to [uri], if one doesn't exist
diff --git a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
index d8a1daa..9219313 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/inference_helper.dart
@@ -26,7 +26,8 @@
   void addProblem(Message message, int charOffset, int length,
       {List<LocatedMessage> context, bool wasHandled});
 
-  Expression wrapInProblem(Expression expression, Message message, int length,
+  Expression wrapInProblem(
+      Expression expression, Message message, int fileOffset, int length,
       {List<LocatedMessage> context});
 
   String constructorNameForDiagnostics(String name,
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 5dc83a6..bb85651 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
@@ -31,6 +31,8 @@
 
 import 'package:kernel/src/future_or.dart';
 
+import 'package:kernel/src/legacy_erasure.dart';
+
 import 'type_schema.dart' show UnknownType;
 
 import '../problems.dart';
@@ -270,13 +272,16 @@
   DartType getStandardLowerBound(
       DartType type1, DartType type2, Library clientLibrary) {
     if (clientLibrary.isNonNullableByDefault) {
-      return getNullabilityAwareStandardLowerBound(type1, type2, clientLibrary);
+      return _getNullabilityAwareStandardLowerBound(
+          type1, type2, clientLibrary);
     }
-    return getNullabilityObliviousStandardLowerBound(
-        type1, type2, clientLibrary);
+    return _getNullabilityObliviousStandardLowerBound(
+        legacyErasure(coreTypes, type1),
+        legacyErasure(coreTypes, type2),
+        clientLibrary);
   }
 
-  DartType getNullabilityAwareStandardLowerBound(
+  DartType _getNullabilityAwareStandardLowerBound(
       DartType type1, DartType type2, Library clientLibrary) {
     // DOWN(T, T) = T.
     if (identical(type1, type2)) return type1;
@@ -417,7 +422,7 @@
         intersectNullabilities(type1.nullability, type2.nullability));
   }
 
-  DartType getNullabilityObliviousStandardLowerBound(
+  DartType _getNullabilityObliviousStandardLowerBound(
       DartType type1, DartType type2, Library clientLibrary) {
     // Do legacy erasure on the argument, so that the result types that are
     // computed from arguments are legacy.
@@ -551,13 +556,16 @@
   DartType getStandardUpperBound(
       DartType type1, DartType type2, Library clientLibrary) {
     if (clientLibrary.isNonNullableByDefault) {
-      return getNullabilityAwareStandardUpperBound(type1, type2, clientLibrary);
+      return _getNullabilityAwareStandardUpperBound(
+          type1, type2, clientLibrary);
     }
-    return getNullabilityObliviousStandardUpperBound(
-        type1, type2, clientLibrary);
+    return _getNullabilityObliviousStandardUpperBound(
+        legacyErasure(coreTypes, type1),
+        legacyErasure(coreTypes, type2),
+        clientLibrary);
   }
 
-  DartType getNullabilityAwareStandardUpperBound(
+  DartType _getNullabilityAwareStandardUpperBound(
       DartType type1, DartType type2, Library clientLibrary) {
     // UP(T, T) = T
     if (identical(type1, type2)) return type1;
@@ -715,7 +723,7 @@
         for (int i = 0; i < n; ++i) {
           int variance = klass.typeParameters[i].variance;
           if (variance == Variance.contravariant) {
-            typeArguments[i] = getNullabilityAwareStandardLowerBound(
+            typeArguments[i] = _getNullabilityAwareStandardLowerBound(
                 leftArguments[i], rightArguments[i], clientLibrary);
           } else if (variance == Variance.invariant) {
             if (!areMutualSubtypes(leftArguments[i], rightArguments[i],
@@ -723,7 +731,7 @@
               return getLegacyLeastUpperBound(type1, type2, clientLibrary);
             }
           } else {
-            typeArguments[i] = getNullabilityAwareStandardUpperBound(
+            typeArguments[i] = _getNullabilityAwareStandardUpperBound(
                 leftArguments[i], rightArguments[i], clientLibrary);
           }
         }
@@ -833,7 +841,7 @@
     List<DartType> positionalParameters =
         new List<DartType>.filled(maxPos, null);
     for (int i = 0; i < minPos; ++i) {
-      positionalParameters[i] = getNullabilityAwareStandardUpperBound(
+      positionalParameters[i] = _getNullabilityAwareStandardUpperBound(
           f.positionalParameters[i],
           substitution.substituteType(g.positionalParameters[i]),
           clientLibrary);
@@ -870,7 +878,7 @@
         } else {
           named = new NamedType(
               named1.name,
-              getNullabilityAwareStandardUpperBound(named1.type,
+              _getNullabilityAwareStandardUpperBound(named1.type,
                   substitution.substituteType(named2.type), clientLibrary),
               isRequired: named1.isRequired && named2.isRequired);
           ++i;
@@ -894,7 +902,7 @@
       }
     }
 
-    DartType returnType = getNullabilityAwareStandardLowerBound(
+    DartType returnType = _getNullabilityAwareStandardLowerBound(
         f.returnType, substitution.substituteType(g.returnType), clientLibrary);
 
     return new FunctionType(positionalParameters, returnType,
@@ -1030,7 +1038,7 @@
     List<DartType> positionalParameters =
         new List<DartType>.filled(minPos, null);
     for (int i = 0; i < minPos; ++i) {
-      positionalParameters[i] = getNullabilityAwareStandardLowerBound(
+      positionalParameters[i] = _getNullabilityAwareStandardLowerBound(
           f.positionalParameters[i],
           substitution.substituteType(g.positionalParameters[i]),
           clientLibrary);
@@ -1053,7 +1061,7 @@
         } else {
           namedParameters.add(new NamedType(
               named1.name,
-              getNullabilityAwareStandardLowerBound(named1.type,
+              _getNullabilityAwareStandardLowerBound(named1.type,
                   substitution.substituteType(named2.type), clientLibrary),
               isRequired: named1.isRequired || named2.isRequired));
           ++i;
@@ -1062,7 +1070,7 @@
       }
     }
 
-    DartType returnType = getNullabilityAwareStandardUpperBound(
+    DartType returnType = _getNullabilityAwareStandardUpperBound(
         f.returnType, substitution.substituteType(g.returnType), clientLibrary);
 
     return new FunctionType(positionalParameters, returnType,
@@ -1090,7 +1098,7 @@
       Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{
         type1.parameter: coreTypes.objectNonNullableRawType
       };
-      return getNullabilityAwareStandardUpperBound(
+      return _getNullabilityAwareStandardUpperBound(
               substitute(type1.parameter.bound, substitution),
               type2,
               clientLibrary)
@@ -1114,7 +1122,7 @@
       Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{
         type1.parameter: coreTypes.objectNonNullableRawType
       };
-      return getNullabilityAwareStandardUpperBound(
+      return _getNullabilityAwareStandardUpperBound(
               substitute(type1.promotedBound, substitution),
               type2,
               clientLibrary)
@@ -1123,8 +1131,12 @@
     }
   }
 
-  DartType getNullabilityObliviousStandardUpperBound(
+  DartType _getNullabilityObliviousStandardUpperBound(
       DartType type1, DartType type2, Library clientLibrary) {
+    /*assert(type1 == legacyErasure(coreTypes, type1),
+        "Non-legacy type $type1 in inference.");
+    assert(type2 == legacyErasure(coreTypes, type2),
+        "Non-legacy type $type2 in inference.");*/
     // For all types T, SUB(T,T) = T.  Note that we don't test for equality
     // because we don't want to make the algorithm quadratic.  This is ok
     // because the check is not needed for correctness; it's just a speed
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 cdb7703..b0271ce 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
@@ -201,6 +201,7 @@
       statement.expression = inferrer.helper.wrapInProblem(
           new NullLiteral()..fileOffset = statement.fileOffset,
           messageReturnWithoutExpression,
+          statement.fileOffset,
           noLength)
         ..parent = statement;
       return false;
@@ -222,7 +223,10 @@
         flattenedExpressionType is! DynamicType &&
         flattenedExpressionType != inferrer.coreTypes.nullType) {
       statement.expression = inferrer.helper.wrapInProblem(
-          statement.expression, messageReturnFromVoidFunction, noLength)
+          statement.expression,
+          messageReturnFromVoidFunction,
+          statement.expression.fileOffset,
+          noLength)
         ..parent = statement;
       return false;
     }
@@ -234,9 +238,9 @@
         flattenedReturnType is! VoidType &&
         flattenedReturnType is! DynamicType &&
         flattenedReturnType != inferrer.coreTypes.nullType) {
-      statement.expression = inferrer.helper
-          .wrapInProblem(statement.expression, messageVoidExpression, noLength)
-            ..parent = statement;
+      statement.expression = inferrer.helper.wrapInProblem(statement.expression,
+          messageVoidExpression, statement.expression.fileOffset, noLength)
+        ..parent = statement;
       return false;
     }
 
@@ -526,12 +530,6 @@
 
   NnbdMode get nnbdMode => library.loader.nnbdMode;
 
-  bool get performNnbdChecks {
-    return !isTopLevel &&
-        isNonNullableByDefault &&
-        library.loader.performNnbdChecks;
-  }
-
   DartType computeNullable(DartType type) {
     if (type == coreTypes.nullType || type is NeverType) {
       return coreTypes.nullType;
@@ -698,9 +696,8 @@
         preciseTypeErrorTemplate = _getPreciseTypeErrorTemplate(expression);
     AssignabilityKind kind = _computeAssignabilityKind(
         contextType, expressionType,
-        isStrongNullabilityMode: isNonNullableByDefault &&
-            performNnbdChecks &&
-            nnbdMode != NnbdMode.Weak,
+        isStrongNullabilityMode:
+            isNonNullableByDefault && nnbdMode != NnbdMode.Weak,
         isVoidAllowed: isVoidAllowed,
         isExpressionTypePrecise: preciseTypeErrorTemplate != null);
 
@@ -735,8 +732,8 @@
         break;
       case AssignabilityKind.unassignableVoid:
         // Error: not assignable.  Perform error recovery.
-        result =
-            helper.wrapInProblem(expression, messageVoidExpression, noLength);
+        result = helper.wrapInProblem(
+            expression, messageVoidExpression, expression.fileOffset, noLength);
         break;
       case AssignabilityKind.unassignablePrecise:
         // The type of the expression is known precisely, so an implicit
@@ -745,6 +742,7 @@
             expression,
             preciseTypeErrorTemplate.withArguments(
                 expressionType, contextType, isNonNullableByDefault),
+            expression.fileOffset,
             noLength);
         break;
       case AssignabilityKind.unassignableTearoff:
@@ -758,9 +756,7 @@
         // of code generation, and the inability to tear off from a
         // potentially nullable receiver shouldn't arise as an issue in any
         // mode other than the strong mode.
-        assert(isNonNullableByDefault &&
-            performNnbdChecks &&
-            nnbdMode != NnbdMode.Weak);
+        assert(isNonNullableByDefault && nnbdMode != NnbdMode.Weak);
 
         result = _wrapTearoffErrorExpression(
             expression, contextType, templateNullableTearoffError);
@@ -770,9 +766,7 @@
     }
 
     // Report warnings in weak mode.
-    if (isNonNullableByDefault &&
-        performNnbdChecks &&
-        nnbdMode == NnbdMode.Weak) {
+    if (isNonNullableByDefault && nnbdMode == NnbdMode.Weak) {
       AssignabilityKind weakKind = _computeAssignabilityKind(
           contextType, expressionType,
           isStrongNullabilityMode: true,
@@ -838,7 +832,7 @@
           // mode.
           assert(nnbdMode == NnbdMode.Weak);
 
-          if (isNonNullableByDefault && performNnbdChecks) {
+          if (isNonNullableByDefault) {
             result = _wrapTearoffErrorExpression(
                 expression, contextType, templateNullableTearoffWarning);
           }
@@ -866,7 +860,10 @@
       ..fileOffset = expression.fileOffset;
     if (contextType is! InvalidType) {
       errorNode = helper.wrapInProblem(
-          errorNode, template.withArguments(callName.name), noLength);
+          errorNode,
+          template.withArguments(callName.name),
+          errorNode.fileOffset,
+          noLength);
     }
     return errorNode;
   }
@@ -891,6 +888,7 @@
           errorNode,
           (template ?? templateInvalidAssignmentError).withArguments(
               expressionType, contextType, isNonNullableByDefault),
+          errorNode.fileOffset,
           noLength);
     }
     return errorNode;
@@ -2366,8 +2364,12 @@
       LocatedMessage argMessage =
           helper.checkArgumentsForType(calleeType, arguments, offset);
       if (argMessage != null) {
-        helper.addProblem(
-            argMessage.messageObject, argMessage.charOffset, argMessage.length);
+        return new WrapInProblemInferenceResult(
+            const InvalidType(),
+            argMessage.messageObject,
+            argMessage.charOffset,
+            argMessage.length,
+            helper);
       } else {
         // Argument counts and names match. Compare types.
         int positionalShift = isImplicitExtensionMember ? 1 : 0;
@@ -2422,7 +2424,7 @@
         "Inferred return type $inferredType contains free variables."
         "Inferred function type: $calleeType.");
 
-    if (isNonNullableByDefault && performNnbdChecks) {
+    if (isNonNullableByDefault) {
       if (receiverType != null &&
           receiverType is! DynamicType &&
           isPotentiallyNullable(receiverType, coreTypes.futureOrClass) &&
@@ -2442,6 +2444,7 @@
               inferredType,
               templateNullableMethodCallError.withArguments(
                   targetName.name, receiverType, isNonNullableByDefault),
+              offset,
               errorSpanLength,
               helper);
         }
@@ -2558,7 +2561,7 @@
         formal.type = demoteTypeInLibrary(inferredType, library.library);
       }
 
-      if (isNonNullableByDefault && performNnbdChecks) {
+      if (isNonNullableByDefault) {
         // If a parameter is a positional or named optional parameter and its
         // type is potentially non-nullable, it should have an initializer.
         bool isOptionalPositional = function.requiredParameterCount <= i &&
@@ -2589,7 +2592,7 @@
       }
     }
 
-    if (isNonNullableByDefault && performNnbdChecks) {
+    if (isNonNullableByDefault) {
       for (VariableDeclarationImpl formal in function.namedParameters) {
         // Required named parameters shouldn't have initializers.
         if (formal.isRequired && formal.hasDeclaredInitializer) {
@@ -2744,11 +2747,13 @@
       Arguments arguments,
       DartType typeContext,
       List<VariableDeclaration> hoistedExpressions,
-      {bool isExpressionInvocation}) {
+      {bool isExpressionInvocation,
+      Name implicitInvocationPropertyName}) {
     assert(isExpressionInvocation != null);
     Expression error = createMissingMethodInvocation(
         fileOffset, receiver, receiverType, name, arguments,
-        isExpressionInvocation: isExpressionInvocation);
+        isExpressionInvocation: isExpressionInvocation,
+        implicitInvocationPropertyName: implicitInvocationPropertyName);
     inferInvocation(typeContext, fileOffset, unknownFunction, arguments, name,
         hoistedExpressions: hoistedExpressions, receiverType: receiverType);
     assert(name != equalsName);
@@ -2771,31 +2776,29 @@
     DartType calleeType = getGetterType(target, receiverType);
     FunctionType functionType = getFunctionType(target, receiverType);
 
-    // TODO(johnniwinther): Disallow all implicit non-function calls?
-    if (calleeType is! DynamicType &&
-        !(calleeType is InterfaceType &&
-            calleeType.classNode == coreTypes.functionClass) &&
-        identical(functionType, unknownFunction)) {
-      Expression error = helper.buildProblem(
-          // TODO(johnniwinther): Use a different message for implicit .call.
-          templateInvokeNonFunction.withArguments(name.name),
-          fileOffset,
-          noLength);
-      return new ExpressionInferenceResult(const DynamicType(), error);
+    if (target.extensionMethodKind == ProcedureKind.Getter) {
+      StaticInvocation staticInvocation = transformExtensionMethodInvocation(
+          fileOffset, target, receiver, new Arguments.empty());
+      return inferMethodInvocation(fileOffset, nullAwareGuards,
+          staticInvocation, calleeType, callName, arguments, typeContext,
+          hoistedExpressions: hoistedExpressions,
+          isExpressionInvocation: false,
+          implicitInvocationPropertyName: name);
+    } else {
+      StaticInvocation staticInvocation = transformExtensionMethodInvocation(
+          fileOffset, target, receiver, arguments);
+      InvocationInferenceResult result = inferInvocation(typeContext,
+          fileOffset, functionType, staticInvocation.arguments, name,
+          hoistedExpressions: hoistedExpressions,
+          receiverType: receiverType,
+          isImplicitExtensionMember: true);
+      if (!isTopLevel) {
+        library.checkBoundsInStaticInvocation(staticInvocation,
+            typeSchemaEnvironment, helper.uri, getTypeArgumentsInfo(arguments));
+      }
+      return createNullAwareExpressionInferenceResult(result.inferredType,
+          result.applyResult(staticInvocation), nullAwareGuards);
     }
-    StaticInvocation staticInvocation = transformExtensionMethodInvocation(
-        fileOffset, target, receiver, arguments);
-    InvocationInferenceResult result = inferInvocation(
-        typeContext, fileOffset, functionType, staticInvocation.arguments, name,
-        hoistedExpressions: hoistedExpressions,
-        receiverType: receiverType,
-        isImplicitExtensionMember: true);
-    if (!isTopLevel) {
-      library.checkBoundsInStaticInvocation(staticInvocation,
-          typeSchemaEnvironment, helper.uri, getTypeArgumentsInfo(arguments));
-    }
-    return createNullAwareExpressionInferenceResult(result.inferredType,
-        result.applyResult(staticInvocation), nullAwareGuards);
   }
 
   ExpressionInferenceResult _inferFunctionInvocation(
@@ -2858,20 +2861,6 @@
     DartType calleeType = getGetterType(target, receiverType);
     FunctionType functionType = getFunctionType(target, receiverType);
 
-    // TODO(johnniwinther): Refactor to avoid this test in multiple places,
-    // either by providing a shared helper method or avoiding the calleeType/
-    // functionType distinction altogether.
-    if (!target.isUnresolved &&
-        calleeType is! DynamicType &&
-        !(calleeType is InterfaceType &&
-            calleeType.classNode == coreTypes.functionClass) &&
-        identical(functionType, unknownFunction)) {
-      Expression error = helper.buildProblem(
-          templateInvokeNonFunction.withArguments(methodName.name),
-          fileOffset,
-          noLength);
-      return new ExpressionInferenceResult(const DynamicType(), error);
-    }
     bool contravariantCheck = false;
     if (receiver is! ThisExpression &&
         method != null &&
@@ -2951,18 +2940,6 @@
     DartType calleeType = getGetterType(target, receiverType);
     FunctionType functionType = getFunctionTypeForImplicitCall(calleeType);
 
-    if (!target.isUnresolved &&
-        calleeType is! DynamicType &&
-        !(calleeType is InterfaceType &&
-            calleeType.classNode == coreTypes.functionClass) &&
-        identical(functionType, unknownFunction)) {
-      Expression error = helper.buildProblem(
-          templateInvokeNonFunction.withArguments(getter.name.name),
-          fileOffset,
-          noLength);
-      return new ExpressionInferenceResult(const DynamicType(), error);
-    }
-
     List<VariableDeclaration> locallyHoistedExpressions;
     if (hoistedExpressions == null) {
       hoistedExpressions = locallyHoistedExpressions = <VariableDeclaration>[];
@@ -2999,7 +2976,8 @@
         arguments,
         typeContext,
         hoistedExpressions: hoistedExpressions,
-        isExpressionInvocation: false);
+        isExpressionInvocation: false,
+        implicitInvocationPropertyName: getter.name);
 
     if (isExpressionInvocation) {
       Expression error = helper.buildProblem(
@@ -3074,17 +3052,6 @@
     DartType calleeType = getGetterType(target, receiverType);
     FunctionType functionType = getFunctionTypeForImplicitCall(calleeType);
 
-    if (calleeType is! DynamicType &&
-        !(calleeType is InterfaceType &&
-            calleeType.classNode == coreTypes.functionClass) &&
-        identical(functionType, unknownFunction)) {
-      Expression error = helper.buildProblem(
-          templateInvokeNonFunction.withArguments(target.member.name.name),
-          fileOffset,
-          noLength);
-      return new ExpressionInferenceResult(const DynamicType(), error);
-    }
-
     List<VariableDeclaration> locallyHoistedExpressions;
     if (hoistedExpressions == null) {
       hoistedExpressions = locallyHoistedExpressions = <VariableDeclaration>[];
@@ -3122,7 +3089,8 @@
         arguments,
         typeContext,
         isExpressionInvocation: false,
-        hoistedExpressions: hoistedExpressions);
+        hoistedExpressions: hoistedExpressions,
+        implicitInvocationPropertyName: field.name);
 
     if (isExpressionInvocation) {
       Expression error = helper.buildProblem(
@@ -3166,6 +3134,7 @@
       Arguments arguments,
       DartType typeContext,
       {bool isExpressionInvocation,
+      Name implicitInvocationPropertyName,
       List<VariableDeclaration> hoistedExpressions}) {
     assert(isExpressionInvocation != null);
     ObjectAccessTarget target = findInterfaceMember(
@@ -3235,7 +3204,8 @@
             arguments,
             typeContext,
             hoistedExpressions,
-            isExpressionInvocation: isExpressionInvocation);
+            isExpressionInvocation: isExpressionInvocation,
+            implicitInvocationPropertyName: implicitInvocationPropertyName);
       case ObjectAccessTargetKind.dynamic:
       case ObjectAccessTargetKind.invalid:
       case ObjectAccessTargetKind.unresolved:
@@ -3315,15 +3285,6 @@
     DartType calleeType = getGetterType(target, receiverType);
     FunctionType functionType = getFunctionType(target, receiverType);
 
-    if (!target.isUnresolved &&
-        calleeType is! DynamicType &&
-        !(calleeType is InterfaceType &&
-            calleeType.classNode == coreTypes.functionClass) &&
-        identical(functionType, unknownFunction)) {
-      Expression error = helper.wrapInProblem(expression,
-          templateInvokeNonFunction.withArguments(methodName.name), noLength);
-      return new ExpressionInferenceResult(const DynamicType(), error);
-    }
     InvocationInferenceResult result = inferInvocation(
         typeContext, fileOffset, functionType, arguments, target.member?.name,
         isOverloadedArithmeticOperator: isOverloadedArithmeticOperator,
@@ -3645,11 +3606,17 @@
 
   Expression createMissingMethodInvocation(int fileOffset, Expression receiver,
       DartType receiverType, Name name, Arguments arguments,
-      {bool isExpressionInvocation}) {
+      {bool isExpressionInvocation, Name implicitInvocationPropertyName}) {
     assert(isExpressionInvocation != null);
     if (isTopLevel) {
       return engine.forest
           .createMethodInvocation(fileOffset, receiver, name, arguments);
+    } else if (implicitInvocationPropertyName != null) {
+      return helper.buildProblem(
+          templateInvokeNonFunction
+              .withArguments(implicitInvocationPropertyName.name),
+          fileOffset,
+          implicitInvocationPropertyName.name.length);
     } else {
       return helper.buildProblem(
           templateUndefinedMethod.withArguments(name.name,
@@ -3985,16 +3952,18 @@
 
   final Message message;
 
+  final int fileOffset;
+
   final int length;
 
   final InferenceHelper helper;
 
-  WrapInProblemInferenceResult(
-      this.inferredType, this.message, this.length, this.helper);
+  WrapInProblemInferenceResult(this.inferredType, this.message, this.fileOffset,
+      this.length, this.helper);
 
   @override
   Expression applyResult(Expression expression) {
-    return helper.wrapInProblem(expression, message, length);
+    return helper.wrapInProblem(expression, message, fileOffset, length);
   }
 }
 
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 2ae59d3..adb3a6e 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -219,6 +219,8 @@
 ExplicitExtensionTypeArgumentMismatch/example: Fail
 ExportAfterPart/part_wrapped_script1: Fail
 ExportAfterPart/script1: Fail
+ExportOptOutFromOptIn/analyzerCode: Fail
+ExportOptOutFromOptIn/part_wrapped_script: Fail
 ExpressionNotMetadata/analyzerCode: Fail
 ExpressionNotMetadata/example: Fail
 ExtendingEnum/example: Fail
@@ -646,14 +648,6 @@
 TypeArgumentsOnTypeVariable/script1: Fail
 TypeNotFound/example: Fail
 TypeVariableDuplicatedName/example: Fail
-TypeVariableInStaticContext/declaration1: Fail # Unfortunate message from outline phase.
-TypeVariableInStaticContext/declaration2: Fail # Unfortunate message from outline phase.
-TypeVariableInStaticContext/declaration3: Fail # Unfortunate message from outline phase.
-TypeVariableInStaticContext/declaration4: Fail # Unfortunate message from outline phase.
-TypeVariableInStaticContext/part_wrapped_declaration1: Fail
-TypeVariableInStaticContext/part_wrapped_declaration2: Fail
-TypeVariableInStaticContext/part_wrapped_declaration3: Fail
-TypeVariableInStaticContext/part_wrapped_declaration4: Fail
 TypeVariableSameNameAsEnclosing/example: Fail
 TypedefNotFunction/example: Fail
 TypedefNotType/example: Fail # Feature not yet enabled by default.
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index edbf467..12dc0e6 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -4046,3 +4046,13 @@
 
 NonAgnosticConstant:
   template: "Constant value is not strong/weak mode agnostic."
+
+ExportOptOutFromOptIn:
+  template: "Null safe libraries are not allowed to export declarations from of opt-out libraries."
+  configuration: nnbd-strong
+  script:
+    main.dart: |
+      export 'lib.dart';
+    lib.dart: |
+      // @dart=2.5
+      class A {}
diff --git a/pkg/front_end/test/fasta/messages_suite.dart b/pkg/front_end/test/fasta/messages_suite.dart
index 03da9f6..cb0f930 100644
--- a/pkg/front_end/test/fasta/messages_suite.dart
+++ b/pkg/front_end/test/fasta/messages_suite.dart
@@ -78,7 +78,6 @@
   CompilerOptions apply(CompilerOptions options) {
     if (nnbdMode != null) {
       options.experimentalFlags[ExperimentalFlag.nonNullable] = true;
-      options.performNnbdChecks = true;
       options.nnbdMode = nnbdMode;
     }
     return options;
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 61b94ee..de177ef 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -153,7 +153,6 @@
 class TestOptions {
   final Map<ExperimentalFlag, bool> _experimentalFlags;
   final bool forceLateLowering;
-  final bool forceNnbdChecks;
   final bool forceNoExplicitGetterCalls;
   final bool nnbdAgnosticMode;
   final String target;
@@ -161,14 +160,12 @@
 
   TestOptions(this._experimentalFlags,
       {this.forceLateLowering: false,
-      this.forceNnbdChecks: false,
       this.forceNoExplicitGetterCalls: false,
       this.nnbdAgnosticMode: false,
       this.target: "vm",
       // can be null
       this.overwriteCurrentSdkVersion})
       : assert(forceLateLowering != null),
-        assert(forceNnbdChecks != null),
         assert(forceNoExplicitGetterCalls != null),
         assert(nnbdAgnosticMode != null),
         assert(target != null);
@@ -294,14 +291,12 @@
     TestOptions testOptions = _testOptions[directory.uri];
     if (testOptions == null) {
       bool forceLateLowering = false;
-      bool forceNnbdChecks = false;
       bool forceNoExplicitGetterCalls = false;
       bool nnbdAgnosticMode = false;
       String target = "vm";
       if (directory.uri == baseUri) {
         testOptions = new TestOptions({},
             forceLateLowering: forceLateLowering,
-            forceNnbdChecks: forceNnbdChecks,
             forceNoExplicitGetterCalls: forceNoExplicitGetterCalls,
             nnbdAgnosticMode: nnbdAgnosticMode,
             target: target);
@@ -321,8 +316,6 @@
                   line.substring(overwriteCurrentSdkVersion.length);
             } else if (line.startsWith(Flags.forceLateLowering)) {
               forceLateLowering = true;
-            } else if (line.startsWith(Flags.forceNnbdChecks)) {
-              forceNnbdChecks = true;
             } else if (line.startsWith(Flags.forceNoExplicitGetterCalls)) {
               forceNoExplicitGetterCalls = true;
             } else if (line.startsWith(Flags.forceNoExplicitGetterCalls)) {
@@ -344,7 +337,6 @@
                   onWarning: (String message) =>
                       throw new ArgumentError(message)),
               forceLateLowering: forceLateLowering,
-              forceNnbdChecks: forceNnbdChecks,
               forceNoExplicitGetterCalls: forceNoExplicitGetterCalls,
               nnbdAgnosticMode: nnbdAgnosticMode,
               target: target,
@@ -621,7 +613,6 @@
         }
         ..environmentDefines = {}
         ..experimentalFlags = experimentalFlags
-        ..performNnbdChecks = testOptions.forceNnbdChecks
         ..nnbdMode = nnbdMode
         ..librariesSpecificationUri = librariesSpecificationUri;
       if (testOptions.overwriteCurrentSdkVersion != null) {
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index f38f1d0..d83c19d 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -344,6 +344,7 @@
 exp
 expect
 expense
+exportable
 exportee
 exportees
 expr
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 68fea26..00036f4 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -581,6 +581,7 @@
 consisting
 consists
 console
+consolidated
 const
 constant
 constants
@@ -2932,6 +2933,7 @@
 times
 timing
 tip
+title
 to
 today
 together
@@ -2985,6 +2987,7 @@
 trick
 tried
 tries
+trigger
 triggered
 trim
 trimmed
diff --git a/pkg/front_end/test/spell_checking_list_messages.txt b/pkg/front_end/test/spell_checking_list_messages.txt
index 358ed80..1dbcdac 100644
--- a/pkg/front_end/test/spell_checking_list_messages.txt
+++ b/pkg/front_end/test/spell_checking_list_messages.txt
@@ -42,6 +42,7 @@
 nosuchmethod
 num1%.3ms
 o
+opt
 opts
 part(s)
 patch(es)
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 0d1bb73..46fbd01 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -199,6 +199,19 @@
 five
 floor
 fluctuate
+foo1
+foo10
+foo12
+foo13
+foo14
+foo15
+foo2
+foo4
+foo5
+foo6
+foo7
+foo8
+foo9
 foos
 forbidden
 forces
@@ -277,6 +290,31 @@
 linux
 listening
 ll
+local1a
+local1b
+local1c
+local1d
+local1e
+local1f
+local1g
+local1h
+local1i
+local2a
+local2b
+local2c
+local2d
+local2e
+local2f
+local2g
+local2h
+local3a
+local3b
+local3c
+local3d
+local3e
+local3f
+local3g
+local3h
 logd
 logs
 loo
@@ -315,6 +353,7 @@
 oh
 okay
 ooo
+ops
 optimal
 oracle
 outbound
@@ -329,6 +368,7 @@
 phrase
 pink
 places
+plug
 pointed
 policy
 pooled
diff --git a/pkg/front_end/test/test_generator_test.dart b/pkg/front_end/test/test_generator_test.dart
new file mode 100644
index 0000000..d0e3e1a
--- /dev/null
+++ b/pkg/front_end/test/test_generator_test.dart
@@ -0,0 +1,228 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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 exitCode, File, stdout;
+
+import 'package:front_end/src/api_prototype/compiler_options.dart';
+import 'package:front_end/src/api_prototype/memory_file_system.dart';
+import 'package:front_end/src/compute_platform_binaries_location.dart';
+import 'package:front_end/src/fasta/kernel/utils.dart';
+import 'package:front_end/src/fasta/messages.dart';
+import 'package:kernel/binary/ast_to_binary.dart';
+
+import 'package:kernel/kernel.dart' show Component;
+
+import 'incremental_load_from_dill_suite.dart' as helper;
+
+main() async {
+  TestCompiler compiler = await TestCompiler.initialize();
+  bool hasNewline = true;
+  int numErrors = 0;
+  List<String> errorSource = [];
+  for (Generator outerContext in generateOuterContext()) {
+    for (Generator innerContext
+        in generateInnerContext(outerContext.typeParameters)) {
+      for (Generator expression in generateExpression([]
+        ..addAll(outerContext.typeParameters)
+        ..addAll(innerContext.typeParameters))) {
+        String source = outerContext
+            .generate(innerContext.generate(expression.generate("")));
+        String compileResult = await compiler.compile(source);
+        if (compileResult != "") {
+          if (!hasNewline) print("");
+          hasNewline = true;
+          print(source);
+          print(compileResult);
+          print("\n\n----------\n\n");
+          numErrors++;
+          errorSource.add(source);
+        } else {
+          hasNewline = false;
+          stdout.write(".");
+        }
+      }
+    }
+  }
+
+  if (numErrors > 0) {
+    if (!hasNewline) print("");
+    hasNewline = true;
+    print("Found $numErrors errors on these programs:");
+    print("");
+    for (String source in errorSource) {
+      print(source);
+      print("----");
+    }
+    exitCode = 1;
+  }
+  if (!hasNewline) print("");
+}
+
+const Set<Code> ignoredCodes = {
+  codeInvalidAssignmentError,
+  codeTypeVariableInStaticContext,
+  codeNonInstanceTypeVariableUse,
+  codeExtensionDeclaresInstanceField,
+  codeExtraneousModifier,
+};
+
+class TestCompiler {
+  final Uri testUri;
+  final MemoryFileSystem fs;
+  final Set<String> formattedErrors;
+  final Set<String> formattedWarnings;
+  final helper.TestIncrementalCompiler compiler;
+  final List<Code> formattedErrorsCodes;
+  final List<Code> formattedWarningsCodes;
+
+  TestCompiler._(
+      this.testUri,
+      this.fs,
+      this.formattedErrors,
+      this.formattedWarnings,
+      this.formattedErrorsCodes,
+      this.formattedWarningsCodes,
+      this.compiler);
+
+  Future<String> compile(String src) async {
+    StringBuffer sb = new StringBuffer();
+    fs.entityForUri(testUri).writeAsStringSync(src);
+    compiler.invalidate(testUri);
+    Component result = await compiler.computeDelta(entryPoints: [testUri]);
+    Iterator<Code> codeIterator = formattedWarningsCodes.iterator;
+    for (String warning in formattedWarnings) {
+      codeIterator.moveNext();
+      Code code = codeIterator.current;
+      if (ignoredCodes.contains(code)) continue;
+      sb.writeln("Warning: $warning ($code)");
+    }
+    codeIterator = formattedErrorsCodes.iterator;
+    for (String error in formattedErrors) {
+      codeIterator.moveNext();
+      Code code = codeIterator.current;
+      if (ignoredCodes.contains(code)) continue;
+      sb.writeln("Error: $error ($code)");
+    }
+    formattedWarnings.clear();
+    formattedWarningsCodes.clear();
+    formattedErrors.clear();
+    formattedErrorsCodes.clear();
+
+    try {
+      ByteSink byteSink = new ByteSink();
+      final BinaryPrinter printer = new BinaryPrinter(byteSink);
+      printer.writeComponentFile(result);
+    } catch (e, st) {
+      sb.writeln("Error: Crash when serializing: $e ($st)");
+    }
+
+    return sb.toString();
+  }
+
+  static Future<TestCompiler> initialize() async {
+    final Uri base = Uri.parse("org-dartlang-test:///");
+    final Uri sdkSummary = base.resolve("vm_platform_strong.dill");
+    final Uri sdkRoot = computePlatformBinariesLocation(forceBuildDir: true);
+    Uri platformUri = sdkRoot.resolve("vm_platform_strong.dill");
+    final List<int> sdkSummaryData =
+        await new File.fromUri(platformUri).readAsBytes();
+    MemoryFileSystem fs = new MemoryFileSystem(base);
+    fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
+
+    CompilerOptions options = helper.getOptions(targetName: "VM");
+    options.fileSystem = fs;
+    options.sdkRoot = null;
+    options.sdkSummary = sdkSummary;
+    options.omitPlatform = true;
+    options.verify = true;
+
+    final Set<String> formattedErrors = new Set<String>();
+    final Set<String> formattedWarnings = new Set<String>();
+    final List<Code> formattedErrorsCodes = new List<Code>();
+    final List<Code> formattedWarningsCodes = new List<Code>();
+
+    options.onDiagnostic = (DiagnosticMessage message) {
+      String stringId = message.ansiFormatted.join("\n");
+      if (message is FormattedMessage) {
+        stringId = message.toJsonString();
+      } else {
+        throw "Unsupported currently";
+      }
+      FormattedMessage formattedMessage = message;
+      if (message.severity == Severity.error) {
+        if (!formattedErrors.add(stringId)) {
+          throw "Got the same message twice: ${stringId}";
+        }
+        formattedErrorsCodes.add(formattedMessage.code);
+      } else if (message.severity == Severity.warning) {
+        if (!formattedWarnings.add(stringId)) {
+          throw "Got the same message twice: ${stringId}";
+        }
+        formattedWarningsCodes.add(formattedMessage.code);
+      }
+    };
+
+    Uri testUri = base.resolve("test.dart");
+    helper.TestIncrementalCompiler compiler =
+        new helper.TestIncrementalCompiler(options, testUri);
+
+    return new TestCompiler._(testUri, fs, formattedErrors, formattedWarnings,
+        formattedErrorsCodes, formattedWarningsCodes, compiler);
+  }
+}
+
+Iterable<Generator> generateOuterContext() sync* {
+  yield new Generator([], "", ""); // top-level.
+  yield new Generator([], "class C {\n", "\n}");
+  yield new Generator(["T1"], "class C<T1> {\n", "\n}");
+  yield new Generator(["T1"],
+      "class NotList<NT1>{}\nclass C<T1> extends NotList<T1> {\n", "\n}");
+  yield new Generator([], "extension E on String {\n", "\n}");
+  yield new Generator(["E1"], "extension E<E1> on String {\n", "\n}");
+  yield new Generator(["E1"], "extension E<E1> on List<E1> {\n", "\n}");
+}
+
+Iterable<Generator> generateInnerContext(
+    List<String> knownTypeParameters) sync* {
+  for (String static in ["", "static "]) {
+    yield new Generator([], "${static}int method() {\nreturn ", ";\n}");
+    yield new Generator(
+        ["T2"], "${static}int method<T2>() {\n  return ", ";\n}");
+    for (String typeParameter in knownTypeParameters) {
+      yield new Generator(
+          [], "${static}$typeParameter method() {\nreturn ", ";\n}");
+    }
+    yield new Generator([], "${static}int field = ", ";");
+    yield new Generator([], "${static}int field = () { return ", "; }();");
+    yield new Generator([], "${static}var field = ", ";");
+    yield new Generator([], "${static}var field = () { return ", "; }();");
+
+    for (String typeParameter in knownTypeParameters) {
+      yield new Generator(["T2"], "${static}int field = <T2>() { return ",
+          "; }<$typeParameter>();");
+      yield new Generator([], "${static}${typeParameter} field = ", ";");
+      yield new Generator(
+          [], "${static}${typeParameter} field = () { return ", "; }();");
+    }
+  }
+}
+
+Iterable<Generator> generateExpression(List<String> knownTypeParameters) sync* {
+  yield new Generator([], "42", "");
+  for (String typeParameter in knownTypeParameters) {
+    yield new Generator([], "() { $typeParameter x = null; return x; }()", "");
+  }
+}
+
+class Generator {
+  final List<String> typeParameters;
+  final String beforePlug;
+  final String afterPlug;
+
+  Generator(this.typeParameters, this.beforePlug, this.afterPlug);
+
+  String generate(String plug) {
+    return "${beforePlug}${plug}${afterPlug}";
+  }
+}
diff --git a/pkg/front_end/testcases/agnostic/test.options b/pkg/front_end/testcases/agnostic/test.options
index d9c0d26..79dd0e8 100644
--- a/pkg/front_end/testcases/agnostic/test.options
+++ b/pkg/front_end/testcases/agnostic/test.options
@@ -1,3 +1,2 @@
 --enable-experiment=non-nullable
---force-nnbd-checks
 --nnbd-agnostic
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart b/pkg/front_end/testcases/extensions/call_methods.dart
index 1850a3b..cf0ecfab 100644
--- a/pkg/front_end/testcases/extensions/call_methods.dart
+++ b/pkg/front_end/testcases/extensions/call_methods.dart
@@ -23,7 +23,6 @@
 }
 
 main() {
-  // TODO(johnniwinther): Should the be an error?
   ""();
 }
 
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart.strong.expect b/pkg/front_end/testcases/extensions/call_methods.dart.strong.expect
index 6227c6f..e831fc5 100644
--- a/pkg/front_end/testcases/extensions/call_methods.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/call_methods.dart.strong.expect
@@ -2,36 +2,49 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extensions/call_methods.dart:27:5: Error: Too many positional arguments: 0 allowed, but 1 found.
+// pkg/front_end/testcases/extensions/call_methods.dart:30:4: Error: Too many positional arguments: 0 allowed, but 1 found.
 // Try removing the extra positional arguments.
-//   ""();
-//     ^
-//
-// pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: 'call' isn't a function or method and can't be invoked.
 //   1(10);
 //    ^
 //
-// pkg/front_end/testcases/extensions/call_methods.dart:32:4: Error: 'call' isn't a function or method and can't be invoked.
+// pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
 //   1("10");
 //    ^
 //
-// pkg/front_end/testcases/extensions/call_methods.dart:33:6: Error: 'call' isn't a function or method and can't be invoked.
+// pkg/front_end/testcases/extensions/call_methods.dart:32:6: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
 //   1.0(10);
 //      ^
 //
-// pkg/front_end/testcases/extensions/call_methods.dart:34:6: Error: 'call' isn't a function or method and can't be invoked.
+// pkg/front_end/testcases/extensions/call_methods.dart:33:6: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
 //   1.0("10");
 //      ^
 //
-// pkg/front_end/testcases/extensions/call_methods.dart:36:4: Error: 'call' isn't a function or method and can't be invoked.
+// pkg/front_end/testcases/extensions/call_methods.dart:35:4: Error: Too many positional arguments: 0 allowed, but 1 found.
+// Try removing the extra positional arguments.
 //   a(2);
 //    ^
 //
-// pkg/front_end/testcases/extensions/call_methods.dart:37:4: Error: 'call' isn't a function or method and can't be invoked.
+// pkg/front_end/testcases/extensions/call_methods.dart:35:4: Error: Cannot invoke an instance of 'A' because it declares 'call' to be something other than a method.
+//  - 'A' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
+// Try changing 'call' to a method or explicitly invoke 'call'.
+//   a(2);
+//    ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:36:4: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
 //   a(2, "3");
 //    ^
 //
-// pkg/front_end/testcases/extensions/call_methods.dart:39:4: Error: Cannot invoke an instance of 'B' because it declares 'call' to be something other than a method.
+// pkg/front_end/testcases/extensions/call_methods.dart:36:4: Error: Cannot invoke an instance of 'A' because it declares 'call' to be something other than a method.
+//  - 'A' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
+// Try changing 'call' to a method or explicitly invoke 'call'.
+//   a(2, "3");
+//    ^
+//
+// pkg/front_end/testcases/extensions/call_methods.dart:38:4: Error: Cannot invoke an instance of 'B' because it declares 'call' to be something other than a method.
 //  - 'B' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
 // Try changing 'call' to a method or explicitly invoke 'call'.
 //   b();
@@ -70,30 +83,38 @@
 static method _extension#2|get#call(final core::String* #this) → () →* core::String*
   return () → core::String* => "My name is String";
 static method main() → dynamic {
-  self::_extension#2|get#call("");
+  self::_extension#2|get#call("").call();
 }
 static method errors() → dynamic {
-  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: 'call' isn't a function or method and can't be invoked.
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:30:4: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
   1(10);
-   ^";
-  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:32:4: Error: 'call' isn't a function or method and can't be invoked.
+   ^" in self::_extension#2|get#call(self::_extension#0|get#call(1)).call(10);
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
   1(\"10\");
-   ^";
-  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:33:6: Error: 'call' isn't a function or method and can't be invoked.
+   ^" in self::_extension#2|get#call(self::_extension#0|get#call(1)).call("10");
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:32:6: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
   1.0(10);
-     ^";
-  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:34:6: Error: 'call' isn't a function or method and can't be invoked.
+     ^" in self::_extension#2|get#call(self::_extension#1|get#call(1.0)).call(10);
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:33:6: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
   1.0(\"10\");
-     ^";
+     ^" in self::_extension#2|get#call(self::_extension#1|get#call(1.0)).call("10");
   self::A* a = new self::A::•();
-  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:36:4: Error: 'call' isn't a function or method and can't be invoked.
+  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:35:4: Error: Cannot invoke an instance of 'A' because it declares 'call' to be something other than a method.
+ - 'A' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
+Try changing 'call' to a method or explicitly invoke 'call'.
   a(2);
    ^";
-  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:37:4: Error: 'call' isn't a function or method and can't be invoked.
+  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:36:4: Error: Cannot invoke an instance of 'A' because it declares 'call' to be something other than a method.
+ - 'A' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
+Try changing 'call' to a method or explicitly invoke 'call'.
   a(2, \"3\");
    ^";
   self::B* b = new self::B::•();
-  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:39:4: Error: Cannot invoke an instance of 'B' because it declares 'call' to be something other than a method.
+  invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:38:4: Error: Cannot invoke an instance of 'B' because it declares 'call' to be something other than a method.
  - 'B' is from 'pkg/front_end/testcases/extensions/call_methods.dart'.
 Try changing 'call' to a method or explicitly invoke 'call'.
   b();
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/call_methods.dart.strong.transformed.expect
index 6227c6f..2c5009c 100644
--- a/pkg/front_end/testcases/extensions/call_methods.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/call_methods.dart.strong.transformed.expect
@@ -2,11 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/extensions/call_methods.dart:27:5: Error: Too many positional arguments: 0 allowed, but 1 found.
-// Try removing the extra positional arguments.
-//   ""();
-//     ^
-//
 // pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: 'call' isn't a function or method and can't be invoked.
 //   1(10);
 //    ^
@@ -70,7 +65,7 @@
 static method _extension#2|get#call(final core::String* #this) → () →* core::String*
   return () → core::String* => "My name is String";
 static method main() → dynamic {
-  self::_extension#2|get#call("");
+  self::_extension#2|get#call("").call();
 }
 static method errors() → dynamic {
   invalid-expression "pkg/front_end/testcases/extensions/call_methods.dart:31:4: Error: 'call' isn't a function or method and can't be invoked.
diff --git a/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart
new file mode 100644
index 0000000..8f41979
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 E<U> on String {
+  U field1 = null;
+  int field2 = () { U x = null; return null; }();
+  List<U> field3 = null;
+  U Function(U) field4 = null;
+  List<U> Function(List<U>) field5 = null;
+  int field6 = <E>() { E x = null; return null; }<String>();
+  int field7 = <E>() { E x = null; return null; }<U>();
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.outline.expect b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.outline.expect
new file mode 100644
index 0000000..a1e7455
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.outline.expect
@@ -0,0 +1,84 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:6:5: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   U field1 = null;
+//     ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:7:7: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   int field2 = () { U x = null; return null; }();
+//       ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:8:11: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   List<U> field3 = null;
+//           ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:9:17: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   U Function(U) field4 = null;
+//                 ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:10:29: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   List<U> Function(List<U>) field5 = null;
+//                             ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:11:7: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   int field6 = <E>() { E x = null; return null; }<String>();
+//       ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:12:7: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   int field7 = <E>() { E x = null; return null; }<U>();
+//       ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:6:3: Error: Type variables can't be used in static members.
+//   U field1 = null;
+//   ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:8:8: Error: Type variables can't be used in static members.
+//   List<U> field3 = null;
+//        ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:9:3: Error: Type variables can't be used in static members.
+//   U Function(U) field4 = null;
+//   ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:9:14: Error: Type variables can't be used in static members.
+//   U Function(U) field4 = null;
+//              ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:10:8: Error: Type variables can't be used in static members.
+//   List<U> Function(List<U>) field5 = null;
+//        ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:10:25: Error: Type variables can't be used in static members.
+//   List<U> Function(List<U>) field5 = null;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E<U extends core::Object* = dynamic> on core::String* {
+  field field1 = self::E|field1;
+  field field2 = self::E|field2;
+  field field3 = self::E|field3;
+  field field4 = self::E|field4;
+  field field5 = self::E|field5;
+  field field6 = self::E|field6;
+  field field7 = self::E|field7;
+}
+static field invalid-type E|field1;
+static field core::int* E|field2;
+static field core::List<invalid-type>* E|field3;
+static field (invalid-type) →* invalid-type E|field4;
+static field (core::List<invalid-type>*) →* core::List<invalid-type>* E|field5;
+static field core::int* E|field6;
+static field core::int* E|field7;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.strong.expect b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.strong.expect
new file mode 100644
index 0000000..69565ac
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.strong.expect
@@ -0,0 +1,100 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:6:5: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   U field1 = null;
+//     ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:7:7: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   int field2 = () { U x = null; return null; }();
+//       ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:8:11: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   List<U> field3 = null;
+//           ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:9:17: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   U Function(U) field4 = null;
+//                 ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:10:29: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   List<U> Function(List<U>) field5 = null;
+//                             ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:11:7: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   int field6 = <E>() { E x = null; return null; }<String>();
+//       ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:12:7: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   int field7 = <E>() { E x = null; return null; }<U>();
+//       ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:6:3: Error: Type variables can't be used in static members.
+//   U field1 = null;
+//   ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:8:8: Error: Type variables can't be used in static members.
+//   List<U> field3 = null;
+//        ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:9:3: Error: Type variables can't be used in static members.
+//   U Function(U) field4 = null;
+//   ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:9:14: Error: Type variables can't be used in static members.
+//   U Function(U) field4 = null;
+//              ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:10:8: Error: Type variables can't be used in static members.
+//   List<U> Function(List<U>) field5 = null;
+//        ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:10:25: Error: Type variables can't be used in static members.
+//   List<U> Function(List<U>) field5 = null;
+//                         ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:7:21: Error: Type variables can't be used in static members.
+//   int field2 = () { U x = null; return null; }();
+//                     ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:12:51: Error: Type variables can't be used in static members.
+//   int field7 = <E>() { E x = null; return null; }<U>();
+//                                                   ^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E<U extends core::Object* = dynamic> on core::String* {
+  field field1 = self::E|field1;
+  field field2 = self::E|field2;
+  field field3 = self::E|field3;
+  field field4 = self::E|field4;
+  field field5 = self::E|field5;
+  field field6 = self::E|field6;
+  field field7 = self::E|field7;
+}
+static field invalid-type E|field1 = null;
+static field core::int* E|field2 = (() → core::Null? {
+  invalid-type x = null;
+  return null;
+}).call();
+static field core::List<invalid-type>* E|field3 = null;
+static field (invalid-type) →* invalid-type E|field4 = null;
+static field (core::List<invalid-type>*) →* core::List<invalid-type>* E|field5 = null;
+static field core::int* E|field6 = (<E extends core::Object* = dynamic>() → core::Null? {
+  E* x = null;
+  return null;
+}).call<core::String*>();
+static field core::int* E|field7 = (<E extends core::Object* = dynamic>() → core::Null? {
+  E* x = null;
+  return null;
+}).call<invalid-type>();
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.strong.transformed.expect
new file mode 100644
index 0000000..69565ac
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.strong.transformed.expect
@@ -0,0 +1,100 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:6:5: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   U field1 = null;
+//     ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:7:7: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   int field2 = () { U x = null; return null; }();
+//       ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:8:11: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   List<U> field3 = null;
+//           ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:9:17: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   U Function(U) field4 = null;
+//                 ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:10:29: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   List<U> Function(List<U>) field5 = null;
+//                             ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:11:7: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   int field6 = <E>() { E x = null; return null; }<String>();
+//       ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:12:7: Error: Extensions can't declare instance fields
+// Try removing the field declaration or making it a static field
+//   int field7 = <E>() { E x = null; return null; }<U>();
+//       ^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:6:3: Error: Type variables can't be used in static members.
+//   U field1 = null;
+//   ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:8:8: Error: Type variables can't be used in static members.
+//   List<U> field3 = null;
+//        ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:9:3: Error: Type variables can't be used in static members.
+//   U Function(U) field4 = null;
+//   ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:9:14: Error: Type variables can't be used in static members.
+//   U Function(U) field4 = null;
+//              ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:10:8: Error: Type variables can't be used in static members.
+//   List<U> Function(List<U>) field5 = null;
+//        ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:10:25: Error: Type variables can't be used in static members.
+//   List<U> Function(List<U>) field5 = null;
+//                         ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:7:21: Error: Type variables can't be used in static members.
+//   int field2 = () { U x = null; return null; }();
+//                     ^
+//
+// pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart:12:51: Error: Type variables can't be used in static members.
+//   int field7 = <E>() { E x = null; return null; }<U>();
+//                                                   ^
+//
+import self as self;
+import "dart:core" as core;
+
+extension E<U extends core::Object* = dynamic> on core::String* {
+  field field1 = self::E|field1;
+  field field2 = self::E|field2;
+  field field3 = self::E|field3;
+  field field4 = self::E|field4;
+  field field5 = self::E|field5;
+  field field6 = self::E|field6;
+  field field7 = self::E|field7;
+}
+static field invalid-type E|field1 = null;
+static field core::int* E|field2 = (() → core::Null? {
+  invalid-type x = null;
+  return null;
+}).call();
+static field core::List<invalid-type>* E|field3 = null;
+static field (invalid-type) →* invalid-type E|field4 = null;
+static field (core::List<invalid-type>*) →* core::List<invalid-type>* E|field5 = null;
+static field core::int* E|field6 = (<E extends core::Object* = dynamic>() → core::Null? {
+  E* x = null;
+  return null;
+}).call<core::String*>();
+static field core::int* E|field7 = (<E extends core::Object* = dynamic>() → core::Null? {
+  E* x = null;
+  return null;
+}).call<invalid-type>();
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/issue39889.dart b/pkg/front_end/testcases/extensions/issue39889.dart
new file mode 100644
index 0000000..7ff900b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue39889.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 {}
+
+extension E on C {
+  void f(String b) {}
+}
+
+void main() {
+  dynamic b = '456';
+  var c = C();
+  c.f(b);
+}
diff --git a/pkg/front_end/testcases/extensions/issue39889.dart.outline.expect b/pkg/front_end/testcases/extensions/issue39889.dart.outline.expect
new file mode 100644
index 0000000..630c471
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue39889.dart.outline.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C*
+    ;
+}
+extension E on self::C* {
+  method f = self::E|f;
+  tearoff f = self::E|get#f;
+}
+static method E|f(final self::C* #this, core::String* b) → void
+  ;
+static method E|get#f(final self::C* #this) → (core::String*) →* void
+  return (core::String* b) → void => self::E|f(#this, b);
+static method main() → void
+  ;
diff --git a/pkg/front_end/testcases/extensions/issue39889.dart.strong.expect b/pkg/front_end/testcases/extensions/issue39889.dart.strong.expect
new file mode 100644
index 0000000..1a949ac
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue39889.dart.strong.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+}
+extension E on self::C* {
+  method f = self::E|f;
+  tearoff f = self::E|get#f;
+}
+static method E|f(final self::C* #this, core::String* b) → void {}
+static method E|get#f(final self::C* #this) → (core::String*) →* void
+  return (core::String* b) → void => self::E|f(#this, b);
+static method main() → void {
+  dynamic b = "456";
+  self::C* c = new self::C::•();
+  self::E|f(c, b as{TypeError,ForDynamic} core::String*);
+}
diff --git a/pkg/front_end/testcases/extensions/issue39889.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/issue39889.dart.strong.transformed.expect
new file mode 100644
index 0000000..1a949ac
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue39889.dart.strong.transformed.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  synthetic constructor •() → self::C*
+    : super core::Object::•()
+    ;
+}
+extension E on self::C* {
+  method f = self::E|f;
+  tearoff f = self::E|get#f;
+}
+static method E|f(final self::C* #this, core::String* b) → void {}
+static method E|get#f(final self::C* #this) → (core::String*) →* void
+  return (core::String* b) → void => self::E|f(#this, b);
+static method main() → void {
+  dynamic b = "456";
+  self::C* c = new self::C::•();
+  self::E|f(c, b as{TypeError,ForDynamic} core::String*);
+}
diff --git a/pkg/front_end/testcases/extensions/issue40596.dart b/pkg/front_end/testcases/extensions/issue40596.dart
new file mode 100644
index 0000000..733236c
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40596.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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';
+
+void main() {
+  var controller = StreamController<String>();
+  controller.stream((s) {
+    print(s);
+  });
+}
+
+extension Extension<T> on Stream<T> {
+  StreamSubscription<T> call(Function onData) {
+    return listen((d) {
+      onData(d);
+    });
+  }
+}
diff --git a/pkg/front_end/testcases/extensions/issue40596.dart.outline.expect b/pkg/front_end/testcases/extensions/issue40596.dart.outline.expect
new file mode 100644
index 0000000..026a6f7
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40596.dart.outline.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+extension Extension<T extends core::Object* = dynamic> on asy::Stream<T*>* {
+  method call = self::Extension|call;
+  tearoff call = self::Extension|get#call;
+}
+static method main() → void
+  ;
+static method Extension|call<T extends core::Object* = dynamic>(final asy::Stream<self::Extension|call::T*>* #this, core::Function* onData) → asy::StreamSubscription<self::Extension|call::T*>*
+  ;
+static method Extension|get#call<T extends core::Object* = dynamic>(final asy::Stream<self::Extension|get#call::T*>* #this) → (core::Function*) →* asy::StreamSubscription<self::Extension|get#call::T*>*
+  return (core::Function* onData) → asy::StreamSubscription<self::Extension|get#call::T*>* => self::Extension|call<self::Extension|get#call::T*>(#this, onData);
diff --git a/pkg/front_end/testcases/extensions/issue40596.dart.strong.expect b/pkg/front_end/testcases/extensions/issue40596.dart.strong.expect
new file mode 100644
index 0000000..f26640b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40596.dart.strong.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+extension Extension<T extends core::Object* = dynamic> on asy::Stream<T*>* {
+  method call = self::Extension|call;
+  tearoff call = self::Extension|get#call;
+}
+static method main() → void {
+  asy::StreamController<core::String*>* controller = asy::StreamController::•<core::String*>();
+  let final asy::StreamController<core::String*>* #t1 = controller in let final (dynamic) →* core::Null? #t2 = (dynamic s) → core::Null? {
+    core::print(s);
+  } in self::Extension|call<core::String*>(#t1.{asy::StreamController::stream}, #t2);
+}
+static method Extension|call<T extends core::Object* = dynamic>(final asy::Stream<self::Extension|call::T*>* #this, core::Function* onData) → asy::StreamSubscription<self::Extension|call::T*>* {
+  return #this.{asy::Stream::listen}((self::Extension|call::T* d) → core::Null? {
+    onData.call(d);
+  });
+}
+static method Extension|get#call<T extends core::Object* = dynamic>(final asy::Stream<self::Extension|get#call::T*>* #this) → (core::Function*) →* asy::StreamSubscription<self::Extension|get#call::T*>*
+  return (core::Function* onData) → asy::StreamSubscription<self::Extension|get#call::T*>* => self::Extension|call<self::Extension|get#call::T*>(#this, onData);
diff --git a/pkg/front_end/testcases/extensions/issue40596.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/issue40596.dart.strong.transformed.expect
new file mode 100644
index 0000000..f26640b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40596.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+extension Extension<T extends core::Object* = dynamic> on asy::Stream<T*>* {
+  method call = self::Extension|call;
+  tearoff call = self::Extension|get#call;
+}
+static method main() → void {
+  asy::StreamController<core::String*>* controller = asy::StreamController::•<core::String*>();
+  let final asy::StreamController<core::String*>* #t1 = controller in let final (dynamic) →* core::Null? #t2 = (dynamic s) → core::Null? {
+    core::print(s);
+  } in self::Extension|call<core::String*>(#t1.{asy::StreamController::stream}, #t2);
+}
+static method Extension|call<T extends core::Object* = dynamic>(final asy::Stream<self::Extension|call::T*>* #this, core::Function* onData) → asy::StreamSubscription<self::Extension|call::T*>* {
+  return #this.{asy::Stream::listen}((self::Extension|call::T* d) → core::Null? {
+    onData.call(d);
+  });
+}
+static method Extension|get#call<T extends core::Object* = dynamic>(final asy::Stream<self::Extension|get#call::T*>* #this) → (core::Function*) →* asy::StreamSubscription<self::Extension|get#call::T*>*
+  return (core::Function* onData) → asy::StreamSubscription<self::Extension|get#call::T*>* => self::Extension|call<self::Extension|get#call::T*>(#this, onData);
diff --git a/pkg/front_end/testcases/extensions/issue40713.dart b/pkg/front_end/testcases/extensions/issue40713.dart
new file mode 100644
index 0000000..609d2f4
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40713.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 SafeAccess<T> on Iterable<T> {
+  T get safeFirst {
+    return isNotEmpty ? first : null;
+  }
+}
+
+main() {}
+
+void test() {
+  final list = [];
+  list.safeFirst();
+  final list2 = <void Function(int)>[];
+  list2.safeFirst(0);
+}
+
+void errors() {
+  final list = <Object>[];
+  list.safeFirst();
+  final list2 = <void Function(int)>[];
+  list2.safeFirst();
+}
diff --git a/pkg/front_end/testcases/extensions/issue40713.dart.outline.expect b/pkg/front_end/testcases/extensions/issue40713.dart.outline.expect
new file mode 100644
index 0000000..9afde88
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40713.dart.outline.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+extension SafeAccess<T extends core::Object* = dynamic> on core::Iterable<T*>* {
+  get safeFirst = self::SafeAccess|get#safeFirst;
+}
+static method SafeAccess|get#safeFirst<T extends core::Object* = dynamic>(final core::Iterable<self::SafeAccess|get#safeFirst::T*>* #this) → self::SafeAccess|get#safeFirst::T*
+  ;
+static method main() → dynamic
+  ;
+static method test() → void
+  ;
+static method errors() → void
+  ;
diff --git a/pkg/front_end/testcases/extensions/issue40713.dart.strong.expect b/pkg/front_end/testcases/extensions/issue40713.dart.strong.expect
new file mode 100644
index 0000000..13b8a9d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40713.dart.strong.expect
@@ -0,0 +1,38 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/issue40713.dart:22:8: Error: 'safeFirst' isn't a function or method and can't be invoked.
+//   list.safeFirst();
+//        ^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/issue40713.dart:24:18: Error: Too few positional arguments: 1 required, 0 given.
+//   list2.safeFirst();
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+extension SafeAccess<T extends core::Object* = dynamic> on core::Iterable<T*>* {
+  get safeFirst = self::SafeAccess|get#safeFirst;
+}
+static method SafeAccess|get#safeFirst<T extends core::Object* = dynamic>(final core::Iterable<self::SafeAccess|get#safeFirst::T*>* #this) → self::SafeAccess|get#safeFirst::T* {
+  return #this.{core::Iterable::isNotEmpty} ?{self::SafeAccess|get#safeFirst::T*} #this.{core::Iterable::first} : null;
+}
+static method main() → dynamic {}
+static method test() → void {
+  final core::List<dynamic>* list = <dynamic>[];
+  self::SafeAccess|get#safeFirst<dynamic>(list).call();
+  final core::List<(core::int*) →* void>* list2 = <(core::int*) →* void>[];
+  self::SafeAccess|get#safeFirst<(core::int*) →* void>(list2).call(0);
+}
+static method errors() → void {
+  final core::List<core::Object*>* list = <core::Object*>[];
+  invalid-expression "pkg/front_end/testcases/extensions/issue40713.dart:22:8: Error: 'safeFirst' isn't a function or method and can't be invoked.
+  list.safeFirst();
+       ^^^^^^^^^";
+  final core::List<(core::int*) →* void>* list2 = <(core::int*) →* void>[];
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/extensions/issue40713.dart:24:18: Error: Too few positional arguments: 1 required, 0 given.
+  list2.safeFirst();
+                 ^" in self::SafeAccess|get#safeFirst<(core::int*) →* void>(list2).call();
+}
diff --git a/pkg/front_end/testcases/extensions/issue40713.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/issue40713.dart.strong.transformed.expect
new file mode 100644
index 0000000..cd9ba8b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40713.dart.strong.transformed.expect
@@ -0,0 +1,44 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/issue40713.dart:17:9: Error: 'safeFirst' isn't a function or method and can't be invoked.
+//   list2.safeFirst(0);
+//         ^
+//
+// pkg/front_end/testcases/extensions/issue40713.dart:22:8: Error: 'safeFirst' isn't a function or method and can't be invoked.
+//   list.safeFirst();
+//        ^
+//
+// pkg/front_end/testcases/extensions/issue40713.dart:24:9: Error: 'safeFirst' isn't a function or method and can't be invoked.
+//   list2.safeFirst();
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+extension SafeAccess<T extends core::Object* = dynamic> on core::Iterable<T*>* {
+  get safeFirst = self::SafeAccess|get#safeFirst;
+}
+static method SafeAccess|get#safeFirst<T extends core::Object* = dynamic>(final core::Iterable<self::SafeAccess|get#safeFirst::T*>* #this) → self::SafeAccess|get#safeFirst::T* {
+  return #this.{core::Iterable::isNotEmpty} ?{self::SafeAccess|get#safeFirst::T*} #this.{core::Iterable::first} : null;
+}
+static method main() → dynamic {}
+static method test() → void {
+  final core::List<dynamic>* list = <dynamic>[];
+  self::SafeAccess|get#safeFirst<dynamic>(list).call();
+  final core::List<(core::int*) →* void>* list2 = <(core::int*) →* void>[];
+  invalid-expression "pkg/front_end/testcases/extensions/issue40713.dart:17:9: Error: 'safeFirst' isn't a function or method and can't be invoked.
+  list2.safeFirst(0);
+        ^";
+}
+static method errors() → void {
+  final core::List<core::Object*>* list = <core::Object*>[];
+  invalid-expression "pkg/front_end/testcases/extensions/issue40713.dart:22:8: Error: 'safeFirst' isn't a function or method and can't be invoked.
+  list.safeFirst();
+       ^";
+  final core::List<(core::int*) →* void>* list2 = <(core::int*) →* void>[];
+  invalid-expression "pkg/front_end/testcases/extensions/issue40713.dart:24:9: Error: 'safeFirst' isn't a function or method and can't be invoked.
+  list2.safeFirst();
+        ^";
+}
diff --git a/pkg/front_end/testcases/extensions/issue40816.dart b/pkg/front_end/testcases/extensions/issue40816.dart
index d521d29..9e85e2c 100644
--- a/pkg/front_end/testcases/extensions/issue40816.dart
+++ b/pkg/front_end/testcases/extensions/issue40816.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
index abc752f..a0e237c 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.outline.expect
@@ -147,17 +147,17 @@
   synthetic constructor •() → self::Ci<self::Ci::T*>*
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
 }
-class Dc<T extends core::Object* = dynamic> extends core::Object {
+class Dc<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Dc<self::Dc::T*>*
     : super core::Object::•()
     ;
 }
-class Di<T extends core::Object* = dynamic> extends core::Object {
+class Di<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Di<self::Di::T*>*
     : super core::Object::•()
     ;
@@ -174,7 +174,7 @@
   synthetic constructor •() → self::Ei<self::Ei::T*>*
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -183,7 +183,7 @@
   synthetic constructor •() → self::F<self::F::T*>*
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
   synthetic constructor •() → self::Fc<self::Fc::T*>*
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
index c4ffb93..8ec61d3 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.expect
@@ -155,17 +155,17 @@
     : super core::Object::•()
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
 }
-class Dc<T extends core::Object* = dynamic> extends core::Object {
+class Dc<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Dc<self::Dc::T*>*
     : super core::Object::•()
     ;
 }
-class Di<T extends core::Object* = dynamic> extends core::Object {
+class Di<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Di<self::Di::T*>*
     : super core::Object::•()
     ;
@@ -185,7 +185,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
index 3dae0c6..397b6e06d 100644
--- a/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
@@ -155,17 +155,17 @@
     : super core::Object::•()
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
 }
-class Dc<T extends core::Object* = dynamic> extends core::Object {
+class Dc<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Dc<self::Dc::T*>*
     : super core::Object::•()
     ;
 }
-class Di<T extends core::Object* = dynamic> extends core::Object {
+class Di<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Di<self::Di::T*>*
     : super core::Object::•()
     ;
@@ -185,7 +185,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug33099.dart.outline.expect b/pkg/front_end/testcases/general/bug33099.dart.outline.expect
index 8274b91..48337e0 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.outline.expect
@@ -17,7 +17,7 @@
   method foo() → void
     ;
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug33099.dart.strong.expect b/pkg/front_end/testcases/general/bug33099.dart.strong.expect
index 7bed644..fa1959d 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.strong.expect
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
index 6cd473f..7c8800f 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug34511.dart.outline.expect b/pkg/front_end/testcases/general/bug34511.dart.outline.expect
index 494ce66..678e133 100644
--- a/pkg/front_end/testcases/general/bug34511.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bug34511.dart.outline.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → self::A<self::A::X*>*
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug34511.dart.strong.expect b/pkg/front_end/testcases/general/bug34511.dart.strong.expect
index 4de7d7e..5e3f196 100644
--- a/pkg/front_end/testcases/general/bug34511.dart.strong.expect
+++ b/pkg/front_end/testcases/general/bug34511.dart.strong.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/bug34511.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug34511.dart.strong.transformed.expect
index ffac059..8fb87ff 100644
--- a/pkg/front_end/testcases/general/bug34511.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug34511.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/call.dart.strong.expect b/pkg/front_end/testcases/general/call.dart.strong.expect
index aa3277e..9efa544 100644
--- a/pkg/front_end/testcases/general/call.dart.strong.expect
+++ b/pkg/front_end/testcases/general/call.dart.strong.expect
@@ -84,14 +84,30 @@
   dynamic string6 = let final self::CallableGetter* #t1 = callableGetter in let final core::int* #t2 = 1 in #t1.{self::CallableGetter::call}.call(#t2);
   dynamic string7 = callableGetter.{self::CallableGetter::call}.call(1);
   dynamic string8 = callableGetter.{self::CallableGetter::call}.call.call(1);
-  dynamic nothing1 = closure.call();
-  dynamic nothing2 = closure.call();
-  dynamic nothing3 = closure.call.call();
-  dynamic nothing4 = closure.call.call.call();
-  dynamic nothing5 = callable.{self::Callable::call}();
-  dynamic nothing6 = callable.{self::Callable::call}();
-  dynamic nothing7 = callable.{self::Callable::call}.call();
-  dynamic nothing8 = callable.{self::Callable::call}.call.call();
+  invalid-type nothing1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/call.dart:34:25: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing1 = closure();
+                        ^" in closure.call();
+  invalid-type nothing2 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general/call.dart:35:30: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing2 = closure.call();
+                             ^" in closure.call();
+  invalid-type nothing3 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general/call.dart:36:35: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing3 = closure.call.call();
+                                  ^" in closure.call.call();
+  invalid-type nothing4 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/general/call.dart:37:40: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing4 = closure.call.call.call();
+                                       ^" in closure.call.call.call();
+  invalid-type nothing5 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/general/call.dart:39:26: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing5 = callable();
+                         ^" in callable.{self::Callable::call}();
+  invalid-type nothing6 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/general/call.dart:40:31: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing6 = callable.call();
+                              ^" in callable.{self::Callable::call}();
+  invalid-type nothing7 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/general/call.dart:41:36: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing7 = callable.call.call();
+                                   ^" in callable.{self::Callable::call}.call();
+  invalid-type nothing8 = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/general/call.dart:42:41: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing8 = callable.call.call.call();
+                                        ^" in callable.{self::Callable::call}.call.call();
   dynamic nothing9 = invalid-expression "pkg/front_end/testcases/general/call.dart:44:32: Error: Cannot invoke an instance of 'CallableGetter' because it declares 'call' to be something other than a method.
  - 'CallableGetter' is from 'pkg/front_end/testcases/general/call.dart'.
 Try changing 'call' to a method or explicitly invoke 'call'.
diff --git a/pkg/front_end/testcases/general/candidate_found.dart.strong.expect b/pkg/front_end/testcases/general/candidate_found.dart.strong.expect
index a111562..978eca5 100644
--- a/pkg/front_end/testcases/general/candidate_found.dart.strong.expect
+++ b/pkg/front_end/testcases/general/candidate_found.dart.strong.expect
@@ -68,6 +68,8 @@
   invalid-expression "pkg/front_end/testcases/general/candidate_found.dart:20:20: Error: Too few positional arguments: 1 required, 0 given.
   Fisk.staticMethod();
                    ^";
-  (null as self::Fisk*).{self::Fisk::method}();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/candidate_found.dart:21:24: Error: Too few positional arguments: 1 required, 0 given.
+  (null as Fisk).method();
+                       ^" in (null as self::Fisk*).{self::Fisk::method}();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect b/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
index 7ee9fd9..62ce381 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
@@ -111,7 +111,7 @@
   synthetic constructor •() → self::Am1<self::Am1::X*, self::Am1::Y*>*
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -120,7 +120,7 @@
   synthetic constructor •() → self::Bm1<self::Bm1::Z*>*
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -129,7 +129,7 @@
   synthetic constructor •() → self::Cm1<self::Cm1::Z*>*
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -138,7 +138,7 @@
   synthetic constructor •() → self::Dm1<self::Dm1::Z*>*
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -147,7 +147,7 @@
   synthetic constructor •() → self::Em1<self::Em1::Z*>*
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -156,7 +156,7 @@
   synthetic constructor •() → self::Fm1<self::Fm1::Z*>*
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -165,7 +165,7 @@
   synthetic constructor •() → self::Gm1<self::Gm1::Z*>*
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -174,7 +174,7 @@
   synthetic constructor •() → self::Hm1<self::Hm1::Z*>*
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -183,7 +183,7 @@
   synthetic constructor •() → self::Im1<self::Im1::Z*>*
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
   synthetic constructor •() → self::Jm1<self::Jm1::Z*>*
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -201,7 +201,7 @@
   synthetic constructor •() → self::Km1<self::Km1::Z*>*
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -210,57 +210,57 @@
   synthetic constructor •() → self::Lm1<self::Lm1::Z*>*
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> {
+class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> {
+class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> {
+class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> {
+class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> {
+class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> {
+class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> {
+class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> {
+class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> {
+class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> {
+class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> {
+class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -269,7 +269,7 @@
   synthetic constructor •() → self::Am2<self::Am2::X*, self::Am2::Y*>*
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -278,7 +278,7 @@
   synthetic constructor •() → self::Bm2<self::Bm2::Z*>*
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -287,7 +287,7 @@
   synthetic constructor •() → self::Cm2<self::Cm2::Z*>*
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -296,7 +296,7 @@
   synthetic constructor •() → self::Dm2<self::Dm2::Z*>*
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -305,7 +305,7 @@
   synthetic constructor •() → self::Em2<self::Em2::Z*>*
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -314,7 +314,7 @@
   synthetic constructor •() → self::Fm2<self::Fm2::Z*>*
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -323,7 +323,7 @@
   synthetic constructor •() → self::Gm2<self::Gm2::Z*>*
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
   synthetic constructor •() → self::Hm2<self::Hm2::Z*>*
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -341,7 +341,7 @@
   synthetic constructor •() → self::Im2<self::Im2::Z*>*
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -350,7 +350,7 @@
   synthetic constructor •() → self::Jm2<self::Jm2::Z*>*
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -359,7 +359,7 @@
   synthetic constructor •() → self::Km2<self::Km2::Z*>*
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -368,57 +368,57 @@
   synthetic constructor •() → self::Lm2<self::Lm2::Z*>*
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> {
+class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> {
+class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> {
+class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> {
+class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> {
+class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> {
+class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> {
+class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> {
+class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> {
+class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> {
+class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> {
+class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -427,7 +427,7 @@
   synthetic constructor •() → self::Am3<self::Am3::L*, self::Am3::Y*>*
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -436,7 +436,7 @@
   synthetic constructor •() → self::Bm3<self::Bm3::Z*>*
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -445,7 +445,7 @@
   synthetic constructor •() → self::Cm3<self::Cm3::Z*>*
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -454,7 +454,7 @@
   synthetic constructor •() → self::Dm3<self::Dm3::Z*>*
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -463,7 +463,7 @@
   synthetic constructor •() → self::Em3<self::Em3::Z*>*
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
   synthetic constructor •() → self::Fm3<self::Fm3::Z*>*
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -481,7 +481,7 @@
   synthetic constructor •() → self::Gm3<self::Gm3::Z*>*
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -490,7 +490,7 @@
   synthetic constructor •() → self::Hm3<self::Hm3::Z*>*
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -499,7 +499,7 @@
   synthetic constructor •() → self::Im3<self::Im3::Z*>*
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -508,7 +508,7 @@
   synthetic constructor •() → self::Jm3<self::Jm3::Z*>*
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect b/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
index c287cae..5ebcc5d 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -222,57 +222,57 @@
     : super self::_Lm1&Object&Am1::•()
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> {
+class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> {
+class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> {
+class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> {
+class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> {
+class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> {
+class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> {
+class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> {
+class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> {
+class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> {
+class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> {
+class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -392,57 +392,57 @@
     : super self::_Lm2&Object&Am2::•()
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> {
+class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> {
+class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> {
+class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> {
+class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> {
+class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> {
+class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> {
+class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> {
+class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> {
+class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> {
+class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> {
+class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
index 071ec09..486e5ad 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -222,57 +222,57 @@
     : super self::_Lm1&Object&Am1::•()
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*isEliminatedMixin*/  {
+class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*isEliminatedMixin*/  {
+class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> /*isEliminatedMixin*/  {
+class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> /*isEliminatedMixin*/  {
+class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> /*isEliminatedMixin*/  {
+class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*isEliminatedMixin*/  {
+class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*isEliminatedMixin*/  {
+class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*isEliminatedMixin*/  {
+class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> /*isEliminatedMixin*/  {
+class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*isEliminatedMixin*/  {
+class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*isEliminatedMixin*/  {
+class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -392,57 +392,57 @@
     : super self::_Lm2&Object&Am2::•()
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*isEliminatedMixin*/  {
+class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*isEliminatedMixin*/  {
+class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> /*isEliminatedMixin*/  {
+class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> /*isEliminatedMixin*/  {
+class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> /*isEliminatedMixin*/  {
+class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*isEliminatedMixin*/  {
+class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*isEliminatedMixin*/  {
+class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*isEliminatedMixin*/  {
+class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> /*isEliminatedMixin*/  {
+class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*isEliminatedMixin*/  {
+class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*isEliminatedMixin*/  {
+class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
index 39e2871..71c3fc8 100644
--- a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
+++ b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
@@ -2,10 +2,15 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
 // Try adding an explicit type.
-//   var field11; // error
-//       ^^^^^^^
+//   var field2; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field4 = 0; // error
+//       ^^^^^^
 //
 // pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
 // Try adding an explicit type.
@@ -17,6 +22,31 @@
 //   var field8 = 0; // error
 //       ^^^^^^
 //
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field11; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field17; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field18; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field2; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field4 = 0; // error
+//       ^^^^^^
+//
 // pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   var field6; // error
@@ -27,36 +57,16 @@
 //   var field8 = 0; // error
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field2; // error
-//       ^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field4 = 0; // error
-//       ^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field2; // error
-//       ^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field4 = 0; // error
-//       ^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field18; // error
-//       ^^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
 //
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field18; // error
+//       ^^^^^^^
+//
 // pkg/front_end/testcases/general/infer_field_from_multiple.dart:61:7: Error: The return type of the method 'C.field14' is 'int', which does not match the return type, 'String', of the overridden method, 'B.field14'.
 // Change to a subtype of 'String'.
 //   int field14; // error
@@ -72,16 +82,6 @@
 //   S field14;
 //     ^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field18; // error
-//       ^^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field17; // error
-//       ^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
index bf8a5eb..811dec5 100644
--- a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
+++ b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
@@ -2,10 +2,15 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
 // Try adding an explicit type.
-//   var field11; // error
-//       ^^^^^^^
+//   var field2; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field4 = 0; // error
+//       ^^^^^^
 //
 // pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
 // Try adding an explicit type.
@@ -17,6 +22,31 @@
 //   var field8 = 0; // error
 //       ^^^^^^
 //
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field11; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field17; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field18; // error
+//       ^^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field2; // error
+//       ^^^^^^
+//
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field4 = 0; // error
+//       ^^^^^^
+//
 // pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   var field6; // error
@@ -27,36 +57,16 @@
 //   var field8 = 0; // error
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field2; // error
-//       ^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field4 = 0; // error
-//       ^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field2; // error
-//       ^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field4 = 0; // error
-//       ^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field18; // error
-//       ^^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
 //
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var field18; // error
+//       ^^^^^^^
+//
 // pkg/front_end/testcases/general/infer_field_from_multiple.dart:61:7: Error: The return type of the method 'C.field14' is 'int', which does not match the return type, 'String', of the overridden method, 'B.field14'.
 // Change to a subtype of 'String'.
 //   int field14; // error
@@ -72,16 +82,6 @@
 //   S field14;
 //     ^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field18; // error
-//       ^^^^^^^
-//
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   var field17; // error
-//       ^^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/infer_field_type.dart b/pkg/front_end/testcases/general/infer_field_type.dart
new file mode 100644
index 0000000..dcea245
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_field_type.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for 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 extends B {
+  var field;
+}
+
+class B extends A {
+  get field => null;
+  set field(value) {}
+}
+
+class A {
+  var field = 0;
+}
+
+var topLevelFieldFromA = new A().field;
+var topLevelFieldFromB = new B().field;
+var topLevelFieldFromC = new C().field;
+
+main() {}
diff --git a/pkg/front_end/testcases/general/infer_field_type.dart.outline.expect b/pkg/front_end/testcases/general/infer_field_type.dart.outline.expect
new file mode 100644
index 0000000..f824624
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_field_type.dart.outline.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends self::B {
+  field core::int* field;
+  synthetic constructor •() → self::C*
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    ;
+  get field() → core::int*
+    ;
+  set field(core::int* value) → void
+    ;
+}
+class A extends core::Object {
+  field core::int* field;
+  synthetic constructor •() → self::A*
+    ;
+}
+static field core::int* topLevelFieldFromA;
+static field core::int* topLevelFieldFromB;
+static field core::int* topLevelFieldFromC;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/infer_field_type.dart.strong.expect b/pkg/front_end/testcases/general/infer_field_type.dart.strong.expect
new file mode 100644
index 0000000..39a2a5d
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_field_type.dart.strong.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends self::B {
+  field core::int* field = null;
+  synthetic constructor •() → self::C*
+    : super self::B::•()
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  get field() → core::int*
+    return null;
+  set field(core::int* value) → void {}
+}
+class A extends core::Object {
+  field core::int* field = 0;
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+static field core::int* topLevelFieldFromA = new self::A::•().{self::A::field};
+static field core::int* topLevelFieldFromB = new self::B::•().{self::B::field};
+static field core::int* topLevelFieldFromC = new self::C::•().{self::C::field};
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/infer_field_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/infer_field_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..39a2a5d
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_field_type.dart.strong.transformed.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends self::B {
+  field core::int* field = null;
+  synthetic constructor •() → self::C*
+    : super self::B::•()
+    ;
+}
+class B extends self::A {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+  get field() → core::int*
+    return null;
+  set field(core::int* value) → void {}
+}
+class A extends core::Object {
+  field core::int* field = 0;
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+}
+static field core::int* topLevelFieldFromA = new self::A::•().{self::A::field};
+static field core::int* topLevelFieldFromB = new self::B::•().{self::B::field};
+static field core::int* topLevelFieldFromC = new self::C::•().{self::C::field};
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart
new file mode 100644
index 0000000..d10fb48
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class Base {}
+
+abstract class MixinA<T> {
+  T method(Object t);
+}
+
+abstract class Class extends Base with MixinA {
+  method(t) {}
+}
+
+abstract class YamlNode {}
+
+abstract class Map<K, V> {
+  V operator [](Object key);
+}
+
+abstract class MapMixin<K, V> implements Map<K, V> {
+  V operator [](Object key);
+}
+
+abstract class UnmodifiableMapMixin<K, V> implements Map<K, V> {}
+
+class YamlMap extends YamlNode with MapMixin, UnmodifiableMapMixin {
+  operator [](key) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.outline.expect b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.outline.expect
new file mode 100644
index 0000000..62e1775
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.outline.expect
@@ -0,0 +1,60 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Base extends core::Object {
+  synthetic constructor •() → self::Base*
+    ;
+}
+abstract class MixinA<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::MixinA<self::MixinA::T*>*
+    ;
+  abstract method method(core::Object* t) → self::MixinA::T*;
+}
+abstract class _Class&Base&MixinA = self::Base with self::MixinA<dynamic> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Class&Base&MixinA*
+    : super self::Base::•()
+    ;
+}
+abstract class Class extends self::_Class&Base&MixinA {
+  synthetic constructor •() → self::Class*
+    ;
+  method method(core::Object* t) → dynamic
+    ;
+}
+abstract class YamlNode extends core::Object {
+  synthetic constructor •() → self::YamlNode*
+    ;
+}
+abstract class Map<K extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K*, self::Map::V*>*
+    ;
+  abstract operator [](core::Object* key) → self::Map::V*;
+}
+abstract class MapMixin<K extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object implements self::Map<self::MapMixin::K*, self::MapMixin::V*> {
+  synthetic constructor •() → self::MapMixin<self::MapMixin::K*, self::MapMixin::V*>*
+    ;
+  abstract operator [](core::Object* key) → self::MapMixin::V*;
+}
+abstract class UnmodifiableMapMixin<K extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object implements self::Map<self::UnmodifiableMapMixin::K*, self::UnmodifiableMapMixin::V*> {
+  synthetic constructor •() → self::UnmodifiableMapMixin<self::UnmodifiableMapMixin::K*, self::UnmodifiableMapMixin::V*>*
+    ;
+}
+abstract class _YamlMap&YamlNode&MapMixin = self::YamlNode with self::MapMixin<dynamic, dynamic> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin*
+    : super self::YamlNode::•()
+    ;
+}
+abstract class _YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin = self::_YamlMap&YamlNode&MapMixin with self::UnmodifiableMapMixin<dynamic, dynamic> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin*
+    : super self::_YamlMap&YamlNode&MapMixin::•()
+    ;
+}
+class YamlMap extends self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin {
+  synthetic constructor •() → self::YamlMap*
+    ;
+  operator [](core::Object* key) → dynamic
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.expect b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.expect
new file mode 100644
index 0000000..8a3d100
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.expect
@@ -0,0 +1,65 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Base extends core::Object {
+  synthetic constructor •() → self::Base*
+    : super core::Object::•()
+    ;
+}
+abstract class MixinA<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::MixinA<self::MixinA::T*>*
+    : super core::Object::•()
+    ;
+  abstract method method(core::Object* t) → self::MixinA::T*;
+}
+abstract class _Class&Base&MixinA = self::Base with self::MixinA<dynamic> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Class&Base&MixinA*
+    : super self::Base::•()
+    ;
+}
+abstract class Class extends self::_Class&Base&MixinA {
+  synthetic constructor •() → self::Class*
+    : super self::_Class&Base&MixinA::•()
+    ;
+  method method(core::Object* t) → dynamic {}
+}
+abstract class YamlNode extends core::Object {
+  synthetic constructor •() → self::YamlNode*
+    : super core::Object::•()
+    ;
+}
+abstract class Map<K extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K*, self::Map::V*>*
+    : super core::Object::•()
+    ;
+  abstract operator [](core::Object* key) → self::Map::V*;
+}
+abstract class MapMixin<K extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object implements self::Map<self::MapMixin::K*, self::MapMixin::V*> {
+  synthetic constructor •() → self::MapMixin<self::MapMixin::K*, self::MapMixin::V*>*
+    : super core::Object::•()
+    ;
+  abstract operator [](core::Object* key) → self::MapMixin::V*;
+}
+abstract class UnmodifiableMapMixin<K extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object implements self::Map<self::UnmodifiableMapMixin::K*, self::UnmodifiableMapMixin::V*> {
+  synthetic constructor •() → self::UnmodifiableMapMixin<self::UnmodifiableMapMixin::K*, self::UnmodifiableMapMixin::V*>*
+    : super core::Object::•()
+    ;
+}
+abstract class _YamlMap&YamlNode&MapMixin = self::YamlNode with self::MapMixin<dynamic, dynamic> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin*
+    : super self::YamlNode::•()
+    ;
+}
+abstract class _YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin = self::_YamlMap&YamlNode&MapMixin with self::UnmodifiableMapMixin<dynamic, dynamic> /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin*
+    : super self::_YamlMap&YamlNode&MapMixin::•()
+    ;
+}
+class YamlMap extends self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin {
+  synthetic constructor •() → self::YamlMap*
+    : super self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin::•()
+    ;
+  operator [](core::Object* key) → dynamic {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..6e58968
--- /dev/null
+++ b/pkg/front_end/testcases/general/infer_fixed_generic_return_type.dart.strong.transformed.expect
@@ -0,0 +1,67 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Base extends core::Object {
+  synthetic constructor •() → self::Base*
+    : super core::Object::•()
+    ;
+}
+abstract class MixinA<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::MixinA<self::MixinA::T*>*
+    : super core::Object::•()
+    ;
+  abstract method method(core::Object* t) → self::MixinA::T*;
+}
+abstract class _Class&Base&MixinA extends self::Base implements self::MixinA<dynamic> /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_Class&Base&MixinA*
+    : super self::Base::•()
+    ;
+  abstract method method(core::Object* t) → dynamic;
+}
+abstract class Class extends self::_Class&Base&MixinA {
+  synthetic constructor •() → self::Class*
+    : super self::_Class&Base&MixinA::•()
+    ;
+  method method(core::Object* t) → dynamic {}
+}
+abstract class YamlNode extends core::Object {
+  synthetic constructor •() → self::YamlNode*
+    : super core::Object::•()
+    ;
+}
+abstract class Map<K extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K*, self::Map::V*>*
+    : super core::Object::•()
+    ;
+  abstract operator [](core::Object* key) → self::Map::V*;
+}
+abstract class MapMixin<K extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object implements self::Map<self::MapMixin::K*, self::MapMixin::V*> {
+  synthetic constructor •() → self::MapMixin<self::MapMixin::K*, self::MapMixin::V*>*
+    : super core::Object::•()
+    ;
+  abstract operator [](core::Object* key) → self::MapMixin::V*;
+}
+abstract class UnmodifiableMapMixin<K extends core::Object* = dynamic, V extends core::Object* = dynamic> extends core::Object implements self::Map<self::UnmodifiableMapMixin::K*, self::UnmodifiableMapMixin::V*> {
+  synthetic constructor •() → self::UnmodifiableMapMixin<self::UnmodifiableMapMixin::K*, self::UnmodifiableMapMixin::V*>*
+    : super core::Object::•()
+    ;
+}
+abstract class _YamlMap&YamlNode&MapMixin extends self::YamlNode implements self::MapMixin<dynamic, dynamic> /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin*
+    : super self::YamlNode::•()
+    ;
+  abstract operator [](core::Object* key) → dynamic;
+}
+abstract class _YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin extends self::_YamlMap&YamlNode&MapMixin implements self::UnmodifiableMapMixin<dynamic, dynamic> /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin*
+    : super self::_YamlMap&YamlNode&MapMixin::•()
+    ;
+}
+class YamlMap extends self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin {
+  synthetic constructor •() → self::YamlMap*
+    : super self::_YamlMap&YamlNode&MapMixin&UnmodifiableMapMixin::•()
+    ;
+  operator [](core::Object* key) → dynamic {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue38944.dart.outline.expect b/pkg/front_end/testcases/general/issue38944.dart.outline.expect
index 4c9456c..2919730 100644
--- a/pkg/front_end/testcases/general/issue38944.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue38944.dart.outline.expect
@@ -13,7 +13,7 @@
   synthetic constructor •() → self::A<self::A::Q*>*
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/issue38944.dart.strong.expect b/pkg/front_end/testcases/general/issue38944.dart.strong.expect
index d6a3d0a..5180b5d 100644
--- a/pkg/front_end/testcases/general/issue38944.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue38944.dart.strong.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect
index d6a3d0a..5180b5d 100644
--- a/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue38944.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/issue41070.dart b/pkg/front_end/testcases/general/issue41070.dart
new file mode 100644
index 0000000..3129cb6
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue41070.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class Mixin {}
+
+class Base {
+  final int x;
+  const Base(this.x);
+}
+
+class Application = Base with Mixin;
+
+main() {
+  expect(42, const Application(42).x);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/general/issue41070.dart.outline.expect b/pkg/front_end/testcases/general/issue41070.dart.outline.expect
new file mode 100644
index 0000000..903a7cb
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue41070.dart.outline.expect
@@ -0,0 +1,23 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin*
+    ;
+}
+class Base extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  const constructor •(core::int* x) → self::Base*
+    : self::Base::x = x, super core::Object::•()
+    ;
+}
+class Application = self::Base with self::Mixin /*hasConstConstructor*/  {
+  const synthetic constructor •(core::int* x) → self::Application*
+    : super self::Base::•(x)
+    ;
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue41070.dart.strong.expect b/pkg/front_end/testcases/general/issue41070.dart.strong.expect
new file mode 100644
index 0000000..1d250f6
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue41070.dart.strong.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin*
+    : super core::Object::•()
+    ;
+}
+class Base extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  const constructor •(core::int* x) → self::Base*
+    : self::Base::x = x, super core::Object::•()
+    ;
+}
+class Application = self::Base with self::Mixin /*hasConstConstructor*/  {
+  const synthetic constructor •(core::int* x) → self::Application*
+    : super self::Base::•(x)
+    ;
+}
+static method main() → dynamic {
+  self::expect(42, (#C2).{self::Base::x});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = self::Application {x:#C1}
+}
diff --git a/pkg/front_end/testcases/general/issue41070.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue41070.dart.strong.transformed.expect
new file mode 100644
index 0000000..5087726
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue41070.dart.strong.transformed.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class Mixin extends core::Object {
+  synthetic constructor •() → self::Mixin*
+    : super core::Object::•()
+    ;
+}
+class Base extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  const constructor •(core::int* x) → self::Base*
+    : self::Base::x = x, super core::Object::•()
+    ;
+}
+class Application extends self::Base implements self::Mixin /*isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •(core::int* x) → self::Application*
+    : super self::Base::•(x)
+    ;
+}
+static method main() → dynamic {
+  self::expect(42, (#C2).{self::Base::x});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = 42
+  #C2 = self::Application {x:#C1}
+}
diff --git a/pkg/front_end/testcases/general/mixin.dart.outline.expect b/pkg/front_end/testcases/general/mixin.dart.outline.expect
index 9a57e29..d4a20e6 100644
--- a/pkg/front_end/testcases/general/mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin.dart.outline.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -28,12 +28,12 @@
   method m() → dynamic
     ;
 }
-abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -48,7 +48,7 @@
   method m() → dynamic
     ;
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin.dart.strong.expect b/pkg/front_end/testcases/general/mixin.dart.strong.expect
index 2cca9cf..5e30f41 100644
--- a/pkg/front_end/testcases/general/mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin.dart.strong.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -31,12 +31,12 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -53,7 +53,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect
index b51ef02..903d96c 100644
--- a/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin.dart.strong.transformed.expect
@@ -2,14 +2,14 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -35,14 +35,14 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -61,7 +61,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect b/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect
index 87dfa06..df81fd0a 100644
--- a/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_conflicts.dart.outline.expect
@@ -39,12 +39,12 @@
   method foo() → dynamic
     ;
 }
-class N = core::Object with self::M {
+class N = core::Object with self::M /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -59,17 +59,17 @@
   method bar() → dynamic
     ;
 }
-class N2 = core::Object with self::M2 {
+class N2 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
 }
-abstract class N3 = core::Object with self::M2 {
+abstract class N3 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -78,7 +78,7 @@
   synthetic constructor •() → self::C2*
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect
index 73140d2..676600e 100644
--- a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.expect
@@ -39,12 +39,12 @@
     ;
   method foo() → dynamic {}
 }
-class N = core::Object with self::M {
+class N = core::Object with self::M /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -60,17 +60,17 @@
     ;
   method bar() → dynamic {}
 }
-class N2 = core::Object with self::M2 {
+class N2 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
 }
-abstract class N3 = core::Object with self::M2 {
+abstract class N3 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -80,7 +80,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect
index 52ec3ad..32bacea 100644
--- a/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_conflicts.dart.strong.transformed.expect
@@ -39,13 +39,13 @@
     ;
   method foo() → dynamic {}
 }
-class N extends core::Object implements self::M /*isEliminatedMixin*/  {
+class N extends core::Object implements self::M /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
   method foo() → dynamic {}
 }
-abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -62,19 +62,19 @@
     ;
   method bar() → dynamic {}
 }
-class N2 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
+class N2 extends core::Object implements self::M2 /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
+abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -85,7 +85,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C3&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/mixin_covariant.dart b/pkg/front_end/testcases/general/mixin_covariant.dart
new file mode 100644
index 0000000..b9384c1
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_covariant.dart
@@ -0,0 +1,161 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Derived from language_2/covariant_override/tear_off_type_test
+
+// If a parameter is directly or indirectly a covariant override, its type in
+// the method tear-off should become Object.
+
+typedef void TakeInts(int a, int b, int c, int d, int e);
+typedef void TakeObjectsAndInts(Object a, int b, Object c, int d, int e);
+typedef void TakeObjects(Object a, Object b, Object c, Object d, Object e);
+
+typedef void TakeOptionalInts([int a, int b, int c, int d]);
+typedef void TakeOptionalObjectsAndInts([Object a, int b, Object c, int d]);
+
+typedef void TakeNamedInts({int a, int b, int c, int d});
+typedef void TakeNamedObjectsAndInts({Object a, int b, Object c, int d});
+
+class M1 {
+  method(covariant int a, int b) {}
+}
+
+class M2 {
+  method(int a, covariant int b) {}
+}
+
+class C extends Object with M1, M2 {}
+
+class Direct {
+  void positional(covariant int a, int b, covariant int c, int d, int e) {}
+  void optional([covariant int a, int b, covariant int c, int d]) {}
+  void named({covariant int a, int b, covariant int c, int d}) {}
+}
+
+class Inherited extends Direct {}
+
+// ---
+
+class Override1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Override2 extends Override1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Override3 extends Override2 {
+  void method(int a, int b, int c, int d, int e) {}
+}
+
+// ---
+
+abstract class Implement1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Implement2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class Implement3 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Implement4 implements Implement3 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Implement5 implements Implement1, Implement2, Implement4 {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+// ---
+
+class Interface1 {
+  void method(covariant int a, int b, int c, int d, int e) {}
+}
+
+class Interface2 {
+  void method(int a, covariant int b, int c, int d, int e) {}
+}
+
+class Mixin1 {
+  void method(int a, int b, covariant int c, int d, int e) {}
+}
+
+class Mixin2 {
+  void method(int a, int b, int c, covariant int d, int e) {}
+}
+
+class Superclass {
+  void method(int a, int b, int c, int d, covariant int e) {}
+}
+
+class Mixed extends Superclass
+    with Mixin1, Mixin2
+    implements Interface1, Interface2 {}
+
+void main() {
+  testDirect();
+  testInherited();
+  testOverridden();
+  testImplemented();
+  testMixed();
+}
+
+void testDirect() {
+  var positional = new Direct().positional;
+  isTrue(positional is TakeInts);
+  isTrue(positional is TakeObjectsAndInts);
+
+  var optional = new Direct().optional;
+  isTrue(optional is TakeOptionalInts);
+  isTrue(optional is TakeOptionalObjectsAndInts);
+
+  var named = new Direct().named;
+  isTrue(named is TakeNamedInts);
+  isTrue(named is TakeNamedObjectsAndInts);
+}
+
+void testInherited() {
+  var positional = new Inherited().positional;
+  isTrue(positional is TakeInts);
+  isTrue(positional is TakeObjectsAndInts);
+
+  var optional = new Inherited().optional;
+  isTrue(optional is TakeOptionalInts);
+  isTrue(optional is TakeOptionalObjectsAndInts);
+
+  var named = new Inherited().named;
+  isTrue(named is TakeNamedInts);
+  isTrue(named is TakeNamedObjectsAndInts);
+}
+
+void testOverridden() {
+  var method2 = new Override2().method;
+  isTrue(method2 is TakeInts);
+  isTrue(method2 is TakeObjectsAndInts);
+
+  var method3 = new Override3().method;
+  isTrue(method3 is TakeInts);
+  isTrue(method3 is TakeObjectsAndInts);
+}
+
+void testImplemented() {
+  var method = new Implement5().method;
+  isTrue(method is TakeInts);
+  isTrue(method is TakeObjects);
+}
+
+void testMixed() {
+  // TODO(rnystrom): https://github.com/dart-lang/sdk/issues/28395
+  var method = new Mixed().method;
+  isTrue(method is TakeInts);
+  isTrue(method is TakeObjects);
+}
+
+void isTrue(bool value) {
+  if (!value) throw 'Expected true';
+}
diff --git a/pkg/front_end/testcases/general/mixin_covariant.dart.outline.expect b/pkg/front_end/testcases/general/mixin_covariant.dart.outline.expect
new file mode 100644
index 0000000..926cb3e
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_covariant.dart.outline.expect
@@ -0,0 +1,165 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef TakeInts = (core::int*, core::int*, core::int*, core::int*, core::int*) →* void;
+typedef TakeObjectsAndInts = (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void;
+typedef TakeObjects = (core::Object*, core::Object*, core::Object*, core::Object*, core::Object*) →* void;
+typedef TakeOptionalInts = ([core::int*, core::int*, core::int*, core::int*]) →* void;
+typedef TakeOptionalObjectsAndInts = ([core::Object*, core::int*, core::Object*, core::int*]) →* void;
+typedef TakeNamedInts = ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void;
+typedef TakeNamedObjectsAndInts = ({a: core::Object*, b: core::int*, c: core::Object*, d: core::int*}) →* void;
+class M1 extends core::Object {
+  synthetic constructor •() → self::M1*
+    ;
+  method method(covariant core::int* a, core::int* b) → dynamic
+    ;
+}
+class M2 extends core::Object {
+  synthetic constructor •() → self::M2*
+    ;
+  method method(core::int* a, covariant core::int* b) → dynamic
+    ;
+}
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1*
+    : super core::Object::•()
+    ;
+}
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1&M2*
+    : super self::_C&Object&M1::•()
+    ;
+  forwarding-stub method method(covariant core::int* a, covariant core::int* b) → dynamic
+    return super.{self::M1::method}(a, b);
+}
+class C extends self::_C&Object&M1&M2 {
+  synthetic constructor •() → self::C*
+    ;
+}
+class Direct extends core::Object {
+  synthetic constructor •() → self::Direct*
+    ;
+  method positional(covariant core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void
+    ;
+  method optional([covariant core::int* a, core::int* b, covariant core::int* c, core::int* d]) → void
+    ;
+  method named({covariant core::int* a, core::int* b, covariant core::int* c, core::int* d}) → void
+    ;
+}
+class Inherited extends self::Direct {
+  synthetic constructor •() → self::Inherited*
+    ;
+}
+class Override1 extends core::Object {
+  synthetic constructor •() → self::Override1*
+    ;
+  method method(covariant core::int* a, core::int* b, core::int* c, core::int* d, core::int* e) → void
+    ;
+}
+class Override2 extends self::Override1 {
+  synthetic constructor •() → self::Override2*
+    ;
+  method method(covariant core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void
+    ;
+}
+class Override3 extends self::Override2 {
+  synthetic constructor •() → self::Override3*
+    ;
+  method method(covariant core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void
+    ;
+}
+abstract class Implement1 extends core::Object {
+  synthetic constructor •() → self::Implement1*
+    ;
+  method method(covariant core::int* a, core::int* b, core::int* c, core::int* d, core::int* e) → void
+    ;
+}
+class Implement2 extends core::Object {
+  synthetic constructor •() → self::Implement2*
+    ;
+  method method(core::int* a, covariant core::int* b, core::int* c, core::int* d, core::int* e) → void
+    ;
+}
+class Implement3 extends core::Object {
+  synthetic constructor •() → self::Implement3*
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void
+    ;
+}
+class Implement4 extends core::Object implements self::Implement3 {
+  synthetic constructor •() → self::Implement4*
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, covariant core::int* d, core::int* e) → void
+    ;
+}
+class Implement5 extends core::Object implements self::Implement1, self::Implement2, self::Implement4 {
+  synthetic constructor •() → self::Implement5*
+    ;
+  method method(covariant core::int* a, covariant core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
+    ;
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1*
+    ;
+  method method(covariant core::int* a, core::int* b, core::int* c, core::int* d, core::int* e) → void
+    ;
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2*
+    ;
+  method method(core::int* a, covariant core::int* b, core::int* c, core::int* d, core::int* e) → void
+    ;
+}
+class Mixin1 extends core::Object {
+  synthetic constructor •() → self::Mixin1*
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void
+    ;
+}
+class Mixin2 extends core::Object {
+  synthetic constructor •() → self::Mixin2*
+    ;
+  method method(core::int* a, core::int* b, core::int* c, covariant core::int* d, core::int* e) → void
+    ;
+}
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass*
+    ;
+  method method(core::int* a, core::int* b, core::int* c, core::int* d, covariant core::int* e) → void
+    ;
+}
+abstract class _Mixed&Superclass&Mixin1 = self::Superclass with self::Mixin1 /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1*
+    : super self::Superclass::•()
+    ;
+  forwarding-stub method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, covariant core::int* e) → void
+    return super.{self::Superclass::method}(a, b, c, d, e);
+}
+abstract class _Mixed&Superclass&Mixin1&Mixin2 = self::_Mixed&Superclass&Mixin1 with self::Mixin2 /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1&Mixin2*
+    : super self::_Mixed&Superclass&Mixin1::•()
+    ;
+  forwarding-stub method method(core::int* a, core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
+    return super.{self::Superclass::method}(a, b, c, d, e);
+}
+class Mixed extends self::_Mixed&Superclass&Mixin1&Mixin2 implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::Mixed*
+    ;
+  forwarding-stub method method(covariant core::int* a, covariant core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
+    return super.{self::Superclass::method}(a, b, c, d, e);
+}
+static method main() → void
+  ;
+static method testDirect() → void
+  ;
+static method testInherited() → void
+  ;
+static method testOverridden() → void
+  ;
+static method testImplemented() → void
+  ;
+static method testMixed() → void
+  ;
+static method isTrue(core::bool* value) → void
+  ;
diff --git a/pkg/front_end/testcases/general/mixin_covariant.dart.strong.expect b/pkg/front_end/testcases/general/mixin_covariant.dart.strong.expect
new file mode 100644
index 0000000..903302c
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_covariant.dart.strong.expect
@@ -0,0 +1,207 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef TakeInts = (core::int*, core::int*, core::int*, core::int*, core::int*) →* void;
+typedef TakeObjectsAndInts = (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void;
+typedef TakeObjects = (core::Object*, core::Object*, core::Object*, core::Object*, core::Object*) →* void;
+typedef TakeOptionalInts = ([core::int*, core::int*, core::int*, core::int*]) →* void;
+typedef TakeOptionalObjectsAndInts = ([core::Object*, core::int*, core::Object*, core::int*]) →* void;
+typedef TakeNamedInts = ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void;
+typedef TakeNamedObjectsAndInts = ({a: core::Object*, b: core::int*, c: core::Object*, d: core::int*}) →* void;
+class M1 extends core::Object {
+  synthetic constructor •() → self::M1*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, core::int* b) → dynamic {}
+}
+class M2 extends core::Object {
+  synthetic constructor •() → self::M2*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, covariant core::int* b) → dynamic {}
+}
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1*
+    : super core::Object::•()
+    ;
+}
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1&M2*
+    : super self::_C&Object&M1::•()
+    ;
+  forwarding-stub method method(covariant core::int* a, covariant core::int* b) → dynamic
+    return super.{self::M1::method}(a, b);
+}
+class C extends self::_C&Object&M1&M2 {
+  synthetic constructor •() → self::C*
+    : super self::_C&Object&M1&M2::•()
+    ;
+}
+class Direct extends core::Object {
+  synthetic constructor •() → self::Direct*
+    : super core::Object::•()
+    ;
+  method positional(covariant core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+  method optional([covariant core::int* a = #C1, core::int* b = #C1, covariant core::int* c = #C1, core::int* d = #C1]) → void {}
+  method named({covariant core::int* a = #C1, core::int* b = #C1, covariant core::int* c = #C1, core::int* d = #C1}) → void {}
+}
+class Inherited extends self::Direct {
+  synthetic constructor •() → self::Inherited*
+    : super self::Direct::•()
+    ;
+}
+class Override1 extends core::Object {
+  synthetic constructor •() → self::Override1*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Override2 extends self::Override1 {
+  synthetic constructor •() → self::Override2*
+    : super self::Override1::•()
+    ;
+  method method(covariant core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+}
+class Override3 extends self::Override2 {
+  synthetic constructor •() → self::Override3*
+    : super self::Override2::•()
+    ;
+  method method(covariant core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+}
+abstract class Implement1 extends core::Object {
+  synthetic constructor •() → self::Implement1*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Implement2 extends core::Object {
+  synthetic constructor •() → self::Implement2*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, covariant core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Implement3 extends core::Object {
+  synthetic constructor •() → self::Implement3*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+}
+class Implement4 extends core::Object implements self::Implement3 {
+  synthetic constructor •() → self::Implement4*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, covariant core::int* d, core::int* e) → void {}
+}
+class Implement5 extends core::Object implements self::Implement1, self::Implement2, self::Implement4 {
+  synthetic constructor •() → self::Implement5*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, covariant core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void {}
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, covariant core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Mixin1 extends core::Object {
+  synthetic constructor •() → self::Mixin1*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+}
+class Mixin2 extends core::Object {
+  synthetic constructor •() → self::Mixin2*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, core::int* c, covariant core::int* d, core::int* e) → void {}
+}
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, core::int* c, core::int* d, covariant core::int* e) → void {}
+}
+abstract class _Mixed&Superclass&Mixin1 = self::Superclass with self::Mixin1 /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1*
+    : super self::Superclass::•()
+    ;
+  forwarding-stub method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, covariant core::int* e) → void
+    return super.{self::Superclass::method}(a, b, c, d, e);
+}
+abstract class _Mixed&Superclass&Mixin1&Mixin2 = self::_Mixed&Superclass&Mixin1 with self::Mixin2 /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1&Mixin2*
+    : super self::_Mixed&Superclass&Mixin1::•()
+    ;
+  forwarding-stub method method(core::int* a, core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
+    return super.{self::Superclass::method}(a, b, c, d, e);
+}
+class Mixed extends self::_Mixed&Superclass&Mixin1&Mixin2 implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::Mixed*
+    : super self::_Mixed&Superclass&Mixin1&Mixin2::•()
+    ;
+  forwarding-stub method method(covariant core::int* a, covariant core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
+    return super.{self::Superclass::method}(a, b, c, d, e);
+}
+static method main() → void {
+  self::testDirect();
+  self::testInherited();
+  self::testOverridden();
+  self::testImplemented();
+  self::testMixed();
+}
+static method testDirect() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void positional = new self::Direct::•().{self::Direct::positional};
+  self::isTrue(positional is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(positional is (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void);
+  ([core::int*, core::int*, core::int*, core::int*]) →* void optional = new self::Direct::•().{self::Direct::optional};
+  self::isTrue(optional is ([core::int*, core::int*, core::int*, core::int*]) →* void);
+  self::isTrue(optional is ([core::Object*, core::int*, core::Object*, core::int*]) →* void);
+  ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void named = new self::Direct::•().{self::Direct::named};
+  self::isTrue(named is ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void);
+  self::isTrue(named is ({a: core::Object*, b: core::int*, c: core::Object*, d: core::int*}) →* void);
+}
+static method testInherited() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void positional = new self::Inherited::•().{self::Direct::positional};
+  self::isTrue(positional is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(positional is (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void);
+  ([core::int*, core::int*, core::int*, core::int*]) →* void optional = new self::Inherited::•().{self::Direct::optional};
+  self::isTrue(optional is ([core::int*, core::int*, core::int*, core::int*]) →* void);
+  self::isTrue(optional is ([core::Object*, core::int*, core::Object*, core::int*]) →* void);
+  ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void named = new self::Inherited::•().{self::Direct::named};
+  self::isTrue(named is ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void);
+  self::isTrue(named is ({a: core::Object*, b: core::int*, c: core::Object*, d: core::int*}) →* void);
+}
+static method testOverridden() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void method2 = new self::Override2::•().{self::Override2::method};
+  self::isTrue(method2 is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(method2 is (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void);
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void method3 = new self::Override3::•().{self::Override3::method};
+  self::isTrue(method3 is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(method3 is (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void);
+}
+static method testImplemented() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void method = new self::Implement5::•().{self::Implement5::method};
+  self::isTrue(method is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(method is (core::Object*, core::Object*, core::Object*, core::Object*, core::Object*) →* void);
+}
+static method testMixed() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void method = new self::Mixed::•().{self::Mixed::method};
+  self::isTrue(method is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(method is (core::Object*, core::Object*, core::Object*, core::Object*, core::Object*) →* void);
+}
+static method isTrue(core::bool* value) → void {
+  if(!value)
+    throw "Expected true";
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/mixin_covariant.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_covariant.dart.strong.transformed.expect
new file mode 100644
index 0000000..baacb5a
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_covariant.dart.strong.transformed.expect
@@ -0,0 +1,205 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef TakeInts = (core::int*, core::int*, core::int*, core::int*, core::int*) →* void;
+typedef TakeObjectsAndInts = (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void;
+typedef TakeObjects = (core::Object*, core::Object*, core::Object*, core::Object*, core::Object*) →* void;
+typedef TakeOptionalInts = ([core::int*, core::int*, core::int*, core::int*]) →* void;
+typedef TakeOptionalObjectsAndInts = ([core::Object*, core::int*, core::Object*, core::int*]) →* void;
+typedef TakeNamedInts = ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void;
+typedef TakeNamedObjectsAndInts = ({a: core::Object*, b: core::int*, c: core::Object*, d: core::int*}) →* void;
+class M1 extends core::Object {
+  synthetic constructor •() → self::M1*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, core::int* b) → dynamic {}
+}
+class M2 extends core::Object {
+  synthetic constructor •() → self::M2*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, covariant core::int* b) → dynamic {}
+}
+abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, core::int* b) → dynamic {}
+}
+abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •() → self::_C&Object&M1&M2*
+    : super self::_C&Object&M1::•()
+    ;
+  method method(covariant core::int* a, covariant core::int* b) → dynamic {}
+}
+class C extends self::_C&Object&M1&M2 {
+  synthetic constructor •() → self::C*
+    : super self::_C&Object&M1&M2::•()
+    ;
+}
+class Direct extends core::Object {
+  synthetic constructor •() → self::Direct*
+    : super core::Object::•()
+    ;
+  method positional(covariant core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+  method optional([covariant core::int* a = #C1, core::int* b = #C1, covariant core::int* c = #C1, core::int* d = #C1]) → void {}
+  method named({covariant core::int* a = #C1, core::int* b = #C1, covariant core::int* c = #C1, core::int* d = #C1}) → void {}
+}
+class Inherited extends self::Direct {
+  synthetic constructor •() → self::Inherited*
+    : super self::Direct::•()
+    ;
+}
+class Override1 extends core::Object {
+  synthetic constructor •() → self::Override1*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Override2 extends self::Override1 {
+  synthetic constructor •() → self::Override2*
+    : super self::Override1::•()
+    ;
+  method method(covariant core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+}
+class Override3 extends self::Override2 {
+  synthetic constructor •() → self::Override3*
+    : super self::Override2::•()
+    ;
+  method method(covariant core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+}
+abstract class Implement1 extends core::Object {
+  synthetic constructor •() → self::Implement1*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Implement2 extends core::Object {
+  synthetic constructor •() → self::Implement2*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, covariant core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Implement3 extends core::Object {
+  synthetic constructor •() → self::Implement3*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+}
+class Implement4 extends core::Object implements self::Implement3 {
+  synthetic constructor •() → self::Implement4*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, covariant core::int* d, core::int* e) → void {}
+}
+class Implement5 extends core::Object implements self::Implement1, self::Implement2, self::Implement4 {
+  synthetic constructor •() → self::Implement5*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, covariant core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void {}
+}
+class Interface1 extends core::Object {
+  synthetic constructor •() → self::Interface1*
+    : super core::Object::•()
+    ;
+  method method(covariant core::int* a, core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Interface2 extends core::Object {
+  synthetic constructor •() → self::Interface2*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, covariant core::int* b, core::int* c, core::int* d, core::int* e) → void {}
+}
+class Mixin1 extends core::Object {
+  synthetic constructor •() → self::Mixin1*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, core::int* e) → void {}
+}
+class Mixin2 extends core::Object {
+  synthetic constructor •() → self::Mixin2*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, core::int* c, covariant core::int* d, core::int* e) → void {}
+}
+class Superclass extends core::Object {
+  synthetic constructor •() → self::Superclass*
+    : super core::Object::•()
+    ;
+  method method(core::int* a, core::int* b, core::int* c, core::int* d, covariant core::int* e) → void {}
+}
+abstract class _Mixed&Superclass&Mixin1 extends self::Superclass implements self::Mixin1 /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1*
+    : super self::Superclass::•()
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, core::int* d, covariant core::int* e) → void {}
+}
+abstract class _Mixed&Superclass&Mixin1&Mixin2 extends self::_Mixed&Superclass&Mixin1 implements self::Mixin2 /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_Mixed&Superclass&Mixin1&Mixin2*
+    : super self::_Mixed&Superclass&Mixin1::•()
+    ;
+  method method(core::int* a, core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void {}
+}
+class Mixed extends self::_Mixed&Superclass&Mixin1&Mixin2 implements self::Interface1, self::Interface2 {
+  synthetic constructor •() → self::Mixed*
+    : super self::_Mixed&Superclass&Mixin1&Mixin2::•()
+    ;
+  forwarding-stub method method(covariant core::int* a, covariant core::int* b, covariant core::int* c, covariant core::int* d, covariant core::int* e) → void
+    return super.{self::Superclass::method}(a, b, c, d, e);
+}
+static method main() → void {
+  self::testDirect();
+  self::testInherited();
+  self::testOverridden();
+  self::testImplemented();
+  self::testMixed();
+}
+static method testDirect() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void positional = new self::Direct::•().{self::Direct::positional};
+  self::isTrue(positional is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(positional is (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void);
+  ([core::int*, core::int*, core::int*, core::int*]) →* void optional = new self::Direct::•().{self::Direct::optional};
+  self::isTrue(optional is ([core::int*, core::int*, core::int*, core::int*]) →* void);
+  self::isTrue(optional is ([core::Object*, core::int*, core::Object*, core::int*]) →* void);
+  ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void named = new self::Direct::•().{self::Direct::named};
+  self::isTrue(named is ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void);
+  self::isTrue(named is ({a: core::Object*, b: core::int*, c: core::Object*, d: core::int*}) →* void);
+}
+static method testInherited() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void positional = new self::Inherited::•().{self::Direct::positional};
+  self::isTrue(positional is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(positional is (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void);
+  ([core::int*, core::int*, core::int*, core::int*]) →* void optional = new self::Inherited::•().{self::Direct::optional};
+  self::isTrue(optional is ([core::int*, core::int*, core::int*, core::int*]) →* void);
+  self::isTrue(optional is ([core::Object*, core::int*, core::Object*, core::int*]) →* void);
+  ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void named = new self::Inherited::•().{self::Direct::named};
+  self::isTrue(named is ({a: core::int*, b: core::int*, c: core::int*, d: core::int*}) →* void);
+  self::isTrue(named is ({a: core::Object*, b: core::int*, c: core::Object*, d: core::int*}) →* void);
+}
+static method testOverridden() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void method2 = new self::Override2::•().{self::Override2::method};
+  self::isTrue(method2 is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(method2 is (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void);
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void method3 = new self::Override3::•().{self::Override3::method};
+  self::isTrue(method3 is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(method3 is (core::Object*, core::int*, core::Object*, core::int*, core::int*) →* void);
+}
+static method testImplemented() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void method = new self::Implement5::•().{self::Implement5::method};
+  self::isTrue(method is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(method is (core::Object*, core::Object*, core::Object*, core::Object*, core::Object*) →* void);
+}
+static method testMixed() → void {
+  (core::int*, core::int*, core::int*, core::int*, core::int*) →* void method = new self::Mixed::•().{self::Mixed::method};
+  self::isTrue(method is (core::int*, core::int*, core::int*, core::int*, core::int*) →* void);
+  self::isTrue(method is (core::Object*, core::Object*, core::Object*, core::Object*, core::Object*) →* void);
+}
+static method isTrue(core::bool* value) → void {
+  if(!value)
+    throw "Expected true";
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/general/optional.dart.strong.expect b/pkg/front_end/testcases/general/optional.dart.strong.expect
index 6c29683..b6d1e02 100644
--- a/pkg/front_end/testcases/general/optional.dart.strong.expect
+++ b/pkg/front_end/testcases/general/optional.dart.strong.expect
@@ -85,10 +85,20 @@
  - 'Listener' is from 'pkg/front_end/testcases/general/optional.dart'.
   extern.listen(new InvalidListener());
                     ^" in new self::InvalidListener::•() as{TypeError} self::Listener*);
-  dynamic nothing1 = foo.{self::Foo::method}();
-  dynamic nothing2 = foo.{self::Foo::method}(1, 2, 3, 4);
-  core::String* nothing3 = extern.{self::External::externalMethod}();
-  core::String* nothing4 = extern.{self::External::externalMethod}(1, 2, 3, 4);
+  invalid-type nothing1 = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/optional.dart:49:28: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing1 = foo.method();
+                           ^" in foo.{self::Foo::method}();
+  invalid-type nothing2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/optional.dart:50:28: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  var nothing2 = foo.method(1, 2, 3, 4);
+                           ^" in foo.{self::Foo::method}(1, 2, 3, 4);
+  invalid-type nothing3 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general/optional.dart:51:39: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing3 = extern.externalMethod();
+                                      ^" in extern.{self::External::externalMethod}();
+  invalid-type nothing4 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general/optional.dart:52:39: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  var nothing4 = extern.externalMethod(1, 2, 3, 4);
+                                      ^" in extern.{self::External::externalMethod}(1, 2, 3, 4);
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/general/override_check_basic.dart.outline.expect b/pkg/front_end/testcases/general/override_check_basic.dart.outline.expect
index 82a45c2..b8edb06 100644
--- a/pkg/front_end/testcases/general/override_check_basic.dart.outline.expect
+++ b/pkg/front_end/testcases/general/override_check_basic.dart.outline.expect
@@ -2,26 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/override_check_basic.dart:27:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
-//  - 'Object' is from 'dart:core'.
-//  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
-// Change to a subtype of 'A'.
-//   Object f4() {}
-//          ^
-// pkg/front_end/testcases/general/override_check_basic.dart:13:5: Context: This is the overridden method ('f4').
-//   A f4() {}
-//     ^
-//
-// pkg/front_end/testcases/general/override_check_basic.dart:26:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
-//  - 'B' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
-//  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f3({B x}) {}
-//              ^
-// pkg/front_end/testcases/general/override_check_basic.dart:12:8: Context: This is the overridden method ('f3').
-//   void f3({A x}) {}
-//        ^
-//
 // pkg/front_end/testcases/general/override_check_basic.dart:24:13: Error: The parameter 'x' of the method 'E.f1' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f1'.
 //  - 'B' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
@@ -42,6 +22,26 @@
 //   void f2([A x]) {}
 //        ^
 //
+// pkg/front_end/testcases/general/override_check_basic.dart:26:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
+//  - 'B' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f3({B x}) {}
+//              ^
+// pkg/front_end/testcases/general/override_check_basic.dart:12:8: Context: This is the overridden method ('f3').
+//   void f3({A x}) {}
+//        ^
+//
+// pkg/front_end/testcases/general/override_check_basic.dart:27:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
+//  - 'Object' is from 'dart:core'.
+//  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
+// Change to a subtype of 'A'.
+//   Object f4() {}
+//          ^
+// pkg/front_end/testcases/general/override_check_basic.dart:13:5: Context: This is the overridden method ('f4').
+//   A f4() {}
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/override_check_basic.dart.strong.expect b/pkg/front_end/testcases/general/override_check_basic.dart.strong.expect
index a225c07..a53d9df 100644
--- a/pkg/front_end/testcases/general/override_check_basic.dart.strong.expect
+++ b/pkg/front_end/testcases/general/override_check_basic.dart.strong.expect
@@ -2,26 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/override_check_basic.dart:27:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
-//  - 'Object' is from 'dart:core'.
-//  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
-// Change to a subtype of 'A'.
-//   Object f4() {}
-//          ^
-// pkg/front_end/testcases/general/override_check_basic.dart:13:5: Context: This is the overridden method ('f4').
-//   A f4() {}
-//     ^
-//
-// pkg/front_end/testcases/general/override_check_basic.dart:26:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
-//  - 'B' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
-//  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f3({B x}) {}
-//              ^
-// pkg/front_end/testcases/general/override_check_basic.dart:12:8: Context: This is the overridden method ('f3').
-//   void f3({A x}) {}
-//        ^
-//
 // pkg/front_end/testcases/general/override_check_basic.dart:24:13: Error: The parameter 'x' of the method 'E.f1' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f1'.
 //  - 'B' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
@@ -42,6 +22,26 @@
 //   void f2([A x]) {}
 //        ^
 //
+// pkg/front_end/testcases/general/override_check_basic.dart:26:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
+//  - 'B' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f3({B x}) {}
+//              ^
+// pkg/front_end/testcases/general/override_check_basic.dart:12:8: Context: This is the overridden method ('f3').
+//   void f3({A x}) {}
+//        ^
+//
+// pkg/front_end/testcases/general/override_check_basic.dart:27:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
+//  - 'Object' is from 'dart:core'.
+//  - 'A' is from 'pkg/front_end/testcases/general/override_check_basic.dart'.
+// Change to a subtype of 'A'.
+//   Object f4() {}
+//          ^
+// pkg/front_end/testcases/general/override_check_basic.dart:13:5: Context: This is the overridden method ('f4').
+//   A f4() {}
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart.outline.expect b/pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart.outline.expect
index 4c08082..73c8fd7 100644
--- a/pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart.outline.expect
+++ b/pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart.outline.expect
@@ -2,15 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:23:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
-//  - 'A' is from 'pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f5(covariant String x) {}
-//                            ^
-// pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:14:8: Context: This is the overridden method ('f5').
-//   void f5(covariant A x) {}
-//        ^
-//
 // pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:22:13: Error: The parameter 'x' of the method 'D.f4' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f4'.
 //  - 'B' is from 'pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart'.
@@ -21,6 +12,15 @@
 //   void f4(A x) {}
 //        ^
 //
+// pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:23:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
+//  - 'A' is from 'pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f5(covariant String x) {}
+//                            ^
+// pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:14:8: Context: This is the overridden method ('f5').
+//   void f5(covariant A x) {}
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart.strong.expect b/pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart.strong.expect
index 7b32667..8dc7035 100644
--- a/pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart.strong.expect
+++ b/pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart.strong.expect
@@ -2,15 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:23:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
-//  - 'A' is from 'pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f5(covariant String x) {}
-//                            ^
-// pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:14:8: Context: This is the overridden method ('f5').
-//   void f5(covariant A x) {}
-//        ^
-//
 // pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:22:13: Error: The parameter 'x' of the method 'D.f4' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f4'.
 //  - 'B' is from 'pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart'.
@@ -21,6 +12,15 @@
 //   void f4(A x) {}
 //        ^
 //
+// pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:23:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
+//  - 'A' is from 'pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f5(covariant String x) {}
+//                            ^
+// pkg/front_end/testcases/general/override_check_with_covariant_modifier.dart:14:8: Context: This is the overridden method ('f5').
+//   void f5(covariant A x) {}
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart
index d39e9de..fa06830 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart
@@ -4,23 +4,37 @@
 
 class Foo<U> {
   static U foo1() { return null; }
+  static List<U> foo1Prime() { return null; }
   static void foo2(U x) { return null; }
+  static void foo2Prime(List<U> x) { return null; }
   static void foo3() {
     U foo4;
+    List<U> foo4Prime;
     void foo5(U y) => print(y);
+    void foo5Prime(List<U> y) => print(y);
     U foo6() => null;
+    List<U> foo6Prime() => null;
     void Function (U y) foo7 = (U y) => y;
+    void Function (List<U> y) foo7Prime = (List<U> y) => y;
   }
   static U Function() foo8() { return null; }
+  static List<U> Function() foo8Prime() { return null; }
   static void Function(U) foo9() { return null; }
+  static void Function(List<U>) foo9Prime() { return null; }
   static void foo10(U Function()) { return null; }
+  static void foo10Prime(List<U> Function()) { return null; }
   // old syntax: variable named "U" of a function called 'Function'.
   static void foo11(void Function(U)) { return null; }
   static void foo12(void Function(U) b) { return null; }
+  static void foo12Prime(void Function(List<U>) b) { return null; }
   // old syntax: variable named "b" of type "U" of a function called 'Function'.
   static void foo13(void Function(U b)) { return null; }
+  // old syntax: variable named "b" of type "List<U>" of a function called 'Function'.
+  static void foo13Prime(void Function(List<U> b)) { return null; }
   static U foo14 = null;
+  static List<U> foo14Prime = null;
   static U Function(U) foo15 = null;
+  static List<U> Function(List<U>) foo15Prime = null;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect
index 725cfb7..f003356 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect
@@ -2,71 +2,127 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:6:12: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:6:10: Error: Type variables can't be used in static members.
 //   static U foo1() { return null; }
-//            ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:15: Error: Type variables can't be used in static members.
+//   static List<U> foo1Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:8:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
-//               ^
+//                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:14:23: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:9:30: Error: Type variables can't be used in static members.
+//   static void foo2Prime(List<U> x) { return null; }
+//                              ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:20:10: Error: Type variables can't be used in static members.
 //   static U Function() foo8() { return null; }
-//                       ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:15:27: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:15: Error: Type variables can't be used in static members.
+//   static List<U> Function() foo8Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:22:24: Error: Type variables can't be used in static members.
 //   static void Function(U) foo9() { return null; }
-//                           ^
+//                        ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:29: Error: Type variables can't be used in static members.
+//   static void Function(List<U>) foo9Prime() { return null; }
+//                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:24:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//               ^
+//                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:19:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:25:31: Error: Type variables can't be used in static members.
+//   static void foo10Prime(List<U> Function()) { return null; }
+//                               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:28:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:29:45: Error: Type variables can't be used in static members.
+//   static void foo12Prime(void Function(List<U>) b) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:31:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:22:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:33:45: Error: Type variables can't be used in static members.
+//   static void foo13Prime(void Function(List<U> b)) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:34:10: Error: Type variables can't be used in static members.
 //   static U foo14 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:35:15: Error: Type variables can't be used in static members.
+//   static List<U> foo14Prime = null;
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:36:10: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:21: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:36:21: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //                     ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:37:15: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:37:32: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//                                ^
+//
 import self as self;
 import "dart:core" as core;
 
 class Foo<U extends core::Object* = dynamic> extends core::Object {
   static field invalid-type foo14;
+  static field core::List<invalid-type>* foo14Prime;
   static field (invalid-type) →* invalid-type foo15;
+  static field (core::List<invalid-type>*) →* core::List<invalid-type>* foo15Prime;
   synthetic constructor •() → self::Foo<self::Foo::U*>*
     ;
-  static method foo1() → dynamic
+  static method foo1() → invalid-type
     ;
-  static method foo2(generic-covariant-impl dynamic x) → void
+  static method foo1Prime() → core::List<invalid-type>*
+    ;
+  static method foo2(invalid-type x) → void
+    ;
+  static method foo2Prime(core::List<invalid-type>* x) → void
     ;
   static method foo3() → void
     ;
-  static method foo8() → () →* dynamic
+  static method foo8() → () →* invalid-type
     ;
-  static method foo9() → (dynamic) →* void
+  static method foo8Prime() → () →* core::List<invalid-type>*
     ;
-  static method foo10(generic-covariant-impl () →* dynamic Function) → void
+  static method foo9() → (invalid-type) →* void
+    ;
+  static method foo9Prime() → (core::List<invalid-type>*) →* void
+    ;
+  static method foo10(() →* invalid-type Function) → void
+    ;
+  static method foo10Prime(() →* core::List<invalid-type>* Function) → void
     ;
   static method foo11((dynamic) →* void Function) → void
     ;
-  static method foo12((dynamic) →* void b) → void
+  static method foo12((invalid-type) →* void b) → void
     ;
-  static method foo13((dynamic) →* void Function) → void
+  static method foo12Prime((core::List<invalid-type>*) →* void b) → void
+    ;
+  static method foo13((invalid-type) →* void Function) → void
+    ;
+  static method foo13Prime((core::List<invalid-type>*) →* void Function) → void
     ;
 }
 static method main() → dynamic
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect
index dfd67aa..7cd4aec 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect
@@ -2,121 +2,194 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:6:12: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:6:10: Error: Type variables can't be used in static members.
 //   static U foo1() { return null; }
-//            ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:15: Error: Type variables can't be used in static members.
+//   static List<U> foo1Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:8:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
-//               ^
+//                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:14:23: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:9:30: Error: Type variables can't be used in static members.
+//   static void foo2Prime(List<U> x) { return null; }
+//                              ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:20:10: Error: Type variables can't be used in static members.
 //   static U Function() foo8() { return null; }
-//                       ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:15:27: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:15: Error: Type variables can't be used in static members.
+//   static List<U> Function() foo8Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:22:24: Error: Type variables can't be used in static members.
 //   static void Function(U) foo9() { return null; }
-//                           ^
+//                        ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:29: Error: Type variables can't be used in static members.
+//   static void Function(List<U>) foo9Prime() { return null; }
+//                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:24:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//               ^
+//                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:19:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:25:31: Error: Type variables can't be used in static members.
+//   static void foo10Prime(List<U> Function()) { return null; }
+//                               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:28:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:29:45: Error: Type variables can't be used in static members.
+//   static void foo12Prime(void Function(List<U>) b) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:31:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:22:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:33:45: Error: Type variables can't be used in static members.
+//   static void foo13Prime(void Function(List<U> b)) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:34:10: Error: Type variables can't be used in static members.
 //   static U foo14 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:35:15: Error: Type variables can't be used in static members.
+//   static List<U> foo14Prime = null;
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:36:10: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:21: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:36:21: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:20: Error: Type variables can't be used in static members.
-//   static void foo2(U x) { return null; }
-//                    ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:37:15: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//               ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:9:5: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:37:32: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//                                ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:11:5: Error: Type variables can't be used in static members.
 //     U foo4;
 //     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:10:17: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:12:10: Error: Type variables can't be used in static members.
+//     List<U> foo4Prime;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:13:15: Error: Type variables can't be used in static members.
 //     void foo5(U y) => print(y);
-//                 ^
+//               ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:11:11: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:14:25: Error: Type variables can't be used in static members.
+//     void foo5Prime(List<U> y) => print(y);
+//                         ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:15:5: Error: Type variables can't be used in static members.
 //     U foo6() => null;
-//           ^
+//     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:12:20: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:10: Error: Type variables can't be used in static members.
+//     List<U> foo6Prime() => null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:17:20: Error: Type variables can't be used in static members.
 //     void Function (U y) foo7 = (U y) => y;
 //                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:12:35: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:17:33: Error: Type variables can't be used in static members.
 //     void Function (U y) foo7 = (U y) => y;
-//                                   ^
+//                                 ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:21: Error: Type variables can't be used in static members.
-//   static void foo10(U Function()) { return null; }
-//                     ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:18:25: Error: Type variables can't be used in static members.
+//     void Function (List<U> y) foo7Prime = (List<U> y) => y;
+//                         ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:19:35: Error: Type variables can't be used in static members.
-//   static void foo12(void Function(U) b) { return null; }
-//                                   ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:35: Error: Type variables can't be used in static members.
-//   static void foo13(void Function(U b)) { return null; }
-//                                   ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:18:49: Error: Type variables can't be used in static members.
+//     void Function (List<U> y) foo7Prime = (List<U> y) => y;
+//                                                 ^
 //
 import self as self;
 import "dart:core" as core;
 
 class Foo<U extends core::Object* = dynamic> extends core::Object {
   static field invalid-type foo14 = null;
+  static field core::List<invalid-type>* foo14Prime = null;
   static field (invalid-type) →* invalid-type foo15 = null;
+  static field (core::List<invalid-type>*) →* core::List<invalid-type>* foo15Prime = null;
   synthetic constructor •() → self::Foo<self::Foo::U*>*
     : super core::Object::•()
     ;
-  static method foo1() → dynamic {
+  static method foo1() → invalid-type {
     return null;
   }
-  static method foo2(generic-covariant-impl dynamic x) → void {
+  static method foo1Prime() → core::List<invalid-type>* {
+    return null;
+  }
+  static method foo2(invalid-type x) → void {
+    return null;
+  }
+  static method foo2Prime(core::List<invalid-type>* x) → void {
     return null;
   }
   static method foo3() → void {
     invalid-type foo4;
-    function foo5(dynamic y) → void
+    core::List<invalid-type>* foo4Prime;
+    function foo5(invalid-type y) → void
       return core::print(y);
-    function foo6() → dynamic
+    function foo5Prime(core::List<invalid-type>* y) → void
+      return core::print(y);
+    function foo6() → invalid-type
       return null;
-    (dynamic) →* dynamic foo7 = (dynamic y) → dynamic => y;
+    function foo6Prime() → core::List<invalid-type>*
+      return null;
+    (invalid-type) →* invalid-type foo7 = (invalid-type y) → invalid-type => y;
+    (core::List<invalid-type>*) →* void foo7Prime = (core::List<invalid-type>* y) → core::List<invalid-type>* => y;
   }
-  static method foo8() → () →* dynamic {
+  static method foo8() → () →* invalid-type {
     return null;
   }
-  static method foo9() → (dynamic) →* void {
+  static method foo8Prime() → () →* core::List<invalid-type>* {
     return null;
   }
-  static method foo10(generic-covariant-impl () →* dynamic Function) → void {
+  static method foo9() → (invalid-type) →* void {
+    return null;
+  }
+  static method foo9Prime() → (core::List<invalid-type>*) →* void {
+    return null;
+  }
+  static method foo10(() →* invalid-type Function) → void {
+    return null;
+  }
+  static method foo10Prime(() →* core::List<invalid-type>* Function) → void {
     return null;
   }
   static method foo11((dynamic) →* void Function) → void {
     return null;
   }
-  static method foo12((dynamic) →* void b) → void {
+  static method foo12((invalid-type) →* void b) → void {
     return null;
   }
-  static method foo13((dynamic) →* void Function) → void {
+  static method foo12Prime((core::List<invalid-type>*) →* void b) → void {
+    return null;
+  }
+  static method foo13((invalid-type) →* void Function) → void {
+    return null;
+  }
+  static method foo13Prime((core::List<invalid-type>*) →* void Function) → void {
     return null;
   }
 }
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect
index dfd67aa..7cd4aec 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect
@@ -2,121 +2,194 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:6:12: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:6:10: Error: Type variables can't be used in static members.
 //   static U foo1() { return null; }
-//            ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:15: Error: Type variables can't be used in static members.
+//   static List<U> foo1Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:8:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
-//               ^
+//                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:14:23: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:9:30: Error: Type variables can't be used in static members.
+//   static void foo2Prime(List<U> x) { return null; }
+//                              ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:20:10: Error: Type variables can't be used in static members.
 //   static U Function() foo8() { return null; }
-//                       ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:15:27: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:15: Error: Type variables can't be used in static members.
+//   static List<U> Function() foo8Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:22:24: Error: Type variables can't be used in static members.
 //   static void Function(U) foo9() { return null; }
-//                           ^
+//                        ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:29: Error: Type variables can't be used in static members.
+//   static void Function(List<U>) foo9Prime() { return null; }
+//                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:24:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//               ^
+//                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:19:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:25:31: Error: Type variables can't be used in static members.
+//   static void foo10Prime(List<U> Function()) { return null; }
+//                               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:28:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:29:45: Error: Type variables can't be used in static members.
+//   static void foo12Prime(void Function(List<U>) b) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:31:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:22:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:33:45: Error: Type variables can't be used in static members.
+//   static void foo13Prime(void Function(List<U> b)) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:34:10: Error: Type variables can't be used in static members.
 //   static U foo14 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:35:15: Error: Type variables can't be used in static members.
+//   static List<U> foo14Prime = null;
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:36:10: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:23:21: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:36:21: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:20: Error: Type variables can't be used in static members.
-//   static void foo2(U x) { return null; }
-//                    ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:37:15: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//               ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:9:5: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:37:32: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//                                ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:11:5: Error: Type variables can't be used in static members.
 //     U foo4;
 //     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:10:17: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:12:10: Error: Type variables can't be used in static members.
+//     List<U> foo4Prime;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:13:15: Error: Type variables can't be used in static members.
 //     void foo5(U y) => print(y);
-//                 ^
+//               ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:11:11: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:14:25: Error: Type variables can't be used in static members.
+//     void foo5Prime(List<U> y) => print(y);
+//                         ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:15:5: Error: Type variables can't be used in static members.
 //     U foo6() => null;
-//           ^
+//     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:12:20: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:10: Error: Type variables can't be used in static members.
+//     List<U> foo6Prime() => null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:17:20: Error: Type variables can't be used in static members.
 //     void Function (U y) foo7 = (U y) => y;
 //                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:12:35: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:17:33: Error: Type variables can't be used in static members.
 //     void Function (U y) foo7 = (U y) => y;
-//                                   ^
+//                                 ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:16:21: Error: Type variables can't be used in static members.
-//   static void foo10(U Function()) { return null; }
-//                     ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:18:25: Error: Type variables can't be used in static members.
+//     void Function (List<U> y) foo7Prime = (List<U> y) => y;
+//                         ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:19:35: Error: Type variables can't be used in static members.
-//   static void foo12(void Function(U) b) { return null; }
-//                                   ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:21:35: Error: Type variables can't be used in static members.
-//   static void foo13(void Function(U b)) { return null; }
-//                                   ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:18:49: Error: Type variables can't be used in static members.
+//     void Function (List<U> y) foo7Prime = (List<U> y) => y;
+//                                                 ^
 //
 import self as self;
 import "dart:core" as core;
 
 class Foo<U extends core::Object* = dynamic> extends core::Object {
   static field invalid-type foo14 = null;
+  static field core::List<invalid-type>* foo14Prime = null;
   static field (invalid-type) →* invalid-type foo15 = null;
+  static field (core::List<invalid-type>*) →* core::List<invalid-type>* foo15Prime = null;
   synthetic constructor •() → self::Foo<self::Foo::U*>*
     : super core::Object::•()
     ;
-  static method foo1() → dynamic {
+  static method foo1() → invalid-type {
     return null;
   }
-  static method foo2(generic-covariant-impl dynamic x) → void {
+  static method foo1Prime() → core::List<invalid-type>* {
+    return null;
+  }
+  static method foo2(invalid-type x) → void {
+    return null;
+  }
+  static method foo2Prime(core::List<invalid-type>* x) → void {
     return null;
   }
   static method foo3() → void {
     invalid-type foo4;
-    function foo5(dynamic y) → void
+    core::List<invalid-type>* foo4Prime;
+    function foo5(invalid-type y) → void
       return core::print(y);
-    function foo6() → dynamic
+    function foo5Prime(core::List<invalid-type>* y) → void
+      return core::print(y);
+    function foo6() → invalid-type
       return null;
-    (dynamic) →* dynamic foo7 = (dynamic y) → dynamic => y;
+    function foo6Prime() → core::List<invalid-type>*
+      return null;
+    (invalid-type) →* invalid-type foo7 = (invalid-type y) → invalid-type => y;
+    (core::List<invalid-type>*) →* void foo7Prime = (core::List<invalid-type>* y) → core::List<invalid-type>* => y;
   }
-  static method foo8() → () →* dynamic {
+  static method foo8() → () →* invalid-type {
     return null;
   }
-  static method foo9() → (dynamic) →* void {
+  static method foo8Prime() → () →* core::List<invalid-type>* {
     return null;
   }
-  static method foo10(generic-covariant-impl () →* dynamic Function) → void {
+  static method foo9() → (invalid-type) →* void {
+    return null;
+  }
+  static method foo9Prime() → (core::List<invalid-type>*) →* void {
+    return null;
+  }
+  static method foo10(() →* invalid-type Function) → void {
+    return null;
+  }
+  static method foo10Prime(() →* core::List<invalid-type>* Function) → void {
     return null;
   }
   static method foo11((dynamic) →* void Function) → void {
     return null;
   }
-  static method foo12((dynamic) →* void b) → void {
+  static method foo12((invalid-type) →* void b) → void {
     return null;
   }
-  static method foo13((dynamic) →* void Function) → void {
+  static method foo12Prime((core::List<invalid-type>*) →* void b) → void {
+    return null;
+  }
+  static method foo13((invalid-type) →* void Function) → void {
+    return null;
+  }
+  static method foo13Prime((core::List<invalid-type>*) →* void Function) → void {
     return null;
   }
 }
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart
index 78b773e..043ac34 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart
@@ -4,23 +4,37 @@
 
 extension Foo<U> on List {
   static U foo1() { return null; }
+  static List<U> foo1Prime() { return null; }
   static void foo2(U x) { return null; }
+  static void foo2Prime(List<U> x) { return null; }
   static void foo3() {
     U foo4;
+    List<U> foo4Prime;
     void foo5(U y) => print(y);
+    void foo5Prime(List<U> y) => print(y);
     U foo6() => null;
+    List<U> foo6Prime() => null;
     void Function (U y) foo7 = (U y) => y;
+    void Function (List<U> y) foo7Prime = (List<U> y) => y;
   }
   static U Function() foo8() { return null; }
+  static List<U> Function() foo8Prime() { return null; }
   static void Function(U) foo9() { return null; }
+  static void Function(List<U>) foo9Prime() { return null; }
   static void foo10(U Function()) { return null; }
+  static void foo10Prime(List<U> Function()) { return null; }
   // old syntax: variable named "U" of a function called 'Function'.
   static void foo11(void Function(U)) { return null; }
   static void foo12(void Function(U) b) { return null; }
+  static void foo12Prime(void Function(List<U>) b) { return null; }
   // old syntax: variable named "b" of type "U" of a function called 'Function'.
   static void foo13(void Function(U b)) { return null; }
+  // old syntax: variable named "b" of type "List<U>" of a function called 'Function'.
+  static void foo13Prime(void Function(List<U> b)) { return null; }
   static U foo14 = null;
+  static List<U> foo14Prime = null;
   static U Function(U) foo15 = null;
+  static List<U> Function(List<U>) foo15Prime = null;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect
index d6da116..03ea969 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect
@@ -2,81 +2,146 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:6:12: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:6:10: Error: Type variables can't be used in static members.
 //   static U foo1() { return null; }
-//            ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:15: Error: Type variables can't be used in static members.
+//   static List<U> foo1Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:8:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
-//               ^
+//                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:14:23: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:9:30: Error: Type variables can't be used in static members.
+//   static void foo2Prime(List<U> x) { return null; }
+//                              ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:20:10: Error: Type variables can't be used in static members.
 //   static U Function() foo8() { return null; }
-//                       ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:15:27: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:15: Error: Type variables can't be used in static members.
+//   static List<U> Function() foo8Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:22:24: Error: Type variables can't be used in static members.
 //   static void Function(U) foo9() { return null; }
-//                           ^
+//                        ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:29: Error: Type variables can't be used in static members.
+//   static void Function(List<U>) foo9Prime() { return null; }
+//                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:24:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//               ^
+//                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:19:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:25:31: Error: Type variables can't be used in static members.
+//   static void foo10Prime(List<U> Function()) { return null; }
+//                               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:28:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:29:45: Error: Type variables can't be used in static members.
+//   static void foo12Prime(void Function(List<U>) b) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:31:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:22:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:33:45: Error: Type variables can't be used in static members.
+//   static void foo13Prime(void Function(List<U> b)) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:34:10: Error: Type variables can't be used in static members.
 //   static U foo14 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:35:15: Error: Type variables can't be used in static members.
+//   static List<U> foo14Prime = null;
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:36:10: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:21: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:36:21: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //                     ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:37:15: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:37:32: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//                                ^
+//
 import self as self;
 import "dart:core" as core;
 
 extension Foo<U extends core::Object* = dynamic> on core::List<dynamic>* {
   static method foo1 = self::Foo|foo1;
+  static method foo1Prime = self::Foo|foo1Prime;
   static method foo2 = self::Foo|foo2;
+  static method foo2Prime = self::Foo|foo2Prime;
   static method foo3 = self::Foo|foo3;
   static method foo8 = self::Foo|foo8;
+  static method foo8Prime = self::Foo|foo8Prime;
   static method foo9 = self::Foo|foo9;
+  static method foo9Prime = self::Foo|foo9Prime;
   static method foo10 = self::Foo|foo10;
+  static method foo10Prime = self::Foo|foo10Prime;
   static method foo11 = self::Foo|foo11;
   static method foo12 = self::Foo|foo12;
+  static method foo12Prime = self::Foo|foo12Prime;
   static method foo13 = self::Foo|foo13;
+  static method foo13Prime = self::Foo|foo13Prime;
   static field foo14 = self::Foo|foo14;
+  static field foo14Prime = self::Foo|foo14Prime;
   static field foo15 = self::Foo|foo15;
+  static field foo15Prime = self::Foo|foo15Prime;
 }
 static field invalid-type Foo|foo14;
+static field core::List<invalid-type>* Foo|foo14Prime;
 static field (invalid-type) →* invalid-type Foo|foo15;
-static method Foo|foo1() → dynamic
+static field (core::List<invalid-type>*) →* core::List<invalid-type>* Foo|foo15Prime;
+static method Foo|foo1() → invalid-type
   ;
-static method Foo|foo2(dynamic x) → void
+static method Foo|foo1Prime() → core::List<invalid-type>*
+  ;
+static method Foo|foo2(invalid-type x) → void
+  ;
+static method Foo|foo2Prime(core::List<invalid-type>* x) → void
   ;
 static method Foo|foo3() → void
   ;
-static method Foo|foo8() → () →* dynamic
+static method Foo|foo8() → () →* invalid-type
   ;
-static method Foo|foo9() → (dynamic) →* void
+static method Foo|foo8Prime() → () →* core::List<invalid-type>*
   ;
-static method Foo|foo10(() →* dynamic Function) → void
+static method Foo|foo9() → (invalid-type) →* void
+  ;
+static method Foo|foo9Prime() → (core::List<invalid-type>*) →* void
+  ;
+static method Foo|foo10(() →* invalid-type Function) → void
+  ;
+static method Foo|foo10Prime(() →* core::List<invalid-type>* Function) → void
   ;
 static method Foo|foo11((dynamic) →* void Function) → void
   ;
-static method Foo|foo12((dynamic) →* void b) → void
+static method Foo|foo12((invalid-type) →* void b) → void
   ;
-static method Foo|foo13((dynamic) →* void Function) → void
+static method Foo|foo12Prime((core::List<invalid-type>*) →* void b) → void
+  ;
+static method Foo|foo13((invalid-type) →* void Function) → void
+  ;
+static method Foo|foo13Prime((core::List<invalid-type>*) →* void Function) → void
   ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect
index c1f1018..97ad6b7 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect
@@ -2,130 +2,212 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:6:12: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:6:10: Error: Type variables can't be used in static members.
 //   static U foo1() { return null; }
-//            ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:15: Error: Type variables can't be used in static members.
+//   static List<U> foo1Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:8:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
-//               ^
+//                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:14:23: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:9:30: Error: Type variables can't be used in static members.
+//   static void foo2Prime(List<U> x) { return null; }
+//                              ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:20:10: Error: Type variables can't be used in static members.
 //   static U Function() foo8() { return null; }
-//                       ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:15:27: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:15: Error: Type variables can't be used in static members.
+//   static List<U> Function() foo8Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:22:24: Error: Type variables can't be used in static members.
 //   static void Function(U) foo9() { return null; }
-//                           ^
+//                        ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:29: Error: Type variables can't be used in static members.
+//   static void Function(List<U>) foo9Prime() { return null; }
+//                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:24:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//               ^
+//                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:19:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:25:31: Error: Type variables can't be used in static members.
+//   static void foo10Prime(List<U> Function()) { return null; }
+//                               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:28:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:29:45: Error: Type variables can't be used in static members.
+//   static void foo12Prime(void Function(List<U>) b) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:31:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:22:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:33:45: Error: Type variables can't be used in static members.
+//   static void foo13Prime(void Function(List<U> b)) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:34:10: Error: Type variables can't be used in static members.
 //   static U foo14 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:35:15: Error: Type variables can't be used in static members.
+//   static List<U> foo14Prime = null;
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:36:10: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:21: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:36:21: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:20: Error: Type variables can't be used in static members.
-//   static void foo2(U x) { return null; }
-//                    ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:37:15: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//               ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:9:5: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:37:32: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//                                ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:11:5: Error: Type variables can't be used in static members.
 //     U foo4;
 //     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:10:17: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:12:10: Error: Type variables can't be used in static members.
+//     List<U> foo4Prime;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:13:15: Error: Type variables can't be used in static members.
 //     void foo5(U y) => print(y);
-//                 ^
+//               ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:11:11: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:14:25: Error: Type variables can't be used in static members.
+//     void foo5Prime(List<U> y) => print(y);
+//                         ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:15:5: Error: Type variables can't be used in static members.
 //     U foo6() => null;
-//           ^
+//     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:12:20: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:10: Error: Type variables can't be used in static members.
+//     List<U> foo6Prime() => null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:17:20: Error: Type variables can't be used in static members.
 //     void Function (U y) foo7 = (U y) => y;
 //                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:12:35: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:17:33: Error: Type variables can't be used in static members.
 //     void Function (U y) foo7 = (U y) => y;
-//                                   ^
+//                                 ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:21: Error: Type variables can't be used in static members.
-//   static void foo10(U Function()) { return null; }
-//                     ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:18:25: Error: Type variables can't be used in static members.
+//     void Function (List<U> y) foo7Prime = (List<U> y) => y;
+//                         ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:19:35: Error: Type variables can't be used in static members.
-//   static void foo12(void Function(U) b) { return null; }
-//                                   ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:35: Error: Type variables can't be used in static members.
-//   static void foo13(void Function(U b)) { return null; }
-//                                   ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:18:49: Error: Type variables can't be used in static members.
+//     void Function (List<U> y) foo7Prime = (List<U> y) => y;
+//                                                 ^
 //
 import self as self;
 import "dart:core" as core;
 
 extension Foo<U extends core::Object* = dynamic> on core::List<dynamic>* {
   static method foo1 = self::Foo|foo1;
+  static method foo1Prime = self::Foo|foo1Prime;
   static method foo2 = self::Foo|foo2;
+  static method foo2Prime = self::Foo|foo2Prime;
   static method foo3 = self::Foo|foo3;
   static method foo8 = self::Foo|foo8;
+  static method foo8Prime = self::Foo|foo8Prime;
   static method foo9 = self::Foo|foo9;
+  static method foo9Prime = self::Foo|foo9Prime;
   static method foo10 = self::Foo|foo10;
+  static method foo10Prime = self::Foo|foo10Prime;
   static method foo11 = self::Foo|foo11;
   static method foo12 = self::Foo|foo12;
+  static method foo12Prime = self::Foo|foo12Prime;
   static method foo13 = self::Foo|foo13;
+  static method foo13Prime = self::Foo|foo13Prime;
   static field foo14 = self::Foo|foo14;
+  static field foo14Prime = self::Foo|foo14Prime;
   static field foo15 = self::Foo|foo15;
+  static field foo15Prime = self::Foo|foo15Prime;
 }
 static field invalid-type Foo|foo14 = null;
+static field core::List<invalid-type>* Foo|foo14Prime = null;
 static field (invalid-type) →* invalid-type Foo|foo15 = null;
-static method Foo|foo1() → dynamic {
+static field (core::List<invalid-type>*) →* core::List<invalid-type>* Foo|foo15Prime = null;
+static method Foo|foo1() → invalid-type {
   return null;
 }
-static method Foo|foo2(dynamic x) → void {
+static method Foo|foo1Prime() → core::List<invalid-type>* {
+  return null;
+}
+static method Foo|foo2(invalid-type x) → void {
+  return null;
+}
+static method Foo|foo2Prime(core::List<invalid-type>* x) → void {
   return null;
 }
 static method Foo|foo3() → void {
   invalid-type foo4;
-  function foo5(dynamic y) → void
+  core::List<invalid-type>* foo4Prime;
+  function foo5(invalid-type y) → void
     return core::print(y);
-  function foo6() → dynamic
+  function foo5Prime(core::List<invalid-type>* y) → void
+    return core::print(y);
+  function foo6() → invalid-type
     return null;
-  (dynamic) →* dynamic foo7 = (dynamic y) → dynamic => y;
+  function foo6Prime() → core::List<invalid-type>*
+    return null;
+  (invalid-type) →* invalid-type foo7 = (invalid-type y) → invalid-type => y;
+  (core::List<invalid-type>*) →* void foo7Prime = (core::List<invalid-type>* y) → core::List<invalid-type>* => y;
 }
-static method Foo|foo8() → () →* dynamic {
+static method Foo|foo8() → () →* invalid-type {
   return null;
 }
-static method Foo|foo9() → (dynamic) →* void {
+static method Foo|foo8Prime() → () →* core::List<invalid-type>* {
   return null;
 }
-static method Foo|foo10(() →* dynamic Function) → void {
+static method Foo|foo9() → (invalid-type) →* void {
+  return null;
+}
+static method Foo|foo9Prime() → (core::List<invalid-type>*) →* void {
+  return null;
+}
+static method Foo|foo10(() →* invalid-type Function) → void {
+  return null;
+}
+static method Foo|foo10Prime(() →* core::List<invalid-type>* Function) → void {
   return null;
 }
 static method Foo|foo11((dynamic) →* void Function) → void {
   return null;
 }
-static method Foo|foo12((dynamic) →* void b) → void {
+static method Foo|foo12((invalid-type) →* void b) → void {
   return null;
 }
-static method Foo|foo13((dynamic) →* void Function) → void {
+static method Foo|foo12Prime((core::List<invalid-type>*) →* void b) → void {
+  return null;
+}
+static method Foo|foo13((invalid-type) →* void Function) → void {
+  return null;
+}
+static method Foo|foo13Prime((core::List<invalid-type>*) →* void Function) → void {
   return null;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect
index c1f1018..97ad6b7 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect
@@ -2,130 +2,212 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:6:12: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:6:10: Error: Type variables can't be used in static members.
 //   static U foo1() { return null; }
-//            ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:15: Error: Type variables can't be used in static members.
+//   static List<U> foo1Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:8:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
-//               ^
+//                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:14:23: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:9:30: Error: Type variables can't be used in static members.
+//   static void foo2Prime(List<U> x) { return null; }
+//                              ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:20:10: Error: Type variables can't be used in static members.
 //   static U Function() foo8() { return null; }
-//                       ^
+//          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:15:27: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:15: Error: Type variables can't be used in static members.
+//   static List<U> Function() foo8Prime() { return null; }
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:22:24: Error: Type variables can't be used in static members.
 //   static void Function(U) foo9() { return null; }
-//                           ^
+//                        ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:29: Error: Type variables can't be used in static members.
+//   static void Function(List<U>) foo9Prime() { return null; }
+//                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:24:21: Error: Type variables can't be used in static members.
 //   static void foo10(U Function()) { return null; }
-//               ^
+//                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:19:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:25:31: Error: Type variables can't be used in static members.
+//   static void foo10Prime(List<U> Function()) { return null; }
+//                               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:28:35: Error: Type variables can't be used in static members.
 //   static void foo12(void Function(U) b) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:15: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:29:45: Error: Type variables can't be used in static members.
+//   static void foo12Prime(void Function(List<U>) b) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:31:35: Error: Type variables can't be used in static members.
 //   static void foo13(void Function(U b)) { return null; }
-//               ^
+//                                   ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:22:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:33:45: Error: Type variables can't be used in static members.
+//   static void foo13Prime(void Function(List<U> b)) { return null; }
+//                                             ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:34:10: Error: Type variables can't be used in static members.
 //   static U foo14 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:10: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:35:15: Error: Type variables can't be used in static members.
+//   static List<U> foo14Prime = null;
+//               ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:36:10: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //          ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:23:21: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:36:21: Error: Type variables can't be used in static members.
 //   static U Function(U) foo15 = null;
 //                     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:20: Error: Type variables can't be used in static members.
-//   static void foo2(U x) { return null; }
-//                    ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:37:15: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//               ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:9:5: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:37:32: Error: Type variables can't be used in static members.
+//   static List<U> Function(List<U>) foo15Prime = null;
+//                                ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:11:5: Error: Type variables can't be used in static members.
 //     U foo4;
 //     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:10:17: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:12:10: Error: Type variables can't be used in static members.
+//     List<U> foo4Prime;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:13:15: Error: Type variables can't be used in static members.
 //     void foo5(U y) => print(y);
-//                 ^
+//               ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:11:11: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:14:25: Error: Type variables can't be used in static members.
+//     void foo5Prime(List<U> y) => print(y);
+//                         ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:15:5: Error: Type variables can't be used in static members.
 //     U foo6() => null;
-//           ^
+//     ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:12:20: Error: Type variables can't be used in static members.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:10: Error: Type variables can't be used in static members.
+//     List<U> foo6Prime() => null;
+//          ^
+//
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:17:20: Error: Type variables can't be used in static members.
 //     void Function (U y) foo7 = (U y) => y;
 //                    ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:12:35: Error: Can only use type variables in instance methods.
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:17:33: Error: Type variables can't be used in static members.
 //     void Function (U y) foo7 = (U y) => y;
-//                                   ^
+//                                 ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:16:21: Error: Type variables can't be used in static members.
-//   static void foo10(U Function()) { return null; }
-//                     ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:18:25: Error: Type variables can't be used in static members.
+//     void Function (List<U> y) foo7Prime = (List<U> y) => y;
+//                         ^
 //
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:19:35: Error: Type variables can't be used in static members.
-//   static void foo12(void Function(U) b) { return null; }
-//                                   ^
-//
-// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:21:35: Error: Type variables can't be used in static members.
-//   static void foo13(void Function(U b)) { return null; }
-//                                   ^
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:18:49: Error: Type variables can't be used in static members.
+//     void Function (List<U> y) foo7Prime = (List<U> y) => y;
+//                                                 ^
 //
 import self as self;
 import "dart:core" as core;
 
 extension Foo<U extends core::Object* = dynamic> on core::List<dynamic>* {
   static method foo1 = self::Foo|foo1;
+  static method foo1Prime = self::Foo|foo1Prime;
   static method foo2 = self::Foo|foo2;
+  static method foo2Prime = self::Foo|foo2Prime;
   static method foo3 = self::Foo|foo3;
   static method foo8 = self::Foo|foo8;
+  static method foo8Prime = self::Foo|foo8Prime;
   static method foo9 = self::Foo|foo9;
+  static method foo9Prime = self::Foo|foo9Prime;
   static method foo10 = self::Foo|foo10;
+  static method foo10Prime = self::Foo|foo10Prime;
   static method foo11 = self::Foo|foo11;
   static method foo12 = self::Foo|foo12;
+  static method foo12Prime = self::Foo|foo12Prime;
   static method foo13 = self::Foo|foo13;
+  static method foo13Prime = self::Foo|foo13Prime;
   static field foo14 = self::Foo|foo14;
+  static field foo14Prime = self::Foo|foo14Prime;
   static field foo15 = self::Foo|foo15;
+  static field foo15Prime = self::Foo|foo15Prime;
 }
 static field invalid-type Foo|foo14 = null;
+static field core::List<invalid-type>* Foo|foo14Prime = null;
 static field (invalid-type) →* invalid-type Foo|foo15 = null;
-static method Foo|foo1() → dynamic {
+static field (core::List<invalid-type>*) →* core::List<invalid-type>* Foo|foo15Prime = null;
+static method Foo|foo1() → invalid-type {
   return null;
 }
-static method Foo|foo2(dynamic x) → void {
+static method Foo|foo1Prime() → core::List<invalid-type>* {
+  return null;
+}
+static method Foo|foo2(invalid-type x) → void {
+  return null;
+}
+static method Foo|foo2Prime(core::List<invalid-type>* x) → void {
   return null;
 }
 static method Foo|foo3() → void {
   invalid-type foo4;
-  function foo5(dynamic y) → void
+  core::List<invalid-type>* foo4Prime;
+  function foo5(invalid-type y) → void
     return core::print(y);
-  function foo6() → dynamic
+  function foo5Prime(core::List<invalid-type>* y) → void
+    return core::print(y);
+  function foo6() → invalid-type
     return null;
-  (dynamic) →* dynamic foo7 = (dynamic y) → dynamic => y;
+  function foo6Prime() → core::List<invalid-type>*
+    return null;
+  (invalid-type) →* invalid-type foo7 = (invalid-type y) → invalid-type => y;
+  (core::List<invalid-type>*) →* void foo7Prime = (core::List<invalid-type>* y) → core::List<invalid-type>* => y;
 }
-static method Foo|foo8() → () →* dynamic {
+static method Foo|foo8() → () →* invalid-type {
   return null;
 }
-static method Foo|foo9() → (dynamic) →* void {
+static method Foo|foo8Prime() → () →* core::List<invalid-type>* {
   return null;
 }
-static method Foo|foo10(() →* dynamic Function) → void {
+static method Foo|foo9() → (invalid-type) →* void {
+  return null;
+}
+static method Foo|foo9Prime() → (core::List<invalid-type>*) →* void {
+  return null;
+}
+static method Foo|foo10(() →* invalid-type Function) → void {
+  return null;
+}
+static method Foo|foo10Prime(() →* core::List<invalid-type>* Function) → void {
   return null;
 }
 static method Foo|foo11((dynamic) →* void Function) → void {
   return null;
 }
-static method Foo|foo12((dynamic) →* void b) → void {
+static method Foo|foo12((invalid-type) →* void b) → void {
   return null;
 }
-static method Foo|foo13((dynamic) →* void Function) → void {
+static method Foo|foo12Prime((core::List<invalid-type>*) →* void b) → void {
+  return null;
+}
+static method Foo|foo13((invalid-type) →* void Function) → void {
+  return null;
+}
+static method Foo|foo13Prime((core::List<invalid-type>*) →* void Function) → void {
   return null;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart b/pkg/front_end/testcases/general/vm_type_ops.dart
new file mode 100644
index 0000000..a7adf35
--- /dev/null
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Copied from pkg/vm/testcases/bytecode/type_ops.dart
+
+class A<T> {}
+
+class B extends A<String> {}
+
+class C<T1, T2, T3> extends B {}
+
+foo1(x) {
+  if (x is B) {
+    print('11');
+  }
+  if (x is C<int, Object, dynamic>) {
+    print('12');
+  }
+  return x as A<int>;
+}
+
+class D<P, Q> extends C<int, Q, P> {
+  Map<P, Q> foo;
+
+  D(tt) : foo = tt;
+
+  foo2(y) {
+    if (y is A<P>) {
+      print('21');
+    }
+    if (y is C<dynamic, Q, List<P>>) {
+      print('22');
+    }
+    foo = y;
+  }
+
+  foo3<T1, T2>(z) {
+    if (z is A<T1>) {
+      print('31');
+    }
+    if (z is C<Map<T1, P>, List<T2>, Q>) {
+      print('32');
+    }
+    return (z as Map<T2, Q>).values;
+  }
+
+  Map<P, Q> foo4(w) {
+    List<Map<P, Q>> list = [w];
+    return w;
+  }
+}
+
+List<Iterable> globalVar;
+
+void foo5(x) {
+  globalVar = x;
+}
+
+class E<P extends String> {
+  factory E() => null;
+  void foo6<T extends P, U extends List<T>>(Map<T, U> map) {}
+}
+
+abstract class F<T> {
+  void foo7<Q extends T>(Q a, covariant num b, T c);
+  void foo8<Q extends T>(Q a, covariant num b, T c);
+}
+
+class G<T> {
+  void foo7<Q extends T>(Q a, int b, T c) {}
+}
+
+class H<T> extends G<T> implements F<T> {
+  void foo8<Q extends T>(Q a, int b, T c) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect
new file mode 100644
index 0000000..3950bfe
--- /dev/null
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.outline.expect
@@ -0,0 +1,60 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T*>*
+    ;
+}
+class B extends self::A<core::String*> {
+  synthetic constructor •() → self::B*
+    ;
+}
+class C<T1 extends core::Object* = dynamic, T2 extends core::Object* = dynamic, T3 extends core::Object* = dynamic> extends self::B {
+  synthetic constructor •() → self::C<self::C::T1*, self::C::T2*, self::C::T3*>*
+    ;
+}
+class D<P extends core::Object* = dynamic, Q extends core::Object* = dynamic> extends self::C<core::int*, self::D::Q*, self::D::P*> {
+  generic-covariant-impl field core::Map<self::D::P*, self::D::Q*>* foo;
+  constructor •(dynamic tt) → self::D<self::D::P*, self::D::Q*>*
+    ;
+  method foo2(dynamic y) → dynamic
+    ;
+  method foo3<T1 extends core::Object* = dynamic, T2 extends core::Object* = dynamic>(dynamic z) → dynamic
+    ;
+  method foo4(dynamic w) → core::Map<self::D::P*, self::D::Q*>*
+    ;
+}
+class E<P extends core::String* = core::String*> extends core::Object {
+  static factory •<P extends core::String* = dynamic>() → self::E<self::E::•::P*>*
+    ;
+  method foo6<generic-covariant-impl T extends self::E::P* = self::E::P*, U extends core::List<self::E::foo6::T*>* = core::List<self::E::P*>*>(core::Map<self::E::foo6::T*, self::E::foo6::U*>* map) → void
+    ;
+}
+abstract class F<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::F<self::F::T*>*
+    ;
+  abstract method foo7<generic-covariant-impl Q extends self::F::T* = self::F::T*>(self::F::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::F::T* c) → void;
+  abstract method foo8<generic-covariant-impl Q extends self::F::T* = self::F::T*>(self::F::foo8::Q* a, covariant core::num* b, generic-covariant-impl self::F::T* c) → void;
+}
+class G<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::G<self::G::T*>*
+    ;
+  method foo7<generic-covariant-impl Q extends self::G::T* = self::G::T*>(self::G::foo7::Q* a, core::int* b, generic-covariant-impl self::G::T* c) → void
+    ;
+}
+class H<T extends core::Object* = dynamic> extends self::G<self::H::T*> implements self::F<self::H::T*> {
+  synthetic constructor •() → self::H<self::H::T*>*
+    ;
+  method foo8<generic-covariant-impl Q extends self::H::T* = self::H::T*>(self::H::foo8::Q* a, covariant core::int* b, generic-covariant-impl self::H::T* c) → void
+    ;
+  forwarding-stub method foo7<generic-covariant-impl Q extends self::H::T*>(self::H::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::H::T* c) → void
+    return super.{self::G::foo7}<self::H::foo7::Q*>(a, b, c);
+}
+static field core::List<core::Iterable<dynamic>*>* globalVar;
+static method foo1(dynamic x) → dynamic
+  ;
+static method foo5(dynamic x) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect
new file mode 100644
index 0000000..ced2c81
--- /dev/null
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.expect
@@ -0,0 +1,87 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T*>*
+    : super core::Object::•()
+    ;
+}
+class B extends self::A<core::String*> {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+}
+class C<T1 extends core::Object* = dynamic, T2 extends core::Object* = dynamic, T3 extends core::Object* = dynamic> extends self::B {
+  synthetic constructor •() → self::C<self::C::T1*, self::C::T2*, self::C::T3*>*
+    : super self::B::•()
+    ;
+}
+class D<P extends core::Object* = dynamic, Q extends core::Object* = dynamic> extends self::C<core::int*, self::D::Q*, self::D::P*> {
+  generic-covariant-impl field core::Map<self::D::P*, self::D::Q*>* foo;
+  constructor •(dynamic tt) → self::D<self::D::P*, self::D::Q*>*
+    : self::D::foo = tt as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*, super self::C::•()
+    ;
+  method foo2(dynamic y) → dynamic {
+    if(y is self::A<self::D::P*>*) {
+      core::print("21");
+    }
+    if(y is self::C<dynamic, self::D::Q*, core::List<self::D::P*>*>*) {
+      core::print("22");
+    }
+    this.{self::D::foo} = y as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*;
+  }
+  method foo3<T1 extends core::Object* = dynamic, T2 extends core::Object* = dynamic>(dynamic z) → dynamic {
+    if(z is self::A<self::D::foo3::T1*>*) {
+      core::print("31");
+    }
+    if(z is self::C<core::Map<self::D::foo3::T1*, self::D::P*>*, core::List<self::D::foo3::T2*>*, self::D::Q*>*) {
+      core::print("32");
+    }
+    return (z as core::Map<self::D::foo3::T2*, self::D::Q*>*).{core::Map::values};
+  }
+  method foo4(dynamic w) → core::Map<self::D::P*, self::D::Q*>* {
+    core::List<core::Map<self::D::P*, self::D::Q*>*>* list = <core::Map<self::D::P*, self::D::Q*>*>[w as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*];
+    return w as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*;
+  }
+}
+class E<P extends core::String* = core::String*> extends core::Object {
+  static factory •<P extends core::String* = dynamic>() → self::E<self::E::•::P*>*
+    return null;
+  method foo6<generic-covariant-impl T extends self::E::P* = self::E::P*, U extends core::List<self::E::foo6::T*>* = core::List<self::E::P*>*>(core::Map<self::E::foo6::T*, self::E::foo6::U*>* map) → void {}
+}
+abstract class F<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::F<self::F::T*>*
+    : super core::Object::•()
+    ;
+  abstract method foo7<generic-covariant-impl Q extends self::F::T* = self::F::T*>(self::F::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::F::T* c) → void;
+  abstract method foo8<generic-covariant-impl Q extends self::F::T* = self::F::T*>(self::F::foo8::Q* a, covariant core::num* b, generic-covariant-impl self::F::T* c) → void;
+}
+class G<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::G<self::G::T*>*
+    : super core::Object::•()
+    ;
+  method foo7<generic-covariant-impl Q extends self::G::T* = self::G::T*>(self::G::foo7::Q* a, core::int* b, generic-covariant-impl self::G::T* c) → void {}
+}
+class H<T extends core::Object* = dynamic> extends self::G<self::H::T*> implements self::F<self::H::T*> {
+  synthetic constructor •() → self::H<self::H::T*>*
+    : super self::G::•()
+    ;
+  method foo8<generic-covariant-impl Q extends self::H::T* = self::H::T*>(self::H::foo8::Q* a, covariant core::int* b, generic-covariant-impl self::H::T* c) → void {}
+  forwarding-stub method foo7<generic-covariant-impl Q extends self::H::T*>(self::H::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::H::T* c) → void
+    return super.{self::G::foo7}<self::H::foo7::Q*>(a, b, c);
+}
+static field core::List<core::Iterable<dynamic>*>* globalVar;
+static method foo1(dynamic x) → dynamic {
+  if(x is self::B*) {
+    core::print("11");
+  }
+  if(x is self::C<core::int*, core::Object*, dynamic>*) {
+    core::print("12");
+  }
+  return x as self::A<core::int*>*;
+}
+static method foo5(dynamic x) → void {
+  self::globalVar = x as{TypeError,ForDynamic} core::List<core::Iterable<dynamic>*>*;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
new file mode 100644
index 0000000..ced2c81
--- /dev/null
+++ b/pkg/front_end/testcases/general/vm_type_ops.dart.strong.transformed.expect
@@ -0,0 +1,87 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T*>*
+    : super core::Object::•()
+    ;
+}
+class B extends self::A<core::String*> {
+  synthetic constructor •() → self::B*
+    : super self::A::•()
+    ;
+}
+class C<T1 extends core::Object* = dynamic, T2 extends core::Object* = dynamic, T3 extends core::Object* = dynamic> extends self::B {
+  synthetic constructor •() → self::C<self::C::T1*, self::C::T2*, self::C::T3*>*
+    : super self::B::•()
+    ;
+}
+class D<P extends core::Object* = dynamic, Q extends core::Object* = dynamic> extends self::C<core::int*, self::D::Q*, self::D::P*> {
+  generic-covariant-impl field core::Map<self::D::P*, self::D::Q*>* foo;
+  constructor •(dynamic tt) → self::D<self::D::P*, self::D::Q*>*
+    : self::D::foo = tt as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*, super self::C::•()
+    ;
+  method foo2(dynamic y) → dynamic {
+    if(y is self::A<self::D::P*>*) {
+      core::print("21");
+    }
+    if(y is self::C<dynamic, self::D::Q*, core::List<self::D::P*>*>*) {
+      core::print("22");
+    }
+    this.{self::D::foo} = y as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*;
+  }
+  method foo3<T1 extends core::Object* = dynamic, T2 extends core::Object* = dynamic>(dynamic z) → dynamic {
+    if(z is self::A<self::D::foo3::T1*>*) {
+      core::print("31");
+    }
+    if(z is self::C<core::Map<self::D::foo3::T1*, self::D::P*>*, core::List<self::D::foo3::T2*>*, self::D::Q*>*) {
+      core::print("32");
+    }
+    return (z as core::Map<self::D::foo3::T2*, self::D::Q*>*).{core::Map::values};
+  }
+  method foo4(dynamic w) → core::Map<self::D::P*, self::D::Q*>* {
+    core::List<core::Map<self::D::P*, self::D::Q*>*>* list = <core::Map<self::D::P*, self::D::Q*>*>[w as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*];
+    return w as{TypeError,ForDynamic} core::Map<self::D::P*, self::D::Q*>*;
+  }
+}
+class E<P extends core::String* = core::String*> extends core::Object {
+  static factory •<P extends core::String* = dynamic>() → self::E<self::E::•::P*>*
+    return null;
+  method foo6<generic-covariant-impl T extends self::E::P* = self::E::P*, U extends core::List<self::E::foo6::T*>* = core::List<self::E::P*>*>(core::Map<self::E::foo6::T*, self::E::foo6::U*>* map) → void {}
+}
+abstract class F<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::F<self::F::T*>*
+    : super core::Object::•()
+    ;
+  abstract method foo7<generic-covariant-impl Q extends self::F::T* = self::F::T*>(self::F::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::F::T* c) → void;
+  abstract method foo8<generic-covariant-impl Q extends self::F::T* = self::F::T*>(self::F::foo8::Q* a, covariant core::num* b, generic-covariant-impl self::F::T* c) → void;
+}
+class G<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::G<self::G::T*>*
+    : super core::Object::•()
+    ;
+  method foo7<generic-covariant-impl Q extends self::G::T* = self::G::T*>(self::G::foo7::Q* a, core::int* b, generic-covariant-impl self::G::T* c) → void {}
+}
+class H<T extends core::Object* = dynamic> extends self::G<self::H::T*> implements self::F<self::H::T*> {
+  synthetic constructor •() → self::H<self::H::T*>*
+    : super self::G::•()
+    ;
+  method foo8<generic-covariant-impl Q extends self::H::T* = self::H::T*>(self::H::foo8::Q* a, covariant core::int* b, generic-covariant-impl self::H::T* c) → void {}
+  forwarding-stub method foo7<generic-covariant-impl Q extends self::H::T*>(self::H::foo7::Q* a, covariant core::num* b, generic-covariant-impl self::H::T* c) → void
+    return super.{self::G::foo7}<self::H::foo7::Q*>(a, b, c);
+}
+static field core::List<core::Iterable<dynamic>*>* globalVar;
+static method foo1(dynamic x) → dynamic {
+  if(x is self::B*) {
+    core::print("11");
+  }
+  if(x is self::C<core::int*, core::Object*, dynamic>*) {
+    core::print("12");
+  }
+  return x as self::A<core::int*>*;
+}
+static method foo5(dynamic x) → void {
+  self::globalVar = x as{TypeError,ForDynamic} core::List<core::Iterable<dynamic>*>*;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.outline.expect
index 193fcfd..1b0f87b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.outline.expect
@@ -147,17 +147,17 @@
   synthetic constructor •() → self::Ci<self::Ci::T*>*
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
 }
-class Dc<T extends core::Object* = dynamic> extends core::Object {
+class Dc<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Dc<self::Dc::T*>*
     : super core::Object::•()
     ;
 }
-class Di<T extends core::Object* = dynamic> extends core::Object {
+class Di<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Di<self::Di::T*>*
     : super core::Object::•()
     ;
@@ -174,7 +174,7 @@
   synthetic constructor •() → self::Ei<self::Ei::T*>*
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -183,7 +183,7 @@
   synthetic constructor •() → self::F<self::F::T*>*
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
   synthetic constructor •() → self::Fc<self::Fc::T*>*
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.expect
index f823e7b..bab8503 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.expect
@@ -155,17 +155,17 @@
     : super core::Object::•()
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
 }
-class Dc<T extends core::Object* = dynamic> extends core::Object {
+class Dc<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Dc<self::Dc::T*>*
     : super core::Object::•()
     ;
 }
-class Di<T extends core::Object* = dynamic> extends core::Object {
+class Di<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Di<self::Di::T*>*
     : super core::Object::•()
     ;
@@ -185,7 +185,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
index 7ca9c2a..a873098 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
@@ -155,17 +155,17 @@
     : super core::Object::•()
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
 }
-class Dc<T extends core::Object* = dynamic> extends core::Object {
+class Dc<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Dc<self::Dc::T*>*
     : super core::Object::•()
     ;
 }
-class Di<T extends core::Object* = dynamic> extends core::Object {
+class Di<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Di<self::Di::T*>*
     : super core::Object::•()
     ;
@@ -185,7 +185,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.expect
index f823e7b..bab8503 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.expect
@@ -155,17 +155,17 @@
     : super core::Object::•()
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
 }
-class Dc<T extends core::Object* = dynamic> extends core::Object {
+class Dc<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Dc<self::Dc::T*>*
     : super core::Object::•()
     ;
 }
-class Di<T extends core::Object* = dynamic> extends core::Object {
+class Di<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Di<self::Di::T*>*
     : super core::Object::•()
     ;
@@ -185,7 +185,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.transformed.expect
index 7ca9c2a..a873098 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bad_type_variable_uses_in_supertypes.dart.weak.transformed.expect
@@ -155,17 +155,17 @@
     : super core::Object::•()
     ;
 }
-class D<T extends core::Object* = dynamic> extends core::Object {
+class D<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::D<self::D::T*>*
     : super core::Object::•()
     ;
 }
-class Dc<T extends core::Object* = dynamic> extends core::Object {
+class Dc<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Dc<self::Dc::T*>*
     : super core::Object::•()
     ;
 }
-class Di<T extends core::Object* = dynamic> extends core::Object {
+class Di<T extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Di<self::Di::T*>*
     : super core::Object::•()
     ;
@@ -185,7 +185,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _F&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -195,7 +195,7 @@
     : super self::_F&Object&A::•()
     ;
 }
-abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fc&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T*>*
     : super core::Object::•()
     ;
@@ -205,7 +205,7 @@
     : super self::_Fc&Object&A::•()
     ;
 }
-abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _Fi&Object&A<T extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.outline.expect
index 8274b91..48337e0 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.outline.expect
@@ -17,7 +17,7 @@
   method foo() → void
     ;
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.expect
index 7bed644..fa1959d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.expect
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.transformed.expect
index 6cd473f..7c8800f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect
index 7bed644..fa1959d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.expect
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin*/  {
+abstract class _MyTest2&Object&MyTest = core::Object with self::MyTest /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
index 6cd473f..7c8800f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
@@ -17,7 +17,7 @@
   @#C1
   method foo() → void {}
 }
-abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _MyTest2&Object&MyTest extends core::Object implements self::MyTest /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_MyTest2&Object&MyTest*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.outline.expect
index 494ce66..678e133 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.outline.expect
@@ -6,7 +6,7 @@
   synthetic constructor •() → self::A<self::A::X*>*
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.expect
index 4de7d7e..5e3f196 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.transformed.expect
index ffac059..8fb87ff 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.strong.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.expect
index 4de7d7e..5e3f196 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin*/  {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> = core::Object with self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.transformed.expect
index ffac059..8fb87ff 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug34511.dart.weak.transformed.expect
@@ -7,7 +7,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&A<Z extends core::Object* = dynamic> extends core::Object implements self::A<() →* self::_B&Object&A::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/call.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/call.dart.strong.expect
index 9236ab4..675a501 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/call.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/call.dart.strong.expect
@@ -84,14 +84,30 @@
   dynamic string6 = let final self::CallableGetter* #t1 = callableGetter in let final core::int* #t2 = 1 in #t1.{self::CallableGetter::call}.call(#t2);
   dynamic string7 = callableGetter.{self::CallableGetter::call}.call(1);
   dynamic string8 = callableGetter.{self::CallableGetter::call}.call.call(1);
-  dynamic nothing1 = closure.call();
-  dynamic nothing2 = closure.call();
-  dynamic nothing3 = closure.call.call();
-  dynamic nothing4 = closure.call.call.call();
-  dynamic nothing5 = callable.{self::Callable::call}();
-  dynamic nothing6 = callable.{self::Callable::call}();
-  dynamic nothing7 = callable.{self::Callable::call}.call();
-  dynamic nothing8 = callable.{self::Callable::call}.call.call();
+  invalid-type nothing1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:36:25: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing1 = closure();
+                        ^" in closure.call();
+  invalid-type nothing2 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:37:30: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing2 = closure.call();
+                             ^" in closure.call();
+  invalid-type nothing3 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:38:35: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing3 = closure.call.call();
+                                  ^" in closure.call.call();
+  invalid-type nothing4 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:39:40: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing4 = closure.call.call.call();
+                                       ^" in closure.call.call.call();
+  invalid-type nothing5 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:41:26: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing5 = callable();
+                         ^" in callable.{self::Callable::call}();
+  invalid-type nothing6 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:42:31: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing6 = callable.call();
+                              ^" in callable.{self::Callable::call}();
+  invalid-type nothing7 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:43:36: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing7 = callable.call.call();
+                                   ^" in callable.{self::Callable::call}.call();
+  invalid-type nothing8 = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:44:41: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing8 = callable.call.call.call();
+                                        ^" in callable.{self::Callable::call}.call.call();
   dynamic nothing9 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:46:32: Error: Cannot invoke an instance of 'CallableGetter' because it declares 'call' to be something other than a method.
  - 'CallableGetter' is from 'pkg/front_end/testcases/general_nnbd_opt_out/call.dart'.
 Try changing 'call' to a method or explicitly invoke 'call'.
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/call.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/call.dart.weak.expect
index 9236ab4..675a501 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/call.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/call.dart.weak.expect
@@ -84,14 +84,30 @@
   dynamic string6 = let final self::CallableGetter* #t1 = callableGetter in let final core::int* #t2 = 1 in #t1.{self::CallableGetter::call}.call(#t2);
   dynamic string7 = callableGetter.{self::CallableGetter::call}.call(1);
   dynamic string8 = callableGetter.{self::CallableGetter::call}.call.call(1);
-  dynamic nothing1 = closure.call();
-  dynamic nothing2 = closure.call();
-  dynamic nothing3 = closure.call.call();
-  dynamic nothing4 = closure.call.call.call();
-  dynamic nothing5 = callable.{self::Callable::call}();
-  dynamic nothing6 = callable.{self::Callable::call}();
-  dynamic nothing7 = callable.{self::Callable::call}.call();
-  dynamic nothing8 = callable.{self::Callable::call}.call.call();
+  invalid-type nothing1 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:36:25: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing1 = closure();
+                        ^" in closure.call();
+  invalid-type nothing2 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:37:30: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing2 = closure.call();
+                             ^" in closure.call();
+  invalid-type nothing3 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:38:35: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing3 = closure.call.call();
+                                  ^" in closure.call.call();
+  invalid-type nothing4 = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:39:40: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing4 = closure.call.call.call();
+                                       ^" in closure.call.call.call();
+  invalid-type nothing5 = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:41:26: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing5 = callable();
+                         ^" in callable.{self::Callable::call}();
+  invalid-type nothing6 = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:42:31: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing6 = callable.call();
+                              ^" in callable.{self::Callable::call}();
+  invalid-type nothing7 = let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:43:36: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing7 = callable.call.call();
+                                   ^" in callable.{self::Callable::call}.call();
+  invalid-type nothing8 = let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:44:41: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing8 = callable.call.call.call();
+                                        ^" in callable.{self::Callable::call}.call.call();
   dynamic nothing9 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/call.dart:46:32: Error: Cannot invoke an instance of 'CallableGetter' because it declares 'call' to be something other than a method.
  - 'CallableGetter' is from 'pkg/front_end/testcases/general_nnbd_opt_out/call.dart'.
 Try changing 'call' to a method or explicitly invoke 'call'.
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart.strong.expect
index 80cd4aa..f2a599d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart.strong.expect
@@ -68,6 +68,8 @@
   invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart:22:20: Error: Too few positional arguments: 1 required, 0 given.
   Fisk.staticMethod();
                    ^";
-  (null as self::Fisk*).{self::Fisk::method}();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart:23:24: Error: Too few positional arguments: 1 required, 0 given.
+  (null as Fisk).method();
+                       ^" in (null as self::Fisk*).{self::Fisk::method}();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart.weak.expect
index 80cd4aa..f2a599d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart.weak.expect
@@ -68,6 +68,8 @@
   invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart:22:20: Error: Too few positional arguments: 1 required, 0 given.
   Fisk.staticMethod();
                    ^";
-  (null as self::Fisk*).{self::Fisk::method}();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/candidate_found.dart:23:24: Error: Too few positional arguments: 1 required, 0 given.
+  (null as Fisk).method();
+                       ^" in (null as self::Fisk*).{self::Fisk::method}();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.outline.expect
index e4929d5..f515adc 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.outline.expect
@@ -111,7 +111,7 @@
   synthetic constructor •() → self::Am1<self::Am1::X*, self::Am1::Y*>*
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -120,7 +120,7 @@
   synthetic constructor •() → self::Bm1<self::Bm1::Z*>*
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -129,7 +129,7 @@
   synthetic constructor •() → self::Cm1<self::Cm1::Z*>*
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -138,7 +138,7 @@
   synthetic constructor •() → self::Dm1<self::Dm1::Z*>*
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -147,7 +147,7 @@
   synthetic constructor •() → self::Em1<self::Em1::Z*>*
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -156,7 +156,7 @@
   synthetic constructor •() → self::Fm1<self::Fm1::Z*>*
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -165,7 +165,7 @@
   synthetic constructor •() → self::Gm1<self::Gm1::Z*>*
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -174,7 +174,7 @@
   synthetic constructor •() → self::Hm1<self::Hm1::Z*>*
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -183,7 +183,7 @@
   synthetic constructor •() → self::Im1<self::Im1::Z*>*
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
   synthetic constructor •() → self::Jm1<self::Jm1::Z*>*
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -201,7 +201,7 @@
   synthetic constructor •() → self::Km1<self::Km1::Z*>*
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -210,57 +210,57 @@
   synthetic constructor •() → self::Lm1<self::Lm1::Z*>*
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> {
+class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> {
+class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> {
+class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> {
+class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> {
+class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> {
+class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> {
+class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> {
+class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> {
+class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> {
+class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> {
+class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -269,7 +269,7 @@
   synthetic constructor •() → self::Am2<self::Am2::X*, self::Am2::Y*>*
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -278,7 +278,7 @@
   synthetic constructor •() → self::Bm2<self::Bm2::Z*>*
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -287,7 +287,7 @@
   synthetic constructor •() → self::Cm2<self::Cm2::Z*>*
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -296,7 +296,7 @@
   synthetic constructor •() → self::Dm2<self::Dm2::Z*>*
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -305,7 +305,7 @@
   synthetic constructor •() → self::Em2<self::Em2::Z*>*
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -314,7 +314,7 @@
   synthetic constructor •() → self::Fm2<self::Fm2::Z*>*
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -323,7 +323,7 @@
   synthetic constructor •() → self::Gm2<self::Gm2::Z*>*
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
   synthetic constructor •() → self::Hm2<self::Hm2::Z*>*
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -341,7 +341,7 @@
   synthetic constructor •() → self::Im2<self::Im2::Z*>*
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -350,7 +350,7 @@
   synthetic constructor •() → self::Jm2<self::Jm2::Z*>*
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -359,7 +359,7 @@
   synthetic constructor •() → self::Km2<self::Km2::Z*>*
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -368,57 +368,57 @@
   synthetic constructor •() → self::Lm2<self::Lm2::Z*>*
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> {
+class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> {
+class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> {
+class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> {
+class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> {
+class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> {
+class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> {
+class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> {
+class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> {
+class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> {
+class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> {
+class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -427,7 +427,7 @@
   synthetic constructor •() → self::Am3<self::Am3::L*, self::Am3::Y*>*
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -436,7 +436,7 @@
   synthetic constructor •() → self::Bm3<self::Bm3::Z*>*
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -445,7 +445,7 @@
   synthetic constructor •() → self::Cm3<self::Cm3::Z*>*
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -454,7 +454,7 @@
   synthetic constructor •() → self::Dm3<self::Dm3::Z*>*
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -463,7 +463,7 @@
   synthetic constructor •() → self::Em3<self::Em3::Z*>*
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
   synthetic constructor •() → self::Fm3<self::Fm3::Z*>*
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -481,7 +481,7 @@
   synthetic constructor •() → self::Gm3<self::Gm3::Z*>*
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -490,7 +490,7 @@
   synthetic constructor •() → self::Hm3<self::Hm3::Z*>*
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -499,7 +499,7 @@
   synthetic constructor •() → self::Im3<self::Im3::Z*>*
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -508,7 +508,7 @@
   synthetic constructor •() → self::Jm3<self::Jm3::Z*>*
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.expect
index 1d8753e..0fec093 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -222,57 +222,57 @@
     : super self::_Lm1&Object&Am1::•()
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> {
+class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> {
+class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> {
+class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> {
+class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> {
+class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> {
+class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> {
+class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> {
+class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> {
+class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> {
+class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> {
+class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -392,57 +392,57 @@
     : super self::_Lm2&Object&Am2::•()
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> {
+class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> {
+class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> {
+class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> {
+class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> {
+class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> {
+class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> {
+class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> {
+class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> {
+class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> {
+class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> {
+class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.transformed.expect
index cae8d00..ab334c7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.strong.transformed.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -222,57 +222,57 @@
     : super self::_Lm1&Object&Am1::•()
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*isEliminatedMixin*/  {
+class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*isEliminatedMixin*/  {
+class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> /*isEliminatedMixin*/  {
+class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> /*isEliminatedMixin*/  {
+class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> /*isEliminatedMixin*/  {
+class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*isEliminatedMixin*/  {
+class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*isEliminatedMixin*/  {
+class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*isEliminatedMixin*/  {
+class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> /*isEliminatedMixin*/  {
+class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*isEliminatedMixin*/  {
+class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*isEliminatedMixin*/  {
+class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -392,57 +392,57 @@
     : super self::_Lm2&Object&Am2::•()
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*isEliminatedMixin*/  {
+class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*isEliminatedMixin*/  {
+class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> /*isEliminatedMixin*/  {
+class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> /*isEliminatedMixin*/  {
+class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> /*isEliminatedMixin*/  {
+class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*isEliminatedMixin*/  {
+class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*isEliminatedMixin*/  {
+class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*isEliminatedMixin*/  {
+class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> /*isEliminatedMixin*/  {
+class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*isEliminatedMixin*/  {
+class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*isEliminatedMixin*/  {
+class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
index 1d8753e..0fec093 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -222,57 +222,57 @@
     : super self::_Lm1&Object&Am1::•()
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> {
+class Mm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> {
+class Nm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> {
+class Om1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* core::int*, self::Om1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> {
+class Pm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Pm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> {
+class Qm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* dynamic, self::Qm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> {
+class Rm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> {
+class Sm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> {
+class Tm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> {
+class Um1<Z extends core::Object* = dynamic> = core::Object with self::Am1<core::Function*, self::Um1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> {
+class Vm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> {
+class Wm1<Z extends core::Object* = dynamic> = core::Object with self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin*/  {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -392,57 +392,57 @@
     : super self::_Lm2&Object&Am2::•()
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> {
+class Mm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> {
+class Nm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> {
+class Om2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* core::int*, self::Om2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> {
+class Pm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Pm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> {
+class Qm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* dynamic, self::Qm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> {
+class Rm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> {
+class Sm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> {
+class Tm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> {
+class Um2<Z extends core::Object* = dynamic> = core::Object with self::Am2<core::Function*, self::Um2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> {
+class Vm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> {
+class Wm2<Z extends core::Object* = dynamic> = core::Object with self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin*/  {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> = core::Object with self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
index cae8d00..ab334c7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
@@ -112,7 +112,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Bm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Bm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm1&Object&Am1<self::_Bm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -122,7 +122,7 @@
     : super self::_Bm1&Object&Am1::•()
     ;
 }
-abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Cm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::_Cm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm1&Object&Am1<self::_Cm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -132,7 +132,7 @@
     : super self::_Cm1&Object&Am1::•()
     ;
 }
-abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Dm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::_Dm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm1&Object&Am1<self::_Dm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -142,7 +142,7 @@
     : super self::_Dm1&Object&Am1::•()
     ;
 }
-abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Em1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Em1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em1&Object&Am1<self::_Em1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -152,7 +152,7 @@
     : super self::_Em1&Object&Am1::•()
     ;
 }
-abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Fm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::_Fm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm1&Object&Am1<self::_Fm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -162,7 +162,7 @@
     : super self::_Fm1&Object&Am1::•()
     ;
 }
-abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Gm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::_Gm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm1&Object&Am1<self::_Gm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -172,7 +172,7 @@
     : super self::_Gm1&Object&Am1::•()
     ;
 }
-abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Hm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm1&Object&Am1<self::_Hm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -182,7 +182,7 @@
     : super self::_Hm1&Object&Am1::•()
     ;
 }
-abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Im1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::_Im1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im1&Object&Am1<self::_Im1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -192,7 +192,7 @@
     : super self::_Im1&Object&Am1::•()
     ;
 }
-abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Jm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::_Jm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm1&Object&Am1<self::_Jm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
     : super self::_Jm1&Object&Am1::•()
     ;
 }
-abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Km1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::_Km1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km1&Object&Am1<self::_Km1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -212,7 +212,7 @@
     : super self::_Km1&Object&Am1::•()
     ;
 }
-abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Lm1&Object&Am1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::_Lm1&Object&Am1::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm1&Object&Am1<self::_Lm1&Object&Am1::Z*>*
     : super core::Object::•()
     ;
@@ -222,57 +222,57 @@
     : super self::_Lm1&Object&Am1::•()
     ;
 }
-class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*isEliminatedMixin*/  {
+class Mm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Mm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm1<self::Mm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*isEliminatedMixin*/  {
+class Nm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::int*) →* dynamic, self::Nm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm1<self::Nm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> /*isEliminatedMixin*/  {
+class Om1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* core::int*, self::Om1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Om1<self::Om1::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> /*isEliminatedMixin*/  {
+class Pm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Pm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm1<self::Pm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> /*isEliminatedMixin*/  {
+class Qm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* dynamic, self::Qm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm1<self::Qm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*isEliminatedMixin*/  {
+class Rm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<({x: core::int*}) →* dynamic, self::Rm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm1<self::Rm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*isEliminatedMixin*/  {
+class Sm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Sm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm1<self::Sm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*isEliminatedMixin*/  {
+class Tm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<([core::int*]) →* dynamic, self::Tm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm1<self::Tm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> /*isEliminatedMixin*/  {
+class Um1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<core::Function*, self::Um1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Um1<self::Um1::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*isEliminatedMixin*/  {
+class Vm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<(core::Function*) →* dynamic, self::Vm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm1<self::Vm1::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*isEliminatedMixin*/  {
+class Wm1<Z extends core::Object* = dynamic> extends core::Object implements self::Am1<() →* (() →* core::Function*) →* dynamic, self::Wm1::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm1<self::Wm1::Z*>*
     : super core::Object::•()
     ;
@@ -282,7 +282,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Bm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Bm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm2&Object&Am2<self::_Bm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -292,7 +292,7 @@
     : super self::_Bm2&Object&Am2::•()
     ;
 }
-abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Cm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::_Cm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm2&Object&Am2<self::_Cm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -302,7 +302,7 @@
     : super self::_Cm2&Object&Am2::•()
     ;
 }
-abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Dm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::_Dm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm2&Object&Am2<self::_Dm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -312,7 +312,7 @@
     : super self::_Dm2&Object&Am2::•()
     ;
 }
-abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Em2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Em2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em2&Object&Am2<self::_Em2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -322,7 +322,7 @@
     : super self::_Em2&Object&Am2::•()
     ;
 }
-abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Fm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::_Fm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm2&Object&Am2<self::_Fm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -332,7 +332,7 @@
     : super self::_Fm2&Object&Am2::•()
     ;
 }
-abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Gm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::_Gm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm2&Object&Am2<self::_Gm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -342,7 +342,7 @@
     : super self::_Gm2&Object&Am2::•()
     ;
 }
-abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Hm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm2&Object&Am2<self::_Hm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -352,7 +352,7 @@
     : super self::_Hm2&Object&Am2::•()
     ;
 }
-abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Im2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::_Im2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im2&Object&Am2<self::_Im2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -362,7 +362,7 @@
     : super self::_Im2&Object&Am2::•()
     ;
 }
-abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Jm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::_Jm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm2&Object&Am2<self::_Jm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -372,7 +372,7 @@
     : super self::_Jm2&Object&Am2::•()
     ;
 }
-abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Km2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::_Km2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km2&Object&Am2<self::_Km2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -382,7 +382,7 @@
     : super self::_Km2&Object&Am2::•()
     ;
 }
-abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Lm2&Object&Am2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::_Lm2&Object&Am2::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Lm2&Object&Am2<self::_Lm2&Object&Am2::Z*>*
     : super core::Object::•()
     ;
@@ -392,57 +392,57 @@
     : super self::_Lm2&Object&Am2::•()
     ;
 }
-class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*isEliminatedMixin*/  {
+class Mm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Mm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Mm2<self::Mm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*isEliminatedMixin*/  {
+class Nm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::int*) →* dynamic, self::Nm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Nm2<self::Nm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> /*isEliminatedMixin*/  {
+class Om2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* core::int*, self::Om2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Om2<self::Om2::Z*>*
     : super core::Object::•()
     ;
 }
-class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> /*isEliminatedMixin*/  {
+class Pm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Pm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Pm2<self::Pm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> /*isEliminatedMixin*/  {
+class Qm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* dynamic, self::Qm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Qm2<self::Qm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*isEliminatedMixin*/  {
+class Rm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<({x: core::int*}) →* dynamic, self::Rm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Rm2<self::Rm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*isEliminatedMixin*/  {
+class Sm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Sm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Sm2<self::Sm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*isEliminatedMixin*/  {
+class Tm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<([core::int*]) →* dynamic, self::Tm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Tm2<self::Tm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> /*isEliminatedMixin*/  {
+class Um2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<core::Function*, self::Um2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Um2<self::Um2::Z*>*
     : super core::Object::•()
     ;
 }
-class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*isEliminatedMixin*/  {
+class Vm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<(core::Function*) →* dynamic, self::Vm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Vm2<self::Vm2::Z*>*
     : super core::Object::•()
     ;
 }
-class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*isEliminatedMixin*/  {
+class Wm2<Z extends core::Object* = dynamic> extends core::Object implements self::Am2<() →* (() →* core::Function*) →* dynamic, self::Wm2::Z*> /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Wm2<self::Wm2::Z*>*
     : super core::Object::•()
     ;
@@ -452,7 +452,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Bm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Bm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Bm3&Object&Am3<self::_Bm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -462,7 +462,7 @@
     : super self::_Bm3&Object&Am3::•()
     ;
 }
-abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Cm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::int*) →* dynamic, self::_Cm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Cm3&Object&Am3<self::_Cm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -472,7 +472,7 @@
     : super self::_Cm3&Object&Am3::•()
     ;
 }
-abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Dm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* core::int*, self::_Dm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Dm3&Object&Am3<self::_Dm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -482,7 +482,7 @@
     : super self::_Dm3&Object&Am3::•()
     ;
 }
-abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Em3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Em3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Em3&Object&Am3<self::_Em3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -492,7 +492,7 @@
     : super self::_Em3&Object&Am3::•()
     ;
 }
-abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Fm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* dynamic, self::_Fm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Fm3&Object&Am3<self::_Fm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -502,7 +502,7 @@
     : super self::_Fm3&Object&Am3::•()
     ;
 }
-abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Gm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<({x: core::int*}) →* dynamic, self::_Gm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Gm3&Object&Am3<self::_Gm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -512,7 +512,7 @@
     : super self::_Gm3&Object&Am3::•()
     ;
 }
-abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Hm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hm3&Object&Am3<self::_Hm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -522,7 +522,7 @@
     : super self::_Hm3&Object&Am3::•()
     ;
 }
-abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Im3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<([core::int*]) →* dynamic, self::_Im3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Im3&Object&Am3<self::_Im3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -532,7 +532,7 @@
     : super self::_Im3&Object&Am3::•()
     ;
 }
-abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Jm3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<(core::Function*) →* dynamic, self::_Jm3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Jm3&Object&Am3<self::_Jm3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
@@ -542,7 +542,7 @@
     : super self::_Jm3&Object&Am3::•()
     ;
 }
-abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Km3&Object&Am3<Z extends core::Object* = dynamic> extends core::Object implements self::Am3<() →* (() →* core::Function*) →* dynamic, self::_Km3&Object&Am3::Z*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Km3&Object&Am3<self::_Km3&Object&Am3::Z*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.outline.expect
index 23b1937..bb1a2fb 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.outline.expect
@@ -13,7 +13,7 @@
   synthetic constructor •() → self::A<self::A::Q*>*
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.expect
index 7473a34..8098e01 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.transformed.expect
index 7473a34..8098e01 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.expect
index 7473a34..8098e01 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.transformed.expect
index 7473a34..8098e01 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/issue38944.dart.weak.transformed.expect
@@ -14,7 +14,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin*/  {
+abstract class _B&Object&A<X extends core::Object* = dynamic> extends core::Object /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A<self::_B&Object&A::X*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.outline.expect
index 9a57e29..d4a20e6 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.outline.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -28,12 +28,12 @@
   method m() → dynamic
     ;
 }
-abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -48,7 +48,7 @@
   method m() → dynamic
     ;
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.expect
index 2cca9cf..5e30f41 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -31,12 +31,12 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -53,7 +53,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.transformed.expect
index b51ef02..903d96c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.strong.transformed.expect
@@ -2,14 +2,14 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -35,14 +35,14 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -61,7 +61,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect
index 2cca9cf..5e30f41 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.expect
@@ -2,12 +2,12 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _B&Object&M1&M2 = self::_B&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -31,12 +31,12 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1 = core::Object with self::M1 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin*/  {
+abstract class _C&Object&M1&M2 = self::_C&Object&M1 with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -53,7 +53,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin*/  {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> = core::Object with self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect
index b51ef02..903d96c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin.dart.weak.transformed.expect
@@ -2,14 +2,14 @@
 import self as self;
 import "dart:core" as core;
 
-abstract class _B&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&M1&M2 extends self::_B&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M1&M2*
     : super self::_B&Object&M1::•()
     ;
@@ -35,14 +35,14 @@
   method m() → dynamic
     return core::print("M2");
 }
-abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&M1 extends core::Object implements self::M1 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1*
     : super core::Object::•()
     ;
   method m() → dynamic
     return core::print("M1");
 }
-abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&M1&M2 extends self::_C&Object&M1 implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&M1&M2*
     : super self::_C&Object&M1::•()
     ;
@@ -61,7 +61,7 @@
   method m() → dynamic
     return core::print(self::G1::T*);
 }
-abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _D&Object&G1<S extends core::Object* = dynamic> extends core::Object implements self::G1<self::_D&Object&G1::S*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_D&Object&G1<self::_D&Object&G1::S*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.outline.expect
index 67867e3..2295e57 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.outline.expect
@@ -39,12 +39,12 @@
   method foo() → dynamic
     ;
 }
-class N = core::Object with self::M {
+class N = core::Object with self::M /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -59,17 +59,17 @@
   method bar() → dynamic
     ;
 }
-class N2 = core::Object with self::M2 {
+class N2 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
 }
-abstract class N3 = core::Object with self::M2 {
+abstract class N3 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -78,7 +78,7 @@
   synthetic constructor •() → self::C2*
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.expect
index 7f6f63d..85c5aad 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.expect
@@ -39,12 +39,12 @@
     ;
   method foo() → dynamic {}
 }
-class N = core::Object with self::M {
+class N = core::Object with self::M /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -60,17 +60,17 @@
     ;
   method bar() → dynamic {}
 }
-class N2 = core::Object with self::M2 {
+class N2 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
 }
-abstract class N3 = core::Object with self::M2 {
+abstract class N3 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -80,7 +80,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.transformed.expect
index 964368f..1162018 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.strong.transformed.expect
@@ -39,13 +39,13 @@
     ;
   method foo() → dynamic {}
 }
-class N extends core::Object implements self::M /*isEliminatedMixin*/  {
+class N extends core::Object implements self::M /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
   method foo() → dynamic {}
 }
-abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -62,19 +62,19 @@
     ;
   method bar() → dynamic {}
 }
-class N2 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
+class N2 extends core::Object implements self::M2 /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
+abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -85,7 +85,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C3&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect
index 7f6f63d..85c5aad 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.expect
@@ -39,12 +39,12 @@
     ;
   method foo() → dynamic {}
 }
-class N = core::Object with self::M {
+class N = core::Object with self::M /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin*/  {
+abstract class _C&Object&N = core::Object with self::N /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -60,17 +60,17 @@
     ;
   method bar() → dynamic {}
 }
-class N2 = core::Object with self::M2 {
+class N2 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
 }
-abstract class N3 = core::Object with self::M2 {
+abstract class N3 = core::Object with self::M2 /*hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
 }
-abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C2&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -80,7 +80,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin*/  {
+abstract class _C3&Object&M2 = core::Object with self::M2 /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect
index 964368f..1162018 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_conflicts.dart.weak.transformed.expect
@@ -39,13 +39,13 @@
     ;
   method foo() → dynamic {}
 }
-class N extends core::Object implements self::M /*isEliminatedMixin*/  {
+class N extends core::Object implements self::M /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N*
     : super core::Object::•()
     ;
   method foo() → dynamic {}
 }
-abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&N extends core::Object implements self::N /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&N*
     : super core::Object::•()
     ;
@@ -62,19 +62,19 @@
     ;
   method bar() → dynamic {}
 }
-class N2 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
+class N2 extends core::Object implements self::M2 /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N2*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin*/  {
+abstract class N3 extends core::Object implements self::M2 /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::N3*
     : super core::Object::•()
     ;
   method bar() → dynamic {}
 }
-abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C2&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C2&Object&M2*
     : super core::Object::•()
     ;
@@ -85,7 +85,7 @@
     : super self::_C2&Object&M2::•()
     ;
 }
-abstract class _C3&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C3&Object&M2 extends core::Object implements self::M2 /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C3&Object&M2*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/optional.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/optional.dart.strong.expect
index 357231c..d5b76c7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/optional.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/optional.dart.strong.expect
@@ -85,10 +85,20 @@
  - 'Listener' is from 'pkg/front_end/testcases/general_nnbd_opt_out/optional.dart'.
   extern.listen(new InvalidListener());
                     ^" in new self::InvalidListener::•() as{TypeError} self::Listener*);
-  dynamic nothing1 = foo.{self::Foo::method}();
-  dynamic nothing2 = foo.{self::Foo::method}(1, 2, 3, 4);
-  core::String* nothing3 = extern.{self::External::externalMethod}();
-  core::String* nothing4 = extern.{self::External::externalMethod}(1, 2, 3, 4);
+  invalid-type nothing1 = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/optional.dart:51:28: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing1 = foo.method();
+                           ^" in foo.{self::Foo::method}();
+  invalid-type nothing2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/optional.dart:52:28: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  var nothing2 = foo.method(1, 2, 3, 4);
+                           ^" in foo.{self::Foo::method}(1, 2, 3, 4);
+  invalid-type nothing3 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/optional.dart:53:39: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing3 = extern.externalMethod();
+                                      ^" in extern.{self::External::externalMethod}();
+  invalid-type nothing4 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/optional.dart:54:39: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  var nothing4 = extern.externalMethod(1, 2, 3, 4);
+                                      ^" in extern.{self::External::externalMethod}(1, 2, 3, 4);
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/optional.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/optional.dart.weak.expect
index 357231c..d5b76c7 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/optional.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/optional.dart.weak.expect
@@ -85,10 +85,20 @@
  - 'Listener' is from 'pkg/front_end/testcases/general_nnbd_opt_out/optional.dart'.
   extern.listen(new InvalidListener());
                     ^" in new self::InvalidListener::•() as{TypeError} self::Listener*);
-  dynamic nothing1 = foo.{self::Foo::method}();
-  dynamic nothing2 = foo.{self::Foo::method}(1, 2, 3, 4);
-  core::String* nothing3 = extern.{self::External::externalMethod}();
-  core::String* nothing4 = extern.{self::External::externalMethod}(1, 2, 3, 4);
+  invalid-type nothing1 = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/optional.dart:51:28: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing1 = foo.method();
+                           ^" in foo.{self::Foo::method}();
+  invalid-type nothing2 = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/optional.dart:52:28: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  var nothing2 = foo.method(1, 2, 3, 4);
+                           ^" in foo.{self::Foo::method}(1, 2, 3, 4);
+  invalid-type nothing3 = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/optional.dart:53:39: Error: Too few positional arguments: 1 required, 0 given.
+  var nothing3 = extern.externalMethod();
+                                      ^" in extern.{self::External::externalMethod}();
+  invalid-type nothing4 = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/optional.dart:54:39: Error: Too many positional arguments: 3 allowed, but 4 found.
+Try removing the extra positional arguments.
+  var nothing4 = extern.externalMethod(1, 2, 3, 4);
+                                      ^" in extern.{self::External::externalMethod}(1, 2, 3, 4);
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.outline.expect
index e336cd1..f59135a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.outline.expect
@@ -2,26 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:29:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
-//  - 'Object' is from 'dart:core'.
-//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
-// Change to a subtype of 'A'.
-//   Object f4() {}
-//          ^
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:15:5: Context: This is the overridden method ('f4').
-//   A f4() {}
-//     ^
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:28:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
-//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
-//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f3({B x}) {}
-//              ^
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:14:8: Context: This is the overridden method ('f3').
-//   void f3({A x}) {}
-//        ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:26:13: Error: The parameter 'x' of the method 'E.f1' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f1'.
 //  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
@@ -42,6 +22,26 @@
 //   void f2([A x]) {}
 //        ^
 //
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:28:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f3({B x}) {}
+//              ^
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:14:8: Context: This is the overridden method ('f3').
+//   void f3({A x}) {}
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:29:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
+//  - 'Object' is from 'dart:core'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
+// Change to a subtype of 'A'.
+//   Object f4() {}
+//          ^
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:15:5: Context: This is the overridden method ('f4').
+//   A f4() {}
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.strong.expect
index 5517232..68684e3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.strong.expect
@@ -2,26 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:29:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
-//  - 'Object' is from 'dart:core'.
-//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
-// Change to a subtype of 'A'.
-//   Object f4() {}
-//          ^
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:15:5: Context: This is the overridden method ('f4').
-//   A f4() {}
-//     ^
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:28:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
-//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
-//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f3({B x}) {}
-//              ^
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:14:8: Context: This is the overridden method ('f3').
-//   void f3({A x}) {}
-//        ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:26:13: Error: The parameter 'x' of the method 'E.f1' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f1'.
 //  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
@@ -42,6 +22,26 @@
 //   void f2([A x]) {}
 //        ^
 //
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:28:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f3({B x}) {}
+//              ^
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:14:8: Context: This is the overridden method ('f3').
+//   void f3({A x}) {}
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:29:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
+//  - 'Object' is from 'dart:core'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
+// Change to a subtype of 'A'.
+//   Object f4() {}
+//          ^
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:15:5: Context: This is the overridden method ('f4').
+//   A f4() {}
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.weak.expect
index 5517232..68684e3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart.weak.expect
@@ -2,26 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:29:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
-//  - 'Object' is from 'dart:core'.
-//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
-// Change to a subtype of 'A'.
-//   Object f4() {}
-//          ^
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:15:5: Context: This is the overridden method ('f4').
-//   A f4() {}
-//     ^
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:28:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
-//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
-//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f3({B x}) {}
-//              ^
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:14:8: Context: This is the overridden method ('f3').
-//   void f3({A x}) {}
-//        ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:26:13: Error: The parameter 'x' of the method 'E.f1' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f1'.
 //  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
@@ -42,6 +22,26 @@
 //   void f2([A x]) {}
 //        ^
 //
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:28:14: Error: The parameter 'x' of the method 'E.f3' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f3'.
+//  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f3({B x}) {}
+//              ^
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:14:8: Context: This is the overridden method ('f3').
+//   void f3({A x}) {}
+//        ^
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:29:10: Error: The return type of the method 'E.f4' is 'Object', which does not match the return type, 'A', of the overridden method, 'C.f4'.
+//  - 'Object' is from 'dart:core'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart'.
+// Change to a subtype of 'A'.
+//   Object f4() {}
+//          ^
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_basic.dart:15:5: Context: This is the overridden method ('f4').
+//   A f4() {}
+//     ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.outline.expect
index 3f5495c..34dec1e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.outline.expect
@@ -2,15 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:25:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
-//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f5(covariant String x) {}
-//                            ^
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:16:8: Context: This is the overridden method ('f5').
-//   void f5(covariant A x) {}
-//        ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:24:13: Error: The parameter 'x' of the method 'D.f4' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f4'.
 //  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
@@ -21,6 +12,15 @@
 //   void f4(A x) {}
 //        ^
 //
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:25:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f5(covariant String x) {}
+//                            ^
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:16:8: Context: This is the overridden method ('f5').
+//   void f5(covariant A x) {}
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.strong.expect b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.strong.expect
index 5811e2b..695cb19 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.strong.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.strong.expect
@@ -2,15 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:25:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
-//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f5(covariant String x) {}
-//                            ^
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:16:8: Context: This is the overridden method ('f5').
-//   void f5(covariant A x) {}
-//        ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:24:13: Error: The parameter 'x' of the method 'D.f4' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f4'.
 //  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
@@ -21,6 +12,15 @@
 //   void f4(A x) {}
 //        ^
 //
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:25:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f5(covariant String x) {}
+//                            ^
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:16:8: Context: This is the overridden method ('f5').
+//   void f5(covariant A x) {}
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.weak.expect
index 5811e2b..695cb19 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart.weak.expect
@@ -2,15 +2,6 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:25:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
-//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
-// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
-//   void f5(covariant String x) {}
-//                            ^
-// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:16:8: Context: This is the overridden method ('f5').
-//   void f5(covariant A x) {}
-//        ^
-//
 // pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:24:13: Error: The parameter 'x' of the method 'D.f4' has type 'B', which does not match the corresponding type, 'A', in the overridden method, 'C.f4'.
 //  - 'B' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
 //  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
@@ -21,6 +12,15 @@
 //   void f4(A x) {}
 //        ^
 //
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:25:28: Error: The parameter 'x' of the method 'D.f5' has type 'String', which does not match the corresponding type, 'A', in the overridden method, 'C.f5'.
+//  - 'A' is from 'pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart'.
+// Change to a supertype of 'A', or, for a covariant parameter, a subtype.
+//   void f5(covariant String x) {}
+//                            ^
+// pkg/front_end/testcases/general_nnbd_opt_out/override_check_with_covariant_modifier.dart:16:8: Context: This is the overridden method ('f5').
+//   void f5(covariant A x) {}
+//        ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/test.options b/pkg/front_end/testcases/general_nnbd_opt_out/test.options
index 19bb8ec..b552a65 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/test.options
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/test.options
@@ -1,2 +1 @@
---enable-experiment=non-nullable
---force-nnbd-checks
\ No newline at end of file
+--enable-experiment=non-nullable
\ No newline at end of file
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
index 1c53914..a00b651 100644
--- 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
@@ -23,7 +23,7 @@
   }
   abstract class M<T extends dart.core::Object* = dynamic> extends main::A<main::M::T*> /*isMixinDeclaration*/  {
   }
-  abstract class _C&Object&M extends dart.core::Object implements main::M<dynamic> /*isAnonymousMixin,isEliminatedMixin*/  {
+  abstract class _C&Object&M extends dart.core::Object implements main::M<dynamic> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
     const synthetic constructor •() → main::_C&Object&M*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect
index b9ec6ce..a20d4ff 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.1.expect
@@ -3,7 +3,7 @@
 
   import "dart:collection";
 
-  abstract class _WithListMixin&Object&ListMixin extends dart.core::Object implements dart.collection::ListMixin<dart.core::int*> /*isAnonymousMixin,isEliminatedMixin*/  {
+  abstract class _WithListMixin&Object&ListMixin extends dart.core::Object implements dart.collection::ListMixin<dart.core::int*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
     const synthetic constructor •() → main::_WithListMixin&Object&ListMixin*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect
index b9ec6ce..a20d4ff 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_22.yaml.world.2.expect
@@ -3,7 +3,7 @@
 
   import "dart:collection";
 
-  abstract class _WithListMixin&Object&ListMixin extends dart.core::Object implements dart.collection::ListMixin<dart.core::int*> /*isAnonymousMixin,isEliminatedMixin*/  {
+  abstract class _WithListMixin&Object&ListMixin extends dart.core::Object implements dart.collection::ListMixin<dart.core::int*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
     const synthetic constructor •() → main::_WithListMixin&Object&ListMixin*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect
index f4a1ddd..414582b 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.1.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///main.dart" as main {
 
-  abstract class _A&Object&B extends dart.core::Object implements main::B /*isAnonymousMixin,isEliminatedMixin*/  {
+  abstract class _A&Object&B extends dart.core::Object implements main::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
     const synthetic constructor •() → main::_A&Object&B*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect
index f4a1ddd..414582b 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_23.yaml.world.2.expect
@@ -1,7 +1,7 @@
 main = <No Member>;
 library from "org-dartlang-test:///main.dart" as main {
 
-  abstract class _A&Object&B extends dart.core::Object implements main::B /*isAnonymousMixin,isEliminatedMixin*/  {
+  abstract class _A&Object&B extends dart.core::Object implements main::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
     const synthetic constructor •() → main::_A&Object&B*
       : super dart.core::Object::•()
       ;
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
index 174ad04..c3e9c3f 100644
--- 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
@@ -3,7 +3,7 @@
 
   import "org-dartlang-test:///main.dart";
 
-  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo /*isAnonymousMixin,isEliminatedMixin*/  {
+  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
     const synthetic constructor •() → libA::_Bar&Object&Foo*
       : super dart.core::Object::•()
       ;
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
index 089f7dc..7ce591c 100644
--- 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
@@ -3,7 +3,7 @@
 
   import "org-dartlang-test:///main.dart";
 
-  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo /*isAnonymousMixin,isEliminatedMixin*/  {
+  abstract class _Bar&Object&Foo extends dart.core::Object implements main::Foo /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
     const synthetic constructor •() → libA::_Bar&Object&Foo*
       : super dart.core::Object::•()
       ;
diff --git a/pkg/front_end/testcases/inference/call_corner_cases.dart b/pkg/front_end/testcases/inference/call_corner_cases.dart
index 6713a4a..998d8a7 100644
--- a/pkg/front_end/testcases/inference/call_corner_cases.dart
+++ b/pkg/front_end/testcases/inference/call_corner_cases.dart
@@ -26,8 +26,10 @@
       new D(). /*@target=D::fieldA*/ /*@target=A::call*/ fieldA();
   var /*@ type=int* */ callGetA =
       new D(). /*@target=D::getA*/ /*@target=A::call*/ getA();
-  var /*@ type=dynamic */ callFieldB = new D(). /*@target=D::fieldB*/ fieldB();
-  var /*@ type=dynamic */ callGetB = new D(). /*@target=D::getB*/ getB();
+  var /*@type=int**/ callFieldB = new D()
+      . /*@target=D::fieldB*/ /*@target=B::call*/ /*@target=A::call*/ fieldB();
+  var /*@type=int**/ callGetB = new D()
+      . /*@target=D::getB*/ /*@target=B::call*/ /*@target=A::call*/ getB();
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.expect b/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.expect
index 02e8131..bf2de7e 100644
--- a/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.expect
@@ -1,15 +1,4 @@
 library test;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/inference/call_corner_cases.dart:29:71: Error: 'fieldB' isn't a function or method and can't be invoked.
-//   var /*@ type=dynamic */ callFieldB = new D(). /*@target=D::fieldB*/ fieldB();
-//                                                                       ^
-//
-// pkg/front_end/testcases/inference/call_corner_cases.dart:30:67: Error: 'getB' isn't a function or method and can't be invoked.
-//   var /*@ type=dynamic */ callGetB = new D(). /*@target=D::getB*/ getB();
-//                                                                   ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -42,11 +31,7 @@
   core::int* callA = new self::A::•().{self::A::call}();
   core::int* callFieldA = new self::D::•().{self::D::fieldA}.{self::A::call}();
   core::int* callGetA = new self::D::•().{self::D::getA}.{self::A::call}();
-  dynamic callFieldB = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:29:71: Error: 'fieldB' isn't a function or method and can't be invoked.
-  var /*@ type=dynamic */ callFieldB = new D(). /*@target=D::fieldB*/ fieldB();
-                                                                      ^";
-  dynamic callGetB = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:30:67: Error: 'getB' isn't a function or method and can't be invoked.
-  var /*@ type=dynamic */ callGetB = new D(). /*@target=D::getB*/ getB();
-                                                                  ^";
+  core::int* callFieldB = new self::D::•().{self::D::fieldB}.{self::B::call}.{self::A::call}();
+  core::int* callGetB = new self::D::•().{self::D::getB}.{self::B::call}.{self::A::call}();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.transformed.expect
index 02e8131..bf2de7e 100644
--- a/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/call_corner_cases.dart.strong.transformed.expect
@@ -1,15 +1,4 @@
 library test;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/inference/call_corner_cases.dart:29:71: Error: 'fieldB' isn't a function or method and can't be invoked.
-//   var /*@ type=dynamic */ callFieldB = new D(). /*@target=D::fieldB*/ fieldB();
-//                                                                       ^
-//
-// pkg/front_end/testcases/inference/call_corner_cases.dart:30:67: Error: 'getB' isn't a function or method and can't be invoked.
-//   var /*@ type=dynamic */ callGetB = new D(). /*@target=D::getB*/ getB();
-//                                                                   ^
-//
 import self as self;
 import "dart:core" as core;
 
@@ -42,11 +31,7 @@
   core::int* callA = new self::A::•().{self::A::call}();
   core::int* callFieldA = new self::D::•().{self::D::fieldA}.{self::A::call}();
   core::int* callGetA = new self::D::•().{self::D::getA}.{self::A::call}();
-  dynamic callFieldB = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:29:71: Error: 'fieldB' isn't a function or method and can't be invoked.
-  var /*@ type=dynamic */ callFieldB = new D(). /*@target=D::fieldB*/ fieldB();
-                                                                      ^";
-  dynamic callGetB = invalid-expression "pkg/front_end/testcases/inference/call_corner_cases.dart:30:67: Error: 'getB' isn't a function or method and can't be invoked.
-  var /*@ type=dynamic */ callGetB = new D(). /*@target=D::getB*/ getB();
-                                                                  ^";
+  core::int* callFieldB = new self::D::•().{self::D::fieldB}.{self::B::call}.{self::A::call}();
+  core::int* callGetB = new self::D::•().{self::D::getB}.{self::B::call}.{self::A::call}();
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
index c5baff1..36d9d8f 100644
--- a/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
@@ -7,16 +7,16 @@
 //   get field1 => null;
 //       ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   get field2 => null;
-//       ^^^^^^
-//
 // pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   set field1(value) {}
 //              ^^^^^
 //
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   get field2 => null;
+//       ^^^^^^
+//
 // pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   set field2(value) {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
index 46451b5..cdd0b47 100644
--- a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
@@ -7,16 +7,16 @@
 //   get field1 => null;
 //       ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   get field2 => null;
-//       ^^^^^^
-//
 // pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   set field1(value) {}
 //              ^^^^^
 //
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   get field2 => null;
+//       ^^^^^^
+//
 // pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   set field2(value) {}
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
index 46451b5..cdd0b47 100644
--- a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
@@ -7,16 +7,16 @@
 //   get field1 => null;
 //       ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   get field2 => null;
-//       ^^^^^^
-//
 // pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   set field1(value) {}
 //              ^^^^^
 //
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   get field2 => null;
+//       ^^^^^^
+//
 // pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   set field2(value) {}
diff --git a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect
index 4ae05470..1f6a002 100644
--- a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.expect
@@ -4,7 +4,7 @@
 //
 // pkg/front_end/testcases/inference/dynamic_methods.dart:16:39: Error: 'hashCode' isn't a function or method and can't be invoked.
 //       d. /*@target=Object::hashCode*/ hashCode();
-//                                       ^
+//                                       ^^^^^^^^
 //
 import self as self;
 import "dart:core" as core;
@@ -21,7 +21,7 @@
   core::int* get_hashCode = d.{core::Object::hashCode};
   dynamic call_hashCode = invalid-expression "pkg/front_end/testcases/inference/dynamic_methods.dart:16:39: Error: 'hashCode' isn't a function or method and can't be invoked.
       d. /*@target=Object::hashCode*/ hashCode();
-                                      ^";
+                                      ^^^^^^^^";
   core::String* call_toString = d.{core::Object::toString}();
   dynamic call_toStringArg = d.toString(color: "pink");
   dynamic call_foo0 = d.foo();
diff --git a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect
index 4ae05470..1f6a002 100644
--- a/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/dynamic_methods.dart.strong.transformed.expect
@@ -4,7 +4,7 @@
 //
 // pkg/front_end/testcases/inference/dynamic_methods.dart:16:39: Error: 'hashCode' isn't a function or method and can't be invoked.
 //       d. /*@target=Object::hashCode*/ hashCode();
-//                                       ^
+//                                       ^^^^^^^^
 //
 import self as self;
 import "dart:core" as core;
@@ -21,7 +21,7 @@
   core::int* get_hashCode = d.{core::Object::hashCode};
   dynamic call_hashCode = invalid-expression "pkg/front_end/testcases/inference/dynamic_methods.dart:16:39: Error: 'hashCode' isn't a function or method and can't be invoked.
       d. /*@target=Object::hashCode*/ hashCode();
-                                      ^";
+                                      ^^^^^^^^";
   core::String* call_toString = d.{core::Object::toString}();
   dynamic call_toStringArg = d.toString(color: "pink");
   dynamic call_foo0 = d.foo();
diff --git a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
index b4da5d7..1e35606 100644
--- a/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart.strong.expect
@@ -39,6 +39,8 @@
     return x;
 }
 static method main() → dynamic {
-  core::int* y = new self::D::•().{self::D::m}<core::int*>(42) as{TypeError,ForDynamic} core::int*;
+  core::int* y = (let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/generic_methods_do_not_infer_invalid_override_of_generic_method.dart:18:74: Error: Expected 0 type arguments.
+      . /*error:WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD*/ /*@target=D::m*/ m<int>(
+                                                                         ^" in new self::D::•().{self::D::m}<core::int*>(42)) as{TypeError} core::int*;
   core::print(y);
 }
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect
index 845ab16..4287368 100644
--- a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect
@@ -17,11 +17,6 @@
 //   f(x, {y}) {}
 //         ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   h(x, {y}) {}
-//         ^
-//
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   g(x, {y}) {}
@@ -32,6 +27,11 @@
 //   g(x, {y}) {}
 //         ^
 //
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   h(x, {y}) {}
+//         ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect
index bf74c35..490cc37 100644
--- a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect
@@ -17,11 +17,6 @@
 //   f(x, {y}) {}
 //         ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   h(x, {y}) {}
-//         ^
-//
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   g(x, {y}) {}
@@ -32,6 +27,11 @@
 //   g(x, {y}) {}
 //         ^
 //
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   h(x, {y}) {}
+//         ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
index bf74c35..490cc37 100644
--- a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
@@ -17,11 +17,6 @@
 //   f(x, {y}) {}
 //         ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
-// Try adding an explicit type.
-//   h(x, {y}) {}
-//         ^
-//
 // pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   g(x, {y}) {}
@@ -32,6 +27,11 @@
 //   g(x, {y}) {}
 //         ^
 //
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   h(x, {y}) {}
+//         ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
index 75fcb77..aa99310 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.outline.expect
@@ -33,7 +33,7 @@
   synthetic constructor •() → self::F*
     ;
 }
-abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
+abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
index 37866ab..f4d57d7 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.expect
@@ -39,7 +39,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
+abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect
index ae76c80..34832b2 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_getter.dart.strong.transformed.expect
@@ -39,7 +39,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _G&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _G&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
index 496e5d9..a74fb0d 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.outline.expect
@@ -33,7 +33,7 @@
   synthetic constructor •() → self::F*
     ;
 }
-abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
+abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
index f22d679..b74a039 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.expect
@@ -38,7 +38,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
+abstract class _G&Object&B = core::Object with self::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect
index 92238fe..e34d9aa 100644
--- a/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_field_overrides_setter.dart.strong.transformed.expect
@@ -38,7 +38,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _G&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _G&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_G&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.outline.expect
index 4a322ab..0c50386 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.outline.expect
@@ -27,12 +27,12 @@
   synthetic constructor •() → self::M1<self::M1::T*>*
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<core::int*> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<core::int*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.strong.expect
index 439d8bf..440e0b2 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.strong.expect
@@ -30,12 +30,12 @@
     : super self::I::•()
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<core::int*> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<core::int*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.outline.expect
index b4b8a61..a2ce3e3 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.outline.expect
@@ -22,12 +22,12 @@
   synthetic constructor •() → self::M1<self::M1::T*>*
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.strong.expect
index d0df383..ab3b42f 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.strong.expect
@@ -25,12 +25,12 @@
     : super self::I::•()
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.outline.expect
index d440c3a..b00323d 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.outline.expect
@@ -27,12 +27,12 @@
   synthetic constructor •() → self::M1<self::M1::T*>*
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.strong.expect
index 2643b49..7d11e0c 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.strong.expect
@@ -30,12 +30,12 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.outline.expect
index 946f92c..73edc70 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.outline.expect
@@ -29,12 +29,12 @@
   synthetic constructor •() → self::M1<self::M1::T*>*
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.strong.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.strong.expect
index 9389ac6..af62b10 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.strong.expect
@@ -32,12 +32,12 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0 = core::Object with self::M0<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0*
     : super core::Object::•()
     ;
 }
-abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin*/  {
+abstract class _A&Object&M0&M1 = self::_A&Object&M0 with self::M1<dynamic> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M0&M1*
     : super self::_A&Object&M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect
index 2b5aaee..f373c67 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect
@@ -2,6 +2,11 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
 // pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   var y;
@@ -23,7 +28,7 @@
     ;
 }
 class C extends self::B {
-  field self::A* x;
+  field invalid-type x;
   field invalid-type y;
   synthetic constructor •() → self::C*
     ;
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect
index 1f6563a..b5ca7dd 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect
@@ -2,6 +2,11 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
 // pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   var y;
@@ -25,7 +30,7 @@
     ;
 }
 class C extends self::B {
-  field self::A* x = null;
+  field invalid-type x = null;
   field invalid-type y = null;
   synthetic constructor •() → self::C*
     : super self::B::•()
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
index 1f6563a..b5ca7dd 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
@@ -2,6 +2,11 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
 // pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the inherited members have different types.
 // Try adding an explicit type.
 //   var y;
@@ -25,7 +30,7 @@
     ;
 }
 class C extends self::B {
-  field self::A* x = null;
+  field invalid-type x = null;
   field invalid-type y = null;
   synthetic constructor •() → self::C*
     : super self::B::•()
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect
index db06c2a..ac573d6 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect
@@ -1,4 +1,12 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -13,7 +21,7 @@
   abstract set x(core::int* value) → void;
 }
 class C extends self::B {
-  field core::num* x;
+  field invalid-type x;
   synthetic constructor •() → self::C*
     ;
 }
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect
index 5cdec7f..0d0b140 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect
@@ -1,4 +1,12 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -15,7 +23,7 @@
   abstract set x(core::int* value) → void;
 }
 class C extends self::B {
-  field core::num* x = null;
+  field invalid-type x = null;
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect
index 5cdec7f..0d0b140 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect
@@ -1,4 +1,12 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// Try adding an explicit type.
+//   var x;
+//       ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -15,7 +23,7 @@
   abstract set x(core::int* value) → void;
 }
 class C extends self::B {
-  field core::num* x = null;
+  field invalid-type x = null;
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart
new file mode 100644
index 0000000..78c5027
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  int? field;
+}
+
+class B implements A {
+  late var field;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.outline.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.outline.expect
new file mode 100644
index 0000000..c636c33
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.outline.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int? field;
+  synthetic constructor •() → self::A
+    ;
+}
+class B extends core::Object implements self::A {
+  field core::int? _#B#field;
+  field core::bool _#B#field#isSet;
+  synthetic constructor •() → self::B
+    ;
+  get field() → core::int?;
+  set field(core::int? #t1) → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.expect
new file mode 100644
index 0000000..0cb82625
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class A extends core::Object {
+  field core::int? field = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A {
+  field core::int? _#B#field = null;
+  field core::bool _#B#field#isSet = false;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get field() → core::int?
+    return this.{self::B::_#B#field#isSet} ?{core::int?} this.{self::B::_#B#field} : throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.");
+  set field(core::int? #t1) → void {
+    this.{self::B::_#B#field#isSet} = true;
+    this.{self::B::_#B#field} = #t1;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..0cb82625
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class A extends core::Object {
+  field core::int? field = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A {
+  field core::int? _#B#field = null;
+  field core::bool _#B#field#isSet = false;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get field() → core::int?
+    return this.{self::B::_#B#field#isSet} ?{core::int?} this.{self::B::_#B#field} : throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.");
+  set field(core::int? #t1) → void {
+    this.{self::B::_#B#field#isSet} = true;
+    this.{self::B::_#B#field} = #t1;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.expect
new file mode 100644
index 0000000..0cb82625
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class A extends core::Object {
+  field core::int? field = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A {
+  field core::int? _#B#field = null;
+  field core::bool _#B#field#isSet = false;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get field() → core::int?
+    return this.{self::B::_#B#field#isSet} ?{core::int?} this.{self::B::_#B#field} : throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.");
+  set field(core::int? #t1) → void {
+    this.{self::B::_#B#field#isSet} = true;
+    this.{self::B::_#B#field} = #t1;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.transformed.expect
new file mode 100644
index 0000000..0cb82625
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/infer_late_field_type.dart.weak.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class A extends core::Object {
+  field core::int? field = null;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A {
+  field core::int? _#B#field = null;
+  field core::bool _#B#field#isSet = false;
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  get field() → core::int?
+    return this.{self::B::_#B#field#isSet} ?{core::int?} this.{self::B::_#B#field} : throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.");
+  set field(core::int? #t1) → void {
+    this.{self::B::_#B#field#isSet} = true;
+    this.{self::B::_#B#field} = #t1;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart b/pkg/front_end/testcases/late_lowering/issue40805.dart
new file mode 100644
index 0000000..9f68135
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  D().x = 3.14;
+}
+
+class C {
+  covariant late final int x;
+}
+
+class D extends C {
+  set x(num value) { super.x = value.toInt(); }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.outline.expect
new file mode 100644
index 0000000..094d748
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.outline.expect
@@ -0,0 +1,19 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  covariant field core::int? _#C#x;
+  synthetic constructor •() → self::C
+    ;
+  get x() → core::int;
+  set x(core::int #t1) → void;
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    ;
+  set x(core::num value) → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.expect
new file mode 100644
index 0000000..b0526f2
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  covariant field core::int? _#C#x = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get x() → core::int
+    return let final core::int? #t1 = this.{self::C::_#C#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
+  set x(core::int #t2) → void
+    if(this.{self::C::_#C#x}.==(null))
+      this.{self::C::_#C#x} = #t2;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  set x(core::num value) → void {
+    super.{self::C::x} = value.{core::num::toInt}();
+  }
+}
+static method main() → dynamic {
+  new self::D::•().{self::D::x} = 3.14;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.transformed.expect
new file mode 100644
index 0000000..b0526f2
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.strong.transformed.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  covariant field core::int? _#C#x = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get x() → core::int
+    return let final core::int? #t1 = this.{self::C::_#C#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
+  set x(core::int #t2) → void
+    if(this.{self::C::_#C#x}.==(null))
+      this.{self::C::_#C#x} = #t2;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  set x(core::num value) → void {
+    super.{self::C::x} = value.{core::num::toInt}();
+  }
+}
+static method main() → dynamic {
+  new self::D::•().{self::D::x} = 3.14;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect
new file mode 100644
index 0000000..b0526f2
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  covariant field core::int? _#C#x = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get x() → core::int
+    return let final core::int? #t1 = this.{self::C::_#C#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
+  set x(core::int #t2) → void
+    if(this.{self::C::_#C#x}.==(null))
+      this.{self::C::_#C#x} = #t2;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  set x(core::num value) → void {
+    super.{self::C::x} = value.{core::num::toInt}();
+  }
+}
+static method main() → dynamic {
+  new self::D::•().{self::D::x} = 3.14;
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect
new file mode 100644
index 0000000..b0526f2
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+  covariant field core::int? _#C#x = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  get x() → core::int
+    return let final core::int? #t1 = this.{self::C::_#C#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
+  set x(core::int #t2) → void
+    if(this.{self::C::_#C#x}.==(null))
+      this.{self::C::_#C#x} = #t2;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  set x(core::num value) → void {
+    super.{self::C::x} = value.{core::num::toInt}();
+  }
+}
+static method main() → dynamic {
+  new self::D::•().{self::D::x} = 3.14;
+}
diff --git a/pkg/front_end/testcases/late_lowering/test.options b/pkg/front_end/testcases/late_lowering/test.options
index 63755f4..b7deb9b 100644
--- a/pkg/front_end/testcases/late_lowering/test.options
+++ b/pkg/front_end/testcases/late_lowering/test.options
@@ -1,4 +1,3 @@
 --enable-experiment=non-nullable
 --force-late-lowering
---force-nnbd-checks
 --overwrite-current-sdk-version=2.9999
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out.dart b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart
new file mode 100644
index 0000000..62bc3cd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Error: LegacyClass1 is exported and declared in opt-out.
+export 'export_from_opt_out_lib1.dart';
+
+// Error: LegacyClass3 and LegacyClass4 are still exported and declared in
+// opt-out.
+export 'export_from_opt_out_lib2.dart' hide legacyMethod2;
+
+// Error: LegacyClass2 is exported and declared in opt-out.
+export 'export_from_opt_out_lib3.dart' show LegacyClass2;
+
+// Error: legacyMethod1 is exported and declared in opt-out.
+export 'export_from_opt_out_lib3.dart' show legacyMethod1;
+
+// Error: LegacyExtension is exported and declared in opt-out.
+export 'export_from_opt_out_lib3.dart' show LegacyExtension;
+
+// Error: LegacyTypedef is exported and declared in opt-out.
+export 'export_from_opt_out_lib3.dart' show LegacyTypedef;
+
+// Ok: NnbdClass1 is declared in opt-in.
+export 'export_from_opt_out_lib3.dart' show NnbdClass1;
+
+// Ok: Only NnbdClass1 and NnbdClass2 are exported but are declared in opt-in.
+export 'export_from_opt_out_lib3.dart'
+    hide LegacyClass2, LegacyExtension, LegacyTypedef, legacyMethod1;
+
+// Ok: All exported declaration are from opt-in.
+export 'export_from_opt_out_lib4.dart';
+
+// Ok: All exported declaration are from opt-in.
+export 'export_from_opt_out_lib5.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.outline.expect
new file mode 100644
index 0000000..c7aa445
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.outline.expect
@@ -0,0 +1,121 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:6:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib1.dart';
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:10:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib2.dart' hide legacyMethod2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:13:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyClass2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:16:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show legacyMethod1;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:19:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyExtension;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:22:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyTypedef;
+// ^
+//
+import self as self;
+import "export_from_opt_out_lib1.dart" as exp;
+import "export_from_opt_out_lib2.dart" as exp2;
+import "export_from_opt_out_lib3.dart" as exp3;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp::LegacyClass1,
+  exp2::LegacyClass3,
+  exp2::LegacyClass4,
+  exp3::LegacyClass2,
+  exp3::legacyMethod1,
+  exp3::LegacyExtension,
+  exp3::LegacyTypedef,
+  exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib1.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib2.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib4.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+static method main() → dynamic
+  ;
+
+library;
+import self as exp;
+import "dart:core" as core;
+
+class LegacyClass1 extends core::Object {
+  synthetic constructor •() → exp::LegacyClass1*
+    ;
+}
+
+library;
+import self as exp2;
+import "dart:core" as core;
+
+class LegacyClass3 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass3*
+    ;
+}
+class LegacyClass4 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass4*
+    ;
+}
+static method legacyMethod2() → dynamic
+  ;
+
+library;
+import self as exp3;
+import "dart:core" as core;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+typedef LegacyTypedef = () →* void;
+class LegacyClass2 extends core::Object {
+  synthetic constructor •() → exp3::LegacyClass2*
+    ;
+}
+extension LegacyExtension on core::String* {
+}
+static method legacyMethod1() → dynamic
+  ;
+
+library;
+import self as self2;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as exp4;
+import "dart:core" as core;
+
+class NnbdClass1 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass1
+    ;
+}
+class NnbdClass2 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass2
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.strong.expect
new file mode 100644
index 0000000..93959c2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.strong.expect
@@ -0,0 +1,124 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:6:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib1.dart';
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:10:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib2.dart' hide legacyMethod2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:13:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyClass2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:16:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show legacyMethod1;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:19:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyExtension;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:22:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyTypedef;
+// ^
+//
+import self as self;
+import "export_from_opt_out_lib1.dart" as exp;
+import "export_from_opt_out_lib2.dart" as exp2;
+import "export_from_opt_out_lib3.dart" as exp3;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp::LegacyClass1,
+  exp2::LegacyClass3,
+  exp2::LegacyClass4,
+  exp3::LegacyClass2,
+  exp3::legacyMethod1,
+  exp3::LegacyExtension,
+  exp3::LegacyTypedef,
+  exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib1.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib2.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib4.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+static method main() → dynamic {}
+
+library;
+import self as exp;
+import "dart:core" as core;
+
+class LegacyClass1 extends core::Object {
+  synthetic constructor •() → exp::LegacyClass1*
+    : super core::Object::•()
+    ;
+}
+
+library;
+import self as exp2;
+import "dart:core" as core;
+
+class LegacyClass3 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass3*
+    : super core::Object::•()
+    ;
+}
+class LegacyClass4 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass4*
+    : super core::Object::•()
+    ;
+}
+static method legacyMethod2() → dynamic {}
+
+library;
+import self as exp3;
+import "dart:core" as core;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+typedef LegacyTypedef = () →* void;
+class LegacyClass2 extends core::Object {
+  synthetic constructor •() → exp3::LegacyClass2*
+    : super core::Object::•()
+    ;
+}
+extension LegacyExtension on core::String* {
+}
+static method legacyMethod1() → dynamic {}
+
+library;
+import self as self2;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as exp4;
+import "dart:core" as core;
+
+class NnbdClass1 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass1
+    : super core::Object::•()
+    ;
+}
+class NnbdClass2 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass2
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.strong.transformed.expect
new file mode 100644
index 0000000..93959c2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.strong.transformed.expect
@@ -0,0 +1,124 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:6:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib1.dart';
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:10:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib2.dart' hide legacyMethod2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:13:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyClass2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:16:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show legacyMethod1;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:19:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyExtension;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:22:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyTypedef;
+// ^
+//
+import self as self;
+import "export_from_opt_out_lib1.dart" as exp;
+import "export_from_opt_out_lib2.dart" as exp2;
+import "export_from_opt_out_lib3.dart" as exp3;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp::LegacyClass1,
+  exp2::LegacyClass3,
+  exp2::LegacyClass4,
+  exp3::LegacyClass2,
+  exp3::legacyMethod1,
+  exp3::LegacyExtension,
+  exp3::LegacyTypedef,
+  exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib1.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib2.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib4.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+static method main() → dynamic {}
+
+library;
+import self as exp;
+import "dart:core" as core;
+
+class LegacyClass1 extends core::Object {
+  synthetic constructor •() → exp::LegacyClass1*
+    : super core::Object::•()
+    ;
+}
+
+library;
+import self as exp2;
+import "dart:core" as core;
+
+class LegacyClass3 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass3*
+    : super core::Object::•()
+    ;
+}
+class LegacyClass4 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass4*
+    : super core::Object::•()
+    ;
+}
+static method legacyMethod2() → dynamic {}
+
+library;
+import self as exp3;
+import "dart:core" as core;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+typedef LegacyTypedef = () →* void;
+class LegacyClass2 extends core::Object {
+  synthetic constructor •() → exp3::LegacyClass2*
+    : super core::Object::•()
+    ;
+}
+extension LegacyExtension on core::String* {
+}
+static method legacyMethod1() → dynamic {}
+
+library;
+import self as self2;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as exp4;
+import "dart:core" as core;
+
+class NnbdClass1 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass1
+    : super core::Object::•()
+    ;
+}
+class NnbdClass2 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass2
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.weak.expect
new file mode 100644
index 0000000..93959c2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.weak.expect
@@ -0,0 +1,124 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:6:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib1.dart';
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:10:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib2.dart' hide legacyMethod2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:13:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyClass2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:16:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show legacyMethod1;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:19:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyExtension;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:22:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyTypedef;
+// ^
+//
+import self as self;
+import "export_from_opt_out_lib1.dart" as exp;
+import "export_from_opt_out_lib2.dart" as exp2;
+import "export_from_opt_out_lib3.dart" as exp3;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp::LegacyClass1,
+  exp2::LegacyClass3,
+  exp2::LegacyClass4,
+  exp3::LegacyClass2,
+  exp3::legacyMethod1,
+  exp3::LegacyExtension,
+  exp3::LegacyTypedef,
+  exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib1.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib2.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib4.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+static method main() → dynamic {}
+
+library;
+import self as exp;
+import "dart:core" as core;
+
+class LegacyClass1 extends core::Object {
+  synthetic constructor •() → exp::LegacyClass1*
+    : super core::Object::•()
+    ;
+}
+
+library;
+import self as exp2;
+import "dart:core" as core;
+
+class LegacyClass3 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass3*
+    : super core::Object::•()
+    ;
+}
+class LegacyClass4 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass4*
+    : super core::Object::•()
+    ;
+}
+static method legacyMethod2() → dynamic {}
+
+library;
+import self as exp3;
+import "dart:core" as core;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+typedef LegacyTypedef = () →* void;
+class LegacyClass2 extends core::Object {
+  synthetic constructor •() → exp3::LegacyClass2*
+    : super core::Object::•()
+    ;
+}
+extension LegacyExtension on core::String* {
+}
+static method legacyMethod1() → dynamic {}
+
+library;
+import self as self2;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as exp4;
+import "dart:core" as core;
+
+class NnbdClass1 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass1
+    : super core::Object::•()
+    ;
+}
+class NnbdClass2 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass2
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.weak.transformed.expect
new file mode 100644
index 0000000..93959c2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out.dart.weak.transformed.expect
@@ -0,0 +1,124 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:6:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib1.dart';
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:10:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib2.dart' hide legacyMethod2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:13:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyClass2;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:16:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show legacyMethod1;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:19:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyExtension;
+// ^
+//
+// pkg/front_end/testcases/nnbd/export_from_opt_out.dart:22:1: Error: Null safe libraries are not allowed to export declarations from of opt-out libraries.
+// export 'export_from_opt_out_lib3.dart' show LegacyTypedef;
+// ^
+//
+import self as self;
+import "export_from_opt_out_lib1.dart" as exp;
+import "export_from_opt_out_lib2.dart" as exp2;
+import "export_from_opt_out_lib3.dart" as exp3;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp::LegacyClass1,
+  exp2::LegacyClass3,
+  exp2::LegacyClass4,
+  exp3::LegacyClass2,
+  exp3::legacyMethod1,
+  exp3::LegacyExtension,
+  exp3::LegacyTypedef,
+  exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib1.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib2.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib3.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib4.dart";
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+static method main() → dynamic {}
+
+library;
+import self as exp;
+import "dart:core" as core;
+
+class LegacyClass1 extends core::Object {
+  synthetic constructor •() → exp::LegacyClass1*
+    : super core::Object::•()
+    ;
+}
+
+library;
+import self as exp2;
+import "dart:core" as core;
+
+class LegacyClass3 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass3*
+    : super core::Object::•()
+    ;
+}
+class LegacyClass4 extends core::Object {
+  synthetic constructor •() → exp2::LegacyClass4*
+    : super core::Object::•()
+    ;
+}
+static method legacyMethod2() → dynamic {}
+
+library;
+import self as exp3;
+import "dart:core" as core;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+typedef LegacyTypedef = () →* void;
+class LegacyClass2 extends core::Object {
+  synthetic constructor •() → exp3::LegacyClass2*
+    : super core::Object::•()
+    ;
+}
+extension LegacyExtension on core::String* {
+}
+static method legacyMethod1() → dynamic {}
+
+library;
+import self as self2;
+import "export_from_opt_out_lib5.dart" as exp4;
+additionalExports = (exp4::NnbdClass1,
+  exp4::NnbdClass2)
+
+export "org-dartlang-testcase:///export_from_opt_out_lib5.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as exp4;
+import "dart:core" as core;
+
+class NnbdClass1 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass1
+    : super core::Object::•()
+    ;
+}
+class NnbdClass2 extends core::Object {
+  synthetic constructor •() → exp4::NnbdClass2
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out_lib1.dart b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib1.dart
new file mode 100644
index 0000000..1943b6e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib1.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+class LegacyClass1 {}
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out_lib2.dart b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib2.dart
new file mode 100644
index 0000000..1723c1f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib2.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+class LegacyClass3 {}
+
+class LegacyClass4 {}
+
+legacyMethod2() {}
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out_lib3.dart b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib3.dart
new file mode 100644
index 0000000..148a845
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib3.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+export 'export_from_opt_out_lib5.dart';
+
+class LegacyClass2 {
+}
+
+legacyMethod1() {}
+
+extension LegacyExtension on String {
+}
+
+typedef LegacyTypedef = void Function();
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out_lib4.dart b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib4.dart
new file mode 100644
index 0000000..5a7261a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib4.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.5
+
+export 'export_from_opt_out_lib5.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_from_opt_out_lib5.dart b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib5.dart
new file mode 100644
index 0000000..be34d8b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_from_opt_out_lib5.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for 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 NnbdClass1 {}
+
+class NnbdClass2 {}
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect
index 3847c08..33133b3 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.outline.expect
@@ -193,7 +193,7 @@
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo = core::Object with self::Aoo /*isAnonymousMixin*/  {
+abstract class _Hoo&Object&Aoo = core::Object with self::Aoo /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -202,7 +202,7 @@
   synthetic constructor •() → self::Hoo
     ;
 }
-class Ioo = core::Object with self::Aoo implements self::Boo {
+class Ioo = core::Object with self::Aoo implements self::Boo /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Ioo
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect
index 443c33e..5fac846 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.expect
@@ -199,7 +199,7 @@
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo = core::Object with self::Aoo /*isAnonymousMixin*/  {
+abstract class _Hoo&Object&Aoo = core::Object with self::Aoo /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -209,7 +209,7 @@
     : super self::_Hoo&Object&Aoo::•()
     ;
 }
-class Ioo = core::Object with self::Aoo implements self::Boo {
+class Ioo = core::Object with self::Aoo implements self::Boo /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Ioo
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect
index d14af9b..a6f6d2a 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.strong.transformed.expect
@@ -199,7 +199,7 @@
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo extends core::Object implements self::Aoo /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hoo&Object&Aoo extends core::Object implements self::Aoo /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -209,7 +209,7 @@
     : super self::_Hoo&Object&Aoo::•()
     ;
 }
-class Ioo extends core::Object implements self::Boo, self::Aoo /*isEliminatedMixin*/  {
+class Ioo extends core::Object implements self::Boo, self::Aoo /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Ioo
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect
index 6bb2ecb..7dd2f83 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.expect
@@ -199,7 +199,7 @@
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo = core::Object with self::Aoo /*isAnonymousMixin*/  {
+abstract class _Hoo&Object&Aoo = core::Object with self::Aoo /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -209,7 +209,7 @@
     : super self::_Hoo&Object&Aoo::•()
     ;
 }
-class Ioo = core::Object with self::Aoo implements self::Boo {
+class Ioo = core::Object with self::Aoo implements self::Boo /*hasConstConstructor*/  {
   const synthetic constructor •() → self::Ioo
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect
index 470a8e7..2222d06 100644
--- a/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/forbidden_supers.dart.weak.transformed.expect
@@ -199,7 +199,7 @@
     : super self::Boo::•()
     ;
 }
-abstract class _Hoo&Object&Aoo extends core::Object implements self::Aoo /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Hoo&Object&Aoo extends core::Object implements self::Aoo /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Hoo&Object&Aoo
     : super core::Object::•()
     ;
@@ -209,7 +209,7 @@
     : super self::_Hoo&Object&Aoo::•()
     ;
 }
-class Ioo extends core::Object implements self::Boo, self::Aoo /*isEliminatedMixin*/  {
+class Ioo extends core::Object implements self::Boo, self::Aoo /*isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::Ioo
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect
index 0221dc8..7af22c0 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.outline.expect
@@ -2,6 +2,14 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+//  - 'Object' is from 'dart:core'.
+//   void method4b<T extends Object?>(); // error
+//        ^
+// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+//   void method4b<T extends Object>();
+//        ^
+//
 // pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
@@ -10,14 +18,6 @@
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
-//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
-//   void method5c<T extends Class1>(); // error
-//        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
-//   void method5c<T extends Class1?>();
-//        ^
-//
 // pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
@@ -26,12 +26,12 @@
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
-//  - 'Object' is from 'dart:core'.
-//   void method4b<T extends Object?>(); // error
+// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
+//   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
-//   void method4b<T extends Object>();
+// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+//   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect
index be101f6..f9ca321 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.expect
@@ -2,6 +2,14 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+//  - 'Object' is from 'dart:core'.
+//   void method4b<T extends Object?>(); // error
+//        ^
+// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+//   void method4b<T extends Object>();
+//        ^
+//
 // pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
@@ -10,14 +18,6 @@
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
-//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
-//   void method5c<T extends Class1>(); // error
-//        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
-//   void method5c<T extends Class1?>();
-//        ^
-//
 // pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
@@ -26,12 +26,12 @@
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
-//  - 'Object' is from 'dart:core'.
-//   void method4b<T extends Object?>(); // error
+// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
+//   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
-//   void method4b<T extends Object>();
+// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+//   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect
index be101f6..f9ca321 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.strong.transformed.expect
@@ -2,6 +2,14 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+//  - 'Object' is from 'dart:core'.
+//   void method4b<T extends Object?>(); // error
+//        ^
+// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+//   void method4b<T extends Object>();
+//        ^
+//
 // pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
@@ -10,14 +18,6 @@
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
-//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
-//   void method5c<T extends Class1>(); // error
-//        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
-//   void method5c<T extends Class1?>();
-//        ^
-//
 // pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
@@ -26,12 +26,12 @@
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
-//  - 'Object' is from 'dart:core'.
-//   void method4b<T extends Object?>(); // error
+// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
+//   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
-//   void method4b<T extends Object>();
+// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+//   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect
index be101f6..f9ca321 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.expect
@@ -2,6 +2,14 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+//  - 'Object' is from 'dart:core'.
+//   void method4b<T extends Object?>(); // error
+//        ^
+// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+//   void method4b<T extends Object>();
+//        ^
+//
 // pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
@@ -10,14 +18,6 @@
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
-//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
-//   void method5c<T extends Class1>(); // error
-//        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
-//   void method5c<T extends Class1?>();
-//        ^
-//
 // pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
@@ -26,12 +26,12 @@
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
-//  - 'Object' is from 'dart:core'.
-//   void method4b<T extends Object?>(); // error
+// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
+//   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
-//   void method4b<T extends Object>();
+// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+//   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
diff --git a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect
index be101f6..f9ca321 100644
--- a/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/generic_override.dart.weak.transformed.expect
@@ -2,6 +2,14 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
+//  - 'Object' is from 'dart:core'.
+//   void method4b<T extends Object?>(); // error
+//        ^
+// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
+//   void method4b<T extends Object>();
+//        ^
+//
 // pkg/front_end/testcases/nnbd/generic_override.dart:38:8: Error: Declared bound 'Object' of type variable 'T' of 'Class2.method4c' doesn't match the bound 'Object?' on overridden method 'Class1.method4c'.
 //  - 'Object' is from 'dart:core'.
 //   void method4c<T extends Object>(); // error
@@ -10,14 +18,6 @@
 //   void method4c<T extends Object?>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
-//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
-//   void method5c<T extends Class1>(); // error
-//        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
-//   void method5c<T extends Class1?>();
-//        ^
-//
 // pkg/front_end/testcases/nnbd/generic_override.dart:41:8: Error: Declared bound 'Class1?' of type variable 'T' of 'Class2.method5b' doesn't match the bound 'Class1' on overridden method 'Class1.method5b'.
 //  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
 //   void method5b<T extends Class1?>(); // error
@@ -26,12 +26,12 @@
 //   void method5b<T extends Class1>();
 //        ^
 //
-// pkg/front_end/testcases/nnbd/generic_override.dart:37:8: Error: Declared bound 'Object?' of type variable 'T' of 'Class2.method4b' doesn't match the bound 'Object' on overridden method 'Class1.method4b'.
-//  - 'Object' is from 'dart:core'.
-//   void method4b<T extends Object?>(); // error
+// pkg/front_end/testcases/nnbd/generic_override.dart:42:8: Error: Declared bound 'Class1' of type variable 'T' of 'Class2.method5c' doesn't match the bound 'Class1?' on overridden method 'Class1.method5c'.
+//  - 'Class1' is from 'pkg/front_end/testcases/nnbd/generic_override.dart'.
+//   void method5c<T extends Class1>(); // error
 //        ^
-// pkg/front_end/testcases/nnbd/generic_override.dart:17:8: Context: This is the overridden method ('method4b').
-//   void method4b<T extends Object>();
+// pkg/front_end/testcases/nnbd/generic_override.dart:22:8: Context: This is the overridden method ('method5c').
+//   void method5c<T extends Class1?>();
 //        ^
 //
 import self as self;
diff --git a/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart
new file mode 100644
index 0000000..aff7e8c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights 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 'infer_constraints_from_opt_in_lib.dart';
+
+main() {
+  var local0 = [];
+  var local1a = [field1];
+  var local1b = [field2];
+  var local1c = [field3];
+  var local1d = [field4];
+  var local1e = [field5];
+  var local1f = [field6];
+  var local1g = [field7];
+  var local1h = [field8];
+  var local1i = [null];
+  var local2a = {field1, null};
+  var local2b = {field2, null};
+  var local2c = {field3, null};
+  var local2d = {field4, null};
+  var local2e = {field5, null};
+  var local2f = {field6, null};
+  var local2g = {field7, null};
+  var local2h = {field8, null};
+  var local3a = {null, field1};
+  var local3b = {null, field2};
+  var local3c = {null, field3};
+  var local3d = {null, field4};
+  var local3e = {null, field5};
+  var local3f = {null, field6};
+  var local3g = {null, field7};
+  var local3h = {null, field8};
+}
+
+abstract class A {
+  baz(B b) {
+    b.foo(b.bar());
+  }
+}
diff --git a/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.outline.expect
new file mode 100644
index 0000000..bcaa0e0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.outline.expect
@@ -0,0 +1,52 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "infer_constraints_from_opt_in_lib.dart" as inf;
+
+import "org-dartlang-testcase:///infer_constraints_from_opt_in_lib.dart";
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    ;
+  method baz(inf::B* b) → dynamic
+    ;
+}
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:11:9: Error: Field 'field5' should be initialized because its type 'C<int?>' doesn't allow null.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart'.
+// C<int?> field5;
+//         ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:13:5: Error: Field 'field7' should be initialized because its type 'int' doesn't allow null.
+// int field7;
+//     ^^^^^^
+//
+import self as inf;
+import "dart:core" as core;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → inf::C<inf::C::T%>
+    ;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → inf::B
+    ;
+  abstract method bar<X extends core::List<core::int?>? = core::List<core::int?>?>() → inf::B::bar::X%;
+  abstract method foo(core::List<core::int> list) → dynamic;
+}
+static field inf::C<dynamic> field1;
+static field inf::C<dynamic>? field2;
+static field inf::C<core::int> field3;
+static field inf::C<core::int>? field4;
+static field inf::C<core::int?> field5;
+static field inf::C<core::int?>? field6;
+static field core::int field7;
+static field core::int? field8;
+static method method() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.strong.expect
new file mode 100644
index 0000000..2ab45fe
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.strong.expect
@@ -0,0 +1,110 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "infer_constraints_from_opt_in_lib.dart" as inf;
+import "dart:collection" as col;
+
+import "org-dartlang-testcase:///infer_constraints_from_opt_in_lib.dart";
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  method baz(inf::B* b) → dynamic {
+    b.{inf::B::foo}(b.{inf::B::bar}<core::List<core::int*>*>());
+  }
+}
+static method main() → dynamic {
+  core::List<dynamic>* local0 = <dynamic>[];
+  core::List<inf::C<dynamic>*>* local1a = <inf::C<dynamic>*>[inf::field1];
+  core::List<inf::C<dynamic>*>* local1b = <inf::C<dynamic>*>[inf::field2];
+  core::List<inf::C<core::int*>*>* local1c = <inf::C<core::int*>*>[inf::field3];
+  core::List<inf::C<core::int*>*>* local1d = <inf::C<core::int*>*>[inf::field4];
+  core::List<inf::C<core::int*>*>* local1e = <inf::C<core::int*>*>[inf::field5];
+  core::List<inf::C<core::int*>*>* local1f = <inf::C<core::int*>*>[inf::field6];
+  core::List<core::int*>* local1g = <core::int*>[inf::field7];
+  core::List<core::int*>* local1h = <core::int*>[inf::field8];
+  core::List<core::Null?>* local1i = <core::Null?>[null];
+  core::Set<inf::C<dynamic>*>* local2a = let final core::Set<inf::C<dynamic>*>* #t1 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final dynamic #t2 = #t1.{core::Set::add}(inf::field1) in let final dynamic #t3 = #t1.{core::Set::add}(null) in #t1;
+  core::Set<inf::C<dynamic>*>* local2b = let final core::Set<inf::C<dynamic>*>* #t4 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final dynamic #t5 = #t4.{core::Set::add}(inf::field2) in let final dynamic #t6 = #t4.{core::Set::add}(null) in #t4;
+  core::Set<inf::C<core::int*>*>* local2c = let final core::Set<inf::C<core::int*>*>* #t7 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t8 = #t7.{core::Set::add}(inf::field3) in let final dynamic #t9 = #t7.{core::Set::add}(null) in #t7;
+  core::Set<inf::C<core::int*>*>* local2d = let final core::Set<inf::C<core::int*>*>* #t10 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t11 = #t10.{core::Set::add}(inf::field4) in let final dynamic #t12 = #t10.{core::Set::add}(null) in #t10;
+  core::Set<inf::C<core::int*>*>* local2e = let final core::Set<inf::C<core::int*>*>* #t13 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t14 = #t13.{core::Set::add}(inf::field5) in let final dynamic #t15 = #t13.{core::Set::add}(null) in #t13;
+  core::Set<inf::C<core::int*>*>* local2f = let final core::Set<inf::C<core::int*>*>* #t16 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t17 = #t16.{core::Set::add}(inf::field6) in let final dynamic #t18 = #t16.{core::Set::add}(null) in #t16;
+  core::Set<core::int*>* local2g = let final core::Set<core::int*>* #t19 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t20 = #t19.{core::Set::add}(inf::field7) in let final dynamic #t21 = #t19.{core::Set::add}(null) in #t19;
+  core::Set<core::int*>* local2h = let final core::Set<core::int*>* #t22 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t23 = #t22.{core::Set::add}(inf::field8) in let final dynamic #t24 = #t22.{core::Set::add}(null) in #t22;
+  core::Set<inf::C<dynamic>*>* local3a = let final core::Set<inf::C<dynamic>*>* #t25 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final dynamic #t26 = #t25.{core::Set::add}(null) in let final dynamic #t27 = #t25.{core::Set::add}(inf::field1) in #t25;
+  core::Set<inf::C<dynamic>*>* local3b = let final core::Set<inf::C<dynamic>*>* #t28 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final dynamic #t29 = #t28.{core::Set::add}(null) in let final dynamic #t30 = #t28.{core::Set::add}(inf::field2) in #t28;
+  core::Set<inf::C<core::int*>*>* local3c = let final core::Set<inf::C<core::int*>*>* #t31 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t32 = #t31.{core::Set::add}(null) in let final dynamic #t33 = #t31.{core::Set::add}(inf::field3) in #t31;
+  core::Set<inf::C<core::int*>*>* local3d = let final core::Set<inf::C<core::int*>*>* #t34 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t35 = #t34.{core::Set::add}(null) in let final dynamic #t36 = #t34.{core::Set::add}(inf::field4) in #t34;
+  core::Set<inf::C<core::int*>*>* local3e = let final core::Set<inf::C<core::int*>*>* #t37 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t38 = #t37.{core::Set::add}(null) in let final dynamic #t39 = #t37.{core::Set::add}(inf::field5) in #t37;
+  core::Set<inf::C<core::int*>*>* local3f = let final core::Set<inf::C<core::int*>*>* #t40 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t41 = #t40.{core::Set::add}(null) in let final dynamic #t42 = #t40.{core::Set::add}(inf::field6) in #t40;
+  core::Set<core::int*>* local3g = let final core::Set<core::int*>* #t43 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t44 = #t43.{core::Set::add}(null) in let final dynamic #t45 = #t43.{core::Set::add}(inf::field7) in #t43;
+  core::Set<core::int*>* local3h = let final core::Set<core::int*>* #t46 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t47 = #t46.{core::Set::add}(null) in let final dynamic #t48 = #t46.{core::Set::add}(inf::field8) in #t46;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:11:9: Error: Field 'field5' should be initialized because its type 'C<int?>' doesn't allow null.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart'.
+// C<int?> field5;
+//         ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:13:5: Error: Field 'field7' should be initialized because its type 'int' doesn't allow null.
+// int field7;
+//     ^^^^^^
+//
+import self as inf;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → inf::C<inf::C::T%>
+    : super core::Object::•()
+    ;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → inf::B
+    : super core::Object::•()
+    ;
+  abstract method bar<X extends core::List<core::int?>? = core::List<core::int?>?>() → inf::B::bar::X%;
+  abstract method foo(core::List<core::int> list) → dynamic;
+}
+static field inf::C<dynamic> field1 = new inf::C::•<dynamic>();
+static field inf::C<dynamic>? field2;
+static field inf::C<core::int> field3 = new inf::C::•<core::int>();
+static field inf::C<core::int>? field4;
+static field inf::C<core::int?> field5;
+static field inf::C<core::int?>? field6;
+static field core::int field7;
+static field core::int? field8;
+static method method() → dynamic {
+  core::List<dynamic> local0 = <dynamic>[];
+  core::List<inf::C<dynamic>> local1a = <inf::C<dynamic>>[inf::field1];
+  core::List<inf::C<dynamic>?> local1b = <inf::C<dynamic>?>[inf::field2];
+  core::List<inf::C<core::int>> local1c = <inf::C<core::int>>[inf::field3];
+  core::List<inf::C<core::int>?> local1d = <inf::C<core::int>?>[inf::field4];
+  core::List<inf::C<core::int?>> local1e = <inf::C<core::int?>>[inf::field5];
+  core::List<inf::C<core::int?>?> local1f = <inf::C<core::int?>?>[inf::field6];
+  core::List<core::int> local1g = <core::int>[inf::field7];
+  core::List<core::int?> local1h = <core::int?>[inf::field8];
+  core::List<core::Null?> local1i = <core::Null?>[null];
+  core::Set<inf::C<dynamic>?> local2a = let final core::Set<inf::C<dynamic>?> #t49 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final dynamic #t50 = #t49.{core::Set::add}(inf::field1) in let final dynamic #t51 = #t49.{core::Set::add}(null) in #t49;
+  core::Set<inf::C<dynamic>?> local2b = let final core::Set<inf::C<dynamic>?> #t52 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final dynamic #t53 = #t52.{core::Set::add}(inf::field2) in let final dynamic #t54 = #t52.{core::Set::add}(null) in #t52;
+  core::Set<inf::C<core::int>?> local2c = let final core::Set<inf::C<core::int>?> #t55 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final dynamic #t56 = #t55.{core::Set::add}(inf::field3) in let final dynamic #t57 = #t55.{core::Set::add}(null) in #t55;
+  core::Set<inf::C<core::int>?> local2d = let final core::Set<inf::C<core::int>?> #t58 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final dynamic #t59 = #t58.{core::Set::add}(inf::field4) in let final dynamic #t60 = #t58.{core::Set::add}(null) in #t58;
+  core::Set<inf::C<core::int?>?> local2e = let final core::Set<inf::C<core::int?>?> #t61 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final dynamic #t62 = #t61.{core::Set::add}(inf::field5) in let final dynamic #t63 = #t61.{core::Set::add}(null) in #t61;
+  core::Set<inf::C<core::int?>?> local2f = let final core::Set<inf::C<core::int?>?> #t64 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final dynamic #t65 = #t64.{core::Set::add}(inf::field6) in let final dynamic #t66 = #t64.{core::Set::add}(null) in #t64;
+  core::Set<core::int?> local2g = let final core::Set<core::int?> #t67 = col::LinkedHashSet::•<core::int?>() in let final dynamic #t68 = #t67.{core::Set::add}(inf::field7) in let final dynamic #t69 = #t67.{core::Set::add}(null) in #t67;
+  core::Set<core::int?> local2h = let final core::Set<core::int?> #t70 = col::LinkedHashSet::•<core::int?>() in let final dynamic #t71 = #t70.{core::Set::add}(inf::field8) in let final dynamic #t72 = #t70.{core::Set::add}(null) in #t70;
+  core::Set<inf::C<dynamic>?> local3a = let final core::Set<inf::C<dynamic>?> #t73 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final dynamic #t74 = #t73.{core::Set::add}(null) in let final dynamic #t75 = #t73.{core::Set::add}(inf::field1) in #t73;
+  core::Set<inf::C<dynamic>?> local3b = let final core::Set<inf::C<dynamic>?> #t76 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final dynamic #t77 = #t76.{core::Set::add}(null) in let final dynamic #t78 = #t76.{core::Set::add}(inf::field2) in #t76;
+  core::Set<inf::C<core::int>?> local3c = let final core::Set<inf::C<core::int>?> #t79 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final dynamic #t80 = #t79.{core::Set::add}(null) in let final dynamic #t81 = #t79.{core::Set::add}(inf::field3) in #t79;
+  core::Set<inf::C<core::int>?> local3d = let final core::Set<inf::C<core::int>?> #t82 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final dynamic #t83 = #t82.{core::Set::add}(null) in let final dynamic #t84 = #t82.{core::Set::add}(inf::field4) in #t82;
+  core::Set<inf::C<core::int?>?> local3e = let final core::Set<inf::C<core::int?>?> #t85 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final dynamic #t86 = #t85.{core::Set::add}(null) in let final dynamic #t87 = #t85.{core::Set::add}(inf::field5) in #t85;
+  core::Set<inf::C<core::int?>?> local3f = let final core::Set<inf::C<core::int?>?> #t88 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final dynamic #t89 = #t88.{core::Set::add}(null) in let final dynamic #t90 = #t88.{core::Set::add}(inf::field6) in #t88;
+  core::Set<core::int?> local3g = let final core::Set<core::int?> #t91 = col::LinkedHashSet::•<core::int?>() in let final dynamic #t92 = #t91.{core::Set::add}(null) in let final dynamic #t93 = #t91.{core::Set::add}(inf::field7) in #t91;
+  core::Set<core::int?> local3h = let final core::Set<core::int?> #t94 = col::LinkedHashSet::•<core::int?>() in let final dynamic #t95 = #t94.{core::Set::add}(null) in let final dynamic #t96 = #t94.{core::Set::add}(inf::field8) in #t94;
+}
diff --git a/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..755f2c9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.strong.transformed.expect
@@ -0,0 +1,110 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "infer_constraints_from_opt_in_lib.dart" as inf;
+import "dart:collection" as col;
+
+import "org-dartlang-testcase:///infer_constraints_from_opt_in_lib.dart";
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  method baz(inf::B* b) → dynamic {
+    b.{inf::B::foo}(b.{inf::B::bar}<core::List<core::int*>*>());
+  }
+}
+static method main() → dynamic {
+  core::List<dynamic>* local0 = <dynamic>[];
+  core::List<inf::C<dynamic>*>* local1a = <inf::C<dynamic>*>[inf::field1];
+  core::List<inf::C<dynamic>*>* local1b = <inf::C<dynamic>*>[inf::field2];
+  core::List<inf::C<core::int*>*>* local1c = <inf::C<core::int*>*>[inf::field3];
+  core::List<inf::C<core::int*>*>* local1d = <inf::C<core::int*>*>[inf::field4];
+  core::List<inf::C<core::int*>*>* local1e = <inf::C<core::int*>*>[inf::field5];
+  core::List<inf::C<core::int*>*>* local1f = <inf::C<core::int*>*>[inf::field6];
+  core::List<core::int*>* local1g = <core::int*>[inf::field7];
+  core::List<core::int*>* local1h = <core::int*>[inf::field8];
+  core::List<core::Null?>* local1i = <core::Null?>[null];
+  core::Set<inf::C<dynamic>*>* local2a = let final core::Set<inf::C<dynamic>*>* #t1 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final core::bool* #t2 = #t1.{core::Set::add}(inf::field1) in let final core::bool* #t3 = #t1.{core::Set::add}(null) in #t1;
+  core::Set<inf::C<dynamic>*>* local2b = let final core::Set<inf::C<dynamic>*>* #t4 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final core::bool* #t5 = #t4.{core::Set::add}(inf::field2) in let final core::bool* #t6 = #t4.{core::Set::add}(null) in #t4;
+  core::Set<inf::C<core::int*>*>* local2c = let final core::Set<inf::C<core::int*>*>* #t7 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t8 = #t7.{core::Set::add}(inf::field3) in let final core::bool* #t9 = #t7.{core::Set::add}(null) in #t7;
+  core::Set<inf::C<core::int*>*>* local2d = let final core::Set<inf::C<core::int*>*>* #t10 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t11 = #t10.{core::Set::add}(inf::field4) in let final core::bool* #t12 = #t10.{core::Set::add}(null) in #t10;
+  core::Set<inf::C<core::int*>*>* local2e = let final core::Set<inf::C<core::int*>*>* #t13 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t14 = #t13.{core::Set::add}(inf::field5) in let final core::bool* #t15 = #t13.{core::Set::add}(null) in #t13;
+  core::Set<inf::C<core::int*>*>* local2f = let final core::Set<inf::C<core::int*>*>* #t16 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t17 = #t16.{core::Set::add}(inf::field6) in let final core::bool* #t18 = #t16.{core::Set::add}(null) in #t16;
+  core::Set<core::int*>* local2g = let final core::Set<core::int*>* #t19 = col::LinkedHashSet::•<core::int*>() in let final core::bool* #t20 = #t19.{core::Set::add}(inf::field7) in let final core::bool* #t21 = #t19.{core::Set::add}(null) in #t19;
+  core::Set<core::int*>* local2h = let final core::Set<core::int*>* #t22 = col::LinkedHashSet::•<core::int*>() in let final core::bool* #t23 = #t22.{core::Set::add}(inf::field8) in let final core::bool* #t24 = #t22.{core::Set::add}(null) in #t22;
+  core::Set<inf::C<dynamic>*>* local3a = let final core::Set<inf::C<dynamic>*>* #t25 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final core::bool* #t26 = #t25.{core::Set::add}(null) in let final core::bool* #t27 = #t25.{core::Set::add}(inf::field1) in #t25;
+  core::Set<inf::C<dynamic>*>* local3b = let final core::Set<inf::C<dynamic>*>* #t28 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final core::bool* #t29 = #t28.{core::Set::add}(null) in let final core::bool* #t30 = #t28.{core::Set::add}(inf::field2) in #t28;
+  core::Set<inf::C<core::int*>*>* local3c = let final core::Set<inf::C<core::int*>*>* #t31 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t32 = #t31.{core::Set::add}(null) in let final core::bool* #t33 = #t31.{core::Set::add}(inf::field3) in #t31;
+  core::Set<inf::C<core::int*>*>* local3d = let final core::Set<inf::C<core::int*>*>* #t34 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t35 = #t34.{core::Set::add}(null) in let final core::bool* #t36 = #t34.{core::Set::add}(inf::field4) in #t34;
+  core::Set<inf::C<core::int*>*>* local3e = let final core::Set<inf::C<core::int*>*>* #t37 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t38 = #t37.{core::Set::add}(null) in let final core::bool* #t39 = #t37.{core::Set::add}(inf::field5) in #t37;
+  core::Set<inf::C<core::int*>*>* local3f = let final core::Set<inf::C<core::int*>*>* #t40 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t41 = #t40.{core::Set::add}(null) in let final core::bool* #t42 = #t40.{core::Set::add}(inf::field6) in #t40;
+  core::Set<core::int*>* local3g = let final core::Set<core::int*>* #t43 = col::LinkedHashSet::•<core::int*>() in let final core::bool* #t44 = #t43.{core::Set::add}(null) in let final core::bool* #t45 = #t43.{core::Set::add}(inf::field7) in #t43;
+  core::Set<core::int*>* local3h = let final core::Set<core::int*>* #t46 = col::LinkedHashSet::•<core::int*>() in let final core::bool* #t47 = #t46.{core::Set::add}(null) in let final core::bool* #t48 = #t46.{core::Set::add}(inf::field8) in #t46;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:11:9: Error: Field 'field5' should be initialized because its type 'C<int?>' doesn't allow null.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart'.
+// C<int?> field5;
+//         ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:13:5: Error: Field 'field7' should be initialized because its type 'int' doesn't allow null.
+// int field7;
+//     ^^^^^^
+//
+import self as inf;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → inf::C<inf::C::T%>
+    : super core::Object::•()
+    ;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → inf::B
+    : super core::Object::•()
+    ;
+  abstract method bar<X extends core::List<core::int?>? = core::List<core::int?>?>() → inf::B::bar::X%;
+  abstract method foo(core::List<core::int> list) → dynamic;
+}
+static field inf::C<dynamic> field1 = new inf::C::•<dynamic>();
+static field inf::C<dynamic>? field2;
+static field inf::C<core::int> field3 = new inf::C::•<core::int>();
+static field inf::C<core::int>? field4;
+static field inf::C<core::int?> field5;
+static field inf::C<core::int?>? field6;
+static field core::int field7;
+static field core::int? field8;
+static method method() → dynamic {
+  core::List<dynamic> local0 = <dynamic>[];
+  core::List<inf::C<dynamic>> local1a = <inf::C<dynamic>>[inf::field1];
+  core::List<inf::C<dynamic>?> local1b = <inf::C<dynamic>?>[inf::field2];
+  core::List<inf::C<core::int>> local1c = <inf::C<core::int>>[inf::field3];
+  core::List<inf::C<core::int>?> local1d = <inf::C<core::int>?>[inf::field4];
+  core::List<inf::C<core::int?>> local1e = <inf::C<core::int?>>[inf::field5];
+  core::List<inf::C<core::int?>?> local1f = <inf::C<core::int?>?>[inf::field6];
+  core::List<core::int> local1g = <core::int>[inf::field7];
+  core::List<core::int?> local1h = <core::int?>[inf::field8];
+  core::List<core::Null?> local1i = <core::Null?>[null];
+  core::Set<inf::C<dynamic>?> local2a = let final core::Set<inf::C<dynamic>?> #t49 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final core::bool* #t50 = #t49.{core::Set::add}(inf::field1) in let final core::bool* #t51 = #t49.{core::Set::add}(null) in #t49;
+  core::Set<inf::C<dynamic>?> local2b = let final core::Set<inf::C<dynamic>?> #t52 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final core::bool* #t53 = #t52.{core::Set::add}(inf::field2) in let final core::bool* #t54 = #t52.{core::Set::add}(null) in #t52;
+  core::Set<inf::C<core::int>?> local2c = let final core::Set<inf::C<core::int>?> #t55 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final core::bool* #t56 = #t55.{core::Set::add}(inf::field3) in let final core::bool* #t57 = #t55.{core::Set::add}(null) in #t55;
+  core::Set<inf::C<core::int>?> local2d = let final core::Set<inf::C<core::int>?> #t58 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final core::bool* #t59 = #t58.{core::Set::add}(inf::field4) in let final core::bool* #t60 = #t58.{core::Set::add}(null) in #t58;
+  core::Set<inf::C<core::int?>?> local2e = let final core::Set<inf::C<core::int?>?> #t61 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final core::bool* #t62 = #t61.{core::Set::add}(inf::field5) in let final core::bool* #t63 = #t61.{core::Set::add}(null) in #t61;
+  core::Set<inf::C<core::int?>?> local2f = let final core::Set<inf::C<core::int?>?> #t64 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final core::bool* #t65 = #t64.{core::Set::add}(inf::field6) in let final core::bool* #t66 = #t64.{core::Set::add}(null) in #t64;
+  core::Set<core::int?> local2g = let final core::Set<core::int?> #t67 = col::LinkedHashSet::•<core::int?>() in let final core::bool* #t68 = #t67.{core::Set::add}(inf::field7) in let final core::bool* #t69 = #t67.{core::Set::add}(null) in #t67;
+  core::Set<core::int?> local2h = let final core::Set<core::int?> #t70 = col::LinkedHashSet::•<core::int?>() in let final core::bool* #t71 = #t70.{core::Set::add}(inf::field8) in let final core::bool* #t72 = #t70.{core::Set::add}(null) in #t70;
+  core::Set<inf::C<dynamic>?> local3a = let final core::Set<inf::C<dynamic>?> #t73 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final core::bool* #t74 = #t73.{core::Set::add}(null) in let final core::bool* #t75 = #t73.{core::Set::add}(inf::field1) in #t73;
+  core::Set<inf::C<dynamic>?> local3b = let final core::Set<inf::C<dynamic>?> #t76 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final core::bool* #t77 = #t76.{core::Set::add}(null) in let final core::bool* #t78 = #t76.{core::Set::add}(inf::field2) in #t76;
+  core::Set<inf::C<core::int>?> local3c = let final core::Set<inf::C<core::int>?> #t79 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final core::bool* #t80 = #t79.{core::Set::add}(null) in let final core::bool* #t81 = #t79.{core::Set::add}(inf::field3) in #t79;
+  core::Set<inf::C<core::int>?> local3d = let final core::Set<inf::C<core::int>?> #t82 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final core::bool* #t83 = #t82.{core::Set::add}(null) in let final core::bool* #t84 = #t82.{core::Set::add}(inf::field4) in #t82;
+  core::Set<inf::C<core::int?>?> local3e = let final core::Set<inf::C<core::int?>?> #t85 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final core::bool* #t86 = #t85.{core::Set::add}(null) in let final core::bool* #t87 = #t85.{core::Set::add}(inf::field5) in #t85;
+  core::Set<inf::C<core::int?>?> local3f = let final core::Set<inf::C<core::int?>?> #t88 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final core::bool* #t89 = #t88.{core::Set::add}(null) in let final core::bool* #t90 = #t88.{core::Set::add}(inf::field6) in #t88;
+  core::Set<core::int?> local3g = let final core::Set<core::int?> #t91 = col::LinkedHashSet::•<core::int?>() in let final core::bool* #t92 = #t91.{core::Set::add}(null) in let final core::bool* #t93 = #t91.{core::Set::add}(inf::field7) in #t91;
+  core::Set<core::int?> local3h = let final core::Set<core::int?> #t94 = col::LinkedHashSet::•<core::int?>() in let final core::bool* #t95 = #t94.{core::Set::add}(null) in let final core::bool* #t96 = #t94.{core::Set::add}(inf::field8) in #t94;
+}
diff --git a/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..1e36767
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.weak.expect
@@ -0,0 +1,110 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "infer_constraints_from_opt_in_lib.dart" as inf;
+import "dart:collection" as col;
+
+import "org-dartlang-testcase:///infer_constraints_from_opt_in_lib.dart";
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  method baz(inf::B* b) → dynamic {
+    b.{inf::B::foo}(b.{inf::B::bar}<core::List<core::int*>*>());
+  }
+}
+static method main() → dynamic {
+  core::List<dynamic>* local0 = <dynamic>[];
+  core::List<inf::C<dynamic>*>* local1a = <inf::C<dynamic>*>[inf::field1];
+  core::List<inf::C<dynamic>*>* local1b = <inf::C<dynamic>*>[inf::field2];
+  core::List<inf::C<core::int*>*>* local1c = <inf::C<core::int*>*>[inf::field3];
+  core::List<inf::C<core::int*>*>* local1d = <inf::C<core::int*>*>[inf::field4];
+  core::List<inf::C<core::int*>*>* local1e = <inf::C<core::int*>*>[inf::field5];
+  core::List<inf::C<core::int*>*>* local1f = <inf::C<core::int*>*>[inf::field6];
+  core::List<core::int*>* local1g = <core::int*>[inf::field7];
+  core::List<core::int*>* local1h = <core::int*>[inf::field8];
+  core::List<core::Null?>* local1i = <core::Null?>[null];
+  core::Set<inf::C<dynamic>*>* local2a = let final core::Set<inf::C<dynamic>*>* #t1 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final dynamic #t2 = #t1.{core::Set::add}(inf::field1) in let final dynamic #t3 = #t1.{core::Set::add}(null) in #t1;
+  core::Set<inf::C<dynamic>*>* local2b = let final core::Set<inf::C<dynamic>*>* #t4 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final dynamic #t5 = #t4.{core::Set::add}(inf::field2) in let final dynamic #t6 = #t4.{core::Set::add}(null) in #t4;
+  core::Set<inf::C<core::int*>*>* local2c = let final core::Set<inf::C<core::int*>*>* #t7 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t8 = #t7.{core::Set::add}(inf::field3) in let final dynamic #t9 = #t7.{core::Set::add}(null) in #t7;
+  core::Set<inf::C<core::int*>*>* local2d = let final core::Set<inf::C<core::int*>*>* #t10 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t11 = #t10.{core::Set::add}(inf::field4) in let final dynamic #t12 = #t10.{core::Set::add}(null) in #t10;
+  core::Set<inf::C<core::int*>*>* local2e = let final core::Set<inf::C<core::int*>*>* #t13 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t14 = #t13.{core::Set::add}(inf::field5) in let final dynamic #t15 = #t13.{core::Set::add}(null) in #t13;
+  core::Set<inf::C<core::int*>*>* local2f = let final core::Set<inf::C<core::int*>*>* #t16 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t17 = #t16.{core::Set::add}(inf::field6) in let final dynamic #t18 = #t16.{core::Set::add}(null) in #t16;
+  core::Set<core::int*>* local2g = let final core::Set<core::int*>* #t19 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t20 = #t19.{core::Set::add}(inf::field7) in let final dynamic #t21 = #t19.{core::Set::add}(null) in #t19;
+  core::Set<core::int*>* local2h = let final core::Set<core::int*>* #t22 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t23 = #t22.{core::Set::add}(inf::field8) in let final dynamic #t24 = #t22.{core::Set::add}(null) in #t22;
+  core::Set<inf::C<dynamic>*>* local3a = let final core::Set<inf::C<dynamic>*>* #t25 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final dynamic #t26 = #t25.{core::Set::add}(null) in let final dynamic #t27 = #t25.{core::Set::add}(inf::field1) in #t25;
+  core::Set<inf::C<dynamic>*>* local3b = let final core::Set<inf::C<dynamic>*>* #t28 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final dynamic #t29 = #t28.{core::Set::add}(null) in let final dynamic #t30 = #t28.{core::Set::add}(inf::field2) in #t28;
+  core::Set<inf::C<core::int*>*>* local3c = let final core::Set<inf::C<core::int*>*>* #t31 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t32 = #t31.{core::Set::add}(null) in let final dynamic #t33 = #t31.{core::Set::add}(inf::field3) in #t31;
+  core::Set<inf::C<core::int*>*>* local3d = let final core::Set<inf::C<core::int*>*>* #t34 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t35 = #t34.{core::Set::add}(null) in let final dynamic #t36 = #t34.{core::Set::add}(inf::field4) in #t34;
+  core::Set<inf::C<core::int*>*>* local3e = let final core::Set<inf::C<core::int*>*>* #t37 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t38 = #t37.{core::Set::add}(null) in let final dynamic #t39 = #t37.{core::Set::add}(inf::field5) in #t37;
+  core::Set<inf::C<core::int*>*>* local3f = let final core::Set<inf::C<core::int*>*>* #t40 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final dynamic #t41 = #t40.{core::Set::add}(null) in let final dynamic #t42 = #t40.{core::Set::add}(inf::field6) in #t40;
+  core::Set<core::int*>* local3g = let final core::Set<core::int*>* #t43 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t44 = #t43.{core::Set::add}(null) in let final dynamic #t45 = #t43.{core::Set::add}(inf::field7) in #t43;
+  core::Set<core::int*>* local3h = let final core::Set<core::int*>* #t46 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t47 = #t46.{core::Set::add}(null) in let final dynamic #t48 = #t46.{core::Set::add}(inf::field8) in #t46;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:11:9: Warning: Field 'field5' isn't initialized and its type 'C<int?>' doesn't allow null.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart'.
+// C<int?> field5;
+//         ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:13:5: Warning: Field 'field7' isn't initialized and its type 'int' doesn't allow null.
+// int field7;
+//     ^^^^^^
+//
+import self as inf;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → inf::C<inf::C::T%>
+    : super core::Object::•()
+    ;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → inf::B
+    : super core::Object::•()
+    ;
+  abstract method bar<X extends core::List<core::int?>? = core::List<core::int?>?>() → inf::B::bar::X%;
+  abstract method foo(core::List<core::int> list) → dynamic;
+}
+static field inf::C<dynamic> field1 = new inf::C::•<dynamic>();
+static field inf::C<dynamic>? field2;
+static field inf::C<core::int> field3 = new inf::C::•<core::int>();
+static field inf::C<core::int>? field4;
+static field inf::C<core::int?> field5;
+static field inf::C<core::int?>? field6;
+static field core::int field7;
+static field core::int? field8;
+static method method() → dynamic {
+  core::List<dynamic> local0 = <dynamic>[];
+  core::List<inf::C<dynamic>> local1a = <inf::C<dynamic>>[inf::field1];
+  core::List<inf::C<dynamic>?> local1b = <inf::C<dynamic>?>[inf::field2];
+  core::List<inf::C<core::int>> local1c = <inf::C<core::int>>[inf::field3];
+  core::List<inf::C<core::int>?> local1d = <inf::C<core::int>?>[inf::field4];
+  core::List<inf::C<core::int?>> local1e = <inf::C<core::int?>>[inf::field5];
+  core::List<inf::C<core::int?>?> local1f = <inf::C<core::int?>?>[inf::field6];
+  core::List<core::int> local1g = <core::int>[inf::field7];
+  core::List<core::int?> local1h = <core::int?>[inf::field8];
+  core::List<core::Null?> local1i = <core::Null?>[null];
+  core::Set<inf::C<dynamic>?> local2a = let final core::Set<inf::C<dynamic>?> #t49 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final dynamic #t50 = #t49.{core::Set::add}(inf::field1) in let final dynamic #t51 = #t49.{core::Set::add}(null) in #t49;
+  core::Set<inf::C<dynamic>?> local2b = let final core::Set<inf::C<dynamic>?> #t52 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final dynamic #t53 = #t52.{core::Set::add}(inf::field2) in let final dynamic #t54 = #t52.{core::Set::add}(null) in #t52;
+  core::Set<inf::C<core::int>?> local2c = let final core::Set<inf::C<core::int>?> #t55 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final dynamic #t56 = #t55.{core::Set::add}(inf::field3) in let final dynamic #t57 = #t55.{core::Set::add}(null) in #t55;
+  core::Set<inf::C<core::int>?> local2d = let final core::Set<inf::C<core::int>?> #t58 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final dynamic #t59 = #t58.{core::Set::add}(inf::field4) in let final dynamic #t60 = #t58.{core::Set::add}(null) in #t58;
+  core::Set<inf::C<core::int?>?> local2e = let final core::Set<inf::C<core::int?>?> #t61 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final dynamic #t62 = #t61.{core::Set::add}(inf::field5) in let final dynamic #t63 = #t61.{core::Set::add}(null) in #t61;
+  core::Set<inf::C<core::int?>?> local2f = let final core::Set<inf::C<core::int?>?> #t64 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final dynamic #t65 = #t64.{core::Set::add}(inf::field6) in let final dynamic #t66 = #t64.{core::Set::add}(null) in #t64;
+  core::Set<core::int?> local2g = let final core::Set<core::int?> #t67 = col::LinkedHashSet::•<core::int?>() in let final dynamic #t68 = #t67.{core::Set::add}(inf::field7) in let final dynamic #t69 = #t67.{core::Set::add}(null) in #t67;
+  core::Set<core::int?> local2h = let final core::Set<core::int?> #t70 = col::LinkedHashSet::•<core::int?>() in let final dynamic #t71 = #t70.{core::Set::add}(inf::field8) in let final dynamic #t72 = #t70.{core::Set::add}(null) in #t70;
+  core::Set<inf::C<dynamic>?> local3a = let final core::Set<inf::C<dynamic>?> #t73 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final dynamic #t74 = #t73.{core::Set::add}(null) in let final dynamic #t75 = #t73.{core::Set::add}(inf::field1) in #t73;
+  core::Set<inf::C<dynamic>?> local3b = let final core::Set<inf::C<dynamic>?> #t76 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final dynamic #t77 = #t76.{core::Set::add}(null) in let final dynamic #t78 = #t76.{core::Set::add}(inf::field2) in #t76;
+  core::Set<inf::C<core::int>?> local3c = let final core::Set<inf::C<core::int>?> #t79 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final dynamic #t80 = #t79.{core::Set::add}(null) in let final dynamic #t81 = #t79.{core::Set::add}(inf::field3) in #t79;
+  core::Set<inf::C<core::int>?> local3d = let final core::Set<inf::C<core::int>?> #t82 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final dynamic #t83 = #t82.{core::Set::add}(null) in let final dynamic #t84 = #t82.{core::Set::add}(inf::field4) in #t82;
+  core::Set<inf::C<core::int?>?> local3e = let final core::Set<inf::C<core::int?>?> #t85 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final dynamic #t86 = #t85.{core::Set::add}(null) in let final dynamic #t87 = #t85.{core::Set::add}(inf::field5) in #t85;
+  core::Set<inf::C<core::int?>?> local3f = let final core::Set<inf::C<core::int?>?> #t88 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final dynamic #t89 = #t88.{core::Set::add}(null) in let final dynamic #t90 = #t88.{core::Set::add}(inf::field6) in #t88;
+  core::Set<core::int?> local3g = let final core::Set<core::int?> #t91 = col::LinkedHashSet::•<core::int?>() in let final dynamic #t92 = #t91.{core::Set::add}(null) in let final dynamic #t93 = #t91.{core::Set::add}(inf::field7) in #t91;
+  core::Set<core::int?> local3h = let final core::Set<core::int?> #t94 = col::LinkedHashSet::•<core::int?>() in let final dynamic #t95 = #t94.{core::Set::add}(null) in let final dynamic #t96 = #t94.{core::Set::add}(inf::field8) in #t94;
+}
diff --git a/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.weak.transformed.expect
new file mode 100644
index 0000000..81342ac
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in.dart.weak.transformed.expect
@@ -0,0 +1,110 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "infer_constraints_from_opt_in_lib.dart" as inf;
+import "dart:collection" as col;
+
+import "org-dartlang-testcase:///infer_constraints_from_opt_in_lib.dart";
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  method baz(inf::B* b) → dynamic {
+    b.{inf::B::foo}(b.{inf::B::bar}<core::List<core::int*>*>());
+  }
+}
+static method main() → dynamic {
+  core::List<dynamic>* local0 = <dynamic>[];
+  core::List<inf::C<dynamic>*>* local1a = <inf::C<dynamic>*>[inf::field1];
+  core::List<inf::C<dynamic>*>* local1b = <inf::C<dynamic>*>[inf::field2];
+  core::List<inf::C<core::int*>*>* local1c = <inf::C<core::int*>*>[inf::field3];
+  core::List<inf::C<core::int*>*>* local1d = <inf::C<core::int*>*>[inf::field4];
+  core::List<inf::C<core::int*>*>* local1e = <inf::C<core::int*>*>[inf::field5];
+  core::List<inf::C<core::int*>*>* local1f = <inf::C<core::int*>*>[inf::field6];
+  core::List<core::int*>* local1g = <core::int*>[inf::field7];
+  core::List<core::int*>* local1h = <core::int*>[inf::field8];
+  core::List<core::Null?>* local1i = <core::Null?>[null];
+  core::Set<inf::C<dynamic>*>* local2a = let final core::Set<inf::C<dynamic>*>* #t1 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final core::bool* #t2 = #t1.{core::Set::add}(inf::field1) in let final core::bool* #t3 = #t1.{core::Set::add}(null) in #t1;
+  core::Set<inf::C<dynamic>*>* local2b = let final core::Set<inf::C<dynamic>*>* #t4 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final core::bool* #t5 = #t4.{core::Set::add}(inf::field2) in let final core::bool* #t6 = #t4.{core::Set::add}(null) in #t4;
+  core::Set<inf::C<core::int*>*>* local2c = let final core::Set<inf::C<core::int*>*>* #t7 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t8 = #t7.{core::Set::add}(inf::field3) in let final core::bool* #t9 = #t7.{core::Set::add}(null) in #t7;
+  core::Set<inf::C<core::int*>*>* local2d = let final core::Set<inf::C<core::int*>*>* #t10 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t11 = #t10.{core::Set::add}(inf::field4) in let final core::bool* #t12 = #t10.{core::Set::add}(null) in #t10;
+  core::Set<inf::C<core::int*>*>* local2e = let final core::Set<inf::C<core::int*>*>* #t13 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t14 = #t13.{core::Set::add}(inf::field5) in let final core::bool* #t15 = #t13.{core::Set::add}(null) in #t13;
+  core::Set<inf::C<core::int*>*>* local2f = let final core::Set<inf::C<core::int*>*>* #t16 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t17 = #t16.{core::Set::add}(inf::field6) in let final core::bool* #t18 = #t16.{core::Set::add}(null) in #t16;
+  core::Set<core::int*>* local2g = let final core::Set<core::int*>* #t19 = col::LinkedHashSet::•<core::int*>() in let final core::bool* #t20 = #t19.{core::Set::add}(inf::field7) in let final core::bool* #t21 = #t19.{core::Set::add}(null) in #t19;
+  core::Set<core::int*>* local2h = let final core::Set<core::int*>* #t22 = col::LinkedHashSet::•<core::int*>() in let final core::bool* #t23 = #t22.{core::Set::add}(inf::field8) in let final core::bool* #t24 = #t22.{core::Set::add}(null) in #t22;
+  core::Set<inf::C<dynamic>*>* local3a = let final core::Set<inf::C<dynamic>*>* #t25 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final core::bool* #t26 = #t25.{core::Set::add}(null) in let final core::bool* #t27 = #t25.{core::Set::add}(inf::field1) in #t25;
+  core::Set<inf::C<dynamic>*>* local3b = let final core::Set<inf::C<dynamic>*>* #t28 = col::LinkedHashSet::•<inf::C<dynamic>*>() in let final core::bool* #t29 = #t28.{core::Set::add}(null) in let final core::bool* #t30 = #t28.{core::Set::add}(inf::field2) in #t28;
+  core::Set<inf::C<core::int*>*>* local3c = let final core::Set<inf::C<core::int*>*>* #t31 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t32 = #t31.{core::Set::add}(null) in let final core::bool* #t33 = #t31.{core::Set::add}(inf::field3) in #t31;
+  core::Set<inf::C<core::int*>*>* local3d = let final core::Set<inf::C<core::int*>*>* #t34 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t35 = #t34.{core::Set::add}(null) in let final core::bool* #t36 = #t34.{core::Set::add}(inf::field4) in #t34;
+  core::Set<inf::C<core::int*>*>* local3e = let final core::Set<inf::C<core::int*>*>* #t37 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t38 = #t37.{core::Set::add}(null) in let final core::bool* #t39 = #t37.{core::Set::add}(inf::field5) in #t37;
+  core::Set<inf::C<core::int*>*>* local3f = let final core::Set<inf::C<core::int*>*>* #t40 = col::LinkedHashSet::•<inf::C<core::int*>*>() in let final core::bool* #t41 = #t40.{core::Set::add}(null) in let final core::bool* #t42 = #t40.{core::Set::add}(inf::field6) in #t40;
+  core::Set<core::int*>* local3g = let final core::Set<core::int*>* #t43 = col::LinkedHashSet::•<core::int*>() in let final core::bool* #t44 = #t43.{core::Set::add}(null) in let final core::bool* #t45 = #t43.{core::Set::add}(inf::field7) in #t43;
+  core::Set<core::int*>* local3h = let final core::Set<core::int*>* #t46 = col::LinkedHashSet::•<core::int*>() in let final core::bool* #t47 = #t46.{core::Set::add}(null) in let final core::bool* #t48 = #t46.{core::Set::add}(inf::field8) in #t46;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:11:9: Warning: Field 'field5' isn't initialized and its type 'C<int?>' doesn't allow null.
+//  - 'C' is from 'pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart'.
+// C<int?> field5;
+//         ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart:13:5: Warning: Field 'field7' isn't initialized and its type 'int' doesn't allow null.
+// int field7;
+//     ^^^^^^
+//
+import self as inf;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → inf::C<inf::C::T%>
+    : super core::Object::•()
+    ;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → inf::B
+    : super core::Object::•()
+    ;
+  abstract method bar<X extends core::List<core::int?>? = core::List<core::int?>?>() → inf::B::bar::X%;
+  abstract method foo(core::List<core::int> list) → dynamic;
+}
+static field inf::C<dynamic> field1 = new inf::C::•<dynamic>();
+static field inf::C<dynamic>? field2;
+static field inf::C<core::int> field3 = new inf::C::•<core::int>();
+static field inf::C<core::int>? field4;
+static field inf::C<core::int?> field5;
+static field inf::C<core::int?>? field6;
+static field core::int field7;
+static field core::int? field8;
+static method method() → dynamic {
+  core::List<dynamic> local0 = <dynamic>[];
+  core::List<inf::C<dynamic>> local1a = <inf::C<dynamic>>[inf::field1];
+  core::List<inf::C<dynamic>?> local1b = <inf::C<dynamic>?>[inf::field2];
+  core::List<inf::C<core::int>> local1c = <inf::C<core::int>>[inf::field3];
+  core::List<inf::C<core::int>?> local1d = <inf::C<core::int>?>[inf::field4];
+  core::List<inf::C<core::int?>> local1e = <inf::C<core::int?>>[inf::field5];
+  core::List<inf::C<core::int?>?> local1f = <inf::C<core::int?>?>[inf::field6];
+  core::List<core::int> local1g = <core::int>[inf::field7];
+  core::List<core::int?> local1h = <core::int?>[inf::field8];
+  core::List<core::Null?> local1i = <core::Null?>[null];
+  core::Set<inf::C<dynamic>?> local2a = let final core::Set<inf::C<dynamic>?> #t49 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final core::bool* #t50 = #t49.{core::Set::add}(inf::field1) in let final core::bool* #t51 = #t49.{core::Set::add}(null) in #t49;
+  core::Set<inf::C<dynamic>?> local2b = let final core::Set<inf::C<dynamic>?> #t52 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final core::bool* #t53 = #t52.{core::Set::add}(inf::field2) in let final core::bool* #t54 = #t52.{core::Set::add}(null) in #t52;
+  core::Set<inf::C<core::int>?> local2c = let final core::Set<inf::C<core::int>?> #t55 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final core::bool* #t56 = #t55.{core::Set::add}(inf::field3) in let final core::bool* #t57 = #t55.{core::Set::add}(null) in #t55;
+  core::Set<inf::C<core::int>?> local2d = let final core::Set<inf::C<core::int>?> #t58 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final core::bool* #t59 = #t58.{core::Set::add}(inf::field4) in let final core::bool* #t60 = #t58.{core::Set::add}(null) in #t58;
+  core::Set<inf::C<core::int?>?> local2e = let final core::Set<inf::C<core::int?>?> #t61 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final core::bool* #t62 = #t61.{core::Set::add}(inf::field5) in let final core::bool* #t63 = #t61.{core::Set::add}(null) in #t61;
+  core::Set<inf::C<core::int?>?> local2f = let final core::Set<inf::C<core::int?>?> #t64 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final core::bool* #t65 = #t64.{core::Set::add}(inf::field6) in let final core::bool* #t66 = #t64.{core::Set::add}(null) in #t64;
+  core::Set<core::int?> local2g = let final core::Set<core::int?> #t67 = col::LinkedHashSet::•<core::int?>() in let final core::bool* #t68 = #t67.{core::Set::add}(inf::field7) in let final core::bool* #t69 = #t67.{core::Set::add}(null) in #t67;
+  core::Set<core::int?> local2h = let final core::Set<core::int?> #t70 = col::LinkedHashSet::•<core::int?>() in let final core::bool* #t71 = #t70.{core::Set::add}(inf::field8) in let final core::bool* #t72 = #t70.{core::Set::add}(null) in #t70;
+  core::Set<inf::C<dynamic>?> local3a = let final core::Set<inf::C<dynamic>?> #t73 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final core::bool* #t74 = #t73.{core::Set::add}(null) in let final core::bool* #t75 = #t73.{core::Set::add}(inf::field1) in #t73;
+  core::Set<inf::C<dynamic>?> local3b = let final core::Set<inf::C<dynamic>?> #t76 = col::LinkedHashSet::•<inf::C<dynamic>?>() in let final core::bool* #t77 = #t76.{core::Set::add}(null) in let final core::bool* #t78 = #t76.{core::Set::add}(inf::field2) in #t76;
+  core::Set<inf::C<core::int>?> local3c = let final core::Set<inf::C<core::int>?> #t79 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final core::bool* #t80 = #t79.{core::Set::add}(null) in let final core::bool* #t81 = #t79.{core::Set::add}(inf::field3) in #t79;
+  core::Set<inf::C<core::int>?> local3d = let final core::Set<inf::C<core::int>?> #t82 = col::LinkedHashSet::•<inf::C<core::int>?>() in let final core::bool* #t83 = #t82.{core::Set::add}(null) in let final core::bool* #t84 = #t82.{core::Set::add}(inf::field4) in #t82;
+  core::Set<inf::C<core::int?>?> local3e = let final core::Set<inf::C<core::int?>?> #t85 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final core::bool* #t86 = #t85.{core::Set::add}(null) in let final core::bool* #t87 = #t85.{core::Set::add}(inf::field5) in #t85;
+  core::Set<inf::C<core::int?>?> local3f = let final core::Set<inf::C<core::int?>?> #t88 = col::LinkedHashSet::•<inf::C<core::int?>?>() in let final core::bool* #t89 = #t88.{core::Set::add}(null) in let final core::bool* #t90 = #t88.{core::Set::add}(inf::field6) in #t88;
+  core::Set<core::int?> local3g = let final core::Set<core::int?> #t91 = col::LinkedHashSet::•<core::int?>() in let final core::bool* #t92 = #t91.{core::Set::add}(null) in let final core::bool* #t93 = #t91.{core::Set::add}(inf::field7) in #t91;
+  core::Set<core::int?> local3h = let final core::Set<core::int?> #t94 = col::LinkedHashSet::•<core::int?>() in let final core::bool* #t95 = #t94.{core::Set::add}(null) in let final core::bool* #t96 = #t94.{core::Set::add}(inf::field8) in #t94;
+}
diff --git a/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart
new file mode 100644
index 0000000..079a96e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_constraints_from_opt_in_lib.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C<T> {}
+
+C field1 = new C();
+C? field2;
+C<int> field3 = new C<int>();
+C<int>? field4;
+C<int?> field5;
+C<int?>? field6;
+int field7;
+int? field8;
+
+method() {
+  var local0 = [];
+  var local1a = [field1];
+  var local1b = [field2];
+  var local1c = [field3];
+  var local1d = [field4];
+  var local1e = [field5];
+  var local1f = [field6];
+  var local1g = [field7];
+  var local1h = [field8];
+  var local1i = [null];
+  var local2a = {field1, null};
+  var local2b = {field2, null};
+  var local2c = {field3, null};
+  var local2d = {field4, null};
+  var local2e = {field5, null};
+  var local2f = {field6, null};
+  var local2g = {field7, null};
+  var local2h = {field8, null};
+  var local3a = {null, field1};
+  var local3b = {null, field2};
+  var local3c = {null, field3};
+  var local3d = {null, field4};
+  var local3e = {null, field5};
+  var local3f = {null, field6};
+  var local3g = {null, field7};
+  var local3h = {null, field8};
+}
+
+abstract class B {
+  X bar<X extends List<int?>?>();
+  foo(List<int> list);
+}
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart b/pkg/front_end/testcases/nnbd/infer_method_types.dart
new file mode 100644
index 0000000..4cb5df23
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A {
+  Object? m(covariant int a);
+}
+
+abstract class B {
+  dynamic m(covariant num a);
+}
+
+abstract class C {
+  void m(num a);
+}
+
+abstract class D implements A {
+  Object? m(int a);
+}
+
+abstract class E implements B {
+  dynamic m(num a);
+}
+
+abstract class F {
+  Object? m(int a);
+}
+
+abstract class G implements C {
+  m(a);
+}
+
+abstract class H implements D, E, F, C {}
+
+abstract class I implements D {
+  m(a);
+}
+
+abstract class J implements H {
+  m(a);
+}
+
+abstract class K implements I, E, G {}
+
+abstract class L implements K {
+  m(a);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.outline.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.outline.expect
new file mode 100644
index 0000000..5f8c4b8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.outline.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → self::B
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class C extends core::Object {
+  synthetic constructor •() → self::C
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class D extends core::Object implements self::A {
+  synthetic constructor •() → self::D
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class F extends core::Object {
+  synthetic constructor •() → self::F
+    ;
+  abstract method m(core::int a) → core::Object?;
+}
+abstract class G extends core::Object implements self::C {
+  synthetic constructor •() → self::G
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class H extends core::Object implements self::D, self::E, self::F, self::C {
+  synthetic constructor •() → self::H
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class I extends core::Object implements self::D {
+  synthetic constructor •() → self::I
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class J extends core::Object implements self::H {
+  synthetic constructor •() → self::J
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+abstract class K extends core::Object implements self::I, self::E, self::G {
+  synthetic constructor •() → self::K
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class L extends core::Object implements self::K {
+  synthetic constructor •() → self::L
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.expect
new file mode 100644
index 0000000..cc03fc1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class D extends core::Object implements self::A {
+  synthetic constructor •() → self::D
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class F extends core::Object {
+  synthetic constructor •() → self::F
+    : super core::Object::•()
+    ;
+  abstract method m(core::int a) → core::Object?;
+}
+abstract class G extends core::Object implements self::C {
+  synthetic constructor •() → self::G
+    : super core::Object::•()
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class H extends core::Object implements self::D, self::E, self::F, self::C {
+  synthetic constructor •() → self::H
+    : super core::Object::•()
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class I extends core::Object implements self::D {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class J extends core::Object implements self::H {
+  synthetic constructor •() → self::J
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+abstract class K extends core::Object implements self::I, self::E, self::G {
+  synthetic constructor •() → self::K
+    : super core::Object::•()
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class L extends core::Object implements self::K {
+  synthetic constructor •() → self::L
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.transformed.expect
new file mode 100644
index 0000000..cc03fc1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.strong.transformed.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class D extends core::Object implements self::A {
+  synthetic constructor •() → self::D
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class F extends core::Object {
+  synthetic constructor •() → self::F
+    : super core::Object::•()
+    ;
+  abstract method m(core::int a) → core::Object?;
+}
+abstract class G extends core::Object implements self::C {
+  synthetic constructor •() → self::G
+    : super core::Object::•()
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class H extends core::Object implements self::D, self::E, self::F, self::C {
+  synthetic constructor •() → self::H
+    : super core::Object::•()
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class I extends core::Object implements self::D {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class J extends core::Object implements self::H {
+  synthetic constructor •() → self::J
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+abstract class K extends core::Object implements self::I, self::E, self::G {
+  synthetic constructor •() → self::K
+    : super core::Object::•()
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class L extends core::Object implements self::K {
+  synthetic constructor •() → self::L
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.expect
new file mode 100644
index 0000000..cc03fc1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class D extends core::Object implements self::A {
+  synthetic constructor •() → self::D
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class F extends core::Object {
+  synthetic constructor •() → self::F
+    : super core::Object::•()
+    ;
+  abstract method m(core::int a) → core::Object?;
+}
+abstract class G extends core::Object implements self::C {
+  synthetic constructor •() → self::G
+    : super core::Object::•()
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class H extends core::Object implements self::D, self::E, self::F, self::C {
+  synthetic constructor •() → self::H
+    : super core::Object::•()
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class I extends core::Object implements self::D {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class J extends core::Object implements self::H {
+  synthetic constructor •() → self::J
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+abstract class K extends core::Object implements self::I, self::E, self::G {
+  synthetic constructor •() → self::K
+    : super core::Object::•()
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class L extends core::Object implements self::K {
+  synthetic constructor •() → self::L
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.transformed.expect
new file mode 100644
index 0000000..cc03fc1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_method_types.dart.weak.transformed.expect
@@ -0,0 +1,77 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class C extends core::Object {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class D extends core::Object implements self::A {
+  synthetic constructor •() → self::D
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class E extends core::Object implements self::B {
+  synthetic constructor •() → self::E
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → dynamic;
+}
+abstract class F extends core::Object {
+  synthetic constructor •() → self::F
+    : super core::Object::•()
+    ;
+  abstract method m(core::int a) → core::Object?;
+}
+abstract class G extends core::Object implements self::C {
+  synthetic constructor •() → self::G
+    : super core::Object::•()
+    ;
+  abstract method m(core::num a) → void;
+}
+abstract class H extends core::Object implements self::D, self::E, self::F, self::C {
+  synthetic constructor •() → self::H
+    : super core::Object::•()
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class I extends core::Object implements self::D {
+  synthetic constructor •() → self::I
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::int a) → core::Object?;
+}
+abstract class J extends core::Object implements self::H {
+  synthetic constructor •() → self::J
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+abstract class K extends core::Object implements self::I, self::E, self::G {
+  synthetic constructor •() → self::K
+    : super core::Object::•()
+    ;
+  abstract forwarding-stub member-signature method m(covariant core::num a) → void;
+}
+abstract class L extends core::Object implements self::K {
+  synthetic constructor •() → self::L
+    : super core::Object::•()
+    ;
+  abstract method m(covariant core::num a) → void;
+}
+static method main() → dynamic {}
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
index dafa598..0871a1c 100644
--- 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
@@ -72,7 +72,7 @@
   synthetic constructor •() → inh::LegacyClass5<inh::LegacyClass5::T*>*
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -85,7 +85,7 @@
   synthetic constructor •() → inh::LegacyClass7<inh::LegacyClass7::T*>*
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
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
index 8706c95..e7d6af8 100644
--- 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
@@ -86,7 +86,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -101,7 +101,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.transformed.expect
index 187a284..4fdfac4 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.strong.transformed.expect
@@ -86,7 +86,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -101,7 +101,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.expect
index 8706c95..e7d6af8 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.expect
@@ -86,7 +86,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -101,7 +101,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin*/  {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> = core::Object with inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.transformed.expect
index 187a284..4fdfac4 100644
--- a/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/inheritance_from_opt_out.dart.weak.transformed.expect
@@ -86,7 +86,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _LegacyClass6&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass6&Object&LegacyClass3<inh::_LegacyClass6&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
@@ -101,7 +101,7 @@
     : super inh::LegacyClass3::•()
     ;
 }
-abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _LegacyClass8&Object&LegacyClass3<T extends core::Object* = dynamic> extends core::Object implements inh::LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*> /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → inh::_LegacyClass8&Object&LegacyClass3<inh::_LegacyClass8&Object&LegacyClass3::T*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.outline.expect
index 33cec59..82e41a4 100644
--- a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.outline.expect
@@ -5,12 +5,12 @@
 
 import "org-dartlang-testcase:///issue40512_lib.dart";
 
-abstract class _C&Object&A = core::Object with baz2::A /*isAnonymousMixin*/  {
+abstract class _C&Object&A = core::Object with baz2::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&A&B = self::_C&Object&A with baz2::B /*isAnonymousMixin*/  {
+abstract class _C&Object&A&B = self::_C&Object&A with baz2::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.strong.expect
index c6d5ee1..125f1c6 100644
--- a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.strong.expect
@@ -5,12 +5,12 @@
 
 import "org-dartlang-testcase:///issue40512_lib.dart";
 
-abstract class _C&Object&A = core::Object with baz2::A /*isAnonymousMixin*/  {
+abstract class _C&Object&A = core::Object with baz2::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&A&B = self::_C&Object&A with baz2::B /*isAnonymousMixin*/  {
+abstract class _C&Object&A&B = self::_C&Object&A with baz2::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.strong.transformed.expect
index d3a7004..134d5ef 100644
--- a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.strong.transformed.expect
@@ -5,14 +5,14 @@
 
 import "org-dartlang-testcase:///issue40512_lib.dart";
 
-abstract class _C&Object&A extends core::Object implements baz2::A /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&A extends core::Object implements baz2::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
   method /* from org-dartlang-testcase:///issue40512_lib.dart */ toString({core::String* s = #C1}) → core::String*
     return s;
 }
-abstract class _C&Object&A&B extends self::_C&Object&A implements baz2::B /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&A&B extends self::_C&Object&A implements baz2::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.weak.expect
index c6d5ee1..125f1c6 100644
--- a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.weak.expect
@@ -5,12 +5,12 @@
 
 import "org-dartlang-testcase:///issue40512_lib.dart";
 
-abstract class _C&Object&A = core::Object with baz2::A /*isAnonymousMixin*/  {
+abstract class _C&Object&A = core::Object with baz2::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
 }
-abstract class _C&Object&A&B = self::_C&Object&A with baz2::B /*isAnonymousMixin*/  {
+abstract class _C&Object&A&B = self::_C&Object&A with baz2::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.weak.transformed.expect
index d3a7004..134d5ef 100644
--- a/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue40512/issue40512_lib.dart.weak.transformed.expect
@@ -5,14 +5,14 @@
 
 import "org-dartlang-testcase:///issue40512_lib.dart";
 
-abstract class _C&Object&A extends core::Object implements baz2::A /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&A extends core::Object implements baz2::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A*
     : super core::Object::•()
     ;
   method /* from org-dartlang-testcase:///issue40512_lib.dart */ toString({core::String* s = #C1}) → core::String*
     return s;
 }
-abstract class _C&Object&A&B extends self::_C&Object&A implements baz2::B /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&A&B extends self::_C&Object&A implements baz2::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&A&B*
     : super self::_C&Object&A::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/issue40805.dart b/pkg/front_end/testcases/nnbd/issue40805.dart
new file mode 100644
index 0000000..9f68135
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40805.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  D().x = 3.14;
+}
+
+class C {
+  covariant late final int x;
+}
+
+class D extends C {
+  set x(num value) { super.x = value.toInt(); }
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd/issue40805.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue40805.dart.outline.expect
new file mode 100644
index 0000000..260c576
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40805.dart.outline.expect
@@ -0,0 +1,17 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  late covariant final [setter] field core::int x;
+  synthetic constructor •() → self::C
+    ;
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    ;
+  set x(covariant core::num value) → void
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue40805.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue40805.dart.strong.expect
new file mode 100644
index 0000000..12e6ed1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40805.dart.strong.expect
@@ -0,0 +1,21 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  late covariant final [setter] field core::int x;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  set x(covariant core::num value) → void {
+    super.{self::C::x} = value.{core::num::toInt}();
+  }
+}
+static method main() → dynamic {
+  new self::D::•().{self::D::x} = 3.14;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue40805.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue40805.dart.strong.transformed.expect
new file mode 100644
index 0000000..12e6ed1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40805.dart.strong.transformed.expect
@@ -0,0 +1,21 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  late covariant final [setter] field core::int x;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  set x(covariant core::num value) → void {
+    super.{self::C::x} = value.{core::num::toInt}();
+  }
+}
+static method main() → dynamic {
+  new self::D::•().{self::D::x} = 3.14;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue40805.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue40805.dart.weak.expect
new file mode 100644
index 0000000..12e6ed1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40805.dart.weak.expect
@@ -0,0 +1,21 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  late covariant final [setter] field core::int x;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  set x(covariant core::num value) → void {
+    super.{self::C::x} = value.{core::num::toInt}();
+  }
+}
+static method main() → dynamic {
+  new self::D::•().{self::D::x} = 3.14;
+}
diff --git a/pkg/front_end/testcases/nnbd/issue40805.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue40805.dart.weak.transformed.expect
new file mode 100644
index 0000000..12e6ed1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40805.dart.weak.transformed.expect
@@ -0,0 +1,21 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  late covariant final [setter] field core::int x;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends self::C {
+  synthetic constructor •() → self::D
+    : super self::C::•()
+    ;
+  set x(covariant core::num value) → void {
+    super.{self::C::x} = value.{core::num::toInt}();
+  }
+}
+static method main() → dynamic {
+  new self::D::•().{self::D::x} = 3.14;
+}
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect
index 331438b..da71c66 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.outline.expect
@@ -46,31 +46,31 @@
     ;
   set property4(core::int* value) → void
     ;
-  abstract member-signature get property6() → core::int*;
-  abstract member-signature get getter1() → core::int*;
-  abstract member-signature get field1() → core::int*;
-  abstract member-signature get field2() → core::int*;
-  abstract member-signature get getter2() → core::int*;
-  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
-  abstract member-signature method method9a(core::int* a, {core::int* b}) → core::int*;
-  abstract member-signature method method5c([core::int* a, core::int* b]) → core::int*;
-  abstract member-signature get property5() → core::int*;
-  abstract member-signature method method2() → core::int*;
-  abstract member-signature method method7a(core::int* a, {core::int* b}) → core::int*;
-  abstract member-signature method method5b(core::int* a, [core::int* b]) → core::int*;
-  abstract member-signature method method9b({core::int* a, core::int* b}) → core::int*;
   abstract member-signature method method1() → core::int*;
-  abstract member-signature get property1() → core::int*;
-  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b]) → core::int*;
+  abstract member-signature method method5c([core::int* a, core::int* b]) → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b}) → core::int*;
   abstract member-signature method method7b({core::int* a, core::int* b}) → core::int*;
-  abstract member-signature set setter1(core::int* value) → void;
-  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature method method9a(core::int* a, {core::int* b}) → core::int*;
+  abstract member-signature method method9b({core::int* a, core::int* b}) → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature get field1() → core::int*;
   abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature get field2() → core::int*;
   abstract member-signature set field2(core::int* _) → void;
-  abstract member-signature set property5(core::int* _) → void;
-  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature get property1() → core::int*;
   abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature get property2() → core::int*;
   abstract member-signature set property2(core::int* value) → void;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set setter2(core::int* value) → void;
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect
index a926f8b..f993fb1 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.expect
@@ -43,31 +43,31 @@
   get property4() → core::int*
     return 0;
   set property4(core::int* value) → void {}
-  abstract member-signature get property6() → core::int*;
-  abstract member-signature get getter1() → core::int*;
-  abstract member-signature get field1() → core::int*;
-  abstract member-signature get field2() → core::int*;
-  abstract member-signature get getter2() → core::int*;
-  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
-  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
-  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
-  abstract member-signature get property5() → core::int*;
-  abstract member-signature method method2() → core::int*;
-  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
-  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
-  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
   abstract member-signature method method1() → core::int*;
-  abstract member-signature get property1() → core::int*;
-  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
   abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*;
-  abstract member-signature set setter1(core::int* value) → void;
-  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature get field1() → core::int*;
   abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature get field2() → core::int*;
   abstract member-signature set field2(core::int* _) → void;
-  abstract member-signature set property5(core::int* _) → void;
-  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature get property1() → core::int*;
   abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature get property2() → core::int*;
   abstract member-signature set property2(core::int* value) → void;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set setter2(core::int* value) → void;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect
index a926f8b..f993fb1 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.strong.transformed.expect
@@ -43,31 +43,31 @@
   get property4() → core::int*
     return 0;
   set property4(core::int* value) → void {}
-  abstract member-signature get property6() → core::int*;
-  abstract member-signature get getter1() → core::int*;
-  abstract member-signature get field1() → core::int*;
-  abstract member-signature get field2() → core::int*;
-  abstract member-signature get getter2() → core::int*;
-  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
-  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
-  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
-  abstract member-signature get property5() → core::int*;
-  abstract member-signature method method2() → core::int*;
-  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
-  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
-  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
   abstract member-signature method method1() → core::int*;
-  abstract member-signature get property1() → core::int*;
-  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
   abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*;
-  abstract member-signature set setter1(core::int* value) → void;
-  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature get field1() → core::int*;
   abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature get field2() → core::int*;
   abstract member-signature set field2(core::int* _) → void;
-  abstract member-signature set property5(core::int* _) → void;
-  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature get property1() → core::int*;
   abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature get property2() → core::int*;
   abstract member-signature set property2(core::int* value) → void;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set setter2(core::int* value) → void;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect
index a926f8b..f993fb1 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.expect
@@ -43,31 +43,31 @@
   get property4() → core::int*
     return 0;
   set property4(core::int* value) → void {}
-  abstract member-signature get property6() → core::int*;
-  abstract member-signature get getter1() → core::int*;
-  abstract member-signature get field1() → core::int*;
-  abstract member-signature get field2() → core::int*;
-  abstract member-signature get getter2() → core::int*;
-  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
-  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
-  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
-  abstract member-signature get property5() → core::int*;
-  abstract member-signature method method2() → core::int*;
-  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
-  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
-  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
   abstract member-signature method method1() → core::int*;
-  abstract member-signature get property1() → core::int*;
-  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
   abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*;
-  abstract member-signature set setter1(core::int* value) → void;
-  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature get field1() → core::int*;
   abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature get field2() → core::int*;
   abstract member-signature set field2(core::int* _) → void;
-  abstract member-signature set property5(core::int* _) → void;
-  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature get property1() → core::int*;
   abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature get property2() → core::int*;
   abstract member-signature set property2(core::int* value) → void;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set setter2(core::int* value) → void;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect
index a926f8b..f993fb1 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_in.dart.weak.transformed.expect
@@ -43,31 +43,31 @@
   get property4() → core::int*
     return 0;
   set property4(core::int* value) → void {}
-  abstract member-signature get property6() → core::int*;
-  abstract member-signature get getter1() → core::int*;
-  abstract member-signature get field1() → core::int*;
-  abstract member-signature get field2() → core::int*;
-  abstract member-signature get getter2() → core::int*;
-  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
-  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
-  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
-  abstract member-signature get property5() → core::int*;
-  abstract member-signature method method2() → core::int*;
-  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
-  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
-  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
   abstract member-signature method method1() → core::int*;
-  abstract member-signature get property1() → core::int*;
-  abstract member-signature get property2() → core::int*;
+  abstract member-signature method method2() → core::int*;
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*;
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*;
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*;
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*;
   abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*;
-  abstract member-signature set setter1(core::int* value) → void;
-  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*;
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*;
+  abstract member-signature get getter1() → core::int*;
+  abstract member-signature get getter2() → core::int*;
+  abstract member-signature get field1() → core::int*;
   abstract member-signature set field1(core::int* _) → void;
+  abstract member-signature get field2() → core::int*;
   abstract member-signature set field2(core::int* _) → void;
-  abstract member-signature set property5(core::int* _) → void;
-  abstract member-signature set setter2(core::int* value) → void;
+  abstract member-signature get property1() → core::int*;
   abstract member-signature set property1(core::int* value) → void;
+  abstract member-signature get property2() → core::int*;
   abstract member-signature set property2(core::int* value) → void;
+  abstract member-signature get property5() → core::int*;
+  abstract member-signature set property5(core::int* _) → void;
+  abstract member-signature get property6() → core::int*;
+  abstract member-signature set property6(core::int* _) → void;
+  abstract member-signature set setter1(core::int* value) → void;
+  abstract member-signature set setter2(core::int* value) → void;
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect
index bf466c5..96347ea 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.outline.expect
@@ -46,40 +46,40 @@
 class Class2a extends opt::LegacyClass implements self::Interface {
   synthetic constructor •() → self::Class2a
     ;
-  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
-  abstract member-signature method method4c([core::int? a, core::int? b]) → core::int?;
-  abstract member-signature get getter1() → core::int;
-  abstract member-signature get field1() → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature method method2() → core::int?;
   abstract member-signature method method3a(core::int a, core::int b) → core::int;
-  abstract member-signature get field4() → core::int?;
-  abstract member-signature get property3() → core::int;
-  abstract member-signature get field2() → core::int?;
-  abstract member-signature method method6a(core::int? a, {core::int? b}) → core::int?;
-  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b]) → core::int;
+  abstract member-signature method method3c([core::int a, core::int b]) → core::int;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4b(core::int? a, [core::int? b]) → core::int?;
+  abstract member-signature method method4c([core::int? a, core::int? b]) → core::int?;
   abstract member-signature method method5a(core::int a, {core::int b}) → core::int;
+  abstract member-signature method method5b({core::int a, core::int b}) → core::int;
   abstract member-signature method method5c({core::int a, core::int b}) → core::int;
-  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b}) → core::int?;
   abstract member-signature method method6b({core::int? a, core::int? b}) → core::int?;
   abstract member-signature method method6c({core::int? a, core::int? b}) → core::int?;
-  abstract member-signature method method2() → core::int?;
-  abstract member-signature method method5b({core::int a, core::int b}) → core::int;
-  abstract member-signature method method4b(core::int? a, [core::int? b]) → core::int?;
-  abstract member-signature get field3() → core::int;
-  abstract member-signature method method3c([core::int a, core::int b]) → core::int;
-  abstract member-signature method method1() → core::int;
-  abstract member-signature get property1() → core::int;
-  abstract member-signature get property2() → core::int?;
-  abstract member-signature method method3b(core::int a, [core::int b]) → core::int;
-  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature get field1() → core::int;
   abstract member-signature set field1(core::int _) → void;
-  abstract member-signature set field4(core::int? _) → void;
-  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get field2() → core::int?;
   abstract member-signature set field2(core::int? _) → void;
-  abstract member-signature set property4(core::int? value) → void;
-  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature get field3() → core::int;
   abstract member-signature set field3(core::int _) → void;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature get property1() → core::int;
   abstract member-signature set property1(core::int value) → void;
+  abstract member-signature get property2() → core::int?;
   abstract member-signature set property2(core::int? value) → void;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
 }
 class Class2b extends opt::LegacyClass implements self::Interface {
   field core::int field1;
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect
index 85e1534..b776417 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.expect
@@ -49,40 +49,40 @@
   synthetic constructor •() → self::Class2a
     : super opt::LegacyClass::•()
     ;
-  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
-  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
-  abstract member-signature get getter1() → core::int;
-  abstract member-signature get field1() → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature method method2() → core::int?;
   abstract member-signature method method3a(core::int a, core::int b) → core::int;
-  abstract member-signature get field4() → core::int?;
-  abstract member-signature get property3() → core::int;
-  abstract member-signature get field2() → core::int?;
-  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
-  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
   abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int;
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
   abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int;
-  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
   abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
   abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?;
-  abstract member-signature method method2() → core::int?;
-  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
-  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
-  abstract member-signature get field3() → core::int;
-  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
-  abstract member-signature method method1() → core::int;
-  abstract member-signature get property1() → core::int;
-  abstract member-signature get property2() → core::int?;
-  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
-  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature get field1() → core::int;
   abstract member-signature set field1(core::int _) → void;
-  abstract member-signature set field4(core::int? _) → void;
-  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get field2() → core::int?;
   abstract member-signature set field2(core::int? _) → void;
-  abstract member-signature set property4(core::int? value) → void;
-  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature get field3() → core::int;
   abstract member-signature set field3(core::int _) → void;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature get property1() → core::int;
   abstract member-signature set property1(core::int value) → void;
+  abstract member-signature get property2() → core::int?;
   abstract member-signature set property2(core::int? value) → void;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
 }
 class Class2b extends opt::LegacyClass implements self::Interface {
   field core::int field1 = 0;
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect
index 85e1534..b776417 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.strong.transformed.expect
@@ -49,40 +49,40 @@
   synthetic constructor •() → self::Class2a
     : super opt::LegacyClass::•()
     ;
-  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
-  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
-  abstract member-signature get getter1() → core::int;
-  abstract member-signature get field1() → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature method method2() → core::int?;
   abstract member-signature method method3a(core::int a, core::int b) → core::int;
-  abstract member-signature get field4() → core::int?;
-  abstract member-signature get property3() → core::int;
-  abstract member-signature get field2() → core::int?;
-  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
-  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
   abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int;
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
   abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int;
-  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
   abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
   abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?;
-  abstract member-signature method method2() → core::int?;
-  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
-  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
-  abstract member-signature get field3() → core::int;
-  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
-  abstract member-signature method method1() → core::int;
-  abstract member-signature get property1() → core::int;
-  abstract member-signature get property2() → core::int?;
-  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
-  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature get field1() → core::int;
   abstract member-signature set field1(core::int _) → void;
-  abstract member-signature set field4(core::int? _) → void;
-  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get field2() → core::int?;
   abstract member-signature set field2(core::int? _) → void;
-  abstract member-signature set property4(core::int? value) → void;
-  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature get field3() → core::int;
   abstract member-signature set field3(core::int _) → void;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature get property1() → core::int;
   abstract member-signature set property1(core::int value) → void;
+  abstract member-signature get property2() → core::int?;
   abstract member-signature set property2(core::int? value) → void;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
 }
 class Class2b extends opt::LegacyClass implements self::Interface {
   field core::int field1 = 0;
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect
index 85e1534..b776417 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.expect
@@ -49,40 +49,40 @@
   synthetic constructor •() → self::Class2a
     : super opt::LegacyClass::•()
     ;
-  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
-  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
-  abstract member-signature get getter1() → core::int;
-  abstract member-signature get field1() → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature method method2() → core::int?;
   abstract member-signature method method3a(core::int a, core::int b) → core::int;
-  abstract member-signature get field4() → core::int?;
-  abstract member-signature get property3() → core::int;
-  abstract member-signature get field2() → core::int?;
-  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
-  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
   abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int;
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
   abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int;
-  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
   abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
   abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?;
-  abstract member-signature method method2() → core::int?;
-  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
-  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
-  abstract member-signature get field3() → core::int;
-  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
-  abstract member-signature method method1() → core::int;
-  abstract member-signature get property1() → core::int;
-  abstract member-signature get property2() → core::int?;
-  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
-  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature get field1() → core::int;
   abstract member-signature set field1(core::int _) → void;
-  abstract member-signature set field4(core::int? _) → void;
-  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get field2() → core::int?;
   abstract member-signature set field2(core::int? _) → void;
-  abstract member-signature set property4(core::int? value) → void;
-  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature get field3() → core::int;
   abstract member-signature set field3(core::int _) → void;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature get property1() → core::int;
   abstract member-signature set property1(core::int value) → void;
+  abstract member-signature get property2() → core::int?;
   abstract member-signature set property2(core::int? value) → void;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
 }
 class Class2b extends opt::LegacyClass implements self::Interface {
   field core::int field1 = 0;
diff --git a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect
index 85e1534..b776417 100644
--- a/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/member_inheritance_from_opt_out.dart.weak.transformed.expect
@@ -49,40 +49,40 @@
   synthetic constructor •() → self::Class2a
     : super opt::LegacyClass::•()
     ;
-  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
-  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
-  abstract member-signature get getter1() → core::int;
-  abstract member-signature get field1() → core::int;
+  abstract member-signature method method1() → core::int;
+  abstract member-signature method method2() → core::int?;
   abstract member-signature method method3a(core::int a, core::int b) → core::int;
-  abstract member-signature get field4() → core::int?;
-  abstract member-signature get property3() → core::int;
-  abstract member-signature get field2() → core::int?;
-  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
-  abstract member-signature get getter2() → core::int?;
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?;
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?;
   abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int;
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
   abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int;
-  abstract member-signature get property4() → core::int?;
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?;
   abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?;
   abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?;
-  abstract member-signature method method2() → core::int?;
-  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int;
-  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?;
-  abstract member-signature get field3() → core::int;
-  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int;
-  abstract member-signature method method1() → core::int;
-  abstract member-signature get property1() → core::int;
-  abstract member-signature get property2() → core::int?;
-  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int;
-  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature get getter1() → core::int;
+  abstract member-signature get getter2() → core::int?;
+  abstract member-signature get field1() → core::int;
   abstract member-signature set field1(core::int _) → void;
-  abstract member-signature set field4(core::int? _) → void;
-  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get field2() → core::int?;
   abstract member-signature set field2(core::int? _) → void;
-  abstract member-signature set property4(core::int? value) → void;
-  abstract member-signature set setter2(core::int? value) → void;
+  abstract member-signature get field3() → core::int;
   abstract member-signature set field3(core::int _) → void;
+  abstract member-signature get field4() → core::int?;
+  abstract member-signature set field4(core::int? _) → void;
+  abstract member-signature get property1() → core::int;
   abstract member-signature set property1(core::int value) → void;
+  abstract member-signature get property2() → core::int?;
   abstract member-signature set property2(core::int? value) → void;
+  abstract member-signature get property3() → core::int;
+  abstract member-signature set property3(core::int value) → void;
+  abstract member-signature get property4() → core::int?;
+  abstract member-signature set property4(core::int? value) → void;
+  abstract member-signature set setter1(core::int value) → void;
+  abstract member-signature set setter2(core::int? value) → void;
 }
 class Class2b extends opt::LegacyClass implements self::Interface {
   field core::int field1 = 0;
diff --git a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.expect b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.expect
index a0b5e12..aea1af9 100644
--- a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.expect
@@ -48,9 +48,15 @@
   new A();
        ^";
   self::A a = new self::A::•(x: 42);
-  a.{self::A::foo}();
-  a.{self::A::f}.call();
-  self::g.call();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart:18:8: Error: Required named parameter 'y' must be provided.
+  a.foo();
+       ^" in a.{self::A::foo}();
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart:19:6: Error: Required named parameter 's' must be provided.
+  a.f();
+     ^" in a.{self::A::f}.call();
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart:20:4: Error: Required named parameter 's' must be provided.
+  g();
+   ^" in self::g.call();
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.transformed.expect
index a0b5e12..aea1af9 100644
--- a/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart.strong.transformed.expect
@@ -48,9 +48,15 @@
   new A();
        ^";
   self::A a = new self::A::•(x: 42);
-  a.{self::A::foo}();
-  a.{self::A::f}.call();
-  self::g.call();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart:18:8: Error: Required named parameter 'y' must be provided.
+  a.foo();
+       ^" in a.{self::A::foo}();
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart:19:6: Error: Required named parameter 's' must be provided.
+  a.f();
+     ^" in a.{self::A::f}.call();
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/missing_required_named_parameter.dart:20:4: Error: Required named parameter 's' must be provided.
+  g();
+   ^" in self::g.call();
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.outline.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.outline.expect
index ae199c7..d51062b 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.outline.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
 
-abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.expect
index 10e5a0f..ea3253c 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
 
-abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.transformed.expect
index 7dd0788..1325fd4 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
 
-abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.expect
index 10e5a0f..ea3253c 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
 
-abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.transformed.expect
index 7dd0788..1325fd4 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_in.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_in_lib.dart";
 
-abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.outline.expect
index 7e6b375..cd9b6b1 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.outline.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
 
-abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.expect
index 342e2d1..05e67e7 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
 
-abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.transformed.expect
index 8106b0b..fb6d79d 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.strong.transformed.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
 
-abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.expect
index 342e2d1..05e67e7 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
 
-abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin*/  {
+abstract class _Class&Object&Mixin = core::Object with mix::Mixin /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.transformed.expect
index 8106b0b..fb6d79d 100644
--- a/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/mixin_from_opt_out.dart.weak.transformed.expect
@@ -5,7 +5,7 @@
 
 import "org-dartlang-testcase:///mixin_from_opt_out_lib.dart";
 
-abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _Class&Object&Mixin extends core::Object implements mix::Mixin /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_Class&Object&Mixin
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.outline.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.outline.expect
index 6ca32e4..d7377b8 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.outline.expect
@@ -7,13 +7,12 @@
 //   factory C1 = C2<int?>; // Error in strong mode and Warning in weak mode.
 //              ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Error: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
-// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
-//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
-//                 ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
-//   void hest(num? value) {}
-//        ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Error: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
+//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
+//       ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
+//   void set bar(num? value) {}
+//            ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:15:12: Error: The return type of the method 'B2.baz' is 'num?', which does not match the return type, 'num', of the overridden method, 'B1.baz'.
 // Change to a subtype of 'num'.
@@ -23,12 +22,13 @@
 //   num get baz => 42;
 //           ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Error: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
-//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
-//       ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
-//   void set bar(num? value) {}
-//            ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Error: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
+// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
+//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
+//                 ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
+//   void hest(num? value) {}
+//        ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:20:16: Error: The type 'int?' doesn't extend 'int'.
 // Try using a different type as argument.
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.strong.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.strong.expect
index a2a15d0..0c70778 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.strong.expect
@@ -7,13 +7,12 @@
 //   factory C1 = C2<int?>; // Error in strong mode and Warning in weak mode.
 //              ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Error: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
-// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
-//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
-//                 ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
-//   void hest(num? value) {}
-//        ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Error: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
+//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
+//       ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
+//   void set bar(num? value) {}
+//            ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:15:12: Error: The return type of the method 'B2.baz' is 'num?', which does not match the return type, 'num', of the overridden method, 'B1.baz'.
 // Change to a subtype of 'num'.
@@ -23,12 +22,13 @@
 //   num get baz => 42;
 //           ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Error: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
-//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
-//       ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
-//   void set bar(num? value) {}
-//            ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Error: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
+// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
+//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
+//                 ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
+//   void hest(num? value) {}
+//        ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:20:16: Error: The type 'int?' doesn't extend 'int'.
 // Try using a different type as argument.
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.strong.transformed.expect
index 3ddcd06..1387d52 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.strong.transformed.expect
@@ -7,13 +7,12 @@
 //   factory C1 = C2<int?>; // Error in strong mode and Warning in weak mode.
 //              ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Error: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
-// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
-//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
-//                 ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
-//   void hest(num? value) {}
-//        ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Error: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
+//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
+//       ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
+//   void set bar(num? value) {}
+//            ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:15:12: Error: The return type of the method 'B2.baz' is 'num?', which does not match the return type, 'num', of the overridden method, 'B1.baz'.
 // Change to a subtype of 'num'.
@@ -23,12 +22,13 @@
 //   num get baz => 42;
 //           ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Error: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
-//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
-//       ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
-//   void set bar(num? value) {}
-//            ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Error: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
+// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
+//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
+//                 ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
+//   void hest(num? value) {}
+//        ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:20:16: Error: The type 'int?' doesn't extend 'int'.
 // Try using a different type as argument.
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.weak.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.weak.expect
index ffb08e6..4749c02 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.weak.expect
@@ -7,13 +7,12 @@
 //   factory C1 = C2<int?>; // Error in strong mode and Warning in weak mode.
 //              ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Warning: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
-// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
-//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
-//                 ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
-//   void hest(num? value) {}
-//        ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Warning: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
+//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
+//       ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
+//   void set bar(num? value) {}
+//            ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:15:12: Warning: The return type of the method 'B2.baz' is 'num?', which does not match the return type, 'num', of the overridden method, 'B1.baz'.
 // Change to a subtype of 'num'.
@@ -23,12 +22,13 @@
 //   num get baz => 42;
 //           ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Warning: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
-//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
-//       ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
-//   void set bar(num? value) {}
-//            ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Warning: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
+// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
+//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
+//                 ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
+//   void hest(num? value) {}
+//        ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:20:16: Warning: The type 'int?' doesn't extend 'int'.
 // Try using a different type as argument.
diff --git a/pkg/front_end/testcases/nnbd/override_checks.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/override_checks.dart.weak.transformed.expect
index 7042115..8670b98 100644
--- a/pkg/front_end/testcases/nnbd/override_checks.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/override_checks.dart.weak.transformed.expect
@@ -7,13 +7,12 @@
 //   factory C1 = C2<int?>; // Error in strong mode and Warning in weak mode.
 //              ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Warning: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
-// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
-//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
-//                 ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
-//   void hest(num? value) {}
-//        ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Warning: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
+//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
+//       ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
+//   void set bar(num? value) {}
+//            ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:15:12: Warning: The return type of the method 'B2.baz' is 'num?', which does not match the return type, 'num', of the overridden method, 'B1.baz'.
 // Change to a subtype of 'num'.
@@ -23,12 +22,13 @@
 //   num get baz => 42;
 //           ^
 //
-// pkg/front_end/testcases/nnbd/override_checks.dart:14:7: Warning: The field 'B2.bar' has type 'num', which does not match the corresponding type, 'num?', in the overridden setter, 'B1.bar'.
-//   num bar = 3.14; // Error in strong mode and Warning in weak mode.
-//       ^
-// pkg/front_end/testcases/nnbd/override_checks.dart:8:12: Context: This is the overridden method ('bar').
-//   void set bar(num? value) {}
-//            ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:16:17: Warning: The parameter 'value' of the method 'B2.hest' has type 'num', which does not match the corresponding type, 'num?', in the overridden method, 'B1.hest'.
+// Change to a supertype of 'num?', or, for a covariant parameter, a subtype.
+//   void hest(num value) {} // Error in strong mode and Warning in weak mode.
+//                 ^
+// pkg/front_end/testcases/nnbd/override_checks.dart:10:8: Context: This is the overridden method ('hest').
+//   void hest(num? value) {}
+//        ^
 //
 // pkg/front_end/testcases/nnbd/override_checks.dart:20:16: Warning: The type 'int?' doesn't extend 'int'.
 // Try using a different type as argument.
diff --git a/pkg/front_end/testcases/nnbd/test.options b/pkg/front_end/testcases/nnbd/test.options
index 19bb8ec..b552a65 100644
--- a/pkg/front_end/testcases/nnbd/test.options
+++ b/pkg/front_end/testcases/nnbd/test.options
@@ -1,2 +1 @@
---enable-experiment=non-nullable
---force-nnbd-checks
\ No newline at end of file
+--enable-experiment=non-nullable
\ No newline at end of file
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
index b57bf0f..ec7b0ad 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
@@ -17,7 +17,7 @@
   no-such-method-forwarder set foo(core::int* value) → void
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#foo=, 2, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
-abstract class _C&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
+abstract class _C&Object&B = core::Object with self::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect
index 1a87161..9122024 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.expect
@@ -21,7 +21,7 @@
   no-such-method-forwarder set foo(core::int* value) → void
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _C&Object&B = core::Object with self::B /*isAnonymousMixin*/  {
+abstract class _C&Object&B = core::Object with self::B /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect
index 2f8a597..d79f7d2 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.strong.transformed.expect
@@ -21,7 +21,7 @@
   no-such-method-forwarder set foo(core::int* value) → void
     return this.{self::B::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _C&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _C&Object&B extends core::Object implements self::B /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_C&Object&B*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
index edbb0ed..b8d08ac 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
@@ -15,7 +15,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
-abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin*/  {
+abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect
index 3b19a6c..06216c7 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.expect
@@ -17,7 +17,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin*/  {
+abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect
index 44e754a..e4bb8b9 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.strong.transformed.expect
@@ -17,7 +17,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::A::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _B&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
index 7dd0cad..1b7f1ee 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
@@ -16,7 +16,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     ;
 }
-abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
+abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
@@ -27,7 +27,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#foo, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{})));
 }
-abstract class _B&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
+abstract class _B&Object&M = core::Object with self::M /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
index 46f8531..0ee259e 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
@@ -18,7 +18,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     return null;
 }
-abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
+abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
@@ -30,7 +30,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _B&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
+abstract class _B&Object&M = core::Object with self::M /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
index 32bc4ba..c1b4b9b 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
@@ -18,7 +18,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     return null;
 }
-abstract class _A&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _A&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
@@ -32,7 +32,7 @@
   no-such-method-forwarder method foo() → void
     return this.{self::M::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
-abstract class _B&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
index cd0cff0..8f1ca90 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
@@ -8,7 +8,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     ;
 }
-abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin*/  {
+abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
index 8b0741b..bc7397f 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
@@ -10,7 +10,7 @@
     return null;
   }
 }
-abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin*/  {
+abstract class _B&Object&A = core::Object with self::A /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
index 2594975..3db25ae 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
@@ -10,7 +10,7 @@
     return null;
   }
 }
-abstract class _B&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _B&Object&A extends core::Object implements self::A /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_B&Object&A*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
index 96ee192..27b2e4f 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
@@ -13,7 +13,7 @@
   method noSuchMethod(core::Invocation* i) → dynamic
     ;
 }
-abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
+abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
index 9cef3ba..a1b9e10 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
@@ -16,7 +16,7 @@
     return null;
   }
 }
-abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin*/  {
+abstract class _A&Object&M = core::Object with self::M /*isAnonymousMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
index 53a2959..1ba767c 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
@@ -16,7 +16,7 @@
     return null;
   }
 }
-abstract class _A&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin*/  {
+abstract class _A&Object&M extends core::Object implements self::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
   const synthetic constructor •() → self::_A&Object&M*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect
index db36893..7791978 100644
--- a/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.outline.expect
@@ -37,7 +37,7 @@
   synthetic constructor •() → self::B*
     ;
 }
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
index c31d7a4..9f814bb 100644
--- a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.expect
@@ -39,7 +39,7 @@
     : super core::Object::•()
     ;
 }
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
index 78b0fc3..85dc9e7 100644
--- a/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/class_hierarchy.dart.strong.transformed.expect
@@ -39,7 +39,7 @@
     : super core::Object::•()
     ;
 }
-class C extends core::Object {
+class C extends core::Object /*hasConstConstructor*/  {
   const synthetic constructor •() → self::C*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/rasta/super.dart.strong.expect b/pkg/front_end/testcases/rasta/super.dart.strong.expect
index ac97d8e..4ed69fe 100644
--- a/pkg/front_end/testcases/rasta/super.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/super.dart.strong.expect
@@ -283,10 +283,6 @@
 //     use(super.m(87));
 //                ^
 //
-// pkg/front_end/testcases/rasta/super.dart:148:15: Error: This expression has type 'void' and can't be used.
-//     use(super.m(87));
-//               ^
-//
 // pkg/front_end/testcases/rasta/super.dart:149:12: Error: Too many positional arguments: 0 allowed, but 1 found.
 // Try removing the extra positional arguments.
 //     super.n(87);
@@ -297,10 +293,6 @@
 //     use(super.n(87));
 //                ^
 //
-// pkg/front_end/testcases/rasta/super.dart:150:15: Error: This expression has type 'void' and can't be used.
-//     use(super.n(87));
-//               ^
-//
 // pkg/front_end/testcases/rasta/super.dart:222:13: Error: The method '+' isn't defined for the class 'void Function()'.
 // Try correcting the name to the name of an existing method, or defining a method named '+'.
 //     super.m += 42;
@@ -539,14 +531,22 @@
     self::use(let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:146:15: Error: This expression has type 'void' and can't be used.
     use(super.m());
               ^" in super.{self::A::m}());
-    super.{self::A::m}(87);
-    self::use(let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:148:15: Error: This expression has type 'void' and can't be used.
+    let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:147:12: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    super.m(87);
+           ^" in super.{self::A::m}(87);
+    self::use(let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:148:16: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
     use(super.m(87));
-              ^" in super.{self::A::m}(87));
-    super.{self::A::n}(87);
-    self::use(let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:150:15: Error: This expression has type 'void' and can't be used.
+               ^" in super.{self::A::m}(87));
+    let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:149:12: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
+    super.n(87);
+           ^" in super.{self::A::n}(87);
+    self::use(let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/rasta/super.dart:150:16: Error: Too many positional arguments: 0 allowed, but 1 found.
+Try removing the extra positional arguments.
     use(super.n(87));
-              ^" in super.{self::A::n}(87));
+               ^" in super.{self::A::n}(87));
     super.{self::A::a} = 42;
     self::use(super.{self::A::a} = 42);
     super.{self::A::b} = 42;
@@ -566,35 +566,35 @@
     super.{self::B::i} = 42;
     self::use(super.{self::B::i} = 42);
     super.{self::A::[]=}(87, 42);
-    self::use(let final core::int* #t36 = 87 in let final core::int* #t37 = 42 in let final void #t38 = super.{self::A::[]=}(#t36, #t37) in #t37);
+    self::use(let final core::int* #t38 = 87 in let final core::int* #t39 = 42 in let final void #t40 = super.{self::A::[]=}(#t38, #t39) in #t39);
     super.m = 42;
     self::use(super.m = 42);
     super.{self::A::n} = 42;
     self::use(super.{self::A::n} = 42);
     super.{self::A::a}.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : null;
-    self::use(let final dynamic #t39 = super.{self::A::a} in #t39.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : #t39);
+    self::use(let final dynamic #t41 = super.{self::A::a} in #t41.{core::Object::==}(null) ?{dynamic} super.{self::A::a} = 42 : #t41);
     super.{self::B::b}.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : null;
-    self::use(let final dynamic #t40 = super.{self::B::b} in #t40.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : #t40);
+    self::use(let final dynamic #t42 = super.{self::B::b} in #t42.{core::Object::==}(null) ?{dynamic} super.{self::A::b} = 42 : #t42);
     super.{self::A::c}.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : null;
-    self::use(let final dynamic #t41 = super.{self::A::c} in #t41.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : #t41);
+    self::use(let final dynamic #t43 = super.{self::A::c} in #t43.{core::Object::==}(null) ?{dynamic} super.{self::B::c} = 42 : #t43);
     super.{self::B::d}.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : null;
-    self::use(let final dynamic #t42 = super.{self::B::d} in #t42.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : #t42);
+    self::use(let final dynamic #t44 = super.{self::B::d} in #t44.{core::Object::==}(null) ?{dynamic} super.{self::A::d} = 42 : #t44);
     super.{self::A::e}.{core::Object::==}(null) ?{dynamic} super.e = 42 : null;
-    self::use(let final dynamic #t43 = super.{self::A::e} in #t43.{core::Object::==}(null) ?{dynamic} super.e = 42 : #t43);
+    self::use(let final dynamic #t45 = super.{self::A::e} in #t45.{core::Object::==}(null) ?{dynamic} super.e = 42 : #t45);
     super.{self::A::f}.{core::Object::==}(null) ?{dynamic} super.f = 42 : null;
-    self::use(let final dynamic #t44 = super.{self::A::f} in #t44.{core::Object::==}(null) ?{dynamic} super.f = 42 : #t44);
+    self::use(let final dynamic #t46 = super.{self::A::f} in #t46.{core::Object::==}(null) ?{dynamic} super.f = 42 : #t46);
     super.g.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : null;
-    self::use(let final dynamic #t45 = super.g in #t45.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : #t45);
+    self::use(let final dynamic #t47 = super.g in #t47.{core::Object::==}(null) ?{dynamic} super.{self::A::g} = 42 : #t47);
     super.{self::A::h}.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : null;
-    self::use(let final dynamic #t46 = super.{self::A::h} in #t46.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : #t46);
+    self::use(let final dynamic #t48 = super.{self::A::h} in #t48.{core::Object::==}(null) ?{dynamic} super.{self::A::h} = 42 : #t48);
     super.{self::A::i}.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : null;
-    self::use(let final dynamic #t47 = super.{self::A::i} in #t47.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : #t47);
-    let final core::int* #t48 = 87 in super.{self::A::[]}(#t48).{core::Object::==}(null) ?{dynamic} super.{self::A::[]=}(#t48, 42) : null;
-    self::use(let final core::int* #t49 = 87 in let final dynamic #t50 = super.{self::A::[]}(#t49) in #t50.{core::Object::==}(null) ?{dynamic} let final core::int* #t51 = 42 in let final void #t52 = super.{self::A::[]=}(#t49, #t51) in #t51 : #t50);
+    self::use(let final dynamic #t49 = super.{self::A::i} in #t49.{core::Object::==}(null) ?{dynamic} super.{self::B::i} = 42 : #t49);
+    let final core::int* #t50 = 87 in super.{self::A::[]}(#t50).{core::Object::==}(null) ?{dynamic} super.{self::A::[]=}(#t50, 42) : null;
+    self::use(let final core::int* #t51 = 87 in let final dynamic #t52 = super.{self::A::[]}(#t51) in #t52.{core::Object::==}(null) ?{dynamic} let final core::int* #t53 = 42 in let final void #t54 = super.{self::A::[]=}(#t51, #t53) in #t53 : #t52);
     super.{self::A::m}.{core::Object::==}(null) ?{core::Object*} super.m = 42 : null;
-    self::use(let final () →* void #t53 = super.{self::A::m} in #t53.{core::Object::==}(null) ?{core::Object*} super.m = 42 : #t53);
+    self::use(let final () →* void #t55 = super.{self::A::m} in #t55.{core::Object::==}(null) ?{core::Object*} super.m = 42 : #t55);
     super.{self::A::n}.{core::Object::==}(null) ?{core::Object*} super.{self::A::n} = 42 : null;
-    self::use(let final () →* void #t54 = super.{self::A::n} in #t54.{core::Object::==}(null) ?{core::Object*} super.{self::A::n} = 42 : #t54);
+    self::use(let final () →* void #t56 = super.{self::A::n} in #t56.{core::Object::==}(null) ?{core::Object*} super.{self::A::n} = 42 : #t56);
     super.{self::A::a} = super.{self::A::a}.+(42);
     self::use(super.{self::A::a} = super.{self::A::a}.+(42));
     super.{self::A::b} = super.{self::B::b}.+(42);
@@ -613,8 +613,8 @@
     self::use(super.{self::A::h} = super.{self::A::h}.+(42));
     super.{self::B::i} = super.{self::A::i}.+(42);
     self::use(super.{self::B::i} = super.{self::A::i}.+(42));
-    let final core::int* #t55 = 87 in super.{self::A::[]=}(#t55, super.{self::A::[]}(#t55).+(42));
-    self::use(let final core::int* #t56 = 87 in let final dynamic #t57 = super.{self::A::[]}(#t56).+(42) in let final void #t58 = super.{self::A::[]=}(#t56, #t57) in #t57);
+    let final core::int* #t57 = 87 in super.{self::A::[]=}(#t57, super.{self::A::[]}(#t57).+(42));
+    self::use(let final core::int* #t58 = 87 in let final dynamic #t59 = super.{self::A::[]}(#t58).+(42) in let final void #t60 = super.{self::A::[]=}(#t58, #t59) in #t59);
     super.m = invalid-expression "pkg/front_end/testcases/rasta/super.dart:222:13: Error: The method '+' isn't defined for the class 'void Function()'.
 Try correcting the name to the name of an existing method, or defining a method named '+'.
     super.m += 42;
@@ -649,8 +649,8 @@
     self::use(super.{self::A::h} = super.{self::A::h}.-(42));
     super.{self::B::i} = super.{self::A::i}.-(42);
     self::use(super.{self::B::i} = super.{self::A::i}.-(42));
-    let final core::int* #t59 = 87 in super.{self::A::[]=}(#t59, super.{self::A::[]}(#t59).-(42));
-    self::use(let final core::int* #t60 = 87 in let final dynamic #t61 = super.{self::A::[]}(#t60).-(42) in let final void #t62 = super.{self::A::[]=}(#t60, #t61) in #t61);
+    let final core::int* #t61 = 87 in super.{self::A::[]=}(#t61, super.{self::A::[]}(#t61).-(42));
+    self::use(let final core::int* #t62 = 87 in let final dynamic #t63 = super.{self::A::[]}(#t62).-(42) in let final void #t64 = super.{self::A::[]=}(#t62, #t63) in #t63);
     super.m = invalid-expression "pkg/front_end/testcases/rasta/super.dart:247:13: Error: The method '-' isn't defined for the class 'void Function()'.
 Try correcting the name to the name of an existing method, or defining a method named '-'.
     super.m -= 42;
diff --git a/pkg/front_end/testcases/regress/issue_31299.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31299.dart.strong.expect
index f7a19ab..50ff2ba 100644
--- a/pkg/front_end/testcases/regress/issue_31299.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31299.dart.strong.expect
@@ -29,7 +29,9 @@
     return a.{core::num::+}(b.{core::num::*}(this.{self::A::m}));
 }
 static method test() → dynamic {
-  new self::A::•().{self::A::foo}();
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/regress/issue_31299.dart:15:14: Error: Too few positional arguments: 2 required, 0 given.
+  new A().foo();
+             ^" in new self::A::•().{self::A::foo}();
   new self::A::•().{self::A::foo}(1, 2);
   new self::A::foo();
   invalid-expression "pkg/front_end/testcases/regress/issue_31299.dart:18:12: Error: Too many positional arguments: 0 allowed, but 2 found.
diff --git a/pkg/front_end/testcases/regress/issue_32972.dart.strong.expect b/pkg/front_end/testcases/regress/issue_32972.dart.strong.expect
index 98ebef5..5afee15 100644
--- a/pkg/front_end/testcases/regress/issue_32972.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_32972.dart.strong.expect
@@ -59,7 +59,9 @@
       ^";
   self::Foo::foo<core::int*>(42);
   self::Foo* f = new self::Foo::•();
-  f.{self::Foo::bar}<core::double*, core::double*>(42.42);
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/regress/issue_32972.dart:27:5: Error: Expected 1 type arguments.
+  f.bar<double, double>(42.42);
+    ^" in f.{self::Foo::bar}<core::double*, core::double*>(42.42);
   f.{self::Foo::bar}<core::double*>(42.42);
   invalid-expression "pkg/front_end/testcases/regress/issue_32972.dart:29:7: Error: Expected 2 type arguments.
   new Bar<String>();
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect
index f26c179..7e62b61 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.outline.expect
@@ -46,10 +46,10 @@
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
-  forwarding-stub set y(covariant core::Object* value) → void
-    return super.{self::B::y} = value;
   forwarding-stub set x(generic-covariant-impl core::int* _) → void
     return super.{self::B::x} = _;
+  forwarding-stub set y(covariant core::Object* value) → void
+    return super.{self::B::y} = value;
 }
 static method expectTypeError(() →* void callback) → void
   ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
index 5c70f1e..f9f56be 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_field.dart.strong.expect
@@ -53,10 +53,10 @@
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
-  forwarding-stub set y(covariant core::Object* value) → void
-    return super.{self::B::y} = value;
   forwarding-stub set x(generic-covariant-impl core::int* _) → void
     return super.{self::B::x} = _;
+  forwarding-stub set y(covariant core::Object* value) → void
+    return super.{self::B::y} = value;
 }
 static method expectTypeError(() →* void callback) → void {
   try {
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect
index f230923..990d151 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.outline.expect
@@ -53,10 +53,10 @@
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
-  forwarding-stub set y(covariant core::Object* value) → void
-    return super.{self::B::y} = value;
   forwarding-stub set x(generic-covariant-impl core::int* value) → void
     return super.{self::B::x} = value;
+  forwarding-stub set y(covariant core::Object* value) → void
+    return super.{self::B::y} = value;
 }
 static method expectTypeError(() →* void callback) → void
   ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
index 96c8e8b..6c05a9d 100644
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_setter.dart.strong.expect
@@ -62,10 +62,10 @@
   synthetic constructor •() → self::C*
     : super self::B::•()
     ;
-  forwarding-stub set y(covariant core::Object* value) → void
-    return super.{self::B::y} = value;
   forwarding-stub set x(generic-covariant-impl core::int* value) → void
     return super.{self::B::x} = value;
+  forwarding-stub set y(covariant core::Object* value) → void
+    return super.{self::B::y} = value;
 }
 static method expectTypeError(() →* void callback) → void {
   try {
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 9f8f2a2..a15ef79 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -6,9 +6,11 @@
 # Kernel ASTs directly, that is, code in pkg/fasta/lib/src/kernel/ with
 # strong-mode enabled.
 
+extensions/call_methods: TypeCheckError
 extensions/extension_setter_error: TypeCheckError
 extensions/instance_access_of_static: RuntimeError
 extensions/invalid_explicit_access: RuntimeError
+extensions/issue40713: TypeCheckError
 extensions/static_access_of_instance: RuntimeError
 general/abstract_members: TypeCheckError
 general/accessors: RuntimeError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 72977f5..20fccba 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -13,7 +13,7 @@
 expression/main: TextSerializationFailure # Was: Pass
 extensions/annotations: TextSerializationFailure
 extensions/builtin_identifiers: TextSerializationFailure
-extensions/call_methods: TextSerializationFailure
+extensions/call_methods: TypeCheckError
 extensions/check_bounds: TextSerializationFailure
 extensions/compounds: TextSerializationFailure
 extensions/conflict_with_object: TextSerializationFailure
@@ -32,6 +32,7 @@
 extensions/export_twice: TextSerializationFailure
 extensions/extension_call: TextSerializationFailure
 extensions/extension_constructor: TextSerializationFailure
+extensions/extension_field_with_type_parameter_usage: TextSerializationFailure
 extensions/extension_methods: TextSerializationFailure
 extensions/extension_setter: TextSerializationFailure
 extensions/extension_setter_error: TypeCheckError
@@ -56,7 +57,10 @@
 extensions/issue38750: TextSerializationFailure
 extensions/issue38755: TextSerializationFailure
 extensions/issue38915: TextSerializationFailure
+extensions/issue39889: TextSerializationFailure
 extensions/issue39938/issue39938: TextSerializationFailure
+extensions/issue40596: TextSerializationFailure
+extensions/issue40713: TypeCheckError
 extensions/issue40816: TextSerializationFailure
 extensions/missing_toplevel: TextSerializationFailure
 extensions/nested_on_types: TextSerializationFailure
@@ -210,6 +214,8 @@
 general/import_conflicting_types: TextSerializationFailure
 general/incomplete_field_formal_parameter: TextSerializationFailure # Was: RuntimeError
 general/infer_field_from_multiple: TypeCheckError
+general/infer_field_type: TextSerializationFailure
+general/infer_fixed_generic_return_type: TextSerializationFailure
 general/infer_map_literal_with_closure: TextSerializationFailure
 general/interface_conflict: TextSerializationFailure
 general/interface_contravariant_from_class: TextSerializationFailure
@@ -239,6 +245,7 @@
 general/issue40428: TextSerializationFailure
 general/issue40662: TextSerializationFailure
 general/issue40744: TextSerializationFailure
+general/issue41070: TextSerializationFailure
 general/literals: TextSerializationFailure # Was: Pass
 general/local_generic_function: TextSerializationFailure # Was: Pass
 general/long_chain_of_typedefs: TextSerializationFailure
@@ -257,6 +264,7 @@
 general/mixin_application_override: TypeCheckError
 general/mixin_conflicts: TextSerializationFailure
 general/mixin_constructors_with_default_values: TextSerializationFailure # Was: Pass
+general/mixin_covariant: TextSerializationFailure
 general/mixin_inherited_setter_for_mixed_in_field: TextSerializationFailure # Was: Pass
 general/mixin_interface_conflict: TextSerializationFailure
 general/mixin_super_repeated: TextSerializationFailure # Was: Pass
@@ -358,6 +366,7 @@
 general/unsound_promotion: TypeCheckError
 general/unused_methods: TextSerializationFailure # Was: Pass
 general/var_as_type_name: TextSerializationFailure # Was: Pass
+general/vm_type_ops: TextSerializationFailure
 general/void_methods: TextSerializationFailure
 general/warn_unresolved_sends: InstrumentationMismatch # Test assumes Dart 1.0 semantics
 general/well_boundness_checks_in_outline: TextSerializationFailure
@@ -1203,6 +1212,7 @@
 instantiate_to_bound/typedef_raw_in_bound: TextSerializationFailure # Was: Pass
 instantiate_to_bound/typedef_super_bounded_type: TextSerializationFailure # Was: Pass
 late_lowering/initializer_rewrite: TextSerializationFailure
+late_lowering/infer_late_field_type: TextSerializationFailure
 late_lowering/injected_late_field_checks/main: TextSerializationFailure
 late_lowering/instance_field_with_initializer: TextSerializationFailure
 late_lowering/instance_field_without_initializer: TextSerializationFailure
@@ -1213,6 +1223,7 @@
 late_lowering/issue40093: TextSerializationFailure
 late_lowering/issue40373: TextSerializationFailure
 late_lowering/issue40373b: TextSerializationFailure
+late_lowering/issue40805: TextSerializationFailure
 late_lowering/late_field_inference: TextSerializationFailure
 late_lowering/late_field_with_initializer: TextSerializationFailure
 late_lowering/late_field_without_initializer: TextSerializationFailure
@@ -1246,16 +1257,19 @@
 nnbd/definite_assignment_and_completion: TextSerializationFailure
 nnbd/definitely_unassigned_late_local_variables: TextSerializationFailure
 nnbd/demote_closure_types: TextSerializationFailure
+nnbd/export_from_opt_out: TextSerializationFailure
 nnbd/forbidden_supers: TextSerializationFailure
 nnbd/forin: TextSerializationFailure
 nnbd/from_agnostic/from_agnostic: TextSerializationFailure
 nnbd/function_types: TextSerializationFailure
 nnbd/future_or_variables: TextSerializationFailure
 nnbd/generic_override: TextSerializationFailure
+nnbd/infer_constraints_from_opt_in: TextSerializationFailure
 nnbd/infer_from_opt_in: TextSerializationFailure
 nnbd/infer_from_opt_out: TextSerializationFailure
 nnbd/infer_if_null: TextSerializationFailure
 nnbd/infer_in_legacy_from_opted_in: TextSerializationFailure
+nnbd/infer_method_types: TextSerializationFailure
 nnbd/inheritance_from_opt_in: TypeCheckError
 nnbd/inheritance_from_opt_out: TextSerializationFailure
 nnbd/injected_late_field_checks/main: TextSerializationFailure
@@ -1266,6 +1280,7 @@
 nnbd/issue40134: TextSerializationFailure
 nnbd/issue40512/issue40512: TextSerializationFailure
 nnbd/issue40600: TextSerializationFailure
+nnbd/issue40805: TextSerializationFailure
 nnbd/issue_39286: TextSerializationFailure
 nnbd/issue_39286_2: TextSerializationFailure
 nnbd/late: TextSerializationFailure
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index c6f08ee..23aa8f9 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -4,9 +4,11 @@
 
 # Status file for the weak_suite.dart test suite.
 
+extensions/call_methods: TypeCheckError
 extensions/extension_setter_error: TypeCheckError
 extensions/instance_access_of_static: RuntimeError
 extensions/invalid_explicit_access: RuntimeError
+extensions/issue40713: TypeCheckError
 extensions/static_access_of_instance: RuntimeError
 general_nnbd_opt_out/abstract_members: TypeCheckError
 general_nnbd_opt_out/accessors: RuntimeError
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index 5a38138..392a4d3 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -253,7 +253,6 @@
   "--fatal": ",",
   "--fatal-skip": String,
   Flags.forceLateLowering: false,
-  Flags.forceNnbdChecks: false,
   Flags.forceNoExplicitGetterCalls: false,
   "--help": false,
   // TODO(johnniwinther): Remove legacy option flags. Legacy mode is no longer
@@ -374,8 +373,6 @@
         "'${Flags.nnbdAgnosticMode}'.");
   }
 
-  final bool forceNnbdChecks = options[Flags.forceNnbdChecks];
-
   FileSystem fileSystem = StandardFileSystem.instance;
   if (singleRootScheme != null) {
     fileSystem = new SchemeBasedFileSystem({
@@ -422,8 +419,7 @@
           ..bytecode = bytecode
           ..experimentalFlags = experimentalFlags
           ..environmentDefines = noDefines ? null : parsedArguments.defines
-          ..nnbdMode = nnbdMode
-          ..performNnbdChecks = forceNnbdChecks,
+          ..nnbdMode = nnbdMode,
         inputs: <Uri>[Uri.parse(arguments[0])],
         output: resolveInputUri(arguments[3]));
   } else if (arguments.isEmpty) {
@@ -480,8 +476,7 @@
     ..verify = verify
     ..experimentalFlags = experimentalFlags
     ..environmentDefines = noDefines ? null : parsedArguments.defines
-    ..nnbdMode = nnbdMode
-    ..performNnbdChecks = forceNnbdChecks;
+    ..nnbdMode = nnbdMode;
 
   // TODO(ahe): What about chase dependencies?
 
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index add6b9a..3cfa8b2 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -521,11 +521,10 @@
       if (_compilerOptions.target.name == 'dartdevc') {
         await writeJavascriptBundle(
             results, _kernelBinaryFilename, options['filesystem-scheme']);
-      } else {
-        await writeDillFile(results, _kernelBinaryFilename,
-            filterExternal: importDill != null,
-            incrementalSerializer: incrementalSerializer);
       }
+      await writeDillFile(results, _kernelBinaryFilename,
+          filterExternal: importDill != null,
+          incrementalSerializer: incrementalSerializer);
 
       _outputStream.writeln(boundaryKey);
       await _outputDependenciesDelta(results.compiledSources);
diff --git a/pkg/kernel/bin/transform.dart b/pkg/kernel/bin/transform.dart
index 40064fd..c0b9d02 100755
--- a/pkg/kernel/bin/transform.dart
+++ b/pkg/kernel/bin/transform.dart
@@ -104,7 +104,7 @@
           component,
           backend,
           defines,
-          const constants.SimpleErrorReporter(false),
+          const constants.SimpleErrorReporter(),
           constants.EvaluationMode.legacy);
       break;
     case 'empty':
diff --git a/pkg/kernel/lib/src/future_or.dart b/pkg/kernel/lib/src/future_or.dart
index 5555a0b..d5f39db 100644
--- a/pkg/kernel/lib/src/future_or.dart
+++ b/pkg/kernel/lib/src/future_or.dart
@@ -75,7 +75,7 @@
   if (_isFutureOr(type, futureOrClass)) {
     return computeNullabilityOfFutureOr(type, futureOrClass);
   }
-  return type.nullability;
+  return type is InvalidType ? Nullability.undetermined : type.nullability;
 }
 
 bool isPotentiallyNullable(DartType type, Class futureOrClass) {
diff --git a/pkg/nnbd_migration/lib/instrumentation.dart b/pkg/nnbd_migration/lib/instrumentation.dart
index 93f3a9d..cda88c5 100644
--- a/pkg/nnbd_migration/lib/instrumentation.dart
+++ b/pkg/nnbd_migration/lib/instrumentation.dart
@@ -112,7 +112,7 @@
   DecoratedTypeInfo typeArgument(int i);
 }
 
-/// Information about a propagation stup that occurred during downstream
+/// Information about a propagation step that occurred during downstream
 /// propagation.
 abstract class DownstreamPropagationStepInfo implements PropagationStepInfo {
   DownstreamPropagationStepInfo get principalCause;
@@ -362,6 +362,10 @@
   /// The edges that caused this node to have the nullability that it has.
   Iterable<EdgeInfo> get upstreamEdges;
 
+  /// If [isNullable] is false, the propagation step that caused this node to
+  /// become non-nullable (if any).
+  UpstreamPropagationStepInfo get whyNotNullable;
+
   /// If [isNullable] is true, the propagation step that caused this node to
   /// become nullable.
   DownstreamPropagationStepInfo get whyNullable;
@@ -388,3 +392,17 @@
   /// `*` in `T*`.
   NullabilityNodeInfo get outerNode;
 }
+
+/// Information about a propagation step that occurred during upstream
+/// propagation.
+abstract class UpstreamPropagationStepInfo implements PropagationStepInfo {
+  /// The node whose nullability was changed.
+  ///
+  /// Any propagation step that took effect should have a non-null value here.
+  /// Propagation steps that are pending but have not taken effect yet, or that
+  /// never had an effect (e.g. because an edge was not triggered) will have a
+  /// `null` value for this field.
+  NullabilityNodeInfo get node;
+
+  UpstreamPropagationStepInfo get principalCause;
+}
diff --git a/pkg/nnbd_migration/lib/src/messages.dart b/pkg/nnbd_migration/lib/src/messages.dart
new file mode 100644
index 0000000..3a32d14
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/messages.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const String migratedAlready =
+    "Seem to be migrating code that's already migrated";
+const String nnbdExperimentOff =
+    'Analyzer seems to need the nnbd experiment on in the SDK.';
+const String sdkNnbdOff = 'Analysis seems to have an SDK without NNBD enabled.';
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index 0dda2f2..48d2fbc 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -15,6 +16,7 @@
 import 'package:nnbd_migration/src/edit_plan.dart';
 import 'package:nnbd_migration/src/fix_aggregator.dart';
 import 'package:nnbd_migration/src/fix_builder.dart';
+import 'package:nnbd_migration/src/messages.dart';
 import 'package:nnbd_migration/src/node_builder.dart';
 import 'package:nnbd_migration/src/nullability_node.dart';
 import 'package:nnbd_migration/src/postmortem_file.dart';
@@ -79,6 +81,7 @@
 
   @override
   void finalizeInput(ResolvedUnitResult result) {
+    _sanityCheck(result);
     if (!_propagated) {
       _propagated = true;
       _graph.propagate(_postmortemFileWriter);
@@ -127,6 +130,7 @@
   }
 
   void prepareInput(ResolvedUnitResult result) {
+    _sanityCheck(result);
     if (_variables == null) {
       _variables = Variables(_graph, result.typeProvider,
           instrumentation: _instrumentation,
@@ -145,6 +149,7 @@
   }
 
   void processInput(ResolvedUnitResult result) {
+    _sanityCheck(result);
     var unit = result.unit;
     try {
       DecoratedTypeParameterBounds.current = _decoratedTypeParameterBounds;
@@ -167,6 +172,26 @@
     _graph.update(_postmortemFileWriter);
   }
 
+  void _sanityCheck(ResolvedUnitResult result) {
+    final equalsParamType = result.typeProvider.objectType
+        .getMethod('==')
+        .parameters[0]
+        .type
+        .getDisplayString(withNullability: true);
+    if (equalsParamType == 'Object*') {
+      throw StateError(nnbdExperimentOff);
+    }
+
+    if (equalsParamType != 'Object') {
+      throw StateError(sdkNnbdOff);
+    }
+
+    if (result.unit.featureSet.isEnabled(Feature.non_nullable)) {
+      // TODO(jcollins-g): Allow for skipping already migrated compilation units.
+      throw StateError('$migratedAlready: ${result.path}');
+    }
+  }
+
   static Location _computeLocation(
       LineInfo lineInfo, SourceEdit edit, Source source) {
     final locationInfo = lineInfo.getLocation(edit.offset);
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index bcbe748..506236e 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -766,8 +766,7 @@
   @override
   Iterable<EdgeInfo> get upstreamEdges => _upstreamEdges;
 
-  /// If this node has non-null intent, the propagation step that caused it to
-  /// have non-null intent, otherwise `null`.
+  @override
   UpstreamPropagationStep get whyNotNullable;
 
   String get _jsonKind;
@@ -1167,7 +1166,8 @@
 
 /// Propagation step where we mark a node as having non-null intent due to it
 /// being upstream from another node with non-null intent.
-class UpstreamPropagationStep extends PropagationStep {
+class UpstreamPropagationStep extends PropagationStep
+    implements UpstreamPropagationStepInfo {
   @override
   final UpstreamPropagationStep principalCause;
 
@@ -1177,15 +1177,23 @@
   /// The new state of the node's non-null intent.
   final NonNullIntent newNonNullIntent;
 
+  /// The nullability edge connecting [node] to the node it is upstream from, if
+  /// any.
+  final NullabilityEdge edge;
+
   UpstreamPropagationStep(
-      this.principalCause, this.node, this.newNonNullIntent);
+      this.principalCause, this.node, this.newNonNullIntent, this.edge);
 
   UpstreamPropagationStep.fromJson(
       dynamic json, NullabilityGraphDeserializer deserializer)
       : principalCause = deserializer.stepForId(json['cause'] as int)
             as UpstreamPropagationStep,
         node = deserializer.nodeForId(json['node'] as int),
-        newNonNullIntent = NonNullIntent.fromJson(json['newState']);
+        newNonNullIntent = NonNullIntent.fromJson(json['newState']),
+        edge = deserializer.edgeForId(json['edge'] as int);
+
+  @override
+  CodeReference get codeReference => edge?.codeReference;
 
   @override
   Map<String, Object> toJson(NullabilityGraphSerializer serializer) {
@@ -1193,7 +1201,8 @@
       'kind': 'upstream',
       'cause': serializer.idForStep(principalCause),
       'node': serializer.idForNode(node),
-      'newState': newNonNullIntent.toJson()
+      'newState': newNonNullIntent.toJson(),
+      'edge': serializer.idForEdge(edge)
     };
   }
 
@@ -1388,7 +1397,7 @@
   void _propagateUpstream() {
     Queue<UpstreamPropagationStep> pendingSteps = Queue();
     pendingSteps
-        .add(UpstreamPropagationStep(null, _never, NonNullIntent.direct));
+        .add(UpstreamPropagationStep(null, _never, NonNullIntent.direct, null));
     while (pendingSteps.isNotEmpty) {
       var cause = pendingSteps.removeFirst();
       var pendingNode = cause.node;
@@ -1408,7 +1417,8 @@
           } else {
             newNonNullIntent = oldNonNullIntent.addIndirect();
           }
-          var step = UpstreamPropagationStep(cause, node, newNonNullIntent);
+          var step =
+              UpstreamPropagationStep(cause, node, newNonNullIntent, edge);
           _setNonNullIntent(step);
           if (!oldNonNullIntent.isPresent) {
             // We did not previously have non-null intent, so we need to
@@ -1426,7 +1436,7 @@
         }
         var oldNonNullIntent = node._nonNullIntent;
         var newNonNullIntent = oldNonNullIntent.addIndirect();
-        var step = UpstreamPropagationStep(cause, node, newNonNullIntent);
+        var step = UpstreamPropagationStep(cause, node, newNonNullIntent, null);
         _setNonNullIntent(step);
         if (!oldNonNullIntent.isPresent) {
           // We did not previously have non-null intent, so we need to
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 4750c47..bded508 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -44,7 +44,7 @@
           .having((c) => c.addRequiredKeyword, 'addRequiredKeyword', true);
 
   static final isMakeNullable = TypeMatcher<NodeChangeForTypeAnnotation>()
-      .having((c) => c.makeNullable, 'makeNullable', isNotNull);
+      .having((c) => c.makeNullable, 'makeNullable', true);
 
   static final isNullCheck = TypeMatcher<NodeChangeForExpression>()
       .having((c) => c.addsNullCheck, 'addsNullCheck', true);
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index de8e90f2..2d051df 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -1185,7 +1185,6 @@
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
       if (_configuration.configuration.nnbdMode == NnbdMode.strong) ...[
-        "--force-nnbd-checks",
         "--nnbd-strong"
       ]
     ];
diff --git a/pkg/test_runner/lib/src/test_file.dart b/pkg/test_runner/lib/src/test_file.dart
index 74bb378..6fe642f 100644
--- a/pkg/test_runner/lib/src/test_file.dart
+++ b/pkg/test_runner/lib/src/test_file.dart
@@ -7,9 +7,6 @@
 import 'path.dart';
 import 'static_error.dart';
 
-final _multiHtmlTestGroupRegExp = RegExp(r"\s*[^/]\s*group\('[^,']*");
-final _multiHtmlTestRegExp = RegExp(r"useHtmlIndividualConfiguration\(\)");
-
 // TODO(rnystrom): Remove support for "///" once tests have been migrated.
 // https://dart-review.googlesource.com/c/sdk/+/106201
 // https://github.com/dart-lang/co19/issues/391
@@ -186,8 +183,6 @@
           hasStaticWarning: false,
           hasCrash: false,
           isMultitest: false,
-          isMultiHtmlTest: false,
-          subtestNames: [],
           sharedObjects: [],
           otherResources: []);
     }
@@ -274,15 +269,6 @@
     }
 
     var isMultitest = _multitestRegExp.hasMatch(contents);
-    var isMultiHtmlTest = _multiHtmlTestRegExp.hasMatch(contents);
-
-    var subtestNames = <String>[];
-    if (isMultiHtmlTest) {
-      for (var match in _multiHtmlTestGroupRegExp.allMatches(contents)) {
-        var fullMatch = match.group(0);
-        subtestNames.add(fullMatch.substring(fullMatch.indexOf("'") + 1));
-      }
-    }
 
     // TODO(rnystrom): During the migration of the existing tests to Dart 2.0,
     // we have a number of tests that used to both generate static type warnings
@@ -322,13 +308,11 @@
         packages: packages,
         environment: environment,
         isMultitest: isMultitest,
-        isMultiHtmlTest: isMultiHtmlTest,
         hasSyntaxError: hasSyntaxError,
         hasCompileError: hasCompileError,
         hasRuntimeError: contents.contains("@runtime-error"),
         hasStaticWarning: contents.contains("@static-warning"),
         hasCrash: false,
-        subtestNames: subtestNames,
         requirements: requirements,
         sharedOptions: sharedOptions,
         dartOptions: dartOptions,
@@ -350,8 +334,6 @@
       : packages = null,
         environment = null,
         isMultitest = false,
-        isMultiHtmlTest = false,
-        subtestNames = [],
         requirements = [],
         sharedOptions = [],
         dartOptions = [],
@@ -367,13 +349,11 @@
       {this.packages,
       this.environment,
       this.isMultitest,
-      this.isMultiHtmlTest,
       this.hasSyntaxError,
       this.hasCompileError,
       this.hasRuntimeError,
       this.hasStaticWarning,
       this.hasCrash,
-      this.subtestNames,
       this.requirements,
       this.sharedOptions,
       this.dartOptions,
@@ -396,15 +376,12 @@
   final Map<String, String> environment;
 
   final bool isMultitest;
-  final bool isMultiHtmlTest;
   final bool hasSyntaxError;
   final bool hasCompileError;
   final bool hasRuntimeError;
   final bool hasStaticWarning;
   final bool hasCrash;
 
-  final List<String> subtestNames;
-
   /// The features that a test configuration must support in order to run this
   /// test.
   ///
@@ -445,13 +422,11 @@
   packages: $packages
   environment: $environment
   isMultitest: $isMultitest
-  isMultiHtmlTest: $isMultiHtmlTest
   hasSyntaxError: $hasSyntaxError
   hasCompileError: $hasCompileError
   hasRuntimeError: $hasRuntimeError
   hasStaticWarning: $hasStaticWarning
   hasCrash: $hasCrash
-  subtestNames: $subtestNames
   requirements: $requirements
   sharedOptions: $sharedOptions
   dartOptions: $dartOptions
@@ -498,14 +473,12 @@
   List<String> get ddcOptions => _origin.ddcOptions;
   Map<String, String> get environment => _origin.environment;
 
-  bool get isMultiHtmlTest => _origin.isMultiHtmlTest;
   bool get isMultitest => _origin.isMultitest;
 
   List<String> get otherResources => _origin.otherResources;
   List<String> get sharedObjects => _origin.sharedObjects;
   List<String> get experiments => _origin.experiments;
   List<String> get sharedOptions => _origin.sharedOptions;
-  List<String> get subtestNames => _origin.subtestNames;
   List<List<String>> get vmOptions => _origin.vmOptions;
 
   TestFile split(Path path, String multitestKey, String contents,
diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart
index 45c8d41..b0cb187 100644
--- a/pkg/test_runner/lib/src/test_suite.dart
+++ b/pkg/test_runner/lib/src/test_suite.dart
@@ -574,38 +574,22 @@
       return;
     }
 
+    var expectationSet = expectations.expectations(testFile.name);
     if (configuration.compilerConfiguration.hasCompiler &&
         (testFile.hasCompileError || testFile.isStaticErrorTest)) {
       // If a compile-time error is expected, and we're testing a
       // compiler, we never need to attempt to run the program (in a
       // browser or otherwise).
-      _enqueueStandardTest(testFile, expectations, onTest);
+      _enqueueStandardTest(testFile, expectationSet, onTest);
     } else if (configuration.runtime.isBrowser) {
-      var expectationsMap = <String, Set<Expectation>>{};
-
-      if (testFile.isMultiHtmlTest) {
-        // A browser multi-test has multiple expectations for one test file.
-        // Find all the different sub-test expectations for one entire test
-        // file.
-        var subtestNames = testFile.subtestNames;
-        expectationsMap = <String, Set<Expectation>>{};
-        for (var subtest in subtestNames) {
-          expectationsMap[subtest] =
-              expectations.expectations('${testFile.name}/$subtest');
-        }
-      } else {
-        expectationsMap[testFile.name] =
-            expectations.expectations(testFile.name);
-      }
-
-      _enqueueBrowserTest(testFile, expectationsMap, onTest);
+      _enqueueBrowserTest(testFile, expectationSet, onTest);
     } else {
-      _enqueueStandardTest(testFile, expectations, onTest);
+      _enqueueStandardTest(testFile, expectationSet, onTest);
     }
   }
 
   void _enqueueStandardTest(
-      TestFile testFile, ExpectationSet expectations, TestCaseEvent onTest) {
+      TestFile testFile, Set<Expectation> expectations, TestCaseEvent onTest) {
     var commonArguments = _commonArgumentsFromFile(testFile);
 
     var vmOptionsList = getVmOptions(testFile);
@@ -620,8 +604,7 @@
         allVmOptions = vmOptions.toList()..addAll(extraVmOptions);
       }
 
-      var testExpectations = expectations.expectations(testFile.name);
-      var isCrashExpected = testExpectations.contains(Expectation.crash);
+      var isCrashExpected = expectations.contains(Expectation.crash);
       var commands = _makeCommands(testFile, vmOptionsVariant, allVmOptions,
           commonArguments, isCrashExpected);
       var variantTestName = testFile.name;
@@ -629,8 +612,7 @@
         variantTestName = "${testFile.name}/$vmOptionsVariant";
       }
 
-      _addTestCase(
-          testFile, variantTestName, commands, testExpectations, onTest);
+      _addTestCase(testFile, variantTestName, commands, expectations, onTest);
     }
   }
 
@@ -726,7 +708,7 @@
     return null;
   }
 
-  String _uriForBrowserTest(String pathComponent, [String subtestName]) {
+  String _uriForBrowserTest(String pathComponent) {
     // Note: If we run test.py with the "--list" option, no http servers
     // will be started. So we return a dummy url instead.
     if (configuration.listTests) {
@@ -736,9 +718,6 @@
     var serverPort = configuration.servers.port;
     var crossOriginPort = configuration.servers.crossOriginPort;
     var parameters = {'crossOriginPort': crossOriginPort.toString()};
-    if (subtestName != null) {
-      parameters['group'] = subtestName;
-    }
     return Uri(
             scheme: 'http',
             host: configuration.localIP,
@@ -754,12 +733,8 @@
   /// in a generated output directory. Any additional framework and HTML files
   /// are put there too. Then adds another [Command] the spawn the browser and
   /// run the test.
-  ///
-  /// In order to handle browser multitests, [expectations] is a map of subtest
-  /// names to expectation sets. If the test is not a multitest, the map has
-  /// a single key, `testFile.name`.
-  void _enqueueBrowserTest(TestFile testFile,
-      Map<String, Set<Expectation>> expectations, TestCaseEvent onTest) {
+  void _enqueueBrowserTest(
+      TestFile testFile, Set<Expectation> expectations, TestCaseEvent onTest) {
     var tempDir = createOutputDirectory(testFile.path);
     var compilationTempDir = createCompilationOutputDirectory(testFile.path);
     var nameNoExt = testFile.path.filenameWithoutExtension;
@@ -815,44 +790,27 @@
         .computeCompilationArtifact(outputDir, args, environmentOverrides);
     commands.addAll(compilation.commands);
 
-    if (testFile.isMultiHtmlTest) {
-      // Variables for browser multi-tests.
-      var subtestNames = testFile.subtestNames;
-      for (var subtestName in subtestNames) {
-        _enqueueSingleBrowserTest(
-            commands,
-            testFile,
-            '${testFile.name}/$subtestName',
-            subtestName,
-            expectations[subtestName],
-            htmlPath,
-            onTest);
-      }
-    } else {
-      _enqueueSingleBrowserTest(commands, testFile, testFile.name, null,
-          expectations[testFile.name], htmlPath, onTest);
-    }
+    _enqueueSingleBrowserTest(
+        commands, testFile, testFile.name, expectations, htmlPath, onTest);
   }
 
+  // TODO: Merge with above.
   /// Enqueues a single browser test, or a single subtest of an HTML multitest.
   void _enqueueSingleBrowserTest(
       List<Command> commands,
       TestFile testFile,
       String testName,
-      String subtestName,
       Set<Expectation> expectations,
       String htmlPath,
       TestCaseEvent onTest) {
     // Construct the command that executes the browser test.
     commands = commands.toList();
 
-    var htmlPathSubtest = _createUrlPathFromFile(Path(htmlPath));
-    var fullHtmlPath = _uriForBrowserTest(htmlPathSubtest, subtestName);
-
+    var fullHtmlPath =
+        _uriForBrowserTest(_createUrlPathFromFile(Path(htmlPath)));
     commands.add(BrowserTestCommand(fullHtmlPath, configuration));
 
     var fullName = testName;
-    if (subtestName != null) fullName += "/$subtestName";
     _addTestCase(testFile, fullName, commands, expectations, onTest);
   }
 
@@ -921,8 +879,8 @@
             ["$directoryPath/.status"],
             recursive: true);
 
-  void _enqueueBrowserTest(TestFile testFile,
-      Map<String, Set<Expectation>> expectations, TestCaseEvent onTest) {
+  void _enqueueBrowserTest(
+      TestFile testFile, Set<Expectation> expectations, TestCaseEvent onTest) {
     var dir = testFile.path.directoryPath;
     var nameNoExt = testFile.path.filenameWithoutExtension;
     var customHtmlPath = dir.append('$nameNoExt.html');
@@ -932,8 +890,7 @@
     } else {
       var fullPath = _createUrlPathFromFile(customHtmlPath);
       var command = BrowserTestCommand(fullPath, configuration);
-      _addTestCase(testFile, testFile.name, [command],
-          expectations[testFile.name], onTest);
+      _addTestCase(testFile, testFile.name, [command], expectations, onTest);
     }
   }
 }
diff --git a/pkg/test_runner/test/test_file_test.dart b/pkg/test_runner/test/test_file_test.dart
index 6bbf66e..b2988d3 100644
--- a/pkg/test_runner/test/test_file_test.dart
+++ b/pkg/test_runner/test/test_file_test.dart
@@ -26,7 +26,6 @@
   testParsePackages();
   testParseExperiments();
   testParseMultitest();
-  testParseMultiHtmltest();
   testParseErrorFlags();
   testParseErrorExpectations();
   testName();
@@ -246,31 +245,6 @@
   Expect.isTrue(file.isMultitest);
 }
 
-void testParseMultiHtmltest() {
-  // Not present.
-  var file = parseTestFile("");
-  Expect.isFalse(file.isMultiHtmlTest);
-  Expect.listEquals(<String>[], file.subtestNames);
-
-  // Present.
-  // Note: the "${''}" is to prevent the test runner running *this* test file
-  // from parsing it as a multi-HTML test.
-  file = parseTestFile("""
-  main() {
-    useHtml\IndividualConfiguration();
-    group('pixel_manipulation', () {
-    });
-    group('arc', () {
-    });
-    group('drawImage_image_element', () {
-    });
-  }
-  """);
-  Expect.isTrue(file.isMultiHtmlTest);
-  Expect.listEquals(["pixel_manipulation", "arc", "drawImage_image_element"],
-      file.subtestNames);
-}
-
 void testParseErrorFlags() {
   // Not present.
   var file = parseTestFile("");
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 5cd0297..050407d 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -251,11 +251,19 @@
 // the full (isolate specific) environment as a finite, static map.
 class EnvironmentMap extends UnmodifiableMapBase<String, String> {
   @override
+  bool containsKey(Object key) {
+    return new bool.hasEnvironment(key);
+  }
+
+  @override
   String operator [](Object key) {
     // The fromEnvironment constructor is specified to throw when called using
     // new. However, the VM implementation actually looks up the given name in
     // the environment.
-    return new String.fromEnvironment(key);
+    if (containsKey(key)) {
+      return new String.fromEnvironment(key);
+    }
+    return null;
   }
 
   @override
diff --git a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
index a272248..83bcdd1 100644
--- a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
+++ b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
@@ -29,11 +29,13 @@
 
 void _treeshakeProtos(Target target, Component component, CoreTypes coreTypes,
     TransformationInfo info) {
-  globalTypeFlow.transformComponent(target, coreTypes, component);
+  globalTypeFlow.transformComponent(target, coreTypes, component,
+      treeShakeSignatures: false);
 
   final collector = removeUnusedProtoReferences(component, coreTypes, info);
   if (collector != null) {
-    globalTypeFlow.transformComponent(target, coreTypes, component);
+    globalTypeFlow.transformComponent(target, coreTypes, component,
+        treeShakeSignatures: false);
     if (info != null) {
       for (Class gmSubclass in collector.gmSubclasses) {
         if (!gmSubclass.enclosingLibrary.classes.contains(gmSubclass)) {
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 0986c3c..1850641 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -1405,6 +1405,11 @@
   List<VariableDeclaration> uncheckedParameters(Member member) =>
       _summaries[member]?.uncheckedParameters;
 
+  // The set of optional and named parameters to this procedure which
+  // are passed at all call-sites.
+  Set<String> alwaysPassedOptionalParameters(Member member) =>
+      _summaries[member]?.alwaysPassedOptionalParameters() ?? const {};
+
   bool isTearOffTaken(Member member) => _tearOffTaken.contains(member);
 
   /// Returns true if this member is called on a receiver with static type
diff --git a/pkg/vm/lib/transformations/type_flow/calls.dart b/pkg/vm/lib/transformations/type_flow/calls.dart
index d0c284e..06b20ec 100644
--- a/pkg/vm/lib/transformations/type_flow/calls.dart
+++ b/pkg/vm/lib/transformations/type_flow/calls.dart
@@ -179,15 +179,21 @@
 class Args<T extends TypeExpr> {
   final List<T> values;
   final List<String> names;
+
+  // Whether it is not known which optional arguments are passed or not.
+  final bool unknownArity;
+
   int _hashCode;
 
-  Args(this.values, {this.names = const <String>[]}) {
+  Args(this.values,
+      {this.names = const <String>[], this.unknownArity = false}) {
     assertx(isSorted(names));
   }
 
   Args.withReceiver(Args<T> args, T receiver)
       : values = new List.from(args.values),
-        names = args.names {
+        names = args.names,
+        unknownArity = args.unknownArity {
     values[0] = receiver;
   }
 
@@ -207,6 +213,7 @@
     for (var n in names) {
       hash = (((hash * 31) & kHashMask) + n.hashCode) & kHashMask;
     }
+    if (unknownArity) hash ^= -1;
     return hash;
   }
 
@@ -226,7 +233,7 @@
           return false;
         }
       }
-      return true;
+      return unknownArity == other.unknownArity;
     }
     return false;
   }
@@ -249,7 +256,11 @@
       buf.write(': ');
       buf.write(values[positionalCount + i]);
     }
-    buf.write(")");
+    if (unknownArity) {
+      buf.write(", <unknown arity>)");
+    } else {
+      buf.write(")");
+    }
     return buf.toString();
   }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index f4575d0..18f0a87 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -73,42 +73,42 @@
   @override
   visitProcedure(Procedure proc) {
     var type = _annotationsDefineRoot(proc.annotations);
-    if (type != null) {
-      void addSelector(CallKind ck) {
-        entryPoints.addRawCall(proc.isInstanceMember
-            ? new InterfaceSelector(proc, callKind: ck)
-            : new DirectSelector(proc, callKind: ck));
-      }
+    if (type == null) return;
 
-      final defaultCallKind = proc.isGetter
-          ? CallKind.PropertyGet
-          : (proc.isSetter ? CallKind.PropertySet : CallKind.Method);
-
-      switch (type) {
-        case PragmaEntryPointType.CallOnly:
-          addSelector(defaultCallKind);
-          break;
-        case PragmaEntryPointType.SetterOnly:
-          if (!proc.isSetter) {
-            throw "Error: cannot generate a setter for a method or getter ($proc).";
-          }
-          addSelector(CallKind.PropertySet);
-          break;
-        case PragmaEntryPointType.GetterOnly:
-          if (proc.isSetter) {
-            throw "Error: cannot closurize a setter ($proc).";
-          }
-          addSelector(CallKind.PropertyGet);
-          break;
-        case PragmaEntryPointType.Default:
-          addSelector(defaultCallKind);
-          if (!proc.isSetter && !proc.isGetter) {
-            addSelector(CallKind.PropertyGet);
-          }
-      }
-
-      nativeCodeOracle.setMemberReferencedFromNativeCode(proc);
+    void addSelector(CallKind ck) {
+      entryPoints.addRawCall(proc.isInstanceMember
+          ? new InterfaceSelector(proc, callKind: ck)
+          : new DirectSelector(proc, callKind: ck));
     }
+
+    final defaultCallKind = proc.isGetter
+        ? CallKind.PropertyGet
+        : (proc.isSetter ? CallKind.PropertySet : CallKind.Method);
+
+    switch (type) {
+      case PragmaEntryPointType.CallOnly:
+        addSelector(defaultCallKind);
+        break;
+      case PragmaEntryPointType.SetterOnly:
+        if (!proc.isSetter) {
+          throw "Error: cannot generate a setter for a method or getter ($proc).";
+        }
+        addSelector(CallKind.PropertySet);
+        break;
+      case PragmaEntryPointType.GetterOnly:
+        if (proc.isSetter) {
+          throw "Error: cannot closurize a setter ($proc).";
+        }
+        addSelector(CallKind.PropertyGet);
+        break;
+      case PragmaEntryPointType.Default:
+        addSelector(defaultCallKind);
+        if (!proc.isSetter && !proc.isGetter) {
+          addSelector(CallKind.PropertyGet);
+        }
+    }
+
+    nativeCodeOracle.setMemberReferencedFromNativeCode(proc);
   }
 
   @override
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index cab8e4d..3d190a6 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -7,7 +7,7 @@
 
 import 'dart:core' hide Type;
 
-import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
+import 'package:kernel/ast.dart' hide Statement, StatementVisitor, MapEntry;
 
 import 'calls.dart';
 import 'types.dart';
@@ -74,6 +74,9 @@
   Type defaultValue;
   Type _argumentType = const EmptyType();
 
+  // Whether this parameter is passed at all call-sites.
+  bool isAlwaysPassed = true;
+
   Parameter(this.name, this.staticTypeForNarrowing);
 
   @override
@@ -103,6 +106,13 @@
     _argumentType = _argumentType.union(argType, typeHierarchy);
     assertx(_argumentType.isSpecialized);
   }
+
+  Type _observeNotPassed(TypeHierarchy typeHierarchy) {
+    isAlwaysPassed = false;
+    final Type argType = defaultValue.specialize(typeHierarchy);
+    _observeArgumentType(argType, typeHierarchy);
+    return argType;
+  }
 }
 
 /// Narrows down [arg] to [type].
@@ -558,6 +568,12 @@
 
     List<Type> types = new List<Type>(_statements.length);
 
+    if (arguments.unknownArity) {
+      for (int i = 0; i < parameterCount; ++i) {
+        (_statements[i] as Parameter).isAlwaysPassed = false;
+      }
+    }
+
     for (int i = 0; i < positionalArgCount; i++) {
       final Parameter param = _statements[i] as Parameter;
       if (args[i] is RuntimeType) {
@@ -576,10 +592,7 @@
     }
 
     for (int i = positionalArgCount; i < positionalParameterCount; i++) {
-      final Parameter param = _statements[i] as Parameter;
-      final argType = param.defaultValue.specialize(typeHierarchy);
-      param._observeArgumentType(argType, typeHierarchy);
-      types[i] = argType;
+      types[i] = (_statements[i] as Parameter)._observeNotPassed(typeHierarchy);
     }
 
     final argNames = arguments.names;
@@ -601,9 +614,7 @@
       } else {
         assertx((argIndex == namedArgCount) ||
             (param.name.compareTo(argNames[argIndex]) < 0));
-        final argType = param.defaultValue.specialize(typeHierarchy);
-        param._observeArgumentType(argType, typeHierarchy);
-        types[i] = argType;
+        types[i] = param._observeNotPassed(typeHierarchy);
       }
     }
     assertx(argIndex == namedArgCount);
@@ -651,4 +662,15 @@
     }
     return params;
   }
+
+  Set<String> alwaysPassedOptionalParameters() {
+    final params = Set<String>();
+    for (int i = requiredParameterCount; i < parameterCount; ++i) {
+      final Parameter p = _statements[i] as Parameter;
+      if (p.isAlwaysPassed) {
+        params.add(p.name);
+      }
+    }
+    return params;
+  }
 }
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 41c2526..a6edc90 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -807,7 +807,7 @@
         break;
     }
 
-    return new Args<Type>(args, names: names);
+    return new Args<Type>(args, names: names, unknownArity: true);
   }
 
   TypeExpr _visit(TreeNode node) => node.accept(this);
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 21f0456..296bc42 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -13,6 +13,7 @@
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/library_index.dart' show LibraryIndex;
 import 'package:kernel/type_environment.dart';
+import 'package:kernel/external_name.dart';
 
 import 'analysis.dart';
 import 'calls.dart';
@@ -37,7 +38,7 @@
 /// Assumes strong mode and closed world.
 Component transformComponent(
     Target target, CoreTypes coreTypes, Component component,
-    [PragmaAnnotationParser matcher]) {
+    {PragmaAnnotationParser matcher, bool treeShakeSignatures: true}) {
   void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
   final hierarchy = new ClassHierarchy(component, coreTypes,
       onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
@@ -70,7 +71,9 @@
 
   final transformsStopWatch = new Stopwatch()..start();
 
-  new TreeShaker(component, typeFlowAnalysis).transformComponent(component);
+  final treeShaker = new TreeShaker(component, typeFlowAnalysis,
+      treeShakeSignatures: treeShakeSignatures)
+    ..transformComponent(component);
 
   new TFADevirtualization(component, typeFlowAnalysis, hierarchy)
       .visitComponent(component);
@@ -82,6 +85,8 @@
   new AnnotateKernel(component, typeFlowAnalysis, unboxingInfo)
       .visitComponent(component);
 
+  treeShaker.finalizeSignatures();
+
   transformsStopWatch.stop();
 
   statPrint("TF analysis took ${analysisStopWatch.elapsedMilliseconds}ms");
@@ -561,12 +566,16 @@
   _TreeShakerConstantVisitor constantVisitor;
   _TreeShakerPass1 _pass1;
   _TreeShakerPass2 _pass2;
+  _SignatureShaker _signatureShaker;
 
-  TreeShaker(Component component, this.typeFlowAnalysis) {
+  TreeShaker(Component component, this.typeFlowAnalysis,
+      {bool treeShakeSignatures: true}) {
     typeVisitor = new _TreeShakerTypeVisitor(this);
     constantVisitor = new _TreeShakerConstantVisitor(this, typeVisitor);
     _pass1 = new _TreeShakerPass1(this);
     _pass2 = new _TreeShakerPass2(this);
+    _signatureShaker = new _SignatureShaker(this.typeFlowAnalysis,
+        treeShakeSignatures: treeShakeSignatures);
   }
 
   transformComponent(Component component) {
@@ -574,6 +583,10 @@
     _pass2.transform(component);
   }
 
+  finalizeSignatures() {
+    _signatureShaker.transform();
+  }
+
   bool isClassReferencedFromNativeCode(Class c) =>
       typeFlowAnalysis.nativeCodeOracle.isClassReferencedFromNativeCode(c);
   bool isClassUsed(Class c) => _usedClasses.contains(c);
@@ -728,9 +741,24 @@
 /// transforms unreachable calls into 'throw' expressions.
 class _TreeShakerPass1 extends Transformer {
   final TreeShaker shaker;
+  final TypeEnvironment environment;
+  final List<Initializer> additionalInitializers = [];
   Procedure _unsafeCast;
 
-  _TreeShakerPass1(this.shaker);
+  StaticTypeContext _staticTypeContext;
+  Member _currentMember;
+
+  StaticTypeContext get staticTypeContext =>
+      _staticTypeContext ??= StaticTypeContext(currentMember, environment);
+
+  Member get currentMember => _currentMember;
+  set currentMember(Member m) {
+    _currentMember = m;
+    _staticTypeContext = null;
+  }
+
+  _TreeShakerPass1(this.shaker)
+      : environment = shaker.typeFlowAnalysis.environment;
 
   void transform(Component component) {
     component.transformChildren(this);
@@ -831,12 +859,27 @@
   }
 
   @override
+  Constructor visitConstructor(Constructor node) {
+    additionalInitializers.clear();
+    node = defaultMember(node);
+    if (additionalInitializers.isNotEmpty) {
+      assertx(node.initializers.last is SuperInitializer ||
+          node.initializers.last is RedirectingInitializer);
+      additionalInitializers.forEach((i) => i.parent = node);
+      node.initializers
+          .insertAll(node.initializers.length - 1, additionalInitializers);
+    }
+    return node;
+  }
+
+  @override
   TreeNode defaultMember(Member node) {
     if (shaker.isMemberBodyReachable(node)) {
       if (kPrintTrace) {
         tracePrint("Visiting $node");
       }
       shaker.addUsedMember(node);
+      currentMember = node;
       node.transformChildren(this);
     } else if (shaker.isMemberReferencedFromNativeCode(node)) {
       // Preserve members referenced from native code to satisfy lookups, even
@@ -951,15 +994,99 @@
     }
   }
 
+  Expression _fixArgumentEvaluationOrder(
+      Expression invocation, Arguments args) {
+    if (args.named.isEmpty) return invocation;
+
+    Expression outer = invocation;
+    int argIdx = args.named.length + args.positional.length;
+    for (int i = args.named.length - 1; i >= 0; --i) {
+      final arg = args.named[i];
+      final variable = VariableDeclaration("#arg${argIdx--}",
+          initializer: arg.value,
+          type: arg.value.getStaticType(staticTypeContext));
+      arg.value = VariableGet(variable)..parent = arg;
+      outer = Let(variable, outer);
+    }
+    for (int i = args.positional.length - 1; i >= 0; --i) {
+      final variable = VariableDeclaration("#arg${argIdx--}",
+          initializer: args.positional[i],
+          type: args.positional[i].getStaticType(staticTypeContext));
+      args.positional[i] = VariableGet(variable)..parent = args;
+      outer = Let(variable, outer);
+    }
+    return outer;
+  }
+
+  void _fixArgumentEvaluationOrderInInitializer(Arguments args) {
+    if (args.named.isEmpty) return;
+
+    int argIndex = 0;
+    for (int i = 0; i < args.positional.length; ++i) {
+      final variable = VariableDeclaration("#arg${argIndex++}",
+          initializer: args.positional[i]);
+      args.positional[i] = VariableGet(variable)..parent = args;
+      additionalInitializers.add(LocalInitializer(variable));
+    }
+    for (int i = 0; i < args.named.length; ++i) {
+      final variable = VariableDeclaration("#arg${argIndex++}",
+          initializer: args.named[i].value);
+      args.named[i].value = VariableGet(variable)..parent = args.named[i];
+      additionalInitializers.add(LocalInitializer(variable));
+    }
+  }
+
+  void _rewriteArguments(Arguments args, Member member) {
+    final alwaysPassedParams =
+        shaker.typeFlowAnalysis.alwaysPassedOptionalParameters(member);
+    final func = member.function;
+    final positional = args.positional.toList();
+    final newPositional = args.positional;
+    newPositional.removeRange(
+        func.requiredParameterCount, newPositional.length);
+
+    for (int i = func.requiredParameterCount; i < positional.length; ++i) {
+      if (alwaysPassedParams.contains(func.positionalParameters[i].name)) {
+        newPositional.add(positional[i]);
+      }
+    }
+
+    final newNamed = <NamedExpression>[];
+    final namedPositionals = <NamedExpression>[];
+    for (int i = 0; i < args.named.length; i++) {
+      final arg = args.named[i];
+      if (alwaysPassedParams.contains(arg.name)) {
+        namedPositionals.add(arg);
+      } else {
+        newNamed.add(arg);
+      }
+    }
+    args.named = newNamed;
+    namedPositionals.sort((x, y) => x.name.compareTo(y.name));
+    newPositional
+        .addAll(namedPositionals.map((expr) => expr.value..parent = args));
+
+    for (int i = func.requiredParameterCount; i < positional.length; ++i) {
+      if (!alwaysPassedParams.contains(func.positionalParameters[i].name)) {
+        newPositional.add(positional[i]);
+      }
+    }
+  }
+
   @override
   TreeNode visitStaticInvocation(StaticInvocation node) {
     node.transformChildren(this);
     if (_isUnreachable(node)) {
       return _makeUnreachableCall(_flattenArguments(node.arguments));
-    } else {
-      assertx(shaker.isMemberBodyReachable(node.target), details: node.target);
-      return node;
     }
+
+    final target = node.target;
+    assertx(shaker.isMemberBodyReachable(target), details: target);
+
+    if (!shaker._signatureShaker.isShakingSignature(target)) return node;
+    final result = _fixArgumentEvaluationOrder(node, node.arguments);
+    _rewriteArguments(node.arguments, target);
+    return result;
   }
 
   @override
@@ -1039,7 +1166,10 @@
         assertx(node.isConst);
         shaker.addUsedMember(node.target);
       }
-      return node;
+      if (!shaker._signatureShaker.isShakingSignature(node.target)) return node;
+      final result = _fixArgumentEvaluationOrder(node, node.arguments);
+      _rewriteArguments(node.arguments, node.target);
+      return result;
     }
   }
 
@@ -1050,6 +1180,9 @@
       return _makeUnreachableInitializer(_flattenArguments(node.arguments));
     } else {
       assertx(shaker.isMemberBodyReachable(node.target), details: node.target);
+      if (!shaker._signatureShaker.isShakingSignature(node.target)) return node;
+      _fixArgumentEvaluationOrderInInitializer(node.arguments);
+      _rewriteArguments(node.arguments, node.target);
       return node;
     }
   }
@@ -1061,6 +1194,9 @@
       return _makeUnreachableInitializer(_flattenArguments(node.arguments));
     } else {
       // Can't assert that node.target is used due to partial mixin resolution.
+      if (!shaker._signatureShaker.isShakingSignature(node.target)) return node;
+      _fixArgumentEvaluationOrderInInitializer(node.arguments);
+      _rewriteArguments(node.arguments, node.target);
       return node;
     }
   }
@@ -1112,7 +1248,7 @@
 
 /// The second pass of [TreeShaker]. It is called after set of used
 /// classes, members and typedefs is determined during the first pass.
-/// This pass visits classes and members and removes unused classes and member.
+/// This pass visits classes and members and removes unused classes and members.
 /// Bodies of unreachable but used members are replaced with 'throw'
 /// expressions. This pass does not dive deeper than member level.
 class _TreeShakerPass2 extends Transformer {
@@ -1191,6 +1327,34 @@
       node.enclosingClass.isEnum;
 
   @override
+  Member visitProcedure(Procedure proc) {
+    proc = defaultMember(proc);
+    if (proc == null || !shaker._signatureShaker.isShakingSignature(proc)) {
+      return proc;
+    }
+    final optionals =
+        shaker.typeFlowAnalysis.alwaysPassedOptionalParameters(proc);
+    if (optionals.isNotEmpty) {
+      shaker._signatureShaker.defer(proc);
+    }
+    return proc;
+  }
+
+  @override
+  Member visitConstructor(Constructor ctor) {
+    ctor = defaultMember(ctor);
+    if (ctor == null || !shaker._signatureShaker.isShakingSignature(ctor)) {
+      return ctor;
+    }
+    final optionals =
+        shaker.typeFlowAnalysis.alwaysPassedOptionalParameters(ctor);
+    if (optionals.isNotEmpty) {
+      shaker._signatureShaker.defer(ctor);
+    }
+    return ctor;
+  }
+
+  @override
   Member defaultMember(Member node) {
     if (!shaker.isMemberUsed(node) && !_preserveSpecialMember(node)) {
       node.canonicalName?.unbind();
@@ -1267,6 +1431,84 @@
   }
 }
 
+// Transform signatures of functions to convert optional named and
+// positional parameters to required parameters if we know that all call sites
+// will pass them.
+//
+// Because the AnnotateKernel pass expects signatures to match up with the
+// corresponding summaries, we enqueue the functions which need to be transformed
+// during the _TreeShakerPass1 and delay the actual transformation until after
+// AnnotateKernel has run.
+class _SignatureShaker {
+  final TypeFlowAnalysis analysis;
+  final List<Member> deferred = [];
+  final bool treeShakeSignatures;
+  _SignatureShaker(this.analysis, {this.treeShakeSignatures});
+
+  bool isShakingSignature(Member member) {
+    if (!treeShakeSignatures) return false;
+    if (member is Procedure && member.isStatic || member is Constructor) {
+      if (getExternalName(member) != null) {
+        // This member has a native implementation which we cannot rewrite
+        // to accomodate the new signature.
+        return false;
+      }
+    } else {
+      return false;
+    }
+    final alwaysPassedParams = analysis.alwaysPassedOptionalParameters(member);
+    return alwaysPassedParams.isNotEmpty;
+  }
+
+  void defer(Member m) {
+    assertx(isShakingSignature(m));
+    deferred.add(m);
+  }
+
+  void transform() => deferred.forEach(_update);
+
+  void _update(Member member) {
+    final alwaysPassedOptionals =
+        analysis.alwaysPassedOptionalParameters(member);
+    assertx(alwaysPassedOptionals.isNotEmpty);
+
+    final func = member.function;
+    final newPositional =
+        func.positionalParameters.sublist(0, func.requiredParameterCount);
+    final optionalPositional =
+        func.positionalParameters.sublist(func.requiredParameterCount);
+
+    for (final param in optionalPositional) {
+      if (alwaysPassedOptionals.contains(param.name)) {
+        newPositional.add(param..initializer = null);
+      }
+    }
+
+    final namedPositionals = <VariableDeclaration>[];
+    final namedParameters = <VariableDeclaration>[];
+    for (final param in func.namedParameters) {
+      if (alwaysPassedOptionals.contains(param.name)) {
+        namedPositionals.add(param..initializer = null);
+      } else {
+        namedParameters.add(param);
+      }
+    }
+    namedPositionals.sort((x, y) => x.name.compareTo(y.name));
+    newPositional.addAll(namedPositionals);
+
+    func.requiredParameterCount = newPositional.length;
+
+    for (final param in optionalPositional) {
+      if (!alwaysPassedOptionals.contains(param.name)) {
+        newPositional.add(param);
+      }
+    }
+
+    func.positionalParameters = newPositional;
+    func.namedParameters = namedParameters;
+  }
+}
+
 class _TreeShakerConstantVisitor extends ConstantVisitor<Null> {
   final TreeShaker shaker;
   final _TreeShakerTypeVisitor typeVisitor;
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index b51cbd3..29a5606 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -26,7 +26,7 @@
   final coreTypes = new CoreTypes(component);
 
   component = transformComponent(target, coreTypes, component,
-      new ConstantPragmaAnnotationParser(coreTypes));
+      matcher: new ConstantPragmaAnnotationParser(coreTypes));
 
   final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
 
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index bfec723..02d8487 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -591,11 +591,18 @@
   AssertAssignable     0, CP#5
   Drop1
 L2:
+  Push                 FP[-6]
+  PushConstant         CP#6
+  PushNull
+  PushNull
+  PushConstant         CP#7
+  AssertAssignable     1, CP#8
+  Drop1
   PushNull
   ReturnTOS
 }
-Parameter flags: [0, 0, 2]
-Default function type arguments: CP#6
+Parameter flags: [0, 1, 2]
+Default function type arguments: CP#9
 ConstantPool {
   [0] = TypeArgumentsField #lib::H
   [1] = Type #lib::H::foo8::TypeParam/0
@@ -603,7 +610,10 @@
   [3] = ObjectRef 'Q'
   [4] = ObjectRef 'c'
   [5] = SubtypeTestCache
-  [6] = ObjectRef < #lib::H::TypeParam/0 >
+  [6] = Type dart:core::int
+  [7] = ObjectRef 'b'
+  [8] = SubtypeTestCache
+  [9] = ObjectRef < #lib::H::TypeParam/0 >
 }
 
 
@@ -734,7 +744,7 @@
     synthetic constructor •() → #lib::H<#lib::H::T*>*
       : super #lib::G::•()
       ;
-    method foo8<generic-covariant-impl Q extends #lib::H::T* = #lib::H::T*>(#lib::H::foo8::Q* a, dart.core::int* b, generic-covariant-impl #lib::H::T* c) → void {}
+    method foo8<generic-covariant-impl Q extends #lib::H::T* = #lib::H::T*>(#lib::H::foo8::Q* a, covariant dart.core::int* b, generic-covariant-impl #lib::H::T* c) → void {}
     forwarding-stub method foo7<generic-covariant-impl Q extends #lib::H::T*>(#lib::H::foo7::Q* a, covariant dart.core::num* b, generic-covariant-impl #lib::H::T* c) → void
       return super.{#lib::G::foo7}<#lib::H::foo7::Q*>(a, b, c);
   }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
index 1469023..e683026 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -42,7 +42,7 @@
 static method callerA2([@vm.inferred-type.metadata=#lib::B] self::A* aa) → void {
   [@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}();
 }
-static method callerA3({[@vm.inferred-type.metadata=#lib::C] self::A* aa = #C1}) → void {
+static method callerA3([@vm.inferred-type.metadata=#lib::C] self::A* aa) → void {
   [@vm.direct-call.metadata=#lib::C::foo] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}();
 }
 static method callerA4([@vm.inferred-type.metadata=#lib::D?] self::A* aa) → void {
@@ -58,7 +58,7 @@
   self::callerA1(new self::B::•());
   self::callerA1(new self::C::•());
   self::callerA2(new self::B::•());
-  self::callerA3(aa: new self::C::•());
+  let self::C* #arg1 = new self::C::•() in self::callerA3(#arg1);
   self::callerA4([@vm.inferred-type.metadata=#lib::D?] self::dd);
   self::dd = new self::D::•();
   self::callerE1("abc");
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
new file mode 100644
index 0000000..b941651
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Test that optimization of named parameters doesn't change evaluation order.
+
+import 'dart:math';
+import 'package:expect/expect.dart';
+
+int global = 0;
+
+int inc() => ++global;
+int dec() => global = max(0, --global);
+
+// When converting named parameters to positional parameters, we
+// follow alphabetical order. Ensure that argument evaluation order
+// is unchanged.
+void testNamedOrder(int w, {int z, int y, int x}) {
+  Expect.equals(w, 1);
+  Expect.equals(z, 2);
+  Expect.equals(y, 3);
+  Expect.equals(x, 2);
+}
+
+class TestNamedOrderBase {
+  TestNamedOrderBase(w, {int z, int y, int x}) {
+    testNamedOrder(w, z: z, y: y, x: x);
+  }
+}
+
+class TestNamedOrderSub extends TestNamedOrderBase {
+  int x;
+  TestNamedOrderSub()
+      : x = dec(),
+        super(inc(), z: inc(), y: inc(), x: dec()) {
+    Expect.equals(x, 0);
+  }
+}
+
+main() {
+  testNamedOrder(inc(), z: inc(), y: inc(), x: dec());
+  global = 1;
+  TestNamedOrderSub();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
new file mode 100644
index 0000000..1fa6312
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/named_params_shaking_test.dart.expect
@@ -0,0 +1,39 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+import "package:expect/expect.dart" as exp;
+import "dart:math" as math;
+
+import "dart:math";
+import "package:expect/expect.dart";
+
+abstract class TestNamedOrderBase extends core::Object {
+[@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] dynamic w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → self::TestNamedOrderBase*
+    : super core::Object::•() {
+    let core::int* #arg1 = _in::unsafeCast<core::int*>(w) in let core::int* #arg2 = z in let core::int* #arg3 = y in let core::int* #arg4 = x in self::testNamedOrder(#arg1, #arg4, #arg3, #arg2);
+  }
+}
+class TestNamedOrderSub extends self::TestNamedOrderBase {
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  field core::int* x;
+  constructor •() → self::TestNamedOrderSub*
+    : self::TestNamedOrderSub::x = [@vm.inferred-type.metadata=int] self::dec(), dynamic #arg0 = [@vm.inferred-type.metadata=int] self::inc(), dynamic #arg1 = [@vm.inferred-type.metadata=int] self::inc(), dynamic #arg2 = [@vm.inferred-type.metadata=int] self::inc(), dynamic #arg3 = [@vm.inferred-type.metadata=int] self::dec(), super self::TestNamedOrderBase::•(#arg0, #arg3, #arg2, #arg1) {
+    exp::Expect::equals([@vm.direct-call.metadata=#lib::TestNamedOrderSub::x] [@vm.inferred-type.metadata=int] this.{self::TestNamedOrderSub::x}, 0);
+  }
+}
+[@vm.inferred-type.metadata=int?]static field core::int* global = 0;
+[@vm.unboxing-info.metadata=()->i]static method inc() → core::int*
+  return self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::+??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::+}(1);
+[@vm.unboxing-info.metadata=()->i]static method dec() → core::int*
+  return self::global = [@vm.inferred-type.metadata=int] math::max<core::int*>(0, self::global = [@vm.direct-call.metadata=dart.core::_IntegerImplementation::-??] [@vm.inferred-type.metadata=int (skip check)] [@vm.inferred-type.metadata=int?] self::global.{core::num::-}(1));
+[@vm.unboxing-info.metadata=(i)->b]static method testNamedOrder([@vm.inferred-type.metadata=int] core::int* w, [@vm.inferred-type.metadata=int] core::int* x, [@vm.inferred-type.metadata=int] core::int* y, [@vm.inferred-type.metadata=int] core::int* z) → void {
+  exp::Expect::equals(w, 1);
+  exp::Expect::equals(z, 2);
+  exp::Expect::equals(y, 3);
+  exp::Expect::equals(x, 2);
+}
+static method main() → dynamic {
+  let core::int* #arg1 = [@vm.inferred-type.metadata=int] self::inc() in let core::int* #arg2 = [@vm.inferred-type.metadata=int] self::inc() in let core::int* #arg3 = [@vm.inferred-type.metadata=int] self::inc() in let core::int* #arg4 = [@vm.inferred-type.metadata=int] self::dec() in self::testNamedOrder(#arg1, #arg4, #arg3, #arg2);
+  self::global = 1;
+  new self::TestNamedOrderSub::•();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
index 186aedb..25761a4 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method.dart.expect
@@ -14,8 +14,8 @@
 static get smiOrMint() → core::int*
   return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
 [@vm.unboxing-info.metadata=(i,i,d,b,b,b,b,b,b)->b]static method takePositional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
-static method takeOptional([[@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi = #C1, [@vm.inferred-type.metadata=int] dynamic unboxedInt = #C1, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble = #C1, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt = #C1, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble = #C1, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX = #C1, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX = #C1]) → void {}
-static method takeNamed({[@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi = #C1, [@vm.inferred-type.metadata=int] dynamic unboxedInt = #C1, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble = #C1, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt = #C1, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble = #C1, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX = #C1, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX = #C1}) → void {}
+static method takeOptional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
+static method takeNamed([@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi) → void {}
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
   return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
@@ -37,7 +37,7 @@
 static method main() → dynamic {
   self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
   self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
-  self::takeNamed(unboxedSmi: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, unboxedInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, unboxedDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, boxedNullableInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, boxedNullableDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, boxedIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, boxedNullableIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, boxedNullableX: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, boxedX: new self::X::•());
+  let core::int* #arg1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let core::int* #arg2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let core::double* #arg3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let core::int* #arg4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let core::double* #arg5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let core::num* #arg6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let core::num* #arg7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let self::X* #arg8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let self::X* #arg9 = new self::X::•() in self::takeNamed(#arg6, #arg5, #arg4, #arg7, #arg8, #arg9, #arg3, #arg2, #arg1);
   self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
   self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
   self::use([@vm.inferred-type.metadata=dart.core::_Double] self::returnUnboxedDouble());
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
index 4bc844d..f0401b1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_static_method_tearoff.dart.expect
@@ -14,8 +14,8 @@
 static get smiOrMint() → core::int*
   return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : [@vm.inferred-type.metadata=int] self::mint;
 static method takePositional(core::int* unboxedSmi, dynamic unboxedInt, dynamic unboxedDouble, dynamic boxedNullableInt, dynamic boxedNullableDouble, dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, dynamic boxedNullableX, dynamic boxedX) → void {}
-static method takeOptional([[@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi = #C1, [@vm.inferred-type.metadata=int] dynamic unboxedInt = #C1, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble = #C1, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt = #C1, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble = #C1, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX = #C1, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX = #C1]) → void {}
-static method takeNamed({[@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi = #C1, [@vm.inferred-type.metadata=int] dynamic unboxedInt = #C1, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble = #C1, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt = #C1, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble = #C1, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble = #C1, dynamic boxedNullableIntOrDouble = #C1, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX = #C1, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX = #C1}) → void {}
+static method takeOptional([@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX) → void {}
+static method takeNamed([@vm.inferred-type.metadata=!] dynamic boxedIntOrDouble, [@vm.inferred-type.metadata=dart.core::_Double?] dynamic boxedNullableDouble, [@vm.inferred-type.metadata=int?] dynamic boxedNullableInt, dynamic boxedNullableIntOrDouble, [@vm.inferred-type.metadata=#lib::X?] dynamic boxedNullableX, [@vm.inferred-type.metadata=#lib::X] dynamic boxedX, [@vm.inferred-type.metadata=dart.core::_Double] dynamic unboxedDouble, [@vm.inferred-type.metadata=int] dynamic unboxedInt, [@vm.inferred-type.metadata=dart.core::_Smi] core::int* unboxedSmi) → void {}
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedSmi() → dynamic
   return [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2;
 [@vm.unboxing-info.metadata=()->i]static method returnUnboxedInt() → dynamic
@@ -37,7 +37,7 @@
 static method main() → dynamic {
   self::takePositional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
   self::takeOptional([@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, new self::X::•());
-  self::takeNamed(unboxedSmi: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2, unboxedInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2, unboxedDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2, boxedNullableInt: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null, boxedNullableDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null, boxedIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1, boxedNullableIntOrDouble: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null, boxedNullableX: [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null, boxedX: new self::X::•());
+  let core::int* #arg1 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} 1 : 2 in let core::int* #arg2 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : 2 in let core::double* #arg3 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : 2.2 in let core::int* #arg4 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::int*} [@vm.inferred-type.metadata=int] self::smiOrMint : null in let core::double* #arg5 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::double*} 1.1 : null in let core::num* #arg6 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 in let core::num* #arg7 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{core::num*} [@vm.inferred-type.metadata=dart.core::bool?] self::kFalse ?{core::num*} [@vm.inferred-type.metadata=int] self::smiOrMint : 1.1 : null in let self::X* #arg8 = [@vm.inferred-type.metadata=dart.core::bool?] self::kTrue ?{self::X*} new self::X::•() : null in let self::X* #arg9 = new self::X::•() in self::takeNamed(#arg6, #arg5, #arg4, #arg7, #arg8, #arg9, #arg3, #arg2, #arg1);
   self::use([@vm.inferred-type.metadata=dart.core::_Smi] self::returnUnboxedSmi());
   self::use([@vm.inferred-type.metadata=int] self::returnUnboxedInt());
   self::use([@vm.inferred-type.metadata=dart.core::_Double] self::returnUnboxedDouble());
@@ -47,6 +47,7 @@
   self::use(self::returnBoxedNullableIntOrDouble());
   self::use([@vm.inferred-type.metadata=#lib::X?] self::returnBoxedNullableX());
   self::use([@vm.inferred-type.metadata=#lib::X] self::returnBoxedX());
+  self::use(#C1);
   self::use(#C2);
   self::use(#C3);
   self::use(#C4);
@@ -56,6 +57,5 @@
   self::use(#C8);
   self::use(#C9);
   self::use(#C10);
-  self::use(#C11);
 }
 static method use(dynamic value) → void {}
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index 69363cf..d7395fc 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -895,7 +895,10 @@
 
   output = "$root_out_dir/gen_kernel_bytecode.dill"
   depfile = "$target_gen_dir/gen_kernel_bytecode.dill.d"
-  outputs = [ output ]
+  outputs = [
+    output,
+    depfile,
+  ]
 
   script = "../../pkg/vm/bin/gen_kernel.dart"
 
diff --git a/runtime/bin/dart_embedder_api_impl.cc b/runtime/bin/dart_embedder_api_impl.cc
index 73974ea..fd2c0e6 100644
--- a/runtime/bin/dart_embedder_api_impl.cc
+++ b/runtime/bin/dart_embedder_api_impl.cc
@@ -7,6 +7,8 @@
 #include "bin/dartutils.h"
 #include "bin/eventhandler.h"
 #include "bin/isolate_data.h"
+#include "bin/process.h"
+#include "bin/secure_socket_filter.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 #include "bin/vmservice_impl.h"
@@ -37,10 +39,24 @@
     return false;
   }
   bin::TimerUtils::InitOnce();
+  bin::Process::Init();
+#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
+  bin::SSLFilter::Init();
+#endif
   bin::EventHandler::Start();
   return true;
 }
 
+void Cleanup() {
+  bin::Process::ClearAllSignalHandlers();
+
+  bin::EventHandler::Stop();
+#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
+  bin::SSLFilter::Cleanup();
+#endif
+  bin::Process::Cleanup();
+}
+
 Dart_Isolate CreateKernelServiceIsolate(const IsolateCreationData& data,
                                         const uint8_t* buffer,
                                         intptr_t buffer_size,
diff --git a/runtime/bin/dart_io_api_impl.cc b/runtime/bin/dart_io_api_impl.cc
index e8ab2ad..18be4c8 100644
--- a/runtime/bin/dart_io_api_impl.cc
+++ b/runtime/bin/dart_io_api_impl.cc
@@ -10,6 +10,7 @@
 #include "bin/io_natives.h"
 #include "bin/platform.h"
 #include "bin/process.h"
+#include "bin/secure_socket_filter.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
 
@@ -19,11 +20,19 @@
 void BootstrapDartIo() {
   // Bootstrap 'dart:io' event handler.
   TimerUtils::InitOnce();
+  Process::Init();
+#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
+  SSLFilter::Init();
+#endif
   EventHandler::Start();
 }
 
 void CleanupDartIo() {
   EventHandler::Stop();
+#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
+  SSLFilter::Cleanup();
+#endif
+  Process::Cleanup();
 }
 
 void SetSystemTempDirectory(const char* system_temp) {
diff --git a/runtime/bin/exe_utils.cc b/runtime/bin/exe_utils.cc
index f077ad5..81568ab 100644
--- a/runtime/bin/exe_utils.cc
+++ b/runtime/bin/exe_utils.cc
@@ -27,12 +27,20 @@
     target_size = strlen(name);
   }
   Namespace* namespc = Namespace::Create(Namespace::Default());
-  if (File::GetType(namespc, name, false) == File::kIsLink) {
+
+  // We might run into symlinks of symlinks, so make sure we follow the
+  // links all the way. See https://github.com/dart-lang/sdk/issues/41057 for
+  // an example where this happens with brew on MacOS.
+  bool followedSymlink = false;
+  while (File::GetType(namespc, name, false) == File::kIsLink) {
     // Resolve the link without creating Dart scope String.
     name = File::LinkTarget(namespc, name, target, kTargetSize);
     if (name == NULL) {
       return strdup("");
     }
+    followedSymlink = true;
+  }
+  if (followedSymlink) {
     target_size = strlen(name);
   }
   namespc->Release();
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index e1a5afe..ac3baa5 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -860,8 +860,7 @@
       Syslog::PrintErr("VM cleanup failed: %s\n", error);
       free(error);
     }
-    Process::ClearAllSignalHandlers();
-    EventHandler::Stop();
+    dart::embedder::Cleanup();
     Platform::Exit((exit_code != 0) ? exit_code : kErrorExitCode);
   }
   main_isolate = isolate;
@@ -1190,7 +1189,7 @@
 
   error = Dart_Initialize(&init_params);
   if (error != NULL) {
-    EventHandler::Stop();
+    dart::embedder::Cleanup();
     Syslog::PrintErr("VM initialization failed: %s\n", error);
     free(error);
     Platform::Exit(kErrorExitCode);
@@ -1214,8 +1213,8 @@
     Syslog::PrintErr("VM cleanup failed: %s\n", error);
     free(error);
   }
-  Process::ClearAllSignalHandlers();
-  EventHandler::Stop();
+  const intptr_t global_exit_code = Process::GlobalExitCode();
+  dart::embedder::Cleanup();
 
   delete app_snapshot;
   free(app_script_uri);
@@ -1230,7 +1229,7 @@
   // Free environment if any.
   Options::DestroyEnvironment();
 
-  Platform::Exit(Process::GlobalExitCode());
+  Platform::Exit(global_exit_code);
 }
 
 }  // namespace bin
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 5fc2bc5..71a9b42 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -450,7 +450,7 @@
       i++;
     } else if (!DartDevUtils::TryResolveDartDevSnapshotPath(script_name)) {
       Syslog::PrintErr(
-          "Could not find DartDev snapshot and '%s' is not a valid script.",
+          "Could not find DartDev snapshot and '%s' is not a valid script.\n",
           argv[i]);
       Platform::Exit(kErrorExitCode);
     }
diff --git a/runtime/bin/process.h b/runtime/bin/process.h
index 4f34a36..a1aa3b9 100644
--- a/runtime/bin/process.h
+++ b/runtime/bin/process.h
@@ -87,6 +87,9 @@
 
 class Process {
  public:
+  static void Init();
+  static void Cleanup();
+
   // Start a new process providing access to stdin, stdout, stderr and
   // process exit streams.
   static int Start(Namespace* namespc,
diff --git a/runtime/bin/process_android.cc b/runtime/bin/process_android.cc
index 44df4d6..2a01538 100644
--- a/runtime/bin/process_android.cc
+++ b/runtime/bin/process_android.cc
@@ -35,7 +35,7 @@
 namespace bin {
 
 int Process::global_exit_code_ = 0;
-Mutex* Process::global_exit_code_mutex_ = new Mutex();
+Mutex* Process::global_exit_code_mutex_ = nullptr;
 Process::ExitHook Process::exit_hook_ = NULL;
 
 // ProcessInfo is used to map a process id to the file descriptor for
@@ -68,6 +68,9 @@
 // started from Dart.
 class ProcessInfoList {
  public:
+  static void Init();
+  static void Cleanup();
+
   static void AddProcess(pid_t pid, intptr_t fd) {
     MutexLocker locker(mutex_);
     ProcessInfo* info = new ProcessInfo(pid, fd);
@@ -119,7 +122,7 @@
 };
 
 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
-Mutex* ProcessInfoList::mutex_ = new Mutex();
+Mutex* ProcessInfoList::mutex_ = nullptr;
 
 // The exit code handler sets up a separate thread which waits for child
 // processes to terminate. That separate thread can then get the exit code from
@@ -127,6 +130,9 @@
 // event loop.
 class ExitCodeHandler {
  public:
+  static void Init();
+  static void Cleanup();
+
   // Notify the ExitCodeHandler that another process exists.
   static void ProcessStarted() {
     // Multiple isolates could be starting processes at the same
@@ -241,7 +247,7 @@
 bool ExitCodeHandler::running_ = false;
 int ExitCodeHandler::process_count_ = 0;
 bool ExitCodeHandler::terminate_done_ = false;
-Monitor* ExitCodeHandler::monitor_ = new Monitor();
+Monitor* ExitCodeHandler::monitor_ = nullptr;
 
 class ProcessStarter {
  public:
@@ -953,7 +959,7 @@
   return usage.ru_maxrss * KB;
 }
 
-static Mutex* signal_mutex = new Mutex();
+static Mutex* signal_mutex = nullptr;
 static SignalInfo* signal_handlers = NULL;
 static const int kSignalsCount = 7;
 static const int kSignals[kSignalsCount] = {
@@ -1057,6 +1063,54 @@
   }
 }
 
+void ProcessInfoList::Init() {
+  ASSERT(ProcessInfoList::mutex_ == nullptr);
+  ProcessInfoList::mutex_ = new Mutex();
+}
+
+void ProcessInfoList::Cleanup() {
+  ASSERT(ProcessInfoList::mutex_ != nullptr);
+  delete ProcessInfoList::mutex_;
+  ProcessInfoList::mutex_ = nullptr;
+}
+
+void ExitCodeHandler::Init() {
+  ASSERT(ExitCodeHandler::monitor_ == nullptr);
+  ExitCodeHandler::monitor_ = new Monitor();
+}
+
+void ExitCodeHandler::Cleanup() {
+  ASSERT(ExitCodeHandler::monitor_ != nullptr);
+  delete ExitCodeHandler::monitor_;
+  ExitCodeHandler::monitor_ = nullptr;
+}
+
+void Process::Init() {
+  ExitCodeHandler::Init();
+  ProcessInfoList::Init();
+
+  ASSERT(signal_mutex == nullptr);
+  signal_mutex = new Mutex();
+
+  ASSERT(Process::global_exit_code_mutex_ == nullptr);
+  Process::global_exit_code_mutex_ = new Mutex();
+}
+
+void Process::Cleanup() {
+  ClearAllSignalHandlers();
+
+  ASSERT(signal_mutex != nullptr);
+  delete signal_mutex;
+  signal_mutex = nullptr;
+
+  ASSERT(Process::global_exit_code_mutex_ != nullptr);
+  delete Process::global_exit_code_mutex_;
+  Process::global_exit_code_mutex_ = nullptr;
+
+  ProcessInfoList::Cleanup();
+  ExitCodeHandler::Cleanup();
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index 087d875..009560b 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -50,7 +50,7 @@
 namespace bin {
 
 int Process::global_exit_code_ = 0;
-Mutex* Process::global_exit_code_mutex_ = new Mutex();
+Mutex* Process::global_exit_code_mutex_ = nullptr;
 Process::ExitHook Process::exit_hook_ = NULL;
 
 // ProcessInfo is used to map a process id to the file descriptor for
@@ -85,6 +85,9 @@
 // started from Dart.
 class ProcessInfoList {
  public:
+  static void Init();
+  static void Cleanup();
+
   static void AddProcess(zx_handle_t process, intptr_t fd) {
     MutexLocker locker(mutex_);
     ProcessInfo* info = new ProcessInfo(process, fd);
@@ -140,7 +143,7 @@
 };
 
 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
-Mutex* ProcessInfoList::mutex_ = new Mutex();
+Mutex* ProcessInfoList::mutex_ = nullptr;
 
 // The exit code handler sets up a separate thread which waits for child
 // processes to terminate. That separate thread can then get the exit code from
@@ -148,6 +151,9 @@
 // event loop.
 class ExitCodeHandler {
  public:
+  static void Init();
+  static void Cleanup();
+
   // Notify the ExitCodeHandler that another process exists.
   static void Start() {
     // Multiple isolates could be starting processes at the same
@@ -297,7 +303,7 @@
 zx_handle_t ExitCodeHandler::port_ = ZX_HANDLE_INVALID;
 bool ExitCodeHandler::running_ = false;
 bool ExitCodeHandler::terminate_done_ = false;
-Monitor* ExitCodeHandler::monitor_ = new Monitor();
+Monitor* ExitCodeHandler::monitor_ = nullptr;
 
 void Process::TerminateExitCodeHandler() {
   ExitCodeHandler::Terminate();
@@ -812,6 +818,45 @@
 
 void Process::ClearSignalHandler(intptr_t signal, Dart_Port port) {}
 
+void ProcessInfoList::Init() {
+  ASSERT(ProcessInfoList::mutex_ == nullptr);
+  ProcessInfoList::mutex_ = new Mutex();
+}
+
+void ProcessInfoList::Cleanup() {
+  ASSERT(ProcessInfoList::mutex_ != nullptr);
+  delete ProcessInfoList::mutex_;
+  ProcessInfoList::mutex_ = nullptr;
+}
+
+void ExitCodeHandler::Init() {
+  ASSERT(ExitCodeHandler::monitor_ == nullptr);
+  ExitCodeHandler::monitor_ = new Monitor();
+}
+
+void ExitCodeHandler::Cleanup() {
+  ASSERT(ExitCodeHandler::monitor_ != nullptr);
+  delete ExitCodeHandler::monitor_;
+  ExitCodeHandler::monitor_ = nullptr;
+}
+
+void Process::Init() {
+  ExitCodeHandler::Init();
+  ProcessInfoList::Init();
+
+  ASSERT(Process::global_exit_code_mutex_ == nullptr);
+  Process::global_exit_code_mutex_ = new Mutex();
+}
+
+void Process::Cleanup() {
+  ASSERT(Process::global_exit_code_mutex_ != nullptr);
+  delete Process::global_exit_code_mutex_;
+  Process::global_exit_code_mutex_ = nullptr;
+
+  ProcessInfoList::Cleanup();
+  ExitCodeHandler::Cleanup();
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 5d82e1b..0f4106e 100644
--- a/runtime/bin/process_linux.cc
+++ b/runtime/bin/process_linux.cc
@@ -35,7 +35,7 @@
 namespace bin {
 
 int Process::global_exit_code_ = 0;
-Mutex* Process::global_exit_code_mutex_ = new Mutex();
+Mutex* Process::global_exit_code_mutex_ = nullptr;
 Process::ExitHook Process::exit_hook_ = NULL;
 
 // ProcessInfo is used to map a process id to the file descriptor for
@@ -68,6 +68,9 @@
 // started from Dart.
 class ProcessInfoList {
  public:
+  static void Init();
+  static void Cleanup();
+
   static void AddProcess(pid_t pid, intptr_t fd) {
     MutexLocker locker(mutex_);
     ProcessInfo* info = new ProcessInfo(pid, fd);
@@ -119,7 +122,7 @@
 };
 
 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
-Mutex* ProcessInfoList::mutex_ = new Mutex();
+Mutex* ProcessInfoList::mutex_ = nullptr;
 
 // The exit code handler sets up a separate thread which waits for child
 // processes to terminate. That separate thread can then get the exit code from
@@ -127,6 +130,9 @@
 // event loop.
 class ExitCodeHandler {
  public:
+  static void Init();
+  static void Cleanup();
+
   // Notify the ExitCodeHandler that another process exists.
   static void ProcessStarted() {
     // Multiple isolates could be starting processes at the same
@@ -241,7 +247,7 @@
 bool ExitCodeHandler::running_ = false;
 int ExitCodeHandler::process_count_ = 0;
 bool ExitCodeHandler::terminate_done_ = false;
-Monitor* ExitCodeHandler::monitor_ = new Monitor();
+Monitor* ExitCodeHandler::monitor_ = nullptr;
 
 class ProcessStarter {
  public:
@@ -952,7 +958,7 @@
   return usage.ru_maxrss * KB;
 }
 
-static Mutex* signal_mutex = new Mutex();
+static Mutex* signal_mutex = nullptr;
 static SignalInfo* signal_handlers = NULL;
 static const int kSignalsCount = 7;
 static const int kSignals[kSignalsCount] = {
@@ -1053,6 +1059,54 @@
   }
 }
 
+void ProcessInfoList::Init() {
+  ASSERT(ProcessInfoList::mutex_ == nullptr);
+  ProcessInfoList::mutex_ = new Mutex();
+}
+
+void ProcessInfoList::Cleanup() {
+  ASSERT(ProcessInfoList::mutex_ != nullptr);
+  delete ProcessInfoList::mutex_;
+  ProcessInfoList::mutex_ = nullptr;
+}
+
+void ExitCodeHandler::Init() {
+  ASSERT(ExitCodeHandler::monitor_ == nullptr);
+  ExitCodeHandler::monitor_ = new Monitor();
+}
+
+void ExitCodeHandler::Cleanup() {
+  ASSERT(ExitCodeHandler::monitor_ != nullptr);
+  delete ExitCodeHandler::monitor_;
+  ExitCodeHandler::monitor_ = nullptr;
+}
+
+void Process::Init() {
+  ExitCodeHandler::Init();
+  ProcessInfoList::Init();
+
+  ASSERT(signal_mutex == nullptr);
+  signal_mutex = new Mutex();
+
+  ASSERT(Process::global_exit_code_mutex_ == nullptr);
+  Process::global_exit_code_mutex_ = new Mutex();
+}
+
+void Process::Cleanup() {
+  ClearAllSignalHandlers();
+
+  ASSERT(signal_mutex != nullptr);
+  delete signal_mutex;
+  signal_mutex = nullptr;
+
+  ASSERT(Process::global_exit_code_mutex_ != nullptr);
+  delete Process::global_exit_code_mutex_;
+  Process::global_exit_code_mutex_ = nullptr;
+
+  ProcessInfoList::Cleanup();
+  ExitCodeHandler::Cleanup();
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index 536b1b3..df67348 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -34,7 +34,7 @@
 namespace bin {
 
 int Process::global_exit_code_ = 0;
-Mutex* Process::global_exit_code_mutex_ = new Mutex();
+Mutex* Process::global_exit_code_mutex_ = nullptr;
 Process::ExitHook Process::exit_hook_ = NULL;
 
 // ProcessInfo is used to map a process id to the file descriptor for
@@ -67,6 +67,9 @@
 // started from Dart.
 class ProcessInfoList {
  public:
+  static void Init();
+  static void Cleanup();
+
   static void AddProcess(pid_t pid, intptr_t fd) {
     MutexLocker locker(mutex_);
     ProcessInfo* info = new ProcessInfo(pid, fd);
@@ -118,7 +121,7 @@
 };
 
 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
-Mutex* ProcessInfoList::mutex_ = new Mutex();
+Mutex* ProcessInfoList::mutex_ = nullptr;
 
 // The exit code handler sets up a separate thread which waits for child
 // processes to terminate. That separate thread can then get the exit code from
@@ -126,6 +129,9 @@
 // event loop.
 class ExitCodeHandler {
  public:
+  static void Init();
+  static void Cleanup();
+
   // Notify the ExitCodeHandler that another process exists.
   static void ProcessStarted() {
     // Multiple isolates could be starting processes at the same
@@ -237,7 +243,7 @@
 bool ExitCodeHandler::running_ = false;
 int ExitCodeHandler::process_count_ = 0;
 bool ExitCodeHandler::terminate_done_ = false;
-Monitor* ExitCodeHandler::monitor_ = new Monitor();
+Monitor* ExitCodeHandler::monitor_ = nullptr;
 
 class ProcessStarter {
  public:
@@ -976,7 +982,7 @@
   return usage.ru_maxrss;
 }
 
-static Mutex* signal_mutex = new Mutex();
+static Mutex* signal_mutex = nullptr;
 static SignalInfo* signal_handlers = NULL;
 static const int kSignalsCount = 7;
 static const int kSignals[kSignalsCount] = {
@@ -1089,6 +1095,54 @@
   }
 }
 
+void ProcessInfoList::Init() {
+  ASSERT(ProcessInfoList::mutex_ == nullptr);
+  ProcessInfoList::mutex_ = new Mutex();
+}
+
+void ProcessInfoList::Cleanup() {
+  ASSERT(ProcessInfoList::mutex_ != nullptr);
+  delete ProcessInfoList::mutex_;
+  ProcessInfoList::mutex_ = nullptr;
+}
+
+void ExitCodeHandler::Init() {
+  ASSERT(ExitCodeHandler::monitor_ == nullptr);
+  ExitCodeHandler::monitor_ = new Monitor();
+}
+
+void ExitCodeHandler::Cleanup() {
+  ASSERT(ExitCodeHandler::monitor_ != nullptr);
+  delete ExitCodeHandler::monitor_;
+  ExitCodeHandler::monitor_ = nullptr;
+}
+
+void Process::Init() {
+  ExitCodeHandler::Init();
+  ProcessInfoList::Init();
+
+  ASSERT(signal_mutex == nullptr);
+  signal_mutex = new Mutex();
+
+  ASSERT(Process::global_exit_code_mutex_ == nullptr);
+  Process::global_exit_code_mutex_ = new Mutex();
+}
+
+void Process::Cleanup() {
+  ClearAllSignalHandlers();
+
+  ASSERT(signal_mutex != nullptr);
+  delete signal_mutex;
+  signal_mutex = nullptr;
+
+  ASSERT(Process::global_exit_code_mutex_ != nullptr);
+  delete Process::global_exit_code_mutex_;
+  Process::global_exit_code_mutex_ = nullptr;
+
+  ProcessInfoList::Cleanup();
+  ExitCodeHandler::Cleanup();
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
index 4c3c1de..5648867 100644
--- a/runtime/bin/process_win.cc
+++ b/runtime/bin/process_win.cc
@@ -27,7 +27,7 @@
 static const int kWriteHandle = 1;
 
 int Process::global_exit_code_ = 0;
-Mutex* Process::global_exit_code_mutex_ = new Mutex();
+Mutex* Process::global_exit_code_mutex_ = nullptr;
 Process::ExitHook Process::exit_hook_ = NULL;
 
 // ProcessInfo is used to map a process id to the process handle,
@@ -84,6 +84,9 @@
 // started from Dart.
 class ProcessInfoList {
  public:
+  static void Init();
+  static void Cleanup();
+
   static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) {
     // Register a callback to extract the exit code, when the process
     // is signaled.  The callback runs in a independent thread from the OS pool.
@@ -199,7 +202,7 @@
 };
 
 ProcessInfo* ProcessInfoList::active_processes_ = NULL;
-Mutex* ProcessInfoList::mutex_ = new Mutex();
+Mutex* ProcessInfoList::mutex_ = nullptr;
 
 // Types of pipes to create.
 enum NamedPipeType { kInheritRead, kInheritWrite, kInheritNone };
@@ -331,12 +334,13 @@
 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL;
 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL;
 
+static Mutex* initialized_mutex = nullptr;
+static bool load_attempted = false;
+
 static bool EnsureInitialized() {
-  static bool load_attempted = false;
-  static Mutex* mutex = new Mutex();
   HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll");
   if (!load_attempted) {
-    MutexLocker locker(mutex);
+    MutexLocker locker(initialized_mutex);
     if (load_attempted) {
       return (delete_proc_thread_attr_list != NULL);
     }
@@ -943,7 +947,7 @@
 }
 
 static SignalInfo* signal_handlers = NULL;
-static Mutex* signal_mutex = new Mutex();
+static Mutex* signal_mutex = nullptr;
 
 SignalInfo::~SignalInfo() {
   FileHandle* file_handle = reinterpret_cast<FileHandle*>(fd_);
@@ -1051,6 +1055,48 @@
   }
 }
 
+void ProcessInfoList::Init() {
+  ASSERT(ProcessInfoList::mutex_ == nullptr);
+  ProcessInfoList::mutex_ = new Mutex();
+}
+
+void ProcessInfoList::Cleanup() {
+  ASSERT(ProcessInfoList::mutex_ != nullptr);
+  delete ProcessInfoList::mutex_;
+  ProcessInfoList::mutex_ = nullptr;
+}
+
+void Process::Init() {
+  ProcessInfoList::Init();
+
+  ASSERT(signal_mutex == nullptr);
+  signal_mutex = new Mutex();
+
+  ASSERT(initialized_mutex == nullptr);
+  initialized_mutex = new Mutex();
+
+  ASSERT(Process::global_exit_code_mutex_ == nullptr);
+  Process::global_exit_code_mutex_ = new Mutex();
+}
+
+void Process::Cleanup() {
+  ClearAllSignalHandlers();
+
+  ASSERT(signal_mutex != nullptr);
+  delete signal_mutex;
+  signal_mutex = nullptr;
+
+  ASSERT(initialized_mutex != nullptr);
+  delete initialized_mutex;
+  initialized_mutex = nullptr;
+
+  ASSERT(Process::global_exit_code_mutex_ != nullptr);
+  delete Process::global_exit_code_mutex_;
+  Process::global_exit_code_mutex_ = nullptr;
+
+  ProcessInfoList::Cleanup();
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index e99cd4e..5e44275 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -10,6 +10,7 @@
 #include "bin/file.h"
 #include "bin/loader.h"
 #include "bin/platform.h"
+#include "bin/process.h"
 #include "bin/snapshot_utils.h"
 #include "bin/thread.h"
 #include "bin/utils.h"
@@ -355,6 +356,7 @@
   }
 
   bin::TimerUtils::InitOnce();
+  bin::Process::Init();
   bin::EventHandler::Start();
 
   char* error = Flags::ProcessCommandLineFlags(dart_argc, dart_argv);
@@ -393,6 +395,7 @@
   // Apply the filter to all registered benchmarks.
   Benchmark::RunAll(argv[0]);
 
+  bin::Process::TerminateExitCodeHandler();
   error = Dart::Cleanup();
   if (error != nullptr) {
     Syslog::PrintErr("Failed shutdown VM: %s\n", error);
@@ -403,6 +406,7 @@
   TestCaseBase::RunAllRaw();
 
   bin::EventHandler::Stop();
+  bin::Process::Cleanup();
 
   // Print a warning message if no tests or benchmarks were matched.
   if (run_matches == 0) {
diff --git a/runtime/bin/secure_socket_filter.cc b/runtime/bin/secure_socket_filter.cc
index d61c5cb..a713441 100644
--- a/runtime/bin/secure_socket_filter.cc
+++ b/runtime/bin/secure_socket_filter.cc
@@ -30,9 +30,20 @@
 
 bool SSLFilter::library_initialized_ = false;
 // To protect library initialization.
-Mutex* SSLFilter::mutex_ = new Mutex();
+Mutex* SSLFilter::mutex_ = nullptr;
 int SSLFilter::filter_ssl_index;
 
+void SSLFilter::Init() {
+  ASSERT(SSLFilter::mutex_ == nullptr);
+  SSLFilter::mutex_ = new Mutex();
+}
+
+void SSLFilter::Cleanup() {
+  ASSERT(SSLFilter::mutex_ != nullptr);
+  delete SSLFilter::mutex_;
+  SSLFilter::mutex_ = nullptr;
+}
+
 const intptr_t SSLFilter::kInternalBIOSize = 10 * KB;
 const intptr_t SSLFilter::kApproximateSize =
     sizeof(SSLFilter) + (2 * SSLFilter::kInternalBIOSize);
diff --git a/runtime/bin/secure_socket_filter.h b/runtime/bin/secure_socket_filter.h
index e09f0e6..70ad32e 100644
--- a/runtime/bin/secure_socket_filter.h
+++ b/runtime/bin/secure_socket_filter.h
@@ -23,6 +23,9 @@
 
 class SSLFilter : public ReferenceCounted<SSLFilter> {
  public:
+  static void Init();
+  static void Cleanup();
+
   // These enums must agree with those in sdk/lib/io/secure_socket.dart.
   enum BufferIndex {
     kReadPlaintext,
diff --git a/runtime/docs/compiler/type_testing_stubs.md b/runtime/docs/compiler/type_testing_stubs.md
new file mode 100644
index 0000000..e7ddcec
--- /dev/null
+++ b/runtime/docs/compiler/type_testing_stubs.md
@@ -0,0 +1,73 @@
+# Type Testing Stubs
+
+This page describes how type testing stubs (TTS) are implemented.
+
+### Type Tests
+
+Explicit `<obj> as <desination-type>` checks in Dart code (also generated implicitly in CFE) compile
+in the Dart VM's IL to the `AssertAssignable` instruction.
+
+### Type Testing Stubs
+
+A type testing stub is a piece of generated machine code, specialized for a type.
+The `RawAbstractType` has pointer to the entry of this machine code in `type_test_stub_entry_point_`
+(as well as to the corresponding `RawCode`, but that is actually not required for the operation of the stub)
+
+The specialized machine code is self-contained and doesn't need/have an object pool.
+The stub will not setup a frame: In the fast case it will perform the type check and return.
+
+The TTS has a special calling convention which accepts:
+   * the `<obj>` to perform the type test against
+   * the `<destination-type>` to perform the test against
+   * the instantiator type argument vector (if the destination type is not instantiated)
+   * the function type argument vector (if the `<destination-type>` is not instantiated)
+   * a loaded slot from the caller's object pool (which is lazily populated by runtime to contain a `RawSubtypeTestCache` if the TTS was unable to handle the type test).
+
+This calling convention is the same as for the SubtypeTestCache-based implementation.
+
+We distuinguish between different type tests (based on the `<destination-type>`):
+
+#### Simple Subtype ClassId-based range checks
+
+Types of the form `<obj> as Foo<T1, ..., Tn>` where `T1` .. `Tn` are all top-types are performed
+by loading the class id of `<obj>` and checking whether it is contained in the set of all class-id ranges of
+classes directly or transitively extending/implementing `Foo`.
+
+In AOT mode in particular this is very fast because we perform a depth-first preorder numbering of classes, which
+means we have a single range for `as Foo` if `Foo` is not implemented. Otherwise we might have multiple ranges.
+
+This test is exhaustive.
+
+#### Complex Subclass ClassId-based range checks
+
+Types of the form `<obj> as Foo<T1, ..., Tn>` where at least one `Ti` is not a top type are performed by loading the class id of `<obj>` and checking whether it lies inside the subclass ranges. Since we check for direct/indirect subclasses and not implementors (this test is non-exhaustive) we know at which offset the type argument vector is.
+
+We then load the instance type arguments vector `<obj>.<tav>` and perform a type check for each `Ti`. Notice these "inner type checks" are different from the original check: Instead of checking `<some-obj> as <type>` we now have to check whether `<some-type> is <other-type>`. This asymmetry is also the reason why a TTS cannot call other TTS.
+
+For each `Ti` we perform now a check of the form `<obj>.tav[i]` is <Ti>` as follows:
+
+* If `Tx` is an instantiated type of the form `Bar<H1, ..., Hn>` where all `H1`..`Hn` are top-types we perform the same ClassId-based range check as above in the simple case (this test is exhaustive)
+
+* If `Tx` is a type parameter we will load its value (i.e. instantiate it) via the instantiator/function type argument vector and compare `<obj>.tav[i] == <Ti>.value` (this test is non-exhaustive)
+
+#### Fallbacks
+
+If the TTS performed the type test and it succeeded, it will return immediately (fast case). If the type test failed or the TTS was non-exhaustive it will do a tail-call to a `SlowTypeTestStub` which will examine the test to be done and call the much slower SubtypeTestCache based implementation. It will, based on the STC's return value either return successfully or go to runtime to either lazily create/update a SubtypeTestCache or throw an exception.
+
+## AssertAssignable via Type Testing Stubs
+
+The implementation of `AssertAssignable` will perform an in-line ClassId-based range check (based on code size heuristics). If such an inline check fails or the check would be too big, we will do an actual call.
+
+Currently this call always uses TTS in AOT mode (and in JIT mode if the destination type is either a type parameter or an instantiated interface type). To perform the call it will ensure the arguments to the TTS are in the right registers.
+
+If `<destination-type>` is a type parameter we will load its value and call its TTS instead.
+
+## JIT mode
+
+In JIT mode we build the TTS lazily on first involcation (the TTS of types will be initialized to the `LazySpecializeTypeTest` stub). If later on more classes get loaded and the TTS fast path starts failing we re-build the TTS.
+
+After a hot-reload we reset all types to the lazy specialize TTS.
+
+## AOT mode
+
+In AOT mode we try to guess for which types we might need a TTS. For every `AssertAssignable` we remember its `<destination-type>`. If it was a type parameter `T` we also try to see (in a limited way) what can flow into `T` and mark such types for needing a TTS.
diff --git a/runtime/include/dart_embedder_api.h b/runtime/include/dart_embedder_api.h
index c9860dd..e565ebf 100644
--- a/runtime/include/dart_embedder_api.h
+++ b/runtime/include/dart_embedder_api.h
@@ -12,10 +12,20 @@
 namespace embedder {
 
 // Initialize all subsystems of the embedder.
+//
+// Must be called before the `Dart_Initialize()` call to initialize the
+// Dart VM.
+//
 // Returns true on success and false otherwise, in which case error would
 // contain error message.
 DART_WARN_UNUSED_RESULT bool InitOnce(char** error);
 
+// Cleans up all subsystems of the embedder.
+//
+// Must be called after the `Dart_Cleanup()` call to initialize the
+// Dart VM.
+void Cleanup();
+
 // Common arguments that are passed to isolate creation callback and to
 // API methods that create isolates.
 struct IsolateCreationData {
diff --git a/runtime/lib/bool.cc b/runtime/lib/bool.cc
index c52fd71..7a4e416 100644
--- a/runtime/lib/bool.cc
+++ b/runtime/lib/bool.cc
@@ -33,4 +33,15 @@
   return default_value.raw();
 }
 
+DEFINE_NATIVE_ENTRY(Bool_hasEnvironment, 0, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(String, name, arguments->NativeArgAt(1));
+  // Call the embedder to supply us with the environment.
+  const String& env_value =
+      String::Handle(Api::GetEnvironmentValue(thread, name));
+  if (!env_value.IsNull()) {
+    return Bool::True().raw();
+  }
+  return Bool::False().raw();
+}
+
 }  // namespace dart
diff --git a/runtime/observatory/lib/src/elements/library_view.dart b/runtime/observatory/lib/src/elements/library_view.dart
index c452e4d..b9c3d5c 100644
--- a/runtime/observatory/lib/src/elements/library_view.dart
+++ b/runtime/observatory/lib/src/elements/library_view.dart
@@ -140,6 +140,8 @@
   }
 
   void render() {
+    final rootScript = library.rootScript;
+
     children = <Element>[
       navBar(<Element>[
         new NavTopMenuElement(queue: _r.queue).element,
@@ -201,11 +203,13 @@
           _createVariables(),
           new BRElement(),
           _createFunctions(),
-          new HRElement(),
-          new ScriptInsetElement(
-                  _isolate, _library.rootScript, _scripts, _objects, _events,
-                  queue: _r.queue)
-              .element,
+          if (rootScript != null) ...[
+            new HRElement(),
+            new ScriptInsetElement(
+                    _isolate, rootScript, _scripts, _objects, _events,
+                    queue: _r.queue)
+                .element
+          ],
           new HRElement(),
           new ViewFooterElement(queue: _r.queue).element
         ]
diff --git a/runtime/observatory/lib/src/elements/script_ref.dart b/runtime/observatory/lib/src/elements/script_ref.dart
index 1ed7453c..f5acf04 100644
--- a/runtime/observatory/lib/src/elements/script_ref.dart
+++ b/runtime/observatory/lib/src/elements/script_ref.dart
@@ -51,10 +51,15 @@
   }
 
   void render() {
+    var displayUri = script.uri.split('/').last;
+    if (displayUri.isEmpty) {
+      displayUri = 'N/A';
+    }
+
     children = <Element>[
       new AnchorElement(href: Uris.inspect(isolate, object: script))
         ..title = script.uri
-        ..text = script.uri.split('/').last
+        ..text = displayUri
     ];
   }
 }
diff --git a/runtime/observatory/tests/service/get_object_rpc_test.dart b/runtime/observatory/tests/service/get_object_rpc_test.dart
index 7ebabac..a19a869 100644
--- a/runtime/observatory/tests/service/get_object_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_object_rpc_test.dart
@@ -762,7 +762,7 @@
     expect(result['name'], equals('_DummyClass'));
     expect(result['_vmName'], startsWith('_DummyClass@'));
     expect(result['abstract'], equals(false));
-    expect(result['const'], equals(true));
+    expect(result['const'], equals(false));
     expect(result['_finalized'], equals(true));
     expect(result['_implemented'], equals(false));
     expect(result['_patch'], equals(false));
diff --git a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
index f68010b..25bcec0 100644
--- a/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_vm_timeline_rpc_test.dart
@@ -15,7 +15,7 @@
   Timeline.instantSync('ISYNC', arguments: {'fruit': 'banana'});
   Timeline.finishSync();
   TimelineTask parentTask = TimelineTask.withTaskId(42);
-  TimelineTask task = TimelineTask(parent: parentTask);
+  TimelineTask task = TimelineTask(parent: parentTask, filterKey: 'testFilter');
   task.start('TASK1', arguments: {'task1-start-key': 'task1-start-value'});
   task.instant('ITASK',
       arguments: {'task1-instant-key': 'task1-instant-value'});
@@ -133,17 +133,22 @@
     expect(eventsContains(dartEvents, 'E', 'apple'), isTrue);
     expect(
         eventsContains(dartEvents, 'b', 'TASK1', {
+          'filterKey': 'testFilter',
           'task1-start-key': 'task1-start-value',
           'parentId': 42.toRadixString(16)
         }),
         isTrue);
     expect(
-        eventsContains(dartEvents, 'e', 'TASK1',
-            {'task1-finish-key': 'task1-finish-value'}),
+        eventsContains(dartEvents, 'e', 'TASK1', {
+          'filterKey': 'testFilter',
+          'task1-finish-key': 'task1-finish-value',
+        }),
         isTrue);
     expect(
-        eventsContains(dartEvents, 'n', 'ITASK',
-            {'task1-instant-key': 'task1-instant-value'}),
+        eventsContains(dartEvents, 'n', 'ITASK', {
+          'filterKey': 'testFilter',
+          'task1-instant-key': 'task1-instant-value',
+        }),
         isTrue);
     expect(eventsContains(dartEvents, 'q', 'ITASK'), isFalse);
     expect(eventsContains(dartEvents, 'B', 'peach'), isTrue);
diff --git a/runtime/observatory/tests/service/verify_http_timeline_test.dart b/runtime/observatory/tests/service/verify_http_timeline_test.dart
index dfd6ad8..f7809c8 100644
--- a/runtime/observatory/tests/service/verify_http_timeline_test.dart
+++ b/runtime/observatory/tests/service/verify_http_timeline_test.dart
@@ -201,6 +201,7 @@
   final args = event['args'];
   expect(args.containsKey('method'), isTrue);
   expect(args['method'], method);
+  expect(args['filterKey'], 'HTTP/client');
   if (!args.containsKey('error')) {
     expect(args.containsKey('requestHeaders'), isTrue);
     expect(args['requestHeaders'] != null, isTrue);
@@ -226,6 +227,7 @@
 void validateHttpFinishEvent(Map event) {
   expect(event.containsKey('args'), isTrue);
   final args = event['args'];
+  expect(args['filterKey'], 'HTTP/client');
   expect(args.containsKey('compressionState'), isTrue);
   expect(args.containsKey('connectionInfo'), isTrue);
   expect(args.containsKey('contentLength'), isTrue);
diff --git a/runtime/tests/vm/dart/named_params_shaking_test.dart b/runtime/tests/vm/dart/named_params_shaking_test.dart
new file mode 100644
index 0000000..b941651
--- /dev/null
+++ b/runtime/tests/vm/dart/named_params_shaking_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Test that optimization of named parameters doesn't change evaluation order.
+
+import 'dart:math';
+import 'package:expect/expect.dart';
+
+int global = 0;
+
+int inc() => ++global;
+int dec() => global = max(0, --global);
+
+// When converting named parameters to positional parameters, we
+// follow alphabetical order. Ensure that argument evaluation order
+// is unchanged.
+void testNamedOrder(int w, {int z, int y, int x}) {
+  Expect.equals(w, 1);
+  Expect.equals(z, 2);
+  Expect.equals(y, 3);
+  Expect.equals(x, 2);
+}
+
+class TestNamedOrderBase {
+  TestNamedOrderBase(w, {int z, int y, int x}) {
+    testNamedOrder(w, z: z, y: y, x: x);
+  }
+}
+
+class TestNamedOrderSub extends TestNamedOrderBase {
+  int x;
+  TestNamedOrderSub()
+      : x = dec(),
+        super(inc(), z: inc(), y: inc(), x: dec()) {
+    Expect.equals(x, 0);
+  }
+}
+
+main() {
+  testNamedOrder(inc(), z: inc(), y: inc(), x: dec());
+  global = 1;
+  TestNamedOrderSub();
+}
diff --git a/runtime/tests/vm/dart/regress_40964_test.dart b/runtime/tests/vm/dart/regress_40964_test.dart
new file mode 100644
index 0000000..df3a4d7
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_40964_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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<T> {
+  test(x) => x as B<T>;
+}
+
+class B<T> {}
+
+class C<T> {}
+
+main() {
+  final a = A<C<int>>();
+  a.test(B<C<int>>());
+  Expect.throwsTypeError(() => a.test(B<C<num>>()));
+}
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index ff1c7b7..67ff960 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -64,7 +64,8 @@
   // VM creates instances of _Closure without compiling its constructors,
   // so it won't get nullability info from a constructor.
   field ^= fields.At(fields.Length() - 1);
-  ASSERT(String::Handle(zone, field.UserVisibleName()).Equals("_hash"));
+  // Note that UserVisibleName depends on --show-internal-names.
+  ASSERT(strncmp(field.UserVisibleNameCString(), "_hash", 5) == 0);
   field.RecordStore(Object::null_object());
 
 #if defined(DEBUG)
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 8429e5f..3bbc59d 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -47,6 +47,7 @@
   V(Integer_shlFromInteger, 2)                                                 \
   V(Integer_shrFromInteger, 2)                                                 \
   V(Bool_fromEnvironment, 3)                                                   \
+  V(Bool_hasEnvironment, 2)                                                    \
   V(CapabilityImpl_factory, 1)                                                 \
   V(CapabilityImpl_equals, 2)                                                  \
   V(CapabilityImpl_get_hashcode, 1)                                            \
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 583d4ea..261728a 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -27,13 +27,15 @@
     ASSERT(kInitialCapacity >= kNumPredefinedCids);
     capacity_ = kInitialCapacity;
     // Note that [calloc] will zero-initialize the memory.
-    table_ = static_cast<intptr_t*>(calloc(capacity_, sizeof(intptr_t)));
+    table_ = reinterpret_cast<RelaxedAtomic<intptr_t>*>(
+        calloc(capacity_, sizeof(RelaxedAtomic<intptr_t>)));
   } else {
     // Duplicate the class table from the VM isolate.
     auto vm_shared_class_table = Dart::vm_isolate()->group()->class_table();
     capacity_ = vm_shared_class_table->capacity_;
     // Note that [calloc] will zero-initialize the memory.
-    table_ = static_cast<intptr_t*>(calloc(capacity_, sizeof(RawClass*)));
+    table_ = reinterpret_cast<RelaxedAtomic<intptr_t>*>(
+        calloc(capacity_, sizeof(RelaxedAtomic<intptr_t>)));
     // The following cids don't have a corresponding class object in Dart code.
     // We therefore need to initialize them eagerly.
     for (intptr_t i = kObjectCid; i < kInstanceCid; i++) {
@@ -237,8 +239,9 @@
 void SharedClassTable::Grow(intptr_t new_capacity) {
   ASSERT(new_capacity >= capacity_);
 
-  intptr_t* new_table = static_cast<intptr_t*>(
-      malloc(new_capacity * sizeof(intptr_t)));  // NOLINT
+  RelaxedAtomic<intptr_t>* new_table =
+      reinterpret_cast<RelaxedAtomic<intptr_t>*>(
+          malloc(new_capacity * sizeof(RelaxedAtomic<intptr_t>)));  // NOLINT
 
   memmove(new_table, table_, capacity_ * sizeof(intptr_t));
   memset(new_table + capacity_, 0,
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 0ff2912..3498946 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -85,8 +85,10 @@
 
     // Ensure we never change size for a given cid from one non-zero size to
     // another non-zero size.
-    RELEASE_ASSERT(table_[index] == 0 || table_[index] == size);
-    table_[index] = size;
+    intptr_t old_size = 0;
+    if (!table_[index].compare_exchange_strong(old_size, size)) {
+      RELEASE_ASSERT(old_size == size);
+    }
   }
 
   bool IsValidIndex(intptr_t index) const { return index > 0 && index < top_; }
@@ -216,7 +218,8 @@
   intptr_t capacity_;
 
   // Copy-on-write is used for table_, with old copies stored in old_tables_.
-  intptr_t* table_ = nullptr;  // Maps the cid to the instance size.
+  // Maps the cid to the instance size.
+  RelaxedAtomic<intptr_t>* table_ = nullptr;
   MallocGrowableArray<void*>* old_tables_;
 
   IsolateGroupReloadContext* reload_context_ = nullptr;
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index b6a759f..5a6e7c1 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -27,10 +27,15 @@
 #include "vm/timeline.h"
 #include "vm/version.h"
 
-#define LOG_SECTION_BOUNDARIES false
-
 namespace dart {
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+DEFINE_FLAG(bool,
+            print_cluster_information,
+            false,
+            "Print information about clusters written to snapshot");
+#endif
+
 #if defined(DART_PRECOMPILER)
 DEFINE_FLAG(charp,
             write_v8_snapshot_profile_to,
@@ -101,27 +106,34 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 void SerializationCluster::WriteAndMeasureAlloc(Serializer* serializer) {
-  if (LOG_SECTION_BOUNDARIES) {
-    OS::PrintErr("Data + %" Px ": Alloc %s\n", serializer->bytes_written(),
-                 name_);
-  }
-  intptr_t start_size = serializer->bytes_written() + serializer->GetDataSize();
+  intptr_t start_size = serializer->bytes_written();
+  intptr_t start_data = serializer->GetDataSize();
   intptr_t start_objects = serializer->next_ref_index();
   WriteAlloc(serializer);
-  intptr_t stop_size = serializer->bytes_written() + serializer->GetDataSize();
+  intptr_t stop_size = serializer->bytes_written();
+  intptr_t stop_data = serializer->GetDataSize();
   intptr_t stop_objects = serializer->next_ref_index();
-  size_ += (stop_size - start_size);
+  if (FLAG_print_cluster_information) {
+    const int hex_size = kWordSize * 2;
+    OS::PrintErr("Snapshot 0x%0*.*" Px " (%" Pd "), ", hex_size, hex_size,
+                 start_size, stop_size - start_size);
+    OS::PrintErr("Data 0x%0*.*" Px " (%" Pd "): ", hex_size, hex_size,
+                 start_data, stop_data - start_data);
+    OS::PrintErr("Alloc %s (%" Pd ")\n", name(), stop_objects - start_objects);
+  }
+  size_ += (stop_size - start_size) + (stop_data - start_data);
   num_objects_ += (stop_objects - start_objects);
 }
 
 void SerializationCluster::WriteAndMeasureFill(Serializer* serializer) {
-  if (LOG_SECTION_BOUNDARIES) {
-    OS::PrintErr("Data + %" Px ": Fill %s\n", serializer->bytes_written(),
-                 name_);
-  }
   intptr_t start = serializer->bytes_written();
   WriteFill(serializer);
   intptr_t stop = serializer->bytes_written();
+  if (FLAG_print_cluster_information) {
+    const int hex_size = kWordSize * 2;
+    OS::PrintErr("Snapshot 0x%0*.*" Px " (%" Pd "): Fill %s\n", hex_size,
+                 hex_size, start, stop - start, name());
+  }
   size_ += (stop - start);
 }
 
@@ -405,6 +417,8 @@
       s->Write<bool>(type_args->IsCanonical());
       intptr_t hash = Smi::Value(type_args->ptr()->hash_);
       s->Write<int32_t>(hash);
+      const intptr_t nullability = Smi::Value(type_args->ptr()->nullability_);
+      s->WriteUnsigned(nullability);
       WriteField(type_args, instantiations_);
       for (intptr_t j = 0; j < length; j++) {
         s->WriteElementRef(type_args->ptr()->types()[j], j);
@@ -445,6 +459,7 @@
                                      is_canonical);
       type_args->ptr()->length_ = Smi::New(length);
       type_args->ptr()->hash_ = Smi::New(d->Read<int32_t>());
+      type_args->ptr()->nullability_ = Smi::New(d->ReadUnsigned());
       type_args->ptr()->instantiations_ =
           reinterpret_cast<RawArray*>(d->ReadRef());
       for (intptr_t j = 0; j < length; j++) {
@@ -2008,8 +2023,11 @@
 // PcDescriptor, CompressedStackMaps, OneByteString, TwoByteString
 class RODataSerializationCluster : public SerializationCluster {
  public:
-  RODataSerializationCluster(const char* name, intptr_t cid)
-      : SerializationCluster(name), cid_(cid) {}
+  RODataSerializationCluster(Zone* zone, const char* type, intptr_t cid)
+      : SerializationCluster(ImageWriter::TagObjectTypeAsReadOnly(zone, type)),
+        cid_(cid),
+        objects_(),
+        type_(type) {}
   ~RODataSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
@@ -2037,9 +2055,9 @@
       RawObject* object = objects_[i];
       s->AssignRef(object);
       if (cid_ == kOneByteStringCid || cid_ == kTwoByteStringCid) {
-        s->TraceStartWritingObject(name(), object, String::RawCast(object));
+        s->TraceStartWritingObject(type_, object, String::RawCast(object));
       } else {
-        s->TraceStartWritingObject(name(), object, nullptr);
+        s->TraceStartWritingObject(type_, object, nullptr);
       }
       uint32_t offset = s->GetDataOffset(object);
       s->TraceDataOffset(offset);
@@ -2060,6 +2078,7 @@
  private:
   const intptr_t cid_;
   GrowableArray<RawObject*> objects_;
+  const char* const type_;
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
 
@@ -4565,6 +4584,23 @@
   }
 }
 
+const char* Serializer::ReadOnlyObjectType(intptr_t cid) {
+  switch (cid) {
+    case kPcDescriptorsCid:
+      return "PcDescriptors";
+    case kCodeSourceMapCid:
+      return "CodeSourceMap";
+    case kCompressedStackMapsCid:
+      return "CompressedStackMaps";
+    case kOneByteStringCid:
+      return "OneByteString";
+    case kTwoByteStringCid:
+      return "TwoByteString";
+    default:
+      return nullptr;
+  }
+}
+
 SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
@@ -4586,18 +4622,8 @@
   }
 
   if (Snapshot::IncludesCode(kind_)) {
-    switch (cid) {
-      case kPcDescriptorsCid:
-        return new (Z) RODataSerializationCluster("(RO)PcDescriptors", cid);
-      case kCodeSourceMapCid:
-        return new (Z) RODataSerializationCluster("(RO)CodeSourceMap", cid);
-      case kCompressedStackMapsCid:
-        return new (Z)
-            RODataSerializationCluster("(RO)CompressedStackMaps", cid);
-      case kOneByteStringCid:
-        return new (Z) RODataSerializationCluster("(RO)OneByteString", cid);
-      case kTwoByteStringCid:
-        return new (Z) RODataSerializationCluster("(RO)TwoByteString", cid);
+    if (auto const type = ReadOnlyObjectType(cid)) {
+      return new (Z) RODataSerializationCluster(Z, type, cid);
     }
   }
 
@@ -4792,13 +4818,6 @@
   return image_writer_->data_size();
 }
 
-intptr_t Serializer::GetTextSize() const {
-  if (image_writer_ == NULL) {
-    return 0;
-  }
-  return image_writer_->text_size();
-}
-
 void Serializer::Push(RawObject* object) {
   if (!object->IsHeapObject()) {
     RawSmi* smi = Smi::RawCast(object);
@@ -5018,6 +5037,127 @@
     }
   }
 }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
+#if defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
+// The serialized format of the dispatch table is a sequence of variable-length
+// integers (the built-in variable-length integer encoding/decoding of
+// the stream). Each encoded integer e is interpreted thus:
+// -kRecentCount .. -1   Pick value from the recent values buffer at index -1-e.
+// 0                     Empty (unused) entry.
+// 1 .. kMaxRepeat       Repeat previous entry e times.
+// kIndexBase or higher  Pick entry point from the object at index e-kIndexBase
+//                       in the snapshot code cluster. Also put it in the recent
+//                       values buffer at the next round-robin index.
+
+// Constants for serialization format. Chosen such that repeats and recent
+// values are encoded as single bytes in SLEB128 encoding.
+static constexpr intptr_t kDispatchTableSpecialEncodingBits = 6;
+static constexpr intptr_t kDispatchTableRecentCount =
+    1 << kDispatchTableSpecialEncodingBits;
+static constexpr intptr_t kDispatchTableRecentMask =
+    (1 << kDispatchTableSpecialEncodingBits) - 1;
+static constexpr intptr_t kDispatchTableMaxRepeat =
+    (1 << kDispatchTableSpecialEncodingBits) - 1;
+static constexpr intptr_t kDispatchTableIndexBase = kDispatchTableMaxRepeat + 1;
+#endif  // defined(DART_PRECOMPILER) || defined(DART_PRECOMPILED_RUNTIME)
+
+void Serializer::WriteDispatchTable(const Array& entries) {
+#if defined(DART_PRECOMPILER)
+  if (kind() != Snapshot::kFullAOT) return;
+
+  const intptr_t bytes_before = bytes_written();
+  const intptr_t table_length = entries.IsNull() ? 0 : entries.Length();
+
+  ASSERT(table_length <= compiler::target::kWordMax);
+  WriteUnsigned(table_length);
+  if (table_length == 0) {
+    dispatch_table_size_ = bytes_written() - bytes_before;
+    return;
+  }
+
+  auto const code_cluster =
+      reinterpret_cast<CodeSerializationCluster*>(clusters_by_cid_[kCodeCid]);
+  ASSERT(code_cluster != nullptr);
+  // Reference IDs in a cluster are allocated sequentially, so we can use the
+  // first code object's reference ID to calculate the cluster index.
+  const intptr_t first_code_id =
+      WriteRefId(code_cluster->discovered_objects()->At(0));
+  // The first object in the code cluster must have its reference ID allocated.
+  ASSERT(first_code_id != 0 && first_code_id != WriteRefId(Code::null()));
+
+  // If instructions can be deduped, the code order table in the deserializer
+  // may not contain all Code objects in the snapshot. Thus, we write the ID
+  // for the first code object here so we can retrieve it during deserialization
+  // and calculate the snapshot ID for Code objects from the cluster index.
+  //
+  // We could just use the snapshot reference ID of the Code object itself
+  // instead of the cluster index and avoid this. However, since entries are
+  // SLEB128 encoded, the size delta for serializing the first ID once is less
+  // than the size delta of serializing the ID plus kIndexBase for each entry,
+  // even when Code objects are allocated before all other non-base objects.
+  //
+  // We could also map Code objects to the first Code object in the cluster with
+  // the same entry point and serialize that ID instead, but that loses
+  // information about which Code object was originally referenced.
+  ASSERT(first_code_id <= compiler::target::kWordMax);
+  WriteUnsigned(first_code_id);
+
+  RawCode* previous_code = nullptr;
+  RawCode* recent[kDispatchTableRecentCount] = {nullptr};
+  intptr_t recent_index = 0;
+  intptr_t repeat_count = 0;
+  for (intptr_t i = 0; i < table_length; i++) {
+    auto const code = Code::RawCast(entries.At(i));
+    // First, see if we're repeating the previous entry (invalid, recent, or
+    // encoded).
+    if (code == previous_code) {
+      if (++repeat_count == kDispatchTableMaxRepeat) {
+        Write(kDispatchTableMaxRepeat);
+        repeat_count = 0;
+      }
+      continue;
+    }
+    // Emit any outsanding repeat count before handling the new code value.
+    if (repeat_count > 0) {
+      Write(repeat_count);
+      repeat_count = 0;
+    }
+    previous_code = code;
+    // The invalid entry can be repeated, but is never part of the recent list
+    // since it already encodes to a single byte..
+    if (code == Code::null()) {
+      Write(0);
+      continue;
+    }
+    // Check against the recent entries, and write an encoded reference to
+    // the recent entry if found.
+    intptr_t found_index = 0;
+    for (; found_index < kDispatchTableRecentCount; found_index++) {
+      if (recent[found_index] == code) break;
+    }
+    if (found_index < kDispatchTableRecentCount) {
+      Write(~found_index);
+      continue;
+    }
+    // We have a non-repeated, non-recent entry, so encode the reference ID of
+    // the code object and emit that.
+    auto const object_id = WriteRefId(code);
+    // Make sure that this code object has an allocated reference ID.
+    ASSERT(object_id != 0 && object_id != WriteRefId(Code::null()));
+    // Use the index in the code cluster, not in the snapshot..
+    auto const encoded = kDispatchTableIndexBase + (object_id - first_code_id);
+    ASSERT(encoded <= compiler::target::kWordMax);
+    Write(encoded);
+    recent[recent_index] = code;
+    recent_index = (recent_index + 1) & kDispatchTableRecentMask;
+  }
+  if (repeat_count > 0) {
+    Write(repeat_count);
+  }
+  dispatch_table_size_ = bytes_written() - bytes_before;
+#endif  // defined(DART_PRECOMPILER)
+}
 
 void Serializer::PrintSnapshotSizes() {
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -5030,19 +5170,37 @@
         clusters_by_size.Add(cluster);
       }
     }
-    if (GetTextSize() != 0) {
+    intptr_t text_size = 0;
+    if (image_writer_ != nullptr) {
+      auto const text_object_count = image_writer_->GetTextObjectCount();
+      text_size = image_writer_->text_size();
+      intptr_t trampoline_count, trampoline_size;
+      image_writer_->GetTrampolineInfo(&trampoline_count, &trampoline_size);
+      auto const instructions_count = text_object_count - trampoline_count;
+      auto const instructions_size = text_size - trampoline_size;
       clusters_by_size.Add(new (zone_) FakeSerializationCluster(
-          "(RO)Instructions", 0, GetTextSize()));
+          ImageWriter::TagObjectTypeAsReadOnly(zone_, "Instructions"),
+          instructions_count, instructions_size));
+      if (trampoline_size > 0) {
+        clusters_by_size.Add(new (zone_) FakeSerializationCluster(
+            ImageWriter::TagObjectTypeAsReadOnly(zone_, "Trampoline"),
+            trampoline_count, trampoline_size));
+      }
     }
-    // An null dispatch table will serialize to a single byte.
-    if (dispatch_table_size_ > 1) {
+    // The dispatch_table_size_ will be 0 if the snapshot did not include a
+    // dispatch table (i.e., the VM snapshot). For a precompiled isolate
+    // snapshot, we always serialize at least _one_ byte for the DispatchTable.
+    if (dispatch_table_size_ > 0) {
+      const auto& dispatch_table_entries = Array::Handle(
+          zone_, isolate()->object_store()->dispatch_table_code_entries());
+      auto const entry_count =
+          dispatch_table_entries.IsNull() ? 0 : dispatch_table_entries.Length();
       clusters_by_size.Add(new (zone_) FakeSerializationCluster(
-          "(RO)DispatchTable", isolate()->dispatch_table()->length(),
-          dispatch_table_size_));
+          "DispatchTable", entry_count, dispatch_table_size_));
     }
     clusters_by_size.Sort(CompareClusters);
     double total_size =
-        static_cast<double>(bytes_written() + GetDataSize() + GetTextSize());
+        static_cast<double>(bytes_written() + GetDataSize() + text_size);
     double cumulative_fraction = 0.0;
     for (intptr_t i = 0; i < clusters_by_size.length(); i++) {
       SerializationCluster* cluster = clusters_by_size[i];
@@ -5056,6 +5214,7 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 void Serializer::AddVMIsolateBaseObjects() {
   // These objects are always allocated by Object::InitOnce, so they are not
   // written into the snapshot.
@@ -5199,6 +5358,23 @@
     Push(*p);
   }
 
+  const auto& dispatch_table_entries =
+      Array::Handle(zone_, object_store->dispatch_table_code_entries());
+  // We should only have a dispatch table in precompiled mode.
+  ASSERT(dispatch_table_entries.IsNull() || kind() == Snapshot::kFullAOT);
+
+#if defined(DART_PRECOMPILER)
+  // We treat the dispatch table as a root object and trace the Code objects it
+  // references. Otherwise, a non-empty entry could be invalid on
+  // deserialization if the corresponding Code object was not reachable from the
+  // existing snapshot roots.
+  if (!dispatch_table_entries.IsNull()) {
+    for (intptr_t i = 0; i < dispatch_table_entries.Length(); i++) {
+      Push(dispatch_table_entries.At(i));
+    }
+  }
+#endif
+
   Serialize();
 
   // Write roots.
@@ -5206,12 +5382,35 @@
     WriteRootRef(*p, kObjectStoreFieldNames[p - from]);
   }
 
-  // Serialize dispatch table.
-  GrowableArray<RawCode*>* code_objects =
-      static_cast<CodeSerializationCluster*>(clusters_by_cid_[kCodeCid])
-          ->discovered_objects();
-  dispatch_table_size_ = DispatchTable::Serialize(
-      this, isolate()->dispatch_table(), *code_objects);
+  // The dispatch table is serialized only for precompiled snapshots.
+  WriteDispatchTable(dispatch_table_entries);
+
+#if defined(DART_PRECOMPILER)
+  // If any bytes were written for the dispatch table, add it to the profile.
+  if (dispatch_table_size_ > 0 && profile_writer_ != nullptr) {
+    // Grab an unused ref index for a unique object id for the dispatch table.
+    const auto dispatch_table_id = next_ref_index_++;
+    const V8SnapshotProfileWriter::ObjectId dispatch_table_snapshot_id(
+        V8SnapshotProfileWriter::kSnapshot, dispatch_table_id);
+    profile_writer_->AddRoot(dispatch_table_snapshot_id, "dispatch_table");
+    profile_writer_->SetObjectTypeAndName(dispatch_table_snapshot_id,
+                                          "DispatchTable", nullptr);
+    profile_writer_->AttributeBytesTo(dispatch_table_snapshot_id,
+                                      dispatch_table_size_);
+
+    if (!dispatch_table_entries.IsNull()) {
+      for (intptr_t i = 0; i < dispatch_table_entries.Length(); i++) {
+        auto const code = Code::RawCast(dispatch_table_entries.At(i));
+        if (code == Code::null()) continue;
+        const V8SnapshotProfileWriter::ObjectId code_id(
+            V8SnapshotProfileWriter::kSnapshot, WriteRefId(code));
+        profile_writer_->AttributeReferenceTo(
+            dispatch_table_snapshot_id,
+            {code_id, V8SnapshotProfileWriter::Reference::kElement, i});
+      }
+    }
+  }
+#endif
 
 #if defined(DEBUG)
   Write<int32_t>(kSectionMarker);
@@ -5377,6 +5576,57 @@
   return NULL;
 }
 
+void Deserializer::ReadDispatchTable() {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  const intptr_t length = ReadUnsigned();
+  if (length == 0) return;
+
+  // Not all Code objects may be in the code_order_table when instructions can
+  // be deduplicated. Thus, we serialize the reference ID of the first code
+  // object, from which we can get the reference ID for any code object.
+  const intptr_t first_code_id = ReadUnsigned();
+
+  auto const I = isolate();
+  auto code = I->object_store()->dispatch_table_null_error_stub();
+  ASSERT(code != Code::null());
+  uword null_entry = Code::EntryPointOf(code);
+
+  auto const table = new DispatchTable(length);
+  auto const array = table->array();
+  uword value = 0;
+  uword recent[kDispatchTableRecentCount] = {0};
+  intptr_t recent_index = 0;
+  intptr_t repeat_count = 0;
+  for (intptr_t i = 0; i < length; i++) {
+    if (repeat_count > 0) {
+      array[i] = value;
+      repeat_count--;
+      continue;
+    }
+    auto const encoded = Read<intptr_t>();
+    if (encoded == 0) {
+      value = null_entry;
+    } else if (encoded < 0) {
+      intptr_t r = ~encoded;
+      ASSERT(r < kDispatchTableRecentCount);
+      value = recent[r];
+    } else if (encoded <= kDispatchTableMaxRepeat) {
+      repeat_count = encoded - 1;
+    } else {
+      intptr_t cluster_index = encoded - kDispatchTableIndexBase;
+      code = Code::RawCast(Ref(first_code_id + cluster_index));
+      value = Code::EntryPointOf(code);
+      recent[recent_index] = value;
+      recent_index = (recent_index + 1) & kDispatchTableRecentMask;
+    }
+    array[i] = value;
+  }
+  ASSERT(repeat_count == 0);
+
+  I->set_dispatch_table(table);
+#endif
+}
+
 RawApiError* Deserializer::VerifyImageAlignment() {
   if (image_reader_ != nullptr) {
     return image_reader_->VerifyAlignment();
@@ -5776,11 +6026,8 @@
       *p = ReadRef();
     }
 
-    // Deserialize dispatch table
-    const Array& code_array =
-        Array::Handle(zone_, object_store->code_order_table());
-    thread()->isolate()->set_dispatch_table(
-        DispatchTable::Deserialize(this, code_array));
+    // Deserialize dispatch table (when applicable)
+    ReadDispatchTable();
 
 #if defined(DEBUG)
     int32_t section_marker = Read<int32_t>();
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index d9e2a83..510a4da 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -246,36 +246,6 @@
   }
   void Align(intptr_t alignment) { stream_.Align(alignment); }
 
- private:
-  intptr_t WriteRefId(RawObject* object) {
-    intptr_t id = 0;
-    if (!object->IsHeapObject()) {
-      RawSmi* smi = Smi::RawCast(object);
-      id = smi_ids_.Lookup(smi)->id_;
-      if (id == 0) {
-        FATAL("Missing ref");
-      }
-    } else {
-      // The object id weak table holds image offsets for Instructions instead
-      // of ref indices.
-      ASSERT(!object->IsInstructions());
-      id = heap_->GetObjectId(object);
-      if (id == 0) {
-        if (object->IsCode() && !Snapshot::IncludesCode(kind_)) {
-          return WriteRefId(Object::null());
-        }
-#if !defined(DART_PRECOMPILED_RUNTIME)
-        if (object->IsBytecode() && !Snapshot::IncludesBytecode(kind_)) {
-          return WriteRefId(Object::null());
-        }
-#endif  // !DART_PRECOMPILED_RUNTIME
-        FATAL("Missing ref");
-      }
-    }
-    return id;
-  }
-
- public:
   void WriteRootRef(RawObject* object, const char* name = nullptr) {
     intptr_t id = WriteRefId(object);
     WriteUnsigned(id);
@@ -382,7 +352,8 @@
   uint32_t GetDataOffset(RawObject* object) const;
   void TraceDataOffset(uint32_t offset);
   intptr_t GetDataSize() const;
-  intptr_t GetTextSize() const;
+
+  void WriteDispatchTable(const Array& entries);
 
   Snapshot::Kind kind() const { return kind_; }
   intptr_t next_ref_index() const { return next_ref_index_; }
@@ -390,6 +361,36 @@
   void DumpCombinedCodeStatistics();
 
  private:
+  static const char* ReadOnlyObjectType(intptr_t cid);
+
+  intptr_t WriteRefId(RawObject* object) {
+    intptr_t id = 0;
+    if (!object->IsHeapObject()) {
+      RawSmi* smi = Smi::RawCast(object);
+      id = smi_ids_.Lookup(smi)->id_;
+      if (id == 0) {
+        FATAL("Missing ref");
+      }
+    } else {
+      // The object id weak table holds image offsets for Instructions instead
+      // of ref indices.
+      ASSERT(!object->IsInstructions());
+      id = heap_->GetObjectId(object);
+      if (id == 0) {
+        if (object->IsCode() && !Snapshot::IncludesCode(kind_)) {
+          return WriteRefId(Object::null());
+        }
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        if (object->IsBytecode() && !Snapshot::IncludesBytecode(kind_)) {
+          return WriteRefId(Object::null());
+        }
+#endif  // !DART_PRECOMPILED_RUNTIME
+        FATAL("Missing ref");
+      }
+    }
+    return id;
+  }
+
   Heap* heap_;
   Zone* zone_;
   Snapshot::Kind kind_;
@@ -593,6 +594,8 @@
 
   DeserializationCluster* ReadCluster();
 
+  void ReadDispatchTable();
+
   intptr_t next_index() const { return next_ref_index_; }
   Heap* heap() const { return heap_; }
   Snapshot::Kind kind() const { return kind_; }
diff --git a/runtime/vm/compiler/aot/dispatch_table_generator.cc b/runtime/vm/compiler/aot/dispatch_table_generator.cc
index 7ce4ea6..99a21ed 100644
--- a/runtime/vm/compiler/aot/dispatch_table_generator.cc
+++ b/runtime/vm/compiler/aot/dispatch_table_generator.cc
@@ -2,13 +2,14 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#if defined(DART_PRECOMPILER) && !defined(DART_PRECOMPILED_RUNTIME)
+#if defined(DART_PRECOMPILER)
 
 #include "vm/compiler/aot/dispatch_table_generator.h"
 
 #include <memory>
 
 #include "vm/compiler/frontend/kernel_translation_helper.h"
+#include "vm/dispatch_table.h"
 #include "vm/stub_code.h"
 #include "vm/thread.h"
 
@@ -94,7 +95,10 @@
 class SelectorRow {
  public:
   SelectorRow(Zone* zone, TableSelector* selector)
-      : selector_(selector), class_ranges_(zone, 0), ranges_(zone, 0) {}
+      : selector_(selector),
+        class_ranges_(zone, 0),
+        ranges_(zone, 0),
+        code_(Code::Handle(zone)) {}
 
   TableSelector* selector() const { return selector_; }
 
@@ -123,7 +127,7 @@
     selector_->offset = offset;
   }
 
-  void FillTable(ClassTable* class_table, DispatchTable* table);
+  void FillTable(ClassTable* class_table, const Array& entries);
 
  private:
   TableSelector* selector_;
@@ -131,6 +135,7 @@
 
   GrowableArray<CidInterval> class_ranges_;
   GrowableArray<Interval> ranges_;
+  Code& code_;
 };
 
 class RowFitter {
@@ -231,12 +236,10 @@
   return true;
 }
 
-void SelectorRow::FillTable(ClassTable* class_table, DispatchTable* table) {
+void SelectorRow::FillTable(ClassTable* class_table, const Array& entries) {
   // Define the entries in the table by going top-down, which means more
   // specific ones will override more general ones.
 
-  Code& code = Code::Handle();
-
   // Sort by depth.
   struct IntervalSorter {
     static int Compare(const CidInterval* a, const CidInterval* b) {
@@ -252,9 +255,9 @@
     const Interval& range = cid_range.range();
     const Function* function = cid_range.function();
     if (function != nullptr && function->HasCode()) {
-      code = function->CurrentCode();
+      code_ = function->CurrentCode();
       for (classid_t cid = range.begin(); cid < range.end(); cid++) {
-        table->SetCodeAt(selector()->offset + cid, code);
+        entries.SetAt(selector()->offset + cid, code_);
       }
     }
   }
@@ -634,17 +637,16 @@
   table_size_ = fitter.TableSize();
 }
 
-DispatchTable* DispatchTableGenerator::BuildTable() {
-  // Allocate the dispatch table and fill it in.
-  DispatchTable* dispatch_table = new DispatchTable(table_size_);
+RawArray* DispatchTableGenerator::BuildCodeArray() {
+  auto& entries = Array::Handle(zone_, Array::New(table_size_, Heap::kOld));
   for (intptr_t i = 0; i < table_rows_.length(); i++) {
-    table_rows_[i]->FillTable(classes_, dispatch_table);
+    table_rows_[i]->FillTable(classes_, entries);
   }
-
-  return dispatch_table;
+  entries.MakeImmutable();
+  return entries.raw();
 }
 
 }  // namespace compiler
 }  // namespace dart
 
-#endif  // defined(DART_PRECOMPILER) && !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // defined(DART_PRECOMPILER)
diff --git a/runtime/vm/compiler/aot/dispatch_table_generator.h b/runtime/vm/compiler/aot/dispatch_table_generator.h
index 6cbf81672..830e122 100644
--- a/runtime/vm/compiler/aot/dispatch_table_generator.h
+++ b/runtime/vm/compiler/aot/dispatch_table_generator.h
@@ -6,9 +6,10 @@
 #define RUNTIME_VM_COMPILER_AOT_DISPATCH_TABLE_GENERATOR_H_
 
 #include "vm/compiler/frontend/kernel_translation_helper.h"
-#include "vm/dispatch_table.h"
 #include "vm/object.h"
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
 namespace dart {
 
 class ClassTable;
@@ -84,8 +85,9 @@
   // Find suitable selectors and compute offsets for them.
   void Initialize(ClassTable* table);
 
-  // Build up the table.
-  DispatchTable* BuildTable();
+  // Build up an array of Code objects, used to serialize the information
+  // deserialized as a DispatchTable at runtime.
+  RawArray* BuildCodeArray();
 
  private:
   void ReadTableSelectorInfo();
@@ -93,7 +95,7 @@
   void SetupSelectorRows();
   void ComputeSelectorOffsets();
 
-  Zone* zone_;
+  Zone* const zone_;
   ClassTable* classes_;
   int32_t num_selectors_;
   int32_t num_classes_;
@@ -107,4 +109,6 @@
 }  // namespace compiler
 }  // namespace dart
 
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 #endif  // RUNTIME_VM_COMPILER_AOT_DISPATCH_TABLE_GENERATOR_H_
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index ae17d44..82ed009 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -402,6 +402,19 @@
       }
 
       TraceForRetainedFunctions();
+
+      if (FLAG_use_bare_instructions && FLAG_use_table_dispatch) {
+        // Build the entries used to serialize the dispatch table before
+        // dropping functions, as we may clear references to Code objects.
+        const auto& entries =
+            Array::Handle(Z, dispatch_table_generator_->BuildCodeArray());
+        I->object_store()->set_dispatch_table_code_entries(entries);
+        // Delete the dispatch table generator to ensure there's no attempt
+        // to add new entries after this point.
+        delete dispatch_table_generator_;
+        dispatch_table_generator_ = nullptr;
+      }
+
       DropFunctions();
       DropFields();
       TraceTypesFromRetainedClasses();
@@ -441,14 +454,6 @@
 
     ProgramVisitor::Dedup();
 
-    if (FLAG_use_bare_instructions && FLAG_use_table_dispatch) {
-      I->set_dispatch_table(dispatch_table_generator_->BuildTable());
-      // Delete the dispatch table generator while the current zone
-      // is still alive.
-      delete dispatch_table_generator_;
-      dispatch_table_generator_ = nullptr;
-    }
-
     zone_ = NULL;
   }
 
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 94ec07e..f75e142 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -399,6 +399,10 @@
   void LoadField(Register dst, FieldAddress address) { ldr(dst, address); }
 
   void CompareWithFieldValue(Register value, FieldAddress address) {
+    CompareWithMemoryValue(value, address);
+  }
+
+  void CompareWithMemoryValue(Register value, Address address) {
     ldr(TMP, address);
     cmp(value, Operand(TMP));
   }
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 985f77a..86b1b03 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -478,6 +478,10 @@
   void LoadField(Register dst, FieldAddress address) { ldr(dst, address); }
 
   void CompareWithFieldValue(Register value, FieldAddress address) {
+    CompareWithMemoryValue(value, address);
+  }
+
+  void CompareWithMemoryValue(Register value, Address address) {
     ldr(TMP, address);
     cmp(value, Operand(TMP));
   }
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 89919d5..87e9008 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -923,67 +923,94 @@
 }
 
 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) {
-  const Object& object =
-      instr->instantiator_type_arguments()->definition()->constant_value();
-  if (IsNonConstant(object)) {
-    SetValue(instr, non_constant_);
-    return;
-  }
-  if (IsConstant(object)) {
-    if (instr->type().IsTypeParameter() &&
-        TypeParameter::Cast(instr->type()).IsClassTypeParameter()) {
-      if (object.IsNull()) {
-        SetValue(instr, Object::dynamic_type());
-        return;
-      }
-      // We could try to instantiate the type parameter and return it if no
-      // malformed error is reported.
+  TypeArguments& instantiator_type_args = TypeArguments::Handle(Z);
+  TypeArguments& function_type_args = TypeArguments::Handle(Z);
+  if (!instr->type().IsInstantiated(kCurrentClass)) {
+    // Type refers to class type parameters.
+    const Object& instantiator_type_args_obj =
+        instr->instantiator_type_arguments()->definition()->constant_value();
+    if (IsNonConstant(instantiator_type_args_obj)) {
+      SetValue(instr, non_constant_);
+      return;
     }
-    SetValue(instr, non_constant_);
+    if (IsConstant(instantiator_type_args_obj)) {
+      instantiator_type_args ^= instantiator_type_args_obj.raw();
+    } else {
+      return;
+    }
   }
-  // TODO(regis): We can do the same as above for a function type parameter.
-  // Better: If both instantiator type arguments and function type arguments are
-  // constant, instantiate the type if no bound error is reported.
+  if (!instr->type().IsInstantiated(kFunctions)) {
+    // Type refers to function type parameters.
+    const Object& function_type_args_obj =
+        instr->function_type_arguments()->definition()->constant_value();
+    if (IsNonConstant(function_type_args_obj)) {
+      SetValue(instr, non_constant_);
+      return;
+    }
+    if (IsConstant(function_type_args_obj)) {
+      function_type_args ^= function_type_args_obj.raw();
+    } else {
+      return;
+    }
+  }
+  AbstractType& result = AbstractType::Handle(
+      Z,
+      instr->type().InstantiateFrom(instantiator_type_args, function_type_args,
+                                    kAllFree, nullptr, Heap::kOld));
+  ASSERT(result.IsInstantiated());
+  result = result.Canonicalize();
+  SetValue(instr, result);
 }
 
 void ConstantPropagator::VisitInstantiateTypeArguments(
     InstantiateTypeArgumentsInstr* instr) {
-  const Object& instantiator_type_args =
-      instr->instantiator_type_arguments()->definition()->constant_value();
-  const Object& function_type_args =
-      instr->function_type_arguments()->definition()->constant_value();
-  if (IsNonConstant(instantiator_type_args) ||
-      IsNonConstant(function_type_args)) {
-    SetValue(instr, non_constant_);
-    return;
-  }
-  if (IsConstant(instantiator_type_args) && IsConstant(function_type_args)) {
-    if (instantiator_type_args.IsNull() && function_type_args.IsNull()) {
-      const intptr_t len = instr->type_arguments().Length();
-      if (instr->type_arguments().IsRawWhenInstantiatedFromRaw(len)) {
+  TypeArguments& instantiator_type_args = TypeArguments::Handle(Z);
+  TypeArguments& function_type_args = TypeArguments::Handle(Z);
+  if (!instr->type_arguments().IsInstantiated(kCurrentClass)) {
+    // Type arguments refer to class type parameters.
+    const Object& instantiator_type_args_obj =
+        instr->instantiator_type_arguments()->definition()->constant_value();
+    if (IsNonConstant(instantiator_type_args_obj)) {
+      SetValue(instr, non_constant_);
+      return;
+    }
+    if (IsConstant(instantiator_type_args_obj)) {
+      instantiator_type_args ^= instantiator_type_args_obj.raw();
+      if (instr->type_arguments().CanShareInstantiatorTypeArguments(
+              instr->instantiator_class())) {
         SetValue(instr, instantiator_type_args);
         return;
       }
-    }
-    if (instr->type_arguments().CanShareInstantiatorTypeArguments(
-            instr->instantiator_class())) {
-      SetValue(instr, instantiator_type_args);
+    } else {
       return;
     }
-    if (instr->type_arguments().CanShareFunctionTypeArguments(
-            instr->function())) {
-      SetValue(instr, function_type_args);
-      return;
-    }
-    SetValue(instr, non_constant_);
   }
-  // TODO(regis): If both instantiator type arguments and function type
-  // arguments are constant, instantiate the type arguments if no bound error
-  // is reported.
-  // TODO(regis): If either instantiator type arguments or function type
-  // arguments are constant null, check
-  // type_arguments().IsRawWhenInstantiatedFromRaw() separately for each
-  // genericity.
+  if (!instr->type_arguments().IsInstantiated(kFunctions)) {
+    // Type arguments refer to function type parameters.
+    const Object& function_type_args_obj =
+        instr->function_type_arguments()->definition()->constant_value();
+    if (IsNonConstant(function_type_args_obj)) {
+      SetValue(instr, non_constant_);
+      return;
+    }
+    if (IsConstant(function_type_args_obj)) {
+      function_type_args ^= function_type_args_obj.raw();
+      if (instr->type_arguments().CanShareFunctionTypeArguments(
+              instr->function())) {
+        SetValue(instr, function_type_args);
+        return;
+      }
+    } else {
+      return;
+    }
+  }
+  TypeArguments& result =
+      TypeArguments::Handle(Z, instr->type_arguments().InstantiateFrom(
+                                   instantiator_type_args, function_type_args,
+                                   kAllFree, nullptr, Heap::kOld));
+  ASSERT(result.IsInstantiated());
+  result = result.Canonicalize();
+  SetValue(instr, result);
 }
 
 void ConstantPropagator::VisitAllocateContext(AllocateContextInstr* instr) {
@@ -1347,9 +1374,15 @@
   }
 }
 
+static bool HasPhis(BlockEntryInstr* block) {
+  if (auto* join = block->AsJoinEntry()) {
+    return (join->phis() != nullptr) && !join->phis()->is_empty();
+  }
+  return false;
+}
+
 static bool IsEmptyBlock(BlockEntryInstr* block) {
-  return block->next()->IsGoto() &&
-         (!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL)) &&
+  return block->next()->IsGoto() && !HasPhis(block) &&
          !block->IsIndirectEntry();
 }
 
@@ -1360,7 +1393,7 @@
                                                    BitVector* empty_blocks) {
   BlockEntryInstr* current = block;
   while (IsEmptyBlock(current) && block->Dominates(current)) {
-    ASSERT(!block->IsJoinEntry() || (block->AsJoinEntry()->phis() == NULL));
+    ASSERT(!HasPhis(block));
     empty_blocks->Add(current->preorder_number());
     current = current->next()->AsGoto()->successor();
   }
@@ -1386,10 +1419,9 @@
         // Replace the branch with a jump to the common successor.
         // Drop the comparison, which does not have side effects
         JoinEntryInstr* join = if_true->AsJoinEntry();
-        if (join->phis() == NULL) {
-          GotoInstr* jump =
-              new (Z) GotoInstr(if_true->AsJoinEntry(), DeoptId::kNone);
-          jump->InheritDeoptTarget(Z, branch);
+        if (!HasPhis(join)) {
+          GotoInstr* jump = new (Z) GotoInstr(join, DeoptId::kNone);
+          graph_->CopyDeoptTarget(jump, branch);
 
           Instruction* previous = branch->previous();
           branch->set_previous(NULL);
@@ -1416,6 +1448,7 @@
 
   if (changed) {
     graph_->DiscoverBlocks();
+    graph_->MergeBlocks();
     // TODO(fschneider): Update dominator tree in place instead of recomputing.
     GrowableArray<BitVector*> dominance_frontier;
     graph_->ComputeDominators(&dominance_frontier);
@@ -1519,14 +1552,14 @@
         ASSERT(if_false->parallel_move() == NULL);
         join = new (Z) JoinEntryInstr(if_false->block_id(),
                                       if_false->try_index(), DeoptId::kNone);
-        join->InheritDeoptTarget(Z, if_false);
+        graph_->CopyDeoptTarget(join, if_false);
         if_false->UnuseAllInputs();
         next = if_false->next();
       } else if (!reachable_->Contains(if_false->preorder_number())) {
         ASSERT(if_true->parallel_move() == NULL);
         join = new (Z) JoinEntryInstr(if_true->block_id(), if_true->try_index(),
                                       DeoptId::kNone);
-        join->InheritDeoptTarget(Z, if_true);
+        graph_->CopyDeoptTarget(join, if_true);
         if_true->UnuseAllInputs();
         next = if_true->next();
       }
@@ -1537,7 +1570,7 @@
         // as it is a strict compare (the only one we can determine is
         // constant with the current analysis).
         GotoInstr* jump = new (Z) GotoInstr(join, DeoptId::kNone);
-        jump->InheritDeoptTarget(Z, branch);
+        graph_->CopyDeoptTarget(jump, branch);
 
         Instruction* previous = branch->previous();
         branch->set_previous(NULL);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 82b69ae..63b0431 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -2340,14 +2340,13 @@
 void FlowGraphCompiler::GenerateAssertAssignableViaTypeTestingStub(
     const AbstractType& dst_type,
     const String& dst_name,
-    const Register instance_reg,
-    const Register instantiator_type_args_reg,
-    const Register function_type_args_reg,
-    const Register subtype_cache_reg,
-    const Register dst_type_reg,
     const Register dst_type_reg_to_call,
     const Register scratch_reg,
     compiler::Label* done) {
+#if defined(TARGET_ARCH_IA32)
+  // ia32 does not have support for TypeTestingStubs.
+  UNREACHABLE();
+#else
   TypeUsageInfo* type_usage_info = thread()->type_usage_info();
 
   // If the int type is assignable to [dst_type] we special case it on the
@@ -2355,14 +2354,16 @@
   const Type& int_type = Type::Handle(zone(), Type::IntType());
   bool is_non_smi = false;
   if (int_type.IsSubtypeOf(dst_type, Heap::kOld)) {
-    __ BranchIfSmi(instance_reg, done);
+    __ BranchIfSmi(TypeTestABI::kInstanceReg, done);
     is_non_smi = true;
   }
 
   // We use two type registers iff the dst type is a type parameter.
   // We "dereference" the type parameter for the TTS call but leave the type
-  // parameter in the dst_type_reg for fallback into SubtypeTestCache.
-  ASSERT(dst_type.IsTypeParameter() == (dst_type_reg != dst_type_reg_to_call));
+  // parameter in the TypeTestABI::kDstTypeReg for fallback into
+  // SubtypeTestCache.
+  ASSERT(dst_type.IsTypeParameter() ==
+         (TypeTestABI::kDstTypeReg != dst_type_reg_to_call));
 
   // We can handle certain types very efficiently on the call site (with a
   // bailout to the normal stub, which will do a runtime call).
@@ -2373,13 +2374,14 @@
     // In NNBD weak mode or if type parameter is non-nullable or has
     // undetermined nullability null instance is correctly handled by TTS.
     if (FLAG_null_safety && (dst_type.IsNullable() || dst_type.IsLegacy())) {
-      __ CompareObject(instance_reg, Object::null_object());
+      __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
       __ BranchIf(EQUAL, done);
     }
     const TypeParameter& type_param = TypeParameter::Cast(dst_type);
-    const Register kTypeArgumentsReg = type_param.IsClassTypeParameter()
-                                           ? instantiator_type_args_reg
-                                           : function_type_args_reg;
+    const Register kTypeArgumentsReg =
+        type_param.IsClassTypeParameter()
+            ? TypeTestABI::kInstantiatorTypeArgumentsReg
+            : TypeTestABI::kFunctionTypeArgumentsReg;
 
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ CompareObject(kTypeArgumentsReg, Object::null_object());
@@ -2389,7 +2391,7 @@
         compiler::FieldAddress(kTypeArgumentsReg,
                                compiler::target::TypeArguments::type_at_offset(
                                    type_param.index())));
-    __ LoadObject(dst_type_reg, type_param);
+    __ LoadObject(TypeTestABI::kDstTypeReg, type_param);
     if (type_usage_info != NULL) {
       type_usage_info->UseTypeInAssertAssignable(dst_type);
     }
@@ -2409,9 +2411,9 @@
             /*exclude_null=*/!Instance::NullIsAssignableTo(dst_type));
         if (ranges.length() <= kMaxNumberOfCidRangesToTest) {
           if (is_non_smi) {
-            __ LoadClassId(scratch_reg, instance_reg);
+            __ LoadClassId(scratch_reg, TypeTestABI::kInstanceReg);
           } else {
-            __ LoadClassIdMayBeSmi(scratch_reg, instance_reg);
+            __ LoadClassIdMayBeSmi(scratch_reg, TypeTestABI::kInstanceReg);
           }
           GenerateCidRangesCheck(assembler(), scratch_reg, ranges, done);
           used_cid_range_check = true;
@@ -2421,7 +2423,7 @@
 
       if (!used_cid_range_check && can_use_simple_cid_range_test &&
           IsListClass(type_class)) {
-        __ LoadClassIdMayBeSmi(scratch_reg, instance_reg);
+        __ LoadClassIdMayBeSmi(scratch_reg, TypeTestABI::kInstanceReg);
         GenerateListTypeCheck(scratch_reg, done);
         used_cid_range_check = true;
       }
@@ -2437,8 +2439,9 @@
         }
       }
     }
-    __ LoadObject(dst_type_reg, dst_type);
+    __ LoadObject(TypeTestABI::kDstTypeReg, dst_type);
   }
+#endif  // defined(TARGET_ARCH_IA32)
 }
 
 #undef __
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index f34e9e7..0c16478 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -568,11 +568,6 @@
   void GenerateAssertAssignableViaTypeTestingStub(
       const AbstractType& dst_type,
       const String& dst_name,
-      const Register instance_reg,
-      const Register instantiator_type_args_reg,
-      const Register function_type_args_reg,
-      const Register subtype_cache_reg,
-      const Register dst_type_reg,
       const Register dst_type_reg_to_call,
       const Register scratch_reg,
       compiler::Label* done);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 30499dc..b1bdb6b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -246,12 +246,16 @@
     ASSERT(function_type_arguments_reg == kNoRegister);
     __ BranchLink(StubCode::Subtype2TestCache());
   } else if (test_kind == kTestTypeFourArgs) {
-    ASSERT(instantiator_type_arguments_reg == R2);
-    ASSERT(function_type_arguments_reg == R1);
+    ASSERT(instantiator_type_arguments_reg ==
+           TypeTestABI::kInstantiatorTypeArgumentsReg);
+    ASSERT(function_type_arguments_reg ==
+           TypeTestABI::kFunctionTypeArgumentsReg);
     __ BranchLink(StubCode::Subtype4TestCache());
   } else if (test_kind == kTestTypeSixArgs) {
-    ASSERT(instantiator_type_arguments_reg == R2);
-    ASSERT(function_type_arguments_reg == R1);
+    ASSERT(instantiator_type_arguments_reg ==
+           TypeTestABI::kInstantiatorTypeArgumentsReg);
+    ASSERT(function_type_arguments_reg ==
+           TypeTestABI::kFunctionTypeArgumentsReg);
     __ BranchLink(StubCode::Subtype6TestCache());
   } else {
     UNREACHABLE();
@@ -277,10 +281,9 @@
   ASSERT(!type.IsFunctionType());
   const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() > 0);
-  const Register kInstanceReg = R0;
   const Type& smi_type = Type::Handle(zone(), Type::SmiType());
   const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
-  __ tst(kInstanceReg, compiler::Operand(kSmiTagMask));
+  __ tst(TypeTestABI::kInstanceReg, compiler::Operand(kSmiTagMask));
   if (smi_is_ok) {
     // Fast case for type = FutureOr<int/num/top-type>.
     __ b(is_instance_lbl, EQ);
@@ -297,7 +300,7 @@
   if (is_raw_type) {
     const Register kClassIdReg = R2;
     // dynamic type argument, check only classes.
-    __ LoadClassId(kClassIdReg, kInstanceReg);
+    __ LoadClassId(kClassIdReg, TypeTestABI::kInstanceReg);
     __ CompareImmediate(kClassIdReg, type_class.id());
     __ b(is_instance_lbl, EQ);
     // List is a very common case.
@@ -328,10 +331,10 @@
   const Register kFunctionTypeArgumentsReg = kNoRegister;
   const Register kTempReg = kNoRegister;
   // R0: instance (must be preserved).
-  return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, kInstanceReg,
-                                     kInstantiatorTypeArgumentsReg,
-                                     kFunctionTypeArgumentsReg, kTempReg,
-                                     is_instance_lbl, is_not_instance_lbl);
+  return GenerateCallSubtypeTestStub(
+      kTestTypeTwoArgs, TypeTestABI::kInstanceReg,
+      kInstantiatorTypeArgumentsReg, kFunctionTypeArgumentsReg, kTempReg,
+      is_instance_lbl, is_not_instance_lbl);
 }
 
 void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
@@ -422,14 +425,13 @@
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
   __ Comment("Subtype1TestCacheLookup");
-  const Register kInstanceReg = R0;
 #if defined(DEBUG)
   compiler::Label ok;
-  __ BranchIfNotSmi(kInstanceReg, &ok);
+  __ BranchIfNotSmi(TypeTestABI::kInstanceReg, &ok);
   __ Breakpoint();
   __ Bind(&ok);
 #endif
-  __ LoadClassId(R2, kInstanceReg);
+  __ LoadClassId(R2, TypeTestABI::kInstanceReg);
   __ LoadClassById(R1, R2);
   // R1: instance class.
   // Check immediate superclass equality.
@@ -443,7 +445,7 @@
   const Register kInstantiatorTypeArgumentsReg = kNoRegister;
   const Register kFunctionTypeArgumentsReg = kNoRegister;
   const Register kTempReg = kNoRegister;
-  return GenerateCallSubtypeTestStub(kTestTypeOneArg, kInstanceReg,
+  return GenerateCallSubtypeTestStub(kTestTypeOneArg, TypeTestABI::kInstanceReg,
                                      kInstantiatorTypeArgumentsReg,
                                      kFunctionTypeArgumentsReg, kTempReg,
                                      is_instance_lbl, is_not_instance_lbl);
@@ -457,23 +459,21 @@
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
   __ Comment("UninstantiatedTypeTest");
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
   const Register kTempReg = kNoRegister;
   ASSERT(!type.IsInstantiated());
   ASSERT(!type.IsFunctionType());
   // Skip check if destination is a dynamic type.
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
-
+    static_assert(kFunctionTypeArgumentsReg < kInstantiatorTypeArgumentsReg,
+                  "Should be ordered to load arguments with one instruction");
     __ ldm(IA, SP,
-           (1 << kFunctionTypeArgumentsReg) |
-               (1 << kInstantiatorTypeArgumentsReg));
-    // R2: instantiator type arguments.
-    // R1: function type arguments.
+           (1 << TypeTestABI::kFunctionTypeArgumentsReg) |
+               (1 << TypeTestABI::kInstantiatorTypeArgumentsReg));
     const Register kTypeArgumentsReg =
-        type_param.IsClassTypeParameter() ? R2 : R1;
+        type_param.IsClassTypeParameter()
+            ? TypeTestABI::kInstantiatorTypeArgumentsReg
+            : TypeTestABI::kFunctionTypeArgumentsReg;
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ CompareObject(kTypeArgumentsReg, Object::null_object());
     __ b(is_instance_lbl, EQ);
@@ -504,25 +504,30 @@
     const auto test_kind = GetTypeTestStubKindForTypeParameter(type_param);
     const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle(
         zone(), GenerateCallSubtypeTestStub(
-                    test_kind, kInstanceReg, kInstantiatorTypeArgumentsReg,
-                    kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
-                    is_not_instance_lbl));
+                    test_kind, TypeTestABI::kInstanceReg,
+                    TypeTestABI::kInstantiatorTypeArgumentsReg,
+                    TypeTestABI::kFunctionTypeArgumentsReg, kTempReg,
+                    is_instance_lbl, is_not_instance_lbl));
     return type_test_cache.raw();
   }
   if (type.IsType()) {
     // Smi is FutureOr<T>, when T is a top type or int or num.
     if (!type.IsFutureOrType()) {
-      __ BranchIfSmi(kInstanceReg, is_not_instance_lbl);
+      __ BranchIfSmi(TypeTestABI::kInstanceReg, is_not_instance_lbl);
     }
+    static_assert(TypeTestABI::kFunctionTypeArgumentsReg <
+                      TypeTestABI::kInstantiatorTypeArgumentsReg,
+                  "Should be ordered to load arguments with one instruction");
     __ ldm(IA, SP,
-           (1 << kFunctionTypeArgumentsReg) |
-               (1 << kInstantiatorTypeArgumentsReg));
+           (1 << TypeTestABI::kFunctionTypeArgumentsReg) |
+               (1 << TypeTestABI::kInstantiatorTypeArgumentsReg));
     // Uninstantiated type class is known at compile time, but the type
     // arguments are determined at runtime by the instantiator(s).
-    return GenerateCallSubtypeTestStub(kTestTypeFourArgs, kInstanceReg,
-                                       kInstantiatorTypeArgumentsReg,
-                                       kFunctionTypeArgumentsReg, kTempReg,
-                                       is_instance_lbl, is_not_instance_lbl);
+    return GenerateCallSubtypeTestStub(
+        kTestTypeFourArgs, TypeTestABI::kInstanceReg,
+        TypeTestABI::kInstantiatorTypeArgumentsReg,
+        TypeTestABI::kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
+        is_not_instance_lbl);
   }
   return SubtypeTestCache::null();
 }
@@ -535,20 +540,21 @@
     const AbstractType& type,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
-  __ BranchIfSmi(kInstanceReg, is_not_instance_lbl);
-  __ ldm(
-      IA, SP,
-      (1 << kFunctionTypeArgumentsReg) | (1 << kInstantiatorTypeArgumentsReg));
+  __ BranchIfSmi(TypeTestABI::kInstanceReg, is_not_instance_lbl);
+  static_assert(TypeTestABI::kFunctionTypeArgumentsReg <
+                    TypeTestABI::kInstantiatorTypeArgumentsReg,
+                "Should be ordered to load arguments with one instruction");
+  __ ldm(IA, SP,
+         (1 << TypeTestABI::kFunctionTypeArgumentsReg) |
+             (1 << TypeTestABI::kInstantiatorTypeArgumentsReg));
   // Uninstantiated type class is known at compile time, but the type
   // arguments are determined at runtime by the instantiator(s).
   const Register kTempReg = kNoRegister;
-  return GenerateCallSubtypeTestStub(kTestTypeSixArgs, kInstanceReg,
-                                     kInstantiatorTypeArgumentsReg,
-                                     kFunctionTypeArgumentsReg, kTempReg,
-                                     is_instance_lbl, is_not_instance_lbl);
+  return GenerateCallSubtypeTestStub(
+      kTestTypeSixArgs, TypeTestABI::kInstanceReg,
+      TypeTestABI::kInstantiatorTypeArgumentsReg,
+      TypeTestABI::kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
+      is_not_instance_lbl);
 }
 
 // Inputs:
@@ -616,10 +622,11 @@
                                            LocationSummary* locs) {
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsTopType());  // Already checked.
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
-  __ PushList((1 << kInstantiatorTypeArgumentsReg) |
-              (1 << kFunctionTypeArgumentsReg));
+  static_assert(TypeTestABI::kFunctionTypeArgumentsReg <
+                    TypeTestABI::kInstantiatorTypeArgumentsReg,
+                "Should be ordered to push arguments with one instruction");
+  __ PushList((1 << TypeTestABI::kInstantiatorTypeArgumentsReg) |
+              (1 << TypeTestABI::kFunctionTypeArgumentsReg));
 
   compiler::Label is_instance, is_not_instance;
   // 'null' is an instance of Null, Object*, Never*, void, and dynamic.
@@ -630,7 +637,7 @@
   if (!unwrapped_type.IsTypeParameter() || unwrapped_type.IsNullable()) {
     // Only nullable type parameter remains nullable after instantiation.
     // See NullIsInstanceOf().
-    __ CompareObject(R0, Object::null_object());
+    __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
     __ b((unwrapped_type.IsNullable() ||
           (unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType()))
              ? &is_instance
@@ -647,14 +654,17 @@
   compiler::Label done;
   if (!test_cache.IsNull()) {
     // Generate runtime call.
+    static_assert(TypeTestABI::kFunctionTypeArgumentsReg <
+                      TypeTestABI::kInstantiatorTypeArgumentsReg,
+                  "Should be ordered to load arguments with one instruction");
     __ ldm(IA, SP,
-           (1 << kFunctionTypeArgumentsReg) |
-               (1 << kInstantiatorTypeArgumentsReg));
+           (1 << TypeTestABI::kFunctionTypeArgumentsReg) |
+               (1 << TypeTestABI::kInstantiatorTypeArgumentsReg));
     __ PushObject(Object::null_object());  // Make room for the result.
-    __ Push(R0);                           // Push the instance.
+    __ Push(TypeTestABI::kInstanceReg);    // Push the instance.
     __ PushObject(type);                   // Push the type.
-    __ PushList((1 << kInstantiatorTypeArgumentsReg) |
-                (1 << kFunctionTypeArgumentsReg));
+    __ PushList((1 << TypeTestABI::kInstantiatorTypeArgumentsReg) |
+                (1 << TypeTestABI::kFunctionTypeArgumentsReg));
     __ LoadUniqueObject(R0, test_cache);
     __ Push(R0);
     GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
@@ -698,9 +708,6 @@
   // Assignable check is skipped in FlowGraphBuilder, not here.
   ASSERT(!dst_type.IsTopTypeForAssignability());
 
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
-
   if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
     GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
                                                dst_name, locs);
@@ -708,12 +715,15 @@
     compiler::Label is_assignable_fast, is_assignable, runtime_call;
 
     if (Instance::NullIsAssignableTo(dst_type)) {
-      __ CompareObject(R0, Object::null_object());
+      __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
       __ b(&is_assignable_fast, EQ);
     }
 
-    __ PushList((1 << kInstantiatorTypeArgumentsReg) |
-                (1 << kFunctionTypeArgumentsReg));
+    static_assert(TypeTestABI::kFunctionTypeArgumentsReg <
+                      TypeTestABI::kInstantiatorTypeArgumentsReg,
+                  "Should be ordered to push arguments with one instruction");
+    __ PushList((1 << TypeTestABI::kInstantiatorTypeArgumentsReg) |
+                (1 << TypeTestABI::kFunctionTypeArgumentsReg));
 
     // Generate inline type check, linking to runtime call if not assignable.
     SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
@@ -721,14 +731,17 @@
                                           &runtime_call);
 
     __ Bind(&runtime_call);
+    static_assert(TypeTestABI::kFunctionTypeArgumentsReg <
+                      TypeTestABI::kInstantiatorTypeArgumentsReg,
+                  "Should be ordered to load arguments with one instruction");
     __ ldm(IA, SP,
-           (1 << kFunctionTypeArgumentsReg) |
-               (1 << kInstantiatorTypeArgumentsReg));
+           (1 << TypeTestABI::kFunctionTypeArgumentsReg) |
+               (1 << TypeTestABI::kInstantiatorTypeArgumentsReg));
     __ PushObject(Object::null_object());  // Make room for the result.
-    __ Push(R0);                           // Push the source object.
+    __ Push(TypeTestABI::kInstanceReg);    // Push the source object.
     __ PushObject(dst_type);               // Push the type of the destination.
-    __ PushList((1 << kInstantiatorTypeArgumentsReg) |
-                (1 << kFunctionTypeArgumentsReg));
+    __ PushList((1 << TypeTestABI::kInstantiatorTypeArgumentsReg) |
+                (1 << TypeTestABI::kFunctionTypeArgumentsReg));
     __ PushObject(dst_name);  // Push the name of the destination.
     __ LoadUniqueObject(R0, test_cache);
     __ Push(R0);
@@ -739,8 +752,8 @@
     __ Drop(7);
     __ Pop(R0);
     __ Bind(&is_assignable);
-    __ PopList((1 << kFunctionTypeArgumentsReg) |
-               (1 << kInstantiatorTypeArgumentsReg));
+    __ PopList((1 << TypeTestABI::kFunctionTypeArgumentsReg) |
+               (1 << TypeTestABI::kInstantiatorTypeArgumentsReg));
     __ Bind(&is_assignable_fast);
   }
 }
@@ -751,21 +764,15 @@
     const AbstractType& dst_type,
     const String& dst_name,
     LocationSummary* locs) {
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
-
-  const Register kSubtypeTestCacheReg = R3;
-  const Register kDstTypeReg = R8;
-  const Register kRegToCall = dst_type.IsTypeParameter() ? R9 : kDstTypeReg;
+  const Register kRegToCall =
+      dst_type.IsTypeParameter() ? R9 : TypeTestABI::kDstTypeReg;
   const Register kScratchReg = R4;
 
   compiler::Label done;
 
-  GenerateAssertAssignableViaTypeTestingStub(
-      dst_type, dst_name, kInstanceReg, kInstantiatorTypeArgumentsReg,
-      kFunctionTypeArgumentsReg, kSubtypeTestCacheReg, kDstTypeReg, kRegToCall,
-      kScratchReg, &done);
+  GenerateAssertAssignableViaTypeTestingStub(dst_type, dst_name, kRegToCall,
+                                             kScratchReg, &done);
+
   // We use 2 consecutive entries in the pool for the subtype cache and the
   // destination name.  The second entry, namely [dst_name] seems to be unused,
   // but it will be used by the code throwing a TypeError if the type test fails
@@ -787,8 +794,8 @@
       compiler::FieldAddress(
           kRegToCall,
           compiler::target::AbstractType::type_test_stub_entry_point_offset()));
-  __ LoadWordFromPoolOffset(kSubtypeTestCacheReg, sub_type_cache_offset, PP,
-                            AL);
+  __ LoadWordFromPoolOffset(TypeTestABI::kSubtypeTestCacheReg,
+                            sub_type_cache_offset, PP, AL);
   __ blx(R9);
   EmitCallsiteMetadata(token_pos, deopt_id, RawPcDescriptors::kOther, locs);
   __ Bind(&done);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index acaa121..f4a6885 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -213,8 +213,8 @@
 }
 
 // R0: instance (must be preserved).
-// R1: instantiator type arguments (if used).
-// R2: function type arguments (if used).
+// R2: instantiator type arguments (if used).
+// R1: function type arguments (if used).
 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub(
     TypeTestStubKind test_kind,
     Register instance_reg,
@@ -237,12 +237,16 @@
     ASSERT(function_type_arguments_reg == kNoRegister);
     __ BranchLink(StubCode::Subtype2TestCache());
   } else if (test_kind == kTestTypeFourArgs) {
-    ASSERT(instantiator_type_arguments_reg == R1);
-    ASSERT(function_type_arguments_reg == R2);
+    ASSERT(instantiator_type_arguments_reg ==
+           TypeTestABI::kInstantiatorTypeArgumentsReg);
+    ASSERT(function_type_arguments_reg ==
+           TypeTestABI::kFunctionTypeArgumentsReg);
     __ BranchLink(StubCode::Subtype4TestCache());
   } else if (test_kind == kTestTypeSixArgs) {
-    ASSERT(instantiator_type_arguments_reg == R1);
-    ASSERT(function_type_arguments_reg == R2);
+    ASSERT(instantiator_type_arguments_reg ==
+           TypeTestABI::kInstantiatorTypeArgumentsReg);
+    ASSERT(function_type_arguments_reg ==
+           TypeTestABI::kFunctionTypeArgumentsReg);
     __ BranchLink(StubCode::Subtype6TestCache());
   } else {
     UNREACHABLE();
@@ -268,11 +272,10 @@
   ASSERT(!type.IsFunctionType());
   const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() > 0);
-  const Register kInstanceReg = R0;
   const Type& smi_type = Type::Handle(zone(), Type::SmiType());
   const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
   // Fast case for type = FutureOr<int/num/top-type>.
-  __ BranchIfSmi(kInstanceReg,
+  __ BranchIfSmi(TypeTestABI::kInstanceReg,
                  smi_is_ok ? is_instance_lbl : is_not_instance_lbl);
 
   const intptr_t num_type_args = type_class.NumTypeArguments();
@@ -285,7 +288,7 @@
   if (is_raw_type) {
     const Register kClassIdReg = R2;
     // dynamic type argument, check only classes.
-    __ LoadClassId(kClassIdReg, kInstanceReg);
+    __ LoadClassId(kClassIdReg, TypeTestABI::kInstanceReg);
     __ CompareImmediate(kClassIdReg, type_class.id());
     __ b(is_instance_lbl, EQ);
     // List is a very common case.
@@ -314,10 +317,10 @@
   const Register kFunctionTypeArgumentsReg = kNoRegister;
   const Register kTempReg = kNoRegister;
   // R0: instance (must be preserved).
-  return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, kInstanceReg,
-                                     kInstantiatorTypeArgumentsReg,
-                                     kFunctionTypeArgumentsReg, kTempReg,
-                                     is_instance_lbl, is_not_instance_lbl);
+  return GenerateCallSubtypeTestStub(
+      kTestTypeTwoArgs, TypeTestABI::kInstanceReg,
+      kInstantiatorTypeArgumentsReg, kFunctionTypeArgumentsReg, kTempReg,
+      is_instance_lbl, is_not_instance_lbl);
 }
 
 void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
@@ -407,14 +410,13 @@
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
   __ Comment("Subtype1TestCacheLookup");
-  const Register kInstanceReg = R0;
 #if defined(DEBUG)
   compiler::Label ok;
-  __ BranchIfNotSmi(kInstanceReg, &ok);
+  __ BranchIfNotSmi(TypeTestABI::kInstanceReg, &ok);
   __ Breakpoint();
   __ Bind(&ok);
 #endif
-  __ LoadClassId(TMP, kInstanceReg);
+  __ LoadClassId(TMP, TypeTestABI::kInstanceReg);
   __ LoadClassById(R1, TMP);
   // R1: instance class.
   // Check immediate superclass equality.
@@ -426,7 +428,7 @@
   const Register kInstantiatorTypeArgumentsReg = kNoRegister;
   const Register kFunctionTypeArgumentsReg = kNoRegister;
   const Register kTempReg = kNoRegister;
-  return GenerateCallSubtypeTestStub(kTestTypeOneArg, kInstanceReg,
+  return GenerateCallSubtypeTestStub(kTestTypeOneArg, TypeTestABI::kInstanceReg,
                                      kInstantiatorTypeArgumentsReg,
                                      kFunctionTypeArgumentsReg, kTempReg,
                                      is_instance_lbl, is_not_instance_lbl);
@@ -440,9 +442,6 @@
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
   __ Comment("UninstantiatedTypeTest");
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
   const Register kTempReg = kNoRegister;
   ASSERT(!type.IsInstantiated());
   ASSERT(!type.IsFunctionType());
@@ -450,12 +449,14 @@
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
 
-    // Get instantiator type args (high, R1) and function type args (low, R2).
-    __ ldp(R2, R1,
+    // Get instantiator type args (high) and function type args (low).
+    __ ldp(TypeTestABI::kFunctionTypeArgumentsReg,
+           TypeTestABI::kInstantiatorTypeArgumentsReg,
            compiler::Address(SP, 0 * kWordSize, compiler::Address::PairOffset));
-    const Register kTypeArgumentsReg = type_param.IsClassTypeParameter()
-                                           ? kInstantiatorTypeArgumentsReg
-                                           : kFunctionTypeArgumentsReg;
+    const Register kTypeArgumentsReg =
+        type_param.IsClassTypeParameter()
+            ? TypeTestABI::kInstantiatorTypeArgumentsReg
+            : TypeTestABI::kFunctionTypeArgumentsReg;
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ CompareObject(kTypeArgumentsReg, Object::null_object());
     __ b(is_instance_lbl, EQ);
@@ -483,24 +484,27 @@
     const auto test_kind = GetTypeTestStubKindForTypeParameter(type_param);
     const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle(
         zone(), GenerateCallSubtypeTestStub(
-                    test_kind, kInstanceReg, kInstantiatorTypeArgumentsReg,
-                    kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
-                    is_not_instance_lbl));
+                    test_kind, TypeTestABI::kInstanceReg,
+                    TypeTestABI::kInstantiatorTypeArgumentsReg,
+                    TypeTestABI::kFunctionTypeArgumentsReg, kTempReg,
+                    is_instance_lbl, is_not_instance_lbl));
     return type_test_cache.raw();
   }
   if (type.IsType()) {
     // Smi is FutureOr<T>, when T is a top type or int or num.
     if (!type.IsFutureOrType()) {
-      __ BranchIfSmi(kInstanceReg, is_not_instance_lbl);
+      __ BranchIfSmi(TypeTestABI::kInstanceReg, is_not_instance_lbl);
     }
-    __ ldp(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg,
+    __ ldp(TypeTestABI::kFunctionTypeArgumentsReg,
+           TypeTestABI::kInstantiatorTypeArgumentsReg,
            compiler::Address(SP, 0 * kWordSize, compiler::Address::PairOffset));
     // Uninstantiated type class is known at compile time, but the type
     // arguments are determined at runtime by the instantiator.
-    return GenerateCallSubtypeTestStub(kTestTypeFourArgs, kInstanceReg,
-                                       kInstantiatorTypeArgumentsReg,
-                                       kFunctionTypeArgumentsReg, kTempReg,
-                                       is_instance_lbl, is_not_instance_lbl);
+    return GenerateCallSubtypeTestStub(
+        kTestTypeFourArgs, TypeTestABI::kInstanceReg,
+        TypeTestABI::kInstantiatorTypeArgumentsReg,
+        TypeTestABI::kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
+        is_not_instance_lbl);
   }
   return SubtypeTestCache::null();
 }
@@ -513,29 +517,28 @@
     const AbstractType& type,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
-  __ BranchIfSmi(kInstanceReg, is_not_instance_lbl);
-  __ ldp(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg,
+  __ BranchIfSmi(TypeTestABI::kInstanceReg, is_not_instance_lbl);
+  __ ldp(TypeTestABI::kFunctionTypeArgumentsReg,
+         TypeTestABI::kInstantiatorTypeArgumentsReg,
          compiler::Address(SP, 0 * kWordSize, compiler::Address::PairOffset));
   // Uninstantiated type class is known at compile time, but the type
   // arguments are determined at runtime by the instantiator(s).
   const Register kTempReg = kNoRegister;
-  return GenerateCallSubtypeTestStub(kTestTypeSixArgs, kInstanceReg,
-                                     kInstantiatorTypeArgumentsReg,
-                                     kFunctionTypeArgumentsReg, kTempReg,
-                                     is_instance_lbl, is_not_instance_lbl);
+  return GenerateCallSubtypeTestStub(
+      kTestTypeSixArgs, TypeTestABI::kInstanceReg,
+      TypeTestABI::kInstantiatorTypeArgumentsReg,
+      TypeTestABI::kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
+      is_not_instance_lbl);
 }
 
 // Inputs:
 // - R0: instance being type checked (preserved).
-// - R1: optional instantiator type arguments (preserved).
-// - R2: optional function type arguments (preserved).
+// - R2: optional instantiator type arguments (preserved).
+// - R1: optional function type arguments (preserved).
 // Clobbers R3, R4, R8, R9.
 // Returns:
-// - preserved instance in R0, optional instantiator type arguments in R1, and
-//   optional function type arguments in R2.
+// - preserved instance in R0, optional instantiator type arguments in R2, and
+//   optional function type arguments in R1.
 // Note that this inlined code must be followed by the runtime_call code, as it
 // may fall through to it. Otherwise, this inline code will jump to the label
 // is_instance or to the label is_not_instance.
@@ -583,8 +586,8 @@
 // - Class equality (only if class is not parameterized).
 // Inputs:
 // - R0: object.
-// - R1: instantiator type arguments or raw_null.
-// - R2: function type arguments or raw_null.
+// - R2: instantiator type arguments or raw_null.
+// - R1: function type arguments or raw_null.
 // Returns:
 // - true or false in R0.
 void FlowGraphCompiler::GenerateInstanceOf(TokenPosition token_pos,
@@ -593,9 +596,8 @@
                                            LocationSummary* locs) {
   ASSERT(type.IsFinalized());
   ASSERT(!type.IsTopType());  // Already checked.
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
-  __ PushPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
+  __ PushPair(TypeTestABI::kFunctionTypeArgumentsReg,
+              TypeTestABI::kInstantiatorTypeArgumentsReg);
 
   compiler::Label is_instance, is_not_instance;
   // 'null' is an instance of Null, Object*, Never*, void, and dynamic.
@@ -606,7 +608,7 @@
   if (!unwrapped_type.IsTypeParameter() || unwrapped_type.IsNullable()) {
     // Only nullable type parameter remains nullable after instantiation.
     // See NullIsInstanceOf().
-    __ CompareObject(R0, Object::null_object());
+    __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
     __ b((unwrapped_type.IsNullable() ||
           (unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType()))
              ? &is_instance
@@ -623,17 +625,17 @@
   compiler::Label done;
   if (!test_cache.IsNull()) {
     // Generate runtime call.
-    const Register kInstantiatorTypeArgumentsReg = R1;
-    const Register kFunctionTypeArgumentsReg = R2;
-    __ ldp(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg,
+    __ ldp(TypeTestABI::kFunctionTypeArgumentsReg,
+           TypeTestABI::kInstantiatorTypeArgumentsReg,
            compiler::Address(SP, 0 * kWordSize, compiler::Address::PairOffset));
-    __ PushPair(R0, NULL_REG);  // Make room for the result and
+    __ PushPair(TypeTestABI::kInstanceReg,
+                NULL_REG);      // Make room for the result and
                                 // push the instance.
     __ LoadObject(TMP, type);   // Push the type.
 
-    __ PushPair(kInstantiatorTypeArgumentsReg, TMP);
+    __ PushPair(TypeTestABI::kInstantiatorTypeArgumentsReg, TMP);
     __ LoadUniqueObject(R0, test_cache);
-    __ PushPair(R0, kFunctionTypeArgumentsReg);
+    __ PushPair(R0, TypeTestABI::kFunctionTypeArgumentsReg);
     GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
     // Pop the parameters supplied to the runtime entry. The result of the
     // instanceof runtime call will be left as the result of the operation.
@@ -658,8 +660,8 @@
 // - Class equality (only if class is not parameterized).
 // Inputs:
 // - R0: instance being type checked.
-// - R1: instantiator type arguments or raw_null.
-// - R2: function type arguments or raw_null.
+// - R2: instantiator type arguments or raw_null.
+// - R1: function type arguments or raw_null.
 // Returns:
 // - object in R0 for successful assignable check (or throws TypeError).
 // Performance notes: positive checks must be quick, negative checks can be slow
@@ -675,9 +677,6 @@
   // Assignable check is skipped in FlowGraphBuilder, not here.
   ASSERT(!dst_type.IsTopTypeForAssignability());
 
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
-
   if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
     GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
                                                dst_name, locs);
@@ -685,11 +684,12 @@
     compiler::Label is_assignable_fast, is_assignable, runtime_call;
 
     if (Instance::NullIsAssignableTo(dst_type)) {
-      __ CompareObject(R0, Object::null_object());
+      __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
       __ b(&is_assignable_fast, EQ);
     }
 
-    __ PushPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
+    __ PushPair(TypeTestABI::kFunctionTypeArgumentsReg,
+                TypeTestABI::kInstantiatorTypeArgumentsReg);
 
     // Generate inline type check, linking to runtime call if not assignable.
     SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(zone());
@@ -697,14 +697,16 @@
                                           &runtime_call);
 
     __ Bind(&runtime_call);
-    __ ldp(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg,
+    __ ldp(TypeTestABI::kFunctionTypeArgumentsReg,
+           TypeTestABI::kInstantiatorTypeArgumentsReg,
            compiler::Address(SP, 0 * kWordSize, compiler::Address::PairOffset));
-    __ PushPair(R0, NULL_REG);     // Make room for the result and
+    __ PushPair(TypeTestABI::kInstanceReg,
+                NULL_REG);         // Make room for the result and
                                    // push the source object.
     __ LoadObject(TMP, dst_type);  // Push the type of the dest.
-    __ PushPair(kInstantiatorTypeArgumentsReg, TMP);
+    __ PushPair(TypeTestABI::kInstantiatorTypeArgumentsReg, TMP);
     __ LoadObject(TMP, dst_name);  // Push the name of the destination.
-    __ PushPair(TMP, kFunctionTypeArgumentsReg);
+    __ PushPair(TMP, TypeTestABI::kFunctionTypeArgumentsReg);
 
     __ LoadUniqueObject(R0, test_cache);
     __ LoadObject(TMP, Smi::ZoneHandle(zone(), Smi::New(kTypeCheckFromInline)));
@@ -715,7 +717,8 @@
     __ Drop(7);
     __ Pop(R0);
     __ Bind(&is_assignable);
-    __ PopPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
+    __ PopPair(TypeTestABI::kFunctionTypeArgumentsReg,
+               TypeTestABI::kInstantiatorTypeArgumentsReg);
     __ Bind(&is_assignable_fast);
   }
 }
@@ -726,21 +729,14 @@
     const AbstractType& dst_type,
     const String& dst_name,
     LocationSummary* locs) {
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
-
-  const Register kSubtypeTestCacheReg = R3;
-  const Register kDstTypeReg = R8;
-  const Register kRegToCall = dst_type.IsTypeParameter() ? R9 : kDstTypeReg;
+  const Register kRegToCall =
+      dst_type.IsTypeParameter() ? R9 : TypeTestABI::kDstTypeReg;
   const Register kScratchReg = R4;
 
   compiler::Label done;
 
-  GenerateAssertAssignableViaTypeTestingStub(
-      dst_type, dst_name, kInstanceReg, kInstantiatorTypeArgumentsReg,
-      kFunctionTypeArgumentsReg, kSubtypeTestCacheReg, kDstTypeReg, kRegToCall,
-      kScratchReg, &done);
+  GenerateAssertAssignableViaTypeTestingStub(dst_type, dst_name, kRegToCall,
+                                             kScratchReg, &done);
 
   // We use 2 consecutive entries in the pool for the subtype cache and the
   // destination name.  The second entry, namely [dst_name] seems to be unused,
@@ -760,7 +756,8 @@
   __ LoadField(
       R9, compiler::FieldAddress(
               kRegToCall, AbstractType::type_test_stub_entry_point_offset()));
-  __ LoadWordFromPoolOffset(kSubtypeTestCacheReg, sub_type_cache_offset);
+  __ LoadWordFromPoolOffset(TypeTestABI::kSubtypeTestCacheReg,
+                            sub_type_cache_offset);
   __ blr(R9);
   EmitCallsiteMetadata(token_pos, deopt_id, RawPcDescriptors::kOther, locs);
   __ Bind(&done);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 0605ba8..d7fcd3e 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -433,8 +433,6 @@
     compiler::Label* is_not_instance_lbl) {
   __ Comment("UninstantiatedTypeTest");
   const Register kInstanceReg = EAX;
-  const Register kInstantiatorTypeArgumentsReg = EDX;
-  const Register kFunctionTypeArgumentsReg = ECX;
   const Register kTempReg = EDI;
   ASSERT(!type.IsInstantiated());
   ASSERT(!type.IsFunctionType());
@@ -450,8 +448,9 @@
             compiler::Address(ESP, 0 * kWordSize));  // Get function type args.
     // EDX: instantiator type arguments.
     // ECX: function type arguments.
-    const Register kTypeArgumentsReg =
-        type_param.IsClassTypeParameter() ? EDX : ECX;
+    const Register kTypeArgumentsReg = type_param.IsClassTypeParameter()
+                                           ? kInstantiatorTypeArgumentsReg
+                                           : kFunctionTypeArgumentsReg;
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ cmpl(kTypeArgumentsReg, raw_null);
     __ j(EQUAL, is_instance_lbl);
@@ -515,8 +514,6 @@
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
   const Register kInstanceReg = EAX;
-  const Register kInstantiatorTypeArgumentsReg = EDX;
-  const Register kFunctionTypeArgumentsReg = ECX;
   __ Comment("FunctionTypeTest");
 
   __ testl(kInstanceReg, compiler::Immediate(kSmiTagMask));
@@ -633,8 +630,8 @@
     __ PushObject(Object::null_object());  // Make room for the result.
     __ pushl(EAX);                         // Push the instance.
     __ PushObject(type);                   // Push the type.
-    __ pushl(EDX);                         // Instantiator type arguments.
-    __ pushl(ECX);                         // Function type arguments.
+    __ pushl(kInstantiatorTypeArgumentsReg);
+    __ pushl(kFunctionTypeArgumentsReg);
     __ LoadObject(EAX, test_cache);
     __ pushl(EAX);
     GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
@@ -678,8 +675,8 @@
   // Assignable check is skipped in FlowGraphBuilder, not here.
   ASSERT(!dst_type.IsTopTypeForAssignability());
 
-  __ pushl(EDX);  // Store instantiator type arguments.
-  __ pushl(ECX);  // Store function type arguments.
+  __ pushl(kInstantiatorTypeArgumentsReg);
+  __ pushl(kFunctionTypeArgumentsReg);
 
   compiler::Label is_assignable, runtime_call;
   if (Instance::NullIsAssignableTo(dst_type)) {
@@ -695,15 +692,16 @@
                                         &runtime_call);
 
   __ Bind(&runtime_call);
-  __ movl(EDX, compiler::Address(
-                   ESP, 1 * kWordSize));  // Get instantiator type args.
-  __ movl(ECX,
+  __ movl(
+      kInstantiatorTypeArgumentsReg,
+      compiler::Address(ESP, 1 * kWordSize));  // Get instantiator type args.
+  __ movl(kFunctionTypeArgumentsReg,
           compiler::Address(ESP, 0 * kWordSize));  // Get function type args.
   __ PushObject(Object::null_object());            // Make room for the result.
   __ pushl(EAX);                                   // Push the source object.
   __ PushObject(dst_type);  // Push the type of the destination.
-  __ pushl(EDX);            // Instantiator type arguments.
-  __ pushl(ECX);            // Function type arguments.
+  __ pushl(kInstantiatorTypeArgumentsReg);
+  __ pushl(kFunctionTypeArgumentsReg);
   __ PushObject(dst_name);  // Push the name of the destination.
   __ LoadObject(EAX, test_cache);
   __ pushl(EAX);
@@ -715,8 +713,8 @@
   __ popl(EAX);
 
   __ Bind(&is_assignable);
-  __ popl(ECX);  // Remove pushed function type arguments.
-  __ popl(EDX);  // Remove pushed instantiator type arguments.
+  __ popl(kFunctionTypeArgumentsReg);
+  __ popl(kInstantiatorTypeArgumentsReg);
 }
 
 void FlowGraphCompiler::EmitInstructionEpilogue(Instruction* instr) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index ab879bc..3f62944 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -243,12 +243,16 @@
     ASSERT(function_type_arguments_reg == kNoRegister);
     __ Call(StubCode::Subtype2TestCache());
   } else if (test_kind == kTestTypeFourArgs) {
-    ASSERT(RDX == instantiator_type_arguments_reg);
-    ASSERT(RCX == function_type_arguments_reg);
+    ASSERT(instantiator_type_arguments_reg ==
+           TypeTestABI::kInstantiatorTypeArgumentsReg);
+    ASSERT(function_type_arguments_reg ==
+           TypeTestABI::kFunctionTypeArgumentsReg);
     __ Call(StubCode::Subtype4TestCache());
   } else if (test_kind == kTestTypeSixArgs) {
-    ASSERT(RDX == instantiator_type_arguments_reg);
-    ASSERT(RCX == function_type_arguments_reg);
+    ASSERT(instantiator_type_arguments_reg ==
+           TypeTestABI::kInstantiatorTypeArgumentsReg);
+    ASSERT(function_type_arguments_reg ==
+           TypeTestABI::kFunctionTypeArgumentsReg);
     __ Call(StubCode::Subtype6TestCache());
   } else {
     UNREACHABLE();
@@ -274,10 +278,9 @@
   ASSERT(!type.IsFunctionType());
   const Class& type_class = Class::ZoneHandle(zone(), type.type_class());
   ASSERT(type_class.NumTypeArguments() > 0);
-  const Register kInstanceReg = RAX;
   const Type& smi_type = Type::Handle(zone(), Type::SmiType());
   const bool smi_is_ok = smi_type.IsSubtypeOf(type, Heap::kOld);
-  __ testq(kInstanceReg, compiler::Immediate(kSmiTagMask));
+  __ testq(TypeTestABI::kInstanceReg, compiler::Immediate(kSmiTagMask));
   if (smi_is_ok) {
     // Fast case for type = FutureOr<int/num/top-type>.
     __ j(ZERO, is_instance_lbl);
@@ -295,7 +298,7 @@
   if (is_raw_type) {
     const Register kClassIdReg = R10;
     // dynamic type argument, check only classes.
-    __ LoadClassId(kClassIdReg, kInstanceReg);
+    __ LoadClassId(kClassIdReg, TypeTestABI::kInstanceReg);
     __ cmpl(kClassIdReg, compiler::Immediate(type_class.id()));
     __ j(EQUAL, is_instance_lbl);
     // List is a very common case.
@@ -325,10 +328,10 @@
   const Register kInstantiatorTypeArgumentsReg = kNoRegister;
   const Register kFunctionTypeArgumentsReg = kNoRegister;
   const Register kTempReg = kNoRegister;
-  return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, kInstanceReg,
-                                     kInstantiatorTypeArgumentsReg,
-                                     kFunctionTypeArgumentsReg, kTempReg,
-                                     is_instance_lbl, is_not_instance_lbl);
+  return GenerateCallSubtypeTestStub(
+      kTestTypeTwoArgs, TypeTestABI::kInstanceReg,
+      kInstantiatorTypeArgumentsReg, kFunctionTypeArgumentsReg, kTempReg,
+      is_instance_lbl, is_not_instance_lbl);
 }
 
 void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
@@ -427,14 +430,13 @@
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
   __ Comment("Subtype1TestCacheLookup");
-  const Register kInstanceReg = RAX;
 #if defined(DEBUG)
   compiler::Label ok;
-  __ BranchIfNotSmi(kInstanceReg, &ok);
+  __ BranchIfNotSmi(TypeTestABI::kInstanceReg, &ok);
   __ Breakpoint();
   __ Bind(&ok);
 #endif
-  __ LoadClassId(TMP, kInstanceReg);
+  __ LoadClassId(TMP, TypeTestABI::kInstanceReg);
   __ LoadClassById(R10, TMP);
   // R10: instance class.
   // Check immediate superclass equality.
@@ -446,7 +448,7 @@
   const Register kInstantiatorTypeArgumentsReg = kNoRegister;
   const Register kFunctionTypeArgumentsReg = kNoRegister;
   const Register kTempReg = kNoRegister;
-  return GenerateCallSubtypeTestStub(kTestTypeOneArg, kInstanceReg,
+  return GenerateCallSubtypeTestStub(kTestTypeOneArg, TypeTestABI::kInstanceReg,
                                      kInstantiatorTypeArgumentsReg,
                                      kFunctionTypeArgumentsReg, kTempReg,
                                      is_instance_lbl, is_not_instance_lbl);
@@ -465,9 +467,6 @@
     const AbstractType& type,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
-  const Register kInstanceReg = RAX;
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
   const Register kTempReg = kNoRegister;
   __ Comment("UninstantiatedTypeTest");
   ASSERT(!type.IsInstantiated());
@@ -476,10 +475,10 @@
   if (type.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type);
 
-    // RDX: instantiator type arguments.
-    // RCX: function type arguments.
     const Register kTypeArgumentsReg =
-        type_param.IsClassTypeParameter() ? RDX : RCX;
+        type_param.IsClassTypeParameter()
+            ? TypeTestABI::kInstantiatorTypeArgumentsReg
+            : TypeTestABI::kFunctionTypeArgumentsReg;
     // Check if type arguments are null, i.e. equivalent to vector of dynamic.
     __ CompareObject(kTypeArgumentsReg, Object::null_object());
     __ j(EQUAL, is_instance_lbl);
@@ -510,24 +509,26 @@
     const auto test_kind = GetTypeTestStubKindForTypeParameter(type_param);
     const SubtypeTestCache& type_test_cache = SubtypeTestCache::ZoneHandle(
         zone(), GenerateCallSubtypeTestStub(
-                    test_kind, kInstanceReg, kInstantiatorTypeArgumentsReg,
-                    kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
-                    is_not_instance_lbl));
+                    test_kind, TypeTestABI::kInstanceReg,
+                    TypeTestABI::kInstantiatorTypeArgumentsReg,
+                    TypeTestABI::kFunctionTypeArgumentsReg, kTempReg,
+                    is_instance_lbl, is_not_instance_lbl));
     return type_test_cache.raw();
   }
   if (type.IsType()) {
     // Smi is FutureOr<T>, when T is a top type or int or num.
     if (!type.IsFutureOrType()) {
-      __ testq(kInstanceReg,
+      __ testq(TypeTestABI::kInstanceReg,
                compiler::Immediate(kSmiTagMask));  // Is instance Smi?
       __ j(ZERO, is_not_instance_lbl);
     }
     // Uninstantiated type class is known at compile time, but the type
     // arguments are determined at runtime by the instantiator(s).
-    return GenerateCallSubtypeTestStub(kTestTypeFourArgs, kInstanceReg,
-                                       kInstantiatorTypeArgumentsReg,
-                                       kFunctionTypeArgumentsReg, kTempReg,
-                                       is_instance_lbl, is_not_instance_lbl);
+    return GenerateCallSubtypeTestStub(
+        kTestTypeFourArgs, TypeTestABI::kInstanceReg,
+        TypeTestABI::kInstantiatorTypeArgumentsReg,
+        TypeTestABI::kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
+        is_not_instance_lbl);
   }
   return SubtypeTestCache::null();
 }
@@ -540,18 +541,16 @@
     const AbstractType& type,
     compiler::Label* is_instance_lbl,
     compiler::Label* is_not_instance_lbl) {
-  const Register kInstanceReg = RAX;
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
   const Register kTempReg = kNoRegister;
   __ Comment("FunctionTypeTest");
 
-  __ testq(kInstanceReg, compiler::Immediate(kSmiTagMask));
+  __ testq(TypeTestABI::kInstanceReg, compiler::Immediate(kSmiTagMask));
   __ j(ZERO, is_not_instance_lbl);
-  return GenerateCallSubtypeTestStub(kTestTypeSixArgs, kInstanceReg,
-                                     kInstantiatorTypeArgumentsReg,
-                                     kFunctionTypeArgumentsReg, kTempReg,
-                                     is_instance_lbl, is_not_instance_lbl);
+  return GenerateCallSubtypeTestStub(
+      kTestTypeSixArgs, TypeTestABI::kInstanceReg,
+      TypeTestABI::kInstantiatorTypeArgumentsReg,
+      TypeTestABI::kFunctionTypeArgumentsReg, kTempReg, is_instance_lbl,
+      is_not_instance_lbl);
 }
 
 // Inputs:
@@ -628,7 +627,7 @@
   if (!unwrapped_type.IsTypeParameter() || unwrapped_type.IsNullable()) {
     // Only nullable type parameter remains nullable after instantiation.
     // See NullIsInstanceOf().
-    __ CompareObject(RAX, Object::null_object());
+    __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
     __ j(EQUAL, (unwrapped_type.IsNullable() ||
                  (unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType()))
                     ? &is_instance
@@ -646,10 +645,10 @@
   if (!test_cache.IsNull()) {
     // Generate runtime call.
     __ PushObject(Object::null_object());  // Make room for the result.
-    __ pushq(RAX);                         // Push the instance.
+    __ pushq(TypeTestABI::kInstanceReg);   // Push the instance.
     __ PushObject(type);                   // Push the type.
-    __ pushq(RDX);                         // Instantiator type arguments.
-    __ pushq(RCX);                         // Function type arguments.
+    __ pushq(TypeTestABI::kInstantiatorTypeArgumentsReg);
+    __ pushq(TypeTestABI::kFunctionTypeArgumentsReg);
     __ LoadUniqueObject(RAX, test_cache);
     __ pushq(RAX);
     GenerateRuntimeCall(token_pos, deopt_id, kInstanceofRuntimeEntry, 5, locs);
@@ -691,9 +690,6 @@
   // Assignable check is skipped in FlowGraphBuilder, not here.
   ASSERT(!dst_type.IsTopTypeForAssignability());
 
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
-
   if (ShouldUseTypeTestingStubFor(is_optimizing(), dst_type)) {
     GenerateAssertAssignableViaTypeTestingStub(token_pos, deopt_id, dst_type,
                                                dst_name, locs);
@@ -701,7 +697,7 @@
     compiler::Label is_assignable, runtime_call;
 
     if (Instance::NullIsAssignableTo(dst_type)) {
-      __ CompareObject(RAX, Object::null_object());
+      __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
       __ j(EQUAL, &is_assignable);
     }
 
@@ -713,10 +709,10 @@
 
     __ Bind(&runtime_call);
     __ PushObject(Object::null_object());  // Make room for the result.
-    __ pushq(RAX);                         // Push the source object.
+    __ pushq(TypeTestABI::kInstanceReg);   // Push the source object.
     __ PushObject(dst_type);               // Push the type of the destination.
-    __ pushq(kInstantiatorTypeArgumentsReg);
-    __ pushq(kFunctionTypeArgumentsReg);
+    __ pushq(TypeTestABI::kInstantiatorTypeArgumentsReg);
+    __ pushq(TypeTestABI::kFunctionTypeArgumentsReg);
     __ PushObject(dst_name);  // Push the name of the destination.
     __ LoadUniqueObject(RAX, test_cache);
     __ pushq(RAX);
@@ -736,21 +732,14 @@
     const AbstractType& dst_type,
     const String& dst_name,
     LocationSummary* locs) {
-  const Register kInstanceReg = RAX;
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
-
   compiler::Label done;
 
-  const Register subtype_cache_reg = R9;
-  const Register kDstTypeReg = RBX;
-  const Register kRegToCall = dst_type.IsTypeParameter() ? RSI : kDstTypeReg;
+  const Register kRegToCall =
+      dst_type.IsTypeParameter() ? RSI : TypeTestABI::kDstTypeReg;
   const Register kScratchReg = kRegToCall;
 
-  GenerateAssertAssignableViaTypeTestingStub(
-      dst_type, dst_name, kInstanceReg, kInstantiatorTypeArgumentsReg,
-      kFunctionTypeArgumentsReg, subtype_cache_reg, kDstTypeReg, kRegToCall,
-      kScratchReg, &done);
+  GenerateAssertAssignableViaTypeTestingStub(dst_type, dst_name, kRegToCall,
+                                             kScratchReg, &done);
 
   // We use 2 consecutive entries in the pool for the subtype cache and the
   // destination name.  The second entry, namely [dst_name] seems to be unused,
@@ -767,7 +756,8 @@
   ASSERT((sub_type_cache_index + 1) == dst_name_index);
   ASSERT(__ constant_pool_allowed());
 
-  __ movq(subtype_cache_reg, compiler::Address(PP, sub_type_cache_offset));
+  __ movq(TypeTestABI::kSubtypeTestCacheReg,
+          compiler::Address(PP, sub_type_cache_offset));
   __ call(compiler::FieldAddress(
       kRegToCall, AbstractType::type_test_stub_entry_point_offset()));
   EmitCallsiteMetadata(token_pos, deopt_id, RawPcDescriptors::kOther, locs);
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index bf06f01..16e9531 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -5195,6 +5195,46 @@
   return true;
 }
 
+Definition* PhiInstr::GetReplacementForRedundantPhi() const {
+  ASSERT(InputCount() > 1);
+  Definition* first = InputAt(0)->definition();
+  Definition* first_origin = first->OriginalDefinition();
+  bool look_for_redefinition = false;
+  for (intptr_t i = 1; i < InputCount(); ++i) {
+    Definition* def = InputAt(i)->definition();
+    if (def != first) {
+      if (def->OriginalDefinition() != first_origin) return nullptr;
+      look_for_redefinition = true;
+    }
+  }
+  if (look_for_redefinition) {
+    // Find the most specific redefinition which is common for all inputs
+    // (the longest common chain).
+    Definition* redef = first;
+    for (intptr_t i = 1, n = InputCount(); redef != first_origin && i < n;) {
+      Value* value = InputAt(i);
+      bool found = false;
+      do {
+        Definition* def = value->definition();
+        if (def == redef) {
+          found = true;
+          break;
+        }
+        value = def->RedefinedValue();
+      } while (value != nullptr);
+      if (found) {
+        ++i;
+      } else {
+        ASSERT(redef != first_origin);
+        redef = redef->RedefinedValue()->definition();
+      }
+    }
+    return redef;
+  } else {
+    return first;
+  }
+}
+
 Instruction* CheckConditionInstr::Canonicalize(FlowGraph* graph) {
   if (StrictCompareInstr* strict_compare = comparison()->AsStrictCompare()) {
     if ((InputAt(0)->definition()->OriginalDefinition() ==
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 0e78547..9445c6a 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -2408,6 +2408,11 @@
   // A phi is redundant if all input operands are the same.
   bool IsRedundant() const;
 
+  // A phi is redundant if all input operands are redefinitions of the same
+  // value. Returns the replacement for this phi if it is redundant.
+  // The replacement is selected among values redefined by inputs.
+  Definition* GetReplacementForRedundantPhi() const;
+
   PRINT_TO_SUPPORT
 
   enum ReceiverType { kUnknownReceiver = -1, kNotReceiver = 0, kReceiver = 1 };
@@ -6176,6 +6181,20 @@
 
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
+  const Code& GetStub() const {
+    bool with_runtime_check;
+    if (type_arguments().CanShareInstantiatorTypeArguments(
+            instantiator_class(), &with_runtime_check)) {
+      ASSERT(with_runtime_check);
+      return StubCode::InstantiateTypeArgumentsMayShareInstantiatorTA();
+    } else if (type_arguments().CanShareFunctionTypeArguments(
+                   function(), &with_runtime_check)) {
+      ASSERT(with_runtime_check);
+      return StubCode::InstantiateTypeArgumentsMayShareFunctionTA();
+    }
+    return StubCode::InstantiateTypeArguments();
+  }
+
   PRINT_OPERANDS_TO_SUPPORT
 
  private:
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index e47f315..22e2e75 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -667,16 +667,13 @@
   // modified by the stub. To tell the register allocator about it, we reserve
   // all the other registers as temporary registers.
   // TODO(http://dartbug.com/32788): Simplify this.
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
-
   const bool using_stub =
       FlowGraphCompiler::ShouldUseTypeTestingStubFor(opt, dst_type());
 
   const intptr_t kNonChangeableInputRegs =
-      (1 << kInstanceReg) | (1 << kInstantiatorTypeArgumentsReg) |
-      (1 << kFunctionTypeArgumentsReg);
+      (1 << TypeTestABI::kInstanceReg) |
+      (1 << TypeTestABI::kInstantiatorTypeArgumentsReg) |
+      (1 << TypeTestABI::kFunctionTypeArgumentsReg);
 
   const intptr_t kNumInputs = 3;
 
@@ -700,16 +697,15 @@
   LocationSummary* summary = new (zone) LocationSummary(
       zone, kNumInputs, kNumTemps,
       using_stub ? LocationSummary::kCallCalleeSafe : LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(kInstanceReg));  // Value.
-  summary->set_in(1,
-                  Location::RegisterLocation(
-                      kInstantiatorTypeArgumentsReg));  // Instant. type args.
-  summary->set_in(2, Location::RegisterLocation(
-                         kFunctionTypeArgumentsReg));  // Function type args.
+  summary->set_in(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
+  summary->set_in(1, Location::RegisterLocation(
+                         TypeTestABI::kInstantiatorTypeArgumentsReg));
+  summary->set_in(
+      2, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
 
   // TODO(http://dartbug.com/32787): Use Location::SameAsFirstInput() instead,
   // once register allocator no longer hits assertion.
-  summary->set_out(0, Location::RegisterLocation(kInstanceReg));
+  summary->set_out(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
 
   if (using_stub) {
     // Let's reserve all registers except for the input ones.
@@ -740,8 +736,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(R2));  // Instant. type args.
-  summary->set_in(1, Location::RegisterLocation(R1));  // Function type args.
+  summary->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  summary->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   return summary;
 }
 
@@ -3005,17 +3001,19 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(R0));  // Instance.
-  summary->set_in(1, Location::RegisterLocation(R2));  // Instant. type args.
-  summary->set_in(2, Location::RegisterLocation(R1));  // Function type args.
+  summary->set_in(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
+  summary->set_in(1, Location::RegisterLocation(
+                         TypeTestABI::kInstantiatorTypeArgumentsReg));
+  summary->set_in(
+      2, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
   summary->set_out(0, Location::RegisterLocation(R0));
   return summary;
 }
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(locs()->in(0).reg() == R0);  // Value.
-  ASSERT(locs()->in(1).reg() == R2);  // Instantiator type arguments.
-  ASSERT(locs()->in(2).reg() == R1);  // Function type arguments.
+  ASSERT(locs()->in(0).reg() == TypeTestABI::kInstanceReg);
+  ASSERT(locs()->in(1).reg() == TypeTestABI::kInstantiatorTypeArgumentsReg);
+  ASSERT(locs()->in(2).reg() == TypeTestABI::kFunctionTypeArgumentsReg);
 
   compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
   ASSERT(locs()->out(0).reg() == R0);
@@ -3320,8 +3318,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(R1));  // Instant. type args.
-  locs->set_in(1, Location::RegisterLocation(R0));  // Function type args.
+  locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   locs->set_out(0, Location::RegisterLocation(R0));
   return locs;
 }
@@ -3336,6 +3334,8 @@
   // A runtime call to instantiate the type is required.
   __ PushObject(Object::null_object());  // Make room for the result.
   __ PushObject(type());
+  static_assert(kFunctionTypeArgumentsReg < kInstantiatorTypeArgumentsReg,
+                "Should be ordered to push arguments with one instruction");
   __ PushList((1 << instantiator_type_args_reg) |
               (1 << function_type_args_reg));
   compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
@@ -3351,9 +3351,9 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(R1));  // Instant. type args.
-  locs->set_in(1, Location::RegisterLocation(R0));  // Function type args.
-  locs->set_out(0, Location::RegisterLocation(R0));
+  locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
+  locs->set_out(0, Location::RegisterLocation(kResultTypeArgumentsReg));
   return locs;
 }
 
@@ -3362,74 +3362,27 @@
   const Register instantiator_type_args_reg = locs()->in(0).reg();
   const Register function_type_args_reg = locs()->in(1).reg();
   const Register result_reg = locs()->out(0).reg();
-  ASSERT(instantiator_type_args_reg == R1);
-  ASSERT(function_type_args_reg == R0);
 
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
-  ASSERT(!type_arguments().CanShareInstantiatorTypeArguments(
-             instantiator_class()) &&
-         !type_arguments().CanShareFunctionTypeArguments(
-             compiler->parsed_function().function()));
+
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
   compiler::Label type_arguments_instantiated;
   const intptr_t len = type_arguments().Length();
   if (type_arguments().IsRawWhenInstantiatedFromRaw(len)) {
-    __ LoadObject(IP, Object::null_object());
-    __ cmp(instantiator_type_args_reg, compiler::Operand(IP));
-    __ cmp(function_type_args_reg, compiler::Operand(IP), EQ);
+    ASSERT(result_reg != instantiator_type_args_reg &&
+           result_reg != function_type_args_reg);
+    __ LoadObject(result_reg, Object::null_object());
+    __ cmp(instantiator_type_args_reg, compiler::Operand(result_reg));
+    __ cmp(function_type_args_reg, compiler::Operand(result_reg), EQ);
     __ b(&type_arguments_instantiated, EQ);
-    ASSERT(function_type_args_reg == result_reg);
   }
-
-  // Lookup cache before calling runtime.
-  // TODO(regis): Consider moving this into a shared stub to reduce
-  // generated code size.
-  __ LoadObject(R3, type_arguments());
-  __ ldr(R3, compiler::FieldAddress(
-                 R3, compiler::target::TypeArguments::instantiations_offset()));
-  __ AddImmediate(R3, compiler::target::Array::data_offset() - kHeapObjectTag);
-  // The instantiations cache is initialized with Object::zero_array() and is
-  // therefore guaranteed to contain kNoInstantiator. No length check needed.
-  compiler::Label loop, next, found, slow_case;
-  __ Bind(&loop);
-  __ ldr(R2, compiler::Address(
-                 R3, TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
-                         compiler::target::kWordSize));
-  __ cmp(R2, compiler::Operand(instantiator_type_args_reg));
-  __ b(&next, NE);
-  __ ldr(IP, compiler::Address(
-                 R3, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
-                         compiler::target::kWordSize));
-  __ cmp(IP, compiler::Operand(function_type_args_reg));
-  __ b(&found, EQ);
-  __ Bind(&next);
-  __ AddImmediate(R3, TypeArguments::Instantiation::kSizeInWords *
-                          compiler::target::kWordSize);
-  __ CompareImmediate(R2, Smi::RawValue(TypeArguments::kNoInstantiator));
-  __ b(&loop, NE);
-  __ b(&slow_case);
-  __ Bind(&found);
-  __ ldr(result_reg,
-         compiler::Address(
-             R3, TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
-                     compiler::target::kWordSize));
-  __ b(&type_arguments_instantiated);
-
-  __ Bind(&slow_case);
-  // Instantiate non-null type arguments.
-  // A runtime call to instantiate the type arguments is required.
-  __ PushObject(Object::null_object());  // Make room for the result.
-  __ PushObject(type_arguments());
-  __ PushList((1 << instantiator_type_args_reg) |
-              (1 << function_type_args_reg));
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
-                                kInstantiateTypeArgumentsRuntimeEntry, 3,
-                                locs());
-  __ Drop(3);          // Drop 2 type vectors, and uninstantiated type.
-  __ Pop(result_reg);  // Pop instantiated type arguments.
+  // Lookup cache in stub before calling runtime.
+  __ LoadObject(kUninstantiatedTypeArgumentsReg, type_arguments());
+  compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
+                         locs());
   __ Bind(&type_arguments_instantiated);
 }
 
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 4486d3c..5987165 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -560,16 +560,13 @@
   // modified by the stub. To tell the register allocator about it, we reserve
   // all the other registers as temporary registers.
   // TODO(http://dartbug.com/32788): Simplify this.
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
-
   const bool using_stub =
       FlowGraphCompiler::ShouldUseTypeTestingStubFor(opt, dst_type());
 
   const intptr_t kNonChangeableInputRegs =
-      (1 << kInstanceReg) | (1 << kInstantiatorTypeArgumentsReg) |
-      (1 << kFunctionTypeArgumentsReg);
+      (1 << TypeTestABI::kInstanceReg) |
+      (1 << TypeTestABI::kInstantiatorTypeArgumentsReg) |
+      (1 << TypeTestABI::kFunctionTypeArgumentsReg);
 
   const intptr_t kNumInputs = 3;
 
@@ -591,16 +588,15 @@
   LocationSummary* summary = new (zone) LocationSummary(
       zone, kNumInputs, kNumTemps,
       using_stub ? LocationSummary::kCallCalleeSafe : LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(kInstanceReg));  // Value.
-  summary->set_in(1,
-                  Location::RegisterLocation(
-                      kInstantiatorTypeArgumentsReg));  // Instant. type args.
-  summary->set_in(2, Location::RegisterLocation(
-                         kFunctionTypeArgumentsReg));  // Function type args.
+  summary->set_in(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
+  summary->set_in(1, Location::RegisterLocation(
+                         TypeTestABI::kInstantiatorTypeArgumentsReg));
+  summary->set_in(
+      2, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
 
   // TODO(http://dartbug.com/32787): Use Location::SameAsFirstInput() instead,
   // once register allocator no longer hits assertion.
-  summary->set_out(0, Location::RegisterLocation(kInstanceReg));
+  summary->set_out(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
 
   if (using_stub) {
     // Let's reserve all registers except for the input ones.
@@ -631,8 +627,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(R1));  // Instant. type args.
-  summary->set_in(1, Location::RegisterLocation(R2));  // Function type args.
+  summary->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  summary->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   return summary;
 }
 
@@ -2519,17 +2515,19 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(R0));  // Instance.
-  summary->set_in(1, Location::RegisterLocation(R1));  // Instant. type args.
-  summary->set_in(2, Location::RegisterLocation(R2));  // Function type args.
+  summary->set_in(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
+  summary->set_in(1, Location::RegisterLocation(
+                         TypeTestABI::kInstantiatorTypeArgumentsReg));
+  summary->set_in(
+      2, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
   summary->set_out(0, Location::RegisterLocation(R0));
   return summary;
 }
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(locs()->in(0).reg() == R0);  // Value.
-  ASSERT(locs()->in(1).reg() == R1);  // Instantiator type arguments.
-  ASSERT(locs()->in(2).reg() == R2);  // Function type arguments.
+  ASSERT(locs()->in(0).reg() == TypeTestABI::kInstanceReg);
+  ASSERT(locs()->in(1).reg() == TypeTestABI::kInstantiatorTypeArgumentsReg);
+  ASSERT(locs()->in(2).reg() == TypeTestABI::kFunctionTypeArgumentsReg);
 
   compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
   ASSERT(locs()->out(0).reg() == R0);
@@ -2811,8 +2809,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(R0));  // Instant. type args.
-  locs->set_in(1, Location::RegisterLocation(R1));  // Function type args.
+  locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   locs->set_out(0, Location::RegisterLocation(R0));
   return locs;
 }
@@ -2832,7 +2830,6 @@
                                 kInstantiateTypeRuntimeEntry, 3, locs());
   __ Drop(3);          // Drop 2 type vectors, and uninstantiated type.
   __ Pop(result_reg);  // Pop instantiated type.
-  ASSERT(instantiator_type_args_reg == result_reg);
 }
 
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
@@ -2842,9 +2839,9 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(R0));  // Instant. type args.
-  locs->set_in(1, Location::RegisterLocation(R1));  // Function type args.
-  locs->set_out(0, Location::RegisterLocation(R0));
+  locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
+  locs->set_out(0, Location::RegisterLocation(kResultTypeArgumentsReg));
   return locs;
 }
 
@@ -2853,15 +2850,10 @@
   const Register instantiator_type_args_reg = locs()->in(0).reg();
   const Register function_type_args_reg = locs()->in(1).reg();
   const Register result_reg = locs()->out(0).reg();
-  ASSERT(instantiator_type_args_reg == R0);
-  ASSERT(instantiator_type_args_reg == result_reg);
 
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
-  ASSERT(!type_arguments().CanShareInstantiatorTypeArguments(
-             instantiator_class()) &&
-         !type_arguments().CanShareFunctionTypeArguments(
-             compiler->parsed_function().function()));
+
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
@@ -2869,55 +2861,19 @@
   const intptr_t len = type_arguments().Length();
   if (type_arguments().IsRawWhenInstantiatedFromRaw(len)) {
     compiler::Label non_null_type_args;
-    __ CompareObject(instantiator_type_args_reg, Object::null_object());
+    ASSERT(result_reg != instantiator_type_args_reg &&
+           result_reg != function_type_args_reg);
+    __ LoadObject(result_reg, Object::null_object());
+    __ CompareRegisters(instantiator_type_args_reg, result_reg);
     __ b(&non_null_type_args, NE);
-    __ CompareObject(function_type_args_reg, Object::null_object());
+    __ CompareRegisters(function_type_args_reg, result_reg);
     __ b(&type_arguments_instantiated, EQ);
     __ Bind(&non_null_type_args);
   }
-
-  // Lookup cache before calling runtime.
-  // TODO(regis): Consider moving this into a shared stub to reduce
-  // generated code size.
-  __ LoadObject(R3, type_arguments());
-  __ LoadFieldFromOffset(R3, R3, TypeArguments::instantiations_offset());
-  __ AddImmediate(R3, Array::data_offset() - kHeapObjectTag);
-  // The instantiations cache is initialized with Object::zero_array() and is
-  // therefore guaranteed to contain kNoInstantiator. No length check needed.
-  compiler::Label loop, next, found, slow_case;
-  __ Bind(&loop);
-  __ LoadFromOffset(
-      R2, R3,
-      TypeArguments::Instantiation::kInstantiatorTypeArgsIndex * kWordSize);
-  __ CompareRegisters(R2, instantiator_type_args_reg);
-  __ b(&next, NE);
-  __ LoadFromOffset(
-      TMP, R3,
-      TypeArguments::Instantiation::kFunctionTypeArgsIndex * kWordSize);
-  __ CompareRegisters(TMP, function_type_args_reg);
-  __ b(&found, EQ);
-  __ Bind(&next);
-  __ AddImmediate(R3, TypeArguments::Instantiation::kSizeInWords * kWordSize);
-  __ CompareImmediate(R2, Smi::RawValue(TypeArguments::kNoInstantiator));
-  __ b(&loop, NE);
-  __ b(&slow_case);
-  __ Bind(&found);
-  __ LoadFromOffset(
-      result_reg, R3,
-      TypeArguments::Instantiation::kInstantiatedTypeArgsIndex * kWordSize);
-  __ b(&type_arguments_instantiated);
-
-  __ Bind(&slow_case);
-  // Instantiate non-null type arguments.
-  // A runtime call to instantiate the type arguments is required.
-  __ LoadObject(TMP, type_arguments());
-  __ PushPair(TMP, NULL_REG);
-  __ PushPair(function_type_args_reg, instantiator_type_args_reg);
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
-                                kInstantiateTypeArgumentsRuntimeEntry, 3,
-                                locs());
-  __ Drop(3);          // Drop 2 type vectors, and uninstantiated type.
-  __ Pop(result_reg);  // Pop instantiated type arguments.
+  // Lookup cache in stub before calling runtime.
+  __ LoadObject(kUninstantiatedTypeArgumentsReg, type_arguments());
+  compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
+                         locs());
   __ Bind(&type_arguments_instantiated);
 }
 
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index d9c0348b..4d31a35 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -368,8 +368,8 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(EAX));  // Value.
-  summary->set_in(1, Location::RegisterLocation(EDX));  // Instant. type args.
-  summary->set_in(2, Location::RegisterLocation(ECX));  // Function type args.
+  summary->set_in(1, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  summary->set_in(2, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   summary->set_out(0, Location::RegisterLocation(EAX));
   return summary;
 }
@@ -380,8 +380,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(EDX));  // Instant. type args.
-  summary->set_in(1, Location::RegisterLocation(ECX));  // Function type args.
+  summary->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  summary->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   return summary;
 }
 
@@ -2230,16 +2230,16 @@
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
   summary->set_in(0, Location::RegisterLocation(EAX));  // Instance.
-  summary->set_in(1, Location::RegisterLocation(EDX));  // Instant. type args.
-  summary->set_in(2, Location::RegisterLocation(ECX));  // Function type args.
+  summary->set_in(1, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  summary->set_in(2, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   summary->set_out(0, Location::RegisterLocation(EAX));
   return summary;
 }
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   ASSERT(locs()->in(0).reg() == EAX);  // Value.
-  ASSERT(locs()->in(1).reg() == EDX);  // Instantiator type arguments.
-  ASSERT(locs()->in(2).reg() == ECX);  // Function type arguments.
+  ASSERT(locs()->in(1).reg() == kInstantiatorTypeArgumentsReg);
+  ASSERT(locs()->in(2).reg() == kFunctionTypeArgumentsReg);
 
   compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
   ASSERT(locs()->out(0).reg() == EAX);
@@ -2488,8 +2488,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(EAX));  // Instant. type args.
-  locs->set_in(1, Location::RegisterLocation(EDX));  // Function type args.
+  locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   locs->set_out(0, Location::RegisterLocation(EAX));
   return locs;
 }
@@ -2510,7 +2510,6 @@
                                 kInstantiateTypeRuntimeEntry, 3, locs());
   __ Drop(3);           // Drop 2 type vectors, and uninstantiated type.
   __ popl(result_reg);  // Pop instantiated type.
-  ASSERT(instantiator_type_args_reg == result_reg);
 }
 
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
@@ -2520,9 +2519,9 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(EAX));  // Instant. type args.
-  locs->set_in(1, Location::RegisterLocation(ECX));  // Function type args.
-  locs->set_out(0, Location::RegisterLocation(EAX));
+  locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
+  locs->set_out(0, Location::RegisterLocation(kResultTypeArgumentsReg));
   return locs;
 }
 
@@ -2531,15 +2530,10 @@
   Register instantiator_type_args_reg = locs()->in(0).reg();
   Register function_type_args_reg = locs()->in(1).reg();
   Register result_reg = locs()->out(0).reg();
-  ASSERT(instantiator_type_args_reg == EAX);
-  ASSERT(instantiator_type_args_reg == result_reg);
 
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
-  ASSERT(!type_arguments().CanShareInstantiatorTypeArguments(
-             instantiator_class()) &&
-         !type_arguments().CanShareFunctionTypeArguments(
-             compiler->parsed_function().function()));
+
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
@@ -2547,62 +2541,19 @@
   const intptr_t len = type_arguments().Length();
   if (type_arguments().IsRawWhenInstantiatedFromRaw(len)) {
     compiler::Label non_null_type_args;
-    const compiler::Immediate& raw_null =
-        compiler::Immediate(reinterpret_cast<intptr_t>(Object::null()));
-    __ cmpl(instantiator_type_args_reg, raw_null);
+    ASSERT(result_reg != instantiator_type_args_reg &&
+           result_reg != function_type_args_reg);
+    __ LoadObject(result_reg, Object::null_object());
+    __ cmpl(instantiator_type_args_reg, result_reg);
     __ j(NOT_EQUAL, &non_null_type_args, compiler::Assembler::kNearJump);
-    __ cmpl(function_type_args_reg, raw_null);
+    __ cmpl(function_type_args_reg, result_reg);
     __ j(EQUAL, &type_arguments_instantiated, compiler::Assembler::kNearJump);
     __ Bind(&non_null_type_args);
   }
-  // Lookup cache before calling runtime.
-  // TODO(regis): Consider moving this into a shared stub to reduce
-  // generated code size.
-  __ LoadObject(EDI, type_arguments());
-  __ movl(EDI,
-          compiler::FieldAddress(EDI, TypeArguments::instantiations_offset()));
-  __ leal(EDI, compiler::FieldAddress(EDI, Array::data_offset()));
-  // The instantiations cache is initialized with Object::zero_array() and is
-  // therefore guaranteed to contain kNoInstantiator. No length check needed.
-  compiler::Label loop, next, found, slow_case;
-  __ Bind(&loop);
-  __ movl(EDX,
-          compiler::Address(
-              EDI, TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
-                       kWordSize));
-  __ cmpl(EDX, instantiator_type_args_reg);
-  __ j(NOT_EQUAL, &next, compiler::Assembler::kNearJump);
-  __ movl(EBX, compiler::Address(
-                   EDI, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
-                            kWordSize));
-  __ cmpl(EBX, function_type_args_reg);
-  __ j(EQUAL, &found, compiler::Assembler::kNearJump);
-  __ Bind(&next);
-  __ addl(EDI, compiler::Immediate(TypeArguments::Instantiation::kSizeInWords *
-                                   kWordSize));
-  __ cmpl(EDX,
-          compiler::Immediate(Smi::RawValue(TypeArguments::kNoInstantiator)));
-  __ j(NOT_EQUAL, &loop, compiler::Assembler::kNearJump);
-  __ jmp(&slow_case, compiler::Assembler::kNearJump);
-  __ Bind(&found);
-  __ movl(result_reg,
-          compiler::Address(
-              EDI, TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
-                       kWordSize));
-  __ jmp(&type_arguments_instantiated, compiler::Assembler::kNearJump);
-
-  __ Bind(&slow_case);
-  // Instantiate non-null type arguments.
-  // A runtime call to instantiate the type arguments is required.
-  __ PushObject(Object::null_object());  // Make room for the result.
-  __ PushObject(type_arguments());
-  __ pushl(instantiator_type_args_reg);  // Push instantiator type arguments.
-  __ pushl(function_type_args_reg);      // Push function type arguments.
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
-                                kInstantiateTypeArgumentsRuntimeEntry, 3,
-                                locs());
-  __ Drop(3);           // Drop 2 type vectors, and uninstantiated args.
-  __ popl(result_reg);  // Pop instantiated type arguments.
+  // Lookup cache in stub before calling runtime.
+  __ LoadObject(kUninstantiatedTypeArgumentsReg, type_arguments());
+  compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
+                         locs());
   __ Bind(&type_arguments_instantiated);
 }
 
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index 6e7f51d..f689b65 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -52,7 +52,23 @@
   return cls.raw();
 }
 
-void Invoke(const Library& lib, const char* name) {
+RawTypeParameter* GetClassTypeParameter(const Class& klass, const char* name) {
+  const auto& param = TypeParameter::Handle(
+      klass.LookupTypeParameter(String::Handle(String::New(name))));
+  EXPECT(!param.IsNull());
+  return param.raw();
+}
+
+RawTypeParameter* GetFunctionTypeParameter(const Function& fun,
+                                           const char* name) {
+  intptr_t fun_level = 0;
+  const auto& param = TypeParameter::Handle(
+      fun.LookupTypeParameter(String::Handle(String::New(name)), &fun_level));
+  EXPECT(!param.IsNull());
+  return param.raw();
+}
+
+RawObject* Invoke(const Library& lib, const char* name) {
   // These tests rely on running unoptimized code to collect type feedback. The
   // interpreter does not collect type feedback for interface calls, so set
   // compilation threshold to 0 in order to compile invoked function
@@ -61,10 +77,14 @@
 
   Thread* thread = Thread::Current();
   Dart_Handle api_lib = Api::NewHandle(thread, lib.raw());
-  TransitionVMToNative transition(thread);
-  Dart_Handle result =
-      Dart_Invoke(api_lib, NewString(name), /*argc=*/0, /*argv=*/nullptr);
-  EXPECT_VALID(result);
+  Dart_Handle result;
+  {
+    TransitionVMToNative transition(thread);
+    result =
+        Dart_Invoke(api_lib, NewString(name), /*argc=*/0, /*argv=*/nullptr);
+    EXPECT_VALID(result);
+  }
+  return Api::UnwrapHandle(result);
 }
 
 FlowGraph* TestPipeline::RunPasses(
diff --git a/runtime/vm/compiler/backend/il_test_helper.h b/runtime/vm/compiler/backend/il_test_helper.h
index 95b6526..9555044 100644
--- a/runtime/vm/compiler/backend/il_test_helper.h
+++ b/runtime/vm/compiler/backend/il_test_helper.h
@@ -59,8 +59,11 @@
 
 RawFunction* GetFunction(const Library& lib, const char* name);
 RawClass* GetClass(const Library& lib, const char* name);
+RawTypeParameter* GetClassTypeParameter(const Class& klass, const char* name);
+RawTypeParameter* GetFunctionTypeParameter(const Function& fun,
+                                           const char* name);
 
-void Invoke(const Library& lib, const char* name);
+RawObject* Invoke(const Library& lib, const char* name);
 
 class TestPipeline : public ValueObject {
  public:
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index c031db4..d1eff91 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -516,16 +516,13 @@
   // modified by the stub. To tell the register allocator about it, we reserve
   // all the other registers as temporary registers.
   // TODO(http://dartbug.com/32788): Simplify this.
-  const Register kInstanceReg = RAX;
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
-
   const bool using_stub =
       FlowGraphCompiler::ShouldUseTypeTestingStubFor(opt, dst_type());
 
   const intptr_t kNonChangeableInputRegs =
-      (1 << kInstanceReg) | (1 << kInstantiatorTypeArgumentsReg) |
-      (1 << kFunctionTypeArgumentsReg);
+      (1 << TypeTestABI::kInstanceReg) |
+      (1 << TypeTestABI::kInstantiatorTypeArgumentsReg) |
+      (1 << TypeTestABI::kFunctionTypeArgumentsReg);
 
   const intptr_t kNumInputs = 3;
 
@@ -546,16 +543,15 @@
   LocationSummary* summary = new (zone) LocationSummary(
       zone, kNumInputs, kNumTemps,
       using_stub ? LocationSummary::kCallCalleeSafe : LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(kInstanceReg));  // Value.
-  summary->set_in(1,
-                  Location::RegisterLocation(
-                      kInstantiatorTypeArgumentsReg));  // Instant. type args.
-  summary->set_in(2, Location::RegisterLocation(
-                         kFunctionTypeArgumentsReg));  // Function type args.
+  summary->set_in(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
+  summary->set_in(1, Location::RegisterLocation(
+                         TypeTestABI::kInstantiatorTypeArgumentsReg));
+  summary->set_in(
+      2, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
 
   // TODO(http://dartbug.com/32787): Use Location::SameAsFirstInput() instead,
   // once register allocator no longer hits assertion.
-  summary->set_out(0, Location::RegisterLocation(kInstanceReg));
+  summary->set_out(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
 
   if (using_stub) {
     // Let's reserve all registers except for the input ones.
@@ -586,8 +582,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(RDX));  // Instant. type args
-  summary->set_in(1, Location::RegisterLocation(RCX));  // Function type args
+  summary->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  summary->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   return summary;
 }
 
@@ -2498,17 +2494,19 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* summary = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  summary->set_in(0, Location::RegisterLocation(RAX));  // Instance.
-  summary->set_in(1, Location::RegisterLocation(RDX));  // Instant. type args.
-  summary->set_in(2, Location::RegisterLocation(RCX));  // Function type args.
+  summary->set_in(0, Location::RegisterLocation(TypeTestABI::kInstanceReg));
+  summary->set_in(1, Location::RegisterLocation(
+                         TypeTestABI::kInstantiatorTypeArgumentsReg));
+  summary->set_in(
+      2, Location::RegisterLocation(TypeTestABI::kFunctionTypeArgumentsReg));
   summary->set_out(0, Location::RegisterLocation(RAX));
   return summary;
 }
 
 void InstanceOfInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  ASSERT(locs()->in(0).reg() == RAX);  // Value.
-  ASSERT(locs()->in(1).reg() == RDX);  // Instantiator type arguments.
-  ASSERT(locs()->in(2).reg() == RCX);  // Function type arguments.
+  ASSERT(locs()->in(0).reg() == TypeTestABI::kInstanceReg);
+  ASSERT(locs()->in(1).reg() == kInstantiatorTypeArgumentsReg);
+  ASSERT(locs()->in(2).reg() == kFunctionTypeArgumentsReg);
 
   compiler->GenerateInstanceOf(token_pos(), deopt_id(), type(), locs());
   ASSERT(locs()->out(0).reg() == RAX);
@@ -2803,8 +2801,8 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(RAX));  // Instant. type args.
-  locs->set_in(1, Location::RegisterLocation(RDX));  // Function type args.
+  locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
   locs->set_out(0, Location::RegisterLocation(RAX));
   return locs;
 }
@@ -2834,9 +2832,9 @@
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(RAX));  // Instant. type args.
-  locs->set_in(1, Location::RegisterLocation(RCX));  // Function type args.
-  locs->set_out(0, Location::RegisterLocation(RAX));
+  locs->set_in(0, Location::RegisterLocation(kInstantiatorTypeArgumentsReg));
+  locs->set_in(1, Location::RegisterLocation(kFunctionTypeArgumentsReg));
+  locs->set_out(0, Location::RegisterLocation(kResultTypeArgumentsReg));
   return locs;
 }
 
@@ -2845,15 +2843,10 @@
   Register instantiator_type_args_reg = locs()->in(0).reg();
   Register function_type_args_reg = locs()->in(1).reg();
   Register result_reg = locs()->out(0).reg();
-  ASSERT(instantiator_type_args_reg == RAX);
-  ASSERT(instantiator_type_args_reg == result_reg);
 
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
-  ASSERT(!type_arguments().CanShareInstantiatorTypeArguments(
-             instantiator_class()) &&
-         !type_arguments().CanShareFunctionTypeArguments(
-             compiler->parsed_function().function()));
+
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
@@ -2861,61 +2854,18 @@
   const intptr_t len = type_arguments().Length();
   if (type_arguments().IsRawWhenInstantiatedFromRaw(len)) {
     compiler::Label non_null_type_args;
-    __ CompareObject(instantiator_type_args_reg, Object::null_object());
+    ASSERT(result_reg != instantiator_type_args_reg &&
+           result_reg != function_type_args_reg);
+    __ LoadObject(result_reg, Object::null_object());
+    __ cmpq(instantiator_type_args_reg, result_reg);
     __ j(NOT_EQUAL, &non_null_type_args, compiler::Assembler::kNearJump);
-    __ CompareObject(function_type_args_reg, Object::null_object());
+    __ cmpq(function_type_args_reg, result_reg);
     __ j(EQUAL, &type_arguments_instantiated, compiler::Assembler::kNearJump);
     __ Bind(&non_null_type_args);
   }
-
-  // Lookup cache before calling runtime.
-  // TODO(regis): Consider moving this into a shared stub to reduce
-  // generated code size.
-  __ LoadObject(RDI, type_arguments());
-  __ movq(RDI,
-          compiler::FieldAddress(RDI, TypeArguments::instantiations_offset()));
-  __ leaq(RDI, compiler::FieldAddress(RDI, Array::data_offset()));
-  // The instantiations cache is initialized with Object::zero_array() and is
-  // therefore guaranteed to contain kNoInstantiator. No length check needed.
-  compiler::Label loop, next, found, slow_case;
-  __ Bind(&loop);
-  __ movq(RDX,
-          compiler::Address(
-              RDI, TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
-                       kWordSize));
-  __ cmpq(RDX, instantiator_type_args_reg);
-  __ j(NOT_EQUAL, &next, compiler::Assembler::kNearJump);
-  __ movq(R10, compiler::Address(
-                   RDI, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
-                            kWordSize));
-  __ cmpq(R10, function_type_args_reg);
-  __ j(EQUAL, &found, compiler::Assembler::kNearJump);
-  __ Bind(&next);
-  __ addq(RDI, compiler::Immediate(TypeArguments::Instantiation::kSizeInWords *
-                                   kWordSize));
-  __ cmpq(RDX,
-          compiler::Immediate(Smi::RawValue(TypeArguments::kNoInstantiator)));
-  __ j(NOT_EQUAL, &loop, compiler::Assembler::kNearJump);
-  __ jmp(&slow_case, compiler::Assembler::kNearJump);
-  __ Bind(&found);
-  __ movq(result_reg,
-          compiler::Address(
-              RDI, TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
-                       kWordSize));
-  __ jmp(&type_arguments_instantiated, compiler::Assembler::kNearJump);
-
-  __ Bind(&slow_case);
-  // Instantiate non-null type arguments.
-  // A runtime call to instantiate the type arguments is required.
-  __ PushObject(Object::null_object());  // Make room for the result.
-  __ PushObject(type_arguments());
-  __ pushq(instantiator_type_args_reg);  // Push instantiator type arguments.
-  __ pushq(function_type_args_reg);      // Push function type arguments.
-  compiler->GenerateRuntimeCall(token_pos(), deopt_id(),
-                                kInstantiateTypeArgumentsRuntimeEntry, 3,
-                                locs());
-  __ Drop(3);           // Drop 2 type vectors, and uninstantiated type.
-  __ popq(result_reg);  // Pop instantiated type arguments.
+  __ LoadObject(kUninstantiatedTypeArgumentsReg, type_arguments());
+  compiler->GenerateCall(token_pos(), GetStub(), RawPcDescriptors::kOther,
+                         locs());
   __ Bind(&type_arguments_instantiated);
 }
 
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index b8ca816..0ca9eb8 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -3661,8 +3661,8 @@
             if (FLAG_trace_optimization) {
               THR_Print("Removing dead phi v%" Pd "\n", phi->ssa_temp_index());
             }
-          } else if (phi->IsRedundant()) {
-            phi->ReplaceUsesWith(phi->InputAt(0)->definition());
+          } else if (auto* replacement = phi->GetReplacementForRedundantPhi()) {
+            phi->ReplaceUsesWith(replacement);
             phi->UnuseAllInputs();
             (*join->phis_)[i] = nullptr;
             if (FLAG_trace_optimization) {
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 11481a0..f519b11 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -116,7 +116,8 @@
     if (FLAG_precompiled_mode) {
       // In precompiler speculate that both sides of bitwise operation
       // are Smi-s.
-      if (Token::IsBinaryBitwiseOperator(op_kind)) {
+      if (Token::IsBinaryBitwiseOperator(op_kind) &&
+          !call->HasNonSmiAssignableInterface(zone())) {
         class_ids[0] = kSmiCid;
         class_ids[1] = kSmiCid;
       }
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 80cbb59..8d79cc1 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -340,6 +340,9 @@
   // so it should not be lifted earlier than that pass.
   INVOKE_PASS(DCE);
   INVOKE_PASS(Canonicalize);
+  // Repeat branches optimization after DCE, as it could make more
+  // empty blocks.
+  INVOKE_PASS(OptimizeBranches);
   INVOKE_PASS(AllocationSinking_Sink);
   INVOKE_PASS(EliminateDeadPhis);
   INVOKE_PASS(DCE);
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index bcdb962..1136484 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -221,7 +221,7 @@
       }
       const auto& obj = Object::Handle(Z, klass.EnsureIsFinalized(H.thread()));
       ASSERT(obj.IsNull());
-      ASSERT(klass.is_const());
+      ASSERT(klass.is_enum_class() || klass.is_const());
       instance = Instance::New(klass, Heap::kOld);
       // Build type from the raw bytes (needs temporary translator).
       TypeTranslator type_translator(&reader, this, active_class_, true,
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index e5f6221..2de2002 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -689,6 +689,8 @@
     kIsEnumClass = 1 << 3,
     kIsAnonymousMixin = 1 << 4,
     kIsEliminatedMixin = 1 << 5,
+    kFlagMixinDeclaration = 1 << 6,
+    kHasConstConstructor = 1 << 7,
   };
 
   explicit ClassHelper(KernelReaderHelper* helper)
@@ -711,6 +713,10 @@
     return (flags_ & Flag::kIsEliminatedMixin) != 0;
   }
 
+  bool has_const_constructor() const {
+    return (flags_ & Flag::kHasConstConstructor) != 0;
+  }
+
   NameIndex canonical_name_;
   TokenPosition start_position_;
   TokenPosition position_;
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 781c353..26b811c 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -280,9 +280,13 @@
 
 using ObjectAlignment = dart::ObjectAlignment<kWordSize, kWordSizeLog2>;
 
-const intptr_t kSmiBits = kBitsPerWord - 2;
-const intptr_t kSmiMax = (static_cast<intptr_t>(1) << kSmiBits) - 1;
-const intptr_t kSmiMin = -(static_cast<intptr_t>(1) << kSmiBits);
+constexpr word kWordMax = (static_cast<uword>(1) << (kBitsPerWord - 1)) - 1;
+constexpr word kWordMin = -(static_cast<uword>(1) << (kBitsPerWord - 1));
+constexpr uword kUwordMax = static_cast<word>(-1);
+
+constexpr int kSmiBits = kBitsPerWord - 2;
+constexpr word kSmiMax = (static_cast<uword>(1) << kSmiBits) - 1;
+constexpr word kSmiMin = -(static_cast<uword>(1) << kSmiBits);
 
 // Information about heap pages.
 extern const word kPageSize;
@@ -1228,6 +1232,7 @@
 class TypeArguments : public AllStatic {
  public:
   static word instantiations_offset();
+  static word nullability_offset();
   static word type_at_offset(intptr_t i);
   static word InstanceSize();
   static word NextFieldOffset();
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index c7b17d0..311c4d3 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -350,6 +350,8 @@
 static constexpr dart::compiler::target::word Type_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    16;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
@@ -366,7 +368,7 @@
 static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
 static constexpr dart::compiler::target::word Array_element_size = 4;
 static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 16;
+    TypeArguments_elements_start_offset = 20;
 static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
 static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
     0;
@@ -465,7 +467,7 @@
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 12;
 static constexpr dart::compiler::target::word Type_InstanceSize = 36;
-static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 16;
+static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 20;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
@@ -817,6 +819,8 @@
 static constexpr dart::compiler::target::word Type_nullability_offset = 61;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    32;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
@@ -833,7 +837,7 @@
 static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
 static constexpr dart::compiler::target::word Array_element_size = 8;
 static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 32;
+    TypeArguments_elements_start_offset = 40;
 static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
 static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
     0;
@@ -934,7 +938,7 @@
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 16;
 static constexpr dart::compiler::target::word Type_InstanceSize = 64;
-static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 32;
+static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 72;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
@@ -1281,6 +1285,8 @@
 static constexpr dart::compiler::target::word Type_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    16;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
@@ -1297,7 +1303,7 @@
 static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
 static constexpr dart::compiler::target::word Array_element_size = 4;
 static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 16;
+    TypeArguments_elements_start_offset = 20;
 static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
 static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
     0;
@@ -1393,7 +1399,7 @@
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 12;
 static constexpr dart::compiler::target::word Type_InstanceSize = 36;
-static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 16;
+static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 20;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
@@ -1745,6 +1751,8 @@
 static constexpr dart::compiler::target::word Type_nullability_offset = 61;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    32;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
@@ -1761,7 +1769,7 @@
 static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
 static constexpr dart::compiler::target::word Array_element_size = 8;
 static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 32;
+    TypeArguments_elements_start_offset = 40;
 static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
 static constexpr dart::compiler::target::word ClassTable_elements_start_offset =
     0;
@@ -1863,7 +1871,7 @@
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 16;
 static constexpr dart::compiler::target::word Type_InstanceSize = 64;
-static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 32;
+static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 72;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
@@ -2209,6 +2217,8 @@
 static constexpr dart::compiler::target::word Type_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    16;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
@@ -2225,7 +2235,7 @@
 static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
 static constexpr dart::compiler::target::word Array_element_size = 4;
 static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 16;
+    TypeArguments_elements_start_offset = 20;
 static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     4, 12, 8, 16};
@@ -2321,7 +2331,7 @@
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 12;
 static constexpr dart::compiler::target::word Type_InstanceSize = 36;
-static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 16;
+static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 20;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
@@ -2670,6 +2680,8 @@
 static constexpr dart::compiler::target::word Type_nullability_offset = 61;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    32;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
@@ -2686,7 +2698,7 @@
 static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
 static constexpr dart::compiler::target::word Array_element_size = 8;
 static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 32;
+    TypeArguments_elements_start_offset = 40;
 static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     8, 24, 16, 32};
@@ -2784,7 +2796,7 @@
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 16;
 static constexpr dart::compiler::target::word Type_InstanceSize = 64;
-static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 32;
+static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 72;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
@@ -3128,6 +3140,8 @@
 static constexpr dart::compiler::target::word Type_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    16;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
@@ -3144,7 +3158,7 @@
 static constexpr dart::compiler::target::word Array_elements_start_offset = 12;
 static constexpr dart::compiler::target::word Array_element_size = 4;
 static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 16;
+    TypeArguments_elements_start_offset = 20;
 static constexpr dart::compiler::target::word TypeArguments_element_size = 4;
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     4, 12, 8, 16};
@@ -3237,7 +3251,7 @@
     TransferableTypedData_InstanceSize = 4;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 12;
 static constexpr dart::compiler::target::word Type_InstanceSize = 36;
-static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 16;
+static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 20;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 16;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 12;
@@ -3586,6 +3600,8 @@
 static constexpr dart::compiler::target::word Type_nullability_offset = 61;
 static constexpr dart::compiler::target::word
     TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word TypeArguments_nullability_offset =
+    32;
 static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
 static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
@@ -3602,7 +3618,7 @@
 static constexpr dart::compiler::target::word Array_elements_start_offset = 24;
 static constexpr dart::compiler::target::word Array_element_size = 8;
 static constexpr dart::compiler::target::word
-    TypeArguments_elements_start_offset = 32;
+    TypeArguments_elements_start_offset = 40;
 static constexpr dart::compiler::target::word TypeArguments_element_size = 8;
 static constexpr dart::compiler::target::word Code_entry_point_offset[] = {
     8, 24, 16, 32};
@@ -3701,7 +3717,7 @@
     TransferableTypedData_InstanceSize = 8;
 static constexpr dart::compiler::target::word TwoByteString_InstanceSize = 16;
 static constexpr dart::compiler::target::word Type_InstanceSize = 64;
-static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 32;
+static constexpr dart::compiler::target::word TypeArguments_InstanceSize = 40;
 static constexpr dart::compiler::target::word TypeParameter_InstanceSize = 72;
 static constexpr dart::compiler::target::word TypeRef_InstanceSize = 32;
 static constexpr dart::compiler::target::word TypedData_InstanceSize = 24;
@@ -4074,6 +4090,8 @@
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 16;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     8;
@@ -4093,7 +4111,7 @@
     12;
 static constexpr dart::compiler::target::word AOT_Array_element_size = 4;
 static constexpr dart::compiler::target::word
-    AOT_TypeArguments_elements_start_offset = 16;
+    AOT_TypeArguments_elements_start_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
     4;
 static constexpr dart::compiler::target::word
@@ -4208,7 +4226,7 @@
     12;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 36;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
-    16;
+    20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 16;
@@ -4583,6 +4601,8 @@
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 61;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -4602,7 +4622,7 @@
     24;
 static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
 static constexpr dart::compiler::target::word
-    AOT_TypeArguments_elements_start_offset = 32;
+    AOT_TypeArguments_elements_start_offset = 40;
 static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
     8;
 static constexpr dart::compiler::target::word
@@ -4719,7 +4739,7 @@
     16;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
-    32;
+    40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
     72;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
@@ -5097,6 +5117,8 @@
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 61;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -5116,7 +5138,7 @@
     24;
 static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
 static constexpr dart::compiler::target::word
-    AOT_TypeArguments_elements_start_offset = 32;
+    AOT_TypeArguments_elements_start_offset = 40;
 static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
     8;
 static constexpr dart::compiler::target::word
@@ -5234,7 +5256,7 @@
     16;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
-    32;
+    40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
     72;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
@@ -5606,6 +5628,8 @@
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 33;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 4;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 16;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     8;
@@ -5625,7 +5649,7 @@
     12;
 static constexpr dart::compiler::target::word AOT_Array_element_size = 4;
 static constexpr dart::compiler::target::word
-    AOT_TypeArguments_elements_start_offset = 16;
+    AOT_TypeArguments_elements_start_offset = 20;
 static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
     4;
 static constexpr dart::compiler::target::word AOT_Code_entry_point_offset[] = {
@@ -5737,7 +5761,7 @@
     12;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 36;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
-    16;
+    20;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
     40;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 16;
@@ -6108,6 +6132,8 @@
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 61;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -6127,7 +6153,7 @@
     24;
 static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
 static constexpr dart::compiler::target::word
-    AOT_TypeArguments_elements_start_offset = 32;
+    AOT_TypeArguments_elements_start_offset = 40;
 static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
     8;
 static constexpr dart::compiler::target::word AOT_Code_entry_point_offset[] = {
@@ -6241,7 +6267,7 @@
     16;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
-    32;
+    40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
     72;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
@@ -6615,6 +6641,8 @@
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 61;
 static constexpr dart::compiler::target::word
     AOT_TypeArguments_instantiations_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_TypeArguments_nullability_offset = 32;
 static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
 static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
     16;
@@ -6634,7 +6662,7 @@
     24;
 static constexpr dart::compiler::target::word AOT_Array_element_size = 8;
 static constexpr dart::compiler::target::word
-    AOT_TypeArguments_elements_start_offset = 32;
+    AOT_TypeArguments_elements_start_offset = 40;
 static constexpr dart::compiler::target::word AOT_TypeArguments_element_size =
     8;
 static constexpr dart::compiler::target::word AOT_Code_entry_point_offset[] = {
@@ -6749,7 +6777,7 @@
     16;
 static constexpr dart::compiler::target::word AOT_Type_InstanceSize = 64;
 static constexpr dart::compiler::target::word AOT_TypeArguments_InstanceSize =
-    32;
+    40;
 static constexpr dart::compiler::target::word AOT_TypeParameter_InstanceSize =
     72;
 static constexpr dart::compiler::target::word AOT_TypeRef_InstanceSize = 32;
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index b582be9..3c16243 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -236,6 +236,7 @@
   FIELD(Type, type_state_offset)                                               \
   FIELD(Type, nullability_offset)                                              \
   FIELD(TypeArguments, instantiations_offset)                                  \
+  FIELD(TypeArguments, nullability_offset)                                     \
   FIELD(TypeRef, type_offset)                                                  \
   FIELD(TypedDataBase, length_offset)                                          \
   FIELD(TypedDataView, data_offset)                                            \
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 956ddd6..0f637de 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -2745,11 +2745,6 @@
 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
   ASSERT(n == 1 || n == 2 || n == 4 || n == 6);
 
-  const Register kCacheReg = R3;
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
-
   const Register kInstanceCidOrFunction = R8;
   const Register kInstanceInstantiatorTypeArgumentsReg = R4;
   const Register kInstanceDelayedFunctionTypeArgumentsReg = PP;
@@ -2776,15 +2771,17 @@
 
   // Loop initialization (moved up here to avoid having all dependent loads
   // after each other).
-  __ ldr(kCacheReg,
-         FieldAddress(kCacheReg, target::SubtypeTestCache::cache_offset()));
-  __ AddImmediate(kCacheReg, target::Array::data_offset() - kHeapObjectTag);
+  __ ldr(TypeTestABI::kSubtypeTestCacheReg,
+         FieldAddress(TypeTestABI::kSubtypeTestCacheReg,
+                      target::SubtypeTestCache::cache_offset()));
+  __ AddImmediate(TypeTestABI::kSubtypeTestCacheReg,
+                  target::Array::data_offset() - kHeapObjectTag);
 
   Label loop, not_closure;
   if (n >= 4) {
-    __ LoadClassIdMayBeSmi(kInstanceCidOrFunction, kInstanceReg);
+    __ LoadClassIdMayBeSmi(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
   } else {
-    __ LoadClassId(kInstanceCidOrFunction, kInstanceReg);
+    __ LoadClassId(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
   }
   __ CompareImmediate(kInstanceCidOrFunction, kClosureCid);
   __ b(&not_closure, NE);
@@ -2792,19 +2789,20 @@
   // Closure handling.
   {
     __ ldr(kInstanceCidOrFunction,
-           FieldAddress(kInstanceReg, target::Closure::function_offset()));
+           FieldAddress(TypeTestABI::kInstanceReg,
+                        target::Closure::function_offset()));
     if (n >= 2) {
       __ ldr(
           kInstanceInstantiatorTypeArgumentsReg,
-          FieldAddress(kInstanceReg,
+          FieldAddress(TypeTestABI::kInstanceReg,
                        target::Closure::instantiator_type_arguments_offset()));
       if (n >= 6) {
         ASSERT(n == 6);
         __ ldr(kInstanceParentFunctionTypeArgumentsReg,
-               FieldAddress(kInstanceReg,
+               FieldAddress(TypeTestABI::kInstanceReg,
                             target::Closure::function_type_arguments_offset()));
         __ ldr(kInstanceDelayedFunctionTypeArgumentsReg,
-               FieldAddress(kInstanceReg,
+               FieldAddress(TypeTestABI::kInstanceReg,
                             target::Closure::delayed_type_arguments_offset()));
       }
     }
@@ -2824,7 +2822,7 @@
                          host_type_arguments_field_offset_in_words_offset()));
       __ CompareImmediate(R9, target::Class::kNoTypeArguments);
       __ b(&has_no_type_arguments, EQ);
-      __ add(R9, kInstanceReg, Operand(R9, LSL, 2));
+      __ add(R9, TypeTestABI::kInstanceReg, Operand(R9, LSL, 2));
       __ ldr(kInstanceInstantiatorTypeArgumentsReg, FieldAddress(R9, 0));
       __ Bind(&has_no_type_arguments);
 
@@ -2840,7 +2838,7 @@
 
   // Loop header.
   __ Bind(&loop);
-  __ ldr(R9, Address(kCacheReg,
+  __ ldr(R9, Address(TypeTestABI::kSubtypeTestCacheReg,
                      target::kWordSize *
                          target::SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmp(R9, Operand(kNullReg));
@@ -2850,7 +2848,7 @@
     __ b(&found, EQ);
   } else {
     __ b(&next_iteration, NE);
-    __ ldr(R9, Address(kCacheReg,
+    __ ldr(R9, Address(TypeTestABI::kSubtypeTestCacheReg,
                        target::kWordSize *
                            target::SubtypeTestCache::kInstanceTypeArguments));
     __ cmp(R9, Operand(kInstanceInstantiatorTypeArgumentsReg));
@@ -2859,29 +2857,29 @@
     } else {
       __ b(&next_iteration, NE);
       __ ldr(R9,
-             Address(kCacheReg,
+             Address(TypeTestABI::kSubtypeTestCacheReg,
                      target::kWordSize *
                          target::SubtypeTestCache::kInstantiatorTypeArguments));
-      __ cmp(R9, Operand(kInstantiatorTypeArgumentsReg));
+      __ cmp(R9, Operand(TypeTestABI::kInstantiatorTypeArgumentsReg));
       __ b(&next_iteration, NE);
-      __ ldr(R9, Address(kCacheReg,
+      __ ldr(R9, Address(TypeTestABI::kSubtypeTestCacheReg,
                          target::kWordSize *
                              target::SubtypeTestCache::kFunctionTypeArguments));
-      __ cmp(R9, Operand(kFunctionTypeArgumentsReg));
+      __ cmp(R9, Operand(TypeTestABI::kFunctionTypeArgumentsReg));
       if (n == 4) {
         __ b(&found, EQ);
       } else {
         ASSERT(n == 6);
         __ b(&next_iteration, NE);
 
-        __ ldr(R9, Address(kCacheReg,
+        __ ldr(R9, Address(TypeTestABI::kSubtypeTestCacheReg,
                            target::kWordSize *
                                target::SubtypeTestCache::
                                    kInstanceParentFunctionTypeArguments));
         __ cmp(R9, Operand(kInstanceParentFunctionTypeArgumentsReg));
         __ b(&next_iteration, NE);
 
-        __ ldr(R9, Address(kCacheReg,
+        __ ldr(R9, Address(TypeTestABI::kSubtypeTestCacheReg,
                            target::kWordSize *
                                target::SubtypeTestCache::
                                    kInstanceDelayedFunctionTypeArguments));
@@ -2891,13 +2889,15 @@
     }
   }
   __ Bind(&next_iteration);
-  __ AddImmediate(kCacheReg, target::kWordSize *
-                                 target::SubtypeTestCache::kTestEntryLength);
+  __ AddImmediate(
+      TypeTestABI::kSubtypeTestCacheReg,
+      target::kWordSize * target::SubtypeTestCache::kTestEntryLength);
   __ b(&loop);
 
   __ Bind(&found);
-  __ ldr(R1, Address(kCacheReg, target::kWordSize *
-                                    target::SubtypeTestCache::kTestResult));
+  __ ldr(R1,
+         Address(TypeTestABI::kSubtypeTestCacheReg,
+                 target::kWordSize * target::SubtypeTestCache::kTestResult));
   if (n >= 6) {
     __ PopList(1 << kInstanceParentFunctionTypeArgumentsReg |
                1 << kInstanceDelayedFunctionTypeArgumentsReg);
@@ -2982,28 +2982,22 @@
 
 static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
                                             TypeCheckMode mode) {
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
-  const Register kDstTypeReg = R8;
-  const Register kSubtypeTestCacheReg = R3;
-
   __ PushObject(NullObject());  // Make room for result.
-  __ Push(kInstanceReg);
-  __ Push(kDstTypeReg);
-  __ Push(kInstantiatorTypeArgumentsReg);
-  __ Push(kFunctionTypeArgumentsReg);
+  __ Push(TypeTestABI::kInstanceReg);
+  __ Push(TypeTestABI::kDstTypeReg);
+  __ Push(TypeTestABI::kInstantiatorTypeArgumentsReg);
+  __ Push(TypeTestABI::kFunctionTypeArgumentsReg);
   __ PushObject(NullObject());
-  __ Push(kSubtypeTestCacheReg);
+  __ Push(TypeTestABI::kSubtypeTestCacheReg);
   __ PushImmediate(target::ToRawSmi(mode));
   __ CallRuntime(kTypeCheckRuntimeEntry, 7);
   __ Drop(1);  // mode
-  __ Pop(kSubtypeTestCacheReg);
+  __ Pop(TypeTestABI::kSubtypeTestCacheReg);
   __ Drop(1);  // dst_name
-  __ Pop(kFunctionTypeArgumentsReg);
-  __ Pop(kInstantiatorTypeArgumentsReg);
-  __ Pop(kDstTypeReg);
-  __ Pop(kInstanceReg);
+  __ Pop(TypeTestABI::kFunctionTypeArgumentsReg);
+  __ Pop(TypeTestABI::kInstantiatorTypeArgumentsReg);
+  __ Pop(TypeTestABI::kDstTypeReg);
+  __ Pop(TypeTestABI::kInstanceReg);
   __ Drop(1);  // Discard return value.
 }
 
@@ -3040,7 +3034,6 @@
   Label done, call_runtime;
 
   const Register kInstanceReg = R0;
-  const Register kFunctionTypeArgumentsReg = R1;
   const Register kDstTypeReg = R8;
   const Register kSubtypeTestCacheReg = R3;
 
@@ -3563,6 +3556,107 @@
   __ bkpt(0);
 }
 
+// Instantiate type arguments from instantiator and function type args.
+// R3 uninstantiated type arguments.
+// R2 instantiator type arguments.
+// R1: function type arguments.
+// Returns instantiated type arguments in R0.
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
+    Assembler* assembler) {
+  // Lookup cache before calling runtime.
+  __ ldr(R0, compiler::FieldAddress(
+                 kUninstantiatedTypeArgumentsReg,
+                 target::TypeArguments::instantiations_offset()));
+  __ AddImmediate(R0, compiler::target::Array::data_offset() - kHeapObjectTag);
+  // The instantiations cache is initialized with Object::zero_array() and is
+  // therefore guaranteed to contain kNoInstantiator. No length check needed.
+  compiler::Label loop, next, found;
+  __ Bind(&loop);
+  __ ldr(R4, compiler::Address(
+                 R0, TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
+                         target::kWordSize));
+  __ cmp(R4, compiler::Operand(kInstantiatorTypeArgumentsReg));
+  __ b(&next, NE);
+  // Using IP as destination register and reading it immediately is safe.
+  __ ldr(IP, compiler::Address(
+                 R0, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
+                         target::kWordSize));
+  __ cmp(IP, compiler::Operand(kFunctionTypeArgumentsReg));
+  __ b(&found, EQ);
+  __ Bind(&next);
+  __ AddImmediate(
+      R0, TypeArguments::Instantiation::kSizeInWords * target::kWordSize);
+  __ CompareImmediate(R4, Smi::RawValue(TypeArguments::kNoInstantiator));
+  __ b(&loop, NE);
+
+  // Instantiate non-null type arguments.
+  // A runtime call to instantiate the type arguments is required.
+  __ EnterStubFrame();
+  __ PushObject(Object::null_object());  // Make room for the result.
+  static_assert(
+      (kUninstantiatedTypeArgumentsReg > kInstantiatorTypeArgumentsReg) &&
+          (kInstantiatorTypeArgumentsReg > kFunctionTypeArgumentsReg),
+      "Should be ordered to push arguments with one instruction");
+  __ PushList((1 << kUninstantiatedTypeArgumentsReg) |
+              (1 << kInstantiatorTypeArgumentsReg) |
+              (1 << kFunctionTypeArgumentsReg));
+  __ CallRuntime(kInstantiateTypeArgumentsRuntimeEntry, 3);
+  __ Drop(3);  // Drop 2 type vectors, and uninstantiated type.
+  __ Pop(kResultTypeArgumentsReg);  // Pop instantiated type arguments.
+  __ LeaveStubFrame();
+  __ Ret();
+
+  __ Bind(&found);
+  __ ldr(kResultTypeArgumentsReg,
+         compiler::Address(
+             R0, TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
+                     target::kWordSize));
+  __ Ret();
+}
+
+void StubCodeCompiler::
+    GenerateInstantiateTypeArgumentsMayShareInstantiatorTAStub(
+        Assembler* assembler) {
+  // Return the instantiator type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ ldr(R0,
+         compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
+                                target::TypeArguments::nullability_offset()));
+  __ ldr(R4,
+         compiler::FieldAddress(kInstantiatorTypeArgumentsReg,
+                                target::TypeArguments::nullability_offset()));
+  __ and_(R4, R4, Operand(R0));
+  __ cmp(R4, Operand(R0));
+  __ b(&cache_lookup, NE);
+  __ mov(kResultTypeArgumentsReg, Operand(kInstantiatorTypeArgumentsReg));
+  __ Ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsMayShareFunctionTAStub(
+    Assembler* assembler) {
+  // Return the function type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ ldr(R0,
+         compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
+                                target::TypeArguments::nullability_offset()));
+  __ ldr(R4,
+         compiler::FieldAddress(kFunctionTypeArgumentsReg,
+                                target::TypeArguments::nullability_offset()));
+  __ and_(R4, R4, Operand(R0));
+  __ cmp(R4, Operand(R0));
+  __ b(&cache_lookup, NE);
+  __ mov(kResultTypeArgumentsReg, Operand(kFunctionTypeArgumentsReg));
+  __ Ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index de4c47a..2a12a90 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -2876,8 +2876,8 @@
 // Used to check class and type arguments. Arguments passed in registers:
 // LR: return address.
 // R0: instance (must be preserved).
-// R1: instantiator type arguments (only if n == 4, can be raw_null).
-// R2: function type arguments (only if n == 4, can be raw_null).
+// R2: instantiator type arguments (only if n == 4, can be raw_null).
+// R1: function type arguments (only if n == 4, can be raw_null).
 // R3: target::SubtypeTestCache.
 //
 // Preserves R0/R2/R8.
@@ -2886,11 +2886,6 @@
 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
   ASSERT(n == 1 || n == 2 || n == 4 || n == 6);
 
-  const Register kCacheReg = R3;
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
-
   const Register kInstanceCidOrFunction = R6;
   const Register kInstanceInstantiatorTypeArgumentsReg = R4;
   const Register kInstanceParentFunctionTypeArgumentsReg = R9;
@@ -2902,15 +2897,18 @@
 
   // Loop initialization (moved up here to avoid having all dependent loads
   // after each other).
-  __ ldr(kCacheReg,
-         FieldAddress(kCacheReg, target::SubtypeTestCache::cache_offset()));
-  __ AddImmediate(kCacheReg, target::Array::data_offset() - kHeapObjectTag);
+  __ ldr(TypeTestABI::kSubtypeTestCacheReg,
+         FieldAddress(TypeTestABI::kSubtypeTestCacheReg,
+                      target::SubtypeTestCache::cache_offset()));
+  __ AddImmediate(TypeTestABI::kSubtypeTestCacheReg,
+                  target::Array::data_offset() - kHeapObjectTag);
 
   Label loop, not_closure;
   if (n >= 4) {
-    __ LoadClassIdMayBeSmi(kInstanceCidOrFunction, kInstanceReg);
+    __ LoadClassIdMayBeSmi(kInstanceCidOrFunction,
+                           TypeTestABI::TypeTestABI::kInstanceReg);
   } else {
-    __ LoadClassId(kInstanceCidOrFunction, kInstanceReg);
+    __ LoadClassId(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
   }
   __ CompareImmediate(kInstanceCidOrFunction, kClosureCid);
   __ b(&not_closure, NE);
@@ -2918,19 +2916,20 @@
   // Closure handling.
   {
     __ ldr(kInstanceCidOrFunction,
-           FieldAddress(kInstanceReg, target::Closure::function_offset()));
+           FieldAddress(TypeTestABI::kInstanceReg,
+                        target::Closure::function_offset()));
     if (n >= 2) {
       __ ldr(
           kInstanceInstantiatorTypeArgumentsReg,
-          FieldAddress(kInstanceReg,
+          FieldAddress(TypeTestABI::kInstanceReg,
                        target::Closure::instantiator_type_arguments_offset()));
       if (n >= 6) {
         ASSERT(n == 6);
         __ ldr(kInstanceParentFunctionTypeArgumentsReg,
-               FieldAddress(kInstanceReg,
+               FieldAddress(TypeTestABI::kInstanceReg,
                             target::Closure::function_type_arguments_offset()));
         __ ldr(kInstanceDelayedFunctionTypeArgumentsReg,
-               FieldAddress(kInstanceReg,
+               FieldAddress(TypeTestABI::kInstanceReg,
                             target::Closure::delayed_type_arguments_offset()));
       }
     }
@@ -2950,7 +2949,7 @@
           kWord);
       __ CompareImmediate(R5, target::Class::kNoTypeArguments);
       __ b(&has_no_type_arguments, EQ);
-      __ add(R5, kInstanceReg, Operand(R5, LSL, 3));
+      __ add(R5, TypeTestABI::kInstanceReg, Operand(R5, LSL, 3));
       __ ldr(kInstanceInstantiatorTypeArgumentsReg, FieldAddress(R5, 0));
       __ Bind(&has_no_type_arguments);
 
@@ -2966,7 +2965,7 @@
 
   // Loop header
   __ Bind(&loop);
-  __ ldr(R5, Address(kCacheReg,
+  __ ldr(R5, Address(TypeTestABI::kSubtypeTestCacheReg,
                      target::kWordSize *
                          target::SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmp(R5, Operand(kNullReg));
@@ -2976,7 +2975,7 @@
     __ b(&found, EQ);
   } else {
     __ b(&next_iteration, NE);
-    __ ldr(R5, Address(kCacheReg,
+    __ ldr(R5, Address(TypeTestABI::kSubtypeTestCacheReg,
                        target::kWordSize *
                            target::SubtypeTestCache::kInstanceTypeArguments));
     __ cmp(R5, Operand(kInstanceInstantiatorTypeArgumentsReg));
@@ -2985,29 +2984,29 @@
     } else {
       __ b(&next_iteration, NE);
       __ ldr(R5,
-             Address(kCacheReg,
+             Address(TypeTestABI::kSubtypeTestCacheReg,
                      target::kWordSize *
                          target::SubtypeTestCache::kInstantiatorTypeArguments));
-      __ cmp(R5, Operand(kInstantiatorTypeArgumentsReg));
+      __ cmp(R5, Operand(TypeTestABI::kInstantiatorTypeArgumentsReg));
       __ b(&next_iteration, NE);
-      __ ldr(R5, Address(kCacheReg,
+      __ ldr(R5, Address(TypeTestABI::kSubtypeTestCacheReg,
                          target::kWordSize *
                              target::SubtypeTestCache::kFunctionTypeArguments));
-      __ cmp(R5, Operand(kFunctionTypeArgumentsReg));
+      __ cmp(R5, Operand(TypeTestABI::kFunctionTypeArgumentsReg));
       if (n == 4) {
         __ b(&found, EQ);
       } else {
         ASSERT(n == 6);
         __ b(&next_iteration, NE);
 
-        __ ldr(R5, Address(kCacheReg,
+        __ ldr(R5, Address(TypeTestABI::kSubtypeTestCacheReg,
                            target::kWordSize *
                                target::SubtypeTestCache::
                                    kInstanceParentFunctionTypeArguments));
         __ cmp(R5, Operand(kInstanceParentFunctionTypeArgumentsReg));
         __ b(&next_iteration, NE);
 
-        __ ldr(R5, Address(kCacheReg,
+        __ ldr(R5, Address(TypeTestABI::kSubtypeTestCacheReg,
                            target::kWordSize *
                                target::SubtypeTestCache::
                                    kInstanceDelayedFunctionTypeArguments));
@@ -3017,13 +3016,15 @@
     }
   }
   __ Bind(&next_iteration);
-  __ AddImmediate(kCacheReg, target::kWordSize *
-                                 target::SubtypeTestCache::kTestEntryLength);
+  __ AddImmediate(
+      TypeTestABI::kSubtypeTestCacheReg,
+      target::kWordSize * target::SubtypeTestCache::kTestEntryLength);
   __ b(&loop);
 
   __ Bind(&found);
-  __ ldr(R1, Address(kCacheReg, target::kWordSize *
-                                    target::SubtypeTestCache::kTestResult));
+  __ ldr(R1,
+         Address(TypeTestABI::kSubtypeTestCacheReg,
+                 target::kWordSize * target::SubtypeTestCache::kTestResult));
   __ ret();
 
   __ Bind(&not_found);
@@ -3105,29 +3106,22 @@
 
 static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
                                             TypeCheckMode mode) {
-  const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
-
-  const Register kSubtypeTestCacheReg = R3;
-  const Register kDstTypeReg = R8;
-
   __ PushObject(NullObject());  // Make room for result.
-  __ Push(kInstanceReg);
-  __ Push(kDstTypeReg);
-  __ Push(kInstantiatorTypeArgumentsReg);
-  __ Push(kFunctionTypeArgumentsReg);
+  __ Push(TypeTestABI::kInstanceReg);
+  __ Push(TypeTestABI::kDstTypeReg);
+  __ Push(TypeTestABI::kInstantiatorTypeArgumentsReg);
+  __ Push(TypeTestABI::kFunctionTypeArgumentsReg);
   __ PushObject(NullObject());
-  __ Push(kSubtypeTestCacheReg);
+  __ Push(TypeTestABI::kSubtypeTestCacheReg);
   __ PushImmediate(target::ToRawSmi(mode));
   __ CallRuntime(kTypeCheckRuntimeEntry, 7);
   __ Drop(1);  // mode
-  __ Pop(kSubtypeTestCacheReg);
+  __ Pop(TypeTestABI::kSubtypeTestCacheReg);
   __ Drop(1);  // dst_name
-  __ Pop(kFunctionTypeArgumentsReg);
-  __ Pop(kInstantiatorTypeArgumentsReg);
-  __ Pop(kDstTypeReg);
-  __ Pop(kInstanceReg);
+  __ Pop(TypeTestABI::kFunctionTypeArgumentsReg);
+  __ Pop(TypeTestABI::kInstantiatorTypeArgumentsReg);
+  __ Pop(TypeTestABI::kDstTypeReg);
+  __ Pop(TypeTestABI::kInstanceReg);
   __ Drop(1);  // Discard return value.
 }
 
@@ -3164,7 +3158,6 @@
   Label done, call_runtime;
 
   const Register kInstanceReg = R0;
-  const Register kInstantiatorTypeArgumentsReg = R1;
   const Register kSubtypeTestCacheReg = R3;
   const Register kDstTypeReg = R8;
 
@@ -3201,20 +3194,20 @@
 
   __ Bind(&is_simple_case);
   {
-    __ PushPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
+    __ PushPair(kFunctionTypeArgumentsReg, kSubtypeTestCacheReg);
     __ BranchLink(StubCodeSubtype2TestCache());
     __ CompareObject(R1, CastHandle<Object>(TrueObject()));
-    __ PopPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
+    __ PopPair(kFunctionTypeArgumentsReg, kSubtypeTestCacheReg);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     __ Jump(&call_runtime);
   }
 
   __ Bind(&is_complex_case);
   {
-    __ PushPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
+    __ PushPair(kFunctionTypeArgumentsReg, kSubtypeTestCacheReg);
     __ BranchLink(StubCodeSubtype6TestCache());
     __ CompareObject(R1, CastHandle<Object>(TrueObject()));
-    __ PopPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
+    __ PopPair(kFunctionTypeArgumentsReg, kSubtypeTestCacheReg);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     // Fall through to runtime_call
   }
@@ -3684,6 +3677,94 @@
   __ brk(0);
 }
 
+// Instantiate type arguments from instantiator and function type args.
+// R3 uninstantiated type arguments.
+// R2 instantiator type arguments.
+// R1: function type arguments.
+// Returns instantiated type arguments in R0.
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
+    Assembler* assembler) {
+  // Lookup cache before calling runtime.
+  __ LoadFieldFromOffset(R0, kUninstantiatedTypeArgumentsReg,
+                         target::TypeArguments::instantiations_offset());
+  __ AddImmediate(R0, Array::data_offset() - kHeapObjectTag);
+  // The instantiations cache is initialized with Object::zero_array() and is
+  // therefore guaranteed to contain kNoInstantiator. No length check needed.
+  compiler::Label loop, next, found;
+  __ Bind(&loop);
+  __ LoadFromOffset(R5, R0,
+                    TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
+                        target::kWordSize);
+  __ CompareRegisters(R5, kInstantiatorTypeArgumentsReg);
+  __ b(&next, NE);
+  __ LoadFromOffset(
+      R4, R0,
+      TypeArguments::Instantiation::kFunctionTypeArgsIndex * target::kWordSize);
+  __ CompareRegisters(R4, kFunctionTypeArgumentsReg);
+  __ b(&found, EQ);
+  __ Bind(&next);
+  __ AddImmediate(
+      R0, TypeArguments::Instantiation::kSizeInWords * target::kWordSize);
+  __ CompareImmediate(R5, Smi::RawValue(TypeArguments::kNoInstantiator));
+  __ b(&loop, NE);
+
+  // Instantiate non-null type arguments.
+  // A runtime call to instantiate the type arguments is required.
+  __ EnterStubFrame();
+  __ PushPair(kUninstantiatedTypeArgumentsReg, NULL_REG);
+  __ PushPair(kFunctionTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
+  __ CallRuntime(kInstantiateTypeArgumentsRuntimeEntry, 3);
+  __ Drop(3);  // Drop 2 type vectors, and uninstantiated type.
+  __ Pop(kResultTypeArgumentsReg);  // Pop instantiated type arguments.
+  __ LeaveStubFrame();
+  __ Ret();
+
+  __ Bind(&found);
+  __ LoadFromOffset(kResultTypeArgumentsReg, R0,
+                    TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
+                        target::kWordSize);
+  __ Ret();
+}
+
+void StubCodeCompiler::
+    GenerateInstantiateTypeArgumentsMayShareInstantiatorTAStub(
+        Assembler* assembler) {
+  // Return the instantiator type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ LoadFieldFromOffset(R0, kUninstantiatedTypeArgumentsReg,
+                         target::TypeArguments::nullability_offset());
+  __ LoadFieldFromOffset(R4, kInstantiatorTypeArgumentsReg,
+                         target::TypeArguments::nullability_offset());
+  __ and_(R4, R4, Operand(R0));
+  __ cmp(R4, Operand(R0));
+  __ b(&cache_lookup, NE);
+  __ mov(kResultTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
+  __ Ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsMayShareFunctionTAStub(
+    Assembler* assembler) {
+  // Return the function type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ LoadFieldFromOffset(R0, kUninstantiatedTypeArgumentsReg,
+                         target::TypeArguments::nullability_offset());
+  __ LoadFieldFromOffset(R4, kFunctionTypeArgumentsReg,
+                         target::TypeArguments::nullability_offset());
+  __ and_(R4, R4, Operand(R0));
+  __ cmp(R4, Operand(R0));
+  __ b(&cache_lookup, NE);
+  __ mov(kResultTypeArgumentsReg, kFunctionTypeArgumentsReg);
+  __ Ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index fbf88cc..c132c5e 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -2907,6 +2907,107 @@
   __ int3();  // Marker stub.
 }
 
+// Instantiate type arguments from instantiator and function type args.
+// EBX: uninstantiated type arguments.
+// EDX: instantiator type arguments.
+// ECX: function type arguments.
+// Returns instantiated type arguments in EAX.
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
+    Assembler* assembler) {
+  // Lookup cache before calling runtime.
+  __ pushl(kUninstantiatedTypeArgumentsReg);  // Preserve reg.
+  __ movl(EAX, compiler::FieldAddress(
+                   kUninstantiatedTypeArgumentsReg,
+                   target::TypeArguments::instantiations_offset()));
+  __ leal(EAX, compiler::FieldAddress(EAX, Array::data_offset()));
+  // The instantiations cache is initialized with Object::zero_array() and is
+  // therefore guaranteed to contain kNoInstantiator. No length check needed.
+  compiler::Label loop, next, found;
+  __ Bind(&loop);
+  __ movl(EDI,
+          compiler::Address(
+              EAX, TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
+                       target::kWordSize));
+  __ cmpl(EDI, kInstantiatorTypeArgumentsReg);
+  __ j(NOT_EQUAL, &next, compiler::Assembler::kNearJump);
+  __ movl(EBX, compiler::Address(
+                   EAX, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
+                            target::kWordSize));
+  __ cmpl(EBX, kFunctionTypeArgumentsReg);
+  __ j(EQUAL, &found, compiler::Assembler::kNearJump);
+  __ Bind(&next);
+  __ addl(EAX, compiler::Immediate(TypeArguments::Instantiation::kSizeInWords *
+                                   target::kWordSize));
+  __ cmpl(EDI,
+          compiler::Immediate(Smi::RawValue(TypeArguments::kNoInstantiator)));
+  __ j(NOT_EQUAL, &loop, compiler::Assembler::kNearJump);
+
+  // Instantiate non-null type arguments.
+  // A runtime call to instantiate the type arguments is required.
+  __ popl(kUninstantiatedTypeArgumentsReg);  // Restore reg.
+  __ EnterStubFrame();
+  __ PushObject(Object::null_object());  // Make room for the result.
+  __ pushl(kUninstantiatedTypeArgumentsReg);
+  __ pushl(kInstantiatorTypeArgumentsReg);  // Push instantiator type arguments.
+  __ pushl(kFunctionTypeArgumentsReg);      // Push function type arguments.
+  __ CallRuntime(kInstantiateTypeArgumentsRuntimeEntry, 3);
+  __ Drop(3);  // Drop 2 type vectors, and uninstantiated args.
+  __ popl(kResultTypeArgumentsReg);  // Pop instantiated type arguments.
+  __ LeaveFrame();
+  __ ret();
+
+  __ Bind(&found);
+  __ popl(kUninstantiatedTypeArgumentsReg);  // Drop reg.
+  __ movl(kResultTypeArgumentsReg,
+          compiler::Address(
+              EAX, TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
+                       target::kWordSize));
+  __ ret();
+}
+
+void StubCodeCompiler::
+    GenerateInstantiateTypeArgumentsMayShareInstantiatorTAStub(
+        Assembler* assembler) {
+  // Return the instantiator type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ movl(EAX,
+          compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
+                                 target::TypeArguments::nullability_offset()));
+  __ movl(EDI,
+          compiler::FieldAddress(kInstantiatorTypeArgumentsReg,
+                                 target::TypeArguments::nullability_offset()));
+  __ andl(EDI, EAX);
+  __ cmpl(EDI, EAX);
+  __ j(NOT_EQUAL, &cache_lookup, compiler::Assembler::kNearJump);
+  __ movl(kResultTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
+  __ ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsMayShareFunctionTAStub(
+    Assembler* assembler) {
+  // Return the function type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ movl(EAX,
+          compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
+                                 target::TypeArguments::nullability_offset()));
+  __ movl(EDI,
+          compiler::FieldAddress(kFunctionTypeArgumentsReg,
+                                 target::TypeArguments::nullability_offset()));
+  __ andl(EDI, EAX);
+  __ cmpl(EDI, EAX);
+  __ j(NOT_EQUAL, &cache_lookup, compiler::Assembler::kNearJump);
+  __ movl(kResultTypeArgumentsReg, kFunctionTypeArgumentsReg);
+  __ ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 64f9f0d..9e91624 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -2830,11 +2830,6 @@
 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
   ASSERT(n == 1 || n == 2 || n == 4 || n == 6);
 
-  const Register kCacheReg = R9;
-  const Register kInstanceReg = RAX;
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
-
   const Register kInstanceCidOrFunction = R10;
   const Register kInstanceInstantiatorTypeArgumentsReg = R13;
   const Register kInstanceParentFunctionTypeArgumentsReg = PP;
@@ -2852,15 +2847,15 @@
 
   // Loop initialization (moved up here to avoid having all dependent loads
   // after each other).
-  __ movq(RSI,
-          FieldAddress(kCacheReg, target::SubtypeTestCache::cache_offset()));
+  __ movq(RSI, FieldAddress(TypeTestABI::kSubtypeTestCacheReg,
+                            target::SubtypeTestCache::cache_offset()));
   __ addq(RSI, Immediate(target::Array::data_offset() - kHeapObjectTag));
 
   Label loop, not_closure;
   if (n >= 4) {
-    __ LoadClassIdMayBeSmi(kInstanceCidOrFunction, kInstanceReg);
+    __ LoadClassIdMayBeSmi(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
   } else {
-    __ LoadClassId(kInstanceCidOrFunction, kInstanceReg);
+    __ LoadClassId(kInstanceCidOrFunction, TypeTestABI::kInstanceReg);
   }
   __ cmpq(kInstanceCidOrFunction, Immediate(kClosureCid));
   __ j(NOT_EQUAL, &not_closure, Assembler::kNearJump);
@@ -2868,20 +2863,21 @@
   // Closure handling.
   {
     __ movq(kInstanceCidOrFunction,
-            FieldAddress(kInstanceReg, target::Closure::function_offset()));
+            FieldAddress(TypeTestABI::kInstanceReg,
+                         target::Closure::function_offset()));
     if (n >= 2) {
       __ movq(
           kInstanceInstantiatorTypeArgumentsReg,
-          FieldAddress(kInstanceReg,
+          FieldAddress(TypeTestABI::kInstanceReg,
                        target::Closure::instantiator_type_arguments_offset()));
       if (n >= 6) {
         ASSERT(n == 6);
         __ movq(
             kInstanceParentFunctionTypeArgumentsReg,
-            FieldAddress(kInstanceReg,
+            FieldAddress(TypeTestABI::kInstanceReg,
                          target::Closure::function_type_arguments_offset()));
         __ movq(kInstanceDelayedFunctionTypeArgumentsReg,
-                FieldAddress(kInstanceReg,
+                FieldAddress(TypeTestABI::kInstanceReg,
                              target::Closure::delayed_type_arguments_offset()));
       }
     }
@@ -2902,7 +2898,7 @@
       __ cmpl(RDI, Immediate(target::Class::kNoTypeArguments));
       __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
       __ movq(kInstanceInstantiatorTypeArgumentsReg,
-              FieldAddress(kInstanceReg, RDI, TIMES_8, 0));
+              FieldAddress(TypeTestABI::kInstanceReg, RDI, TIMES_8, 0));
       __ Bind(&has_no_type_arguments);
 
       if (n >= 6) {
@@ -2936,13 +2932,13 @@
     } else {
       __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
       __ cmpq(
-          kInstantiatorTypeArgumentsReg,
+          TypeTestABI::kInstantiatorTypeArgumentsReg,
           Address(RSI,
                   target::kWordSize *
                       target::SubtypeTestCache::kInstantiatorTypeArguments));
       __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
       __ cmpq(
-          kFunctionTypeArgumentsReg,
+          TypeTestABI::kFunctionTypeArgumentsReg,
           Address(RSI, target::kWordSize *
                            target::SubtypeTestCache::kFunctionTypeArguments));
 
@@ -3057,28 +3053,22 @@
 
 static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
                                             TypeCheckMode mode) {
-  const Register kInstanceReg = RAX;
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
-  const Register kDstTypeReg = RBX;
-  const Register kSubtypeTestCacheReg = R9;
-
   __ PushObject(NullObject());  // Make room for result.
-  __ pushq(kInstanceReg);
-  __ pushq(kDstTypeReg);
-  __ pushq(kInstantiatorTypeArgumentsReg);
-  __ pushq(kFunctionTypeArgumentsReg);
+  __ pushq(TypeTestABI::kInstanceReg);
+  __ pushq(TypeTestABI::kDstTypeReg);
+  __ pushq(TypeTestABI::kInstantiatorTypeArgumentsReg);
+  __ pushq(TypeTestABI::kFunctionTypeArgumentsReg);
   __ PushObject(NullObject());
-  __ pushq(kSubtypeTestCacheReg);
+  __ pushq(TypeTestABI::kSubtypeTestCacheReg);
   __ PushImmediate(Immediate(target::ToRawSmi(mode)));
   __ CallRuntime(kTypeCheckRuntimeEntry, 7);
   __ Drop(1);  // mode
-  __ popq(kSubtypeTestCacheReg);
+  __ popq(TypeTestABI::kSubtypeTestCacheReg);
   __ Drop(1);
-  __ popq(kFunctionTypeArgumentsReg);
-  __ popq(kInstantiatorTypeArgumentsReg);
-  __ popq(kDstTypeReg);
-  __ popq(kInstanceReg);
+  __ popq(TypeTestABI::kFunctionTypeArgumentsReg);
+  __ popq(TypeTestABI::kInstantiatorTypeArgumentsReg);
+  __ popq(TypeTestABI::kDstTypeReg);
+  __ popq(TypeTestABI::kInstanceReg);
   __ Drop(1);  // Discard return value.
 }
 
@@ -3623,6 +3613,104 @@
   __ int3();
 }
 
+// Instantiate type arguments from instantiator and function type args.
+// RBX: uninstantiated type arguments.
+// RDX: instantiator type arguments.
+// RCX: function type arguments.
+// Returns instantiated type arguments in RAX.
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsStub(
+    Assembler* assembler) {
+  // Lookup cache before calling runtime.
+  __ movq(RAX, compiler::FieldAddress(
+                   kUninstantiatedTypeArgumentsReg,
+                   target::TypeArguments::instantiations_offset()));
+  __ leaq(RAX, compiler::FieldAddress(RAX, Array::data_offset()));
+  // The instantiations cache is initialized with Object::zero_array() and is
+  // therefore guaranteed to contain kNoInstantiator. No length check needed.
+  compiler::Label loop, next, found;
+  __ Bind(&loop);
+  __ movq(RDI,
+          compiler::Address(
+              RAX, TypeArguments::Instantiation::kInstantiatorTypeArgsIndex *
+                       target::kWordSize));
+  __ cmpq(RDI, kInstantiatorTypeArgumentsReg);
+  __ j(NOT_EQUAL, &next, compiler::Assembler::kNearJump);
+  __ movq(R10, compiler::Address(
+                   RAX, TypeArguments::Instantiation::kFunctionTypeArgsIndex *
+                            target::kWordSize));
+  __ cmpq(R10, kFunctionTypeArgumentsReg);
+  __ j(EQUAL, &found, compiler::Assembler::kNearJump);
+  __ Bind(&next);
+  __ addq(RAX, compiler::Immediate(TypeArguments::Instantiation::kSizeInWords *
+                                   target::kWordSize));
+  __ cmpq(RDI,
+          compiler::Immediate(Smi::RawValue(TypeArguments::kNoInstantiator)));
+  __ j(NOT_EQUAL, &loop, compiler::Assembler::kNearJump);
+
+  // Instantiate non-null type arguments.
+  // A runtime call to instantiate the type arguments is required.
+  __ EnterStubFrame();
+  __ PushObject(Object::null_object());  // Make room for the result.
+  __ pushq(kUninstantiatedTypeArgumentsReg);
+  __ pushq(kInstantiatorTypeArgumentsReg);  // Push instantiator type arguments.
+  __ pushq(kFunctionTypeArgumentsReg);      // Push function type arguments.
+  __ CallRuntime(kInstantiateTypeArgumentsRuntimeEntry, 3);
+  __ Drop(3);  // Drop 2 type vectors, and uninstantiated type.
+  __ popq(kResultTypeArgumentsReg);  // Pop instantiated type arguments.
+  __ LeaveStubFrame();
+  __ ret();
+
+  __ Bind(&found);
+  __ movq(kResultTypeArgumentsReg,
+          compiler::Address(
+              RAX, TypeArguments::Instantiation::kInstantiatedTypeArgsIndex *
+                       target::kWordSize));
+  __ ret();
+}
+
+void StubCodeCompiler::
+    GenerateInstantiateTypeArgumentsMayShareInstantiatorTAStub(
+        Assembler* assembler) {
+  // Return the instantiator type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ movq(RAX,
+          compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
+                                 target::TypeArguments::nullability_offset()));
+  __ movq(RDI,
+          compiler::FieldAddress(kInstantiatorTypeArgumentsReg,
+                                 target::TypeArguments::nullability_offset()));
+  __ andq(RDI, RAX);
+  __ cmpq(RDI, RAX);
+  __ j(NOT_EQUAL, &cache_lookup, compiler::Assembler::kNearJump);
+  __ movq(kResultTypeArgumentsReg, kInstantiatorTypeArgumentsReg);
+  __ ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
+void StubCodeCompiler::GenerateInstantiateTypeArgumentsMayShareFunctionTAStub(
+    Assembler* assembler) {
+  // Return the function type arguments if its nullability is compatible for
+  // sharing, otherwise proceed to instantiation cache lookup.
+  compiler::Label cache_lookup;
+  __ movq(RAX,
+          compiler::FieldAddress(kUninstantiatedTypeArgumentsReg,
+                                 target::TypeArguments::nullability_offset()));
+  __ movq(RDI,
+          compiler::FieldAddress(kFunctionTypeArgumentsReg,
+                                 target::TypeArguments::nullability_offset()));
+  __ andq(RDI, RAX);
+  __ cmpq(RDI, RAX);
+  __ j(NOT_EQUAL, &cache_lookup, compiler::Assembler::kNearJump);
+  __ movq(kResultTypeArgumentsReg, kFunctionTypeArgumentsReg);
+  __ ret();
+
+  __ Bind(&cache_lookup);
+  GenerateInstantiateTypeArgumentsStub(assembler);
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 8517f88..7967439 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -310,6 +310,38 @@
 // ABI for allocation stubs.
 const Register kAllocationStubTypeArgumentsReg = R3;
 
+// ABI for instantiation stubs.
+const Register kUninstantiatedTypeArgumentsReg = R3;
+const Register kInstantiatorTypeArgumentsReg = R2;
+const Register kFunctionTypeArgumentsReg = R1;
+const Register kResultTypeArgumentsReg = R0;
+
+// Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
+struct TypeTestABI {
+  static const Register kInstanceReg = R0;
+  static const Register kDstTypeReg = R8;
+  static const Register kInstantiatorTypeArgumentsReg = R2;
+  static const Register kFunctionTypeArgumentsReg = R1;
+  static const Register kSubtypeTestCacheReg = R3;
+
+  static const intptr_t kAbiRegisters =
+      (1 << kInstanceReg) | (1 << kDstTypeReg) |
+      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
+      (1 << kSubtypeTestCacheReg);
+};
+
+// Registers used inside the implementation of type testing stubs.
+struct TTSInternalRegs {
+  static const Register kInstanceTypeArgumentsReg = R4;
+  static const Register kScratchReg = R9;
+
+  static const intptr_t kInternalRegisters =
+      (1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg);
+};
+
+// TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
+// of reusing the constants of the instantiation stubs ABI.
+
 // List of registers used in load/store multiple.
 typedef uint16_t RegList;
 const RegList kAllCpuRegistersList = 0xFFFF;
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 3529416..743d7ee 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -142,6 +142,38 @@
 // ABI for allocation stubs.
 const Register kAllocationStubTypeArgumentsReg = R1;
 
+// ABI for instantiation stubs.
+const Register kUninstantiatedTypeArgumentsReg = R3;
+const Register kInstantiatorTypeArgumentsReg = R2;
+const Register kFunctionTypeArgumentsReg = R1;
+const Register kResultTypeArgumentsReg = R0;
+
+// Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
+struct TypeTestABI {
+  static const Register kInstanceReg = R0;
+  static const Register kDstTypeReg = R8;
+  static const Register kInstantiatorTypeArgumentsReg = R2;
+  static const Register kFunctionTypeArgumentsReg = R1;
+  static const Register kSubtypeTestCacheReg = R3;
+
+  static const intptr_t kAbiRegisters =
+      (1 << kInstanceReg) | (1 << kDstTypeReg) |
+      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
+      (1 << kSubtypeTestCacheReg);
+};
+
+// Registers used inside the implementation of type testing stubs.
+struct TTSInternalRegs {
+  static const Register kInstanceTypeArgumentsReg = R7;
+  static const Register kScratchReg = R9;
+
+  static const intptr_t kInternalRegisters =
+      (1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg);
+};
+
+// TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
+// of reusing the constants of the instantiation stubs ABI.
+
 // Masks, sizes, etc.
 const int kXRegSizeInBits = 64;
 const int kWRegSizeInBits = 32;
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index cd4e59e..29dc2b5 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -91,6 +91,15 @@
 // ABI for allocation stubs.
 const Register kAllocationStubTypeArgumentsReg = EDX;
 
+// ABI for instantiation stubs.
+const Register kUninstantiatedTypeArgumentsReg = EBX;
+const Register kInstantiatorTypeArgumentsReg = EDX;
+const Register kFunctionTypeArgumentsReg = ECX;
+const Register kResultTypeArgumentsReg = EAX;
+
+// TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
+// of reusing the constants of the instantiation stubs ABI.
+
 typedef uint32_t RegList;
 const RegList kAllCpuRegistersList = 0xFF;
 
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 992075f..fe9d561 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -132,6 +132,38 @@
 // ABI for allocation stubs.
 const Register kAllocationStubTypeArgumentsReg = RDX;
 
+// ABI for instantiation stubs.
+const Register kUninstantiatedTypeArgumentsReg = RBX;
+const Register kInstantiatorTypeArgumentsReg = RDX;
+const Register kFunctionTypeArgumentsReg = RCX;
+const Register kResultTypeArgumentsReg = RAX;
+
+// Calling convention when calling TypeTestingStub and SubtypeTestCacheStub.
+struct TypeTestABI {
+  static const Register kInstanceReg = RAX;
+  static const Register kDstTypeReg = RBX;
+  static const Register kInstantiatorTypeArgumentsReg = RDX;
+  static const Register kFunctionTypeArgumentsReg = RCX;
+  static const Register kSubtypeTestCacheReg = R9;
+
+  static const intptr_t kAbiRegisters =
+      (1 << kInstanceReg) | (1 << kDstTypeReg) |
+      (1 << kInstantiatorTypeArgumentsReg) | (1 << kFunctionTypeArgumentsReg) |
+      (1 << kSubtypeTestCacheReg);
+};
+
+// Registers used inside the implementation of type testing stubs.
+struct TTSInternalRegs {
+  static const Register kInstanceTypeArgumentsReg = RSI;
+  static const Register kScratchReg = R8;
+
+  static const intptr_t kInternalRegisters =
+      (1 << kInstanceTypeArgumentsReg) | (1 << kScratchReg);
+};
+
+// TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
+// of reusing the constants of the instantiation stubs ABI.
+
 typedef uint32_t RegList;
 const RegList kAllCpuRegistersList = 0xFFFF;
 const RegList kAllFpuRegistersList = 0xFFFF;
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 4f2c567..bbf0ea3 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -436,7 +436,7 @@
   ASSERT(!Isolate::creation_enabled_);
   MonitorLocker ml(Isolate::isolate_creation_monitor_);
   intptr_t num_attempts = 0;
-  while (Isolate::application_isolates_count_ > 1) {
+  while (Isolate::application_isolates_count_ > 0) {
     Monitor::WaitResult retval = ml.Wait(1000);
     if (retval == Monitor::kTimedOut) {
       num_attempts += 1;
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 5d24012..42d53be 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -96,7 +96,6 @@
   LongJumpScope* saved_long_jump_base_;
 };
 
-NO_SANITIZE_SAFE_STACK
 RawObject* DartEntry::InvokeFunction(const Function& function,
                                      const Array& arguments,
                                      const Array& arguments_descriptor,
@@ -165,11 +164,20 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
   // Now Call the invoke stub which will invoke the dart function.
-  invokestub entrypoint =
-      reinterpret_cast<invokestub>(StubCode::InvokeDartCode().EntryPoint());
   const Code& code = Code::Handle(zone, function.CurrentCode());
+  return InvokeCode(code, arguments_descriptor, arguments, thread);
+}
+
+NO_SANITIZE_SAFE_STACK
+RawObject* DartEntry::InvokeCode(const Code& code,
+                                 const Array& arguments_descriptor,
+                                 const Array& arguments,
+                                 Thread* thread) {
   ASSERT(!code.IsNull());
   ASSERT(thread->no_callback_scope_depth() == 0);
+
+  invokestub entrypoint =
+      reinterpret_cast<invokestub>(StubCode::InvokeDartCode().EntryPoint());
   SuspendLongJumpScope suspend_long_jump_scope(thread);
   TransitionToGenerated transition(thread);
 #if defined(USING_SIMULATOR)
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 11411de..e93c991 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -201,6 +201,13 @@
   static RawObject* InvokeFunction(const Function& function,
                                    const Array& arguments);
 
+  // Invokes the specified code as if it was a Dart function.
+  // On success, returns a RawInstance.  On failure, a RawError.
+  static RawObject* InvokeCode(const Code& code,
+                               const Array& arguments_descriptor,
+                               const Array& arguments,
+                               Thread* thread);
+
   // Invokes the specified instance, static, or closure function.
   // On success, returns a RawInstance.  On failure, a RawError.
   static RawObject* InvokeFunction(
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 3057977..93124b1 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -358,6 +358,9 @@
 // Materializes all deferred objects.  Returns the total number of
 // artificial arguments used during deoptimization.
 intptr_t DeoptContext::MaterializeDeferredObjects() {
+  // This region is initialized by a mixture of C++ and generated code.
+  MSAN_UNPOISON(dest_frame_, dest_frame_size_ * kWordSize);
+
   // Populate slots with references to all unboxed "primitive" values (doubles,
   // mints, simd) and deferred objects. Deferred objects are only allocated
   // but not filled with data. This is done later because deferred objects
diff --git a/runtime/vm/dispatch_table.cc b/runtime/vm/dispatch_table.cc
index 183ff29..56e2449 100644
--- a/runtime/vm/dispatch_table.cc
+++ b/runtime/vm/dispatch_table.cc
@@ -4,159 +4,46 @@
 
 #include "vm/dispatch_table.h"
 
-#include "vm/clustered_snapshot.h"
-#include "vm/hash_map.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
+#include "platform/assert.h"
 
 namespace dart {
 
-// The serialized format of the dispatch table is a sequence of variable-length
-// integers (using the built-in variable-length integer encoding/decoding of
-// the stream). Each encoded integer e is interpreted thus:
-// -kRecentCount .. -1   Pick value from the recent values buffer at index -1-e.
-// 0                     Empty (unused) entry.
-// 1 .. kMaxRepeat       Repeat previous entry e times.
-// kIndexBase or higher  Pick entry point from the code object at index
-//                       e-kIndexBase in the code array and also put it into
-//                       the recent values buffer at the next index round-robin.
-
-// Constants for serialization format. Chosen such that repeats and recent
-// values are encoded as single bytes.
-static const intptr_t kMaxRepeat = 63;
-static const intptr_t kRecentCount = 64;  // Must be a power of two.
-static const intptr_t kRecentMask = kRecentCount - 1;
-static const intptr_t kIndexBase = kMaxRepeat + 1;
-
-uword DispatchTable::EntryPointFor(const Code& code) {
-  return code.EntryPoint();
+intptr_t DispatchTable::OriginElement() {
+#if defined(TARGET_ARCH_X64)
+  // Max negative byte offset / 8
+  return 16;
+#elif defined(TARGET_ARCH_ARM)
+  // Max negative load offset / 4
+  return 1023;
+#elif defined(TARGET_ARCH_ARM64)
+  // Max consecutive sub immediate value
+  return 4096;
+#else
+  // No AOT on IA32
+  UNREACHABLE();
+  return 0;
+#endif
 }
 
-void DispatchTable::SetCodeAt(intptr_t index, const Code& code) {
-  ASSERT(index >= 0 && index < length());
-  // The table is built with the same representation as it has at runtime, that
-  // is, table entries are function entry points. This representation assumes
-  // that the code will not move between table building and serialization.
-  // This property is upheld by the fact that the GC does not move code around.
-  array_[index] = EntryPointFor(code);
+intptr_t DispatchTable::LargestSmallOffset() {
+#if defined(TARGET_ARCH_X64)
+  // Origin + Max positive byte offset / 8
+  return 31;
+#elif defined(TARGET_ARCH_ARM)
+  // Origin + Max positive load offset / 4
+  return 2046;
+#elif defined(TARGET_ARCH_ARM64)
+  // Origin + Max consecutive add immediate value
+  return 8192;
+#else
+  // No AOT on IA32
+  UNREACHABLE();
+  return 0;
+#endif
 }
 
-intptr_t DispatchTable::Serialize(Serializer* serializer,
-                                  const DispatchTable* table,
-                                  const GrowableArray<RawCode*>& code_objects) {
-  const intptr_t bytes_before = serializer->bytes_written();
-  if (table != nullptr) {
-    table->Serialize(serializer, code_objects);
-  } else {
-    serializer->Write<uint32_t>(0);
-  }
-  return serializer->bytes_written() - bytes_before;
-}
-
-void DispatchTable::Serialize(
-    Serializer* serializer,
-    const GrowableArray<RawCode*>& code_objects) const {
-  Code& code = Code::Handle();
-  IntMap<intptr_t> entry_to_index;
-  for (intptr_t i = 0; i < code_objects.length(); i++) {
-    code = code_objects[i];
-    const uword entry = EntryPointFor(code);
-    if (!entry_to_index.HasKey(entry)) {
-      entry_to_index.Insert(entry, i + 1);
-    }
-  }
-
-  uword prev_entry = 0;
-  uword recent[kRecentCount] = {0};
-  intptr_t recent_index = 0;
-  intptr_t repeat_count = 0;
-
-  serializer->Write<uint32_t>(length());
-  for (intptr_t i = 0; i < length(); i++) {
-    const uword entry = array_[i];
-    if (entry == prev_entry) {
-      if (++repeat_count == kMaxRepeat) {
-        serializer->Write<uint32_t>(kMaxRepeat);
-        repeat_count = 0;
-      }
-    } else {
-      if (repeat_count > 0) {
-        serializer->Write<uint32_t>(repeat_count);
-        repeat_count = 0;
-      }
-      if (entry == 0) {
-        serializer->Write<uint32_t>(0);
-      } else {
-        bool found_recent = false;
-        for (intptr_t r = 0; r < kRecentCount; r++) {
-          if (recent[r] == entry) {
-            serializer->Write<uint32_t>(~r);
-            found_recent = true;
-            break;
-          }
-        }
-        if (!found_recent) {
-          intptr_t index = entry_to_index.Lookup(entry) - 1;
-          ASSERT(index != -1);
-          ASSERT(EntryPointFor(Code::Handle(code_objects[index])) == entry);
-          serializer->Write<uint32_t>(kIndexBase + index);
-          recent[recent_index] = entry;
-          recent_index = (recent_index + 1) & kRecentMask;
-        }
-      }
-    }
-    prev_entry = entry;
-  }
-  if (repeat_count > 0) {
-    serializer->Write<uint32_t>(repeat_count);
-  }
-}
-
-DispatchTable* DispatchTable::Deserialize(Deserializer* deserializer,
-                                          const Array& code_array) {
-  const intptr_t length = deserializer->Read<uint32_t>();
-  if (length == 0) {
-    return nullptr;
-  }
-
-  DispatchTable* table = new DispatchTable(length);
-
-  Code& code = Code::Handle();
-
-  code =
-      deserializer->isolate()->object_store()->dispatch_table_null_error_stub();
-  uword null_entry = code.EntryPoint();
-
-  uword value = 0;
-  uword recent[kRecentCount] = {0};
-  intptr_t recent_index = 0;
-  intptr_t repeat_count = 0;
-  for (intptr_t i = 0; i < length; i++) {
-    if (repeat_count > 0) {
-      repeat_count--;
-    } else {
-      int32_t encoded = deserializer->Read<uint32_t>();
-      if (encoded == 0) {
-        value = null_entry;
-      } else if (encoded < 0) {
-        intptr_t r = ~encoded;
-        ASSERT(r < kRecentCount);
-        value = recent[r];
-      } else if (encoded <= kMaxRepeat) {
-        repeat_count = encoded - 1;
-      } else {
-        intptr_t index = encoded - kIndexBase;
-        code ^= code_array.At(index);
-        value = EntryPointFor(code);
-        recent[recent_index] = value;
-        recent_index = (recent_index + 1) & kRecentMask;
-      }
-    }
-    table->array_[i] = value;
-  }
-  ASSERT(repeat_count == 0);
-
-  return table;
+const uword* DispatchTable::ArrayOrigin() const {
+  return &array_.get()[OriginElement()];
 }
 
 }  // namespace dart
diff --git a/runtime/vm/dispatch_table.h b/runtime/vm/dispatch_table.h
index cd22910..8d02cdf 100644
--- a/runtime/vm/dispatch_table.h
+++ b/runtime/vm/dispatch_table.h
@@ -8,87 +8,30 @@
 #include <memory>
 
 #include "vm/globals.h"
-#include "vm/growable_array.h"
 
 namespace dart {
 
-class Array;
-class Code;
-class Deserializer;
-class RawCode;
-class Serializer;
-
-namespace compiler {
-class DispatchTableGenerator;
-}
-
 class DispatchTable {
  public:
   explicit DispatchTable(intptr_t length)
       : length_(length), array_(new uword[length]()) {}
 
   intptr_t length() const { return length_; }
-  uword* array() const { return array_.get(); }
 
   // The element of the dispatch table array to which the dispatch table
   // register points.
-  static intptr_t OriginElement() {
-#if defined(TARGET_ARCH_X64)
-    // Max negative byte offset / 8
-    return 16;
-#elif defined(TARGET_ARCH_ARM)
-    // Max negative load offset / 4
-    return 1023;
-#elif defined(TARGET_ARCH_ARM64)
-    // Max consecutive sub immediate value
-    return 4096;
-#else
-    // No AOT on IA32
-    UNREACHABLE();
-    return 0;
-#endif
-  }
-
-  // The largest offset that can use a more compact instruction sequence.
-  static intptr_t LargestSmallOffset() {
-#if defined(TARGET_ARCH_X64)
-    // Origin + Max positive byte offset / 8
-    return 31;
-#elif defined(TARGET_ARCH_ARM)
-    // Origin + Max positive load offset / 4
-    return 2046;
-#elif defined(TARGET_ARCH_ARM64)
-    // Origin + Max consecutive add immediate value
-    return 8192;
-#else
-    // No AOT on IA32
-    UNREACHABLE();
-    return 0;
-#endif
-  }
-
+  static intptr_t OriginElement();
+  static intptr_t LargestSmallOffset();
   // Dispatch table array pointer to put into the dispatch table register.
-  uword* ArrayOrigin() const { return &array()[OriginElement()]; }
-
-  void SetCodeAt(intptr_t index, const Code& code);
-
-  static intptr_t Serialize(Serializer* serializer,
-                            const DispatchTable* table,
-                            const GrowableArray<RawCode*>& code_objects);
-  static DispatchTable* Deserialize(Deserializer* deserializer,
-                                    const Array& code_array);
+  const uword* ArrayOrigin() const;
 
  private:
-  friend class compiler::DispatchTableGenerator;
-
-  void Serialize(Serializer* serializer,
-                 const GrowableArray<RawCode*>& code_objects) const;
-
-  static uword EntryPointFor(const Code& code);
+  uword* array() { return array_.get(); }
 
   intptr_t length_;
   std::unique_ptr<uword[]> array_;
 
+  friend class Deserializer;  // For non-const array().
   DISALLOW_COPY_AND_ASSIGN(DispatchTable);
 };
 
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index 229b3ab..be78898 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -110,16 +110,33 @@
   RELEASE_ASSERT(stream != nullptr || elf != nullptr);
 }
 
-intptr_t Dwarf::AddCode(const Code& code, intptr_t virtual_address) {
-  RELEASE_ASSERT(!code.IsNull());
-  RELEASE_ASSERT(code_to_address_.Lookup(&code) == nullptr);
-  const Code& zone_code = Code::ZoneHandle(zone_, code.raw());
-  if (elf_ != nullptr) {
-    RELEASE_ASSERT(virtual_address >= 0);
-    code_to_address_.Insert(CodeAddressPair(&zone_code, virtual_address));
-  }
+intptr_t Dwarf::AddCode(const Code& code) {
+  ASSERT(elf_ == nullptr);
+  ASSERT(!code.IsNull());
+  return AddCodeHelper(Code::ZoneHandle(zone_, code.raw()));
+}
+
+void Dwarf::AddCode(const Code& code,
+                    const char* name,
+                    intptr_t payload_start) {
+  ASSERT(elf_ != nullptr);
+
+  ASSERT(name != nullptr);
+  ASSERT(payload_start >= 0);
+  auto const virtual_address = elf_->NextMemoryOffset() + payload_start;
+  elf_->AddStaticSymbol(elf_->NextSectionIndex(), name, virtual_address);
+
+  ASSERT(!code.IsNull());
+  ASSERT(code_to_address_.Lookup(&code) == nullptr);
+  const auto& zone_code = Code::ZoneHandle(zone_, code.raw());
+  code_to_address_.Insert(CodeAddressPair(&zone_code, virtual_address));
+
+  AddCodeHelper(zone_code);
+}
+
+intptr_t Dwarf::AddCodeHelper(const Code& code) {
   const intptr_t index = codes_.length();
-  codes_.Add(&zone_code);
+  codes_.Add(&code);
   if (code.IsFunctionCode()) {
     const Function& function = Function::Handle(zone_, code.function());
     AddFunction(function);
@@ -292,7 +309,7 @@
   uint8_t* buffer = nullptr;
   WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
 
-  AssemblyCodeNamer namer(zone_);
+  SnapshotTextObjectNamer namer(zone_);
 
   if (asm_stream_ != nullptr) {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
@@ -358,7 +375,7 @@
     intptr_t last_code_index = codes_.length() - 1;
     const Code& last_code = *(codes_[last_code_index]);
     PrintNamedAddressWithOffset(
-        namer.AssemblyNameFor(last_code_index, last_code), last_code.Size());
+        namer.SnapshotNameFor(last_code_index, last_code), last_code.Size());
   }
   if (elf_ != nullptr) {
     addr(elf_->NextMemoryOffset());
@@ -421,7 +438,7 @@
 void Dwarf::WriteConcreteFunctions() {
   Function& function = Function::Handle(zone_);
   Script& script = Script::Handle(zone_);
-  AssemblyCodeNamer namer(zone_);
+  SnapshotTextObjectNamer namer(zone_);
   for (intptr_t i = 0; i < codes_.length(); i++) {
     const Code& code = *(codes_[i]);
     RELEASE_ASSERT(!code.IsNull());
@@ -456,7 +473,7 @@
 
     // DW_AT_low_pc
     if (asm_stream_ != nullptr) {
-      const char* asm_name = namer.AssemblyNameFor(i, code);
+      const char* asm_name = namer.SnapshotNameFor(i, code);
       // DW_AT_low_pc
       PrintNamedAddress(asm_name);
       // DW_AT_high_pc
@@ -564,7 +581,7 @@
                               intptr_t root_code_index,
                               intptr_t root_code_address,
                               const Script& parent_script,
-                              AssemblyCodeNamer* namer) {
+                              SnapshotTextObjectNamer* namer) {
   RELEASE_ASSERT(elf_ == nullptr || root_code_address >= 0);
   intptr_t file = LookupScript(parent_script);
   intptr_t line = node->call_pos.value();
@@ -587,7 +604,7 @@
 
   if (asm_stream_ != nullptr) {
     const char* asm_name =
-        namer->AssemblyNameFor(root_code_index, *codes_[root_code_index]);
+        namer->SnapshotNameFor(root_code_index, *codes_[root_code_index]);
     // DW_AT_low_pc
     PrintNamedAddressWithOffset(asm_name, node->start_pc_offset);
     // DW_AT_high_pc
@@ -722,14 +739,14 @@
   Array& functions = Array::Handle(zone_);
   GrowableArray<const Function*> function_stack(zone_, 8);
   GrowableArray<TokenPosition> token_positions(zone_, 8);
-  AssemblyCodeNamer namer(zone_);
+  SnapshotTextObjectNamer namer(zone_);
 
   for (intptr_t i = 0; i < codes_.length(); i++) {
     const Code& code = *(codes_[i]);
 
     const char* asm_name = nullptr;
     if (asm_stream_ != nullptr) {
-      asm_name = namer.AssemblyNameFor(i, code);
+      asm_name = namer.SnapshotNameFor(i, code);
     }
 
     intptr_t current_code_address = -1;
@@ -808,7 +825,7 @@
           } else {
             u1(DW_LNS_advance_pc);
             if (asm_stream_ != nullptr) {
-              const char* previous_asm_name = namer.AssemblyNameFor(
+              const char* previous_asm_name = namer.SnapshotNameFor(
                   previous_code_index, *codes_[previous_code_index]);
               Print(".uleb128 %s - %s + %" Pd "\n", asm_name, previous_asm_name,
                     current_pc_offset - previous_pc_offset);
@@ -859,9 +876,9 @@
   u1(DW_LNS_advance_pc);
   if (asm_stream_ != nullptr) {
     const char* last_asm_name =
-        namer.AssemblyNameFor(last_code_index, last_code);
+        namer.SnapshotNameFor(last_code_index, last_code);
     ASSERT(previous_code_index >= 0);
-    const char* previous_asm_name = namer.AssemblyNameFor(
+    const char* previous_asm_name = namer.SnapshotNameFor(
         previous_code_index, *codes_[previous_code_index]);
     Print(".uleb128 %s - %s + %" Pd "\n", last_asm_name, previous_asm_name,
           last_code.Size() - previous_pc_offset);
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index 284323e..c9430d1 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -16,7 +16,7 @@
 
 class Elf;
 class InliningNode;
-class AssemblyCodeNamer;
+class SnapshotTextObjectNamer;
 
 struct ScriptIndexPair {
   // Typedefs needed for the DirectChainedHashMap template.
@@ -201,10 +201,19 @@
 
   // Stores the code object for later creating the line number program.
   //
-  // If [elf()] is not nullptr, then [virtual_address] must be non-negative.
+  // Should only be called when the output is not ELF.
   //
   // Returns the stored index of the code object.
-  intptr_t AddCode(const Code& code, intptr_t virtual_address = -1);
+  intptr_t AddCode(const Code& code);
+
+  // Stores the code object for later creating the line number program.
+  //
+  // [payload_offset] should be the offset of the payload within the text
+  // section. [name] is used to create an ELF static symbol for the payload.
+  //
+  // Should only be called when the output is ELF.
+  void AddCode(const Code& code, const char* name, intptr_t payload_offset);
+
   intptr_t AddFunction(const Function& function);
   intptr_t AddScript(const Script& script);
   intptr_t LookupFunction(const Function& function);
@@ -217,6 +226,10 @@
   }
 
  private:
+  // Implements shared functionality for the two AddCode calls. Assumes the
+  // Code handle is appropriately zoned.
+  intptr_t AddCodeHelper(const Code& code);
+
   static const intptr_t DW_TAG_compile_unit = 0x11;
   static const intptr_t DW_TAG_inlined_subroutine = 0x1d;
   static const intptr_t DW_TAG_subprogram = 0x2e;
@@ -393,7 +406,7 @@
                          intptr_t root_code_index,
                          intptr_t root_code_offset,
                          const Script& parent_script,
-                         AssemblyCodeNamer* namer);
+                         SnapshotTextObjectNamer* namer);
   void WriteLines();
 
   const char* Deobfuscate(const char* cstr);
diff --git a/runtime/vm/heap/scavenger.h b/runtime/vm/heap/scavenger.h
index ff12b6b..9dacdd3 100644
--- a/runtime/vm/heap/scavenger.h
+++ b/runtime/vm/heap/scavenger.h
@@ -354,7 +354,7 @@
   intptr_t idle_scavenge_threshold_in_words_;
 
   // The total size of external data associated with objects in this scavenger.
-  intptr_t external_size_;
+  RelaxedAtomic<intptr_t> external_size_;
 
   bool failed_to_promote_;
 
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 0c4d250..3ae1578 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -78,12 +78,16 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-ImageWriter::ImageWriter(Heap* heap)
-    : heap_(heap),
+ImageWriter::ImageWriter(Thread* t)
+    : heap_(t->heap()),
       next_data_offset_(0),
       next_text_offset_(0),
       objects_(),
-      instructions_() {
+      instructions_(),
+      instructions_section_type_(
+          TagObjectTypeAsReadOnly(t->zone(), "InstructionsSection")),
+      instructions_type_(TagObjectTypeAsReadOnly(t->zone(), "Instructions")),
+      trampoline_type_(TagObjectTypeAsReadOnly(t->zone(), "Trampoline")) {
   ResetOffsets();
 }
 
@@ -243,6 +247,42 @@
   return offset;
 }
 
+intptr_t ImageWriter::GetTextObjectCount() const {
+  return instructions_.length();
+}
+
+void ImageWriter::GetTrampolineInfo(intptr_t* count, intptr_t* size) const {
+  ASSERT(count != nullptr && size != nullptr);
+  *count = 0;
+  *size = 0;
+  for (auto const data : instructions_) {
+    if (data.trampoline_length != 0) {
+      *count += 1;
+      *size += data.trampoline_length;
+    }
+  }
+}
+
+// Returns nullptr if there is no profile writer.
+const char* ImageWriter::ObjectTypeForProfile(const Object& object) const {
+  if (profile_writer_ == nullptr) return nullptr;
+  ASSERT(IsROSpace());
+  Thread* thread = Thread::Current();
+  REUSABLE_CLASS_HANDLESCOPE(thread);
+  REUSABLE_STRING_HANDLESCOPE(thread);
+  Class& klass = thread->ClassHandle();
+  String& name = thread->StringHandle();
+  klass = object.clazz();
+  name = klass.UserVisibleName();
+  auto const name_str = name.ToCString();
+  return TagObjectTypeAsReadOnly(thread->zone(), name_str);
+}
+
+const char* ImageWriter::TagObjectTypeAsReadOnly(Zone* zone, const char* type) {
+  ASSERT(zone != nullptr && type != nullptr);
+  return OS::SCreate(zone, "(RO) %s", type);
+}
+
 #if defined(DART_PRECOMPILER)
 void ImageWriter::DumpInstructionStats() {
   std::unique_ptr<CombinedCodeStatistics> instruction_stats(
@@ -461,7 +501,7 @@
                                          void* callback_data,
                                          bool strip,
                                          Elf* debug_elf)
-    : ImageWriter(thread->heap()),
+    : ImageWriter(thread),
       assembly_stream_(512 * KB, callback, callback_data),
       assembly_dwarf_(nullptr),
       debug_dwarf_(nullptr) {
@@ -537,37 +577,47 @@
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-const char* AssemblyCodeNamer::AssemblyNameFor(intptr_t code_index,
-                                               const Code& code) {
+const char* SnapshotTextObjectNamer::SnapshotNameFor(intptr_t code_index,
+                                                     const Code& code) {
   ASSERT(!code.IsNull());
+  const char* prefix = FLAG_precompiled_mode ? "Precompiled_" : "";
   owner_ = code.owner();
   if (owner_.IsNull()) {
     insns_ = code.instructions();
     const char* name = StubCode::NameOfStub(insns_.EntryPoint());
     if (name != nullptr) {
-      return OS::SCreate(zone_, "Precompiled_Stub_%s", name);
+      return OS::SCreate(zone_, "%sStub_%s", prefix, name);
     }
     name = NameOfStubIsolateSpecificStub(store_, code);
     ASSERT(name != nullptr);
-    return OS::SCreate(zone_, "Precompiled__%s", name);
+    return OS::SCreate(zone_, "%s_%s", prefix, name);
   } else if (owner_.IsClass()) {
     string_ = Class::Cast(owner_).Name();
     const char* name = string_.ToCString();
     EnsureAssemblerIdentifier(const_cast<char*>(name));
-    return OS::SCreate(zone_, "Precompiled_AllocationStub_%s_%" Pd, name,
+    return OS::SCreate(zone_, "%sAllocationStub_%s_%" Pd, prefix, name,
                        code_index);
   } else if (owner_.IsAbstractType()) {
     const char* name = namer_.StubNameForType(AbstractType::Cast(owner_));
-    return OS::SCreate(zone_, "Precompiled_%s", name);
+    return OS::SCreate(zone_, "%s%s", prefix, name);
   } else if (owner_.IsFunction()) {
     const char* name = Function::Cast(owner_).ToQualifiedCString();
     EnsureAssemblerIdentifier(const_cast<char*>(name));
-    return OS::SCreate(zone_, "Precompiled_%s_%" Pd, name, code_index);
+    return OS::SCreate(zone_, "%s%s_%" Pd, prefix, name, code_index);
   } else {
     UNREACHABLE();
   }
 }
 
+const char* SnapshotTextObjectNamer::SnapshotNameFor(
+    intptr_t index,
+    const ImageWriter::InstructionsData& data) {
+  if (data.trampoline_bytes != nullptr) {
+    return OS::SCreate(zone_, "Trampoline_%" Pd "", index);
+  }
+  return SnapshotNameFor(index, *data.code_);
+}
+
 void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
 #if defined(DART_PRECOMPILED_RUNTIME)
   UNREACHABLE();
@@ -614,6 +664,10 @@
     WriteWordLiteralText(0);
   }
 
+  // Only valid if bare_instruction_payloads is true.
+  const V8SnapshotProfileWriter::ObjectId instructions_section_id(
+      offset_space_, bare_instruction_payloads ? Image::kHeaderSize : -1);
+
   if (bare_instruction_payloads) {
     const intptr_t section_size = image_size - Image::kHeaderSize;
     // Add the RawInstructionsSection header.
@@ -633,15 +687,14 @@
     WriteWordLiteralText(instructions_length);
 
     if (profile_writer_ != nullptr) {
-      const intptr_t offset = Image::kHeaderSize;
       const intptr_t non_instruction_bytes =
           compiler::target::InstructionsSection::HeaderSize();
-      profile_writer_->SetObjectTypeAndName({offset_space_, offset},
-                                            "InstructionsSection",
-                                            /*name=*/nullptr);
-      profile_writer_->AttributeBytesTo({offset_space_, offset},
+      profile_writer_->SetObjectTypeAndName(instructions_section_id,
+                                            instructions_section_type_,
+                                            instructions_symbol);
+      profile_writer_->AttributeBytesTo(instructions_section_id,
                                         non_instruction_bytes);
-      profile_writer_->AddRoot({offset_space_, offset});
+      profile_writer_->AddRoot(instructions_section_id);
     }
   }
 
@@ -654,7 +707,7 @@
   FrameUnwindPrologue();
 
   PcDescriptors& descriptors = PcDescriptors::Handle(zone);
-  AssemblyCodeNamer namer(zone);
+  SnapshotTextObjectNamer namer(zone);
   intptr_t text_offset = 0;
 
   ASSERT(offset_space_ != V8SnapshotProfileWriter::kSnapshot);
@@ -663,28 +716,37 @@
     const bool is_trampoline = data.trampoline_bytes != nullptr;
     ASSERT((data.text_offset_ - instructions_[0].text_offset_) == text_offset);
 
-    if (bare_instruction_payloads && profile_writer_ != nullptr) {
-      const intptr_t instructions_sections_offset = Image::kHeaderSize;
-      const intptr_t offset = section_headers_size + text_offset;
-      profile_writer_->AttributeReferenceTo(
-          {offset_space_, instructions_sections_offset},
-          {{offset_space_, offset},
-           V8SnapshotProfileWriter::Reference::kElement,
-           text_offset});
+    intptr_t dwarf_index = i;
+#if defined(DART_PRECOMPILER)
+    if (!is_trampoline && assembly_dwarf_ != nullptr) {
+      dwarf_index = assembly_dwarf_->AddCode(*data.code_);
+    }
+#endif
+
+    const auto object_name = namer.SnapshotNameFor(dwarf_index, data);
+
+    if (profile_writer_ != nullptr) {
+      const auto object_offset = section_headers_size + text_offset;
+      const V8SnapshotProfileWriter::ObjectId object_id(offset_space_,
+                                                        object_offset);
+      auto const type = is_trampoline ? trampoline_type_ : instructions_type_;
+      const intptr_t size = is_trampoline ? data.trampoline_length
+                                          : SizeInSnapshot(data.insns_->raw());
+      profile_writer_->SetObjectTypeAndName(object_id, type, object_name);
+      profile_writer_->AttributeBytesTo(object_id, size);
+      // If the object is wrapped in an InstructionSection, then add an
+      // element reference.
+      if (bare_instruction_payloads) {
+        profile_writer_->AttributeReferenceTo(
+            instructions_section_id,
+            {object_id, V8SnapshotProfileWriter::Reference::kElement,
+             text_offset});
+      }
     }
 
     if (is_trampoline) {
-      if (profile_writer_ != nullptr) {
-        const intptr_t offset = section_headers_size + text_offset;
-        profile_writer_->SetObjectTypeAndName({offset_space_, offset},
-                                              "Trampolines",
-                                              /*name=*/nullptr);
-        profile_writer_->AttributeBytesTo({offset_space_, offset},
-                                          data.trampline_length);
-      }
-
       const auto start = reinterpret_cast<uword>(data.trampoline_bytes);
-      const auto end = start + data.trampline_length;
+      const auto end = start + data.trampoline_length;
       text_offset += WriteByteSequence(start, end);
       delete[] data.trampoline_bytes;
       data.trampoline_bytes = nullptr;
@@ -693,18 +755,9 @@
 
     const intptr_t instr_start = text_offset;
 
-    const Instructions& insns = *data.insns_;
-    const Code& code = *data.code_;
-    descriptors = data.code_->pc_descriptors();
-
-    if (profile_writer_ != nullptr) {
-      const intptr_t offset = section_headers_size + text_offset;
-      profile_writer_->SetObjectTypeAndName({offset_space_, offset},
-                                            "Instructions",
-                                            /*name=*/nullptr);
-      profile_writer_->AttributeBytesTo({offset_space_, offset},
-                                        SizeInSnapshot(insns.raw()));
-    }
+    const auto& code = *data.code_;
+    const auto& insns = *data.insns_;
+    descriptors = code.pc_descriptors();
 
     const uword payload_start = insns.PayloadStart();
 
@@ -746,21 +799,15 @@
              compiler::target::Instructions::HeaderSize());
     }
 
-    intptr_t dwarf_index = i;
-#ifdef DART_PRECOMPILER
-    // Create a label for use by DWARF.
-    if (assembly_dwarf_ != nullptr) {
-      dwarf_index = assembly_dwarf_->AddCode(code);
-    }
+#if defined(DART_PRECOMPILER)
     if (debug_dwarf_ != nullptr) {
-      auto const virtual_address =
-          debug_segment_base + section_headers_size + text_offset;
-      debug_dwarf_->AddCode(code, virtual_address);
+      auto const payload_offset = section_headers_size + text_offset;
+      debug_dwarf_->AddCode(code, object_name, payload_offset);
     }
 #endif
     // 2. Write a label at the entry point.
     // Linux's perf uses these labels.
-    assembly_stream_.Print("%s:\n", namer.AssemblyNameFor(dwarf_index, code));
+    assembly_stream_.Print("%s:\n", object_name);
 
     {
       // 3. Write from the payload start to payload end. For AOT snapshots
@@ -846,20 +893,23 @@
     // We need to generate a text segment of the appropriate size in the ELF
     // for two reasons:
     //
-    // * We use Elf::NextMemoryOffset() as the current segment base when
-    //   calling Dwarf::AddCode above, so we get unique virtual addresses in
-    //   the DWARF line number program.
+    // * We need unique virtual addresses for each text section in the DWARF
+    //   file and that the virtual addresses for payloads within those sections
+    //   do not overlap.
     //
     // * Our tools for converting DWARF stack traces back to "normal" Dart
     //   stack traces calculate an offset into the appropriate instructions
     //   section, and then add that offset to the virtual address of the
     //   corresponding segment to get the virtual address for the frame.
     //
-    // Since we won't actually be adding the instructions to the ELF output,
-    // we can pass nullptr for the bytes of the section/segment.
+    // Since we don't want to add the actual contents of the segment in the
+    // separate debugging information, we pass nullptr for the bytes, which
+    // creates an appropriate NOBITS section instead of PROGBITS.
     auto const debug_segment_base2 =
         debug_dwarf_->elf()->AddText(instructions_symbol, /*bytes=*/nullptr,
                                      section_headers_size + text_offset);
+    // Double-check that no other ELF sections were added in the middle of
+    // writing the text section.
     ASSERT(debug_segment_base2 == debug_segment_base);
   }
 
@@ -1005,7 +1055,7 @@
                                  intptr_t bss_base,
                                  Elf* elf,
                                  Dwarf* elf_dwarf)
-    : ImageWriter(thread->heap()),
+    : ImageWriter(thread),
       instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size),
       elf_(elf),
       elf_dwarf_(elf_dwarf),
@@ -1030,8 +1080,11 @@
 void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
   const bool bare_instruction_payloads =
       FLAG_precompiled_mode && FLAG_use_bare_instructions;
+  const char* instructions_symbol =
+      vm ? "_kDartVmSnapshotInstructions" : "_kDartIsolateSnapshotInstructions";
+  auto const zone = Thread::Current()->zone();
 
-#ifdef DART_PRECOMPILER
+#if defined(DART_PRECOMPILER)
   intptr_t segment_base = 0;
   if (elf_ != nullptr) {
     segment_base = elf_->NextMemoryOffset();
@@ -1059,6 +1112,10 @@
     instructions_blob_stream_.WriteTargetWord(0);
   }
 
+  // Only valid when bare_instructions_payloads is true.
+  const V8SnapshotProfileWriter::ObjectId instructions_section_id(
+      offset_space_, bare_instruction_payloads ? Image::kHeaderSize : -1);
+
   if (bare_instruction_payloads) {
     const intptr_t section_size = image_size - Image::kHeaderSize;
     // Add the RawInstructionsSection header.
@@ -1077,24 +1134,23 @@
     instructions_blob_stream_.WriteTargetWord(instructions_length);
 
     if (profile_writer_ != nullptr) {
-      const intptr_t offset = Image::kHeaderSize;
       const intptr_t non_instruction_bytes =
           compiler::target::InstructionsSection::HeaderSize();
-      profile_writer_->SetObjectTypeAndName({offset_space_, offset},
-                                            "InstructionsSection",
-                                            /*name=*/nullptr);
-      profile_writer_->AttributeBytesTo({offset_space_, offset},
+      profile_writer_->SetObjectTypeAndName(instructions_section_id,
+                                            instructions_section_type_,
+                                            instructions_symbol);
+      profile_writer_->AttributeBytesTo(instructions_section_id,
                                         non_instruction_bytes);
-      profile_writer_->AddRoot({offset_space_, offset});
+      profile_writer_->AddRoot(instructions_section_id);
     }
   }
 
   intptr_t text_offset = 0;
 
 #if defined(DART_PRECOMPILER)
-  PcDescriptors& descriptors = PcDescriptors::Handle();
-  AssemblyCodeNamer namer(Thread::Current()->zone());
+  auto& descriptors = PcDescriptors::Handle(zone);
 #endif
+  SnapshotTextObjectNamer namer(zone);
 
   NoSafepointScope no_safepoint;
   for (intptr_t i = 0; i < instructions_.length(); i++) {
@@ -1102,18 +1158,29 @@
     const bool is_trampoline = data.trampoline_bytes != nullptr;
     ASSERT((data.text_offset_ - instructions_[0].text_offset_) == text_offset);
 
-    if (bare_instruction_payloads && profile_writer_ != nullptr) {
-      const intptr_t instructions_sections_offset = Image::kHeaderSize;
-      profile_writer_->AttributeReferenceTo(
-          {offset_space_, instructions_sections_offset},
-          {{offset_space_, instructions_blob_stream_.Position()},
-           V8SnapshotProfileWriter::Reference::kElement,
-           text_offset});
+    const auto object_name = namer.SnapshotNameFor(i, data);
+
+    if (profile_writer_ != nullptr) {
+      const V8SnapshotProfileWriter::ObjectId object_id(
+          offset_space_, instructions_blob_stream_.Position());
+      auto const type = is_trampoline ? trampoline_type_ : instructions_type_;
+      const intptr_t size = is_trampoline ? data.trampoline_length
+                                          : SizeInSnapshot(data.insns_->raw());
+      profile_writer_->SetObjectTypeAndName(object_id, type, object_name);
+      profile_writer_->AttributeBytesTo(object_id, size);
+      // If the object is wrapped in an InstructionSection, then add an
+      // element reference.
+      if (bare_instruction_payloads) {
+        profile_writer_->AttributeReferenceTo(
+            instructions_section_id,
+            {object_id, V8SnapshotProfileWriter::Reference::kElement,
+             text_offset});
+      }
     }
 
     if (is_trampoline) {
       const auto start = reinterpret_cast<uword>(data.trampoline_bytes);
-      const auto end = start + data.trampline_length;
+      const auto end = start + data.trampoline_length;
       text_offset += WriteByteSequence(start, end);
       delete[] data.trampoline_bytes;
       data.trampoline_bytes = nullptr;
@@ -1122,8 +1189,7 @@
 
     const intptr_t instr_start = text_offset;
 
-    const Instructions& insns = *instructions_[i].insns_;
-    AutoTraceImage(insns, 0, &this->instructions_blob_stream_);
+    const auto& insns = *data.insns_;
     const uword payload_start = insns.PayloadStart();
 
     ASSERT(Utils::IsAligned(payload_start, sizeof(compiler::target::uword)));
@@ -1153,7 +1219,7 @@
       ASSERT(Utils::IsAligned(instructions_blob_stream_.Position(),
                               kBareInstructionsAlignment));
     }
-    const intptr_t payload_stream_start = instructions_blob_stream_.Position();
+    const intptr_t payload_offset = instructions_blob_stream_.Position();
     instructions_blob_stream_.WriteBytes(
         reinterpret_cast<const void*>(insns.PayloadStart()), insns.Size());
     const intptr_t alignment =
@@ -1181,22 +1247,17 @@
       ASSERT(Utils::IsAligned(instructions_blob_stream_.Position(),
                               kBareInstructionsAlignment));
     }
-    const intptr_t payload_stream_start = instructions_blob_stream_.Position();
+    const intptr_t payload_offset = instructions_blob_stream_.Position();
     text_offset += WriteByteSequence(payload_start, object_end);
 #endif
 
 #if defined(DART_PRECOMPILER)
-    if (elf_ != nullptr && elf_dwarf_ != nullptr) {
-      const auto& code = *instructions_[i].code_;
-      auto const virtual_address = segment_base + payload_stream_start;
-      elf_dwarf_->AddCode(code, virtual_address);
-      elf_->AddStaticSymbol(elf_->NextSectionIndex(),
-                            namer.AssemblyNameFor(i, code), virtual_address);
+    const auto& code = *data.code_;
+    if (elf_dwarf_ != nullptr) {
+      elf_dwarf_->AddCode(code, object_name, payload_offset);
     }
     if (debug_dwarf_ != nullptr) {
-      const auto& code = *instructions_[i].code_;
-      auto const virtual_address = debug_segment_base + payload_stream_start;
-      debug_dwarf_->AddCode(code, virtual_address);
+      debug_dwarf_->AddCode(code, object_name, payload_offset);
     }
 
     // Don't patch the relocation if we're not generating ELF. The regular blobs
@@ -1207,7 +1268,7 @@
       const intptr_t current_stream_position =
           instructions_blob_stream_.Position();
 
-      descriptors = data.code_->pc_descriptors();
+      descriptors = code.pc_descriptors();
 
       PcDescriptors::Iterator iterator(
           descriptors, /*kind_mask=*/RawPcDescriptors::kBSSRelocation);
@@ -1224,12 +1285,10 @@
         // Overwrite the relocation position in the instruction stream with the
         // (positive) offset of the start of the payload from the start of the
         // BSS segment plus the addend in the relocation.
-        instructions_blob_stream_.SetPosition(payload_stream_start +
-                                              reloc_offset);
+        instructions_blob_stream_.SetPosition(payload_offset + reloc_offset);
 
         const compiler::target::word offset =
-            bss_base_ - (segment_base + payload_stream_start + reloc_offset) +
-            addend;
+            bss_base_ - (segment_base + payload_offset + reloc_offset) + addend;
         instructions_blob_stream_.WriteTargetWord(offset);
       }
 
@@ -1237,7 +1296,7 @@
       instructions_blob_stream_.SetPosition(current_stream_position);
     }
 #else
-    USE(payload_stream_start);
+    USE(payload_offset);
 #endif
 
     ASSERT((text_offset - instr_start) ==
@@ -1253,8 +1312,6 @@
   ASSERT_EQUAL(instructions_blob_stream_.bytes_written(), image_size);
 
 #ifdef DART_PRECOMPILER
-  const char* instructions_symbol =
-      vm ? "_kDartVmSnapshotInstructions" : "_kDartIsolateSnapshotInstructions";
   if (elf_ != nullptr) {
     auto const segment_base2 =
         elf_->AddText(instructions_symbol, instructions_blob_stream_.buffer(),
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 13d42e1..3d87113 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -149,7 +149,7 @@
 
 class ImageWriter : public ValueObject {
  public:
-  explicit ImageWriter(Heap* heap);
+  explicit ImageWriter(Thread* thread);
   virtual ~ImageWriter() {}
 
   void ResetOffsets() {
@@ -166,12 +166,20 @@
   // [ImageWriterCommand]s.
   void PrepareForSerialization(GrowableArray<ImageWriterCommand>* commands);
 
+  bool IsROSpace() const {
+    return offset_space_ == V8SnapshotProfileWriter::kVmData ||
+           offset_space_ == V8SnapshotProfileWriter::kVmText ||
+           offset_space_ == V8SnapshotProfileWriter::kIsolateData ||
+           offset_space_ == V8SnapshotProfileWriter::kIsolateText;
+  }
   int32_t GetTextOffsetFor(RawInstructions* instructions, RawCode* code);
   uint32_t GetDataOffsetFor(RawObject* raw_object);
 
   void Write(WriteStream* clustered_stream, bool vm);
   intptr_t data_size() const { return next_data_offset_; }
   intptr_t text_size() const { return next_text_offset_; }
+  intptr_t GetTextObjectCount() const;
+  void GetTrampolineInfo(intptr_t* count, intptr_t* size) const;
 
   void DumpStatistics();
 
@@ -215,6 +223,10 @@
                                       marked_tags);
   }
 
+  // Returns nullptr if there is no profile writer.
+  const char* ObjectTypeForProfile(const Object& object) const;
+  static const char* TagObjectTypeAsReadOnly(Zone* zone, const char* type);
+
  protected:
   void WriteROData(WriteStream* stream);
   virtual void WriteText(WriteStream* clustered_stream, bool vm) = 0;
@@ -230,16 +242,16 @@
           raw_code_(code),
           text_offset_(text_offset),
           trampoline_bytes(nullptr),
-          trampline_length(0) {}
+          trampoline_length(0) {}
 
     InstructionsData(uint8_t* trampoline_bytes,
-                     intptr_t trampline_length,
+                     intptr_t trampoline_length,
                      intptr_t text_offset)
         : raw_insns_(nullptr),
           raw_code_(nullptr),
           text_offset_(text_offset),
           trampoline_bytes(trampoline_bytes),
-          trampline_length(trampline_length) {}
+          trampoline_length(trampoline_length) {}
 
     union {
       RawInstructions* raw_insns_;
@@ -252,7 +264,7 @@
     intptr_t text_offset_;
 
     uint8_t* trampoline_bytes;
-    intptr_t trampline_length;
+    intptr_t trampoline_length;
   };
 
   struct ObjectData {
@@ -273,9 +285,13 @@
   V8SnapshotProfileWriter::IdSpace offset_space_ =
       V8SnapshotProfileWriter::kSnapshot;
   V8SnapshotProfileWriter* profile_writer_ = nullptr;
+  const char* const instructions_section_type_;
+  const char* const instructions_type_;
+  const char* const trampoline_type_;
 
   template <class T>
   friend class TraceImageObjectScope;
+  friend class SnapshotTextObjectNamer;  // For InstructionsData.
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ImageWriter);
@@ -293,43 +309,34 @@
                         intptr_t section_offset,
                         const T* stream,
                         const Object& object)
-      : writer_(writer),
-        stream_(stream),
+      : writer_(ASSERT_NOTNULL(writer)),
+        stream_(ASSERT_NOTNULL(stream)),
         section_offset_(section_offset),
-        start_offset_(stream_->Position() - section_offset) {
-    if (writer_->profile_writer_ != nullptr) {
-      Thread* thread = Thread::Current();
-      REUSABLE_CLASS_HANDLESCOPE(thread);
-      REUSABLE_STRING_HANDLESCOPE(thread);
-      Class& klass = thread->ClassHandle();
-      String& name = thread->StringHandle();
-      klass = object.clazz();
-      name = klass.UserVisibleName();
-      ASSERT(writer_->offset_space_ != V8SnapshotProfileWriter::kSnapshot);
-      writer_->profile_writer_->SetObjectTypeAndName(
-          {writer_->offset_space_, start_offset_}, name.ToCString(), nullptr);
-    }
-  }
+        start_offset_(stream_->Position() - section_offset),
+        object_(object) {}
 
   ~TraceImageObjectScope() {
-    if (writer_->profile_writer_ != nullptr) {
-      ASSERT(writer_->offset_space_ != V8SnapshotProfileWriter::kSnapshot);
-      writer_->profile_writer_->AttributeBytesTo(
-          {writer_->offset_space_, start_offset_},
-          stream_->Position() - section_offset_ - start_offset_);
-    }
+    if (writer_->profile_writer_ == nullptr) return;
+    ASSERT(writer_->IsROSpace());
+    writer_->profile_writer_->SetObjectTypeAndName(
+        {writer_->offset_space_, start_offset_},
+        writer_->ObjectTypeForProfile(object_), nullptr);
+    writer_->profile_writer_->AttributeBytesTo(
+        {writer_->offset_space_, start_offset_},
+        stream_->Position() - section_offset_ - start_offset_);
   }
 
  private:
-  ImageWriter* writer_;
-  const T* stream_;
-  intptr_t section_offset_;
-  intptr_t start_offset_;
+  ImageWriter* const writer_;
+  const T* const stream_;
+  const intptr_t section_offset_;
+  const intptr_t start_offset_;
+  const Object& object_;
 };
 
-class AssemblyCodeNamer {
+class SnapshotTextObjectNamer {
  public:
-  explicit AssemblyCodeNamer(Zone* zone)
+  explicit SnapshotTextObjectNamer(Zone* zone)
       : zone_(zone),
         owner_(Object::Handle(zone)),
         string_(String::Handle(zone)),
@@ -338,7 +345,9 @@
 
   const char* StubNameForType(const AbstractType& type) const;
 
-  const char* AssemblyNameFor(intptr_t code_index, const Code& code);
+  const char* SnapshotNameFor(intptr_t code_index, const Code& code);
+  const char* SnapshotNameFor(intptr_t index,
+                              const ImageWriter::InstructionsData& data);
 
  private:
   Zone* const zone_;
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 5652c1a..e3cb9c9 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -998,9 +998,10 @@
 
   Dart_KernelCompilationResult retval = {};
   {
+    const char* root_lib_url = root_lib_url_.ToCString();
     TransitionVMToNative transition(Thread::Current());
-    retval = KernelIsolate::CompileToKernel(root_lib_url_.ToCString(), nullptr,
-                                            0, modified_scripts_count,
+    retval = KernelIsolate::CompileToKernel(root_lib_url, nullptr, 0,
+                                            modified_scripts_count,
                                             modified_scripts, true, nullptr);
   }
   if (retval.status != Dart_KernelCompilationStatus_Ok) {
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 88bed84..7771db0 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1435,6 +1435,9 @@
   if (class_helper->is_transformed_mixin_application()) {
     klass->set_is_transformed_mixin_application();
   }
+  if (class_helper->has_const_constructor()) {
+    klass->set_is_const();
+  }
 }
 
 void KernelLoader::LoadClass(const Library& library,
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index 1b3c546..3690222 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -50,8 +50,8 @@
     Api::Scope api_scope(T);
     Dart_Handle api_function_name = Api::NewHandle(T, function_name.raw());
     {
-      TransitionVMToNative transition(T);
       Dart_NativeEntryResolver resolver = library.native_entry_resolver();
+      TransitionVMToNative transition(T);
       native_function =
           resolver(api_function_name, number_of_arguments, auto_setup_scope);
     }
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index d15e41e..85b1d32 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3685,7 +3685,6 @@
 
 void Class::Finalize() const {
   auto thread = Thread::Current();
-  auto Z = thread->zone();
   Isolate* isolate = thread->isolate();
   ASSERT(thread->IsMutatorThread());
   ASSERT(!isolate->all_classes_finalized());
@@ -3706,22 +3705,21 @@
     }
   }
 
-  if (SuperClass() == Class::null() ||
-      Class::Handle(Z, SuperClass()).is_const()) {
+#if defined(DEBUG)
+  if (is_const()) {
+    // Double-check that all fields are final (CFE should guarantee that if it
+    // marks the class as having a constant constructor).
+    auto Z = thread->zone();
+    const auto& super_class = Class::Handle(Z, SuperClass());
+    ASSERT(super_class.IsNull() || super_class.is_const());
     const auto& fields = Array::Handle(Z, this->fields());
     auto& field = Field::Handle(Z);
-    bool is_const = true;
     for (intptr_t i = 0; i < fields.Length(); ++i) {
       field ^= fields.At(i);
-      if (!field.is_static() && !field.is_final()) {
-        is_const = false;
-        break;
-      }
-    }
-    if (is_const) {
-      set_is_const();
+      ASSERT(field.is_static() || field.is_final());
     }
   }
+#endif
 
   set_is_finalized();
 }
@@ -5573,6 +5571,40 @@
   set.Release();
 }
 
+intptr_t TypeArguments::ComputeNullability() const {
+  if (IsNull()) return 0;
+  const intptr_t num_types = Length();
+  intptr_t result = 0;
+  if (num_types <= kNullabilityMaxTypes) {
+    AbstractType& type = AbstractType::Handle();
+    for (intptr_t i = 0; i < num_types; i++) {
+      result <<= kNullabilityBitsPerType;
+      type = TypeAt(i);
+      if (!type.IsNull() && !type.IsNullTypeRef()) {
+        switch (type.nullability()) {
+          case Nullability::kNullable:
+            result |= kNullableBits;
+            break;
+          case Nullability::kNonNullable:
+            result |= kNonNullableBits;
+            break;
+          case Nullability::kLegacy:
+            result |= kLegacyBits;
+            break;
+          default:
+            UNREACHABLE();
+        }
+      }
+    }
+  }
+  set_nullability(result);
+  return result;
+}
+
+void TypeArguments::set_nullability(intptr_t value) const {
+  StoreSmi(&raw_ptr()->nullability_, Smi::New(value));
+}
+
 intptr_t TypeArguments::ComputeHash() const {
   if (IsNull()) return 0;
   const intptr_t num_types = Length();
@@ -5810,6 +5842,13 @@
   return Smi::Value(raw_ptr()->length_);
 }
 
+intptr_t TypeArguments::nullability() const {
+  if (IsNull()) {
+    return 0;
+  }
+  return Smi::Value(raw_ptr()->nullability_);
+}
+
 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const {
   ASSERT(!IsNull());
   return *TypeAddr(index);
@@ -5883,9 +5922,14 @@
 
 // Return true if this uninstantiated type argument vector, once instantiated
 // at runtime, is a prefix of the type argument vector of its instantiator.
+// A runtime check may be required, as indicated by with_runtime_check.
 bool TypeArguments::CanShareInstantiatorTypeArguments(
-    const Class& instantiator_class) const {
+    const Class& instantiator_class,
+    bool* with_runtime_check) const {
   ASSERT(!IsInstantiated());
+  if (with_runtime_check != nullptr) {
+    *with_runtime_check = false;
+  }
   const intptr_t num_type_args = Length();
   const intptr_t num_instantiator_type_args =
       instantiator_class.NumTypeArguments();
@@ -5923,6 +5967,19 @@
     if ((type_param.index() != i) || type_param.IsFunctionTypeParameter()) {
       return false;
     }
+    // Instantiating nullable and legacy type parameters may change nullability
+    // of a type, so type arguments vector containing such type parameters
+    // cannot be substituted with instantiator type arguments, unless we check
+    // at runtime the nullability of the first 1 or 2 type arguments of the
+    // instantiator.
+    // Note that the presence of non-overlapping super type arguments (i.e.
+    // first_type_param_offset > 0) will prevent this optimization.
+    if (type_param.IsNullable() || type_param.IsLegacy()) {
+      if (with_runtime_check == nullptr || i >= kNullabilityMaxTypes) {
+        return false;
+      }
+      *with_runtime_check = true;
+    }
   }
   // As a second requirement, the type arguments corresponding to the super type
   // must be identical. Overlapping ones have already been checked starting at
@@ -5953,9 +6010,14 @@
 
 // Return true if this uninstantiated type argument vector, once instantiated
 // at runtime, is a prefix of the enclosing function type arguments.
+// A runtime check may be required, as indicated by with_runtime_check.
 bool TypeArguments::CanShareFunctionTypeArguments(
-    const Function& function) const {
+    const Function& function,
+    bool* with_runtime_check) const {
   ASSERT(!IsInstantiated());
+  if (with_runtime_check != nullptr) {
+    *with_runtime_check = false;
+  }
   const intptr_t num_type_args = Length();
   const intptr_t num_parent_type_params = function.NumParentTypeParameters();
   const intptr_t num_function_type_params = function.NumTypeParameters();
@@ -5976,6 +6038,17 @@
     if ((type_param.index() != i) || !type_param.IsFunctionTypeParameter()) {
       return false;
     }
+    // Instantiating nullable and legacy type parameters may change nullability
+    // of a type, so type arguments vector containing such type parameters
+    // cannot be substituted with the enclosing function type arguments, unless
+    // we check at runtime the nullability of the first 1 or 2 type arguments of
+    // the enclosing function type arguments.
+    if (type_param.IsNullable() || type_param.IsLegacy()) {
+      if (with_runtime_check == nullptr || i >= kNullabilityMaxTypes) {
+        return false;
+      }
+      *with_runtime_check = true;
+    }
   }
   return true;
 }
@@ -6118,6 +6191,7 @@
     // Length must be set before we start storing into the array.
     result.SetLength(len);
     result.SetHash(0);
+    result.set_nullability(0);
   }
   // The zero array should have been initialized.
   ASSERT(Object::zero_array().raw() != Array::null());
@@ -6173,9 +6247,9 @@
       SetTypeAt(i, type_arg);
     }
     // Canonicalization of a type argument of a recursive type argument vector
-    // may change the hash of the vector, so recompute.
+    // may change the hash of the vector, so invalidate.
     if (IsRecursive()) {
-      ComputeHash();
+      SetHash(0);
     }
     SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
     CanonicalTypeArgumentsSet table(zone,
@@ -6192,6 +6266,7 @@
         result = this->raw();
       }
       ASSERT(result.IsOld());
+      result.ComputeNullability();
       result.SetCanonical();  // Mark object as being canonical.
       // Now add this TypeArgument into the canonical list of type arguments.
       bool present = table.Insert(result);
@@ -8364,7 +8439,9 @@
       name = type_param.name();
       printer->AddString(name.ToCString());
       bound = type_param.bound();
-      if (!bound.IsNull() && !bound.IsObjectType()) {
+      // Do not print default bound or non-nullable Object bound in weak mode.
+      if (!bound.IsNull() && (!bound.IsObjectType() ||
+                              (FLAG_null_safety && bound.IsNonNullable()))) {
         printer->AddString(" extends ");
         bound.PrintName(name_visibility, printer);
       }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index bed47a7..3706d9e 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -6182,13 +6182,13 @@
 #endif
   }
 
- private:
-  void set_state_bits(intptr_t bits) const;
-
   void set_object_pool(RawObjectPool* object_pool) const {
     StorePointer(&raw_ptr()->object_pool_, object_pool);
   }
 
+ private:
+  void set_state_bits(intptr_t bits) const;
+
   friend class RawObject;  // For RawObject::SizeFromClass().
   friend class RawCode;
   enum {
@@ -7188,6 +7188,31 @@
     static constexpr intptr_t kElementSize = kWordSize;
   };
 
+  // The nullability of a type argument vector represents the nullability of its
+  // type elements (up to a maximum number of them, i.e. kNullabilityMaxTypes).
+  // It is used at runtime in some cases (predetermined by the compiler) to
+  // decide whether the instantiator type arguments (ITA) can be shared instead
+  // of performing a more costly instantiation of the uninstantiated type
+  // arguments (UTA).
+  // The vector nullability is stored as a bit vector (in a Smi field), using
+  // 2 bits per type:
+  //  - the high bit is set if the type is nullable or legacy.
+  //  - the low bit is set if the type is nullable.
+  // The nullabilty is 0 if the vector is longer than kNullabilityMaxTypes.
+  // The condition evaluated at runtime to decide whether UTA can share ITA is
+  //   (UTA.nullability & ITA.nullability) == UTA.nullability
+  // Note that this allows for ITA to be longer than UTA.
+  static const intptr_t kNullabilityBitsPerType = 2;
+  static const intptr_t kNullabilityMaxTypes =
+      kSmiBits / kNullabilityBitsPerType;
+  static const intptr_t kNonNullableBits = 0;
+  static const intptr_t kNullableBits = 3;
+  static const intptr_t kLegacyBits = 2;
+  intptr_t nullability() const;
+  static intptr_t nullability_offset() {
+    return OFFSET_OF(RawTypeArguments, nullability_);
+  }
+
   // The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
   RawString* Name() const;
 
@@ -7209,7 +7234,7 @@
   }
 
   // Check if this type argument vector would consist solely of DynamicType if
-  // it was instantiated from both a raw (null) instantiator typearguments and
+  // it was instantiated from both a raw (null) instantiator type arguments and
   // a raw (null) function type arguments, i.e. consider each class type
   // parameter and function type parameters as it would be first instantiated
   // from a vector of dynamic types.
@@ -7270,8 +7295,19 @@
                                intptr_t num_free_fun_type_params = kAllFree,
                                TrailPtr trail = NULL) const;
   bool IsUninstantiatedIdentity() const;
-  bool CanShareInstantiatorTypeArguments(const Class& instantiator_class) const;
-  bool CanShareFunctionTypeArguments(const Function& function) const;
+
+  // Determine whether this uninstantiated type argument vector can share its
+  // instantiator (resp. function) type argument vector instead of being
+  // instantiated at runtime.
+  // If null is passed in for 'with_runtime_check', the answer is unconditional
+  // (i.e. the answer will be false even if a runtime check may allow sharing),
+  // otherwise, in case the function returns true, 'with_runtime_check'
+  // indicates if a check is still required at runtime before allowing sharing.
+  bool CanShareInstantiatorTypeArguments(
+      const Class& instantiator_class,
+      bool* with_runtime_check = nullptr) const;
+  bool CanShareFunctionTypeArguments(const Function& function,
+                                     bool* with_runtime_check = nullptr) const;
 
   // Return true if all types of this vector are finalized.
   bool IsFinalized() const;
@@ -7346,7 +7382,7 @@
 
   static intptr_t InstanceSize(intptr_t len) {
     // Ensure that the types() is not adding to the object size, which includes
-    // 3 fields: instantiations_, length_ and hash_.
+    // 4 fields: instantiations_, length_, hash_, and nullability_.
     ASSERT(sizeof(RawTypeArguments) ==
            (sizeof(RawObject) + (kNumFields * kWordSize)));
     ASSERT(0 <= len && len <= kMaxElements);
@@ -7363,6 +7399,9 @@
   static RawTypeArguments* New(intptr_t len, Heap::Space space = Heap::kOld);
 
  private:
+  intptr_t ComputeNullability() const;
+  void set_nullability(intptr_t value) const;
+
   intptr_t ComputeHash() const;
   void SetHash(intptr_t value) const;
 
@@ -7378,8 +7417,9 @@
   void set_instantiations(const Array& value) const;
   RawAbstractType* const* TypeAddr(intptr_t index) const;
   void SetLength(intptr_t value) const;
-  // Number of fields in the raw object=3 (instantiations_, length_ and hash_).
-  static const int kNumFields = 3;
+  // Number of fields in the raw object is 4:
+  // instantiations_, length_, hash_ and nullability_.
+  static const int kNumFields = 4;
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(TypeArguments, Instance);
   friend class AbstractType;
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index d3396a2..0b95138 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -186,6 +186,7 @@
   RW(Code, array_write_barrier_stub)                                           \
   R_(Code, megamorphic_miss_code)                                              \
   R_(Function, megamorphic_miss_function)                                      \
+  RW(Array, dispatch_table_code_entries)                                       \
   RW(Array, code_order_table)                                                  \
   RW(Array, obfuscation_map)                                                   \
   RW(Class, ffi_pointer_class)                                                 \
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index f586e9d..0e09117 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -1136,9 +1136,10 @@
   ASSERT(os_thread != NULL);
   Isolate* isolate = Isolate::Current();
   const char* name = isolate == NULL ? NULL : isolate->name();
-  OS::PrintErr(
-      "version=%s\nthread=%" Pd ", isolate=%s(%p)\n", Version::String(),
-      OSThread::ThreadIdToIntPtr(os_thread->trace_id()), name, isolate);
+  OS::PrintErr("version=%s\npid=%" Pd ", thread=%" Pd ", isolate=%s(%p)\n",
+               Version::String(), OS::ProcessId(),
+               OSThread::ThreadIdToIntPtr(os_thread->trace_id()), name,
+               isolate);
   const IsolateGroupSource* source =
       isolate == nullptr ? nullptr : isolate->source();
   const IsolateGroupSource* vm_source =
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 93ac60e..6bcd99f 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -2220,6 +2220,7 @@
   RawArray* instantiations_;  // Of 3-tuple: 2 instantiators, result.
   RawSmi* length_;
   RawSmi* hash_;
+  RawSmi* nullability_;
 
   // Variable length data follows here.
   RawAbstractType* const* types() const {
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index 7c8cb2d..0576ad0 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -143,6 +143,7 @@
   F(TypeArguments, instantiations_)                                            \
   F(TypeArguments, length_)                                                    \
   F(TypeArguments, hash_)                                                      \
+  F(TypeArguments, nullability_)                                               \
   F(AbstractType, type_test_stub_)                                             \
   F(Type, type_test_stub_)                                                     \
   F(Type, type_class_id_)                                                      \
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index e9c7db7..5821da5 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -848,7 +848,9 @@
   }
 
   bool should_update_cache = true;
-#if !defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
+#if !defined(TARGET_ARCH_IA32)
+  bool would_update_cache_if_not_lazy = false;
+#if !defined(DART_PRECOMPILED_RUNTIME)
   if (mode == kTypeCheckFromLazySpecializeStub) {
     // Checks against type parameters are done by loading the value of the type
     // parameter and calling its type testing stub.
@@ -863,8 +865,15 @@
                    dst_type.ToCString());
     }
     TypeTestingStubGenerator::SpecializeStubFor(thread, dst_type);
-    // Only create the cache when we come from a normal stub.
-    should_update_cache = false;
+
+    // Only create the cache if we failed to create a specialized TTS and doing
+    // the same check would cause an update to the cache.
+    would_update_cache_if_not_lazy =
+        (!src_instance.IsNull() &&
+         dst_type.type_test_stub() ==
+             StubCode::DefaultNullableTypeTest().raw()) ||
+        dst_type.type_test_stub() == StubCode::DefaultTypeTest().raw();
+    should_update_cache = would_update_cache_if_not_lazy && cache.IsNull();
   }
 
   // Fast path of type testing stub wasn't able to handle given type, yet it
@@ -889,12 +898,15 @@
     // Only create the cache when we come from a normal stub.
     should_update_cache = false;
   }
-#endif
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // !defined(TARGET_ARCH_IA32)
 
   if (should_update_cache) {
     if (cache.IsNull()) {
 #if !defined(TARGET_ARCH_IA32)
-      ASSERT(mode == kTypeCheckFromSlowStub);
+      ASSERT(mode == kTypeCheckFromSlowStub ||
+             (mode == kTypeCheckFromLazySpecializeStub &&
+              would_update_cache_if_not_lazy));
       // We lazily create [SubtypeTestCache] for those call sites which actually
       // need one and will patch the pool entry.
       DartFrameIterator iterator(thread,
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 6f1f525..64ba0ee 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -583,7 +583,10 @@
           OS::PrintErr("execution tracing off\n");
         }
       } else if (strcmp(cmd, "bt") == 0) {
+        Thread* thread = reinterpret_cast<Thread*>(sim_->get_register(THR));
+        thread->set_execution_state(Thread::kThreadInVM);
         PrintBacktrace();
+        thread->set_execution_state(Thread::kThreadInGenerated);
       } else {
         OS::PrintErr("Unknown command: %s\n", cmd);
       }
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index 629888e..b1fef2f 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -638,7 +638,10 @@
           OS::PrintErr("execution tracing off\n");
         }
       } else if (strcmp(cmd, "bt") == 0) {
+        Thread* thread = reinterpret_cast<Thread*>(sim_->get_register(THR));
+        thread->set_execution_state(Thread::kThreadInVM);
         PrintBacktrace();
+        thread->set_execution_state(Thread::kThreadInGenerated);
       } else {
         OS::PrintErr("Unknown command: %s\n", cmd);
       }
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 12e21e5..9527073 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -571,9 +571,12 @@
   ASSERT(thread_ != NULL);
   uword exit_marker = thread_->top_exit_frame_info();
   frames_.fp_ = exit_marker;
+  frames_.sp_ = 0;
+  frames_.pc_ = 0;
   if (FLAG_enable_interpreter) {
     frames_.CheckIfInterpreted(exit_marker);
   }
+  frames_.Unpoison();
 }
 
 void StackFrameIterator::SetupNextExitFrameData() {
@@ -589,14 +592,7 @@
   if (FLAG_enable_interpreter) {
     frames_.CheckIfInterpreted(exit_marker);
   }
-}
-
-// Tell MemorySanitizer that generated code initializes part of the stack.
-// TODO(koda): Limit to frames that are actually written by generated code.
-static void UnpoisonStack(uword fp) {
-  ASSERT(fp != 0);
-  uword size = OSThread::GetSpecifiedStackSize();
-  MSAN_UNPOISON(reinterpret_cast<void*>(fp - size), 2 * size);
+  frames_.Unpoison();
 }
 
 StackFrameIterator::StackFrameIterator(ValidationPolicy validation_policy,
@@ -631,6 +627,7 @@
   if (FLAG_enable_interpreter) {
     frames_.CheckIfInterpreted(last_fp);
   }
+  frames_.Unpoison();
 }
 
 StackFrameIterator::StackFrameIterator(uword fp,
@@ -653,6 +650,7 @@
   if (FLAG_enable_interpreter) {
     frames_.CheckIfInterpreted(fp);
   }
+  frames_.Unpoison();
 }
 
 StackFrame* StackFrameIterator::NextFrame() {
@@ -672,7 +670,6 @@
     if (!HasNextFrame()) {
       return NULL;
     }
-    UnpoisonStack(frames_.fp_);
     if (frames_.pc_ == 0) {
       // Iteration starts from an exit frame given by its fp.
       current_frame_ = NextExitFrame();
@@ -721,6 +718,31 @@
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
+// Tell MemorySanitizer that generated code initializes part of the stack.
+void StackFrameIterator::FrameSetIterator::Unpoison() {
+  // When using a simulator, all writes to the stack happened from MSAN
+  // instrumented C++, so there is nothing to unpoison. Additionally,
+  // fp_ will be somewhere in the simulator's stack instead of the OSThread's
+  // stack.
+#if !defined(USING_SIMULATOR)
+  if (fp_ == 0) return;
+  // Note that Thread::os_thread_ is cleared when the thread is descheduled.
+  ASSERT(is_interpreted_ || (thread_->os_thread() == nullptr) ||
+         ((thread_->os_thread()->stack_limit() < fp_) &&
+          (thread_->os_thread()->stack_base() > fp_)));
+  uword lower;
+  if (sp_ == 0) {
+    // Exit frame: guess sp.
+    lower = fp_ - kDartFrameFixedSize * kWordSize;
+  } else {
+    lower = sp_;
+  }
+  uword upper = fp_ + kSavedCallerPcSlotFromFp * kWordSize;
+  // Both lower and upper are inclusive, so we add one word when computing size.
+  MSAN_UNPOISON(reinterpret_cast<void*>(lower), upper - lower + kWordSize);
+#endif  // !defined(USING_SIMULATOR)
+}
+
 StackFrame* StackFrameIterator::FrameSetIterator::NextFrame(bool validate) {
   StackFrame* frame;
   ASSERT(HasNext());
@@ -732,6 +754,7 @@
   sp_ = frame->GetCallerSp();
   fp_ = frame->GetCallerFp();
   pc_ = frame->GetCallerPc();
+  Unpoison();
   ASSERT(is_interpreted_ == frame->is_interpreted_);
   ASSERT(!validate || frame->IsValid());
   return frame;
@@ -745,6 +768,7 @@
   frames_.sp_ = exit_.GetCallerSp();
   frames_.fp_ = exit_.GetCallerFp();
   frames_.pc_ = exit_.GetCallerPc();
+  frames_.Unpoison();
   ASSERT(frames_.is_interpreted_ == exit_.is_interpreted_);
   ASSERT(!validate_ || exit_.IsValid());
   return &exit_;
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index 8427dd2..f430e99 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -315,6 +315,7 @@
           is_interpreted_(false) {}
     bool is_interpreted() const { return is_interpreted_; }
     void CheckIfInterpreted(uword exit_marker);
+    void Unpoison();
 
     uword fp_;
     uword sp_;
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index 14feadb..cd45d72 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -85,7 +85,10 @@
   V(OneArgOptimizedCheckInlineCacheWithExactnessCheck)                         \
   V(EnterSafepoint)                                                            \
   V(ExitSafepoint)                                                             \
-  V(CallNativeThroughSafepoint)
+  V(CallNativeThroughSafepoint)                                                \
+  V(InstantiateTypeArguments)                                                  \
+  V(InstantiateTypeArgumentsMayShareInstantiatorTA)                            \
+  V(InstantiateTypeArgumentsMayShareFunctionTA)
 
 }  // namespace dart
 
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 78b610e..c1b0d03 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -575,7 +575,9 @@
   }
 
   const uword* dispatch_table_array() const { return dispatch_table_array_; }
-  void set_dispatch_table_array(uword* array) { dispatch_table_array_ = array; }
+  void set_dispatch_table_array(const uword* array) {
+    dispatch_table_array_ = array;
+  }
 
   static bool CanLoadFromThread(const Object& object);
   static intptr_t OffsetFromThread(const Object& object);
@@ -881,7 +883,7 @@
   RelaxedAtomic<uword> stack_limit_;
   uword write_barrier_mask_;
   Isolate* isolate_;
-  uword* dispatch_table_array_;
+  const uword* dispatch_table_array_;
   uword top_;
   uword end_;
   // Offsets up to this point can all fit in a byte on X64. All of the above
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 71a54ce..07ac698 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -237,21 +237,19 @@
     compiler::Assembler* assembler,
     HierarchyInfo* hi,
     const Type& type,
-    const Class& type_class,
-    Register instance_reg,
-    Register class_id_reg) {
+    const Class& type_class) {
   // These are handled via the TopTypeTypeTestStub!
   ASSERT(!type.IsTopTypeForAssignability());
 
   // Fast case for 'int'.
   if (type.IsIntType()) {
     compiler::Label non_smi_value;
-    __ BranchIfNotSmi(instance_reg, &non_smi_value);
+    __ BranchIfNotSmi(TypeTestABI::kInstanceReg, &non_smi_value);
     __ Ret();
     __ Bind(&non_smi_value);
   } else if (type.IsDartFunctionType()) {
     compiler::Label continue_checking;
-    __ CompareImmediate(class_id_reg, kClosureCid);
+    __ CompareImmediate(TTSInternalRegs::kScratchReg, kClosureCid);
     __ BranchIf(NOT_EQUAL, &continue_checking);
     __ Ret();
     __ Bind(&continue_checking);
@@ -271,8 +269,7 @@
     const Type& int_type = Type::Handle(Type::IntType());
     const bool smi_is_ok = int_type.IsSubtypeOf(type, Heap::kNew);
 
-    BuildOptimizedSubtypeRangeCheck(assembler, ranges, class_id_reg,
-                                    instance_reg, smi_is_ok);
+    BuildOptimizedSubtypeRangeCheck(assembler, ranges, smi_is_ok);
   } else {
     ASSERT(hi->CanUseGenericSubtypeRangeCheckFor(type));
 
@@ -293,7 +290,7 @@
   if (Instance::NullIsAssignableTo(type)) {
     // Fast case for 'null'.
     compiler::Label non_null;
-    __ CompareObject(instance_reg, Object::null_object());
+    __ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
     __ BranchIf(NOT_EQUAL, &non_null);
     __ Ret();
     __ Bind(&non_null);
@@ -303,20 +300,20 @@
 void TypeTestingStubGenerator::BuildOptimizedSubtypeRangeCheck(
     compiler::Assembler* assembler,
     const CidRangeVector& ranges,
-    Register class_id_reg,
-    Register instance_reg,
     bool smi_is_ok) {
   compiler::Label cid_range_failed, is_subtype;
 
   if (smi_is_ok) {
-    __ LoadClassIdMayBeSmi(class_id_reg, instance_reg);
+    __ LoadClassIdMayBeSmi(TTSInternalRegs::kScratchReg,
+                           TypeTestABI::kInstanceReg);
   } else {
-    __ BranchIfSmi(instance_reg, &cid_range_failed);
-    __ LoadClassId(class_id_reg, instance_reg);
+    __ BranchIfSmi(TypeTestABI::kInstanceReg, &cid_range_failed);
+    __ LoadClassId(TTSInternalRegs::kScratchReg, TypeTestABI::kInstanceReg);
   }
 
   FlowGraphCompiler::GenerateCidRangesCheck(
-      assembler, class_id_reg, ranges, &is_subtype, &cid_range_failed, true);
+      assembler, TTSInternalRegs::kScratchReg, ranges, &is_subtype,
+      &cid_range_failed, true);
   __ Bind(&is_subtype);
   __ Ret();
   __ Bind(&cid_range_failed);
@@ -329,23 +326,19 @@
         const Type& type,
         const Class& type_class,
         const TypeArguments& tp,
-        const TypeArguments& ta,
-        const Register class_id_reg,
-        const Register instance_reg,
-        const Register instance_type_args_reg) {
+        const TypeArguments& ta) {
   // a) First we make a quick sub*class* cid-range check.
   compiler::Label check_failed;
   ASSERT(!type_class.is_implemented());
   const CidRangeVector& ranges = hi->SubclassRangesForClass(type_class);
-  BuildOptimizedSubclassRangeCheck(assembler, ranges, class_id_reg,
-                                   instance_reg, &check_failed);
+  BuildOptimizedSubclassRangeCheck(assembler, ranges, &check_failed);
   // fall through to continue
 
   // b) Then we'll load the values for the type parameters.
   __ LoadField(
-      instance_type_args_reg,
+      TTSInternalRegs::kInstanceTypeArgumentsReg,
       compiler::FieldAddress(
-          instance_reg,
+          TypeTestABI::kInstanceReg,
           compiler::target::Class::TypeArgumentsFieldOffset(type_class)));
 
   // The kernel frontend should fill in any non-assigned type parameters on
@@ -355,7 +348,8 @@
   // TODO(kustermann): We could consider not using "null" as type argument
   // vector representing all-dynamic to avoid this extra check (which will be
   // uncommon because most Dart code in 2.0 will be strongly typed)!
-  __ CompareObject(instance_type_args_reg, Object::null_object());
+  __ CompareObject(TTSInternalRegs::kInstanceTypeArgumentsReg,
+                   Object::null_object());
   const Type& rare_type = Type::Handle(Type::RawCast(type_class.RareType()));
   if (rare_type.IsSubtypeOf(type, Heap::kNew)) {
     compiler::Label process_done;
@@ -391,14 +385,14 @@
 void TypeTestingStubGenerator::BuildOptimizedSubclassRangeCheck(
     compiler::Assembler* assembler,
     const CidRangeVector& ranges,
-    Register class_id_reg,
-    Register instance_reg,
     compiler::Label* check_failed) {
-  __ LoadClassIdMayBeSmi(class_id_reg, instance_reg);
+  __ LoadClassIdMayBeSmi(TTSInternalRegs::kScratchReg,
+                         TypeTestABI::kInstanceReg);
 
   compiler::Label is_subtype;
-  FlowGraphCompiler::GenerateCidRangesCheck(assembler, class_id_reg, ranges,
-                                            &is_subtype, check_failed, true);
+  FlowGraphCompiler::GenerateCidRangesCheck(
+      assembler, TTSInternalRegs::kScratchReg, ranges, &is_subtype,
+      check_failed, true);
   __ Bind(&is_subtype);
 }
 
@@ -409,40 +403,34 @@
     HierarchyInfo* hi,
     const AbstractType& type_arg,
     intptr_t type_param_value_offset_i,
-    const Register class_id_reg,
-    const Register instance_type_args_reg,
-    const Register instantiator_type_args_reg,
-    const Register function_type_args_reg,
-    const Register own_type_arg_reg,
     compiler::Label* check_failed) {
   if (type_arg.IsTopType()) {
     return;
   }
-  // TODO(dartbug.com/40736): Even though it should be safe to use TMP here,
-  //  we should avoid using TMP outside the assembler. Try to find a free
-  //  register to use here!
-  __ LoadField(TMP, compiler::FieldAddress(
-                        instance_type_args_reg,
-                        compiler::target::TypeArguments::type_at_offset(
-                            type_param_value_offset_i)));
-  __ LoadField(class_id_reg,
-               compiler::FieldAddress(
-                   TMP, compiler::target::Type::type_class_id_offset()));
 
+  // If the upper bound is a type parameter and its value is "dynamic"
+  // we always succeed.
+  compiler::Label is_dynamic;
   if (type_arg.IsTypeParameter()) {
     const TypeParameter& type_param = TypeParameter::Cast(type_arg);
-    const Register kTypeArgumentsReg = type_param.IsClassTypeParameter()
-                                           ? instantiator_type_args_reg
-                                           : function_type_args_reg;
+    const Register kTypeArgumentsReg =
+        type_param.IsClassTypeParameter()
+            ? TypeTestABI::kInstantiatorTypeArgumentsReg
+            : TypeTestABI::kFunctionTypeArgumentsReg;
+
+    __ CompareObject(kTypeArgumentsReg, Object::null_object());
+    __ BranchIf(EQUAL, &is_dynamic);
+
     __ LoadField(
-        own_type_arg_reg,
+        TTSInternalRegs::kScratchReg,
         compiler::FieldAddress(kTypeArgumentsReg,
                                compiler::target::TypeArguments::type_at_offset(
                                    type_param.index())));
     __ CompareWithFieldValue(
-        class_id_reg,
-        compiler::FieldAddress(own_type_arg_reg,
-                               compiler::target::Type::type_class_id_offset()));
+        TTSInternalRegs::kScratchReg,
+        compiler::FieldAddress(TTSInternalRegs::kInstanceTypeArgumentsReg,
+                               compiler::target::TypeArguments::type_at_offset(
+                                   type_param_value_offset_i)));
     __ BranchIf(NOT_EQUAL, check_failed);
   } else {
     const Class& type_class = Class::Handle(type_arg.type_class());
@@ -451,55 +439,47 @@
         /*include_abstract=*/true,
         /*exclude_null=*/!Instance::NullIsAssignableTo(type_arg));
 
-    compiler::Label is_subtype;
-    __ SmiUntag(class_id_reg);
-    FlowGraphCompiler::GenerateCidRangesCheck(assembler, class_id_reg, ranges,
-                                              &is_subtype, check_failed, true);
-    __ Bind(&is_subtype);
-  }
-
-  // Weak NNBD mode uses LEGACY_SUBTYPE which ignores nullability.
-  // We don't need to check nullability of LHS for nullable and legacy RHS
-  // ("Right Legacy", "Right Nullable" rules).
-  if (FLAG_null_safety && !type_arg.IsNullable() && !type_arg.IsLegacy()) {
-    compiler::Label skip_nullable_check;
-    if (type_arg.IsTypeParameter()) {
-      // Skip the nullability check if actual RHS is nullable or legacy.
-      // TODO(dartbug.com/40736): Allocate register for own_type_arg_reg
-      //  which is not clobbered and avoid reloading own_type_arg_reg.
-      //  Currently own_type_arg_reg == TMP on certain
-      //  architectures and it is clobbered by CompareWithFieldValue.
-      const TypeParameter& type_param = TypeParameter::Cast(type_arg);
-      const Register kTypeArgumentsReg = type_param.IsClassTypeParameter()
-                                             ? instantiator_type_args_reg
-                                             : function_type_args_reg;
-      __ LoadField(own_type_arg_reg,
-                   compiler::FieldAddress(
-                       kTypeArgumentsReg,
-                       compiler::target::TypeArguments::type_at_offset(
-                           type_param.index())));
-      __ CompareTypeNullabilityWith(
-          own_type_arg_reg, compiler::target::Nullability::kNonNullable);
-      __ BranchIf(NOT_EQUAL, &skip_nullable_check);
-    }
-
-    // Nullable type is not a subtype of non-nullable type.
-    // TODO(dartbug.com/40736): allocate a register for instance type argument
-    //  and avoid reloading it. Note that class_id_reg == TMP on certain
-    //  architectures.
     __ LoadField(
-        class_id_reg,
-        compiler::FieldAddress(instance_type_args_reg,
+        TTSInternalRegs::kScratchReg,
+        compiler::FieldAddress(TTSInternalRegs::kInstanceTypeArgumentsReg,
                                compiler::target::TypeArguments::type_at_offset(
                                    type_param_value_offset_i)));
-    __ CompareTypeNullabilityWith(class_id_reg,
-                                  compiler::target::Nullability::kNullable);
-    __ BranchIf(EQUAL, check_failed);
+    __ LoadField(
+        TTSInternalRegs::kScratchReg,
+        compiler::FieldAddress(TTSInternalRegs::kScratchReg,
+                               compiler::target::Type::type_class_id_offset()));
 
-    if (type_arg.IsTypeParameter()) {
-      __ Bind(&skip_nullable_check);
+    compiler::Label is_subtype;
+    __ SmiUntag(TTSInternalRegs::kScratchReg);
+    FlowGraphCompiler::GenerateCidRangesCheck(
+        assembler, TTSInternalRegs::kScratchReg, ranges, &is_subtype,
+        check_failed, true);
+    __ Bind(&is_subtype);
+
+    // Weak NNBD mode uses LEGACY_SUBTYPE which ignores nullability.
+    // We don't need to check nullability of LHS for nullable and legacy RHS
+    // ("Right Legacy", "Right Nullable" rules).
+    if (FLAG_null_safety && !type_arg.IsNullable() && !type_arg.IsLegacy()) {
+      compiler::Label skip_nullable_check;
+      // Nullable type is not a subtype of non-nullable type.
+      // TODO(dartbug.com/40736): Allocate a register for instance type argument
+      // and avoid reloading it.
+      __ LoadField(TTSInternalRegs::kScratchReg,
+                   compiler::FieldAddress(
+                       TTSInternalRegs::kInstanceTypeArgumentsReg,
+                       compiler::target::TypeArguments::type_at_offset(
+                           type_param_value_offset_i)));
+      __ CompareTypeNullabilityWith(TTSInternalRegs::kScratchReg,
+                                    compiler::target::Nullability::kNullable);
+      __ BranchIf(EQUAL, check_failed);
+
+      if (type_arg.IsTypeParameter()) {
+        __ Bind(&skip_nullable_check);
+      }
     }
   }
+
+  __ Bind(&is_dynamic);
 }
 
 void RegisterTypeArgumentsUse(const Function& function,
diff --git a/runtime/vm/type_testing_stubs.h b/runtime/vm/type_testing_stubs.h
index c7274c1..fa9bb07 100644
--- a/runtime/vm/type_testing_stubs.h
+++ b/runtime/vm/type_testing_stubs.h
@@ -63,14 +63,10 @@
       compiler::Assembler* assembler,
       HierarchyInfo* hi,
       const Type& type,
-      const Class& type_class,
-      Register instance_reg,
-      Register class_id_reg);
+      const Class& type_class);
 
   static void BuildOptimizedSubtypeRangeCheck(compiler::Assembler* assembler,
                                               const CidRangeVector& ranges,
-                                              Register class_id_reg,
-                                              Register instance_reg,
                                               bool smi_is_ok);
 
   static void BuildOptimizedSubclassRangeCheckWithTypeArguments(
@@ -89,13 +85,10 @@
       const TypeArguments& type_parameters,
       const TypeArguments& type_arguments,
       const Register class_id_reg,
-      const Register instance_reg,
       const Register instance_type_args_reg);
 
   static void BuildOptimizedSubclassRangeCheck(compiler::Assembler* assembler,
                                                const CidRangeVector& ranges,
-                                               Register class_id_reg,
-                                               Register instance_reg,
                                                compiler::Label* check_failed);
 
   static void BuildOptimizedTypeArgumentValueCheck(
@@ -105,18 +98,6 @@
       intptr_t type_param_value_offset_i,
       compiler::Label* check_failed);
 
-  static void BuildOptimizedTypeArgumentValueCheck(
-      compiler::Assembler* assembler,
-      HierarchyInfo* hi,
-      const AbstractType& type_arg,
-      intptr_t type_param_value_offset_i,
-      const Register class_id_reg,
-      const Register instance_type_args_reg,
-      const Register instantiator_type_args_reg,
-      const Register function_type_args_reg,
-      const Register type_arg_reg,
-      compiler::Label* check_failed);
-
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 #endif  // !defined(TARGET_ARCH_IA32)
 
diff --git a/runtime/vm/type_testing_stubs_arm.cc b/runtime/vm/type_testing_stubs_arm.cc
index 8e49e28..6b176ce 100644
--- a/runtime/vm/type_testing_stubs_arm.cc
+++ b/runtime/vm/type_testing_stubs_arm.cc
@@ -17,11 +17,7 @@
     HierarchyInfo* hi,
     const Type& type,
     const Class& type_class) {
-  const Register kInstanceReg = R0;
-  const Register kClassIdReg = R9;
-
-  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
-                                      kInstanceReg, kClassIdReg);
+  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class);
 
   __ ldr(CODE_REG,
          compiler::Address(
@@ -30,42 +26,6 @@
       CODE_REG, compiler::target::Code::entry_point_offset()));
 }
 
-void TypeTestingStubGenerator::
-    BuildOptimizedSubclassRangeCheckWithTypeArguments(
-        compiler::Assembler* assembler,
-        HierarchyInfo* hi,
-        const Type& type,
-        const Class& type_class,
-        const TypeArguments& tp,
-        const TypeArguments& ta) {
-  const Register kInstanceReg = R0;
-  const Register kInstanceTypeArguments = R4;
-  const Register kClassIdReg = R9;
-
-  BuildOptimizedSubclassRangeCheckWithTypeArguments(
-      assembler, hi, type, type_class, tp, ta, kClassIdReg, kInstanceReg,
-      kInstanceTypeArguments);
-}
-
-void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck(
-    compiler::Assembler* assembler,
-    HierarchyInfo* hi,
-    const AbstractType& type_arg,
-    intptr_t type_param_value_offset_i,
-    compiler::Label* check_failed) {
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
-  const Register kInstanceTypeArguments = R4;
-
-  const Register kClassIdReg = R9;
-  const Register kOwnTypeArgumentValue = TMP;
-
-  BuildOptimizedTypeArgumentValueCheck(
-      assembler, hi, type_arg, type_param_value_offset_i, kClassIdReg,
-      kInstanceTypeArguments, kInstantiatorTypeArgumentsReg,
-      kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
-}
-
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_ARM) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/type_testing_stubs_arm64.cc b/runtime/vm/type_testing_stubs_arm64.cc
index 3e04361..bc2df7f 100644
--- a/runtime/vm/type_testing_stubs_arm64.cc
+++ b/runtime/vm/type_testing_stubs_arm64.cc
@@ -17,11 +17,7 @@
     HierarchyInfo* hi,
     const Type& type,
     const Class& type_class) {
-  const Register kInstanceReg = R0;
-  const Register kClassIdReg = R9;
-
-  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
-                                      kInstanceReg, kClassIdReg);
+  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class);
 
   __ ldr(CODE_REG,
          compiler::Address(THR, Thread::slow_type_test_stub_offset()));
@@ -29,42 +25,6 @@
   __ br(R9);
 }
 
-void TypeTestingStubGenerator::
-    BuildOptimizedSubclassRangeCheckWithTypeArguments(
-        compiler::Assembler* assembler,
-        HierarchyInfo* hi,
-        const Type& type,
-        const Class& type_class,
-        const TypeArguments& tp,
-        const TypeArguments& ta) {
-  const Register kInstanceReg = R0;
-  const Register kInstanceTypeArguments = R7;
-  const Register kClassIdReg = R9;
-
-  BuildOptimizedSubclassRangeCheckWithTypeArguments(
-      assembler, hi, type, type_class, tp, ta, kClassIdReg, kInstanceReg,
-      kInstanceTypeArguments);
-}
-
-void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck(
-    compiler::Assembler* assembler,
-    HierarchyInfo* hi,
-    const AbstractType& type_arg,
-    intptr_t type_param_value_offset_i,
-    compiler::Label* check_failed) {
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
-  const Register kInstanceTypeArguments = R7;
-
-  const Register kClassIdReg = R9;
-  const Register kOwnTypeArgumentValue = TMP;
-
-  BuildOptimizedTypeArgumentValueCheck(
-      assembler, hi, type_arg, type_param_value_offset_i, kClassIdReg,
-      kInstanceTypeArguments, kInstantiatorTypeArgumentsReg,
-      kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
-}
-
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_ARM64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/type_testing_stubs_test.cc b/runtime/vm/type_testing_stubs_test.cc
new file mode 100644
index 0000000..fccb41e
--- /dev/null
+++ b/runtime/vm/type_testing_stubs_test.cc
@@ -0,0 +1,651 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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 <functional>
+
+#include "platform/assert.h"
+
+#include "vm/class_finalizer.h"
+#include "vm/compiler/backend/il_test_helper.h"
+#include "vm/symbols.h"
+#include "vm/type_testing_stubs.h"
+#include "vm/type_testing_stubs_test.h"
+#include "vm/unit_test.h"
+
+#if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM) ||                  \
+    defined(TARGET_ARCH_X64)
+
+namespace dart {
+
+static void FinalizeAndCanonicalize(const Class& klass, AbstractType* type) {
+  *type = ClassFinalizer::FinalizeType(klass, *type);
+  ASSERT(type->IsCanonical());
+}
+
+static void CanonicalizeTAV(TypeArguments* tav) {
+  *tav = tav->Canonicalize();
+}
+
+static void RunTTSTest(
+    const Object& instance,
+    const AbstractType& dst_type,
+    const TypeArguments& instantiator_tav,
+    const TypeArguments& function_tav,
+    std::function<void(const Object& result, const SubtypeTestCache& stc)> lazy,
+    std::function<void(const Object& result,
+                       const SubtypeTestCache& stc,
+                       const Bool& abi_regs_modified,
+                       const Bool& rest_regs_modified)> nonlazy) {
+  ASSERT(instantiator_tav.IsNull() || instantiator_tav.IsCanonical());
+  ASSERT(function_tav.IsNull() || function_tav.IsCanonical());
+  auto thread = Thread::Current();
+
+  // Build a stub which will do calling conversion to call TTS stubs.
+  const auto& klass =
+      Class::Handle(thread->isolate()->class_table()->At(kInstanceCid));
+  const auto& symbol = String::Handle(
+      Symbols::New(thread, OS::SCreate(thread->zone(), "TTSTest")));
+  const auto& function = Function::Handle(
+      Function::New(symbol, RawFunction::kRegularFunction, false, false, false,
+                    false, false, klass, TokenPosition::kNoSource));
+  compiler::ObjectPoolBuilder pool_builder;
+  const auto& invoke_tts = Code::Handle(
+      StubCode::Generate("InvokeTTS", &pool_builder, &GenerateInvokeTTSStub));
+  const auto& pool =
+      ObjectPool::Handle(ObjectPool::NewFromBuilder(pool_builder));
+  invoke_tts.set_object_pool(pool.raw());
+  invoke_tts.set_owner(function);
+  invoke_tts.set_exception_handlers(
+      ExceptionHandlers::Handle(ExceptionHandlers::New(0)));
+
+  EXPECT(pool.Length() == 2);
+  const intptr_t kSubtypeTestCacheIndex = 0;
+
+  const auto& arguments_descriptor =
+      Array::Handle(ArgumentsDescriptor::NewBoxed(0, 6));
+  const auto& arguments = Array::Handle(Array::New(6));
+  const auto& abi_regs_modified_box = Array::Handle(Array::New(1));
+  const auto& rest_regs_modified_box = Array::Handle(Array::New(1));
+  arguments.SetAt(0, abi_regs_modified_box);
+  arguments.SetAt(1, rest_regs_modified_box);
+  arguments.SetAt(2, instance);
+  arguments.SetAt(3, instantiator_tav);
+  arguments.SetAt(4, function_tav);
+  arguments.SetAt(5, dst_type);
+
+  // Ensure we have a) uninitialized TTS b) no/empty SubtypeTestCache.
+  dst_type.SetTypeTestingStub(StubCode::LazySpecializeTypeTest());
+  EXPECT(dst_type.type_test_stub() == StubCode::LazySpecializeTypeTest().raw());
+  EXPECT(pool.ObjectAt(kSubtypeTestCacheIndex) == Object::null());
+
+  auto& result = Object::Handle();
+  auto& result2 = Object::Handle();
+  auto& abi_regs_modified = Bool::Handle();
+  auto& rest_regs_modified = Bool::Handle();
+  auto& tts = Code::Handle();
+  auto& tts2 = Code::Handle();
+  auto& stc = SubtypeTestCache::Handle();
+  auto& stc2 = SubtypeTestCache::Handle();
+
+  // First invocation will a) specialize the TTS b) may create SubtypeTestCache
+  result = DartEntry::InvokeCode(invoke_tts, arguments_descriptor, arguments,
+                                 thread);
+  stc ^= pool.ObjectAt(kSubtypeTestCacheIndex);
+  tts = dst_type.type_test_stub();
+  if (!result.IsError()) {
+    EXPECT(tts.raw() != StubCode::LazySpecializeTypeTest().raw());
+  }
+  lazy(result, stc);
+
+  // Second invocation will a) keep TTS b) keep optional SubtypeTestCache
+  result2 = DartEntry::InvokeCode(invoke_tts, arguments_descriptor, arguments,
+                                  thread);
+  stc2 ^= pool.ObjectAt(kSubtypeTestCacheIndex);
+  tts2 = dst_type.type_test_stub();
+  abi_regs_modified ^= abi_regs_modified_box.At(0);
+  rest_regs_modified ^= rest_regs_modified_box.At(0);
+  EXPECT(result2.IsError() || !abi_regs_modified.IsNull());
+  EXPECT(tts2.raw() == tts.raw());
+  EXPECT(stc2.raw() == stc.raw());
+  nonlazy(result2, stc2, abi_regs_modified, rest_regs_modified);
+
+  // Third invocation will a) explicitly install TTS beforehand b) keep optional
+  // SubtypeTestCache
+  // (This is to simulate AOT where we don't use lazy specialization but
+  // precompile the TTS)
+  auto& dst_type_to_specialize = AbstractType::Handle(dst_type.raw());
+  if (dst_type_to_specialize.IsTypeParameter()) {
+    dst_type_to_specialize = TypeParameter::Cast(dst_type).GetFromTypeArguments(
+        instantiator_tav, function_tav);
+  }
+  TypeTestingStubGenerator::SpecializeStubFor(thread, dst_type_to_specialize);
+  tts = dst_type.type_test_stub();
+
+  result2 = DartEntry::InvokeCode(invoke_tts, arguments_descriptor, arguments,
+                                  thread);
+  stc2 ^= pool.ObjectAt(kSubtypeTestCacheIndex);
+  tts2 = dst_type.type_test_stub();
+  abi_regs_modified ^= abi_regs_modified_box.At(0);
+  rest_regs_modified ^= rest_regs_modified_box.At(0);
+  EXPECT(result2.IsError() || !abi_regs_modified.IsNull());
+  EXPECT(tts2.raw() == tts.raw());
+  EXPECT(stc2.raw() == stc.raw());
+  nonlazy(result2, stc2, abi_regs_modified, rest_regs_modified);
+}
+
+static void ExpectLazilyHandledViaTTS(const Object& result,
+                                      const SubtypeTestCache& stc) {
+  // Ensure the type test succeeded.
+  EXPECT(result.IsNull());
+  // Ensure we didn't fall back to the subtype test cache.
+  EXPECT(stc.IsNull());
+}
+
+static void ExpectHandledViaTTS(const Object& result,
+                                const SubtypeTestCache& stc,
+                                const Bool& abi_regs_modified,
+                                const Bool& rest_regs_modified) {
+  ExpectLazilyHandledViaTTS(result, stc);
+  // Ensure the TTS abi registers were preserved.
+  EXPECT(!abi_regs_modified.value());
+  // Ensure the non-TTS abi registers were preserved.
+  EXPECT(!rest_regs_modified.value());
+}
+
+static void ExpectLazilyHandledViaSTC(const Object& result,
+                                      const SubtypeTestCache& stc) {
+  // Ensure the type test succeeded.
+  EXPECT(result.IsNull());
+  // Ensure we did fall back to the subtype test cache.
+  EXPECT(!stc.IsNull());
+  // Ensure the test is marked as succeeding in the STC.
+  EXPECT(stc.NumberOfChecks() == 1);
+  SubtypeTestCacheTable entries(Array::Handle(stc.cache()));
+  EXPECT(entries[0].Get<SubtypeTestCache::kTestResult>() ==
+         Object::bool_true().raw());
+}
+
+static void ExpectHandledViaSTC(const Object& result,
+                                const SubtypeTestCache& stc,
+                                const Bool& abi_regs_modified,
+                                const Bool& rest_regs_modified) {
+  ExpectLazilyHandledViaSTC(result, stc);
+  // Ensure the TTS/STC abi registers were preserved.
+  EXPECT(!abi_regs_modified.value());
+}
+
+static void ExpectLazilyFailedViaTTS(const Object& result,
+                                     const SubtypeTestCache& stc) {
+  // Ensure we have not updated STC (which we shouldn't do in case the type test
+  // fails, i.e. an exception is thrown).
+  EXPECT(stc.IsNull());
+  // Ensure we get a proper exception for the type test.
+  EXPECT(result.IsUnhandledException());
+  const auto& error =
+      Instance::Handle(UnhandledException::Cast(result).exception());
+  EXPECT(strstr(error.ToCString(), "_TypeError"));
+}
+
+static void ExpectFailedViaTTS(const Object& result,
+                               const SubtypeTestCache& stc,
+                               const Bool& abi_regs_modified,
+                               const Bool& rest_regs_modified) {
+  ExpectLazilyFailedViaTTS(result, stc);
+}
+
+static void ExpectLazilyFailedViaSTC(const Object& result,
+                                     const SubtypeTestCache& stc) {
+  // Ensure we have not updated STC (which we shouldn't do in case the type test
+  // fails, i.e. an exception is thrown).
+  EXPECT(stc.IsNull());
+  // Ensure we get a proper exception for the type test.
+  EXPECT(result.IsUnhandledException());
+  const auto& error =
+      Instance::Handle(UnhandledException::Cast(result).exception());
+  EXPECT(strstr(error.ToCString(), "_TypeError"));
+}
+
+static void ExpectFailedViaSTC(const Object& result,
+                               const SubtypeTestCache& stc,
+                               const Bool& abi_regs_modified,
+                               const Bool& rest_regs_modified) {
+  ExpectLazilyFailedViaSTC(result, stc);
+}
+
+const char* kSubtypeRangeCheckScript =
+    R"(
+      class I<T, U> {}
+      class I2 {}
+
+      class Base<T> {}
+
+      class A extends Base<int> {}
+      class A1 extends A implements I2 {}
+      class A2<T> extends A implements I<int, T> {}
+
+      class B extends Base<String> {}
+      class B1 extends B implements I2 {}
+      class B2<T> extends B implements I<T, String> {}
+
+      genericFun<A, B>() {}
+
+      createI() => I<int, String>();
+      createI2() => I2();
+      createBaseInt() => Base<int>();
+      createA() => A();
+      createA1() => A1();
+      createA2() => A2<int>();
+      createB() => B();
+      createB1() => B1();
+      createB2() => B2<int>();
+      createBaseIStringDouble() => Base<I<String, double>>();
+      createBaseA2Int() => Base<A2<int>>();
+      createBaseA2A1() => Base<A2<A1>>();
+      createBaseB2Int() => Base<B2<int>>();
+)";
+
+ISOLATE_UNIT_TEST_CASE(TTS_SubtypeRangeCheck) {
+  const auto& root_library =
+      Library::Handle(LoadTestScript(kSubtypeRangeCheckScript));
+  const auto& class_a = Class::Handle(GetClass(root_library, "A"));
+  const auto& class_base = Class::Handle(GetClass(root_library, "Base"));
+  const auto& class_i = Class::Handle(GetClass(root_library, "I"));
+  const auto& class_i2 = Class::Handle(GetClass(root_library, "I2"));
+  const auto& class_null = Class::Handle(Class::null());
+
+  const auto& obj_i = Object::Handle(Invoke(root_library, "createI"));
+  const auto& obj_i2 = Object::Handle(Invoke(root_library, "createI2"));
+  const auto& obj_baseint =
+      Object::Handle(Invoke(root_library, "createBaseInt"));
+  const auto& obj_a = Object::Handle(Invoke(root_library, "createA"));
+  const auto& obj_a1 = Object::Handle(Invoke(root_library, "createA1"));
+  const auto& obj_a2 = Object::Handle(Invoke(root_library, "createA2"));
+  const auto& obj_b = Object::Handle(Invoke(root_library, "createB"));
+  const auto& obj_b1 = Object::Handle(Invoke(root_library, "createB1"));
+  const auto& obj_b2 = Object::Handle(Invoke(root_library, "createB2"));
+
+  const auto& type_dynamic = Type::Handle(Type::DynamicType());
+  auto& type_object = Type::Handle(Type::ObjectType());
+  type_object = type_object.ToNullability(Nullability::kNullable, Heap::kNew);
+
+  const auto& tav_null = TypeArguments::Handle(TypeArguments::null());
+
+  auto& tav_object = TypeArguments::Handle(TypeArguments::New(1));
+  tav_object.SetTypeAt(0, type_object);
+  CanonicalizeTAV(&tav_object);
+
+  auto& tav_object_dynamic = TypeArguments::Handle(TypeArguments::New(2));
+  tav_object_dynamic.SetTypeAt(0, type_object);
+  tav_object_dynamic.SetTypeAt(1, type_dynamic);
+  CanonicalizeTAV(&tav_object_dynamic);
+
+  auto& tav_dynamic_t = TypeArguments::Handle(TypeArguments::New(2));
+  tav_dynamic_t.SetTypeAt(0, type_dynamic);
+  tav_dynamic_t.SetTypeAt(
+      1, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
+  CanonicalizeTAV(&tav_dynamic_t);
+
+  // We will generate specialized TTS for instantiated interface types
+  // where there are no type arguments or the type arguments are top
+  // types.
+  //
+  //   obj as A                  // Subclass ranges
+  //   obj as Base<Object>       // Subclass ranges with top-type tav
+  //   obj as I2                 // Subtype ranges
+  //   obj as I<Object, dynamic> // Subtype ranges with top-type tav
+  //
+
+  // <...> as A
+  const auto& type_a = AbstractType::Handle(class_a.RareType());
+  RunTTSTest(obj_i, type_a, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_i2, type_a, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_baseint, type_a, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_a, type_a, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_a1, type_a, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_a2, type_a, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_b, type_a, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_b1, type_a, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_b2, type_a, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+
+  // <...> as Base<Object>
+  auto& type_base = AbstractType::Handle(
+      Type::New(class_base, tav_object, TokenPosition::kNoSource));
+  FinalizeAndCanonicalize(class_null, &type_base);
+  RunTTSTest(obj_i, type_base, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_i2, type_base, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_baseint, type_base, tav_null, tav_null,
+             ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  RunTTSTest(obj_a, type_base, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_a1, type_base, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_a2, type_base, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_b, type_base, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_b1, type_base, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_b2, type_base, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+
+  // <...> as I2
+  const auto& type_i2 = AbstractType::Handle(class_i2.RareType());
+  RunTTSTest(obj_i, type_i2, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_i2, type_i2, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_baseint, type_i2, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_a, type_i2, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_a1, type_i2, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_a2, type_i2, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_b, type_i2, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+  RunTTSTest(obj_b1, type_i2, tav_null, tav_null, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+  RunTTSTest(obj_b2, type_i2, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+
+  // <...> as I<Object, dynamic>
+  auto& type_i_object_dynamic = AbstractType::Handle(
+      Type::New(class_i, tav_object_dynamic, TokenPosition::kNoSource));
+  FinalizeAndCanonicalize(class_null, &type_i_object_dynamic);
+  RunTTSTest(obj_i, type_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  RunTTSTest(obj_i2, type_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_baseint, type_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_a, type_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_a1, type_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_a2, type_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  RunTTSTest(obj_b, type_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_b1, type_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_b2, type_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+
+  // We do not generate TTS for uninstantiated types if we would need to use
+  // subtype range checks for the class of the interface type.
+  //
+  //   obj as I<dynamic, T>
+  //
+  auto& type_dynamic_t = AbstractType::Handle(
+      Type::New(class_i, tav_dynamic_t, TokenPosition::kNoSource));
+  FinalizeAndCanonicalize(class_base, &type_dynamic_t);
+  RunTTSTest(obj_i, type_dynamic_t, tav_object, tav_null,
+             ExpectLazilyHandledViaSTC, ExpectHandledViaSTC);
+  RunTTSTest(obj_i2, type_dynamic_t, tav_object, tav_null,
+             ExpectLazilyFailedViaSTC, ExpectFailedViaSTC);
+  RunTTSTest(obj_baseint, type_dynamic_t, tav_object, tav_null,
+             ExpectLazilyFailedViaSTC, ExpectFailedViaSTC);
+  RunTTSTest(obj_a, type_dynamic_t, tav_object, tav_null,
+             ExpectLazilyFailedViaSTC, ExpectFailedViaSTC);
+  RunTTSTest(obj_a1, type_dynamic_t, tav_object, tav_null,
+             ExpectLazilyFailedViaSTC, ExpectFailedViaSTC);
+  RunTTSTest(obj_a2, type_dynamic_t, tav_object, tav_null,
+             ExpectLazilyHandledViaSTC, ExpectHandledViaSTC);
+  RunTTSTest(obj_b, type_dynamic_t, tav_object, tav_null,
+             ExpectLazilyFailedViaSTC, ExpectFailedViaSTC);
+  RunTTSTest(obj_b1, type_dynamic_t, tav_object, tav_null,
+             ExpectLazilyFailedViaSTC, ExpectFailedViaSTC);
+  RunTTSTest(obj_b2, type_dynamic_t, tav_object, tav_null,
+             ExpectLazilyHandledViaSTC, ExpectHandledViaSTC);
+}
+
+ISOLATE_UNIT_TEST_CASE(TTS_GenericSubtypeRangeCheck) {
+  const auto& root_library =
+      Library::Handle(LoadTestScript(kSubtypeRangeCheckScript));
+  const auto& class_a1 = Class::Handle(GetClass(root_library, "A1"));
+  const auto& class_a2 = Class::Handle(GetClass(root_library, "A2"));
+  const auto& class_base = Class::Handle(GetClass(root_library, "Base"));
+  const auto& class_i = Class::Handle(GetClass(root_library, "I"));
+  const auto& fun_generic =
+      Function::Handle(GetFunction(root_library, "genericFun"));
+  const auto& class_null = Class::Handle(Class::null());
+
+  const auto& obj_i = Object::Handle(Invoke(root_library, "createI"));
+  const auto& obj_i2 = Object::Handle(Invoke(root_library, "createI2"));
+  const auto& obj_baseint =
+      Object::Handle(Invoke(root_library, "createBaseInt"));
+  const auto& obj_a = Object::Handle(Invoke(root_library, "createA"));
+  const auto& obj_a1 = Object::Handle(Invoke(root_library, "createA1"));
+  const auto& obj_a2 = Object::Handle(Invoke(root_library, "createA2"));
+  const auto& obj_b = Object::Handle(Invoke(root_library, "createB"));
+  const auto& obj_b1 = Object::Handle(Invoke(root_library, "createB1"));
+  const auto& obj_b2 = Object::Handle(Invoke(root_library, "createB2"));
+  const auto& obj_basea2int =
+      Object::Handle(Invoke(root_library, "createBaseA2Int"));
+  const auto& obj_basea2a1 =
+      Object::Handle(Invoke(root_library, "createBaseA2A1"));
+  const auto& obj_baseb2int =
+      Object::Handle(Invoke(root_library, "createBaseB2Int"));
+  const auto& obj_baseistringdouble =
+      Object::Handle(Invoke(root_library, "createBaseIStringDouble"));
+
+  const auto& type_dynamic = Type::Handle(Type::DynamicType());
+  auto& type_int = Type::Handle(Type::IntType());
+  type_int = type_int.ToNullability(Nullability::kLegacy, Heap::kNew);
+  auto& type_string = Type::Handle(Type::StringType());
+  type_string = type_string.ToNullability(Nullability::kLegacy, Heap::kNew);
+  auto& type_object = Type::Handle(Type::ObjectType());
+  type_object = type_object.ToNullability(Nullability::kLegacy, Heap::kNew);
+  auto& type_a1 = Type::Handle(class_a1.DeclarationType());
+  type_a1 = type_a1.ToNullability(Nullability::kLegacy, Heap::kNew);
+  FinalizeAndCanonicalize(class_null, &type_a1);
+
+  const auto& tav_null = TypeArguments::Handle(TypeArguments::null());
+
+  auto& tav_object_dynamic = TypeArguments::Handle(TypeArguments::New(2));
+  tav_object_dynamic.SetTypeAt(0, type_object);
+  tav_object_dynamic.SetTypeAt(1, type_dynamic);
+  CanonicalizeTAV(&tav_object_dynamic);
+
+  auto& tav_dynamic_int = TypeArguments::Handle(TypeArguments::New(2));
+  tav_dynamic_int.SetTypeAt(0, type_dynamic);
+  tav_dynamic_int.SetTypeAt(1, type_int);
+  CanonicalizeTAV(&tav_dynamic_int);
+
+  auto& tav_dynamic_string = TypeArguments::Handle(TypeArguments::New(2));
+  tav_dynamic_string.SetTypeAt(0, type_dynamic);
+  tav_dynamic_string.SetTypeAt(1, type_string);
+  CanonicalizeTAV(&tav_dynamic_string);
+
+  auto& tav_int = TypeArguments::Handle(TypeArguments::New(1));
+  tav_int.SetTypeAt(0, type_int);
+  CanonicalizeTAV(&tav_int);
+
+  auto& type_i_object_dynamic = AbstractType::Handle(
+      Type::New(class_i, tav_object_dynamic, TokenPosition::kNoSource));
+  FinalizeAndCanonicalize(class_null, &type_i_object_dynamic);
+  const auto& tav_iod = TypeArguments::Handle(TypeArguments::New(1));
+  tav_iod.SetTypeAt(0, type_i_object_dynamic);
+
+  // We will generate specialized TTS for instantiated interface types
+  // where there are no type arguments or the type arguments are top
+  // types.
+  //
+  //   obj as Base<I<Object, dynamic>>   // Subclass ranges for Base, subtype
+  //                                     // ranges tav arguments.
+  //   obj as Base<T>                    // Subclass ranges for Base, type
+  //                                     // equality for instantiator type arg T
+  //   obj as Base<B>                    // Subclass ranges for Base, type
+  //                                     // equality for function type arg B.
+  //
+
+  // <...> as Base<I<Object, dynamic>>
+  auto& type_base_i_object_dynamic = AbstractType::Handle(
+      Type::New(class_base, tav_iod, TokenPosition::kNoSource));
+  FinalizeAndCanonicalize(class_null, &type_base_i_object_dynamic);
+  RunTTSTest(obj_baseb2int, type_base_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  RunTTSTest(obj_baseistringdouble, type_base_i_object_dynamic, tav_null,
+             tav_null, ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  RunTTSTest(obj_a, type_base_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_a1, type_base_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_a2, type_base_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_b, type_base_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_b1, type_base_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  RunTTSTest(obj_b2, type_base_i_object_dynamic, tav_null, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+
+  // <...> as Base<T>  with T instantiantiator type parameter (T == int)
+  const auto& tav_baset = TypeArguments::Handle(TypeArguments::New(1));
+  tav_baset.SetTypeAt(
+      0, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
+  auto& type_base_t = AbstractType::Handle(
+      Type::New(class_base, tav_baset, TokenPosition::kNoSource));
+  FinalizeAndCanonicalize(class_base, &type_base_t);
+  RunTTSTest(obj_baseint, type_base_t, tav_int, tav_null,
+             ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  RunTTSTest(obj_baseistringdouble, type_base_t, tav_int, tav_null,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+
+  // <...> as Base<B>  with B function type parameter
+  const auto& tav_baseb = TypeArguments::Handle(TypeArguments::New(1));
+  tav_baseb.SetTypeAt(
+      0, TypeParameter::Handle(GetFunctionTypeParameter(fun_generic, "B")));
+  auto& type_base_b = AbstractType::Handle(
+      Type::New(class_base, tav_baseb, TokenPosition::kNoSource));
+  FinalizeAndCanonicalize(class_null, &type_base_b);
+  // With B == int
+  RunTTSTest(obj_baseint, type_base_b, tav_null, tav_dynamic_int,
+             ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  RunTTSTest(obj_baseistringdouble, type_base_b, tav_null, tav_dynamic_int,
+             ExpectLazilyFailedViaTTS, ExpectFailedViaTTS);
+  // With B == dynamic (null vector)
+  RunTTSTest(obj_baseint, type_base_b, tav_null, tav_null,
+             ExpectLazilyHandledViaTTS, ExpectHandledViaTTS);
+  RunTTSTest(obj_i2, type_base_b, tav_null, tav_null, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+
+  // We do not generate TTS for uninstantiated types if we would need to use
+  // subtype range checks for the class of the interface type.
+  //
+  //   obj as I<dynamic, String>       // I is generic & implemented.
+  //   obj as Base<A2<T>>              // A2<T> is not instantiated.
+  //   obj as Base<A2<A1>>             // A2<A1> is not a rare type.
+  //
+
+  //   <...> as I<dynamic, String>
+  RELEASE_ASSERT(class_i.is_implemented());
+  auto& type_i_dynamic_string = Type::Handle(
+      Type::New(class_i, tav_dynamic_string, TokenPosition::kNoSource));
+  type_i_dynamic_string = type_i_dynamic_string.ToNullability(
+      Nullability::kNonNullable, Heap::kNew);
+  FinalizeAndCanonicalize(class_null, &type_i_dynamic_string);
+  RunTTSTest(obj_i, type_i_dynamic_string, tav_null, tav_null,
+             ExpectLazilyHandledViaSTC, ExpectHandledViaSTC);
+  RunTTSTest(obj_baseint, type_i_dynamic_string, tav_null, tav_null,
+             ExpectLazilyFailedViaSTC, ExpectFailedViaSTC);
+
+  //   <...> as Base<A2<T>>
+  const auto& tav_t = TypeArguments::Handle(TypeArguments::New(1));
+  tav_t.SetTypeAt(
+      0, TypeParameter::Handle(GetClassTypeParameter(class_base, "T")));
+  auto& type_a2_t =
+      Type::Handle(Type::New(class_a2, tav_t, TokenPosition::kNoSource));
+  type_a2_t = type_a2_t.ToNullability(Nullability::kLegacy, Heap::kNew);
+  FinalizeAndCanonicalize(class_null, &type_a2_t);
+  const auto& tav_a2_t = TypeArguments::Handle(TypeArguments::New(1));
+  tav_a2_t.SetTypeAt(0, type_a2_t);
+  auto& type_base_a2_t =
+      Type::Handle(Type::New(class_base, tav_a2_t, TokenPosition::kNoSource));
+  type_base_a2_t =
+      type_base_a2_t.ToNullability(Nullability::kNonNullable, Heap::kNew);
+  FinalizeAndCanonicalize(class_null, &type_base_a2_t);
+  RunTTSTest(obj_basea2int, type_base_a2_t, tav_null, tav_null,
+             ExpectLazilyHandledViaSTC, ExpectHandledViaSTC);
+  RunTTSTest(obj_baseint, type_base_a2_t, tav_null, tav_null,
+             ExpectLazilyFailedViaSTC, ExpectFailedViaSTC);
+
+  //   <...> as Base<A2<A1>>
+  const auto& tav_a1 = TypeArguments::Handle(TypeArguments::New(1));
+  tav_a1.SetTypeAt(0, type_a1);
+  auto& type_a2_a1 =
+      Type::Handle(Type::New(class_a2, tav_a1, TokenPosition::kNoSource));
+  type_a2_a1 = type_a2_a1.ToNullability(Nullability::kLegacy, Heap::kNew);
+  FinalizeAndCanonicalize(class_null, &type_a2_a1);
+  const auto& tav_a2_a1 = TypeArguments::Handle(TypeArguments::New(1));
+  tav_a2_a1.SetTypeAt(0, type_a2_a1);
+  auto& type_base_a2_a1 =
+      Type::Handle(Type::New(class_base, tav_a2_a1, TokenPosition::kNoSource));
+  type_base_a2_a1 =
+      type_base_a2_a1.ToNullability(Nullability::kNonNullable, Heap::kNew);
+  FinalizeAndCanonicalize(class_null, &type_base_a2_a1);
+  RunTTSTest(obj_basea2a1, type_base_a2_a1, tav_null, tav_null,
+             ExpectLazilyHandledViaSTC, ExpectHandledViaSTC);
+  RunTTSTest(obj_basea2int, type_base_a2_a1, tav_null, tav_null,
+             ExpectLazilyFailedViaSTC, ExpectFailedViaSTC);
+}
+
+ISOLATE_UNIT_TEST_CASE(TTS_Regress40964) {
+  const char* kScript =
+      R"(
+          class A<T> {
+            test(x) => x as B<T>;
+          }
+          class B<T> {}
+          class C<T> {}
+
+          createACint() => A<C<int>>();
+          createBCint() => B<C<int>>();
+          createBCnum() => B<C<num>>();
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& class_b = Class::Handle(GetClass(root_library, "B"));
+  const auto& class_null = Class::Handle(Class::null());
+
+  const auto& acint = Object::Handle(Invoke(root_library, "createACint"));
+  const auto& bcint = Object::Handle(Invoke(root_library, "createBCint"));
+  const auto& bcnum = Object::Handle(Invoke(root_library, "createBCnum"));
+
+  // dst_type = B<T>
+  const auto& dst_tav = TypeArguments::Handle(TypeArguments::New(1));
+  dst_tav.SetTypeAt(0,
+                    TypeParameter::Handle(GetClassTypeParameter(class_b, "T")));
+  auto& dst_type =
+      Type::Handle(Type::New(class_b, dst_tav, TokenPosition::kNoSource));
+  FinalizeAndCanonicalize(class_null, &dst_type);
+  const auto& cint_tav =
+      TypeArguments::Handle(Instance::Cast(acint).GetTypeArguments());
+  const auto& function_tav = TypeArguments::Handle();
+
+  // a as B<T> -- a==B<C<int>, T==<C<int>>
+  RunTTSTest(bcint, dst_type, cint_tav, function_tav, ExpectLazilyHandledViaTTS,
+             ExpectHandledViaTTS);
+
+  // a as B<T> -- a==B<C<num>, T==<C<int>>
+  RunTTSTest(bcnum, dst_type, cint_tav, function_tav, ExpectLazilyFailedViaTTS,
+             ExpectFailedViaTTS);
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_ARM64) ||  defined(TARGET_ARCH_ARM) ||          \
+        // defined(TARGET_ARCH_X64)
diff --git a/runtime/vm/type_testing_stubs_test.h b/runtime/vm/type_testing_stubs_test.h
new file mode 100644
index 0000000..c11f2d8
--- /dev/null
+++ b/runtime/vm/type_testing_stubs_test.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for 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_TYPE_TESTING_STUBS_TEST_H_
+#define RUNTIME_VM_TYPE_TESTING_STUBS_TEST_H_
+
+#if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM) ||                  \
+    defined(TARGET_ARCH_X64)
+
+#include "include/dart_api.h"
+
+namespace dart {
+
+namespace compiler {
+class Assembler;
+}
+
+void GenerateInvokeTTSStub(compiler::Assembler* assembler);
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_ARM64) ||  defined(TARGET_ARCH_ARM) ||          \
+        // defined(TARGET_ARCH_X64)
+
+#endif  // RUNTIME_VM_TYPE_TESTING_STUBS_TEST_H_
diff --git a/runtime/vm/type_testing_stubs_test_arm.cc b/runtime/vm/type_testing_stubs_test_arm.cc
new file mode 100644
index 0000000..2970a03
--- /dev/null
+++ b/runtime/vm/type_testing_stubs_test_arm.cc
@@ -0,0 +1,123 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+
+#if defined(TARGET_ARCH_ARM)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/runtime_api.h"
+#include "vm/constants.h"
+#include "vm/object.h"
+#include "vm/stack_frame.h"
+#include "vm/symbols.h"
+
+#define __ assembler->
+
+namespace dart {
+
+void GenerateInvokeTTSStub(compiler::Assembler* assembler) {
+  __ EnterDartFrame(0);
+
+  intptr_t sum = 0;
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
+    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
+    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
+    __ LoadImmediate(static_cast<Register>(i), 0x10 + 2 * i);
+    sum += 0x10 + 2 * i;
+  }
+
+  // Load the arguments into the right TTS calling convention registers.
+  __ ldr(TypeTestABI::kInstanceReg,
+         compiler::Address(
+             FP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
+  __ ldr(TypeTestABI::kInstantiatorTypeArgumentsReg,
+         compiler::Address(
+             FP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
+  __ ldr(TypeTestABI::kFunctionTypeArgumentsReg,
+         compiler::Address(
+             FP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
+  __ ldr(TypeTestABI::kDstTypeReg,
+         compiler::Address(
+             FP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
+
+  const intptr_t sub_type_cache_index = __ object_pool_builder().AddObject(
+      Object::null_object(), compiler::ObjectPoolBuilderEntry::kPatchable);
+  const intptr_t sub_type_cache_offset =
+      ObjectPool::element_offset(sub_type_cache_index) - kHeapObjectTag;
+  const intptr_t dst_name_index = __ object_pool_builder().AddObject(
+      Symbols::OptimizedOut(), compiler::ObjectPoolBuilderEntry::kPatchable);
+  ASSERT((sub_type_cache_index + 1) == dst_name_index);
+  ASSERT(__ constant_pool_allowed());
+
+  // Call the TTS.
+  __ ldr(R9, compiler::FieldAddress(
+                 TypeTestABI::kDstTypeReg,
+                 AbstractType::type_test_stub_entry_point_offset()));
+  __ ldr(TypeTestABI::kSubtypeTestCacheReg,
+         compiler::Address(PP, sub_type_cache_offset));
+  __ blx(R9);
+
+  // We have the guarantee that TTS preserve all registers except for one
+  // scratch register atm (if the TTS handles the type test successfully).
+  //
+  // Let the test know whether TTS abi registers were preserved.
+  compiler::Label abi_regs_modified, store_abi_regs_modified_bool;
+  __ CompareWithMemoryValue(
+      TypeTestABI::kInstanceReg,
+      compiler::Address(
+          FP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ CompareWithMemoryValue(
+      TypeTestABI::kInstantiatorTypeArgumentsReg,
+      compiler::Address(
+          FP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ CompareWithMemoryValue(
+      TypeTestABI::kFunctionTypeArgumentsReg,
+      compiler::Address(
+          FP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ CompareWithMemoryValue(
+      TypeTestABI::kDstTypeReg,
+      compiler::Address(
+          FP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ ldr(R0, compiler::Address(THR, Thread::bool_false_offset()));
+  __ b(&store_abi_regs_modified_bool);
+  __ Bind(&abi_regs_modified);
+  __ ldr(R0, compiler::Address(THR, Thread::bool_true_offset()));
+  __ Bind(&store_abi_regs_modified_bool);
+  __ ldr(TMP, compiler::Address(
+                  FP, (kCallerSpSlotFromFp + 5) * compiler::target::kWordSize));
+  __ str(R0, compiler::FieldAddress(TMP, Array::element_offset(0)));
+
+  // Let the test know whether the non-TTS abi registers were preserved.
+  compiler::Label rest_regs_modified, store_rest_regs_modified_bool;
+  __ mov(TMP, compiler::Operand(0));
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
+    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
+    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
+    __ add(TMP, TMP, compiler::Operand(static_cast<Register>(i)));
+  }
+  __ cmp(TMP, compiler::Operand(sum));
+  __ BranchIf(NOT_EQUAL, &rest_regs_modified);
+  __ ldr(R0, compiler::Address(THR, Thread::bool_false_offset()));
+  __ b(&store_rest_regs_modified_bool);
+  __ Bind(&rest_regs_modified);
+  __ ldr(R0, compiler::Address(THR, Thread::bool_true_offset()));
+  __ Bind(&store_rest_regs_modified_bool);
+  __ ldr(TMP, compiler::Address(
+                  FP, (kCallerSpSlotFromFp + 4) * compiler::target::kWordSize));
+  __ str(R0, compiler::FieldAddress(TMP, Array::element_offset(0)));
+
+  __ LoadObject(R0, Object::null_object());
+  __ LeaveDartFrameAndReturn();
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_ARM)
diff --git a/runtime/vm/type_testing_stubs_test_arm64.cc b/runtime/vm/type_testing_stubs_test_arm64.cc
new file mode 100644
index 0000000..858cd33
--- /dev/null
+++ b/runtime/vm/type_testing_stubs_test_arm64.cc
@@ -0,0 +1,124 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+
+#if defined(TARGET_ARCH_ARM64)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/runtime_api.h"
+#include "vm/constants.h"
+#include "vm/object.h"
+#include "vm/stack_frame.h"
+#include "vm/symbols.h"
+
+#define __ assembler->
+
+namespace dart {
+
+void GenerateInvokeTTSStub(compiler::Assembler* assembler) {
+  __ EnterDartFrame(0);
+
+  intptr_t sum = 0;
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
+    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
+    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
+    __ LoadImmediate(static_cast<Register>(i), 0x10 + 2 * i);
+    sum += 0x10 + 2 * i;
+  }
+
+  // Load the arguments into the right TTS calling convention registers.
+  __ ldr(TypeTestABI::kInstanceReg,
+         compiler::Address(
+             FP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
+  __ ldr(TypeTestABI::kInstantiatorTypeArgumentsReg,
+         compiler::Address(
+             FP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
+  __ ldr(TypeTestABI::kFunctionTypeArgumentsReg,
+         compiler::Address(
+             FP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
+  __ ldr(TypeTestABI::kDstTypeReg,
+         compiler::Address(
+             FP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
+
+  const intptr_t sub_type_cache_index = __ object_pool_builder().AddObject(
+      Object::null_object(), compiler::ObjectPoolBuilderEntry::kPatchable);
+  const intptr_t sub_type_cache_offset =
+      ObjectPool::element_offset(sub_type_cache_index);
+  const intptr_t dst_name_index = __ object_pool_builder().AddObject(
+      Symbols::OptimizedOut(), compiler::ObjectPoolBuilderEntry::kPatchable);
+  ASSERT((sub_type_cache_index + 1) == dst_name_index);
+  ASSERT(__ constant_pool_allowed());
+
+  // Call the TTS.
+  __ ldr(R9, compiler::FieldAddress(
+                 TypeTestABI::kDstTypeReg,
+                 AbstractType::type_test_stub_entry_point_offset()));
+  __ LoadWordFromPoolOffset(TypeTestABI::kSubtypeTestCacheReg,
+                            sub_type_cache_offset);
+  __ blr(R9);
+
+  // We have the guarantee that TTS preserve all registers except for one
+  // scratch register atm (if the TTS handles the type test successfully).
+  //
+  // Let the test know whether TTS abi registers were preserved.
+  compiler::Label abi_regs_modified, store_abi_regs_modified_bool;
+  __ CompareWithMemoryValue(
+      TypeTestABI::kInstanceReg,
+      compiler::Address(
+          FP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ CompareWithMemoryValue(
+      TypeTestABI::kInstantiatorTypeArgumentsReg,
+      compiler::Address(
+          FP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ CompareWithMemoryValue(
+      TypeTestABI::kFunctionTypeArgumentsReg,
+      compiler::Address(
+          FP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ CompareWithMemoryValue(
+      TypeTestABI::kDstTypeReg,
+      compiler::Address(
+          FP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ ldr(R0, compiler::Address(THR, Thread::bool_false_offset()));
+  __ b(&store_abi_regs_modified_bool);
+  __ Bind(&abi_regs_modified);
+  __ ldr(R0, compiler::Address(THR, Thread::bool_true_offset()));
+  __ Bind(&store_abi_regs_modified_bool);
+  __ ldr(TMP, compiler::Address(
+                  FP, (kCallerSpSlotFromFp + 5) * compiler::target::kWordSize));
+  __ str(R0, compiler::FieldAddress(TMP, Array::element_offset(0)));
+
+  // Let the test know whether the non-TTS abi registers were preserved.
+  compiler::Label rest_regs_modified, store_rest_regs_modified_bool;
+  __ LoadImmediate(TMP, 0);
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
+    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
+    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
+    __ add(TMP, TMP, compiler::Operand(static_cast<Register>(i)));
+  }
+  __ cmp(TMP, compiler::Operand(sum));
+  __ BranchIf(NOT_EQUAL, &rest_regs_modified);
+  __ ldr(R0, compiler::Address(THR, Thread::bool_false_offset()));
+  __ b(&store_rest_regs_modified_bool);
+  __ Bind(&rest_regs_modified);
+  __ ldr(R0, compiler::Address(THR, Thread::bool_true_offset()));
+  __ Bind(&store_rest_regs_modified_bool);
+  __ ldr(TMP, compiler::Address(
+                  FP, (kCallerSpSlotFromFp + 4) * compiler::target::kWordSize));
+  __ str(R0, compiler::FieldAddress(TMP, Array::element_offset(0)));
+
+  __ LoadObject(R0, Object::null_object());
+  __ LeaveDartFrame();
+  __ Ret();
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_ARM64)
diff --git a/runtime/vm/type_testing_stubs_test_x64.cc b/runtime/vm/type_testing_stubs_test_x64.cc
new file mode 100644
index 0000000..57ae551
--- /dev/null
+++ b/runtime/vm/type_testing_stubs_test_x64.cc
@@ -0,0 +1,118 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+
+#if defined(TARGET_ARCH_X64)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/runtime_api.h"
+#include "vm/constants.h"
+#include "vm/object.h"
+#include "vm/stack_frame.h"
+#include "vm/symbols.h"
+
+#define __ assembler->
+
+namespace dart {
+
+void GenerateInvokeTTSStub(compiler::Assembler* assembler) {
+  __ EnterDartFrame(0);
+  intptr_t sum = 0;
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
+    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
+    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
+    __ movq(static_cast<Register>(i), compiler::Immediate(0x10 + 2 * i));
+    sum += 0x10 + 2 * i;
+  }
+
+  // Load the arguments into the right TTS calling convention registers.
+  __ movq(TypeTestABI::kInstanceReg,
+          compiler::Address(
+              RBP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
+  __ movq(TypeTestABI::kInstantiatorTypeArgumentsReg,
+          compiler::Address(
+              RBP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
+  __ movq(TypeTestABI::kFunctionTypeArgumentsReg,
+          compiler::Address(
+              RBP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
+  __ movq(TypeTestABI::kDstTypeReg,
+          compiler::Address(
+              RBP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
+
+  const intptr_t sub_type_cache_index = __ object_pool_builder().AddObject(
+      Object::null_object(), compiler::ObjectPoolBuilderEntry::kPatchable);
+  const intptr_t sub_type_cache_offset =
+      ObjectPool::element_offset(sub_type_cache_index) - kHeapObjectTag;
+  const intptr_t dst_name_index = __ object_pool_builder().AddObject(
+      Symbols::OptimizedOut(), compiler::ObjectPoolBuilderEntry::kPatchable);
+  ASSERT((sub_type_cache_index + 1) == dst_name_index);
+  ASSERT(__ constant_pool_allowed());
+
+  // Call the TTS.
+  __ movq(TypeTestABI::kSubtypeTestCacheReg,
+          compiler::Address(PP, sub_type_cache_offset));
+  __ call(compiler::FieldAddress(
+      TypeTestABI::kDstTypeReg,
+      AbstractType::type_test_stub_entry_point_offset()));
+
+  // We have the guarantee that TTS preserve all registers except for one
+  // scratch register atm (if the TTS handles the type test successfully).
+  //
+  // Let the test know whether TTS abi registers were preserved.
+  compiler::Label abi_regs_modified, store_abi_regs_modified_bool;
+  __ cmpq(TypeTestABI::kInstanceReg,
+          compiler::Address(
+              RBP, (kCallerSpSlotFromFp + 3) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ cmpq(TypeTestABI::kInstantiatorTypeArgumentsReg,
+          compiler::Address(
+              RBP, (kCallerSpSlotFromFp + 2) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ cmpq(TypeTestABI::kFunctionTypeArgumentsReg,
+          compiler::Address(
+              RBP, (kCallerSpSlotFromFp + 1) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ cmpq(TypeTestABI::kDstTypeReg,
+          compiler::Address(
+              RBP, (kCallerSpSlotFromFp + 0) * compiler::target::kWordSize));
+  __ BranchIf(NOT_EQUAL, &abi_regs_modified);
+  __ movq(RAX, compiler::Address(THR, Thread::bool_false_offset()));
+  __ jmp(&store_abi_regs_modified_bool);
+  __ Bind(&abi_regs_modified);
+  __ movq(RAX, compiler::Address(THR, Thread::bool_true_offset()));
+  __ Bind(&store_abi_regs_modified_bool);
+  __ movq(TMP, compiler::Address(RBP, (kCallerSpSlotFromFp + 5) *
+                                          compiler::target::kWordSize));
+  __ movq(compiler::FieldAddress(TMP, Array::element_offset(0)), RAX);
+
+  // Let the test know whether the non-TTS abi registers were preserved.
+  compiler::Label rest_regs_modified, store_rest_regs_modified_bool;
+  __ movq(TMP, compiler::Immediate(0));
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
+    if (((1 << i) & kDartAvailableCpuRegs) == 0) continue;
+    if (((1 << i) & TypeTestABI::kAbiRegisters) != 0) continue;
+    if (((1 << i) & TTSInternalRegs::kInternalRegisters) != 0) continue;
+    __ addq(TMP, static_cast<Register>(i));
+  }
+  __ cmpq(TMP, compiler::Immediate(sum));
+  __ BranchIf(NOT_EQUAL, &rest_regs_modified);
+  __ movq(RAX, compiler::Address(THR, Thread::bool_false_offset()));
+  __ jmp(&store_rest_regs_modified_bool);
+  __ Bind(&rest_regs_modified);
+  __ movq(RAX, compiler::Address(THR, Thread::bool_true_offset()));
+  __ Bind(&store_rest_regs_modified_bool);
+  __ movq(TMP, compiler::Address(RBP, (kCallerSpSlotFromFp + 4) *
+                                          compiler::target::kWordSize));
+  __ movq(compiler::FieldAddress(TMP, Array::element_offset(0)), RAX);
+
+  __ LoadObject(RAX, Object::null_object());
+  __ LeaveDartFrame();
+  __ Ret();
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_X64)
diff --git a/runtime/vm/type_testing_stubs_x64.cc b/runtime/vm/type_testing_stubs_x64.cc
index 516c90a..a942eb0 100644
--- a/runtime/vm/type_testing_stubs_x64.cc
+++ b/runtime/vm/type_testing_stubs_x64.cc
@@ -17,53 +17,13 @@
     HierarchyInfo* hi,
     const Type& type,
     const Class& type_class) {
-  const Register kInstanceReg = RAX;
-  const Register kClassIdReg = TMP;
-
-  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
-                                      kInstanceReg, kClassIdReg);
+  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class);
 
   __ movq(CODE_REG,
           compiler::Address(THR, Thread::slow_type_test_stub_offset()));
   __ jmp(compiler::FieldAddress(CODE_REG, Code::entry_point_offset()));
 }
 
-void TypeTestingStubGenerator::
-    BuildOptimizedSubclassRangeCheckWithTypeArguments(
-        compiler::Assembler* assembler,
-        HierarchyInfo* hi,
-        const Type& type,
-        const Class& type_class,
-        const TypeArguments& tp,
-        const TypeArguments& ta) {
-  const Register kInstanceReg = RAX;
-  const Register kInstanceTypeArguments = RSI;
-  const Register kClassIdReg = TMP;
-
-  BuildOptimizedSubclassRangeCheckWithTypeArguments(
-      assembler, hi, type, type_class, tp, ta, kClassIdReg, kInstanceReg,
-      kInstanceTypeArguments);
-}
-
-void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck(
-    compiler::Assembler* assembler,
-    HierarchyInfo* hi,
-    const AbstractType& type_arg,
-    intptr_t type_param_value_offset_i,
-    compiler::Label* check_failed) {
-  const Register kInstanceTypeArguments = RSI;
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
-
-  const Register kClassIdReg = TMP;
-  const Register kOwnTypeArgumentValue = RDI;
-
-  BuildOptimizedTypeArgumentValueCheck(
-      assembler, hi, type_arg, type_param_value_offset_i, kClassIdReg,
-      kInstanceTypeArguments, kInstantiatorTypeArgumentsReg,
-      kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
-}
-
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 8f6e1f0..a02d69b 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -445,6 +445,11 @@
   "thread_pool_test.cc",
   "thread_test.cc",
   "timeline_test.cc",
+  "type_testing_stubs_test.h",
+  "type_testing_stubs_test.cc",
+  "type_testing_stubs_test_x64.cc",
+  "type_testing_stubs_test_arm.cc",
+  "type_testing_stubs_test_arm64.cc",
   "unicode_test.cc",
   "unit_test.cc",
   "unit_test.h",
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index 336c6d0..890a570 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -2257,8 +2257,6 @@
   static void _startRequestTimelineEvent(
       TimelineTask timeline, String method, Uri uri) {
     timeline?.start('HTTP CLIENT ${method.toUpperCase()}', arguments: {
-      'filterKey':
-          'HTTP/client', // key used to filter network requests from timeline
       'method': method.toUpperCase(),
       'uri': uri.toString(),
     });
@@ -2304,7 +2302,7 @@
     TimelineTask timeline;
     // TODO(bkonyi): do we want this to be opt-in?
     if (HttpClient.enableTimelineLogging) {
-      timeline = TimelineTask();
+      timeline = TimelineTask(filterKey: 'HTTP/client');
       _startRequestTimelineEvent(timeline, method, uri);
     }
     return _getConnection(uri.host, port, proxyConf, isSecure, timeline).then(
diff --git a/sdk/lib/_http/websocket_impl.dart b/sdk/lib/_http/websocket_impl.dart
index 35ee68b..ce015bb 100644
--- a/sdk/lib/_http/websocket_impl.dart
+++ b/sdk/lib/_http/websocket_impl.dart
@@ -115,6 +115,7 @@
   }
 
   void addError(Object error, [StackTrace stackTrace]) {
+    ArgumentError.checkNotNull(error, "error");
     _eventSink.addError(error, stackTrace);
   }
 
@@ -723,6 +724,7 @@
   }
 
   void addError(Object error, [StackTrace stackTrace]) {
+    ArgumentError.checkNotNull(error, "error");
     _eventSink.addError(error, stackTrace);
   }
 
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
index ef0a652..6dd9546 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart
@@ -419,6 +419,7 @@
   }
 
   void addError(Object error, StackTrace stackTrace) {
+    ArgumentError.checkNotNull(error, "error");
     if (cancellationCompleter != null && !cancellationCompleter.isCompleted) {
       // If the stream has been cancelled, complete the cancellation future
       // with the error.
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 0d8628d..2e1587c 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -678,6 +678,13 @@
   }
 
   @patch
+  factory bool.hasEnvironment(String name) {
+    // ignore: const_constructor_throws_exception
+    throw UnsupportedError(
+        'bool.hasEnvironment can only be used as a const constructor');
+  }
+
+  @patch
   int get hashCode => super.hashCode;
 
   @JSExportName('is')
diff --git a/sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart b/sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
index 5940845..4265799 100644
--- a/sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
+++ b/sdk/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
@@ -24,3 +24,23 @@
 @patch
 TypeMirror reflectType(Type key, [List<Type> typeArguments]) =>
     throw new UnsupportedError(_message);
+
+@patch
+abstract class MirrorSystem {
+  Map<Uri, LibraryMirror> get libraries;
+  IsolateMirror get isolate;
+  TypeMirror get dynamicType;
+  TypeMirror get voidType;
+  TypeMirror get neverType;
+
+  @patch
+  LibraryMirror findLibrary(Symbol libraryName) =>
+      throw new UnsupportedError(_message);
+
+  @patch
+  static String getName(Symbol symbol) => throw new UnsupportedError(_message);
+
+  @patch
+  static Symbol getSymbol(String name, [LibraryMirror library]) =>
+      throw new UnsupportedError(_message);
+}
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index 1adc744..d7764df 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -447,7 +447,7 @@
   String key = Rti._getCanonicalRecipe(instantiationRti);
   var probe = _Utils.mapGet(cache, key);
   if (probe != null) return _castToRti(probe);
-  Rti rti = _instantiate(_theUniverse(),
+  Rti rti = _substitute(_theUniverse(),
       Rti._getGenericFunctionBase(genericFunctionRti), typeArguments, 0);
   _Utils.mapSet(cache, key, rti);
   return rti;
@@ -461,7 +461,11 @@
 /// [depth] is the number of subsequent generic function parameters that are in
 /// scope. This is subtracted off the de Bruijn index for the type parameter to
 /// arrive at an potential index into [typeArguments].
-Rti _instantiate(universe, Rti rti, Object typeArguments, int depth) {
+///
+/// In order to do a partial substitution - that is, substituting only some
+/// type parameters rather than all of them - we encode the unsubstituted
+/// positions of the argument list as `undefined` or `null`.
+Rti _substitute(universe, Rti rti, Object typeArguments, int depth) {
   int kind = Rti._getKind(rti);
   switch (kind) {
     case Rti.kindErased:
@@ -472,92 +476,99 @@
       return rti;
     case Rti.kindStar:
       Rti baseType = _castToRti(Rti._getPrimary(rti));
-      Rti instantiatedBaseType =
-          _instantiate(universe, baseType, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBaseType, baseType)) return rti;
-      return _Universe._lookupStarRti(universe, instantiatedBaseType, true);
+      Rti substitutedBaseType =
+          _substitute(universe, baseType, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBaseType, baseType)) return rti;
+      return _Universe._lookupStarRti(universe, substitutedBaseType, true);
     case Rti.kindQuestion:
       Rti baseType = _castToRti(Rti._getPrimary(rti));
-      Rti instantiatedBaseType =
-          _instantiate(universe, baseType, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBaseType, baseType)) return rti;
-      return _Universe._lookupQuestionRti(universe, instantiatedBaseType, true);
+      Rti substitutedBaseType =
+          _substitute(universe, baseType, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBaseType, baseType)) return rti;
+      return _Universe._lookupQuestionRti(universe, substitutedBaseType, true);
     case Rti.kindFutureOr:
       Rti baseType = _castToRti(Rti._getPrimary(rti));
-      Rti instantiatedBaseType =
-          _instantiate(universe, baseType, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBaseType, baseType)) return rti;
-      return _Universe._lookupFutureOrRti(universe, instantiatedBaseType, true);
+      Rti substitutedBaseType =
+          _substitute(universe, baseType, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBaseType, baseType)) return rti;
+      return _Universe._lookupFutureOrRti(universe, substitutedBaseType, true);
     case Rti.kindInterface:
       Object interfaceTypeArguments = Rti._getInterfaceTypeArguments(rti);
-      Object instantiatedInterfaceTypeArguments = _instantiateArray(
+      Object substitutedInterfaceTypeArguments = _substituteArray(
           universe, interfaceTypeArguments, typeArguments, depth);
       if (_Utils.isIdentical(
-          instantiatedInterfaceTypeArguments, interfaceTypeArguments))
+          substitutedInterfaceTypeArguments, interfaceTypeArguments))
         return rti;
       return _Universe._lookupInterfaceRti(universe, Rti._getInterfaceName(rti),
-          instantiatedInterfaceTypeArguments);
+          substitutedInterfaceTypeArguments);
     case Rti.kindBinding:
       Rti base = Rti._getBindingBase(rti);
-      Rti instantiatedBase = _instantiate(universe, base, typeArguments, depth);
+      Rti substitutedBase = _substitute(universe, base, typeArguments, depth);
       Object arguments = Rti._getBindingArguments(rti);
-      Object instantiatedArguments =
-          _instantiateArray(universe, arguments, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBase, base) &&
-          _Utils.isIdentical(instantiatedArguments, arguments)) return rti;
+      Object substitutedArguments =
+          _substituteArray(universe, arguments, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBase, base) &&
+          _Utils.isIdentical(substitutedArguments, arguments)) return rti;
       return _Universe._lookupBindingRti(
-          universe, instantiatedBase, instantiatedArguments);
+          universe, substitutedBase, substitutedArguments);
     case Rti.kindFunction:
       Rti returnType = Rti._getReturnType(rti);
-      Rti instantiatedReturnType =
-          _instantiate(universe, returnType, typeArguments, depth);
+      Rti substitutedReturnType =
+          _substitute(universe, returnType, typeArguments, depth);
       _FunctionParameters functionParameters = Rti._getFunctionParameters(rti);
-      _FunctionParameters instantiatedFunctionParameters =
-          _instantiateFunctionParameters(
+      _FunctionParameters substitutedFunctionParameters =
+          _substituteFunctionParameters(
               universe, functionParameters, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedReturnType, returnType) &&
-          _Utils.isIdentical(
-              instantiatedFunctionParameters, functionParameters)) return rti;
+      if (_Utils.isIdentical(substitutedReturnType, returnType) &&
+          _Utils.isIdentical(substitutedFunctionParameters, functionParameters))
+        return rti;
       return _Universe._lookupFunctionRti(
-          universe, instantiatedReturnType, instantiatedFunctionParameters);
+          universe, substitutedReturnType, substitutedFunctionParameters);
     case Rti.kindGenericFunction:
       Object bounds = Rti._getGenericFunctionBounds(rti);
       depth += _Utils.arrayLength(bounds);
-      Object instantiatedBounds =
-          _instantiateArray(universe, bounds, typeArguments, depth);
+      Object substitutedBounds =
+          _substituteArray(universe, bounds, typeArguments, depth);
       Rti base = Rti._getGenericFunctionBase(rti);
-      Rti instantiatedBase = _instantiate(universe, base, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBounds, bounds) &&
-          _Utils.isIdentical(instantiatedBase, base)) return rti;
+      Rti substitutedBase = _substitute(universe, base, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBounds, bounds) &&
+          _Utils.isIdentical(substitutedBase, base)) return rti;
       return _Universe._lookupGenericFunctionRti(
-          universe, instantiatedBase, instantiatedBounds);
+          universe, substitutedBase, substitutedBounds, true);
     case Rti.kindGenericFunctionParameter:
       int index = Rti._getGenericFunctionParameterIndex(rti);
-      if (index < depth) return null;
-      return _castToRti(_Utils.arrayAt(typeArguments, index - depth));
+      // Indices below the current depth are out of scope for substitution and
+      // can be returned unchanged.
+      if (index < depth) return rti;
+      var argument = _Utils.arrayAt(typeArguments, index - depth);
+      // In order to do a partial substitution - that is, substituting only some
+      // type parameters rather than all of them - we encode the unsubstituted
+      // positions of the argument list as `undefined` (which will compare equal
+      // to `null`).
+      if (argument == null) return rti;
+      return _castToRti(argument);
     default:
-      throw AssertionError(
-          'Attempted to instantiate unexpected RTI kind $kind');
+      throw AssertionError('Attempted to substitute unexpected RTI kind $kind');
   }
 }
 
-Object _instantiateArray(
+Object _substituteArray(
     universe, Object rtiArray, Object typeArguments, int depth) {
   bool changed = false;
   int length = _Utils.arrayLength(rtiArray);
   Object result = JS('', '[]');
   for (int i = 0; i < length; i++) {
     Rti rti = _castToRti(_Utils.arrayAt(rtiArray, i));
-    Rti instantiatedRti = _instantiate(universe, rti, typeArguments, depth);
-    if (_Utils.isNotIdentical(instantiatedRti, rti)) {
+    Rti substitutedRti = _substitute(universe, rti, typeArguments, depth);
+    if (_Utils.isNotIdentical(substitutedRti, rti)) {
       changed = true;
     }
-    _Utils.arrayPush(result, instantiatedRti);
+    _Utils.arrayPush(result, substitutedRti);
   }
   return changed ? result : rtiArray;
 }
 
-Object _instantiateNamed(
+Object _substituteNamed(
     universe, Object namedArray, Object typeArguments, int depth) {
   bool changed = false;
   int length = _Utils.arrayLength(namedArray);
@@ -566,41 +577,41 @@
   for (int i = 0; i < length; i += 2) {
     String name = _Utils.asString(_Utils.arrayAt(namedArray, i));
     Rti rti = _castToRti(_Utils.arrayAt(namedArray, i + 1));
-    Rti instantiatedRti = _instantiate(universe, rti, typeArguments, depth);
-    if (_Utils.isNotIdentical(instantiatedRti, rti)) {
+    Rti substitutedRti = _substitute(universe, rti, typeArguments, depth);
+    if (_Utils.isNotIdentical(substitutedRti, rti)) {
       changed = true;
     }
     _Utils.arrayPush(result, name);
-    _Utils.arrayPush(result, instantiatedRti);
+    _Utils.arrayPush(result, substitutedRti);
   }
   return changed ? result : namedArray;
 }
 
 // TODO(fishythefish): Support required named parameters.
-_FunctionParameters _instantiateFunctionParameters(universe,
+_FunctionParameters _substituteFunctionParameters(universe,
     _FunctionParameters functionParameters, Object typeArguments, int depth) {
   Object requiredPositional =
       _FunctionParameters._getRequiredPositional(functionParameters);
-  Object instantiatedRequiredPositional =
-      _instantiateArray(universe, requiredPositional, typeArguments, depth);
+  Object substitutedRequiredPositional =
+      _substituteArray(universe, requiredPositional, typeArguments, depth);
   Object optionalPositional =
       _FunctionParameters._getOptionalPositional(functionParameters);
-  Object instantiatedOptionalPositional =
-      _instantiateArray(universe, optionalPositional, typeArguments, depth);
+  Object substitutedOptionalPositional =
+      _substituteArray(universe, optionalPositional, typeArguments, depth);
   Object optionalNamed =
       _FunctionParameters._getOptionalNamed(functionParameters);
-  Object instantiatedOptionalNamed =
-      _instantiateNamed(universe, optionalNamed, typeArguments, depth);
-  if (_Utils.isIdentical(instantiatedRequiredPositional, requiredPositional) &&
-      _Utils.isIdentical(instantiatedOptionalPositional, optionalPositional) &&
-      _Utils.isIdentical(instantiatedOptionalNamed, optionalNamed))
+  Object substitutedOptionalNamed =
+      _substituteNamed(universe, optionalNamed, typeArguments, depth);
+  if (_Utils.isIdentical(substitutedRequiredPositional, requiredPositional) &&
+      _Utils.isIdentical(substitutedOptionalPositional, optionalPositional) &&
+      _Utils.isIdentical(substitutedOptionalNamed, optionalNamed))
     return functionParameters;
   _FunctionParameters result = _FunctionParameters.allocate();
   _FunctionParameters._setRequiredPositional(
-      result, instantiatedRequiredPositional);
+      result, substitutedRequiredPositional);
   _FunctionParameters._setOptionalPositional(
-      result, instantiatedOptionalPositional);
-  _FunctionParameters._setOptionalNamed(result, instantiatedOptionalNamed);
+      result, substitutedOptionalPositional);
+  _FunctionParameters._setOptionalNamed(result, substitutedOptionalNamed);
   return result;
 }
 
@@ -1959,19 +1970,44 @@
       _canonicalRecipeJoin(bounds) +
       Recipe.endTypeArgumentsString;
 
-  // TODO(fishythefish): Normalize `X extends Never` to `Never`.
   static Rti _lookupGenericFunctionRti(
-      Object universe, Rti baseFunctionType, Object bounds) {
+      Object universe, Rti baseFunctionType, Object bounds, bool normalize) {
     String key = _canonicalRecipeOfGenericFunction(baseFunctionType, bounds);
     var cache = evalCache(universe);
     var probe = _cacheGet(cache, key);
     if (probe != null) return _castToRti(probe);
-    return _installRti(universe, key,
-        _createGenericFunctionRti(universe, baseFunctionType, bounds, key));
+    return _installRti(
+        universe,
+        key,
+        _createGenericFunctionRti(
+            universe, baseFunctionType, bounds, key, normalize));
   }
 
-  static Rti _createGenericFunctionRti(
-      Object universe, Rti baseFunctionType, Object bounds, String key) {
+  static Rti _createGenericFunctionRti(Object universe, Rti baseFunctionType,
+      Object bounds, String key, bool normalize) {
+    if (normalize) {
+      int length = _Utils.arrayLength(bounds);
+      int count = 0;
+      Object typeArguments = JS('', 'new Array(#)', length);
+      for (int i = 0; i < length; i++) {
+        Rti bound = _castToRti(_Utils.arrayAt(bounds, i));
+        if (Rti._getKind(bound) == Rti.kindNever) {
+          _Utils.arraySetAt(typeArguments, i, bound);
+          count++;
+        }
+      }
+      if (count > 0) {
+        var substitutedBase =
+            _substitute(universe, baseFunctionType, typeArguments, 0);
+        var substitutedBounds =
+            _substituteArray(universe, bounds, typeArguments, 0);
+        return _lookupGenericFunctionRti(
+            universe,
+            substitutedBase,
+            substitutedBounds,
+            _Utils.isNotIdentical(bounds, substitutedBounds));
+      }
+    }
     Rti rti = Rti.allocate();
     Rti._setKind(rti, Rti.kindGenericFunction);
     Rti._setPrimary(rti, baseFunctionType);
@@ -2311,8 +2347,10 @@
       Rti base = toType(universe, environment(parser), head);
       switch (Rti._getKind(base)) {
         case Rti.kindFunction:
-          push(stack,
-              _Universe._lookupGenericFunctionRti(universe, base, arguments));
+          push(
+              stack,
+              _Universe._lookupGenericFunctionRti(
+                  universe, base, arguments, normalize(parser)));
           break;
 
         default:
@@ -2827,6 +2865,10 @@
   // interface, so rather than iterating over the Ci, we can instead look up
   // [t] in our ruleset.
   // TODO(fishythefish): Handle variance correctly.
+
+  // We don't list Object explicitly as a supertype of each interface, so check
+  // this trivial case first.
+  if (isObjectType(t)) return true;
   Object rule = _Universe.findRule(universe, sName);
   if (rule == null) return false;
   var supertypeArgs = TypeRule.lookupSupertype(rule, tName);
diff --git a/sdk/lib/_internal/vm/lib/async_patch.dart b/sdk/lib/_internal/vm/lib/async_patch.dart
index 0192bfe..85de9dc 100644
--- a/sdk/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk/lib/_internal/vm/lib/async_patch.dart
@@ -209,6 +209,7 @@
   }
 
   void addError(Object error, StackTrace stackTrace) {
+    ArgumentError.checkNotNull(error, "error");
     if ((cancellationFuture != null) && cancellationFuture._mayComplete) {
       // If the stream has been cancelled, complete the cancellation future
       // with the error.
diff --git a/sdk/lib/_internal/vm/lib/bool_patch.dart b/sdk/lib/_internal/vm/lib/bool_patch.dart
index a969c02..56098da 100644
--- a/sdk/lib/_internal/vm/lib/bool_patch.dart
+++ b/sdk/lib/_internal/vm/lib/bool_patch.dart
@@ -14,6 +14,9 @@
       native "Bool_fromEnvironment";
 
   @patch
+  const factory bool.hasEnvironment(String name) native "Bool_hasEnvironment";
+
+  @patch
   int get hashCode => this ? 1231 : 1237;
 
   int get _identityHashCode => this ? 1231 : 1237;
diff --git a/sdk/lib/async/broadcast_stream_controller.dart b/sdk/lib/async/broadcast_stream_controller.dart
index c18a682..09ab783 100644
--- a/sdk/lib/async/broadcast_stream_controller.dart
+++ b/sdk/lib/async/broadcast_stream_controller.dart
@@ -253,7 +253,7 @@
   }
 
   void addError(Object error, [StackTrace stackTrace]) {
-    error = _nonNullError(error);
+    ArgumentError.checkNotNull(error, "error");
     if (!_mayAddEvent) throw _addEventError();
     AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
     if (replacement != null) {
@@ -480,6 +480,7 @@
   }
 
   void addError(Object error, [StackTrace stackTrace]) {
+    ArgumentError.checkNotNull(error, "error");
     if (!isClosed && _isFiring) {
       _addPendingEvent(new _DelayedError(error, stackTrace));
       return;
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index 7aeee47..a0e35b5 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -254,6 +254,7 @@
    *
    * Use [Completer] to create a future and complete it later.
    */
+  @pragma("vm:entry-point")
   factory Future.value([FutureOr<T> value]) {
     return new _Future<T>.immediate(value);
   }
@@ -266,12 +267,12 @@
    * If an error handler isn't added before the future completes, the error
    * will be considered unhandled.
    *
-   * If [error] is `null`, it is replaced by a [NullThrownError].
+   * The [error] must not be `null`.
    *
    * Use [Completer] to create a future and complete it later.
    */
   factory Future.error(Object error, [StackTrace stackTrace]) {
-    error = _nonNullError(error);
+    ArgumentError.checkNotNull(error, "error");
     if (!identical(Zone.current, _rootZone)) {
       AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
       if (replacement != null) {
@@ -874,7 +875,7 @@
    * 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].
+   * The [error] must not be `null`.
    *
    * 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:
diff --git a/sdk/lib/async/future_impl.dart b/sdk/lib/async/future_impl.dart
index 4481da5..e2b548b 100644
--- a/sdk/lib/async/future_impl.dart
+++ b/sdk/lib/async/future_impl.dart
@@ -19,7 +19,7 @@
   void complete([FutureOr<T> value]);
 
   void completeError(Object error, [StackTrace stackTrace]) {
-    error = _nonNullError(error);
+    ArgumentError.checkNotNull(error, "error");
     if (!future._mayComplete) throw new StateError("Future already completed");
     AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
     if (replacement != null) {
@@ -94,8 +94,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;
@@ -293,8 +293,7 @@
   /// 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;
@@ -812,5 +811,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/lib/async/stream.dart b/sdk/lib/async/stream.dart
index ed95a05..203178a 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -132,6 +132,7 @@
    *
    * This stream emits a single error event of [error] and [stackTrace]
    * and then completes with a done event.
+   * The [error] must not be `null`.
    *
    * Example:
    * ```dart
@@ -152,11 +153,13 @@
    * stack trace as well.
    */
   @Since("2.5")
-  factory Stream.error(Object error, [StackTrace stackTrace]) =>
-      (_AsyncStreamController<T>(null, null, null, null)
-            .._addError(error, stackTrace)
-            .._closeUnchecked())
-          .stream;
+  factory Stream.error(Object error, [StackTrace stackTrace]) {
+    ArgumentError.checkNotNull(error, "error");
+    return (_AsyncStreamController<T>(null, null, null, null)
+          .._addError(error, stackTrace)
+          .._closeUnchecked())
+        .stream;
+  }
 
   /**
    * Creates a new single-subscription stream from the future.
@@ -1657,7 +1660,7 @@
    * Returns a future that is completed once the stream has finished
    * its cleanup.
    *
-   * For historical reasons, may also return `null` if no cleanup was necessary.
+   * Historically returned `null` if no cleanup was necessary.
    * Returning `null` is deprecated and should be avoided.
    *
    * Typically, futures are returned when the stream needs to release resources.
@@ -1665,11 +1668,10 @@
    * operation). If the listener wants to delete the file after having
    * canceled the subscription, it must wait for the cleanup future to complete.
    *
-   * A returned future completes with a `null` value.
    * 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.
@@ -1811,6 +1813,8 @@
   /**
    * Adds an [error] to the sink.
    *
+   * The [error] must not be `null`.
+   *
    * Must not be called on a closed sink.
    */
   void addError(Object error, [StackTrace stackTrace]);
diff --git a/sdk/lib/async/stream_controller.dart b/sdk/lib/async/stream_controller.dart
index 50e9aa3..b54ddac 100644
--- a/sdk/lib/async/stream_controller.dart
+++ b/sdk/lib/async/stream_controller.dart
@@ -237,7 +237,7 @@
   /**
    * Sends or enqueues an error event.
    *
-   * If [error] is `null`, it is replaced by a [NullThrownError].
+   * The [error] must not be `null`.
    *
    * Listeners receive this event at a later microtask. This behavior can be
    * overridden by using `sync` controllers. Note, however, that sync
@@ -361,6 +361,8 @@
   /**
    * Adds error to the controller's stream.
    *
+   * The [error] must not be `null`.
+   *
    * As [StreamController.addError], but must not be called while an event is
    * being added by [add], [addError] or [close].
    */
@@ -597,8 +599,11 @@
 
   /**
    * Send or enqueue an error event.
+   *
+   * The [error] must not be `null`.
    */
   void addError(Object error, [StackTrace stackTrace]) {
+    ArgumentError.checkNotNull(error, "error");
     if (!_mayAddEvent) throw _badEventState();
     error = _nonNullError(error);
     AsyncError replacement = Zone.current.errorCallback(error, stackTrace);
diff --git a/sdk/lib/async/stream_transformers.dart b/sdk/lib/async/stream_transformers.dart
index 7cba3ba..41c963f 100644
--- a/sdk/lib/async/stream_transformers.dart
+++ b/sdk/lib/async/stream_transformers.dart
@@ -234,6 +234,7 @@
   }
 
   void addError(Object error, [StackTrace stackTrace]) {
+    ArgumentError.checkNotNull(error, "error");
     if (_isClosed) {
       throw StateError("Sink is closed");
     }
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart
index d8f8596..83c0a80 100644
--- a/sdk/lib/async/zone.dart
+++ b/sdk/lib/async/zone.dart
@@ -43,7 +43,9 @@
   final Object error;
   final StackTrace stackTrace;
 
-  AsyncError(this.error, this.stackTrace);
+  AsyncError(this.error, this.stackTrace) {
+    ArgumentError.checkNotNull(error, "error");
+  }
 
   String toString() => '$error';
 }
@@ -750,6 +752,7 @@
   }
 
   AsyncError errorCallback(Zone zone, Object error, StackTrace stackTrace) {
+    ArgumentError.checkNotNull(error, "error");
     var implementation = _delegationTarget._errorCallback;
     _Zone implZone = implementation.zone;
     if (identical(implZone, _rootZone)) return null;
@@ -1065,6 +1068,7 @@
   }
 
   AsyncError errorCallback(Object error, StackTrace stackTrace) {
+    ArgumentError.checkNotNull(error, "error");
     var implementation = this._errorCallback;
     assert(implementation != null);
     final Zone implementationZone = implementation.zone;
@@ -1109,8 +1113,11 @@
 
 void _rootHandleUncaughtError(
     Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) {
+  if (error == null) {
+    error = ArgumentError.notNull("error");
+    stackTrace = StackTrace.current;
+  }
   _schedulePriorityAsyncCallback(() {
-    error ??= new NullThrownError();
     if (stackTrace == null) throw error;
     _rethrow(error, stackTrace);
   });
diff --git a/sdk/lib/convert/chunked_conversion.dart b/sdk/lib/convert/chunked_conversion.dart
index 7253981..3b67c3a 100644
--- a/sdk/lib/convert/chunked_conversion.dart
+++ b/sdk/lib/convert/chunked_conversion.dart
@@ -75,6 +75,7 @@
   }
 
   void addError(Object error, [StackTrace stackTrace]) {
+    ArgumentError.checkNotNull(error, "error");
     _eventSink.addError(error, stackTrace);
   }
 
diff --git a/sdk/lib/core/bool.dart b/sdk/lib/core/bool.dart
index f2ecf08..ae8341b 100644
--- a/sdk/lib/core/bool.dart
+++ b/sdk/lib/core/bool.dart
@@ -51,6 +51,35 @@
   external const factory bool.fromEnvironment(String name,
       {bool defaultValue = false});
 
+  /// Whether there is an environment declaration [name].
+  ///
+  /// Returns true iff there is an environment declaration with the name [name]
+  /// If there is then the value of that declaration can be accessed using
+  /// `const String.fromEnvironment(name)`. Otherwise,
+  /// `String.fromEnvironment(name, defaultValue: someString)`
+  /// will evaluate to the given `defaultValue`.
+  ///
+  /// This constructor can be used to handle an absent declaration
+  /// specifically, in ways that cannot be represented by providing
+  /// a default value to the `C.fromEnvironment` constructor where `C`
+  /// is [String], [int], or [bool].
+  ///
+  /// Example:
+  /// ```dart
+  /// const loggingIsDeclared = const bool.hasEnvironment("logging");
+  ///
+  /// const String? logger = loggingIsDeclared
+  ///     ? String.fromEnvironment("logging")
+  ///     : null;
+  /// ```
+  // The .hasEnvironment() constructor is special in that we do not want
+  // users to call them using "new". We prohibit that by giving them bodies
+  // that throw, even though const constructors are not allowed to have bodies.
+  // Disable those static errors.
+  //ignore: const_constructor_with_body
+  //ignore: const_factory
+  external const factory bool.hasEnvironment(String name);
+
   external int get hashCode;
 
   /// The logical conjunction ("and") of this and [other].
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index de1ec2c..cd1b43d 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.dart
@@ -186,8 +186,13 @@
   /// If [parent] is provided, the parent's task ID is provided as argument
   /// 'parentId' when [start] is called. In DevTools, this argument will result
   /// in this [TimelineTask] being linked to the [parent] [TimelineTask].
-  TimelineTask({TimelineTask parent})
+  ///
+  /// If [filterKey] is provided, a property named `filterKey` will be inserted
+  /// into the arguments of each event associated with this task. The
+  /// `filterKey` will be set to the value of [filterKey].
+  TimelineTask({TimelineTask parent, String filterKey})
       : _parent = parent,
+        _filterKey = filterKey,
         _taskId = _getNextAsyncId() {}
 
   /// Create a task with an explicit [taskId]. This is useful if you are
@@ -196,8 +201,13 @@
   /// Important note: only provide task IDs which have been obtained as a
   /// result of invoking [TimelineTask.pass]. Specifying a custom ID can lead
   /// to ID collisions, resulting in incorrect rendering of timeline events.
-  TimelineTask.withTaskId(int taskId)
+  ///
+  /// If [filterKey] is provided, a property named `filterKey` will be inserted
+  /// into the arguments of each event associated with this task. The
+  /// `filterKey` will be set to the value of [filterKey].
+  TimelineTask.withTaskId(int taskId, {String filterKey})
       : _parent = null,
+        _filterKey = filterKey,
         _taskId = taskId {
     ArgumentError.checkNotNull(taskId, 'taskId');
   }
@@ -212,6 +222,7 @@
     block._start({
       if (arguments != null) ...arguments,
       if (_parent != null) 'parentId': _parent._taskId.toRadixString(16),
+      if (_filterKey != null) _kFilterKey: _filterKey,
     });
   }
 
@@ -224,6 +235,10 @@
     if (arguments != null) {
       instantArguments = new Map.from(arguments);
     }
+    if (_filterKey != null) {
+      instantArguments ??= {};
+      instantArguments[_kFilterKey] = _filterKey;
+    }
     _reportTaskEvent(
         _taskId, 'n', 'Dart', name, _argumentsAsJson(instantArguments));
   }
@@ -237,6 +252,10 @@
     if (_stack.length == 0) {
       throw new StateError('Uneven calls to start and finish');
     }
+    if (_filterKey != null) {
+      arguments ??= {};
+      arguments[_kFilterKey] = _filterKey;
+    }
     // Pop top item off of stack.
     var block = _stack.removeLast();
     block._finish(arguments);
@@ -254,7 +273,9 @@
     return r;
   }
 
+  static const String _kFilterKey = 'filterKey';
   final TimelineTask _parent;
+  final String _filterKey;
   final int _taskId;
   final List<_AsyncBlock> _stack = [];
 }
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index f4ba2c4..54dbc0d 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -217,6 +217,11 @@
         "uri": "math/math.dart",
         "patches": "_internal/js_runtime/lib/math_patch.dart"
       },
+      "mirrors": {
+        "uri": "mirrors/mirrors.dart",
+        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+        "supported": false
+      },
       "typed_data": {
         "uri": "typed_data/typed_data.dart",
         "patches": "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -322,6 +327,11 @@
         "uri": "math/math.dart",
         "patches": "_internal/js_runtime/lib/math_patch.dart"
       },
+      "mirrors": {
+        "uri": "mirrors/mirrors.dart",
+        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+        "supported": false
+      },
       "typed_data": {
         "uri": "typed_data/typed_data.dart",
         "patches": "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -428,6 +438,11 @@
         "patches": "_internal/js_dev_runtime/patch/isolate_patch.dart",
         "supported": false
       },
+      "mirrors": {
+        "uri": "mirrors/mirrors.dart",
+        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+        "supported": false
+      },
       "math": {
         "uri": "math/math.dart",
         "patches": "_internal/js_dev_runtime/patch/math_patch.dart"
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index cbf0080..8944e12 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -214,6 +214,11 @@
       uri: "math/math.dart"
       patches: "_internal/js_runtime/lib/math_patch.dart"
 
+    mirrors:
+      uri: "mirrors/mirrors.dart"
+      patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+      supported: false
+
     typed_data:
       uri: "typed_data/typed_data.dart"
       patches: "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -317,6 +322,11 @@
       uri: "math/math.dart"
       patches: "_internal/js_runtime/lib/math_patch.dart"
 
+    mirrors:
+      uri: "mirrors/mirrors.dart"
+      patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+      supported: false
+
     typed_data:
       uri: "typed_data/typed_data.dart"
       patches: "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -421,6 +431,11 @@
         patches: "_internal/js_dev_runtime/patch/isolate_patch.dart"
         supported: false
 
+      mirrors:
+        uri: "mirrors/mirrors.dart"
+        patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+        supported: false
+
       math:
         uri: "math/math.dart"
         patches: "_internal/js_dev_runtime/patch/math_patch.dart"
diff --git a/sdk_nnbd/lib/_http/http_impl.dart b/sdk_nnbd/lib/_http/http_impl.dart
index a63bf64..5b9782a 100644
--- a/sdk_nnbd/lib/_http/http_impl.dart
+++ b/sdk_nnbd/lib/_http/http_impl.dart
@@ -2257,8 +2257,6 @@
   static void _startRequestTimelineEvent(
       TimelineTask? timeline, String method, Uri uri) {
     timeline?.start('HTTP CLIENT ${method.toUpperCase()}', arguments: {
-      'filterKey':
-          'HTTP/client', // key used to filter network requests from timeline
       'method': method.toUpperCase(),
       'uri': uri.toString(),
     });
@@ -2305,7 +2303,7 @@
     TimelineTask? timeline;
     // TODO(bkonyi): do we want this to be opt-in?
     if (HttpClient.enableTimelineLogging) {
-      timeline = TimelineTask();
+      timeline = TimelineTask(filterKey: 'HTTP/client');
       _startRequestTimelineEvent(timeline, method, uri);
     }
     return _getConnection(uri.host, port, proxyConf, isSecure, timeline).then(
diff --git a/sdk_nnbd/lib/_http/websocket_impl.dart b/sdk_nnbd/lib/_http/websocket_impl.dart
index 4afba79..64eb1eb 100644
--- a/sdk_nnbd/lib/_http/websocket_impl.dart
+++ b/sdk_nnbd/lib/_http/websocket_impl.dart
@@ -113,6 +113,8 @@
   }
 
   void addError(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     _eventSink!.addError(error, stackTrace);
   }
 
@@ -722,6 +724,8 @@
   }
 
   void addError(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     _eventSink!.addError(error, stackTrace);
   }
 
@@ -1216,6 +1220,7 @@
   }
 
   void addUtf8Text(List<int> bytes) {
+    // TODO(40614): Remove once non-nullability is sound.
     ArgumentError.checkNotNull(bytes, "bytes");
     _sink.add(new _EncodedString(bytes));
   }
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 78ba91b..dbba91e 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
@@ -417,6 +417,7 @@
   }
 
   void addError(Object error, StackTrace stackTrace) {
+    ArgumentError.checkNotNull(error, "error");
     var completer = cancellationCompleter;
     if (completer != null && !completer.isCompleted) {
       // If the stream has been cancelled, complete the cancellation future
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 9b20059..13c2f4c 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
@@ -693,6 +693,13 @@
   }
 
   @patch
+  factory bool.hasEnvironment(String name) {
+    // ignore: const_constructor_throws_exception
+    throw UnsupportedError(
+        'bool.hasEnvironment can only be used as a const constructor');
+  }
+
+  @patch
   int get hashCode => super.hashCode;
 
   @JSExportName('is')
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
index bd293d6..0a8a274 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/js_helper.dart
@@ -591,7 +591,7 @@
 
     // Type inference does not understand that [name] is now always a non-null
     // String. (There is some imprecision in the negation of the disjunction.)
-    name = JS('String', '#', name);
+    name = JS<String>('String', '#', name);
 
     // TODO(kasperl): If the namer gave us a fresh global name, we may
     // want to remove the numeric suffix that makes it unique too.
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
new file mode 100644
index 0000000..cd961a0
--- /dev/null
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/mirrors_patch_cfe.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Patch library for dart:mirrors.
+
+import 'dart:_js_helper' show patch;
+import 'dart:mirrors';
+
+const String _message = 'dart:mirrors is no longer supported for web apps';
+
+@patch
+MirrorSystem currentMirrorSystem() => throw new UnsupportedError(_message);
+
+@patch
+InstanceMirror reflect(dynamic reflectee) =>
+    throw new UnsupportedError(_message);
+
+@patch
+ClassMirror reflectClass(Type key) => throw new UnsupportedError(_message);
+
+@patch
+TypeMirror reflectType(Type key, [List<Type> typeArguments]) =>
+    throw new UnsupportedError(_message);
+
+@patch
+abstract class MirrorSystem {
+  Map<Uri, LibraryMirror> get libraries;
+  IsolateMirror get isolate;
+  TypeMirror get dynamicType;
+  TypeMirror get voidType;
+  TypeMirror get neverType;
+
+  @patch
+  LibraryMirror findLibrary(Symbol libraryName) =>
+      throw new UnsupportedError(_message);
+
+  @patch
+  static String getName(Symbol symbol) => throw new UnsupportedError(_message);
+
+  @patch
+  static Symbol getSymbol(String name, [LibraryMirror library]) =>
+      throw new UnsupportedError(_message);
+}
diff --git a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
index 838643b..690efb3 100644
--- a/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk_nnbd/lib/_internal/js_runtime/lib/rti.dart
@@ -445,7 +445,7 @@
   String key = Rti._getCanonicalRecipe(instantiationRti);
   var probe = _Utils.mapGet(cache, key);
   if (probe != null) return _castToRti(probe);
-  Rti rti = _instantiate(_theUniverse(),
+  Rti rti = _substitute(_theUniverse(),
       Rti._getGenericFunctionBase(genericFunctionRti), typeArguments, 0);
   _Utils.mapSet(cache, key, rti);
   return rti;
@@ -459,7 +459,11 @@
 /// [depth] is the number of subsequent generic function parameters that are in
 /// scope. This is subtracted off the de Bruijn index for the type parameter to
 /// arrive at an potential index into [typeArguments].
-Rti _instantiate(universe, Rti rti, Object typeArguments, int depth) {
+///
+/// In order to do a partial substitution - that is, substituting only some
+/// type parameters rather than all of them - we encode the unsubstituted
+/// positions of the argument list as `undefined` or `null`.
+Rti _substitute(universe, Rti rti, Object typeArguments, int depth) {
   int kind = Rti._getKind(rti);
   switch (kind) {
     case Rti.kindErased:
@@ -470,95 +474,99 @@
       return rti;
     case Rti.kindStar:
       Rti baseType = _castToRti(Rti._getPrimary(rti));
-      Rti instantiatedBaseType =
-          _instantiate(universe, baseType, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBaseType, baseType)) return rti;
-      return _Universe._lookupStarRti(universe, instantiatedBaseType, true);
+      Rti substitutedBaseType =
+          _substitute(universe, baseType, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBaseType, baseType)) return rti;
+      return _Universe._lookupStarRti(universe, substitutedBaseType, true);
     case Rti.kindQuestion:
       Rti baseType = _castToRti(Rti._getPrimary(rti));
-      Rti instantiatedBaseType =
-          _instantiate(universe, baseType, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBaseType, baseType)) return rti;
-      return _Universe._lookupQuestionRti(universe, instantiatedBaseType, true);
+      Rti substitutedBaseType =
+          _substitute(universe, baseType, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBaseType, baseType)) return rti;
+      return _Universe._lookupQuestionRti(universe, substitutedBaseType, true);
     case Rti.kindFutureOr:
       Rti baseType = _castToRti(Rti._getPrimary(rti));
-      Rti instantiatedBaseType =
-          _instantiate(universe, baseType, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBaseType, baseType)) return rti;
-      return _Universe._lookupFutureOrRti(universe, instantiatedBaseType, true);
+      Rti substitutedBaseType =
+          _substitute(universe, baseType, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBaseType, baseType)) return rti;
+      return _Universe._lookupFutureOrRti(universe, substitutedBaseType, true);
     case Rti.kindInterface:
       Object interfaceTypeArguments = Rti._getInterfaceTypeArguments(rti);
-      Object instantiatedInterfaceTypeArguments = _instantiateArray(
+      Object substitutedInterfaceTypeArguments = _substituteArray(
           universe, interfaceTypeArguments, typeArguments, depth);
       if (_Utils.isIdentical(
-          instantiatedInterfaceTypeArguments, interfaceTypeArguments))
+          substitutedInterfaceTypeArguments, interfaceTypeArguments))
         return rti;
       return _Universe._lookupInterfaceRti(universe, Rti._getInterfaceName(rti),
-          instantiatedInterfaceTypeArguments);
+          substitutedInterfaceTypeArguments);
     case Rti.kindBinding:
       Rti base = Rti._getBindingBase(rti);
-      Rti instantiatedBase = _instantiate(universe, base, typeArguments, depth);
+      Rti substitutedBase = _substitute(universe, base, typeArguments, depth);
       Object arguments = Rti._getBindingArguments(rti);
-      Object instantiatedArguments =
-          _instantiateArray(universe, arguments, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBase, base) &&
-          _Utils.isIdentical(instantiatedArguments, arguments)) return rti;
+      Object substitutedArguments =
+          _substituteArray(universe, arguments, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBase, base) &&
+          _Utils.isIdentical(substitutedArguments, arguments)) return rti;
       return _Universe._lookupBindingRti(
-          universe, instantiatedBase, instantiatedArguments);
+          universe, substitutedBase, substitutedArguments);
     case Rti.kindFunction:
       Rti returnType = Rti._getReturnType(rti);
-      Rti instantiatedReturnType =
-          _instantiate(universe, returnType, typeArguments, depth);
+      Rti substitutedReturnType =
+          _substitute(universe, returnType, typeArguments, depth);
       _FunctionParameters functionParameters = Rti._getFunctionParameters(rti);
-      _FunctionParameters instantiatedFunctionParameters =
-          _instantiateFunctionParameters(
+      _FunctionParameters substitutedFunctionParameters =
+          _substituteFunctionParameters(
               universe, functionParameters, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedReturnType, returnType) &&
-          _Utils.isIdentical(
-              instantiatedFunctionParameters, functionParameters)) return rti;
+      if (_Utils.isIdentical(substitutedReturnType, returnType) &&
+          _Utils.isIdentical(substitutedFunctionParameters, functionParameters))
+        return rti;
       return _Universe._lookupFunctionRti(
-          universe, instantiatedReturnType, instantiatedFunctionParameters);
+          universe, substitutedReturnType, substitutedFunctionParameters);
     case Rti.kindGenericFunction:
       Object bounds = Rti._getGenericFunctionBounds(rti);
       depth += _Utils.arrayLength(bounds);
-      Object instantiatedBounds =
-          _instantiateArray(universe, bounds, typeArguments, depth);
+      Object substitutedBounds =
+          _substituteArray(universe, bounds, typeArguments, depth);
       Rti base = Rti._getGenericFunctionBase(rti);
-      Rti instantiatedBase = _instantiate(universe, base, typeArguments, depth);
-      if (_Utils.isIdentical(instantiatedBounds, bounds) &&
-          _Utils.isIdentical(instantiatedBase, base)) return rti;
+      Rti substitutedBase = _substitute(universe, base, typeArguments, depth);
+      if (_Utils.isIdentical(substitutedBounds, bounds) &&
+          _Utils.isIdentical(substitutedBase, base)) return rti;
       return _Universe._lookupGenericFunctionRti(
-          universe, instantiatedBase, instantiatedBounds);
+          universe, substitutedBase, substitutedBounds, true);
     case Rti.kindGenericFunctionParameter:
       int index = Rti._getGenericFunctionParameterIndex(rti);
-      if (index < depth) {
-        throw AssertionError(
-            'Unexpected index $index at instantiation depth $depth');
-      }
-      return _castToRti(_Utils.arrayAt(typeArguments, index - depth));
+      // Indices below the current depth are out of scope for substitution and
+      // can be returned unchanged.
+      if (index < depth) return rti;
+      var argument = _Utils.arrayAt(typeArguments, index - depth);
+      // In order to do a partial substitution - that is, substituting only some
+      // type parameters rather than all of them - we encode the unsubstituted
+      // positions of the argument list as `undefined` (which will compare equal
+      // to `null`).
+      if (argument == null) return rti;
+      return _castToRti(argument);
     default:
-      throw AssertionError(
-          'Attempted to instantiate unexpected RTI kind $kind');
+      throw AssertionError('Attempted to substitute unexpected RTI kind $kind');
   }
 }
 
-Object _instantiateArray(
+Object _substituteArray(
     universe, Object rtiArray, Object typeArguments, int depth) {
   bool changed = false;
   int length = _Utils.arrayLength(rtiArray);
   Object result = JS('', '[]');
   for (int i = 0; i < length; i++) {
     Rti rti = _castToRti(_Utils.arrayAt(rtiArray, i));
-    Rti instantiatedRti = _instantiate(universe, rti, typeArguments, depth);
-    if (_Utils.isNotIdentical(instantiatedRti, rti)) {
+    Rti substitutedRti = _substitute(universe, rti, typeArguments, depth);
+    if (_Utils.isNotIdentical(substitutedRti, rti)) {
       changed = true;
     }
-    _Utils.arrayPush(result, instantiatedRti);
+    _Utils.arrayPush(result, substitutedRti);
   }
   return changed ? result : rtiArray;
 }
 
-Object _instantiateNamed(
+Object _substituteNamed(
     universe, Object namedArray, Object typeArguments, int depth) {
   bool changed = false;
   int length = _Utils.arrayLength(namedArray);
@@ -567,41 +575,41 @@
   for (int i = 0; i < length; i += 2) {
     String name = _Utils.asString(_Utils.arrayAt(namedArray, i));
     Rti rti = _castToRti(_Utils.arrayAt(namedArray, i + 1));
-    Rti instantiatedRti = _instantiate(universe, rti, typeArguments, depth);
-    if (_Utils.isNotIdentical(instantiatedRti, rti)) {
+    Rti substitutedRti = _substitute(universe, rti, typeArguments, depth);
+    if (_Utils.isNotIdentical(substitutedRti, rti)) {
       changed = true;
     }
     _Utils.arrayPush(result, name);
-    _Utils.arrayPush(result, instantiatedRti);
+    _Utils.arrayPush(result, substitutedRti);
   }
   return changed ? result : namedArray;
 }
 
 // TODO(fishythefish): Support required named parameters.
-_FunctionParameters _instantiateFunctionParameters(universe,
+_FunctionParameters _substituteFunctionParameters(universe,
     _FunctionParameters functionParameters, Object typeArguments, int depth) {
   Object requiredPositional =
       _FunctionParameters._getRequiredPositional(functionParameters);
-  Object instantiatedRequiredPositional =
-      _instantiateArray(universe, requiredPositional, typeArguments, depth);
+  Object substitutedRequiredPositional =
+      _substituteArray(universe, requiredPositional, typeArguments, depth);
   Object optionalPositional =
       _FunctionParameters._getOptionalPositional(functionParameters);
-  Object instantiatedOptionalPositional =
-      _instantiateArray(universe, optionalPositional, typeArguments, depth);
+  Object substitutedOptionalPositional =
+      _substituteArray(universe, optionalPositional, typeArguments, depth);
   Object optionalNamed =
       _FunctionParameters._getOptionalNamed(functionParameters);
-  Object instantiatedOptionalNamed =
-      _instantiateNamed(universe, optionalNamed, typeArguments, depth);
-  if (_Utils.isIdentical(instantiatedRequiredPositional, requiredPositional) &&
-      _Utils.isIdentical(instantiatedOptionalPositional, optionalPositional) &&
-      _Utils.isIdentical(instantiatedOptionalNamed, optionalNamed))
+  Object substitutedOptionalNamed =
+      _substituteNamed(universe, optionalNamed, typeArguments, depth);
+  if (_Utils.isIdentical(substitutedRequiredPositional, requiredPositional) &&
+      _Utils.isIdentical(substitutedOptionalPositional, optionalPositional) &&
+      _Utils.isIdentical(substitutedOptionalNamed, optionalNamed))
     return functionParameters;
   _FunctionParameters result = _FunctionParameters.allocate();
   _FunctionParameters._setRequiredPositional(
-      result, instantiatedRequiredPositional);
+      result, substitutedRequiredPositional);
   _FunctionParameters._setOptionalPositional(
-      result, instantiatedOptionalPositional);
-  _FunctionParameters._setOptionalNamed(result, instantiatedOptionalNamed);
+      result, substitutedOptionalPositional);
+  _FunctionParameters._setOptionalNamed(result, substitutedOptionalNamed);
   return result;
 }
 
@@ -1959,19 +1967,44 @@
       _canonicalRecipeJoin(bounds) +
       Recipe.endTypeArgumentsString;
 
-  // TODO(fishythefish): Normalize `X extends Never` to `Never`.
   static Rti _lookupGenericFunctionRti(
-      Object universe, Rti baseFunctionType, Object bounds) {
+      Object universe, Rti baseFunctionType, Object bounds, bool normalize) {
     String key = _canonicalRecipeOfGenericFunction(baseFunctionType, bounds);
     var cache = evalCache(universe);
     var probe = _cacheGet(cache, key);
     if (probe != null) return _castToRti(probe);
-    return _installRti(universe, key,
-        _createGenericFunctionRti(universe, baseFunctionType, bounds, key));
+    return _installRti(
+        universe,
+        key,
+        _createGenericFunctionRti(
+            universe, baseFunctionType, bounds, key, normalize));
   }
 
-  static Rti _createGenericFunctionRti(
-      Object universe, Rti baseFunctionType, Object bounds, String key) {
+  static Rti _createGenericFunctionRti(Object universe, Rti baseFunctionType,
+      Object bounds, String key, bool normalize) {
+    if (normalize) {
+      int length = _Utils.arrayLength(bounds);
+      int count = 0;
+      Object typeArguments = JS('', 'new Array(#)', length);
+      for (int i = 0; i < length; i++) {
+        Rti bound = _castToRti(_Utils.arrayAt(bounds, i));
+        if (Rti._getKind(bound) == Rti.kindNever) {
+          _Utils.arraySetAt(typeArguments, i, bound);
+          count++;
+        }
+      }
+      if (count > 0) {
+        var substitutedBase =
+            _substitute(universe, baseFunctionType, typeArguments, 0);
+        var substitutedBounds =
+            _substituteArray(universe, bounds, typeArguments, 0);
+        return _lookupGenericFunctionRti(
+            universe,
+            substitutedBase,
+            substitutedBounds,
+            _Utils.isNotIdentical(bounds, substitutedBounds));
+      }
+    }
     Rti rti = Rti.allocate();
     Rti._setKind(rti, Rti.kindGenericFunction);
     Rti._setPrimary(rti, baseFunctionType);
@@ -2311,8 +2344,10 @@
       Rti base = toType(universe, environment(parser), head);
       switch (Rti._getKind(base)) {
         case Rti.kindFunction:
-          push(stack,
-              _Universe._lookupGenericFunctionRti(universe, base, arguments));
+          push(
+              stack,
+              _Universe._lookupGenericFunctionRti(
+                  universe, base, arguments, normalize(parser)));
           break;
 
         default:
@@ -2827,6 +2862,10 @@
   // interface, so rather than iterating over the Ci, we can instead look up
   // [t] in our ruleset.
   // TODO(fishythefish): Handle variance correctly.
+
+  // We don't list Object explicitly as a supertype of each interface, so check
+  // this trivial case first.
+  if (isObjectType(t)) return true;
   Object? rule = _Universe.findRule(universe, sName);
   if (rule == null) return false;
   var supertypeArgs = TypeRule.lookupSupertype(rule, tName);
diff --git a/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart
index b2b57d7..9e180a2 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/async_patch.dart
@@ -214,6 +214,8 @@
   }
 
   void addError(Object error, StackTrace stackTrace) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     final future = cancellationFuture;
     if ((future != null) && future._mayComplete) {
       // If the stream has been cancelled, complete the cancellation future
diff --git a/sdk_nnbd/lib/_internal/vm/lib/bool_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/bool_patch.dart
index 8fffd63..d627d46 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/bool_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/bool_patch.dart
@@ -12,6 +12,9 @@
       native "Bool_fromEnvironment";
 
   @patch
+  const factory bool.hasEnvironment(String name) native "Bool_hasEnvironment";
+
+  @patch
   int get hashCode => this ? 1231 : 1237;
 
   int get _identityHashCode => this ? 1231 : 1237;
diff --git a/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart b/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
index 5105075..e4dcee5 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/growable_array.dart
@@ -10,12 +10,11 @@
     if ((index < 0) || (index > length)) {
       throw new RangeError.range(index, 0, length);
     }
-    if (index == this.length) {
-      add(element);
+    int oldLength = this.length;
+    add(element);
+    if (index == oldLength) {
       return;
     }
-    int oldLength = this.length;
-    this.length++;
     Lists.copy(this, index, this, index + 1, oldLength - index);
     this[index] = element;
   }
@@ -52,7 +51,15 @@
     // There might be errors after the length change, in which case the list
     // will end up being modified but the operation not complete. Unless we
     // always go through a "toList" we can't really avoid that.
-    this.length += insertionLength;
+    int capacity = _capacity;
+    int newLength = length + insertionLength;
+    if (newLength > capacity) {
+      do {
+        capacity = _nextCapacity(capacity);
+      } while (newLength > capacity);
+      _grow(capacity);
+    }
+    _setLength(newLength);
     setRange(index + insertionLength, this.length, this, index);
     setAll(index, iterable);
   }
diff --git a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
index 7379f0c..6ed550a 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirrors_impl.dart
@@ -1474,9 +1474,8 @@
     return classMirror;
   }
 
-  static TypeMirror reflectType(Type key,
-      [List<Type> typeArguments = const <Type>[]]) {
-    if (typeArguments.length != 0) {
+  static TypeMirror reflectType(Type key, [List<Type>? typeArguments]) {
+    if (typeArguments != null) {
       key = _instantiateType(key, typeArguments);
     }
     var typeMirror = _instantiationCache[key];
diff --git a/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart b/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart
index 4fd4d31..a06d546 100644
--- a/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart
+++ b/sdk_nnbd/lib/_internal/vm/lib/mirrors_patch.dart
@@ -50,7 +50,7 @@
 }
 
 @patch
-TypeMirror reflectType(Type key, [List<Type> typeArguments = const <Type>[]]) {
+TypeMirror reflectType(Type key, [List<Type>? typeArguments]) {
   return _Mirrors.reflectType(key, typeArguments);
 }
 
diff --git a/sdk_nnbd/lib/async/broadcast_stream_controller.dart b/sdk_nnbd/lib/async/broadcast_stream_controller.dart
index ec0bae3..9a80aab 100644
--- a/sdk_nnbd/lib/async/broadcast_stream_controller.dart
+++ b/sdk_nnbd/lib/async/broadcast_stream_controller.dart
@@ -248,6 +248,8 @@
   }
 
   void addError(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     if (!_mayAddEvent) throw _addEventError();
     AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
     if (replacement != null) {
@@ -476,6 +478,8 @@
   }
 
   void addError(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     if (!isClosed && _isFiring) {
       _addPendingEvent(new _DelayedError(error, stackTrace));
       return;
diff --git a/sdk_nnbd/lib/async/future.dart b/sdk_nnbd/lib/async/future.dart
index a489a6a..62aef45 100644
--- a/sdk_nnbd/lib/async/future.dart
+++ b/sdk_nnbd/lib/async/future.dart
@@ -257,6 +257,7 @@
    *
    * Use [Completer] to create a future and complete it later.
    */
+  @pragma("vm:entry-point")
   factory Future.value([FutureOr<T>? value]) {
     return new _Future<T>.immediate(value as FutureOr<T>);
   }
@@ -269,11 +270,11 @@
    * If an error handler isn't added before the future completes, the error
    * will be considered unhandled.
    *
-   * If [error] is `null`, it is replaced by a [NullThrownError].
-   *
    * Use [Completer] to create a future and complete it later.
    */
   factory Future.error(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     if (!identical(Zone.current, _rootZone)) {
       AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
       if (replacement != null) {
diff --git a/sdk_nnbd/lib/async/future_impl.dart b/sdk_nnbd/lib/async/future_impl.dart
index c012e53..e469175 100644
--- a/sdk_nnbd/lib/async/future_impl.dart
+++ b/sdk_nnbd/lib/async/future_impl.dart
@@ -17,6 +17,8 @@
   void complete([FutureOr<T>? value]);
 
   void completeError(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     if (!future._mayComplete) throw new StateError("Future already completed");
     AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
     if (replacement != null) {
diff --git a/sdk_nnbd/lib/async/stream.dart b/sdk_nnbd/lib/async/stream.dart
index 3969f20..c35d8a8 100644
--- a/sdk_nnbd/lib/async/stream.dart
+++ b/sdk_nnbd/lib/async/stream.dart
@@ -150,11 +150,14 @@
    * stack trace as well.
    */
   @Since("2.5")
-  factory Stream.error(Object error, [StackTrace? stackTrace]) =>
-      (_AsyncStreamController<T>(null, null, null, null)
-            .._addError(error, stackTrace)
-            .._closeUnchecked())
-          .stream;
+  factory Stream.error(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
+    return (_AsyncStreamController<T>(null, null, null, null)
+          .._addError(error, stackTrace)
+          .._closeUnchecked())
+        .stream;
+  }
 
   /**
    * Creates a new single-subscription stream from the future.
@@ -1607,15 +1610,11 @@
    * Returns a future that is completed once the stream has finished
    * its cleanup.
    *
-   * For historical reasons, may also return `null` if no cleanup was necessary.
-   * Returning `null` is deprecated and should be avoided.
-   *
-   * Typically, futures are returned when the stream needs to release resources.
+   * Typically, cleanup happens when the stream needs to release resources.
    * For example, a stream might need to close an open file (as an asynchronous
    * operation). If the listener wants to delete the file after having
    * canceled the subscription, it must wait for the cleanup future to complete.
    *
-   * A returned future completes with a `null` value.
    * If the cleanup throws, which it really shouldn't, the returned future
    * completes with that error.
    */
diff --git a/sdk_nnbd/lib/async/stream_controller.dart b/sdk_nnbd/lib/async/stream_controller.dart
index 31fc5c3..3f3f461 100644
--- a/sdk_nnbd/lib/async/stream_controller.dart
+++ b/sdk_nnbd/lib/async/stream_controller.dart
@@ -600,6 +600,8 @@
    * Send or enqueue an error event.
    */
   void addError(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     if (!_mayAddEvent) throw _badEventState();
     AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
     if (replacement != null) {
diff --git a/sdk_nnbd/lib/async/stream_transformers.dart b/sdk_nnbd/lib/async/stream_transformers.dart
index 3e332b4..b445d66 100644
--- a/sdk_nnbd/lib/async/stream_transformers.dart
+++ b/sdk_nnbd/lib/async/stream_transformers.dart
@@ -229,6 +229,8 @@
   }
 
   void addError(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     var sink = _sink;
     if (sink == null) {
       throw StateError("Sink is closed");
diff --git a/sdk_nnbd/lib/async/zone.dart b/sdk_nnbd/lib/async/zone.dart
index 31644f2..2fc47b8 100644
--- a/sdk_nnbd/lib/async/zone.dart
+++ b/sdk_nnbd/lib/async/zone.dart
@@ -41,7 +41,10 @@
   final Object error;
   final StackTrace? stackTrace;
 
-  AsyncError(this.error, this.stackTrace);
+  AsyncError(this.error, this.stackTrace) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
+  }
 
   String toString() => '$error';
 }
@@ -742,6 +745,8 @@
   }
 
   AsyncError? errorCallback(Zone zone, Object error, StackTrace? stackTrace) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     var implementation = _delegationTarget._errorCallback;
     _Zone implZone = implementation.zone;
     if (identical(implZone, _rootZone)) return null;
@@ -1075,6 +1080,8 @@
   }
 
   AsyncError? errorCallback(Object error, StackTrace? stackTrace) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     var implementation = this._errorCallback;
     final _Zone implementationZone = implementation.zone;
     if (identical(implementationZone, _rootZone)) return null;
diff --git a/sdk_nnbd/lib/convert/chunked_conversion.dart b/sdk_nnbd/lib/convert/chunked_conversion.dart
index 654c9d2..d2c24f0 100644
--- a/sdk_nnbd/lib/convert/chunked_conversion.dart
+++ b/sdk_nnbd/lib/convert/chunked_conversion.dart
@@ -73,6 +73,8 @@
   }
 
   void addError(Object error, [StackTrace? stackTrace]) {
+    // TODO(40614): Remove once non-nullability is sound.
+    ArgumentError.checkNotNull(error, "error");
     _eventSink.addError(error, stackTrace);
   }
 
diff --git a/sdk_nnbd/lib/core/bool.dart b/sdk_nnbd/lib/core/bool.dart
index 8d420fc..3d35d80 100644
--- a/sdk_nnbd/lib/core/bool.dart
+++ b/sdk_nnbd/lib/core/bool.dart
@@ -49,6 +49,35 @@
   external const factory bool.fromEnvironment(String name,
       {bool defaultValue = false});
 
+  /// Whether there is an environment declaration [name].
+  ///
+  /// Returns true iff there is an environment declaration with the name [name]
+  /// If there is then the value of that declaration can be accessed using
+  /// `const String.fromEnvironment(name)`. Otherwise,
+  /// `String.fromEnvironment(name, defaultValue: someString)`
+  /// will evaluate to the given `defaultValue`.
+  ///
+  /// This constructor can be used to handle an absent declaration
+  /// specifically, in ways that cannot be represented by providing
+  /// a default value to the `C.fromEnvironment` constructor where `C`
+  /// is [String], [int], or [bool].
+  ///
+  /// Example:
+  /// ```dart
+  /// const loggingIsDeclared = const bool.hasEnvironment("logging");
+  ///
+  /// const String? logger = loggingIsDeclared
+  ///     ? String.fromEnvironment("logging")
+  ///     : null;
+  /// ```
+  // The .hasEnvironment() constructor is special in that we do not want
+  // users to call them using "new". We prohibit that by giving them bodies
+  // that throw, even though const constructors are not allowed to have bodies.
+  // Disable those static errors.
+  //ignore: const_constructor_with_body
+  //ignore: const_factory
+  external const factory bool.hasEnvironment(String name);
+
   external int get hashCode;
 
   /// The logical conjunction ("and") of this and [other].
diff --git a/sdk_nnbd/lib/developer/timeline.dart b/sdk_nnbd/lib/developer/timeline.dart
index c41d814..cc9cf40 100644
--- a/sdk_nnbd/lib/developer/timeline.dart
+++ b/sdk_nnbd/lib/developer/timeline.dart
@@ -186,8 +186,13 @@
   /// If [parent] is provided, the parent's task ID is provided as argument
   /// 'parentId' when [start] is called. In DevTools, this argument will result
   /// in this [TimelineTask] being linked to the [parent] [TimelineTask].
-  TimelineTask({TimelineTask? parent})
+  ///
+  /// If [filterKey] is provided, a property named `filterKey` will be inserted
+  /// into the arguments of each event associated with this task. The
+  /// `filterKey` will be set to the value of [filterKey].
+  TimelineTask({TimelineTask? parent, String? filterKey})
       : _parent = parent,
+        _filterKey = filterKey,
         _taskId = _getNextAsyncId() {}
 
   /// Create a task with an explicit [taskId]. This is useful if you are
@@ -196,8 +201,13 @@
   /// Important note: only provide task IDs which have been obtained as a
   /// result of invoking [TimelineTask.pass]. Specifying a custom ID can lead
   /// to ID collisions, resulting in incorrect rendering of timeline events.
-  TimelineTask.withTaskId(int taskId)
+  ///
+  /// If [filterKey] is provided, a property named `filterKey` will be inserted
+  /// into the arguments of each event associated with this task. The
+  /// `filterKey` will be set to the value of [filterKey].
+  TimelineTask.withTaskId(int taskId, {String? filterKey})
       : _parent = null,
+        _filterKey = filterKey,
         _taskId = taskId {
     // TODO: When NNBD is complete, delete the following line.
     ArgumentError.checkNotNull(taskId, 'taskId');
@@ -222,6 +232,7 @@
       }
     }
     if (_parent != null) map['parentId'] = _parent!._taskId.toRadixString(16);
+    if (_filterKey != null) map[_kFilterKey] = _filterKey;
     block._start(map);
   }
 
@@ -235,6 +246,10 @@
     if (arguments != null) {
       instantArguments = new Map.from(arguments);
     }
+    if (_filterKey != null) {
+      instantArguments ??= {};
+      instantArguments[_kFilterKey] = _filterKey;
+    }
     _reportTaskEvent(
         _taskId, 'n', 'Dart', name, _argumentsAsJson(instantArguments));
   }
@@ -248,6 +263,10 @@
     if (_stack.length == 0) {
       throw new StateError('Uneven calls to start and finish');
     }
+    if (_filterKey != null) {
+      arguments ??= {};
+      arguments[_kFilterKey] = _filterKey;
+    }
     // Pop top item off of stack.
     var block = _stack.removeLast();
     block._finish(arguments);
@@ -265,7 +284,9 @@
     return r;
   }
 
+  static const String _kFilterKey = 'filterKey';
   final TimelineTask? _parent;
+  final String? _filterKey;
   final int _taskId;
   final List<_AsyncBlock> _stack = [];
 }
diff --git a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
index 1d41744..c16628a 100644
--- a/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
+++ b/sdk_nnbd/lib/html/dart2js/html_dart2js.dart
@@ -13573,7 +13573,7 @@
     return Element._offsetToHelper(this, parent);
   }
 
-  static Point _offsetToHelper(Element current, Element parent) {
+  static Point _offsetToHelper(Element? current, Element parent) {
     // We're hopping from _offsetParent_ to offsetParent (not just parent), so
     // offsetParent, "tops out" at BODY. But people could conceivably pass in
     // the document.documentElement and I want it to return an absolute offset,
@@ -13585,7 +13585,7 @@
       throw new ArgumentError("Specified element is not a transitive offset "
           "parent of this element.");
     }
-    Element parentOffset = current.offsetParent;
+    Element? parentOffset = current.offsetParent;
     Point p = Element._offsetToHelper(parentOffset, parent);
     return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
   }
@@ -13837,7 +13837,7 @@
     return result;
   }
 
-  Element get offsetParent native;
+  Element? get offsetParent native;
 
   int get offsetHeight => JS<num>('num', '#.offsetHeight', this).round();
 
diff --git a/sdk_nnbd/lib/libraries.json b/sdk_nnbd/lib/libraries.json
index 208de69..4960b8b 100644
--- a/sdk_nnbd/lib/libraries.json
+++ b/sdk_nnbd/lib/libraries.json
@@ -217,6 +217,11 @@
         "uri": "math/math.dart",
         "patches": "_internal/js_runtime/lib/math_patch.dart"
       },
+      "mirrors": {
+        "uri": "mirrors/mirrors.dart",
+        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+        "supported": false
+      },
       "typed_data": {
         "uri": "typed_data/typed_data.dart",
         "patches": "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -322,6 +327,11 @@
         "uri": "math/math.dart",
         "patches": "_internal/js_runtime/lib/math_patch.dart"
       },
+      "mirrors": {
+        "uri": "mirrors/mirrors.dart",
+        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+        "supported": false
+      },
       "typed_data": {
         "uri": "typed_data/typed_data.dart",
         "patches": "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -428,6 +438,11 @@
         "patches": "_internal/js_dev_runtime/patch/isolate_patch.dart",
         "supported": false
       },
+      "mirrors": {
+        "uri": "mirrors/mirrors.dart",
+        "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+        "supported": false
+      },
       "math": {
         "uri": "math/math.dart",
         "patches": "_internal/js_dev_runtime/patch/math_patch.dart"
diff --git a/sdk_nnbd/lib/libraries.yaml b/sdk_nnbd/lib/libraries.yaml
index 8dd0eeb..b37041a 100644
--- a/sdk_nnbd/lib/libraries.yaml
+++ b/sdk_nnbd/lib/libraries.yaml
@@ -214,6 +214,11 @@
       uri: "math/math.dart"
       patches: "_internal/js_runtime/lib/math_patch.dart"
 
+    mirrors:
+      uri: "mirrors/mirrors.dart"
+      patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+      supported: false
+
     typed_data:
       uri: "typed_data/typed_data.dart"
       patches: "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -317,6 +322,11 @@
       uri: "math/math.dart"
       patches: "_internal/js_runtime/lib/math_patch.dart"
 
+    mirrors:
+      uri: "mirrors/mirrors.dart"
+      patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+      supported: false
+
     typed_data:
       uri: "typed_data/typed_data.dart"
       patches: "_internal/js_runtime/lib/typed_data_patch.dart"
@@ -421,6 +431,11 @@
         patches: "_internal/js_dev_runtime/patch/isolate_patch.dart"
         supported: false
 
+      mirrors:
+        uri: "mirrors/mirrors.dart"
+        patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+        supported: false
+
       math:
         uri: "math/math.dart"
         patches: "_internal/js_dev_runtime/patch/math_patch.dart"
diff --git a/sdk_nnbd/lib/mirrors/mirrors.dart b/sdk_nnbd/lib/mirrors/mirrors.dart
index 9b7d454..baec2f4 100644
--- a/sdk_nnbd/lib/mirrors/mirrors.dart
+++ b/sdk_nnbd/lib/mirrors/mirrors.dart
@@ -189,8 +189,7 @@
  * function can only be used to obtain type mirrors on types of the current
  * isolate.
  */
-external TypeMirror reflectType(Type key,
-    [List<Type> typeArguments = const <Type>[]]);
+external TypeMirror reflectType(Type key, [List<Type>? typeArguments]);
 
 /**
  * A [Mirror] reflects some Dart language entity.
diff --git a/tests/compiler/dart2js/analyses/analysis_helper.dart b/tests/compiler/dart2js/analyses/analysis_helper.dart
index ba3d4bc..b422f84 100644
--- a/tests/compiler/dart2js/analyses/analysis_helper.dart
+++ b/tests/compiler/dart2js/analyses/analysis_helper.dart
@@ -87,7 +87,7 @@
         const Dart2jsConstantsBackend(supportsUnevaluatedConstants: true),
         const {},
         typeEnvironment,
-        const ir.SimpleErrorReporter(false));
+        const ir.SimpleErrorReporter());
   }
 
   @override
diff --git a/tests/compiler/dart2js/rti/runtime_type_hint_test.dart b/tests/compiler/dart2js/rti/runtime_type_hint_test.dart
index e7f7829..99b6e00 100644
--- a/tests/compiler/dart2js/rti/runtime_type_hint_test.dart
+++ b/tests/compiler/dart2js/rti/runtime_type_hint_test.dart
@@ -42,13 +42,13 @@
   asyncTest(() async {
     await test(runtimeTypeToStringObject, [], []);
     await test(runtimeTypeToStringObject, [Flags.omitImplicitChecks],
-        [MessageKind.RUNTIME_TYPE_TO_STRING_OBJECT]);
+        [MessageKind.RUNTIME_TYPE_TO_STRING]);
     await test(runtimeTypeToStringObject,
         [Flags.omitImplicitChecks, Flags.laxRuntimeTypeToString], []);
 
     await test(runtimeTypeToStringClass, [], []);
     await test(runtimeTypeToStringClass, [Flags.omitImplicitChecks],
-        [MessageKind.RUNTIME_TYPE_TO_STRING_SUBTYPE]);
+        [MessageKind.RUNTIME_TYPE_TO_STRING]);
     await test(runtimeTypeToStringClass,
         [Flags.omitImplicitChecks, Flags.laxRuntimeTypeToString], []);
   });
diff --git a/tests/corelib/analysis_options.yaml b/tests/corelib/analysis_options.yaml
new file mode 100644
index 0000000..0720d0e
--- /dev/null
+++ b/tests/corelib/analysis_options.yaml
@@ -0,0 +1,3 @@
+analyzer:
+  enable-experiment:
+  - non-nullable
\ No newline at end of file
diff --git a/tests/corelib/from_environment_const_type_undefined_test.dart b/tests/corelib/from_environment_const_type_undefined_test.dart
index c555b02..c2e90ef 100644
--- a/tests/corelib/from_environment_const_type_undefined_test.dart
+++ b/tests/corelib/from_environment_const_type_undefined_test.dart
@@ -35,8 +35,8 @@
     d = const String.fromEnvironment('d');
 
 main() {
-  Expect.equals(a, false);
-  Expect.equals(b, false);
-  Expect.equals(c, null);
-  Expect.equals(d, null);
+  Expect.equals(false, a);
+  Expect.equals(false, b);
+  Expect.equals(0, c);
+  Expect.equals('', d);
 }
diff --git a/tests/corelib/int_from_environment2_test.dart b/tests/corelib/int_from_environment2_test.dart
index 348f0b0..1028056 100644
--- a/tests/corelib/int_from_environment2_test.dart
+++ b/tests/corelib/int_from_environment2_test.dart
@@ -6,9 +6,9 @@
 import "package:expect/expect.dart";
 
 main() {
-  Expect.isNull(const int.fromEnvironment('a'));
-  Expect.isNull(const int.fromEnvironment('b'));
-  Expect.isNull(const int.fromEnvironment('c'));
-  Expect.isNull(const int.fromEnvironment('d'));
-  Expect.isNull(const int.fromEnvironment('e'));
+  Expect.equals(0, const int.fromEnvironment('a'));
+  Expect.equals(0, const int.fromEnvironment('b'));
+  Expect.equals(0, const int.fromEnvironment('c'));
+  Expect.equals(0, const int.fromEnvironment('d'));
+  Expect.equals(0, const int.fromEnvironment('e'));
 }
diff --git a/tests/corelib_2/from_environment_const_type_undefined_test.dart b/tests/corelib_2/from_environment_const_type_undefined_test.dart
index c555b02..c2e90ef 100644
--- a/tests/corelib_2/from_environment_const_type_undefined_test.dart
+++ b/tests/corelib_2/from_environment_const_type_undefined_test.dart
@@ -35,8 +35,8 @@
     d = const String.fromEnvironment('d');
 
 main() {
-  Expect.equals(a, false);
-  Expect.equals(b, false);
-  Expect.equals(c, null);
-  Expect.equals(d, null);
+  Expect.equals(false, a);
+  Expect.equals(false, b);
+  Expect.equals(0, c);
+  Expect.equals('', d);
 }
diff --git a/tests/corelib_2/int_from_environment2_test.dart b/tests/corelib_2/int_from_environment2_test.dart
index 348f0b0..1028056 100644
--- a/tests/corelib_2/int_from_environment2_test.dart
+++ b/tests/corelib_2/int_from_environment2_test.dart
@@ -6,9 +6,9 @@
 import "package:expect/expect.dart";
 
 main() {
-  Expect.isNull(const int.fromEnvironment('a'));
-  Expect.isNull(const int.fromEnvironment('b'));
-  Expect.isNull(const int.fromEnvironment('c'));
-  Expect.isNull(const int.fromEnvironment('d'));
-  Expect.isNull(const int.fromEnvironment('e'));
+  Expect.equals(0, const int.fromEnvironment('a'));
+  Expect.equals(0, const int.fromEnvironment('b'));
+  Expect.equals(0, const int.fromEnvironment('c'));
+  Expect.equals(0, const int.fromEnvironment('d'));
+  Expect.equals(0, const int.fromEnvironment('e'));
 }
diff --git a/tests/language/analysis_options.yaml b/tests/language/analysis_options.yaml
new file mode 100644
index 0000000..0720d0e
--- /dev/null
+++ b/tests/language/analysis_options.yaml
@@ -0,0 +1,3 @@
+analyzer:
+  enable-experiment:
+  - non-nullable
\ No newline at end of file
diff --git a/tests/language/nnbd/resolution/null_aware_subscript_produces_nullable_type_test.dart b/tests/language/nnbd/resolution/null_aware_subscript_produces_nullable_type_test.dart
index ed8823d..c4f6385 100644
--- a/tests/language/nnbd/resolution/null_aware_subscript_produces_nullable_type_test.dart
+++ b/tests/language/nnbd/resolution/null_aware_subscript_produces_nullable_type_test.dart
@@ -18,34 +18,34 @@
 
 void f2(NotGeneric? x) {
   x?[0] + 1;
-//^^^^^^
+//^^^^^
 // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
 // [cfe] unspecified
   x?[0] = 1;
   useNonNullable(x?[0] = 1);
-//               ^^^^^^^^^^
+//               ^^^^^^^^^
 // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
 // [cfe] unspecified
   x?[0] += 1;
   useNonNullable(x?[0] += 1);
-//               ^^^^^^^^^^^
+//               ^^^^^^^^^^
 // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
 // [cfe] unspecified
   x?[0]++;
   useNonNullable(x?[0]++);
-//               ^^^^^^^^^^^
+//               ^^^^^^^
 // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
 // [cfe] unspecified
   ++x?[0];
   useNonNullable(++x?[0]);
-//               ^^^^^^^^^^^
+//               ^^^^^^^
 // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
 // [cfe] unspecified
 }
 
 void f3<T extends num>(Generic<T>? x) {
   x?[0] + 1;
-//^^^^^^
+//^^^^^
 // [analyzer] STATIC_WARNING.USE_OF_NULLABLE_VALUE
 // [cfe] unspecified
 }
diff --git a/tests/language/nnbd/type_equality/futureOr_normalization_legacy_test.dart b/tests/language/nnbd/type_equality/futureOr_normalization_legacy_test.dart
index c0570d4..e159821 100644
--- a/tests/language/nnbd/type_equality/futureOr_normalization_legacy_test.dart
+++ b/tests/language/nnbd/type_equality/futureOr_normalization_legacy_test.dart
@@ -21,18 +21,18 @@
 
 main() {
   // FutureOr types are normalized when they appear explicitly in the source.
-  Expect.identical(dynamic, extractType<FutureOr>());
-  Expect.identical(dynamic, extractType<FutureOr<dynamic>>());
-  Expect.identical(extractType<Object>(), extractType<FutureOr<Object>>());
-  Expect.identical(extractType<void>(), extractType<FutureOr<void>>());
-  Expect.identical(nullSafe.embeddedNullableFutureOfNull,
+  Expect.equals(dynamic, extractType<FutureOr>());
+  Expect.equals(dynamic, extractType<FutureOr<dynamic>>());
+  Expect.equals(extractType<Object>(), extractType<FutureOr<Object>>());
+  Expect.equals(extractType<void>(), extractType<FutureOr<void>>());
+  Expect.equals(nullSafe.embeddedNullableFutureOfNull,
       extractType<nullSafe.Embed<FutureOr<Null>>>());
 
   // FutureOr types are normalized when they are created at runtime.
-  Expect.identical(extractType<_<dynamic>>(), extractFutureOrType());
-  Expect.identical(extractType<_<dynamic>>(), extractFutureOrType<dynamic>());
-  Expect.identical(extractType<_<Object>>(), extractFutureOrType<Object>());
-  Expect.identical(extractType<_<void>>(), extractFutureOrType<void>());
-  Expect.identical(
+  Expect.equals(extractType<_<dynamic>>(), extractFutureOrType());
+  Expect.equals(extractType<_<dynamic>>(), extractFutureOrType<dynamic>());
+  Expect.equals(extractType<_<Object>>(), extractFutureOrType<Object>());
+  Expect.equals(extractType<_<void>>(), extractFutureOrType<void>());
+  Expect.equals(
       nullSafe.embeddedNullableFutureOfNull, embedFutureOrType<Null>());
 }
diff --git a/tests/language/nnbd/type_equality/futureOr_normalization_test.dart b/tests/language/nnbd/type_equality/futureOr_normalization_test.dart
index a9e61f5..5592e73 100644
--- a/tests/language/nnbd/type_equality/futureOr_normalization_test.dart
+++ b/tests/language/nnbd/type_equality/futureOr_normalization_test.dart
@@ -15,38 +15,34 @@
 
 main() {
   // FutureOr types are normalized when they appear explicitly in the source.
-  Expect.identical(dynamic, extractType<FutureOr>());
-  Expect.identical(dynamic, extractType<FutureOr<dynamic>>());
-  Expect.identical(Object, extractType<FutureOr<Object>>());
-  Expect.identical(extractType<Object?>(), extractType<FutureOr<Object>?>());
-  Expect.identical(extractType<Object?>(), extractType<FutureOr<Object?>>());
-  Expect.identical(extractType<void>(), extractType<FutureOr<void>>());
-  Expect.identical(
-      extractType<Future<Never>>(), extractType<FutureOr<Never>>());
-  Expect.identical(extractType<Future<Null>?>(), extractType<FutureOr<Null>>());
-  Expect.identical(
-      extractType<FutureOr<int?>>(), extractType<FutureOr<int?>?>());
-  Expect.identical(extractType<FutureOr<A?>>(), extractType<FutureOr<A?>?>());
+  Expect.equals(dynamic, extractType<FutureOr>());
+  Expect.equals(dynamic, extractType<FutureOr<dynamic>>());
+  Expect.equals(Object, extractType<FutureOr<Object>>());
+  Expect.equals(extractType<Object?>(), extractType<FutureOr<Object>?>());
+  Expect.equals(extractType<Object?>(), extractType<FutureOr<Object?>>());
+  Expect.equals(extractType<void>(), extractType<FutureOr<void>>());
+  Expect.equals(extractType<Future<Never>>(), extractType<FutureOr<Never>>());
+  Expect.equals(extractType<Future<Null>?>(), extractType<FutureOr<Null>>());
+  Expect.equals(extractType<FutureOr<int?>>(), extractType<FutureOr<int?>?>());
+  Expect.equals(extractType<FutureOr<A?>>(), extractType<FutureOr<A?>?>());
 
   // FutureOr types are normalized when they are composed at runtime.
-  Expect.identical(extractType<Embed<dynamic>>(), extractFutureOrType());
-  Expect.identical(
-      extractType<Embed<dynamic>>(), extractFutureOrType<dynamic>());
-  Expect.identical(extractType<Embed<Object>>(), extractFutureOrType<Object>());
-  Expect.identical(
+  Expect.equals(extractType<Embed<dynamic>>(), extractFutureOrType());
+  Expect.equals(extractType<Embed<dynamic>>(), extractFutureOrType<dynamic>());
+  Expect.equals(extractType<Embed<Object>>(), extractFutureOrType<Object>());
+  Expect.equals(
       extractType<Embed<Object?>>(), embedNullableFutureOrType<Object>());
-  Expect.identical(
-      extractType<Embed<Object?>>(), extractFutureOrType<Object?>());
-  Expect.identical(extractType<Embed<void>>(), extractFutureOrType<void>());
-  Expect.identical(
+  Expect.equals(extractType<Embed<Object?>>(), extractFutureOrType<Object?>());
+  Expect.equals(extractType<Embed<void>>(), extractFutureOrType<void>());
+  Expect.equals(
       extractType<Embed<Future<Never>>>(), extractFutureOrType<Never>());
-  Expect.identical(
+  Expect.equals(
       extractType<Embed<Future<Null>?>>(), extractFutureOrType<Null>());
-  Expect.identical(
+  Expect.equals(
       extractType<Embed<FutureOr<int?>>>(), embedNullableFutureOrType<int?>());
-  Expect.identical(
+  Expect.equals(
       extractType<Embed<FutureOr<A?>>>(), embedNullableFutureOrType<A?>());
 
   // Object* == FutureOr<Object*>
-  Expect.identical(legacy.object, legacy.nonNullableFutureOrOfLegacyObject());
+  Expect.equals(legacy.object, legacy.nonNullableFutureOrOfLegacyObject());
 }
diff --git a/tests/language_2/bool/has_environment_not_new_test.dart b/tests/language_2/bool/has_environment_not_new_test.dart
new file mode 100644
index 0000000..947c6be
--- /dev/null
+++ b/tests/language_2/bool/has_environment_not_new_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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";
+
+main() {
+  Expect.throws(() => new bool.hasEnvironment("Anything"));
+}
diff --git a/tests/language_2/bool/has_environment_test.dart b/tests/language_2/bool/has_environment_test.dart
new file mode 100644
index 0000000..df593f1
--- /dev/null
+++ b/tests/language_2/bool/has_environment_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=-Da= -Db=b -Dc=Something
+
+import 'package:expect/expect.dart';
+
+main() {
+  Expect.isTrue(const bool.hasEnvironment('dart.library.core'));
+  Expect.isTrue(const bool.hasEnvironment('a'));
+  Expect.isTrue(const bool.hasEnvironment('b'));
+  Expect.isTrue(const bool.hasEnvironment('c'));
+  Expect.isFalse(const bool.hasEnvironment('d'));
+}
diff --git a/tests/language_2/deferred/load_library_wrong_args_test.dart b/tests/language_2/deferred/load_library_wrong_args_test.dart
index d8da7ae..c991e2e6 100644
--- a/tests/language_2/deferred/load_library_wrong_args_test.dart
+++ b/tests/language_2/deferred/load_library_wrong_args_test.dart
@@ -5,8 +5,6 @@
   lib.loadLibrary(10);
 //^
 // [cfe] 'loadLibrary' takes no arguments.
-  //             ^
-  // [cfe] Too many positional arguments: 0 allowed, but 1 found.
 //               ^^^^
 // [analyzer] COMPILE_TIME_ERROR.EXTRA_POSITIONAL_ARGUMENTS
 }
diff --git a/tests/language_2/string/const_interpolation2_test.dart b/tests/language_2/string/const_interpolation2_test.dart
index 4033d8e3..968d2c2 100644
--- a/tests/language_2/string/const_interpolation2_test.dart
+++ b/tests/language_2/string/const_interpolation2_test.dart
@@ -88,7 +88,7 @@
   Expect.equals(b2.toString(), sb2);
   Expect.equals(b3.toString(), sb3);
   Expect.equals(b4.toString(), sb4);
-  var expect = "null null null null null null 42 3.1415 37 4.6692 2.71828 87 "
+  var expect = "null null null  0 null 42 3.1415 37 4.6692 2.71828 87 "
       "s1 s2 s1s2 s4 true false false true";
   Expect.equals(expect, interpolation1);
   Expect.equals(expect, interpolation2);
diff --git a/tests/language_2/variance/variance_out_field_error_test.dart b/tests/language_2/variance/variance_out_field_error_test.dart
index 2123b9d..d87b195 100644
--- a/tests/language_2/variance/variance_out_field_error_test.dart
+++ b/tests/language_2/variance/variance_out_field_error_test.dart
@@ -50,4 +50,5 @@
   var a;
   //  ^
   // [analyzer] COMPILE_TIME_ERROR.WRONG_TYPE_PARAMETER_VARIANCE_POSITION
+  // [cfe] Can't use 'out' type variable 'T' in an 'in' position.
 }
diff --git a/tests/lib/analysis_options.yaml b/tests/lib/analysis_options.yaml
new file mode 100644
index 0000000..0720d0e
--- /dev/null
+++ b/tests/lib/analysis_options.yaml
@@ -0,0 +1,3 @@
+analyzer:
+  enable-experiment:
+  - non-nullable
\ No newline at end of file
diff --git a/tests/lib/async/future_or_strong_test.dart b/tests/lib/async/future_or_strong_test.dart
index f9f1ff9..765a8a6 100644
--- a/tests/lib/async/future_or_strong_test.dart
+++ b/tests/lib/async/future_or_strong_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+// Requirements=nnbd-strong
+
 // In strong mode, `FutureOr` should be equivalent to the union of `Future<T>`
 // and `T`.
 
@@ -12,42 +14,48 @@
 typedef T FunReturns<T>();
 
 main() {
-  Expect.isTrue(499 is FutureOr); // Same as `is Object`.
+  Expect.isTrue(499 is FutureOr); // Same as `is Object?`.
   Expect.isTrue(499 is FutureOr<int>);
   Expect.isFalse(499 is FutureOr<String>);
 
-  Expect.isTrue(new Future.value(499) is FutureOr); // Same as `is Object`.
+  Expect.isTrue(new Future.value(499) is FutureOr); // Same as `is Object?`.
   Expect.isTrue(new Future.value(499) is FutureOr<int>);
   Expect.isFalse(new Future.value(499) is FutureOr<String>);
 
-  void foo(FutureOr x) {} // Equivalent to `void bar(Object x) {}`.
+  void foo(FutureOr x) {} // Equivalent to `void bar(Object? x) {}`.
 
-  // A function that takes Object takes everything.
+  // A function that takes Object? takes everything.
   Expect.isTrue(foo is FunTakes<dynamic>);
   Expect.isTrue(foo is FunTakes<Object>);
+  Expect.isTrue(foo is FunTakes<Object?>);
   Expect.isTrue(foo is FunTakes<int>);
   Expect.isTrue(foo is FunTakes<String>);
   Expect.isTrue(foo is FunTakes<Future<int>>);
   Expect.isTrue(foo is FunTakes<Future<String>>);
   Expect.isTrue(foo is FunTakes<FutureOr<Object>>);
+  Expect.isTrue(foo is FunTakes<FutureOr<Object?>>);
   Expect.isTrue(foo is FunTakes<FutureOr<int>>);
   Expect.isTrue(foo is FunTakes<FutureOr<String>>);
   Expect.isTrue(foo is FunTakes<FutureOr<FutureOr<Object>>>);
+  Expect.isTrue(foo is FunTakes<FutureOr<FutureOr<Object?>>>);
   Expect.isTrue(foo is FunTakes<FutureOr<FutureOr<int>>>);
   Expect.isTrue(foo is FunTakes<FutureOr<FutureOr<String>>>);
 
-  FutureOr bar() => 499; // Equivalent to `Object foo() => 499`.
+  FutureOr bar() => 499; // Equivalent to `Object? foo() => 499`.
 
   Expect.isTrue(bar is FunReturns<dynamic>);
-  Expect.isTrue(bar is FunReturns<Object>);
+  Expect.isFalse(bar is FunReturns<Object>);
+  Expect.isTrue(bar is FunReturns<Object?>);
   Expect.isFalse(bar is FunReturns<int>);
   Expect.isFalse(bar is FunReturns<String>);
   Expect.isFalse(bar is FunReturns<Future<int>>);
   Expect.isFalse(bar is FunReturns<Future<String>>);
-  Expect.isTrue(bar is FunReturns<FutureOr<Object>>);
+  Expect.isFalse(bar is FunReturns<FutureOr<Object>>);
+  Expect.isTrue(bar is FunReturns<FutureOr<Object?>>);
   Expect.isFalse(bar is FunReturns<FutureOr<int>>);
   Expect.isFalse(bar is FunReturns<FutureOr<String>>);
-  Expect.isTrue(bar is FunReturns<FutureOr<FutureOr<Object>>>);
+  Expect.isFalse(bar is FunReturns<FutureOr<FutureOr<Object>>>);
+  Expect.isTrue(bar is FunReturns<FutureOr<FutureOr<Object?>>>);
   Expect.isFalse(bar is FunReturns<FutureOr<FutureOr<int>>>);
   Expect.isFalse(bar is FunReturns<FutureOr<FutureOr<String>>>);
 
@@ -55,14 +63,17 @@
 
   Expect.isFalse(foo2 is FunTakes<dynamic>);
   Expect.isFalse(foo2 is FunTakes<Object>);
+  Expect.isFalse(foo2 is FunTakes<Object?>);
   Expect.isFalse(foo2 is FunTakes<int>);
   Expect.isTrue(foo2 is FunTakes<String>);
   Expect.isFalse(foo2 is FunTakes<Future<int>>);
   Expect.isTrue(foo2 is FunTakes<Future<String>>);
   Expect.isFalse(foo2 is FunTakes<FutureOr<Object>>);
+  Expect.isFalse(foo2 is FunTakes<FutureOr<Object?>>);
   Expect.isFalse(foo2 is FunTakes<FutureOr<int>>);
   Expect.isTrue(foo2 is FunTakes<FutureOr<String>>);
   Expect.isFalse(foo2 is FunTakes<FutureOr<FutureOr<Object>>>);
+  Expect.isFalse(foo2 is FunTakes<FutureOr<FutureOr<Object?>>>);
   Expect.isFalse(foo2 is FunTakes<FutureOr<FutureOr<int>>>);
   Expect.isFalse(foo2 is FunTakes<FutureOr<FutureOr<String>>>);
 
@@ -70,14 +81,17 @@
 
   Expect.isTrue(bar2 is FunReturns<dynamic>);
   Expect.isTrue(bar2 is FunReturns<Object>);
+  Expect.isTrue(bar2 is FunReturns<Object?>);
   Expect.isFalse(bar2 is FunReturns<int>);
   Expect.isFalse(bar2 is FunReturns<String>);
   Expect.isFalse(bar2 is FunReturns<Future<int>>);
   Expect.isFalse(bar2 is FunReturns<Future<String>>);
   Expect.isTrue(bar2 is FunReturns<FutureOr<Object>>);
+  Expect.isTrue(bar2 is FunReturns<FutureOr<Object?>>);
   Expect.isTrue(bar2 is FunReturns<FutureOr<int>>);
   Expect.isFalse(bar2 is FunReturns<FutureOr<String>>);
   Expect.isTrue(bar2 is FunReturns<FutureOr<FutureOr<Object>>>);
+  Expect.isTrue(bar2 is FunReturns<FutureOr<FutureOr<Object?>>>);
   Expect.isTrue(bar2 is FunReturns<FutureOr<FutureOr<int>>>);
   Expect.isFalse(bar2 is FunReturns<FutureOr<FutureOr<String>>>);
 
@@ -85,14 +99,17 @@
 
   Expect.isFalse(foo3 is FunTakes<dynamic>);
   Expect.isFalse(foo3 is FunTakes<Object>);
+  Expect.isFalse(foo3 is FunTakes<Object?>);
   Expect.isFalse(foo3 is FunTakes<int>);
   Expect.isTrue(foo3 is FunTakes<String>);
   Expect.isFalse(foo3 is FunTakes<Future<int>>);
   Expect.isFalse(foo3 is FunTakes<Future<String>>);
   Expect.isFalse(foo3 is FunTakes<FutureOr<Object>>);
+  Expect.isFalse(foo3 is FunTakes<FutureOr<Object?>>);
   Expect.isFalse(foo3 is FunTakes<FutureOr<int>>);
   Expect.isFalse(foo3 is FunTakes<FutureOr<String>>);
   Expect.isFalse(foo3 is FunTakes<FutureOr<FutureOr<Object>>>);
+  Expect.isFalse(foo3 is FunTakes<FutureOr<FutureOr<Object?>>>);
   Expect.isFalse(foo3 is FunTakes<FutureOr<FutureOr<int>>>);
   Expect.isFalse(foo3 is FunTakes<FutureOr<FutureOr<String>>>);
 
@@ -100,14 +117,17 @@
 
   Expect.isTrue(bar3 is FunReturns<dynamic>);
   Expect.isTrue(bar3 is FunReturns<Object>);
+  Expect.isTrue(bar3 is FunReturns<Object?>);
   Expect.isTrue(bar3 is FunReturns<int>);
   Expect.isFalse(bar3 is FunReturns<String>);
   Expect.isFalse(bar3 is FunReturns<Future<int>>);
   Expect.isFalse(bar3 is FunReturns<Future<String>>);
   Expect.isTrue(bar3 is FunReturns<FutureOr<Object>>);
+  Expect.isTrue(bar3 is FunReturns<FutureOr<Object?>>);
   Expect.isTrue(bar3 is FunReturns<FutureOr<int>>);
   Expect.isFalse(bar3 is FunReturns<FutureOr<String>>);
   Expect.isTrue(bar3 is FunReturns<FutureOr<FutureOr<Object>>>);
+  Expect.isTrue(bar3 is FunReturns<FutureOr<FutureOr<Object?>>>);
   Expect.isTrue(bar3 is FunReturns<FutureOr<FutureOr<int>>>);
   Expect.isFalse(bar3 is FunReturns<FutureOr<FutureOr<String>>>);
-}
+}
\ No newline at end of file
diff --git a/tests/lib/async/stream_iterator_test.dart b/tests/lib/async/stream_iterator_test.dart
index c50f53e..c64a32f 100644
--- a/tests/lib/async/stream_iterator_test.dart
+++ b/tests/lib/async/stream_iterator_test.dart
@@ -51,7 +51,7 @@
     Stream stream = createStream();
     StreamIterator iterator = new StreamIterator(stream);
     var hasNext = iterator.moveNext();
-    expect(iterator.moveNext, throwsA(isStateError));
+    expect(iterator.moveNext, throwsStateError);
     expect(await hasNext, isTrue);
     expect(iterator.current, 42);
     iterator.cancel();
diff --git a/tests/lib/collection/failing_list_test.dart b/tests/lib/collection/failing_list_test.dart
index ad65e0d..aa7f689 100644
--- a/tests/lib/collection/failing_list_test.dart
+++ b/tests/lib/collection/failing_list_test.dart
@@ -90,7 +90,6 @@
 void testRetainWhere() {
   List<int> list = <int>[1, 2, 3];
   list.retainWhere((x) => x % 2 == 0);
-  Expect.equals(true, false);
   Expect.equals(1, list.length);
   Expect.equals(2, list.first);
   Expect.equals(2, list[0]);
diff --git a/tests/lib/mirrors/accessor_cache_overflow_test.dart b/tests/lib/mirrors/accessor_cache_overflow_test.dart
index 5703ea1..0e65d64 100644
--- a/tests/lib/mirrors/accessor_cache_overflow_test.dart
+++ b/tests/lib/mirrors/accessor_cache_overflow_test.dart
@@ -32,7 +32,7 @@
     'E',
     'F'
   ];
-  var symbols = new List();
+  var symbols = <dynamic>[];
   for (var high in digits) {
     for (var low in digits) {
       symbols.add(MirrorSystem.getSymbol("v$high$low"));
diff --git a/tests/lib/mirrors/generic_list_test.dart b/tests/lib/mirrors/generic_list_test.dart
index 79d5e94..a4fae3a 100644
--- a/tests/lib/mirrors/generic_list_test.dart
+++ b/tests/lib/mirrors/generic_list_test.dart
@@ -10,7 +10,7 @@
 class Foo<T> {
   List<T> makeList() {
     if (new DateTime.now().millisecondsSinceEpoch == 42) return [];
-    return new List<T>();
+    return <T>[];
   }
 }
 
diff --git a/tests/lib/mirrors/instance_members_easier_test.dart b/tests/lib/mirrors/instance_members_easier_test.dart
index a017ac0..e71fb13 100644
--- a/tests/lib/mirrors/instance_members_easier_test.dart
+++ b/tests/lib/mirrors/instance_members_easier_test.dart
@@ -10,7 +10,7 @@
 import 'declarations_model_easier.dart' as declarations_model;
 
 selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
-  return map.keys.where((K key) => predicate(map[key]));
+  return map.keys.where((K key) => predicate(map[key] as V));
 }
 
 class EasierSuperclass {
diff --git a/tests/lib/mirrors/instance_members_test.dart b/tests/lib/mirrors/instance_members_test.dart
index 203c665..c71b5fa5 100644
--- a/tests/lib/mirrors/instance_members_test.dart
+++ b/tests/lib/mirrors/instance_members_test.dart
@@ -10,7 +10,7 @@
 import 'declarations_model.dart' as declarations_model;
 
 selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
-  return map.keys.where((K key) => predicate(map[key]));
+  return map.keys.where((K key) => predicate(map[key] as V));
 }
 
 main() {
diff --git a/tests/lib/mirrors/instance_members_with_override_test.dart b/tests/lib/mirrors/instance_members_with_override_test.dart
index f091200..f1065c5 100644
--- a/tests/lib/mirrors/instance_members_with_override_test.dart
+++ b/tests/lib/mirrors/instance_members_with_override_test.dart
@@ -29,7 +29,7 @@
 }
 
 selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
-  return map.keys.where((K key) => predicate(map[key]));
+  return map.keys.where((K key) => predicate(map[key] as V));
 }
 
 main() {
diff --git a/tests/lib/mirrors/instantiate_abstract_class_test.dart b/tests/lib/mirrors/instantiate_abstract_class_test.dart
index 057b40b..1368dcc 100644
--- a/tests/lib/mirrors/instantiate_abstract_class_test.dart
+++ b/tests/lib/mirrors/instantiate_abstract_class_test.dart
@@ -11,7 +11,7 @@
   classMirror.declarations.values.forEach((decl) {
     if (decl is! MethodMirror) return;
     if (!decl.isGenerativeConstructor) return;
-    var args = new List(decl.parameters.length);
+    var args = new List<dynamic>.filled(decl.parameters.length, null);
     Expect.throws(
         () => classMirror.newInstance(decl.constructorName, args),
         (e) => e is AbstractClassInstantiationError,
@@ -23,7 +23,7 @@
   classMirror.declarations.values.forEach((decl) {
     if (decl is! MethodMirror) return;
     if (!decl.isFactoryConstructor) return;
-    var args = new List(decl.parameters.length);
+    var args = new List<dynamic>.filled(decl.parameters.length, null);
     classMirror.newInstance(decl.constructorName, args); // Should not throw.
   });
 }
diff --git a/tests/lib/mirrors/invocation_fuzz_test.dart b/tests/lib/mirrors/invocation_fuzz_test.dart
index d08c351..b241d49 100644
--- a/tests/lib/mirrors/invocation_fuzz_test.dart
+++ b/tests/lib/mirrors/invocation_fuzz_test.dart
@@ -55,7 +55,7 @@
   dynamic action;
 }
 
-var queue = new List<Task>();
+var queue = <Task>[];
 
 checkMethod(MethodMirror m, ObjectMirror target, [origin]) {
   if (isBlacklisted(m.qualifiedName)) return;
@@ -152,7 +152,7 @@
   fuzzArgument = 1; // //# smi: ok
   fuzzArgument = false; // //# false: ok
   fuzzArgument = 'string'; // //# string: ok
-  fuzzArgument = new List(0); // //# emptyarray: ok
+  fuzzArgument = new List<dynamic>.filled(0, null); // //# emptyarray: ok
 
   print('Fuzzing with $fuzzArgument');
 
diff --git a/tests/lib/mirrors/invoke_closurization2_test.dart b/tests/lib/mirrors/invoke_closurization2_test.dart
index 2e18330..efbc7da 100644
--- a/tests/lib/mirrors/invoke_closurization2_test.dart
+++ b/tests/lib/mirrors/invoke_closurization2_test.dart
@@ -49,7 +49,7 @@
 }
 
 main() {
-  var list = ["foo", new List(), new A()];
+  var list = ["foo", <dynamic>[], new A()];
 
   getAMirror() => reflect(list[confuse(2)]);
 
@@ -83,11 +83,14 @@
 
   // Now the same thing through mirrors and mirror-invocation.
   f = getAMirror().getField(#codeUnitAt);
-  Expect.equals("codeUnitAt-42", f.invoke(#call, [42], {}).reflectee);
+  Expect.equals(
+      "codeUnitAt-42", f.invoke(#call, [42], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#toUpperCase);
-  Expect.equals("toUpperCase", f.invoke(#call, [], {}).reflectee);
+  Expect.equals(
+      "toUpperCase", f.invoke(#call, [], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#indexOf);
-  Expect.equals("indexOf-499", f.invoke(#call, [499], {}).reflectee);
+  Expect.equals(
+      "indexOf-499", f.invoke(#call, [499], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#lastIndexOf);
   Expect.equals(
       "lastIndexOf-FOO,BAR", f.invoke(#call, ["FOO", "BAR"]).reflectee);
@@ -114,11 +117,14 @@
   Expect.equals("toSet-true", f(named: true));
 
   f = getAMirror().getField(#endsWith);
-  Expect.equals("endsWith-42", f.invoke(#call, [42], {}).reflectee);
+  Expect.equals(
+      "endsWith-42", f.invoke(#call, [42], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#toLowerCase);
-  Expect.equals("toLowerCase", f.invoke(#call, [], {}).reflectee);
+  Expect.equals(
+      "toLowerCase", f.invoke(#call, [], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#indexOf);
-  Expect.equals("indexOf-499", f.invoke(#call, [499], {}).reflectee);
+  Expect.equals(
+      "indexOf-499", f.invoke(#call, [499], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#matchAsPrefix);
   Expect.equals(
       "matchAsPrefix-FOO,BAR", f.invoke(#call, ["FOO", "BAR"]).reflectee);
diff --git a/tests/lib/mirrors/invoke_natives_malicious_test.dart b/tests/lib/mirrors/invoke_natives_malicious_test.dart
index 43ccb5d..5e50da7 100644
--- a/tests/lib/mirrors/invoke_natives_malicious_test.dart
+++ b/tests/lib/mirrors/invoke_natives_malicious_test.dart
@@ -17,9 +17,9 @@
   LibraryMirror dartcore = reflectClass(Object).owner as LibraryMirror;
 
   test('List_copyFromObjectArray', () {
-    var receiver = new List(3);
+    var receiver = new List<dynamic>.filled(3, null);
     var selector = MirrorSystem.getSymbol('_copyFromObjectArray', dartcore);
-    var src = new List(3);
+    var src = new List<dynamic>.filled(3, null);
     var srcStart = 10;
     var dstStart = 10;
     var count = 10;
diff --git a/tests/lib/mirrors/mixin_members_test.dart b/tests/lib/mirrors/mixin_members_test.dart
index 76670b0..57202f1 100644
--- a/tests/lib/mirrors/mixin_members_test.dart
+++ b/tests/lib/mirrors/mixin_members_test.dart
@@ -32,7 +32,7 @@
 class C extends S with M1, M2 {}
 
 membersOf(ClassMirror cm) {
-  var result = new Map();
+  var result = new Map<Symbol, dynamic>();
   cm.declarations.forEach((k, v) {
     if (v is MethodMirror && !v.isConstructor) result[k] = v;
     if (v is VariableMirror) result[k] = v;
diff --git a/tests/lib/mirrors/static_members_easier_test.dart b/tests/lib/mirrors/static_members_easier_test.dart
index a3912e9..43b02b9 100644
--- a/tests/lib/mirrors/static_members_easier_test.dart
+++ b/tests/lib/mirrors/static_members_easier_test.dart
@@ -11,7 +11,7 @@
 import 'declarations_model_easier.dart' as declarations_model;
 
 selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
-  return map.keys.where((K key) => predicate(map[key]));
+  return map.keys.where((K key) => predicate(map[key] as V));
 }
 
 main() {
diff --git a/tests/lib/mirrors/static_members_test.dart b/tests/lib/mirrors/static_members_test.dart
index aad20e7..beeed6d 100644
--- a/tests/lib/mirrors/static_members_test.dart
+++ b/tests/lib/mirrors/static_members_test.dart
@@ -11,7 +11,7 @@
 import 'declarations_model.dart' as declarations_model;
 
 selectKeys<K, V>(Map<K, V> map, bool Function(V) predicate) {
-  return map.keys.where((K key) => predicate(map[key]));
+  return map.keys.where((K key) => predicate(map[key] as V));
 }
 
 main() {
diff --git a/tests/lib/mirrors/stringify.dart b/tests/lib/mirrors/stringify.dart
index 25e2061..09f28fe 100644
--- a/tests/lib/mirrors/stringify.dart
+++ b/tests/lib/mirrors/stringify.dart
@@ -141,7 +141,7 @@
     if (dep.prefix != null) buffer.write(' as ${n(dep.prefix)}');
     buffer.write('\n');
 
-    List flattenedCombinators = new List();
+    var flattenedCombinators = <dynamic>[];
     dep.combinators.forEach((com) {
       com.identifiers.forEach((ident) {
         flattenedCombinators.add([n(ident), com.isShow, com.isHide]);
diff --git a/tests/lib_2/async/future_error_test.dart b/tests/lib_2/async/future_error_test.dart
new file mode 100644
index 0000000..3ef0eb3
--- /dev/null
+++ b/tests/lib_2/async/future_error_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/expect.dart';
+
+main() {
+  // The error cannot be null.
+  Expect.throwsArgumentError(() {
+    Future.error(null);
+  });
+}
diff --git a/tests/lib_2/async/future_test.dart b/tests/lib_2/async/future_test.dart
index 9223646..3a4f09d 100644
--- a/tests/lib_2/async/future_test.dart
+++ b/tests/lib_2/async/future_test.dart
@@ -697,13 +697,10 @@
 }
 
 void testCompleteErrorWithNull() {
-  asyncStart();
   final completer = new Completer<int>();
-  completer.future.catchError((e) {
-    Expect.isTrue(e is NullThrownError);
-    asyncEnd();
+  Expect.throwsArgumentError(() {
+    completer.completeError(null);
   });
-  completer.completeError(null);
 }
 
 void testChainedFutureValue() {
diff --git a/tests/lib_2/async/stream_controller_add_error_test.dart b/tests/lib_2/async/stream_controller_add_error_test.dart
new file mode 100644
index 0000000..aed39e8
--- /dev/null
+++ b/tests/lib_2/async/stream_controller_add_error_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/expect.dart';
+
+main() {
+  // Single-cast async.
+  var controller = StreamController();
+  Expect.throwsArgumentError(() {
+    controller.addError(null);
+  });
+
+  Expect.throwsArgumentError(() {
+    controller.sink.addError(null);
+  });
+
+  // Single-cast sync.
+  controller = StreamController(sync: true);
+  Expect.throwsArgumentError(() {
+    controller.addError(null);
+  });
+
+  Expect.throwsArgumentError(() {
+    controller.sink.addError(null);
+  });
+
+  // Broadcast async.
+  controller = StreamController.broadcast();
+  Expect.throwsArgumentError(() {
+    controller.addError(null);
+  });
+
+  Expect.throwsArgumentError(() {
+    controller.sink.addError(null);
+  });
+
+  // Broadcast sync.
+  controller = StreamController.broadcast(sync: true);
+  Expect.throwsArgumentError(() {
+    controller.addError(null);
+  });
+
+  Expect.throwsArgumentError(() {
+    controller.sink.addError(null);
+  });
+}
diff --git a/tests/lib_2/async/stream_error_test.dart b/tests/lib_2/async/stream_error_test.dart
index 11f6a93..22b091b 100644
--- a/tests/lib_2/async/stream_error_test.dart
+++ b/tests/lib_2/async/stream_error_test.dart
@@ -72,6 +72,11 @@
     await onDone.future;
   }
 
+  // A null error argument is a synchronous error.
+  Expect.throwsArgumentError(() {
+    Stream.error(null);
+  });
+
   asyncEnd();
 }
 
diff --git a/tests/lib_2/async/stream_iterator_test.dart b/tests/lib_2/async/stream_iterator_test.dart
index c50f53e..c64a32f 100644
--- a/tests/lib_2/async/stream_iterator_test.dart
+++ b/tests/lib_2/async/stream_iterator_test.dart
@@ -51,7 +51,7 @@
     Stream stream = createStream();
     StreamIterator iterator = new StreamIterator(stream);
     var hasNext = iterator.moveNext();
-    expect(iterator.moveNext, throwsA(isStateError));
+    expect(iterator.moveNext, throwsStateError);
     expect(await hasNext, isTrue);
     expect(iterator.current, 42);
     iterator.cancel();
diff --git a/tests/lib_2/async/zone_async_error_test.dart b/tests/lib_2/async/zone_async_error_test.dart
new file mode 100644
index 0000000..b1f67ce
--- /dev/null
+++ b/tests/lib_2/async/zone_async_error_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:expect/expect.dart';
+
+main() {
+  // The error cannot be null.
+  Expect.throwsArgumentError(() {
+    AsyncError(null, StackTrace.current);
+  });
+}
diff --git a/tests/lib_2/html/custom/attribute_changed_callback_test.dart b/tests/lib_2/html/custom/attribute_changed_callback_test.dart
index 1d6a85e..f30a048 100644
--- a/tests/lib_2/html/custom/attribute_changed_callback_test.dart
+++ b/tests/lib_2/html/custom/attribute_changed_callback_test.dart
@@ -8,7 +8,7 @@
 import 'dart:html';
 import 'dart:js' as js;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'utils.dart';
 
@@ -51,17 +51,12 @@
   }
 }
 
-main() {
+main() async {
   // Adapted from Blink's fast/dom/custom/attribute-changed-callback test.
 
-  var registered = false;
-  setUp(() => customElementsReady.then((_) {
-        if (!registered) {
-          registered = true;
-          document.registerElement2(A.tag, {'prototype': A});
-          document.registerElement2(B.tag, {'prototype': B});
-        }
-      }));
+  await customElementsReady;
+  document.registerElement2(A.tag, {'prototype': A});
+  document.registerElement2(B.tag, {'prototype': B});
 
   group('fully_supported', () {
     test('transfer attribute changed callback', () {
diff --git a/tests/lib_2/html/custom/created_callback_test.dart b/tests/lib_2/html/custom/created_callback_test.dart
index 1e75937..d5e193a 100644
--- a/tests/lib_2/html/custom/created_callback_test.dart
+++ b/tests/lib_2/html/custom/created_callback_test.dart
@@ -7,7 +7,7 @@
 import 'dart:html';
 import 'dart:js' as js;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'utils.dart';
 
@@ -56,21 +56,14 @@
   static var div;
 }
 
-main() {
+main() async {
   // Adapted from Blink's
   // fast/dom/custom/created-callback test.
 
-  var registered = false;
-  setUp(() {
-    return customElementsReady.then((_) {
-      if (!registered) {
-        registered = true;
-        document.registerElement2(B.tag, {'prototype': B});
-        document.registerElement2(C.tag, {'prototype': C});
-        ErrorConstructorElement.register();
-      }
-    });
-  });
+  await customElementsReady;
+  document.registerElement2(B.tag, {'prototype': B});
+  document.registerElement2(C.tag, {'prototype': C});
+  ErrorConstructorElement.register();
 
   test('transfer created callback', () {
     document.registerElement2(A.tag, {'prototype': A as dynamic});
diff --git a/tests/lib_2/html/custom/document_register_basic_test.dart b/tests/lib_2/html/custom/document_register_basic_test.dart
index 6bec727..3205761 100644
--- a/tests/lib_2/html/custom/document_register_basic_test.dart
+++ b/tests/lib_2/html/custom/document_register_basic_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'utils.dart';
 
@@ -40,10 +40,10 @@
   BadC.created() : super.created();
 }
 
-main() {
+main() async {
   // Adapted from Blink's fast/dom/custom/document-register-basic test.
 
-  setUp(() => customElementsReady);
+  await customElementsReady;
 
   test('Testing document.registerElement2() basic behaviors', () {
     document.registerElement2(Foo.tag, {'prototype': Foo});
diff --git a/tests/lib_2/html/custom/document_register_template_test.dart b/tests/lib_2/html/custom/document_register_template_test.dart
index 883f4f0..7e37b96 100644
--- a/tests/lib_2/html/custom/document_register_template_test.dart
+++ b/tests/lib_2/html/custom/document_register_template_test.dart
@@ -1,11 +1,11 @@
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'utils.dart';
 
-main() {
-  setUp(() => customElementsReady);
+main() async {
+  await customElementsReady;
 
   test('can register custom template with webcomponents-lite polyfill', () {
     document.registerElement2(
diff --git a/tests/lib_2/html/custom/document_register_type_extensions_test.dart b/tests/lib_2/html/custom/document_register_type_extensions_test.dart
index 964d80d..b1bdd67 100644
--- a/tests/lib_2/html/custom/document_register_type_extensions_test.dart
+++ b/tests/lib_2/html/custom/document_register_type_extensions_test.dart
@@ -4,7 +4,7 @@
 
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'utils.dart';
 
@@ -76,7 +76,7 @@
   CustomCustomDiv.created() : super.created();
 }
 
-main() {
+main() async {
   // Adapted from Blink's fast/dom/custom/document-register-type-extension test.
 
   var testForm = new FormElement()..id = 'testForm';
@@ -102,23 +102,24 @@
         'extends': 'div'});
   }
 
-  setUp(() => customElementsReady);
+  await customElementsReady;
 
   group('registration', () {
-    setUp(registerTypes);
-
     test('cannot register twice', () {
+      registerTypes();
       expect(() => document.registerElement2(FooBad.tag, {'prototype': Foo, 'extends': 'div'}),
           throws);
     });
 
     test('cannot register for non-matching tag', () {
+      registerTypes();
       expect(() {
         document.registerElement2('x-input-div', {'prototype': Bar, 'extends': 'div'});
       }, throws);
     });
 
     test('cannot register type extension for custom tag', () {
+      registerTypes();
       expect(() {
         document.registerElement2('x-custom-tag',  {'prototype': CustomCustomDiv});
       }, throws);
@@ -126,9 +127,8 @@
   });
 
   group('construction', () {
-    setUp(registerTypes);
-
     group('constructors', () {
+      registerTypes();
       test('custom tag', () {
         var fooNewed = new Foo();
         expect(fooNewed.outerHtml, anyOf(Foo.outerHtmlStrings));
@@ -164,6 +164,7 @@
     });
 
     group('single-parameter createElement', () {
+      registerTypes();
       test('custom tag', () {
         var fooCreated = new Element.tag('x-foo');
         expect(fooCreated.outerHtml, anyOf(Foo.outerHtmlStrings));
@@ -195,6 +196,7 @@
     });
 
     group('createElement with type extension', () {
+      registerTypes();
       test('does not upgrade extension of custom tag', () {
         var divFooCreated = new Element.tag("div", Foo.tag);
         expect(divFooCreated.outerHtml, '<div is="x-foo"></div>');
@@ -250,9 +252,8 @@
   });
 
   group('namespaces', () {
-    setUp(registerTypes);
-
     test('createElementNS', () {
+      registerTypes();
       var fooCreatedNS = document.createElementNS(
           "http://www.w3.org/1999/xhtml", Foo.tag, null);
       expect(fooCreatedNS.outerHtml, anyOf(Foo.outerHtmlStrings));
@@ -272,9 +273,8 @@
   });
 
   group('parsing', () {
-    setUp(registerTypes);
-
     test('parsing', () {
+      registerTypes();
       createElementFromHtml(html) {
         var container = new DivElement()
           ..setInnerHtml(html, treeSanitizer: new NullTreeSanitizer());
@@ -307,9 +307,8 @@
   });
 
   group('functional', () {
-    setUp(registerTypes);
-
     test('canvas', () {
+      registerTypes();
       var canvas = new MyCanvas();
       canvas.fillAsRed();
     });
diff --git a/tests/lib_2/html/custom/element_upgrade_failure_test.dart b/tests/lib_2/html/custom/element_upgrade_failure_test.dart
index a255162..28248ca 100644
--- a/tests/lib_2/html/custom/element_upgrade_failure_test.dart
+++ b/tests/lib_2/html/custom/element_upgrade_failure_test.dart
@@ -2,11 +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:async';
 import 'dart:html';
 import 'dart:js' as js;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'utils.dart';
 
@@ -26,34 +25,32 @@
   bool get fooCreated => _proxy['fooCreated'];
 }
 
-main() {
-  var registered = false;
-  var upgrader;
-  setUp(() => customElementsReady.then((_) {
-        if (!registered) {
-          registered = true;
-          upgrader = document.createElementUpgrader(FooElement);
-          js.context['upgradeListener'] = (e) {
-            upgrader.upgrade(e);
-          };
-        }
-      }));
-
+main() async {
+  await customElementsReady;
+  var upgrader = document.createElementUpgrader(FooElement);
+  js.context['upgradeListener'] = (e) {
+    upgrader.upgrade(e);
+  };
 
   test('cannot create upgrader for interfaces', () {
     expect(() {
-      document.createElementUpgrader(HtmlElementInterface); /*@compile-error=unspecified*/
+      // TODO(srujzs): Determine if this should be a static error.
+      document.createElementUpgrader(HtmlElementInterface);
     }, throws);
   });
 
   test('cannot upgrade interfaces', () {
     expect(() {
       upgrader.upgrade(new HtmlElementInterface());
+      //                   ^^^^^^^^^^^^^^^^^^^^
+      // [analyzer] STATIC_WARNING.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT
     }, throws);
   });
 }
 
-class HtmlElementInterface implements HtmlElement { /*@compile-error=unspecified*/
+class HtmlElementInterface implements HtmlElement {
+  //  ^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER
   HtmlElementInterface.created();
 }
 
diff --git a/tests/lib_2/html/custom/element_upgrade_test.dart b/tests/lib_2/html/custom/element_upgrade_test.dart
index 135cf3d..8c3df43 100644
--- a/tests/lib_2/html/custom/element_upgrade_test.dart
+++ b/tests/lib_2/html/custom/element_upgrade_test.dart
@@ -2,11 +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:async';
 import 'dart:html';
 import 'dart:js' as js;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'utils.dart';
 
@@ -26,21 +25,14 @@
   bool get fooCreated => _proxy['fooCreated'];
 }
 
-main() {
-  var registered = false;
-  var upgrader;
-  setUp(() => customElementsReady.then((_) {
-        if (!registered) {
-          registered = true;
-          upgrader = document.createElementUpgrader(FooElement);
-          js.context['upgradeListener'] = (e) {
-            upgrader.upgrade(e);
-          };
+main() async {
+  await customElementsReady;
+  var upgrader = document.createElementUpgrader(FooElement);
+  js.context['upgradeListener'] = (e) {
+    upgrader.upgrade(e);
+  };
 
-          document
-              .registerElement2('custom-element', {'prototype': CustomElement});
-        }
-      }));
+  document.registerElement2('custom-element', {'prototype': CustomElement});
 
   test('created gets proxied', () {
     var element = document.createElement(FooElement.tag);
diff --git a/tests/lib_2/html/custom/entered_left_view/disconnected_subtree_test.dart b/tests/lib_2/html/custom/entered_left_view/disconnected_subtree_test.dart
index 4f620f3..aacbfc5 100644
--- a/tests/lib_2/html/custom/entered_left_view/disconnected_subtree_test.dart
+++ b/tests/lib_2/html/custom/entered_left_view/disconnected_subtree_test.dart
@@ -9,20 +9,21 @@
 import 'dart:js' as js;
 
 import 'entered_left_view_util.dart';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import '../utils.dart';
 
-main() {
-  setUp(setupFunc);
+main() async {
+  await setupFunc();
   group('disconnected_subtree', () {
     var div = new DivElement();
 
-    setUp(() {
+    setUp() {
       invocations = [];
-    });
+    }
 
     test('Enters a disconnected subtree of DOM', () {
+      setUp();
       div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
       upgradeCustomElements(div);
 
@@ -32,6 +33,7 @@
     });
 
     test('Leaves a disconnected subtree of DOM', () {
+      setUp();
       div.innerHtml = '';
       expect(invocations, [],
           reason:
@@ -40,6 +42,7 @@
     });
 
     test('Enters a document with a view as a constituent of a subtree', () {
+      setUp();
       div.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
       upgradeCustomElements(div);
       invocations = [];
diff --git a/tests/lib_2/html/custom/entered_left_view/entered_left_view_standard_events_test.dart b/tests/lib_2/html/custom/entered_left_view/entered_left_view_standard_events_test.dart
index cbcaa84..8a5c69d 100644
--- a/tests/lib_2/html/custom/entered_left_view/entered_left_view_standard_events_test.dart
+++ b/tests/lib_2/html/custom/entered_left_view/entered_left_view_standard_events_test.dart
@@ -9,30 +9,33 @@
 import 'dart:js' as js;
 
 import 'entered_left_view_util.dart';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import '../utils.dart';
 
-main() {
-  setUp(setupFunc);
+main() async {
+  await setupFunc();
   group('standard_events', () {
     var a;
-    setUp(() {
+    setUp() {
       invocations = [];
-    });
+    }
 
     test('Created', () {
+      setUp();
       a = new Element.tag('x-a');
       expect(invocations, ['created']);
     });
 
     test('attached', () {
+      setUp();
       document.body.append(a);
       customElementsTakeRecords();
       expect(invocations, ['attached']);
     });
 
     test('detached', () {
+      setUp();
       a.remove();
       customElementsTakeRecords();
       expect(invocations, ['detached']);
@@ -40,18 +43,21 @@
 
     var div = new DivElement();
     test('nesting does not trigger attached', () {
+      setUp();
       div.append(a);
       customElementsTakeRecords();
       expect(invocations, []);
     });
 
     test('nested entering triggers attached', () {
+      setUp();
       document.body.append(div);
       customElementsTakeRecords();
       expect(invocations, ['attached']);
     });
 
     test('nested leaving triggers detached', () {
+      setUp();
       div.remove();
       customElementsTakeRecords();
       expect(invocations, ['detached']);
diff --git a/tests/lib_2/html/custom/entered_left_view/entered_left_view_util.dart b/tests/lib_2/html/custom/entered_left_view/entered_left_view_util.dart
index 7387775..ab3ad97 100644
--- a/tests/lib_2/html/custom/entered_left_view/entered_left_view_util.dart
+++ b/tests/lib_2/html/custom/entered_left_view/entered_left_view_util.dart
@@ -8,7 +8,7 @@
 import 'dart:html';
 import 'dart:js' as js;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import '../utils.dart';
 
@@ -66,14 +66,11 @@
 var docA = document;
 var docB = document.implementation.createHtmlDocument('');
 var nullSanitizer = new NullTreeSanitizer();
-var registeredTypes = false;
 
 setupFunc() {
   // Adapted from Blink's
   // fast/dom/custom/attached-detached-document.html test.
   return customElementsReady.then((_) {
-    if (registeredTypes) return;
-    registeredTypes = true;
     document.registerElement2('x-a', {'prototype': Foo});
     document.registerElement2('x-a-old', {'prototype': FooOldCallbacks});
   });
diff --git a/tests/lib_2/html/custom/entered_left_view/shadow_dom_test.dart b/tests/lib_2/html/custom/entered_left_view/shadow_dom_test.dart
index b40b912..3da0230 100644
--- a/tests/lib_2/html/custom/entered_left_view/shadow_dom_test.dart
+++ b/tests/lib_2/html/custom/entered_left_view/shadow_dom_test.dart
@@ -9,42 +9,47 @@
 import 'dart:js' as js;
 
 import 'entered_left_view_util.dart';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import '../utils.dart';
 
-main() {
-  setUp(setupFunc);
+main() async {
+  await setupFunc();
   group('shadow_dom', () {
     var div;
     var s;
-    setUp(() {
+    setUp() {
       invocations = [];
       div = new DivElement();
       s = div.createShadowRoot();
-    });
+    }
 
-    tearDown(() {
+    tearDown() {
       customElementsTakeRecords();
-    });
+    }
 
     test('Created in Shadow DOM that is not in a document', () {
+      setUp();
       s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
       upgradeCustomElements(s);
 
       expect(invocations, ['created'],
           reason: 'the attached callback should not be invoked when entering a '
               'Shadow DOM subtree not in the document');
+      tearDown();
     });
 
     test('Leaves Shadow DOM that is not in a document', () {
+      setUp();
       s.innerHtml = '';
       expect(invocations, [],
           reason: 'the detached callback should not be invoked when leaving a '
               'Shadow DOM subtree not in the document');
+      tearDown();
     });
 
     test('Enters a document with a view as a constituent of Shadow DOM', () {
+      setUp();
       s.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
       upgradeCustomElements(s);
 
@@ -60,6 +65,7 @@
       expect(invocations, ['created', 'attached', 'detached'],
           reason: 'the detached callback should be invoked when removed from a '
               'document with a view as part of Shadow DOM');
+      tearDown();
     });
   });
 }
diff --git a/tests/lib_2/html/custom/entered_left_view/standard_events_old_callback_names_test.dart b/tests/lib_2/html/custom/entered_left_view/standard_events_old_callback_names_test.dart
index 7c39184..36d8eaa 100644
--- a/tests/lib_2/html/custom/entered_left_view/standard_events_old_callback_names_test.dart
+++ b/tests/lib_2/html/custom/entered_left_view/standard_events_old_callback_names_test.dart
@@ -9,31 +9,34 @@
 import 'dart:js' as js;
 
 import 'entered_left_view_util.dart';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import '../utils.dart';
 
-main() {
-  setUp(setupFunc);
+main() async {
+  await setupFunc();
   // TODO(jmesserly): remove after deprecation period.
   group('standard_events_old_callback_names', () {
     var a;
-    setUp(() {
+    setUp() {
       invocations = [];
-    });
+    }
 
     test('Created', () {
+      setUp();
       a = new Element.tag('x-a-old');
       expect(invocations, ['created']);
     });
 
     test('enteredView', () {
+      setUp();
       document.body.append(a);
       customElementsTakeRecords();
       expect(invocations, ['enteredView']);
     });
 
     test('leftView', () {
+      setUp();
       a.remove();
       customElementsTakeRecords();
       expect(invocations, ['leftView']);
@@ -41,18 +44,21 @@
 
     var div = new DivElement();
     test('nesting does not trigger enteredView', () {
+      setUp();
       div.append(a);
       customElementsTakeRecords();
       expect(invocations, []);
     });
 
     test('nested entering triggers enteredView', () {
+      setUp();
       document.body.append(div);
       customElementsTakeRecords();
       expect(invocations, ['enteredView']);
     });
 
     test('nested leaving triggers leftView', () {
+      setUp();
       div.remove();
       customElementsTakeRecords();
       expect(invocations, ['leftView']);
diff --git a/tests/lib_2/html/custom/entered_left_view/viewless_document_test.dart b/tests/lib_2/html/custom/entered_left_view/viewless_document_test.dart
index 9fad3c0..75b57fa 100644
--- a/tests/lib_2/html/custom/entered_left_view/viewless_document_test.dart
+++ b/tests/lib_2/html/custom/entered_left_view/viewless_document_test.dart
@@ -9,19 +9,20 @@
 import 'dart:js' as js;
 
 import 'entered_left_view_util.dart';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import '../utils.dart';
 
-main() {
-  setUp(setupFunc);
+main() async {
+  await setupFunc();
   group('viewless_document', () {
     var a;
-    setUp(() {
+    setUp() {
       invocations = [];
-    });
+    }
 
     test('Created, owned by a document without a view', () {
+      setUp();
       a = docB.createElement('x-a');
       expect(a.ownerDocument, docB,
           reason: 'new instance should be owned by the document the definition '
@@ -31,6 +32,7 @@
     });
 
     test('Entered document without a view', () {
+      setUp();
       docB.body.append(a);
       expect(invocations, [],
           reason: 'attached callback should not be invoked when entering a '
@@ -38,6 +40,7 @@
     });
 
     test('Attribute changed in document without a view', () {
+      setUp();
       a.setAttribute('data-foo', 'bar');
       expect(invocations, ['attribute changed'],
           reason: 'changing an attribute should invoke the callback, even in a '
@@ -45,6 +48,7 @@
     });
 
     test('Entered document with a view', () {
+      setUp();
       document.body.append(a);
       customElementsTakeRecords();
       expect(invocations, ['attached'],
@@ -54,6 +58,7 @@
     });
 
     test('Left document with a view', () {
+      setUp();
       a.remove();
       customElementsTakeRecords();
       expect(invocations, ['detached'],
@@ -62,6 +67,7 @@
     });
 
     test('Created in a document without a view', () {
+      setUp();
       docB.body.setInnerHtml('<x-a></x-a>', treeSanitizer: nullSanitizer);
       upgradeCustomElements(docB.body);
 
diff --git a/tests/lib_2/html/custom/regress_194523002_test.dart b/tests/lib_2/html/custom/regress_194523002_test.dart
index bfecc97..692be98 100644
--- a/tests/lib_2/html/custom/regress_194523002_test.dart
+++ b/tests/lib_2/html/custom/regress_194523002_test.dart
@@ -5,7 +5,7 @@
 // Regression test for CL 194523002.
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 import 'utils.dart';
 
@@ -15,17 +15,10 @@
   A.created() : super.created();
 }
 
-main() {
+main() async {
   // Adapted from Blink's
   // fast/dom/custom/constructor-calls-created-synchronously test.
 
-  var registered = false;
-  setUp(() {
-    return customElementsReady.then((_) {
-      if (!registered) {
-        registered = true;
-        document.registerElement2(A.tag, {'prototype': A});
-      }
-    });
-  });
+  await customElementsReady;
+  document.registerElement2(A.tag, {'prototype': A});
 }
diff --git a/tests/lib_2/html/custom_element_method_clash_test.dart b/tests/lib_2/html/custom_element_method_clash_test.dart
index dca1d12..c152980 100644
--- a/tests/lib_2/html/custom_element_method_clash_test.dart
+++ b/tests/lib_2/html/custom_element_method_clash_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'utils.dart';
 
 class CustomElement extends HtmlElement {
@@ -20,8 +20,8 @@
   }
 }
 
-main() {
-  setUp(() => customElementsReady);
+main() async {
+  await customElementsReady;
 
   group('test', () {
     test('test', () {
diff --git a/tests/lib_2/html/custom_element_name_clash_test.dart b/tests/lib_2/html/custom_element_name_clash_test.dart
index 3ca1768..5061d34 100644
--- a/tests/lib_2/html/custom_element_name_clash_test.dart
+++ b/tests/lib_2/html/custom_element_name_clash_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'utils.dart';
 
 class CustomElement extends HtmlElement {
@@ -18,8 +18,8 @@
   var appendChild = 123;
 }
 
-main() {
-  setUp(() => customElementsReady);
+main() async {
+  await customElementsReady;
 
   group('test', () {
     test('test', () {
diff --git a/tests/lib_2/html/custom_elements_23127_test.dart b/tests/lib_2/html/custom_elements_23127_test.dart
index 6e04e01..a1f0545 100644
--- a/tests/lib_2/html/custom_elements_23127_test.dart
+++ b/tests/lib_2/html/custom_elements_23127_test.dart
@@ -10,7 +10,7 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'utils.dart';
 
 abstract class B1 extends HtmlElement {
@@ -86,8 +86,8 @@
 
 var callTwice;
 
-main() {
-  setUp(() => customElementsReady);
+main() async {
+  await customElementsReady;
 
   callTwice = (f) {
     f();
diff --git a/tests/lib_2/html/custom_elements_test.dart b/tests/lib_2/html/custom_elements_test.dart
index 6c787c4..4af42ec 100644
--- a/tests/lib_2/html/custom_elements_test.dart
+++ b/tests/lib_2/html/custom_elements_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'utils.dart';
 
 class CustomMixin {
@@ -38,8 +38,8 @@
 
 class NotAnElement {}
 
-main() {
-  setUp(() => customElementsReady);
+main() async {
+  await customElementsReady;
 
   group('register', () {
     test('register', () {
diff --git a/tests/lib_2/html/element_animate_omit_timing_test.dart b/tests/lib_2/html/element_animate_omit_timing_test.dart
index 92716c2..9aa98e0 100644
--- a/tests/lib_2/html/element_animate_omit_timing_test.dart
+++ b/tests/lib_2/html/element_animate_omit_timing_test.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test('omit timing', () {
diff --git a/tests/lib_2/html/element_animate_simple_timing_test.dart b/tests/lib_2/html/element_animate_simple_timing_test.dart
index ea33b0a..b35dd99 100644
--- a/tests/lib_2/html/element_animate_simple_timing_test.dart
+++ b/tests/lib_2/html/element_animate_simple_timing_test.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test('simple timing', () {
diff --git a/tests/lib_2/html/element_animate_supported_test.dart b/tests/lib_2/html/element_animate_supported_test.dart
index 233c138..7f11c8a 100644
--- a/tests/lib_2/html/element_animate_supported_test.dart
+++ b/tests/lib_2/html/element_animate_supported_test.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test('supported', () {
diff --git a/tests/lib_2/html/element_animate_timing_dict_test.dart b/tests/lib_2/html/element_animate_timing_dict_test.dart
index c4e414a..1276b90 100644
--- a/tests/lib_2/html/element_animate_timing_dict_test.dart
+++ b/tests/lib_2/html/element_animate_timing_dict_test.dart
@@ -7,7 +7,7 @@
 import 'dart:async';
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 main() {
   test('timing dict', () {
diff --git a/tests/lib_2/html/element_test.dart b/tests/lib_2/html/element_test.dart
index e6e3e9a..d428999 100644
--- a/tests/lib_2/html/element_test.dart
+++ b/tests/lib_2/html/element_test.dart
@@ -4,17 +4,13 @@
 
 library ElementTest;
 
-import 'package:unittest/unittest.dart';
-import 'package:unittest/src/expected_function.dart' show ExpectedFunction;
+import 'package:async_helper/async_minitest.dart';
+import 'package:expect/expect.dart';
 import 'dart:async';
 import 'dart:html';
 import 'dart:svg' as svg;
 import 'utils.dart';
 
-T Function(A) expectAsync1<T, A>(T Function(A) callback,
-        {int count: 1, int max: 0}) =>
-    new ExpectedFunction<T>(callback, count, max).max1;
-
 expectLargeRect(Rectangle rect) {
   expect(rect.top, 0);
   expect(rect.left, 0);
@@ -25,9 +21,7 @@
 }
 
 void testUnsupported(String name, void f()) {
-  test(name, () {
-    expect(f, throwsUnsupportedError);
-  });
+  test(name, () => Expect.throwsUnsupportedError(f));
 }
 
 main() {
@@ -87,7 +81,7 @@
 
   group('constructors', () {
     test('error', () {
-      expect(() => new Element.html('<br/><br/>'), throwsStateError);
+      Expect.throwsStateError(() => new Element.html('<br/><br/>'));
     });
 
     test('.html has no parent',
@@ -358,6 +352,7 @@
           treeSanitizer: new NullTreeSanitizer());
       final attributes = element.attributes;
       expect(attributes['class'], 'foo');
+      startsWith(match) => predicate((x) => x is String && x.startsWith(match));
       expect(attributes['style'], startsWith('overflow: hidden'));
       expect(attributes['data-foo'], 'bar');
       expect(attributes['data-foo2'], 'bar2');
diff --git a/tests/lib_2/html/events_test.dart b/tests/lib_2/html/events_test.dart
index 807bcfe..8211f66 100644
--- a/tests/lib_2/html/events_test.dart
+++ b/tests/lib_2/html/events_test.dart
@@ -6,16 +6,8 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:unittest/unittest.dart';
-import 'package:unittest/src/expected_function.dart' show ExpectedFunction;
-
-T Function() expectAsync0<T>(T Function() callback,
-        {int count: 1, int max: 0}) =>
-    new ExpectedFunction<T>(callback, count, max).max0;
-
-T Function(A) expectAsync1<T, A>(T Function(A) callback,
-        {int count: 1, int max: 0}) =>
-    new ExpectedFunction<T>(callback, count, max).max1;
+import 'package:async_helper/async_minitest.dart';
+import 'package:expect/expect.dart';
 
 main() {
   test('TimeStamp', () {
@@ -55,7 +47,7 @@
 
     invocationCounter = 0;
     element.dispatchEvent(event);
-    expect(invocationCounter, isZero);
+    expect(invocationCounter, 0);
 
     var provider = new EventStreamProvider<Event>('test');
 
@@ -67,7 +59,7 @@
     sub.cancel();
     invocationCounter = 0;
     element.dispatchEvent(event);
-    expect(invocationCounter, isZero);
+    expect(invocationCounter, 0);
 
     provider.forTarget(element).listen(handler);
     invocationCounter = 0;
@@ -105,7 +97,7 @@
     // rely on this. We therefore wrap it into an expectAsync.
     runZoned(expectAsync0(() {
       var zone = Zone.current;
-      expect(zone, isNot(equals(Zone.root)));
+      Expect.notEquals(zone, Zone.root);
 
       StreamSubscription<Event> sub;
 
diff --git a/tests/lib_2/html/file_sample_test.dart b/tests/lib_2/html/file_sample_test.dart
index 4d0db32..2e626e8 100644
--- a/tests/lib_2/html/file_sample_test.dart
+++ b/tests/lib_2/html/file_sample_test.dart
@@ -4,7 +4,7 @@
 import 'dart:html';
 
 import 'package:async_helper/async_helper.dart';
-import 'package:unittest/unittest.dart';
+import 'package:expect/minitest.dart';
 
 // Expected output from all functions, asynchronous, and event routines.
 const String log_results = 'test-first\n' +
@@ -99,44 +99,47 @@
   return entries;
 }
 
+Future testFileSystemRequest() async {
+  testLog.log('test-first');
+  var fs = await fileSystem;
+  testLog.log('first START');
+  expect(fs != null, true);
+  expect(fs.root != null, true);
+  expect(fs.runtimeType, FileSystem);
+  expect(fs.root.runtimeType, DirectoryEntry);
+  testLog.log('first END');
+}
+
+Future testFileSystemRequestCreateRW() async {
+  testLog.log('test-second');
+  var fs = await fileSystem;
+  testLog.log('second START');
+  expect(fs != null, true);
+  expect(fs.root != null, true);
+  expect(fs.runtimeType, FileSystem);
+  expect(fs.root.runtimeType, DirectoryEntry);
+  testLog.log('second END');
+
+  FileEntry fileEntry = await createFile();
+  expect(fileEntry.name, 'log.txt');
+
+  List<Entry> entries = await readEntries(fs.root);
+  expect(entries.length > 0, true);
+  expect(entries[0].isDirectory, true);
+  expect(entries[0].name, 'my_directory');
+
+  List<Entry> myEntries = await readEntries(_myDirectory);
+  expect(myEntries.length, 1);
+  expect(myEntries[0].isFile, true);
+  expect(myEntries[0].name, 'log.txt');
+
+  // Validate every function, async and event mechanism successfully ran.
+  expect(testLog.contents, log_results);
+}
+
 main() {
-  group('test FileSystem', () {
-    test('FileSystem request #1', () async {
-      testLog.log('test-first');
-      var fs = await fileSystem;
-      testLog.log('first START');
-      expect(fs != null, true);
-      expect(fs.root != null, true);
-      expect(fs.runtimeType, FileSystem);
-      expect(fs.root.runtimeType, DirectoryEntry);
-      testLog.log('first END');
-    });
-
-    test('FileSystem request, create, R/W', () async {
-      testLog.log('test-second');
-      var fs = await fileSystem;
-      testLog.log('second START');
-      expect(fs != null, true);
-      expect(fs.root != null, true);
-      expect(fs.runtimeType, FileSystem);
-      expect(fs.root.runtimeType, DirectoryEntry);
-      testLog.log('second END');
-
-      FileEntry fileEntry = await createFile();
-      expect(fileEntry.name, 'log.txt');
-
-      List<Entry> entries = await readEntries(fs.root);
-      expect(entries.length > 0, true);
-      expect(entries[0].isDirectory, true);
-      expect(entries[0].name, 'my_directory');
-
-      List<Entry> myEntries = await readEntries(_myDirectory);
-      expect(myEntries.length, 1);
-      expect(myEntries[0].isFile, true);
-      expect(myEntries[0].name, 'log.txt');
-
-      // Validate every function, async and event mechanism successfully ran.
-      expect(testLog.contents, log_results);
-    });
+  asyncTest(() async {
+    await testFileSystemRequest();
+    await testFileSystemRequestCreateRW();
   });
 }
diff --git a/tests/lib_2/html/fileapi_entry_test.dart b/tests/lib_2/html/fileapi_entry_test.dart
index 07b8840..0f2f490 100644
--- a/tests/lib_2/html/fileapi_entry_test.dart
+++ b/tests/lib_2/html/fileapi_entry_test.dart
@@ -4,7 +4,7 @@
 import 'dart:html';
 
 import 'package:async_helper/async_helper.dart';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 
 class FileAndDir {
   FileEntry file;
diff --git a/tests/lib_2/html/form_data_test.dart b/tests/lib_2/html/form_data_test.dart
index 2a01ea0..03592e2 100644
--- a/tests/lib_2/html/form_data_test.dart
+++ b/tests/lib_2/html/form_data_test.dart
@@ -4,7 +4,7 @@
 
 library FormDataTest;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:html';
 
 void main() {
@@ -68,7 +68,7 @@
             '${window.location.protocol}//${window.location.host}/echo');
 
         xhr.onLoad.listen(expectAsync((e) {
-          expect(xhr.responseText, contains(blobString));
+          expect(xhr.responseText.contains(blobString), isTrue);
         }));
         xhr.onError.listen((e) {
           fail('$e');
diff --git a/tests/lib_2/html/history_hash_change_test.dart b/tests/lib_2/html/history_hash_change_test.dart
index 8bca7e0..b15685f 100644
--- a/tests/lib_2/html/history_hash_change_test.dart
+++ b/tests/lib_2/html/history_hash_change_test.dart
@@ -1,6 +1,6 @@
 library HistoryTest;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:html';
 import 'dart:async';
 
diff --git a/tests/lib_2/html/history_supported_test.dart b/tests/lib_2/html/history_supported_test.dart
index 1795e35..358d32a 100644
--- a/tests/lib_2/html/history_supported_test.dart
+++ b/tests/lib_2/html/history_supported_test.dart
@@ -1,6 +1,6 @@
 library HistoryTest;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:html';
 import 'dart:async';
 
diff --git a/tests/lib_2/html/history_test.dart b/tests/lib_2/html/history_test.dart
index 064c583..ffcdede 100644
--- a/tests/lib_2/html/history_test.dart
+++ b/tests/lib_2/html/history_test.dart
@@ -1,6 +1,6 @@
 library HistoryTest;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:html';
 import 'dart:async';
 
diff --git a/tests/lib_2/html/indexeddb_1_test.dart b/tests/lib_2/html/indexeddb_1_test.dart
index 513c028..932f3fb 100644
--- a/tests/lib_2/html/indexeddb_1_test.dart
+++ b/tests/lib_2/html/indexeddb_1_test.dart
@@ -1,6 +1,6 @@
 library IndexedDB1Test;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:async';
 import 'dart:html' as html;
 import 'dart:math' as math;
diff --git a/tests/lib_2/html/indexeddb_2_test.dart b/tests/lib_2/html/indexeddb_2_test.dart
index 5875a290..17478b9 100644
--- a/tests/lib_2/html/indexeddb_2_test.dart
+++ b/tests/lib_2/html/indexeddb_2_test.dart
@@ -1,6 +1,7 @@
 library IndexedDB1Test;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:async';
 import 'dart:html' as html;
 import 'dart:indexed_db' as idb;
@@ -68,7 +69,7 @@
   var cyclic_list = <Object>[1, 2, 3];
   cyclic_list[1] = cyclic_list;
 
-  go(name, data) => test(name, () => testReadWrite(123, data, verifyGraph));
+  go(name, data) => testReadWrite(123, data, verifyGraph);
 
   test('test_verifyGraph', () {
     // Nice to know verifyGraph is working before we rely on it.
@@ -82,12 +83,17 @@
       const [1, 2, 3]
     ];
     verifyGraph([l1, l1], l2);
-    expect(
-        () => verifyGraph([
-              [1, 2, 3],
-              [1, 2, 3]
-            ], l2),
-        throws);
+    // Use a try-catch block, since failure can be an expect exception.
+    // package:expect does not allow catching test exceptions.
+    try {
+      verifyGraph([
+        [1, 2, 3],
+        [1, 2, 3]
+      ], l2);
+      fail("Expected failure in verifying the graph.");
+    } catch (_) {
+      // Expected failure. Continue.
+    }
 
     verifyGraph(cyclic_list, cyclic_list);
   });
@@ -95,27 +101,29 @@
   // Don't bother with these tests if it's unsupported.
   // Support is tested in indexeddb_1_test
   if (idb.IdbFactory.supported) {
-    go('test_simple', obj1);
-    go('test_DAG', obj2);
-    go('test_cycle', obj3);
-    go('test_simple_splay', obj4);
-    go('const_array_1', const [
-      const [1],
-      const [2]
-    ]);
-    go('const_array_dag', const [
-      const [1],
-      const [1]
-    ]);
-    go('array_deferred_copy', [1, 2, 3, obj3, obj3, 6]);
-    go('array_deferred_copy_2', [
-      1,
-      2,
-      3,
-      [4, 5, obj3],
-      [obj3, 6]
-    ]);
-    go('cyclic_list', cyclic_list);
-    go('non-native lists', nonNativeListData);
+    asyncTest(() async {
+      await go('test_simple', obj1);
+      await go('test_DAG', obj2);
+      await go('test_cycle', obj3);
+      await go('test_simple_splay', obj4);
+      await go('const_array_1', const [
+        const [1],
+        const [2]
+      ]);
+      await go('const_array_dag', const [
+        const [1],
+        const [1]
+      ]);
+      await go('array_deferred_copy', [1, 2, 3, obj3, obj3, 6]);
+      await go('array_deferred_copy_2', [
+        1,
+        2,
+        3,
+        [4, 5, obj3],
+        [obj3, 6]
+      ]);
+      await go('cyclic_list', cyclic_list);
+      await go('non-native lists', nonNativeListData);
+    });
   }
 }
diff --git a/tests/lib_2/html/indexeddb_3_test.dart b/tests/lib_2/html/indexeddb_3_test.dart
index add27e3..52bccb4 100644
--- a/tests/lib_2/html/indexeddb_3_test.dart
+++ b/tests/lib_2/html/indexeddb_3_test.dart
@@ -1,6 +1,7 @@
 library IndexedDB3Test;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:async';
 import 'dart:html' as html;
 import 'dart:indexed_db';
@@ -92,18 +93,10 @@
   // Don't bother with these tests if it's unsupported.
   // Support is tested in indexeddb_1_test
   if (IdbFactory.supported) {
-    var db;
-    test('prepare', () {
-      return setupDb().then((result) {
-        db = result;
-      });
-    });
-    test('readAll1', () {
-      return readAllViaCursor(db);
-    });
-
-    test('readAll2', () {
-      return readAllReversedViaCursor(db);
+    asyncTest(() async {
+      var db = await setupDb();
+      await readAllViaCursor(db);
+      await readAllReversedViaCursor(db);
     });
   }
 }
diff --git a/tests/lib_2/html/indexeddb_4_test.dart b/tests/lib_2/html/indexeddb_4_test.dart
index bebf61f..2c98884 100644
--- a/tests/lib_2/html/indexeddb_4_test.dart
+++ b/tests/lib_2/html/indexeddb_4_test.dart
@@ -1,6 +1,6 @@
 library IndexedDB4Test;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:async';
 import 'dart:html' as html;
 import 'dart:indexed_db';
@@ -69,25 +69,18 @@
 
   return cursors.length.then((length) {
     if (expectedFirst == null) {
-      expect(length, isZero);
+      expect(length, 0);
     } else {
       expect(length, expectedLast - expectedFirst + 1);
     }
   });
 }
 
-main() {
+main() async {
   // Don't bother with these tests if it's unsupported.
   // Support is tested in indexeddb_1_test
   if (IdbFactory.supported) {
-    var db;
-    setUp(() {
-      if (db == null) {
-        return setupDb().then((result) {
-          db = result;
-        });
-      }
-    });
+    var db = await setupDb();
     test('only1', () => testRange(db, new KeyRange.only(55), 55, 55));
     test('only2', () => testRange(db, new KeyRange.only(100), null, null));
     test('only3', () => testRange(db, new KeyRange.only(-1), null, null));
diff --git a/tests/lib_2/html/indexeddb_5_test.dart b/tests/lib_2/html/indexeddb_5_test.dart
index bd32965..41c557a 100644
--- a/tests/lib_2/html/indexeddb_5_test.dart
+++ b/tests/lib_2/html/indexeddb_5_test.dart
@@ -1,168 +1,144 @@
 library IndexedDB1Test;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:async';
 import 'dart:html' as html;
 import 'dart:indexed_db' as idb;
 
+var dbName = 'test_db_5';
+var storeName = 'test_store';
+var indexName = 'name_index';
+var db;
+var value = {'name_index': 'one', 'value': 'add_value'};
+
+Future testInit() async {
+  await html.window.indexedDB.deleteDatabase(dbName);
+  db = await html.window.indexedDB.open(dbName, version: 1,
+      onUpgradeNeeded: (idb.VersionChangeEvent e) {
+    var db = e.target.result;
+    var objectStore = db.createObjectStore(storeName, autoIncrement: true);
+    objectStore.createIndex(indexName, 'name_index', unique: false);
+  });
+}
+
+Future testAddDelete() async {
+  var transaction = db.transaction(storeName, 'readwrite');
+  var key = await transaction.objectStore(storeName).add(value);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  var readValue = await transaction.objectStore(storeName).getObject(key);
+  expect(readValue['value'], value['value']);
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readwrite');
+  await transaction.objectStore(storeName).delete(key);
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readonly');
+  var count = await transaction.objectStore(storeName).count();
+  expect(count, 0);
+}
+
+Future testClearCount() async {
+  var transaction = db.transaction(storeName, 'readwrite');
+  transaction.objectStore(storeName).add(value);
+
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  var count = await transaction.objectStore(storeName).count();
+  expect(count, 1);
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readwrite');
+  transaction.objectStore(storeName).clear();
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readonly');
+  count = await transaction.objectStore(storeName).count();
+  expect(count, 0);
+}
+
+Future testIndex() async {
+  var transaction = db.transaction(storeName, 'readwrite');
+  transaction.objectStore(storeName).add(value);
+  transaction.objectStore(storeName).add(value);
+  transaction.objectStore(storeName).add(value);
+  transaction.objectStore(storeName).add(value);
+
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readonly');
+  var index = transaction.objectStore(storeName).index(indexName);
+  var count = await index.count();
+  expect(count, 4);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  var cursorsLength = await index.openCursor(autoAdvance: true).length;
+  expect(cursorsLength, 4);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  cursorsLength = await index.openKeyCursor(autoAdvance: true).length;
+  expect(cursorsLength, 4);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  var readValue = await index.get('one');
+  expect(readValue['value'], value['value']);
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readwrite');
+  transaction.objectStore(storeName).clear();
+  return transaction.completed;
+}
+
+Future testCursor() async {
+  var deleteValue = {'name_index': 'two', 'value': 'delete_value'};
+  var updateValue = {'name_index': 'three', 'value': 'update_value'};
+  var updatedValue = {'name_index': 'three', 'value': 'updated_value'};
+  var transaction = db.transaction(storeName, 'readwrite');
+  transaction.objectStore(storeName).add(value);
+  transaction.objectStore(storeName).add(deleteValue);
+  transaction.objectStore(storeName).add(updateValue);
+
+  await transaction.completed;
+  transaction = db.transactionList([storeName], 'readwrite');
+  var index = transaction.objectStore(storeName).index(indexName);
+  var cursors = index.openCursor().asBroadcastStream();
+
+  cursors.listen((cursor) {
+    var value = cursor.value;
+    if (value['value'] == 'delete_value') {
+      cursor.delete().then((_) {
+        cursor.next();
+      });
+    } else if (value['value'] == 'update_value') {
+      cursor.update(updatedValue).then((_) {
+        cursor.next();
+      });
+    } else {
+      cursor.next();
+    }
+  });
+  await cursors.last;
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  var readValue = await index.get('three');
+  expect(readValue['value'], 'updated_value');
+  await transaction.completed;
+  transaction = db.transaction(storeName, 'readonly');
+  index = transaction.objectStore(storeName).index(indexName);
+  readValue = await index.get('two');
+  expect(readValue, isNull);
+  return transaction.completed;
+}
+
 main() {
   if (!idb.IdbFactory.supported) {
     return;
   }
-
-  var dbName = 'test_db_5';
-  var storeName = 'test_store';
-  var indexName = 'name_index';
-  var db;
-
-  test('init', () async {
-    await html.window.indexedDB.deleteDatabase(dbName);
-    db = await html.window.indexedDB.open(dbName, version: 1,
-        onUpgradeNeeded: (idb.VersionChangeEvent e) {
-      var db = e.target.result;
-      var objectStore = db.createObjectStore(storeName, autoIncrement: true);
-      var index =
-          objectStore.createIndex(indexName, 'name_index', unique: false);
-    });
-  });
-
-  var value = {'name_index': 'one', 'value': 'add_value'};
-  test('add/delete', () {
-    var transaction = db.transaction(storeName, 'readwrite');
-    var key;
-    return transaction.objectStore(storeName).add(value).then((addedKey) {
-      key = addedKey;
-    }).then((_) {
-      return transaction.completed;
-    }).then((_) {
-      transaction = db.transaction(storeName, 'readonly');
-      return transaction.objectStore(storeName).getObject(key);
-    }).then((readValue) {
-      expect(readValue['value'], value['value']);
-      return transaction.completed;
-    }).then((_) {
-      transaction = db.transactionList([storeName], 'readwrite');
-      return transaction.objectStore(storeName).delete(key);
-    }).then((_) {
-      return transaction.completed;
-    }).then((_) {
-      var transaction = db.transactionList([storeName], 'readonly');
-      return transaction.objectStore(storeName).count();
-    }).then((count) {
-      expect(count, 0);
-    });
-  });
-
-  test('clear/count', () {
-    var transaction = db.transaction(storeName, 'readwrite');
-    transaction.objectStore(storeName).add(value);
-
-    return transaction.completed.then((_) {
-      transaction = db.transaction(storeName, 'readonly');
-      return transaction.objectStore(storeName).count();
-    }).then((count) {
-      expect(count, 1);
-    }).then((_) {
-      return transaction.completed;
-    }).then((_) {
-      transaction = db.transactionList([storeName], 'readwrite');
-      transaction.objectStore(storeName).clear();
-      return transaction.completed;
-    }).then((_) {
-      var transaction = db.transactionList([storeName], 'readonly');
-      return transaction.objectStore(storeName).count();
-    }).then((count) {
-      expect(count, 0);
-    });
-  });
-
-  test('index', () {
-    var transaction = db.transaction(storeName, 'readwrite');
-    transaction.objectStore(storeName).add(value);
-    transaction.objectStore(storeName).add(value);
-    transaction.objectStore(storeName).add(value);
-    transaction.objectStore(storeName).add(value);
-
-    return transaction.completed.then((_) {
-      transaction = db.transactionList([storeName], 'readonly');
-      var index = transaction.objectStore(storeName).index(indexName);
-      return index.count();
-    }).then((count) {
-      expect(count, 4);
-      return transaction.completed;
-    }).then((_) {
-      transaction = db.transaction(storeName, 'readonly');
-      var index = transaction.objectStore(storeName).index(indexName);
-      return index.openCursor(autoAdvance: true).length;
-    }).then((cursorsLength) {
-      expect(cursorsLength, 4);
-      return transaction.completed;
-    }).then((_) {
-      transaction = db.transaction(storeName, 'readonly');
-      var index = transaction.objectStore(storeName).index(indexName);
-      return index.openKeyCursor(autoAdvance: true).length;
-    }).then((cursorsLength) {
-      expect(cursorsLength, 4);
-      return transaction.completed;
-    }).then((_) {
-      transaction = db.transaction(storeName, 'readonly');
-      var index = transaction.objectStore(storeName).index(indexName);
-      return index.get('one');
-    }).then((readValue) {
-      expect(readValue['value'], value['value']);
-      return transaction.completed;
-    }).then((_) {
-      transaction = db.transaction(storeName, 'readwrite');
-      transaction.objectStore(storeName).clear();
-      return transaction.completed;
-    });
-  });
-
-  var deleteValue = {'name_index': 'two', 'value': 'delete_value'};
-  var updateValue = {'name_index': 'three', 'value': 'update_value'};
-  var updatedValue = {'name_index': 'three', 'value': 'updated_value'};
-  test('cursor', () {
-    var transaction = db.transaction(storeName, 'readwrite');
-    transaction.objectStore(storeName).add(value);
-    transaction.objectStore(storeName).add(deleteValue);
-    transaction.objectStore(storeName).add(updateValue);
-
-    return transaction.completed.then((_) {
-      transaction = db.transactionList([storeName], 'readwrite');
-      var index = transaction.objectStore(storeName).index(indexName);
-      var cursors = index.openCursor().asBroadcastStream();
-
-      cursors.listen((cursor) {
-        var value = cursor.value;
-        if (value['value'] == 'delete_value') {
-          cursor.delete().then((_) {
-            cursor.next();
-          });
-        } else if (value['value'] == 'update_value') {
-          cursor.update(updatedValue).then((_) {
-            cursor.next();
-          });
-        } else {
-          cursor.next();
-        }
-      });
-      return cursors.last;
-    }).then((_) {
-      return transaction.completed;
-    }).then((_) {
-      transaction = db.transaction(storeName, 'readonly');
-      var index = transaction.objectStore(storeName).index(indexName);
-      return index.get('three');
-    }).then((readValue) {
-      expect(readValue['value'], 'updated_value');
-      return transaction.completed;
-    }).then((_) {
-      transaction = db.transaction(storeName, 'readonly');
-      var index = transaction.objectStore(storeName).index(indexName);
-      return index.get('two');
-    }).then((readValue) {
-      expect(readValue, isNull);
-      return transaction.completed;
-    });
+  asyncTest(() async {
+    await testInit();
+    await testAddDelete();
+    await testClearCount();
+    await testIndex();
+    await testCursor();
   });
 }
diff --git a/tests/lib_2/html/interactive_geolocation_test.dart b/tests/lib_2/html/interactive_geolocation_test.dart
index 11d34c3..1ad3a13 100644
--- a/tests/lib_2/html/interactive_geolocation_test.dart
+++ b/tests/lib_2/html/interactive_geolocation_test.dart
@@ -6,26 +6,27 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:expect/expect.dart';
 import 'utils.dart';
 
-main() {
-  test('getCurrentPosition', () {
-    return window.navigator.geolocation.getCurrentPosition().then((position) {
-      expect(position.coords.latitude, isNotNull);
-      expect(position.coords.longitude, isNotNull);
-      expect(position.coords.accuracy, isNotNull);
-    });
-  });
+Future testGetCurrentPosition() async {
+  var position = await window.navigator.geolocation.getCurrentPosition();
+  Expect.isNotNull(position.coords.latitude);
+  Expect.isNotNull(position.coords.longitude);
+  Expect.isNotNull(position.coords.accuracy);
+}
 
-  test('watchPosition', () {
-    return window.navigator.geolocation
-        .watchPosition()
-        .first
-        .then((position) {
-      expect(position.coords.latitude, isNotNull);
-      expect(position.coords.longitude, isNotNull);
-      expect(position.coords.accuracy, isNotNull);
-    });
+Future testWatchPosition() async {
+  var position = await window.navigator.geolocation.watchPosition().first;
+  Expect.isNotNull(position.coords.latitude);
+  Expect.isNotNull(position.coords.longitude);
+  Expect.isNotNull(position.coords.accuracy);
+}
+
+main() {
+  asyncTest(() async {
+    await testGetCurrentPosition();
+    await testWatchPosition();
   });
 }
diff --git a/tests/lib_2/html/interactive_test.dart b/tests/lib_2/html/interactive_test.dart
index d1f1269..2392e27 100644
--- a/tests/lib_2/html/interactive_test.dart
+++ b/tests/lib_2/html/interactive_test.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 import 'dart:html';
-import 'package:unittest/unittest.dart';
+import 'package:expect/minitest.dart';
 import 'utils.dart';
 
 main() {
diff --git a/tests/lib_2/html/js_interop_1_test.dart b/tests/lib_2/html/js_interop_1_test.dart
index c4238d6..d008a39 100644
--- a/tests/lib_2/html/js_interop_1_test.dart
+++ b/tests/lib_2/html/js_interop_1_test.dart
@@ -4,7 +4,8 @@
 
 library JsInterop1Test;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_helper.dart';
+import 'dart:async';
 import 'dart:html';
 
 injectSource(code) {
@@ -15,17 +16,17 @@
 }
 
 main() {
-  var callback;
-
-  test('js-to-dart-post-message', () {
-    var subscription = null;
-    var complete = false;
-    subscription = window.onMessage.listen(expectAsyncUntil((e) {
-      if (e.data == 'hello') {
+  asyncTest(() async {
+    var subscription;
+    var completer = Completer<void>();
+    subscription = window.onMessage.listen((e) {
+      if (!completer.isCompleted && e.data == 'hello') {
+        completer.complete();
         subscription.cancel();
-        complete = true;
       }
-    }, () => complete));
+    });
     injectSource("window.postMessage('hello', '*');");
+
+    await completer;
   });
 }
diff --git a/tests/lib_2/html/js_interop_constructor_name/div_test.dart b/tests/lib_2/html/js_interop_constructor_name/div_test.dart
index f24cfe6..02a7826 100644
--- a/tests/lib_2/html/js_interop_constructor_name/div_test.dart
+++ b/tests/lib_2/html/js_interop_constructor_name/div_test.dart
@@ -9,8 +9,8 @@
 import 'dart:js';
 import 'package:js/js.dart';
 
-import 'package:unittest/unittest.dart';
 import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:expect/minitest.dart';
 
 @JS()
 external makeDiv(String text);
diff --git a/tests/lib_2/html/js_interop_constructor_name/error1_test.dart b/tests/lib_2/html/js_interop_constructor_name/error1_test.dart
index 06323e7..bb27475 100644
--- a/tests/lib_2/html/js_interop_constructor_name/error1_test.dart
+++ b/tests/lib_2/html/js_interop_constructor_name/error1_test.dart
@@ -9,8 +9,8 @@
 import 'dart:js';
 import 'package:js/js.dart';
 
-import 'package:unittest/unittest.dart';
 import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:expect/minitest.dart';
 
 @JS()
 external makeDiv(String text);
diff --git a/tests/lib_2/html/js_interop_constructor_name/error2_test.dart b/tests/lib_2/html/js_interop_constructor_name/error2_test.dart
index 44c2226..9fab532 100644
--- a/tests/lib_2/html/js_interop_constructor_name/error2_test.dart
+++ b/tests/lib_2/html/js_interop_constructor_name/error2_test.dart
@@ -9,8 +9,8 @@
 import 'dart:js';
 import 'package:js/js.dart';
 
-import 'package:unittest/unittest.dart';
 import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:expect/minitest.dart';
 
 @JS()
 external makeDiv(String text);
diff --git a/tests/lib_2/html/js_interop_constructor_name/method_test.dart b/tests/lib_2/html/js_interop_constructor_name/method_test.dart
index 4de6adf..e881467 100644
--- a/tests/lib_2/html/js_interop_constructor_name/method_test.dart
+++ b/tests/lib_2/html/js_interop_constructor_name/method_test.dart
@@ -9,8 +9,8 @@
 import 'dart:js';
 import 'package:js/js.dart';
 
-import 'package:unittest/unittest.dart';
-import 'package:expect/expect.dart' show NoInline, AssumeDynamic;
+import 'package:expect/expect.dart' show NoInline, AssumeDynamic, Expect;
+import 'package:expect/minitest.dart';
 
 @JS()
 external makeDiv(String text);
@@ -42,6 +42,6 @@
 
   test('dom-call-dom-method', () {
     var e = confuse(new html.DivElement());
-    expect(e.clone(false), new isInstanceOf<html.DivElement>());
+    Expect.type<html.DivElement>(e.clone(false));
   });
 }
diff --git a/tests/lib_2/html/js_test_util.dart b/tests/lib_2/html/js_test_util.dart
index a1ea26a..4702c16 100644
--- a/tests/lib_2/html/js_test_util.dart
+++ b/tests/lib_2/html/js_test_util.dart
@@ -8,7 +8,7 @@
 import 'dart:indexed_db' show IdbFactory, KeyRange;
 import 'dart:js';
 
-import 'package:unittest/unittest.dart';
+import 'package:expect/minitest.dart';
 
 injectJs() {
   final script = new ScriptElement();
diff --git a/tests/lib_2/html/js_util_test.dart b/tests/lib_2/html/js_util_test.dart
index 1a4ebe6..0166e9c 100644
--- a/tests/lib_2/html/js_util_test.dart
+++ b/tests/lib_2/html/js_util_test.dart
@@ -12,7 +12,7 @@
 
 import 'package:js/js.dart';
 import 'package:js/js_util.dart' as js_util;
-import 'package:unittest/unittest.dart';
+import 'package:expect/minitest.dart';
 import 'package:async_helper/async_helper.dart';
 
 _injectJs() {
@@ -360,24 +360,28 @@
     });
   });
 
-  group('promiseToFuture', () {
-    test('resolved promise', () async {
-      final String result = await js_util.promiseToFuture(resolvedPromise);
-      expect(result, equals('resolved'));
-    });
+  void testResolvedPromise() 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'));
-      }
-    });
+  void testRejectedPromise() 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'));
-    });
+  void testReturnRejectedPromise() async {
+    final String result = await promiseToFuture(getResolvedPromise());
+    expect(result, equals('resolved'));
+  }
+
+  asyncTest(() async {
+    await testResolvedPromise();
+    await testRejectedPromise();
+    await testReturnRejectedPromise();
   });
 }
diff --git a/tests/lib_2/html/notification_permission_test.dart b/tests/lib_2/html/notification_permission_test.dart
index 97c4803..0edd8ee 100644
--- a/tests/lib_2/html/notification_permission_test.dart
+++ b/tests/lib_2/html/notification_permission_test.dart
@@ -2,13 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
 import 'dart:html';
 
-import 'package:unittest/unittest.dart';
-import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
 
-main() async {
+main() {
   test('Notification.requestPermission', () async {
     String permission = await Notification.requestPermission();
     expect(permission, isNotNull);
diff --git a/tests/lib_2/html/worker_functional_test.dart b/tests/lib_2/html/worker_functional_test.dart
index 497f808..cf3d5ab 100644
--- a/tests/lib_2/html/worker_functional_test.dart
+++ b/tests/lib_2/html/worker_functional_test.dart
@@ -4,7 +4,7 @@
 
 library worker_test;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:html';
 
 main() {
diff --git a/tests/lib_2/html/worker_supported_test.dart b/tests/lib_2/html/worker_supported_test.dart
index 2196c02..fecb78e 100644
--- a/tests/lib_2/html/worker_supported_test.dart
+++ b/tests/lib_2/html/worker_supported_test.dart
@@ -4,7 +4,7 @@
 
 library worker_test;
 
-import 'package:unittest/unittest.dart';
+import 'package:expect/minitest.dart';
 import 'dart:html';
 
 main() {
diff --git a/tests/lib_2/html/xhr_cross_origin_test.dart b/tests/lib_2/html/xhr_cross_origin_test.dart
index 997f01a..bb2a75f 100644
--- a/tests/lib_2/html/xhr_cross_origin_test.dart
+++ b/tests/lib_2/html/xhr_cross_origin_test.dart
@@ -4,7 +4,8 @@
 
 library XHRCrossOriginTest;
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_helper.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'dart:html';
 import "dart:convert";
 
@@ -24,84 +25,81 @@
       nextArg == -1 ? searchUrl.length : nextArg));
 }
 
+var port = crossOriginPort;
+var host = '${window.location.protocol}//${window.location.hostname}:$port';
+
+Future testGetCrossDomain() async {
+  var gotError = false;
+  var url = '$host/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt';
+  try {
+    var xhr = await HttpRequest.request(url);
+    var data = json.decode(xhr.response);
+    expect(data.containsKey('feed'), isTrue);
+    expect(data['feed'].containsKey('entry'), isTrue);
+    expect(data, isMap);
+  } catch (e) {
+    // Consume errors when not supporting cross origin.
+    gotError = true;
+  }
+  // Expect that we got an error when cross origin is not supported.
+  expect(gotError, !HttpRequest.supportsCrossOrigin);
+}
+
+Future testRequestCrossOrigin() async {
+  var url = '$host/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt';
+  var response = await HttpRequest.requestCrossOrigin(url);
+  expect(response.contains('feed'), isTrue);
+}
+
+Future testRequestCrossOriginErrors() async {
+  try {
+    var response = await HttpRequest.requestCrossOrigin('does_not_exist');
+    fail('404s should fail request.');
+  } catch (_) {
+    // Expected failure.
+  }
+}
+
+void testCrossDomain() {
+  var url = '$host/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt';
+  var xhr = new HttpRequest();
+  xhr.open('GET', url, async: true);
+  var validate = expectAsync((data) {
+    expect(data.containsKey('feed'), isTrue);
+    expect(data['feed'].containsKey('entry'), isTrue);
+    expect(data, isMap);
+  });
+  xhr.onReadyStateChange.listen((e) {
+    if (xhr.readyState == HttpRequest.DONE) {
+      validate(json.decode(xhr.response));
+    }
+  });
+  xhr.send();
+}
+
+Future testGetWithCredentialsCrossDomain() async {
+  var url = '$host/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt';
+  var xhr = await HttpRequest.request(url, withCredentials: true);
+  var data = json.decode(xhr.response);
+  expect(data.containsKey('feed'), isTrue);
+  expect(data['feed'].containsKey('entry'), isTrue);
+  expect(data, isMap);
+}
+
 main() {
-  group('supported', () {
-    test('supported', () {
-      expect(HttpRequest.supportsCrossOrigin, isTrue);
-    });
+  test('supported', () {
+    expect(HttpRequest.supportsCrossOrigin, isTrue);
   });
 
-  group('functional', () {
-    var port = crossOriginPort;
-    var host = '${window.location.protocol}//${window.location.hostname}:$port';
-
-    test('XHR.get Cross-domain', () {
-      var gotError = false;
-      var url = '$host/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt';
-      return HttpRequest.request(url).then((xhr) {
-        var data = json.decode(xhr.response);
-        expect(data, contains('feed'));
-        expect(data['feed'], contains('entry'));
-        expect(data, isMap);
-      }).catchError((error) {}, test: (error) {
-        gotError = true;
-        // Consume errors when not supporting cross origin.
-        return !HttpRequest.supportsCrossOrigin;
-      }).whenComplete(() {
-        // Expect that we got an error when cross origin is not supported.
-        expect(gotError, !HttpRequest.supportsCrossOrigin);
-      });
-    });
-
-    test('XHR.requestCrossOrigin', () {
-      var url = '$host/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt';
-      return HttpRequest.requestCrossOrigin(url).then((response) {
-        expect(response, contains('feed'));
-      });
-    });
-
-    test('XHR.requestCrossOrigin errors', () {
-      var gotError = false;
-      return HttpRequest.requestCrossOrigin('does_not_exist').then((response) {
-        expect(true, isFalse, reason: '404s should fail request.');
-      }).catchError((error) {}, test: (error) {
-        gotError = true;
-        return true;
-      }).whenComplete(() {
-        expect(gotError, isTrue);
-      });
-    });
-
+  asyncTest(() async {
+    await testGetCrossDomain();
+    await testRequestCrossOrigin();
+    await testRequestCrossOriginErrors();
     // Skip the rest if not supported.
     if (!HttpRequest.supportsCrossOrigin) {
       return;
     }
-
-    test('XHR Cross-domain', () {
-      var url = '$host/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt';
-      var xhr = new HttpRequest();
-      xhr.open('GET', url, async: true);
-      var validate = expectAsync((data) {
-        expect(data, contains('feed'));
-        expect(data['feed'], contains('entry'));
-        expect(data, isMap);
-      });
-      xhr.onReadyStateChange.listen((e) {
-        if (xhr.readyState == HttpRequest.DONE) {
-          validate(json.decode(xhr.response));
-        }
-      });
-      xhr.send();
-    });
-
-    test('XHR.getWithCredentials Cross-domain', () {
-      var url = '$host/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt';
-      return HttpRequest.request(url, withCredentials: true).then((xhr) {
-        var data = json.decode(xhr.response);
-        expect(data, contains('feed'));
-        expect(data['feed'], contains('entry'));
-        expect(data, isMap);
-      });
-    });
+    testCrossDomain();
+    await testGetWithCredentialsCrossDomain();
   });
 }
diff --git a/tests/lib_2/html/xhr_test.dart b/tests/lib_2/html/xhr_test.dart
index f199186..e2a7377 100644
--- a/tests/lib_2/html/xhr_test.dart
+++ b/tests/lib_2/html/xhr_test.dart
@@ -9,254 +9,257 @@
 import 'dart:html';
 import 'dart:typed_data';
 
-import 'package:unittest/unittest.dart';
+import 'package:async_helper/async_minitest.dart';
 import 'package:async_helper/async_helper.dart';
 
-main() async {
-  // Cache blocker is a workaround for:
-  // https://code.google.com/p/dart/issues/detail?id=11834
-  var cacheBlocker = new DateTime.now().millisecondsSinceEpoch;
-  var url = '/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt?'
-      'cacheBlock=$cacheBlocker';
+// Cache blocker is a workaround for:
+// https://code.google.com/p/dart/issues/detail?id=11834
+var cacheBlocker = new DateTime.now().millisecondsSinceEpoch;
+var url = '/root_dart/tests/lib_2/html/xhr_cross_origin_data.txt?'
+    'cacheBlock=$cacheBlocker';
 
-  void validate200Response(xhr) {
-    expect(xhr.status, equals(200));
-    var data = json.decode(xhr.responseText);
-    expect(data, contains('feed'));
-    expect(data['feed'], contains('entry'));
-    expect(data, isMap);
-  }
+void validate200Response(xhr) {
+  expect(xhr.status, 200);
+  var data = json.decode(xhr.responseText);
+  expect(data.containsKey('feed'), isTrue);
+  expect(data['feed'].containsKey('entry'), isTrue);
+  expect(data, isMap);
+}
 
-  void validate404(xhr) {
-    expect(xhr.status, equals(404));
-    // We cannot say much about xhr.responseText, most HTTP servers will
-    // include an HTML page explaining the error to a human.
-    String responseText = xhr.responseText;
-    expect(responseText, isNotNull);
-  }
+void validate404(xhr) {
+  expect(xhr.status, 404);
+  // We cannot say much about xhr.responseText, most HTTP servers will
+  // include an HTML page explaining the error to a human.
+  String responseText = xhr.responseText;
+  expect(responseText, isNotNull);
+}
 
-  group('supported_onProgress', () {
-    test('supported', () {
-      expect(HttpRequest.supportsProgressEvent, isTrue);
-    });
-  });
-
-  group('supported_onLoadEnd', () {
-    test('supported', () {
-      expect(HttpRequest.supportsLoadEndEvent, isTrue);
-    });
-  });
-
-  group('supported_overrideMimeType', () {
-    test('supported', () {
-      expect(HttpRequest.supportsOverrideMimeType, isTrue);
-    });
-  });
-
-  group('xhr', () {
-    test('XHR No file', () {
-      HttpRequest xhr = new HttpRequest();
-      xhr.open("GET", "NonExistingFile", async: true);
-      xhr.onReadyStateChange.listen(expectAsyncUntil((event) {
-        if (xhr.readyState == HttpRequest.DONE) {
-          validate404(xhr);
-        }
-      }, () => xhr.readyState == HttpRequest.DONE));
-      xhr.send();
-    });
-
-    test('XHR_file', () {
-      var loadEndCalled = false;
-
-      var xhr = new HttpRequest();
-      xhr.open('GET', url, async: true);
-      xhr.onReadyStateChange.listen(expectAsyncUntil((e) {
-        if (xhr.readyState == HttpRequest.DONE) {
-          validate200Response(xhr);
-
-          Timer.run(expectAsync(() {
-            expect(loadEndCalled, HttpRequest.supportsLoadEndEvent);
-          }));
-        }
-      }, () => xhr.readyState == HttpRequest.DONE));
-
-      xhr.onLoadEnd.listen((ProgressEvent e) {
-        loadEndCalled = true;
-      });
-      xhr.send();
-    });
-
-    test('XHR.request No file', () {
-      HttpRequest.request('NonExistingFile').then((_) {
-        fail('Request should not have succeeded.');
-      }).catchError((error) {
-        HttpRequest xhr = error.target;
-        expect(xhr.readyState, equals(HttpRequest.DONE));
-        validate404(xhr);
-      });
-    });
-
-    test('XHR.request file', () {
-      HttpRequest.request(url).then(expectAsync((xhr) {
-        expect(xhr.readyState, equals(HttpRequest.DONE));
-        validate200Response(xhr);
-      }));
-    });
-
-    test('XHR.request onProgress', () {
-      var progressCalled = false;
-      HttpRequest.request(url, onProgress: (_) {
-        progressCalled = true;
-      }).then(expectAsync((xhr) {
-        expect(xhr.readyState, equals(HttpRequest.DONE));
-        expect(progressCalled, HttpRequest.supportsProgressEvent);
-        validate200Response(xhr);
-      }));
-    });
-
-    test('XHR.request withCredentials No file', () {
-      HttpRequest.request('NonExistingFile', withCredentials: true).then((_) {
-        fail('Request should not have succeeded.');
-      }).catchError((error) {
-        HttpRequest xhr = error.target;
-        expect(xhr.readyState, equals(HttpRequest.DONE));
-        validate404(xhr);
-      });
-    });
-
-    test('XHR.request withCredentials file', () async {
-      try {
-        HttpRequest xhr = await HttpRequest.request(url, withCredentials: true);
-        expect(xhr.readyState, equals(HttpRequest.DONE));
-        validate200Response(xhr);
-      } catch (error) {
-        fail('Request should succeed.');
-      }
-    });
-
-    test('XHR.getString file', () {
-      HttpRequest.getString(url).then(expectAsync((str) {}));
-    });
-
-    test('XHR.getString No file', () async {
-      try {
-        await HttpRequest.getString('NonExistingFile');
-        fail('Succeeded for non-existing file.');
-      } catch (error) {
-        HttpRequest xhr = error.target;
-        expect(xhr.readyState, equals(HttpRequest.DONE));
-        validate404(xhr);
-      }
-    });
-
-    test('XHR.request responseType arraybuffer', () {
-      if (Platform.supportsTypedData) {
-        HttpRequest.request(url, responseType: 'arraybuffer', requestHeaders: {
-          'Content-Type': 'text/xml'
-        }).then(expectAsync((xhr) {
-          expect(xhr.status, equals(200));
-          var byteBuffer = xhr.response;
-          expect(byteBuffer, new isInstanceOf<ByteBuffer>());
-          expect(byteBuffer, isNotNull);
-        }));
-      }
-    });
-
-    test('overrideMimeType', () {
-      var expectation =
-          HttpRequest.supportsOverrideMimeType ? returnsNormally : throws;
-
-      expect(() {
-        HttpRequest.request(url, mimeType: 'application/binary');
-      }, expectation);
-    });
-
-    if (Platform.supportsTypedData) {
-      test('xhr upload', () {
-        var xhr = new HttpRequest();
-        var progressCalled = false;
-        xhr.upload.onProgress.listen((e) {
-          progressCalled = true;
-        });
-
-        xhr.open('POST',
-            '${window.location.protocol}//${window.location.host}/echo');
-
-        // 10MB of payload data w/ a bit of data to make sure it
-        // doesn't get compressed to nil.
-        var data = new Uint8List(1 * 1024 * 1024);
-        for (var i = 0; i < data.length; ++i) {
-          data[i] = i & 0xFF;
-        }
-        xhr.send(new Uint8List.view(data.buffer));
-
-        return xhr.onLoad.first.then((_) {
-          expect(progressCalled, isTrue, reason: 'onProgress should be fired');
-        });
-      });
+Future testXhrNoFile() async {
+  HttpRequest xhr = new HttpRequest();
+  xhr.open("GET", "NonExistingFile", async: true);
+  var completer = new Completer<void>();
+  xhr.onReadyStateChange.listen((event) {
+    if (!completer.isCompleted && xhr.readyState == HttpRequest.DONE) {
+      completer.complete();
+      validate404(xhr);
     }
-
-    test('xhr postFormData', () {
-      var data = {'name': 'John', 'time': '2 pm'};
-
-      var parts = [];
-      for (var key in data.keys) {
-        parts.add('${Uri.encodeQueryComponent(key)}='
-            '${Uri.encodeQueryComponent(data[key])}');
-      }
-      var encodedData = parts.join('&');
-
-      return HttpRequest
-          .postFormData(
-              '${window.location.protocol}//${window.location.host}/echo', data)
-          .then((xhr) {
-        expect(xhr.responseText, encodedData);
-      });
-    });
   });
+  xhr.send();
+  await completer;
+}
 
-  group('xhr_requestBlob', () {
-    test('XHR.request responseType blob', () {
-      if (Platform.supportsTypedData) {
-        return HttpRequest.request(url, responseType: 'blob').then((xhr) {
-          expect(xhr.status, equals(200));
-          var blob = xhr.response;
-          expect(blob is Blob, isTrue);
-          expect(blob, isNotNull);
-        });
-      }
-    });
-  });
+Future testXhrFile() async {
+  var loadEndCalled = false;
 
-  group('json', () {
-    test('xhr responseType json', () {
-      var url = '${window.location.protocol}//${window.location.host}/echo';
-      var data = {
-        'key': 'value',
-        'a': 'b',
-        'one': 2,
-      };
+  var xhr = new HttpRequest();
+  xhr.open('GET', url, async: true);
+  var completer = new Completer<void>();
+  xhr.onReadyStateChange.listen((e) {
+    if (!completer.isCompleted && xhr.readyState == HttpRequest.DONE) {
+      completer.complete();
+      validate200Response(xhr);
 
-      HttpRequest
-          .request(url,
-              method: 'POST', sendData: json.encode(data), responseType: 'json')
-          .then(expectAsync((xhr) {
-        expect(xhr.status, equals(200));
-        var json = xhr.response;
-        expect(json, equals(data));
+      Timer.run(expectAsync(() {
+        expect(loadEndCalled, HttpRequest.supportsLoadEndEvent);
       }));
-    });
+    }
   });
 
-  group('headers', () {
-    test('xhr responseHeaders', () {
-      return HttpRequest.request(url).then((xhr) {
-        var contentTypeHeader = xhr.responseHeaders['content-type'];
-        expect(contentTypeHeader, isNotNull);
-        // Should be like: 'text/plain; charset=utf-8'
-        expect(contentTypeHeader.contains('text/plain'), isTrue);
-        expect(contentTypeHeader.contains('charset=utf-8'), isTrue);
-      });
+  xhr.onLoadEnd.listen((ProgressEvent e) {
+    loadEndCalled = true;
+  });
+  xhr.send();
+  await completer;
+}
+
+Future testRequestNoFile() async {
+  try {
+    await HttpRequest.request('NonExistingFile');
+    fail('Request should not have succeeded.');
+  } catch (error) {
+    HttpRequest xhr = error.target;
+    expect(xhr.readyState, HttpRequest.DONE);
+    validate404(xhr);
+  }
+}
+
+Future testRequestFile() async {
+  var xhr = await HttpRequest.request(url);
+  expect(xhr.readyState, HttpRequest.DONE);
+  validate200Response(xhr);
+}
+
+Future testRequestOnProgress() async {
+  var progressCalled = false;
+  var xhr = await HttpRequest.request(url, onProgress: (_) {
+    progressCalled = true;
+  });
+  expect(xhr.readyState, HttpRequest.DONE);
+  expect(progressCalled, HttpRequest.supportsProgressEvent);
+  validate200Response(xhr);
+}
+
+Future testRequestWithCredentialsNoFile() async {
+  try {
+    await HttpRequest.request('NonExistingFile', withCredentials: true);
+    fail('Request should not have succeeded.');
+  } catch (error) {
+    HttpRequest xhr = error.target;
+    expect(xhr.readyState, HttpRequest.DONE);
+    validate404(xhr);
+  }
+}
+
+Future testRequestWithCredentialsFile() async {
+  try {
+    HttpRequest xhr = await HttpRequest.request(url, withCredentials: true);
+    expect(xhr.readyState, HttpRequest.DONE);
+    validate200Response(xhr);
+  } catch (_) {
+    fail('Request should succeed.');
+  }
+}
+
+Future testGetStringFile() => HttpRequest.getString(url);
+
+Future testGetStringNoFile() async {
+  try {
+    await HttpRequest.getString('NonExistingFile');
+    fail('Succeeded for non-existing file.');
+  } catch (error) {
+    HttpRequest xhr = error.target;
+    expect(xhr.readyState, HttpRequest.DONE);
+    validate404(xhr);
+  }
+}
+
+Future testRequestResponseTypeArrayBuffer() async {
+  if (Platform.supportsTypedData) {
+    var xhr = await HttpRequest.request(url,
+        responseType: 'arraybuffer',
+        requestHeaders: {'Content-Type': 'text/xml'});
+    expect(xhr.status, 200);
+    var byteBuffer = xhr.response;
+    expect(byteBuffer, isInstanceOf<ByteBuffer>());
+    expect(byteBuffer, isNotNull);
+  }
+}
+
+Future testOverrideMimeType() async {
+  bool gotError = false;
+  try {
+    await HttpRequest.request(url, mimeType: 'application/binary');
+  } catch (_) {
+    gotError = true;
+  }
+  expect(gotError, !HttpRequest.supportsOverrideMimeType);
+}
+
+Future testXhrUpload() async {
+  if (Platform.supportsTypedData) {
+    var xhr = new HttpRequest();
+    var progressCalled = false;
+    xhr.upload.onProgress.listen((e) {
+      progressCalled = true;
     });
+
+    xhr.open(
+        'POST', '${window.location.protocol}//${window.location.host}/echo');
+
+    // 10MB of payload data w/ a bit of data to make sure it
+    // doesn't get compressed to nil.
+    var data = new Uint8List(1 * 1024 * 1024);
+    for (var i = 0; i < data.length; ++i) {
+      data[i] = i & 0xFF;
+    }
+    xhr.send(new Uint8List.view(data.buffer));
+
+    await xhr.onLoad.first;
+    expect(progressCalled, isTrue, reason: 'onProgress should be fired');
+  }
+}
+
+Future testXhrPostFormData() async {
+  var data = {'name': 'John', 'time': '2 pm'};
+
+  var parts = [];
+  for (var key in data.keys) {
+    parts.add('${Uri.encodeQueryComponent(key)}='
+        '${Uri.encodeQueryComponent(data[key])}');
+  }
+  var encodedData = parts.join('&');
+
+  var xhr = await HttpRequest.postFormData(
+      '${window.location.protocol}//${window.location.host}/echo', data);
+  expect(xhr.responseText, encodedData);
+}
+
+Future testRequestResponseTypeBlob() async {
+  if (Platform.supportsTypedData) {
+    var xhr = await HttpRequest.request(url, responseType: 'blob');
+    expect(xhr.status, 200);
+    var blob = xhr.response;
+    expect(blob is Blob, isTrue);
+    expect(blob, isNotNull);
+  }
+}
+
+Future testResponseTypeJson() async {
+  var url = '${window.location.protocol}//${window.location.host}/echo';
+  var data = {
+    'key': 'value',
+    'a': 'b',
+    'one': 2,
+  };
+
+  var xhr = await HttpRequest.request(url,
+      method: 'POST', sendData: json.encode(data), responseType: 'json');
+  expect(xhr.status, 200);
+  var jsonResponse = xhr.response;
+  expect(jsonResponse, data);
+}
+
+Future testResponseHeaders() async {
+  var xhr = await HttpRequest.request(url);
+  var contentTypeHeader = xhr.responseHeaders['content-type'];
+  expect(contentTypeHeader, isNotNull);
+  // Should be like: 'text/plain; charset=utf-8'
+  expect(contentTypeHeader.contains('text/plain'), isTrue);
+  expect(contentTypeHeader.contains('charset=utf-8'), isTrue);
+}
+
+main() {
+  test('supportsProgressEvent', () {
+    expect(HttpRequest.supportsProgressEvent, isTrue);
+  });
+
+  test('supportsOnLoadEnd', () {
+    expect(HttpRequest.supportsLoadEndEvent, isTrue);
+  });
+
+  test('supportsOverrideMimeType', () {
+    expect(HttpRequest.supportsOverrideMimeType, isTrue);
+  });
+
+  asyncTest(() async {
+    await testXhrNoFile();
+    await testXhrFile();
+    await testRequestNoFile();
+    await testRequestFile();
+    await testRequestOnProgress();
+    await testRequestWithCredentialsNoFile();
+    await testRequestWithCredentialsFile();
+    await testGetStringFile();
+    await testGetStringNoFile();
+    await testRequestResponseTypeArrayBuffer();
+    await testOverrideMimeType();
+    await testXhrUpload();
+    await testXhrPostFormData();
+
+    await testRequestResponseTypeBlob();
+
+    await testResponseTypeJson();
+
+    await testResponseHeaders();
   });
 }
diff --git a/tests/lib_2/isolate/int_from_environment_default_value_test.dart b/tests/lib_2/isolate/int_from_environment_default_value_test.dart
index 852d646..af7ccac 100644
--- a/tests/lib_2/isolate/int_from_environment_default_value_test.dart
+++ b/tests/lib_2/isolate/int_from_environment_default_value_test.dart
@@ -11,7 +11,7 @@
 import "package:expect/expect.dart";
 
 void test(port) {
-  Expect.isNull(const int.fromEnvironment('NOT_FOUND'));
+  Expect.equals(0, const int.fromEnvironment('NOT_FOUND'));
   Expect.equals(
       12345, const int.fromEnvironment('NOT_FOUND', defaultValue: 12345));
   if (port != null) port.send(null);
diff --git a/tests/lib_2/isolate/string_from_environment_default_value_test.dart b/tests/lib_2/isolate/string_from_environment_default_value_test.dart
index d26e759..78b2feb 100644
--- a/tests/lib_2/isolate/string_from_environment_default_value_test.dart
+++ b/tests/lib_2/isolate/string_from_environment_default_value_test.dart
@@ -10,7 +10,7 @@
 import "package:expect/expect.dart";
 
 void test(port) {
-  Expect.isNull(const String.fromEnvironment('NOT_FOUND'));
+  Expect.equals('', const String.fromEnvironment('NOT_FOUND'));
   Expect.equals(
       'x', const String.fromEnvironment('NOT_FOUND', defaultValue: 'x'));
   if (port != null) port.send(null);
diff --git a/tests/lib_2/mirrors/invoke_closurization2_test.dart b/tests/lib_2/mirrors/invoke_closurization2_test.dart
index 2e18330..28c6f7a 100644
--- a/tests/lib_2/mirrors/invoke_closurization2_test.dart
+++ b/tests/lib_2/mirrors/invoke_closurization2_test.dart
@@ -83,11 +83,14 @@
 
   // Now the same thing through mirrors and mirror-invocation.
   f = getAMirror().getField(#codeUnitAt);
-  Expect.equals("codeUnitAt-42", f.invoke(#call, [42], {}).reflectee);
+  Expect.equals(
+      "codeUnitAt-42", f.invoke(#call, [42], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#toUpperCase);
-  Expect.equals("toUpperCase", f.invoke(#call, [], {}).reflectee);
+  Expect.equals(
+      "toUpperCase", f.invoke(#call, [], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#indexOf);
-  Expect.equals("indexOf-499", f.invoke(#call, [499], {}).reflectee);
+  Expect.equals(
+      "indexOf-499", f.invoke(#call, [499], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#lastIndexOf);
   Expect.equals(
       "lastIndexOf-FOO,BAR", f.invoke(#call, ["FOO", "BAR"]).reflectee);
@@ -114,11 +117,14 @@
   Expect.equals("toSet-true", f(named: true));
 
   f = getAMirror().getField(#endsWith);
-  Expect.equals("endsWith-42", f.invoke(#call, [42], {}).reflectee);
+  Expect.equals(
+      "endsWith-42", f.invoke(#call, [42], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#toLowerCase);
-  Expect.equals("toLowerCase", f.invoke(#call, [], {}).reflectee);
+  Expect.equals(
+      "toLowerCase", f.invoke(#call, [], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#indexOf);
-  Expect.equals("indexOf-499", f.invoke(#call, [499], {}).reflectee);
+  Expect.equals(
+      "indexOf-499", f.invoke(#call, [499], <Symbol, dynamic>{}).reflectee);
   f = getAMirror().getField(#matchAsPrefix);
   Expect.equals(
       "matchAsPrefix-FOO,BAR", f.invoke(#call, ["FOO", "BAR"]).reflectee);
diff --git a/tools/VERSION b/tools/VERSION
index e997a23..4acf823 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 8
 PATCH 0
-PRERELEASE 15
+PRERELEASE 16
 PRERELEASE_PATCH 0
 ABI_VERSION 29
 OLDEST_SUPPORTED_ABI_VERSION 29
diff --git a/tools/bots/bot_utils.py b/tools/bots/bot_utils.py
index f3543ce..7e3c496 100755
--- a/tools/bots/bot_utils.py
+++ b/tools/bots/bot_utils.py
@@ -43,12 +43,13 @@
 
 
 class Channel(object):
+    BETA = 'beta'
     BLEEDING_EDGE = 'be'
     DEV = 'dev'
     STABLE = 'stable'
     TRY = 'try'
     INTEGRATION = 'integration'
-    ALL_CHANNELS = [BLEEDING_EDGE, DEV, STABLE, TRY, INTEGRATION]
+    ALL_CHANNELS = [BETA, BLEEDING_EDGE, DEV, STABLE, TRY, INTEGRATION]
 
 
 class ReleaseType(object):
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index d05d9c5..d692342 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -1253,7 +1253,7 @@
     return Element._offsetToHelper(this, parent);
   }
 
-  static Point _offsetToHelper(Element current, Element parent) {
+  static Point _offsetToHelper(Element$NULLABLE current, Element parent) {
     // We're hopping from _offsetParent_ to offsetParent (not just parent), so
     // offsetParent, "tops out" at BODY. But people could conceivably pass in
     // the document.documentElement and I want it to return an absolute offset,
@@ -1265,7 +1265,7 @@
       throw new ArgumentError("Specified element is not a transitive offset "
           "parent of this element.");
     }
-    Element parentOffset = current.offsetParent;
+    Element$NULLABLE parentOffset = current.offsetParent;
     Point p = Element._offsetToHelper(parentOffset, parent);
     return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
   }
@@ -1497,7 +1497,7 @@
     return result;
   }
 
-  Element get offsetParent native;
+  Element$NULLABLE get offsetParent native;
 
   int get offsetHeight => JS<num>('num', '#.offsetHeight', this).round();
 
diff --git a/tools/promote.py b/tools/promote.py
index c9b820b..dea4dd2 100644
--- a/tools/promote.py
+++ b/tools/promote.py
@@ -72,7 +72,7 @@
 
         # Make sure options.channel is a valid
         if not options.channel:
-            die('Specify --channel=be/dev/stable')
+            die('Specify --channel=beta/dev/stable')
         if options.channel not in bot_utils.Channel.ALL_CHANNELS:
             die('You must supply a valid channel to --channel to promote')
     else:
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index e8884dd..6925150 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -362,10 +362,7 @@
 
   # TODO(38701): Cleanup after merging the forked SDK into mainline.
   if (use_nnbd) {
-    args += [
-      "--enable-experiment=non-nullable",
-      "--force-nnbd-checks",
-    ]
+    args += [ "--enable-experiment=non-nullable" ]
   }
 }