Version 2.13.0-169.0.dev

Merge commit 'a7b0f5108d2938f03eda39bdd72e05135f07d76f' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 9f0bf0b..8a5f7e9 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2021-03-24T12:15:31.538873",
+  "generated": "2021-03-24T13:42:28.071470",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -638,12 +638,6 @@
       "languageVersion": "2.12"
     },
     {
-      "name": "stagehand",
-      "rootUri": "../third_party/pkg/stagehand",
-      "packageUri": "lib/",
-      "languageVersion": "2.10"
-    },
-    {
       "name": "status_file",
       "rootUri": "../pkg/status_file",
       "packageUri": "lib/",
diff --git a/.packages b/.packages
index 5fc05a8..7646deb 100644
--- a/.packages
+++ b/.packages
@@ -95,7 +95,6 @@
 source_span:third_party/pkg/source_span/lib
 sse:third_party/pkg/sse/lib
 stack_trace:third_party/pkg/stack_trace/lib
-stagehand:third_party/pkg/stagehand/lib
 status_file:pkg/status_file/lib
 stream_channel:third_party/pkg/stream_channel/lib
 string_scanner:third_party/pkg/string_scanner/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 143873c..f9bed69 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -40,6 +40,18 @@
 - new lint: `use_named_constants`.
 - deprecation of `avoid_as`.
 
+### Other libraries
+
+#### `package:js`
+
+*   **Breaking change:** It is no longer valid to use `String`s that match
+    an `@Native` annotation in an `@JS()` annotation for a non-anonymous JS
+    interop class. This led to erroneous behavior due to the way interceptors
+    work. If you need to work with a native class, prefer `dart:html`, an
+    `@anonymous` class, or `js_util`. See issue [#44211][] for more details.
+
+[#44211]: https://github.com/dart-lang/sdk/issues/44211
+
 ## 2.12.2 - 2021-03-17
 
 This is a patch release that fixes crashes reported by Flutter 2 users (issue
diff --git a/DEPS b/DEPS
index 2948ee6..4ecf65b 100644
--- a/DEPS
+++ b/DEPS
@@ -152,7 +152,6 @@
   "source_span_rev": "1be3c44045a06dff840d2ed3a13e6082d7a03a23",
   "sse_tag": "5da8fedcdc56f306933d202e2d204753eecefd36",
   "stack_trace_tag": "6788afc61875079b71b3d1c3e65aeaa6a25cbc2f",
-  "stagehand_rev": "e64ac90cac508981011299c4ceb819149e71f1bd",
   "stream_channel_tag": "d7251e61253ec389ee6e045ee1042311bced8f1d",
   "string_scanner_rev": "1b63e6e5db5933d7be0a45da6e1129fe00262734",
   "sync_http_rev": "b59c134f2e34d12acac110d4f17f83e5a7db4330",
@@ -430,8 +429,6 @@
       Var("dart_git") + "sse.git" + "@" + Var("sse_tag"),
   Var("dart_root") + "/third_party/pkg/stack_trace":
       Var("dart_git") + "stack_trace.git" + "@" + Var("stack_trace_tag"),
-  Var("dart_root") + "/third_party/pkg/stagehand":
-      Var("dart_git") + "stagehand.git" + "@" + Var("stagehand_rev"),
   Var("dart_root") + "/third_party/pkg/stream_channel":
       Var("dart_git") + "stream_channel.git" +
       "@" + Var("stream_channel_tag"),
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index 0efadbc..6668855 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -5,8 +5,8 @@
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
 import 'package:test/test.dart';
 
+import '../mini_ast.dart';
 import '../mini_types.dart';
-import 'flow_analysis_mini_ast.dart';
 
 main() {
   group('API', () {
@@ -42,8 +42,8 @@
     test('assert_end joins previous and ifTrue states', () {
       var h = Harness();
       var x = Var('x', 'int?');
-      var y = Var('x', 'int?');
-      var z = Var('x', 'int?');
+      var y = Var('y', 'int?');
+      var z = Var('z', 'int?');
       h.run([
         x.read.as_('int').stmt,
         z.read.as_('int').stmt,
@@ -519,13 +519,13 @@
     });
 
     test('equalityOp_end does not set reachability for `this`', () {
-      var h = Harness()
+      var h = Harness(thisType: 'C')
         ..addSubtype('Null', 'C', false)
         ..addFactor('C', 'Null', 'C');
       h.addSubtype('C', 'Object', true);
       h.run([
-        if_(this_('C').is_('Null'), [
-          if_(this_('C').eq(nullLiteral), [
+        if_(this_.is_('Null'), [
+          if_(this_.eq(nullLiteral), [
             checkReachable(true),
           ], [
             checkReachable(true),
@@ -564,10 +564,10 @@
       });
 
       test('on explicit this', () {
-        var h = Harness();
+        var h = Harness(thisType: 'C');
         h.run([
-          if_(this_('C').propertyGet('f').is_('Null'), [
-            if_(this_('C').propertyGet('f').eq(nullLiteral), [
+          if_(this_.propertyGet('f').is_('Null'), [
+            if_(this_.propertyGet('f').eq(nullLiteral), [
               checkReachable(true),
             ], [
               checkReachable(true),
@@ -1464,11 +1464,11 @@
     });
 
     test('isExpression_end() does not set reachability for `this`', () {
-      var h = Harness()
+      var h = Harness(thisType: 'C')
         ..addSubtype('Never', 'C', true)
         ..addFactor('C', 'Never', 'C');
       h.run([
-        if_(this_('C').is_('Never'), [
+        if_(this_.is_('Never'), [
           checkReachable(true),
         ], [
           checkReachable(true),
@@ -1502,9 +1502,9 @@
       });
 
       test('on explicit this', () {
-        var h = Harness();
+        var h = Harness(thisType: 'C');
         h.run([
-          if_(this_('C').propertyGet('f').is_('Never'), [
+          if_(this_.propertyGet('f').is_('Never'), [
             checkReachable(true),
           ], [
             checkReachable(true),
@@ -2007,15 +2007,13 @@
         declare(x, initialized: true),
         declare(y, initialized: true),
         y.read.as_('int').stmt,
-        tryCatch([
+        try_([
           x.read.as_('int').stmt,
           checkPromoted(x, 'int'),
           checkPromoted(y, 'int'),
-        ], [
-          catch_(body: [
-            checkNotPromoted(x),
-            checkPromoted(y, 'int'),
-          ])
+        ]).catch_(body: [
+          checkNotPromoted(x),
+          checkPromoted(y, 'int'),
         ]),
       ]);
     });
@@ -2029,16 +2027,14 @@
         declare(x, initialized: true),
         x.read.as_('int').stmt,
         checkPromoted(x, 'int'),
-        tryCatch([
+        try_([
           x.write(expr('int?')).stmt,
           x.read.as_('int').stmt,
           checkPromoted(x, 'int'),
           getSsaNodes((nodes) => ssaAfterTry = nodes[x]!),
-        ], [
-          catch_(body: [
-            checkNotPromoted(x),
-            getSsaNodes((nodes) => expect(nodes[x], isNot(ssaAfterTry))),
-          ]),
+        ]).catch_(body: [
+          checkNotPromoted(x),
+          getSsaNodes((nodes) => expect(nodes[x], isNot(ssaAfterTry))),
         ]),
       ]);
     });
@@ -2053,16 +2049,14 @@
         declare(x, initialized: true),
         x.read.as_('int').stmt,
         checkPromoted(x, 'int'),
-        tryCatch([
+        try_([
           localFunction([
             x.write(expr('int?')).stmt,
           ]),
           return_(),
-        ], [
-          catch_(body: [
-            x.read.as_('int').stmt,
-            checkNotPromoted(x),
-          ])
+        ]).catch_(body: [
+          x.read.as_('int').stmt,
+          checkNotPromoted(x),
         ]),
       ]);
     });
@@ -2073,14 +2067,11 @@
       var x = Var('x', 'int?');
       h.run([
         declare(x, initialized: true),
-        tryCatch([], [
-          catch_(body: [
-            x.read.as_('int').stmt,
-            checkPromoted(x, 'int'),
-          ]),
-          catch_(body: [
-            checkNotPromoted(x),
-          ]),
+        try_([]).catch_(body: [
+          x.read.as_('int').stmt,
+          checkPromoted(x, 'int'),
+        ]).catch_(body: [
+          checkNotPromoted(x),
         ]),
       ]);
     });
@@ -2090,11 +2081,9 @@
       var e = Var('e', 'int');
       var st = Var('st', 'StackTrace');
       h.run([
-        tryCatch([], [
-          catch_(exception: e, stackTrace: st, body: [
-            checkAssigned(e, true),
-            checkAssigned(st, true),
-          ]),
+        try_([]).catch_(exception: e, stackTrace: st, body: [
+          checkAssigned(e, true),
+          checkAssigned(st, true),
         ]),
       ]);
     });
@@ -2108,14 +2097,12 @@
       h.run([
         declare(x, initialized: true), declare(y, initialized: true),
         declare(z, initialized: true),
-        tryCatch([
+        try_([
           x.read.as_('int').stmt,
           y.read.as_('int').stmt,
-        ], [
-          catch_(body: [
-            x.read.as_('int').stmt,
-            z.read.as_('int').stmt,
-          ]),
+        ]).catch_(body: [
+          x.read.as_('int').stmt,
+          z.read.as_('int').stmt,
         ]),
         // Only x should be promoted, because it's the only variable
         // promoted in both the try body and the catch handler.
@@ -2131,17 +2118,14 @@
       h.run([
         declare(x, initialized: true), declare(y, initialized: true),
         declare(z, initialized: true),
-        tryCatch([
+        try_([
           return_(),
-        ], [
-          catch_(body: [
-            x.read.as_('int').stmt,
-            y.read.as_('int').stmt,
-          ]),
-          catch_(body: [
-            x.read.as_('int').stmt,
-            z.read.as_('int').stmt,
-          ]),
+        ]).catch_(body: [
+          x.read.as_('int').stmt,
+          y.read.as_('int').stmt,
+        ]).catch_(body: [
+          x.read.as_('int').stmt,
+          z.read.as_('int').stmt,
         ]),
         // Only x should be promoted, because it's the only variable promoted
         // in both catch handlers.
@@ -2157,11 +2141,11 @@
         declare(x, initialized: true),
         declare(y, initialized: true),
         y.read.as_('int').stmt,
-        tryFinally([
+        try_([
           x.read.as_('int').stmt,
           checkPromoted(x, 'int'),
           checkPromoted(y, 'int'),
-        ], [
+        ]).finally_([
           checkNotPromoted(x),
           checkPromoted(y, 'int'),
         ]),
@@ -2179,13 +2163,13 @@
         declare(x, initialized: true),
         x.read.as_('int').stmt,
         checkPromoted(x, 'int'),
-        tryFinally([
+        try_([
           getSsaNodes((nodes) => ssaAtStartOfTry = nodes[x]!),
           x.write(expr('int?')).stmt,
           x.read.as_('int').stmt,
           checkPromoted(x, 'int'),
           getSsaNodes((nodes) => ssaAfterTry = nodes[x]!),
-        ], [
+        ]).finally_([
           checkNotPromoted(x),
           // The SSA node for X should be different from what it was at any time
           // during the try block, because there is no telling at what point an
@@ -2207,12 +2191,12 @@
       var x = Var('x', 'int?');
       h.run([
         declare(x, initialized: true),
-        tryFinally([
+        try_([
           localFunction([
             x.write(expr('int?')).stmt,
           ]),
           return_(),
-        ], [
+        ]).finally_([
           x.read.as_('int').stmt,
           checkNotPromoted(x),
         ]),
@@ -2225,10 +2209,10 @@
       var y = Var('y', 'int?');
       h.run([
         declare(x, initialized: true), declare(y, initialized: true),
-        tryFinally([
+        try_([
           x.read.as_('int').stmt,
           checkPromoted(x, 'int'),
-        ], [
+        ]).finally_([
           checkNotPromoted(x),
           y.read.as_('int').stmt,
           checkPromoted(y, 'int'),
@@ -2248,10 +2232,10 @@
       late SsaNode<Var, Type> ySsaAtEndOfFinally;
       h.run([
         declare(x, initialized: true), declare(y, initialized: true),
-        tryFinally([
+        try_([
           x.read.as_('int').stmt,
           checkPromoted(x, 'int'),
-        ], [
+        ]).finally_([
           checkNotPromoted(x),
           x.write(expr('int?')).stmt,
           y.write(expr('int?')).stmt,
@@ -2289,14 +2273,14 @@
         late SsaNode<Var, Type> ySsaAtEndOfFinally;
         h.run([
           declare(x, initialized: true), declare(y, initialized: true),
-          tryFinally([
+          try_([
             x.write(expr('int?')).stmt,
             y.write(expr('int?')).stmt,
             getSsaNodes((nodes) {
               xSsaAtEndOfTry = nodes[x]!;
               ySsaAtEndOfTry = nodes[y]!;
             }),
-          ], [
+          ]).finally_([
             if_(expr('bool'), [
               x.write(expr('int?')).stmt,
             ]),
@@ -2329,10 +2313,10 @@
           'unreachable', () {
         var h = Harness();
         h.run([
-          tryFinally([
+          try_([
             return_(),
             checkReachable(false),
-          ], [
+          ]).finally_([
             checkReachable(true),
           ]),
           checkReachable(false),
@@ -2344,9 +2328,9 @@
           'unreachable', () {
         var h = Harness();
         h.run([
-          tryFinally([
+          try_([
             checkReachable(true),
-          ], [
+          ]).finally_([
             return_(),
             checkReachable(false),
           ]),
@@ -2360,9 +2344,9 @@
         var h = Harness();
         var x = Var('x', 'int?');
         h.run([
-          tryFinally([
+          try_([
             declare(x, initialized: true),
-          ], []),
+          ]).finally_([]),
         ]);
       });
 
@@ -2372,7 +2356,7 @@
         var h = Harness();
         var x = Var('x', 'int?');
         h.run([
-          tryFinally([], [
+          try_([]).finally_([
             declare(x, initialized: true),
           ]),
         ]);
@@ -2385,11 +2369,11 @@
         var x = Var('x', 'int?');
         h.run([
           declare(x, initialized: true),
-          tryFinally([
+          try_([
             localFunction([
               x.write(expr('int?')).stmt,
             ]),
-          ], []),
+          ]).finally_([]),
           if_(x.read.notEq(nullLiteral), [
             checkNotPromoted(x),
           ]),
@@ -2403,7 +2387,7 @@
         var x = Var('x', 'int?');
         h.run([
           declare(x, initialized: true),
-          tryFinally([], [
+          try_([]).finally_([
             localFunction([
               x.write(expr('int?')).stmt,
             ]),
@@ -2421,12 +2405,12 @@
         var x = Var('x', 'int?');
         h.run([
           declare(x, initialized: true),
-          tryFinally([
+          try_([
             if_(x.read.eq(nullLiteral), [
               return_(),
             ]),
             checkPromoted(x, 'int'),
-          ], [
+          ]).finally_([
             localFunction([
               x.write(expr('int?')).stmt,
             ]),
@@ -2447,12 +2431,12 @@
         var x = Var('x', 'Object');
         h.run([
           declare(x, initialized: true),
-          tryFinally([
+          try_([
             if_(x.read.is_('num', isInverted: true), [
               return_(),
             ]),
             checkPromoted(x, 'num'),
-          ], [
+          ]).finally_([
             if_(x.read.is_('int', isInverted: true), [
               return_(),
             ]),
@@ -2471,12 +2455,12 @@
         var x = Var('x', 'Object');
         h.run([
           declare(x, initialized: true),
-          tryFinally([
+          try_([
             if_(x.read.is_('String', isInverted: true), [
               return_(),
             ]),
             checkPromoted(x, 'String'),
-          ], [
+          ]).finally_([
             x.write(expr('Object')).stmt,
             if_(x.read.is_('int', isInverted: true), [
               return_(),
@@ -2493,10 +2477,10 @@
         var x = Var('x', 'Object');
         h.run([
           declare(x, initialized: true),
-          tryFinally([
+          try_([
             if_(x.read.is_('String', isInverted: true), []),
             checkNotPromoted(x),
-          ], [
+          ]).finally_([
             if_(x.read.is_('int', isInverted: true), []),
             checkNotPromoted(x),
           ]),
@@ -2519,12 +2503,12 @@
         h.run([
           declare(x, initialized: false),
           checkAssigned(x, false),
-          tryFinally([
+          try_([
             if_(expr('bool'), [
               x.write(expr('Object')).stmt,
             ]),
             checkAssigned(x, false),
-          ], [
+          ]).finally_([
             if_(expr('bool'), [
               x.write(expr('Object')).stmt,
             ]),
@@ -2542,10 +2526,10 @@
         h.run([
           declare(x, initialized: false),
           checkAssigned(x, false),
-          tryFinally([
+          try_([
             x.write(expr('Object')).stmt,
             checkAssigned(x, true),
-          ], [
+          ]).finally_([
             if_(expr('bool'), [
               x.write(expr('Object')).stmt,
             ]),
@@ -2563,12 +2547,12 @@
         h.run([
           declare(x, initialized: false),
           checkAssigned(x, false),
-          tryFinally([
+          try_([
             if_(expr('bool'), [
               x.write(expr('Object')).stmt,
             ]),
             checkAssigned(x, false),
-          ], [
+          ]).finally_([
             x.write(expr('Object')).stmt,
             checkAssigned(x, true),
           ]),
@@ -2584,9 +2568,9 @@
         h.run([
           declare(x, initialized: false),
           checkUnassigned(x, true),
-          tryFinally([
+          try_([
             checkUnassigned(x, true),
-          ], [
+          ]).finally_([
             checkUnassigned(x, true),
           ]),
           checkUnassigned(x, true),
@@ -2601,9 +2585,9 @@
         h.run([
           declare(x, initialized: false),
           checkUnassigned(x, true),
-          tryFinally([
+          try_([
             checkUnassigned(x, true),
-          ], [
+          ]).finally_([
             if_(expr('bool'), [
               x.write(expr('Object')).stmt,
             ]),
@@ -2621,12 +2605,12 @@
         h.run([
           declare(x, initialized: false),
           checkUnassigned(x, true),
-          tryFinally([
+          try_([
             if_(expr('bool'), [
               x.write(expr('Object')).stmt,
             ]),
             checkUnassigned(x, false),
-          ], [
+          ]).finally_([
             checkUnassigned(x, false),
           ]),
           checkUnassigned(x, false),
@@ -5622,12 +5606,12 @@
 
     group('because property', () {
       test('via explicit this', () {
-        var h = Harness();
+        var h = Harness(thisType: 'C');
         h.run([
-          if_(this_('C').propertyGet('field').eq(nullLiteral), [
+          if_(this_.propertyGet('field').eq(nullLiteral), [
             return_(),
           ]),
-          this_('C').propertyGet('field').whyNotPromoted((reasons) {
+          this_.propertyGet('field').whyNotPromoted((reasons) {
             expect(reasons.keys, unorderedEquals([Type('Object')]));
             var nonPromotionReason = reasons.values.single;
             expect(nonPromotionReason, TypeMatcher<PropertyNotPromoted>());
@@ -5668,14 +5652,14 @@
 
     group('because this', () {
       test('explicit', () {
-        var h = Harness()
+        var h = Harness(thisType: 'C')
           ..addSubtype('D', 'C', true)
           ..addFactor('C', 'D', 'C');
         h.run([
-          if_(this_('C').isNot('D'), [
+          if_(this_.isNot('D'), [
             return_(),
           ]),
-          this_('C').whyNotPromoted((reasons) {
+          this_.whyNotPromoted((reasons) {
             expect(reasons.keys, unorderedEquals([Type('D')]));
             var nonPromotionReason = reasons.values.single;
             expect(nonPromotionReason, TypeMatcher<ThisNotPromoted>());
@@ -5684,11 +5668,11 @@
       });
 
       test('implicit', () {
-        var h = Harness()
+        var h = Harness(thisType: 'C')
           ..addSubtype('D', 'C', true)
           ..addFactor('C', 'D', 'C');
         h.run([
-          if_(this_('C').isNot('D'), [
+          if_(this_.isNot('D'), [
             return_(),
           ]),
           implicitThis_whyNotPromoted('C', (reasons) {
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/argument_type_not_assignable_nullability_error.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/argument_type_not_assignable_nullability_error.dart
index 8f705df..e83ebea 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/argument_type_not_assignable_nullability_error.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/why_not_promoted/data/argument_type_not_assignable_nullability_error.dart
@@ -389,3 +389,15 @@
       null: null
   });
 }
+
+class C26 {
+  int? bad;
+}
+
+compoundAssignmentRhs(C26 c) {
+  int i = 0;
+  if (c.bad == null) return;
+  i +=
+      /*analyzer.notPromoted(propertyNotPromoted(target: member:C26.bad, type: int?))*/ c
+          . /*cfe.notPromoted(propertyNotPromoted(target: member:C26.bad, type: int?))*/ bad;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart b/pkg/_fe_analyzer_shared/test/mini_ast.dart
similarity index 95%
rename from pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
rename to pkg/_fe_analyzer_shared/test/mini_ast.dart
index d7fbe42..1d026cf 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_mini_ast.dart
+++ b/pkg/_fe_analyzer_shared/test/mini_ast.dart
@@ -9,10 +9,12 @@
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
 import 'package:test/test.dart';
 
-import '../mini_types.dart';
+import 'mini_types.dart';
 
 Expression get nullLiteral => new _NullLiteral();
 
+Expression get this_ => new _This();
+
 Statement assert_(Expression condition, [Expression? message]) =>
     new _Assert(condition, message);
 
@@ -37,10 +39,6 @@
 SwitchCase case_(List<Statement> body, {bool hasLabel = false}) =>
     SwitchCase._(hasLabel, body);
 
-CatchClause catch_(
-        {Var? exception, Var? stackTrace, required List<Statement> body}) =>
-    CatchClause._(body, exception, stackTrace);
-
 /// Creates a pseudo-statement whose function is to verify that flow analysis
 /// considers [variable]'s assigned state to be [expectedAssignedState].
 Statement checkAssigned(Var variable, bool expectedAssignedState) =>
@@ -160,18 +158,12 @@
         {required bool isExhaustive}) =>
     new _Switch(expression, cases, isExhaustive);
 
-Expression this_(String type) => new _This(Type(type));
-
 Expression thisOrSuperPropertyGet(String name, {String type = 'Object?'}) =>
     new _ThisOrSuperPropertyGet(name, Type(type));
 
 Expression throw_(Expression operand) => new _Throw(operand);
 
-Statement tryCatch(List<Statement> body, List<CatchClause> catches) =>
-    new _TryCatch(body, catches);
-
-Statement tryFinally(List<Statement> body, List<Statement> finally_) =>
-    new _TryFinally(body, finally_);
+TryBuilder try_(List<Statement> body) => new _TryStatement(body, [], null);
 
 Statement while_(Expression condition, List<Statement> body) =>
     new _While(condition, body);
@@ -184,39 +176,6 @@
   BranchTargetPlaceholder._();
 }
 
-/// Representation of a single catch clause in a try/catch statement.  Use
-/// [catch_] to create instances of this class.
-class CatchClause implements _Visitable<void> {
-  final List<Statement> _body;
-  final Var? _exception;
-  final Var? _stackTrace;
-
-  CatchClause._(this._body, this._exception, this._stackTrace);
-
-  String toString() {
-    String initialPart;
-    if (_stackTrace != null) {
-      initialPart = 'catch (${_exception!.name}, ${_stackTrace!.name})';
-    } else if (_exception != null) {
-      initialPart = 'catch (${_exception!.name})';
-    } else {
-      initialPart = 'on ...';
-    }
-    return '$initialPart ${block(_body)}';
-  }
-
-  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
-    _body._preVisit(assignedVariables);
-  }
-
-  void _visit(
-      Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
-    flow.tryCatchStatement_catchBegin(_exception, _stackTrace);
-    _body._visit(h, flow);
-    flow.tryCatchStatement_catchEnd();
-  }
-}
-
 /// Representation of an expression in the pseudo-Dart language used for flow
 /// analysis testing.  Methods in this class may be used to create more complex
 /// expressions based on this one.
@@ -427,6 +386,8 @@
 
   final bool legacy;
 
+  final Type? thisType;
+
   final Map<String, bool> _subtypes = Map.of(_coreSubtypes);
 
   final Map<String, Type> _factorResults = Map.of(_coreFactors);
@@ -435,7 +396,8 @@
 
   Map<String, Map<String, String>> _promotionExceptions = {};
 
-  Harness({this.legacy = false});
+  Harness({this.legacy = false, String? thisType})
+      : thisType = thisType == null ? null : Type(thisType);
 
   /// Updates the harness so that when a [factor] query is invoked on types
   /// [from] and [what], [result] will be returned.
@@ -625,6 +587,17 @@
   }
 }
 
+abstract class TryBuilder {
+  TryStatement catch_(
+      {Var? exception, Var? stackTrace, required List<Statement> body});
+
+  Statement finally_(List<Statement> statements);
+}
+
+abstract class TryStatement extends Statement implements TryBuilder {
+  TryStatement._() : super._();
+}
+
 /// Representation of a local variable in the pseudo-Dart language used for flow
 /// analysis testing.
 class Var {
@@ -757,6 +730,39 @@
   }
 }
 
+/// Representation of a single catch clause in a try/catch statement.  Use
+/// [catch_] to create instances of this class.
+class _CatchClause implements _Visitable<void> {
+  final List<Statement> _body;
+  final Var? _exception;
+  final Var? _stackTrace;
+
+  _CatchClause(this._body, this._exception, this._stackTrace);
+
+  String toString() {
+    String initialPart;
+    if (_stackTrace != null) {
+      initialPart = 'catch (${_exception!.name}, ${_stackTrace!.name})';
+    } else if (_exception != null) {
+      initialPart = 'catch (${_exception!.name})';
+    } else {
+      initialPart = 'on ...';
+    }
+    return '$initialPart ${block(_body)}';
+  }
+
+  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
+    _body._preVisit(assignedVariables);
+  }
+
+  void _visit(
+      Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
+    flow.tryCatchStatement_catchBegin(_exception, _stackTrace);
+    _body._visit(h, flow);
+    flow.tryCatchStatement_catchEnd();
+  }
+}
+
 class _CheckAssigned extends Statement {
   final Var variable;
   final bool expectedAssignedState;
@@ -1515,10 +1521,6 @@
 }
 
 class _This extends Expression {
-  final Type type;
-
-  _This(this.type);
-
   @override
   String toString() => 'this';
 
@@ -1528,8 +1530,9 @@
   @override
   Type _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
-    flow.thisOrSuper(this, type);
-    return type;
+    var thisType = h.thisType!;
+    flow.thisOrSuper(this, thisType);
+    return thisType;
   }
 }
 
@@ -1573,60 +1576,68 @@
   }
 }
 
-class _TryCatch extends Statement {
-  final List<Statement> body;
-  final List<CatchClause> catches;
+class _TryStatement extends TryStatement {
+  final List<Statement> _body;
+  final List<_CatchClause> _catches;
+  final List<Statement>? _finally;
+  final _bodyNode = Node._();
 
-  _TryCatch(this.body, this.catches) : super._();
+  _TryStatement(this._body, this._catches, this._finally) : super._();
 
   @override
-  String toString() => 'try ${block(body)} ${catches.join(' ')}';
-
-  @override
-  void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
-    assignedVariables.beginNode();
-    body._preVisit(assignedVariables);
-    assignedVariables.endNode(this);
-    catches._preVisit(assignedVariables);
+  TryStatement catch_(
+      {Var? exception, Var? stackTrace, required List<Statement> body}) {
+    assert(_finally == null, 'catch after finally');
+    return _TryStatement(
+        _body, [..._catches, _CatchClause(body, exception, stackTrace)], null);
   }
 
   @override
-  void _visit(
-      Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
-    flow.tryCatchStatement_bodyBegin();
-    body._visit(h, flow);
-    flow.tryCatchStatement_bodyEnd(this);
-    catches._visit(h, flow);
-    flow.tryCatchStatement_end();
+  Statement finally_(List<Statement> statements) {
+    assert(_finally == null, 'multiple finally clauses');
+    return _TryStatement(_body, _catches, statements);
   }
-}
-
-class _TryFinally extends Statement {
-  final List<Statement> body;
-  final List<Statement> finally_;
-  final Node _bodyNode = Node._();
-
-  _TryFinally(this.body, this.finally_) : super._();
-
-  @override
-  String toString() => 'try ${block(body)} finally ${block(finally_)}';
 
   @override
   void _preVisit(AssignedVariables<Node, Var> assignedVariables) {
-    assignedVariables.beginNode();
-    body._preVisit(assignedVariables);
+    if (_finally != null) {
+      assignedVariables.beginNode();
+    }
+    if (_catches.isNotEmpty) {
+      assignedVariables.beginNode();
+    }
+    _body._preVisit(assignedVariables);
     assignedVariables.endNode(_bodyNode);
-    finally_._preVisit(assignedVariables);
+    _catches._preVisit(assignedVariables);
+    if (_finally != null) {
+      if (_catches.isNotEmpty) {
+        assignedVariables.endNode(this);
+      }
+      _finally!._preVisit(assignedVariables);
+    }
   }
 
   @override
   void _visit(
       Harness h, FlowAnalysis<Node, Statement, Expression, Var, Type> flow) {
-    flow.tryFinallyStatement_bodyBegin();
-    body._visit(h, flow);
-    flow.tryFinallyStatement_finallyBegin(_bodyNode);
-    finally_._visit(h, flow);
-    flow.tryFinallyStatement_end();
+    if (_finally != null) {
+      flow.tryFinallyStatement_bodyBegin();
+    }
+    if (_catches.isNotEmpty) {
+      flow.tryCatchStatement_bodyBegin();
+    }
+    _body._visit(h, flow);
+    if (_catches.isNotEmpty) {
+      flow.tryCatchStatement_bodyEnd(_bodyNode);
+      _catches._visit(h, flow);
+      flow.tryCatchStatement_end();
+    }
+    if (_finally != null) {
+      flow.tryFinallyStatement_finallyBegin(
+          _catches.isNotEmpty ? this : _bodyNode);
+      _finally!._visit(h, flow);
+      flow.tryFinallyStatement_end();
+    }
   }
 }
 
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index 3ac8da4..92777a1 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -35,6 +35,21 @@
     assertHasRegion(HighlightRegionType.ANNOTATION, ') main', ')'.length);
   }
 
+  Future<void> test_ANNOTATION_hasTypeArguments_hasArguments() async {
+    addTestFile('''
+class AAA<T> {
+  const AAA(a, b, c);
+}
+
+@AAA<int>(1, 2, 3) void f() {}
+''');
+    await prepareHighlights();
+    assertHasRegion(
+        HighlightRegionType.ANNOTATION, '@AAA', '@AAA<int>('.length);
+    assertHasRegion(HighlightRegionType.ANNOTATION, ') void', ')'.length);
+    assertHasRegion(HighlightRegionType.CLASS, 'int>');
+  }
+
   Future<void> test_ANNOTATION_noArguments() async {
     addTestFile('''
 const AAA = 42;
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index f7a70e9..8f42b24 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -197,6 +197,53 @@
     assertHasRegionTarget('AAA aaa;', 'AAA {}');
   }
 
+  Future<void> test_annotation_generic_typeArguments_class() async {
+    addTestFile('''
+class A<T> {
+  const A();
+}
+
+@A<int>()
+void f() {}
+''');
+    await prepareNavigation();
+    assertHasRegion('int>()');
+  }
+
+  Future<void> test_annotationConstructor_generic_named() async {
+    addTestFile('''
+class A<T> {
+  const A.named(_);
+}
+
+@A<int>.named(0)
+void f() {}
+''');
+    await prepareNavigation();
+    {
+      assertHasRegion('A<int>.named(0)');
+      assertHasTarget('named(_);');
+    }
+    {
+      assertHasRegion('named(0)');
+      assertHasTarget('named(_);');
+    }
+  }
+
+  Future<void> test_annotationConstructor_generic_unnamed() async {
+    addTestFile('''
+class A<T> {
+  const A(_);
+}
+
+@A<int>(0)
+void f() {}
+''');
+    await prepareNavigation();
+    assertHasRegionString('A<int>(0)', 'A'.length);
+    assertHasTarget('A(_);', 0);
+  }
+
   Future<void> test_annotationConstructor_implicit() async {
     addTestFile('''
 class A {
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
index ecb0f00..f8b642b 100644
--- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -32,6 +32,34 @@
 @reflectiveTest
 class ImportedReferenceContributorTest extends DartCompletionContributorTest
     with ImportedReferenceContributorMixin {
+  Future<void> test_Annotation_typeArguments() async {
+    addSource('/home/test/lib/a.dart', '''
+class C {}
+typedef T1 = void Function();
+typedef T2 = List<int>;
+''');
+
+    addTestSource('''
+import 'a.dart';
+
+class A<T> {
+  const A();
+}
+
+@A<^>()
+void f() {}
+''');
+    await computeSuggestions();
+
+    expect(replacementOffset, completionOffset);
+    expect(replacementLength, 0);
+    assertSuggestClass('C');
+    assertSuggestTypeAlias('T1',
+        aliasedType: 'void Function()', returnType: 'void');
+    assertSuggestTypeAlias('T2', aliasedType: 'List<int>');
+    assertNotSuggested('identical');
+  }
+
   /// Sanity check.  Permutations tested in local_ref_contributor.
   Future<void> test_ArgDefaults_function_with_required_named() async {
     writeTestPackageConfig(meta: true);
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 10488ef..0317cd7 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -164,6 +164,7 @@
   CompileTimeErrorCode.EXTENDS_DEFERRED_CLASS,
   CompileTimeErrorCode.EXTENDS_DISALLOWED_CLASS,
   CompileTimeErrorCode.EXTENDS_NON_CLASS,
+  CompileTimeErrorCode.EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
   CompileTimeErrorCode.EXTENSION_AS_EXPRESSION,
   CompileTimeErrorCode.EXTENSION_CONFLICTING_STATIC_AND_INSTANCE,
   CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT,
@@ -206,6 +207,7 @@
   CompileTimeErrorCode.IMPLEMENTS_NON_CLASS,
   CompileTimeErrorCode.IMPLEMENTS_REPEATED,
   CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS,
+  CompileTimeErrorCode.IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
   CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER,
   CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY,
   CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY,
@@ -287,6 +289,8 @@
   CompileTimeErrorCode.MIXIN_INSTANTIATE,
   CompileTimeErrorCode.MIXIN_OF_DISALLOWED_CLASS,
   CompileTimeErrorCode.MIXIN_OF_NON_CLASS,
+  CompileTimeErrorCode.MIXIN_OF_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+  CompileTimeErrorCode.MIXIN_ON_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
   CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS,
   CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS,
   CompileTimeErrorCode.MIXIN_SUPER_CLASS_CONSTRAINT_NON_INTERFACE,
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 5fb5657..8989422 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -80,7 +80,7 @@
       if (_lastClonedOffset <= token.offset) {
         _cloneTokens(_nextToClone ?? token, token.offset);
       }
-      return _clonedTokens[token]!;
+      return _clonedTokens[token];
     } else {
       return token;
     }
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
index 2ffd93d..d246ff1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
@@ -30,11 +30,11 @@
       _definingLibrary.featureSet.isEnabled(Feature.generic_metadata);
 
   void resolve(AnnotationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     AstNode parent = node.parent;
 
     node.typeArguments?.accept(_resolver);
-    _resolve(node, whyNotPromotedInfo);
+    _resolve(node, whyNotPromotedList);
 
     var elementAnnotationImpl =
         node.elementAnnotation as ElementAnnotationImpl?;
@@ -50,7 +50,7 @@
     AnnotationImpl node,
     ClassElement classElement,
     SimpleIdentifierImpl? getterName,
-    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
     ExecutableElement? getter;
     if (getterName != null) {
@@ -66,7 +66,7 @@
     node.element = getter;
 
     if (getterName != null && getter is PropertyAccessorElement) {
-      _propertyAccessorElement(node, getterName, getter, whyNotPromotedInfo);
+      _propertyAccessorElement(node, getterName, getter, whyNotPromotedList);
       _resolveAnnotationElementGetter(node, getter);
     } else if (getter is! ConstructorElement) {
       _errorReporter.reportErrorForNode(
@@ -75,7 +75,7 @@
       );
     }
 
-    _visitArguments(node, whyNotPromotedInfo);
+    _visitArguments(node, whyNotPromotedList);
   }
 
   void _constructorInvocation(
@@ -83,7 +83,7 @@
     ClassElement classElement,
     SimpleIdentifierImpl? constructorName,
     ArgumentList argumentList,
-    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
     ConstructorElement? constructorElement;
     if (constructorName != null) {
@@ -104,7 +104,7 @@
         node,
       );
       _resolver.visitArgumentList(argumentList,
-          whyNotPromotedInfo: whyNotPromotedInfo);
+          whyNotPromotedList: whyNotPromotedList);
       return;
     }
 
@@ -115,7 +115,7 @@
       _resolveConstructorInvocationArguments(node);
       InferenceContext.setType(argumentList, constructorElement.type);
       _resolver.visitArgumentList(argumentList,
-          whyNotPromotedInfo: whyNotPromotedInfo);
+          whyNotPromotedList: whyNotPromotedList);
       return;
     }
 
@@ -134,7 +134,7 @@
 
       InferenceContext.setType(argumentList, constructorElement.type);
       _resolver.visitArgumentList(argumentList,
-          whyNotPromotedInfo: whyNotPromotedInfo);
+          whyNotPromotedList: whyNotPromotedList);
     }
 
     if (!_genericMetadataIsEnabled) {
@@ -164,7 +164,7 @@
     }
 
     _resolver.visitArgumentList(argumentList,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
 
     var constructorRawType = _resolver.typeAnalyzer
         .constructorToGenericFunctionType(constructorElement);
@@ -194,7 +194,7 @@
     AnnotationImpl node,
     ExtensionElement extensionElement,
     SimpleIdentifierImpl? getterName,
-    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
     ExecutableElement? getter;
     if (getterName != null) {
@@ -206,7 +206,7 @@
     node.element = getter;
 
     if (getterName != null && getter is PropertyAccessorElement) {
-      _propertyAccessorElement(node, getterName, getter, whyNotPromotedInfo);
+      _propertyAccessorElement(node, getterName, getter, whyNotPromotedList);
       _resolveAnnotationElementGetter(node, getter);
     } else {
       _errorReporter.reportErrorForNode(
@@ -215,25 +215,25 @@
       );
     }
 
-    _visitArguments(node, whyNotPromotedInfo);
+    _visitArguments(node, whyNotPromotedList);
   }
 
   void _propertyAccessorElement(
     AnnotationImpl node,
     SimpleIdentifierImpl name,
     PropertyAccessorElement element,
-    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
     element = _resolver.toLegacyElement(element);
     name.staticElement = element;
     node.element = element;
 
     _resolveAnnotationElementGetter(node, element);
-    _visitArguments(node, whyNotPromotedInfo);
+    _visitArguments(node, whyNotPromotedList);
   }
 
   void _resolve(AnnotationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     SimpleIdentifierImpl name1;
     SimpleIdentifierImpl? name2;
     SimpleIdentifierImpl? name3;
@@ -257,7 +257,7 @@
         node,
         [name1.name],
       );
-      _visitArguments(node, whyNotPromotedInfo);
+      _visitArguments(node, whyNotPromotedList);
       return;
     }
 
@@ -265,16 +265,16 @@
     if (element1 is ClassElement) {
       if (argumentList != null) {
         _constructorInvocation(
-            node, element1, name2, argumentList, whyNotPromotedInfo);
+            node, element1, name2, argumentList, whyNotPromotedList);
       } else {
-        _classGetter(node, element1, name2, whyNotPromotedInfo);
+        _classGetter(node, element1, name2, whyNotPromotedList);
       }
       return;
     }
 
     // Extension.CONST
     if (element1 is ExtensionElement) {
-      _extensionGetter(node, element1, name2, whyNotPromotedInfo);
+      _extensionGetter(node, element1, name2, whyNotPromotedList);
       return;
     }
 
@@ -287,20 +287,20 @@
         if (element2 is ClassElement) {
           if (argumentList != null) {
             _constructorInvocation(
-                node, element2, name3, argumentList, whyNotPromotedInfo);
+                node, element2, name3, argumentList, whyNotPromotedList);
           } else {
-            _classGetter(node, element2, name3, whyNotPromotedInfo);
+            _classGetter(node, element2, name3, whyNotPromotedList);
           }
           return;
         }
         // prefix.Extension.CONST
         if (element2 is ExtensionElement) {
-          _extensionGetter(node, element2, name3, whyNotPromotedInfo);
+          _extensionGetter(node, element2, name3, whyNotPromotedList);
           return;
         }
         // prefix.CONST
         if (element2 is PropertyAccessorElement) {
-          _propertyAccessorElement(node, name2, element2, whyNotPromotedInfo);
+          _propertyAccessorElement(node, name2, element2, whyNotPromotedList);
           return;
         }
         // undefined
@@ -310,7 +310,7 @@
             node,
             [name2.name],
           );
-          _visitArguments(node, whyNotPromotedInfo);
+          _visitArguments(node, whyNotPromotedList);
           return;
         }
       }
@@ -318,7 +318,7 @@
 
     // CONST
     if (element1 is PropertyAccessorElement) {
-      _propertyAccessorElement(node, name1, element1, whyNotPromotedInfo);
+      _propertyAccessorElement(node, name1, element1, whyNotPromotedList);
       return;
     }
 
@@ -332,7 +332,7 @@
       node,
     );
 
-    _visitArguments(node, whyNotPromotedInfo);
+    _visitArguments(node, whyNotPromotedList);
   }
 
   void _resolveAnnotationElementGetter(
@@ -394,11 +394,11 @@
   }
 
   void _visitArguments(AnnotationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     var arguments = node.arguments;
     if (arguments != null) {
       _resolver.visitArgumentList(arguments,
-          whyNotPromotedInfo: whyNotPromotedInfo);
+          whyNotPromotedList: whyNotPromotedList);
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index a3a966c..4c05164 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -248,6 +248,11 @@
       assignedType,
       whyNotPromoted: operator == TokenType.EQ ? whyNotPromoted : null,
     );
+    if (operator != TokenType.EQ &&
+        operator != TokenType.QUESTION_QUESTION_EQ) {
+      _resolver.checkForArgumentTypeNotAssignableForArgument(node.rightHandSide,
+          whyNotPromoted: whyNotPromoted);
+    }
   }
 
   void _setRhsContext(AssignmentExpressionImpl node, DartType leftType,
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index 0fb7a3a..b6453e8 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -111,8 +111,7 @@
     var right = node.rightOperand;
     right.accept(_resolver);
     right = node.rightOperand;
-    var whyNotPromotedInfo =
-        _resolver.flowAnalysis?.flow?.whyNotPromoted(right);
+    var whyNotPromoted = _resolver.flowAnalysis?.flow?.whyNotPromoted(right);
 
     if (!leftExtensionOverride) {
       flow?.equalityOp_end(node, right, right.typeOrThrow, notEqual: notEqual);
@@ -125,8 +124,7 @@
     );
     _resolveUserDefinableType(node);
     _resolver.checkForArgumentTypeNotAssignableForArgument(node.rightOperand,
-        promoteParameterToNullable: true,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        promoteParameterToNullable: true, whyNotPromoted: whyNotPromoted);
   }
 
   void _resolveIfNull(BinaryExpressionImpl node) {
@@ -275,12 +273,11 @@
 
     right.accept(_resolver);
     right = node.rightOperand;
-    var whyNotPromotedInfo =
-        _resolver.flowAnalysis?.flow?.whyNotPromoted(right);
+    var whyNotPromoted = _resolver.flowAnalysis?.flow?.whyNotPromoted(right);
 
     _resolveUserDefinableType(node);
     _resolver.checkForArgumentTypeNotAssignableForArgument(right,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromoted: whyNotPromoted);
   }
 
   void _resolveUserDefinableElement(
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 a515061..9a099ed 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
@@ -37,11 +37,11 @@
       _resolver.nullableDereferenceVerifier;
 
   void resolve(FunctionExpressionInvocationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     var function = node.function;
 
     if (function is ExtensionOverrideImpl) {
-      _resolveReceiverExtensionOverride(node, function, whyNotPromotedInfo);
+      _resolveReceiverExtensionOverride(node, function, whyNotPromotedList);
       return;
     }
 
@@ -52,12 +52,12 @@
       // `_resolveReceiverInterfaceType` calls `TypePropertyResolver.resolve`,
       // which does the necessary null checking.
       _resolveReceiverInterfaceType(
-          node, function, receiverType, whyNotPromotedInfo);
+          node, function, receiverType, whyNotPromotedList);
       return;
     }
 
     if (_checkForUseOfVoidResult(function, receiverType)) {
-      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
+      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
       return;
     }
 
@@ -65,18 +65,18 @@
         errorCode: CompileTimeErrorCode.UNCHECKED_INVOCATION_OF_NULLABLE_VALUE);
 
     if (receiverType is FunctionType) {
-      _resolve(node, receiverType, whyNotPromotedInfo);
+      _resolve(node, receiverType, whyNotPromotedList);
       return;
     }
 
     if (identical(receiverType, NeverTypeImpl.instance)) {
       _errorReporter.reportErrorForNode(
           HintCode.RECEIVER_OF_TYPE_NEVER, function);
-      _unresolved(node, NeverTypeImpl.instance, whyNotPromotedInfo);
+      _unresolved(node, NeverTypeImpl.instance, whyNotPromotedList);
       return;
     }
 
-    _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
+    _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
   }
 
   /// Check for situations where the result of a method or function is used,
@@ -104,11 +104,11 @@
   }
 
   void _resolve(FunctionExpressionInvocationImpl node, FunctionType rawType,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     _inferenceHelper.resolveFunctionExpressionInvocation(
       node: node,
       rawType: rawType,
-      whyNotPromotedInfo: whyNotPromotedInfo,
+      whyNotPromotedList: whyNotPromotedList,
     );
 
     var returnType = _inferenceHelper.computeInvokeReturnType(
@@ -118,15 +118,15 @@
   }
 
   void _resolveArguments(FunctionExpressionInvocationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     _resolver.visitArgumentList(node.argumentList,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
   }
 
   void _resolveReceiverExtensionOverride(
     FunctionExpressionInvocationImpl node,
     ExtensionOverride function,
-    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
     var result = _extensionResolver.getOverrideMember(
       function,
@@ -141,7 +141,7 @@
         function,
         [function.extensionName.name],
       );
-      return _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
+      return _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
     }
 
     if (callElement.isStatic) {
@@ -152,14 +152,14 @@
     }
 
     var rawType = callElement.type;
-    _resolve(node, rawType, whyNotPromotedInfo);
+    _resolve(node, rawType, whyNotPromotedList);
   }
 
   void _resolveReceiverInterfaceType(
     FunctionExpressionInvocationImpl node,
     Expression function,
     InterfaceType receiverType,
-    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
     var result = _typePropertyResolver.resolve(
       receiver: function,
@@ -177,7 +177,7 @@
           function,
         );
       }
-      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
+      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
       return;
     }
 
@@ -186,19 +186,19 @@
         CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
         function,
       );
-      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedInfo);
+      _unresolved(node, DynamicTypeImpl.instance, whyNotPromotedList);
       return;
     }
 
     node.staticElement = callElement;
     var rawType = callElement.type;
-    _resolve(node, rawType, whyNotPromotedInfo);
+    _resolve(node, rawType, whyNotPromotedList);
   }
 
   void _unresolved(FunctionExpressionInvocationImpl node, DartType type,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     _setExplicitTypeArgumentTypes(node);
-    _resolveArguments(node, whyNotPromotedInfo);
+    _resolveArguments(node, whyNotPromotedList);
     node.staticInvokeType = DynamicTypeImpl.instance;
     node.staticType = type;
   }
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 865c8dd..f7bef84 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
@@ -209,7 +209,7 @@
     required FunctionExpressionInvocationImpl node,
     required FunctionType rawType,
     required List<Map<DartType, NonPromotionReason> Function()>
-        whyNotPromotedInfo,
+        whyNotPromotedList,
   }) {
     _resolveInvocation(
       rawType: rawType,
@@ -218,7 +218,7 @@
       contextType: InferenceContext.getContext(node),
       isConst: false,
       errorNode: node.function,
-      whyNotPromotedInfo: whyNotPromotedInfo,
+      whyNotPromotedList: whyNotPromotedList,
     );
 
     node.typeArgumentTypes = _typeArgumentTypes;
@@ -234,7 +234,7 @@
     required MethodInvocationImpl node,
     required FunctionType rawType,
     required List<Map<DartType, NonPromotionReason> Function()>
-        whyNotPromotedInfo,
+        whyNotPromotedList,
   }) {
     _resolveInvocation(
       rawType: rawType,
@@ -243,7 +243,7 @@
       contextType: InferenceContext.getContext(node),
       isConst: false,
       errorNode: node.function,
-      whyNotPromotedInfo: whyNotPromotedInfo,
+      whyNotPromotedList: whyNotPromotedList,
     );
 
     node.typeArgumentTypes = _typeArgumentTypes;
@@ -333,10 +333,10 @@
   }
 
   void _resolveArguments(ArgumentList argumentList,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     _resolver.visitArgumentList(argumentList,
         isIdentical: _isCallToIdentical(argumentList.parent),
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
   }
 
   void _resolveInvocation({
@@ -347,14 +347,14 @@
     required bool isConst,
     required AstNode errorNode,
     required List<Map<DartType, NonPromotionReason> Function()>
-        whyNotPromotedInfo,
+        whyNotPromotedList,
   }) {
     if (typeArgumentList != null) {
       _resolveInvocationWithTypeArguments(
         rawType: rawType,
         typeArgumentList: typeArgumentList,
         argumentList: argumentList,
-        whyNotPromotedInfo: whyNotPromotedInfo,
+        whyNotPromotedList: whyNotPromotedList,
       );
     } else {
       _resolveInvocationWithoutTypeArguments(
@@ -363,7 +363,7 @@
         argumentList: argumentList,
         isConst: isConst,
         errorNode: errorNode,
-        whyNotPromotedInfo: whyNotPromotedInfo,
+        whyNotPromotedList: whyNotPromotedList,
       );
     }
     _setCorrespondingParameters(argumentList, _invokeType!);
@@ -376,13 +376,13 @@
     required bool isConst,
     required AstNode errorNode,
     required List<Map<DartType, NonPromotionReason> Function()>
-        whyNotPromotedInfo,
+        whyNotPromotedList,
   }) {
     var typeParameters = rawType.typeFormals;
 
     if (typeParameters.isEmpty) {
       InferenceContext.setType(argumentList, rawType);
-      _resolveArguments(argumentList, whyNotPromotedInfo);
+      _resolveArguments(argumentList, whyNotPromotedList);
 
       _typeArgumentTypes = const <DartType>[];
       _invokeType = rawType;
@@ -399,7 +399,7 @@
       var downwardsInvokeType = rawType.instantiate(downwardsTypeArguments);
       InferenceContext.setType(argumentList, downwardsInvokeType);
 
-      _resolveArguments(argumentList, whyNotPromotedInfo);
+      _resolveArguments(argumentList, whyNotPromotedList);
 
       _typeArgumentTypes = _inferUpwards(
         rawType: rawType,
@@ -417,7 +417,7 @@
     required TypeArgumentList typeArgumentList,
     required ArgumentList argumentList,
     required List<Map<DartType, NonPromotionReason> Function()>
-        whyNotPromotedInfo,
+        whyNotPromotedList,
   }) {
     var typeParameters = rawType.typeFormals;
 
@@ -445,7 +445,7 @@
     var invokeType = rawType.instantiate(typeArguments);
     InferenceContext.setType(argumentList, invokeType);
 
-    _resolveArguments(argumentList, whyNotPromotedInfo);
+    _resolveArguments(argumentList, whyNotPromotedList);
 
     _typeArgumentTypes = typeArguments;
     _invokeType = invokeType;
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 7310f7e..c585b07 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -82,7 +82,7 @@
   TypeSystemImpl get _typeSystem => _resolver.typeSystem;
 
   void resolve(MethodInvocationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     _invocation = node;
 
     var nameNode = node.methodName;
@@ -92,7 +92,7 @@
     var receiver = node.realTarget;
 
     if (receiver == null) {
-      _resolveReceiverNull(node, nameNode, name, whyNotPromotedInfo);
+      _resolveReceiverNull(node, nameNode, name, whyNotPromotedList);
       return;
     }
 
@@ -100,7 +100,7 @@
       var receiverElement = receiver.staticElement;
       if (receiverElement is PrefixElement) {
         _resolveReceiverPrefix(
-            node, receiverElement, nameNode, name, whyNotPromotedInfo);
+            node, receiverElement, nameNode, name, whyNotPromotedList);
         return;
       }
     }
@@ -109,19 +109,19 @@
       var receiverElement = receiver.staticElement;
       if (receiverElement is ExtensionElement) {
         _resolveExtensionMember(node, receiver, receiverElement, nameNode, name,
-            whyNotPromotedInfo);
+            whyNotPromotedList);
         return;
       }
     }
 
     if (receiver is SuperExpressionImpl) {
-      _resolveReceiverSuper(node, receiver, nameNode, name, whyNotPromotedInfo);
+      _resolveReceiverSuper(node, receiver, nameNode, name, whyNotPromotedList);
       return;
     }
 
     if (receiver is ExtensionOverrideImpl) {
       _resolveExtensionOverride(
-          node, receiver, nameNode, name, whyNotPromotedInfo);
+          node, receiver, nameNode, name, whyNotPromotedList);
       return;
     }
 
@@ -129,13 +129,13 @@
       var element = receiver.staticElement;
       if (element is ClassElement) {
         _resolveReceiverTypeLiteral(
-            node, element, nameNode, name, whyNotPromotedInfo);
+            node, element, nameNode, name, whyNotPromotedList);
         return;
       } else if (element is TypeAliasElement) {
         var aliasedType = element.aliasedType;
         if (aliasedType is InterfaceType) {
           _resolveReceiverTypeLiteral(
-              node, aliasedType.element, nameNode, name, whyNotPromotedInfo);
+              node, aliasedType.element, nameNode, name, whyNotPromotedList);
           return;
         }
       }
@@ -144,17 +144,17 @@
     DartType receiverType = receiver.typeOrThrow;
 
     if (_typeSystem.isDynamicBounded(receiverType)) {
-      _resolveReceiverDynamicBounded(node, whyNotPromotedInfo);
+      _resolveReceiverDynamicBounded(node, whyNotPromotedList);
       return;
     }
 
     if (receiverType is NeverTypeImpl) {
-      _resolveReceiverNever(node, receiver, receiverType, whyNotPromotedInfo);
+      _resolveReceiverNever(node, receiver, receiverType, whyNotPromotedList);
       return;
     }
 
     if (receiverType is VoidType) {
-      _reportUseOfVoidType(node, receiver, whyNotPromotedInfo);
+      _reportUseOfVoidType(node, receiver, whyNotPromotedList);
       return;
     }
 
@@ -165,7 +165,7 @@
 
     if (_typeSystem.isFunctionBounded(receiverType)) {
       _resolveReceiverFunctionBounded(
-          node, receiver, receiverType, nameNode, name, whyNotPromotedInfo);
+          node, receiver, receiverType, nameNode, name, whyNotPromotedList);
       return;
     }
 
@@ -176,7 +176,7 @@
       nameNode: nameNode,
       name: name,
       receiverErrorNode: receiver,
-      whyNotPromotedInfo: whyNotPromotedInfo,
+      whyNotPromotedList: whyNotPromotedList,
     );
   }
 
@@ -217,9 +217,9 @@
   }
 
   void _reportInvocationOfNonFunction(MethodInvocationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     _setDynamicResolution(node,
-        setNameTypeToDynamic: false, whyNotPromotedInfo: whyNotPromotedInfo);
+        setNameTypeToDynamic: false, whyNotPromotedList: whyNotPromotedList);
     _resolver.errorReporter.reportErrorForNode(
       CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION,
       node.methodName,
@@ -251,9 +251,9 @@
     required String? prefix,
     required String name,
     required List<Map<DartType, NonPromotionReason> Function()>
-        whyNotPromotedInfo,
+        whyNotPromotedList,
   }) {
-    _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
 
     if (nameScope.shouldIgnoreUndefined2(prefix: prefix, name: name)) {
       return;
@@ -270,8 +270,8 @@
       MethodInvocationImpl node,
       String name,
       ClassElement typeReference,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
-    _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
+    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
     _resolver.errorReporter.reportErrorForNode(
       CompileTimeErrorCode.UNDEFINED_METHOD,
       node.methodName,
@@ -280,8 +280,8 @@
   }
 
   void _reportUseOfVoidType(MethodInvocationImpl node, AstNode errorNode,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
-    _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
+    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
     _resolver.errorReporter.reportErrorForNode(
       CompileTimeErrorCode.USE_OF_VOID_RESULT,
       errorNode,
@@ -291,19 +291,19 @@
   /// [InvocationExpression.staticInvokeType] has been set for the [node].
   /// Use it to set context for arguments, and resolve them.
   void _resolveArguments(MethodInvocationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     // TODO(scheglov) This is bad, don't write raw type, carry it
     _inferenceHelper.inferArgumentTypesForInvocation(
       node,
       node.methodName.staticType,
     );
     _resolver.visitArgumentList(node.argumentList,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
   }
 
   void _resolveArguments_finishInference(MethodInvocationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
-    _resolveArguments(node, whyNotPromotedInfo);
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
+    _resolveArguments(node, whyNotPromotedList);
 
     // TODO(scheglov) This is bad, don't put / get raw FunctionType this way.
     _inferenceHelper.inferGenericInvocationExpression(
@@ -341,7 +341,7 @@
       ExtensionElement extension,
       SimpleIdentifierImpl nameNode,
       String name,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     var getter = extension.getGetter(name);
     if (getter != null) {
       getter = _resolver.toLegacyElement(getter);
@@ -356,11 +356,11 @@
       method = _resolver.toLegacyElement(method);
       nameNode.staticElement = method;
       _reportStaticAccessToInstanceMember(method, nameNode);
-      _setResolution(node, method.type, whyNotPromotedInfo);
+      _setResolution(node, method.type, whyNotPromotedList);
       return;
     }
 
-    _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
     _resolver.errorReporter.reportErrorForNode(
       CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD,
       nameNode,
@@ -373,12 +373,12 @@
       ExtensionOverride override,
       SimpleIdentifierImpl nameNode,
       String name,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     var result = _extensionResolver.getOverrideMember(override, name);
     var member = _resolver.toLegacyElement(result.getter);
 
     if (member == null) {
-      _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+      _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
       _resolver.errorReporter.reportErrorForNode(
         CompileTimeErrorCode.UNDEFINED_EXTENSION_METHOD,
         nameNode,
@@ -408,11 +408,11 @@
       return _rewriteAsFunctionExpressionInvocation(node, member.returnType);
     }
 
-    _setResolution(node, member.type, whyNotPromotedInfo);
+    _setResolution(node, member.type, whyNotPromotedList);
   }
 
   void _resolveReceiverDynamicBounded(MethodInvocationImpl node,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     var nameNode = node.methodName;
 
     var objectElement = _typeSystem.typeProvider.objectElement;
@@ -439,7 +439,7 @@
 
     _setExplicitTypeArgumentTypes();
     _resolver.visitArgumentList(node.argumentList,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
   }
 
   void _resolveReceiverFunctionBounded(
@@ -448,10 +448,10 @@
     DartType receiverType,
     SimpleIdentifierImpl nameNode,
     String name,
-    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
     if (name == FunctionElement.CALL_METHOD_NAME) {
-      _setResolution(node, receiverType, whyNotPromotedInfo);
+      _setResolution(node, receiverType, whyNotPromotedList);
       // TODO(scheglov) Replace this with using FunctionType directly.
       // Here was erase resolution that _setResolution() sets.
       nameNode.staticElement = null;
@@ -466,7 +466,7 @@
       nameNode: nameNode,
       name: name,
       receiverErrorNode: nameNode,
-      whyNotPromotedInfo: whyNotPromotedInfo,
+      whyNotPromotedList: whyNotPromotedList,
     );
   }
 
@@ -474,7 +474,7 @@
     MethodInvocationImpl node,
     Expression receiver,
     DartType receiverType,
-    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
     _setExplicitTypeArgumentTypes();
 
@@ -488,10 +488,10 @@
         _setResolution(
           node,
           objectMember.type,
-          whyNotPromotedInfo,
+          whyNotPromotedList,
         );
       } else {
-        _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+        _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
         _resolver.nullableDereferenceVerifier.report(receiver, receiverType,
             errorCode: CompileTimeErrorCode
                 .UNCHECKED_METHOD_INVOCATION_OF_NULLABLE_VALUE);
@@ -504,7 +504,7 @@
       node.staticInvokeType = _dynamicType;
       node.staticType = NeverTypeImpl.instance;
 
-      _resolveArguments(node, whyNotPromotedInfo);
+      _resolveArguments(node, whyNotPromotedList);
 
       _resolver.errorReporter.reportErrorForNode(
         HintCode.RECEIVER_OF_TYPE_NEVER,
@@ -518,7 +518,7 @@
       node.staticInvokeType = _dynamicType;
       node.staticType = _dynamicType;
 
-      _resolveArguments(node, whyNotPromotedInfo);
+      _resolveArguments(node, whyNotPromotedList);
       return;
     }
   }
@@ -527,7 +527,7 @@
       MethodInvocationImpl node,
       SimpleIdentifierImpl nameNode,
       String name,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     var element = nameScope.lookup(name).getter;
     if (element != null) {
       element = _resolver.toLegacyElement(element);
@@ -540,7 +540,7 @@
         return _rewriteAsFunctionExpressionInvocation(node, element.returnType);
       }
       if (element is ExecutableElement) {
-        return _setResolution(node, element.type, whyNotPromotedInfo);
+        return _setResolution(node, element.type, whyNotPromotedList);
       }
       if (element is VariableElement) {
         _resolver.checkReadOfNotAssignedLocalVariable(nameNode, element);
@@ -549,10 +549,10 @@
       }
       // TODO(scheglov) This is a questionable distinction.
       if (element is PrefixElement) {
-        _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+        _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
         return _reportPrefixIdentifierNotFollowedByDot(nameNode);
       }
-      return _reportInvocationOfNonFunction(node, whyNotPromotedInfo);
+      return _reportInvocationOfNonFunction(node, whyNotPromotedList);
     }
 
     DartType receiverType;
@@ -565,7 +565,7 @@
         node,
         prefix: null,
         name: node.methodName.name,
-        whyNotPromotedInfo: whyNotPromotedInfo,
+        whyNotPromotedList: whyNotPromotedList,
       );
     }
 
@@ -576,7 +576,7 @@
       nameNode: nameNode,
       name: name,
       receiverErrorNode: nameNode,
-      whyNotPromotedInfo: whyNotPromotedInfo,
+      whyNotPromotedList: whyNotPromotedList,
     );
   }
 
@@ -585,7 +585,7 @@
       PrefixElement prefix,
       SimpleIdentifierImpl nameNode,
       String name,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     // Note: prefix?.bar is reported as an error in ElementResolver.
 
     if (name == FunctionElement.LOAD_LIBRARY_NAME) {
@@ -597,7 +597,7 @@
         if (element is ExecutableElement) {
           nameNode.staticElement = element;
           return _setResolution(
-              node, (element as ExecutableElement).type, whyNotPromotedInfo);
+              node, (element as ExecutableElement).type, whyNotPromotedList);
         }
       }
     }
@@ -616,14 +616,14 @@
     }
 
     if (element is ExecutableElement) {
-      return _setResolution(node, element.type, whyNotPromotedInfo);
+      return _setResolution(node, element.type, whyNotPromotedList);
     }
 
     _reportUndefinedFunction(
       node,
       prefix: prefix.name,
       name: name,
-      whyNotPromotedInfo: whyNotPromotedInfo,
+      whyNotPromotedList: whyNotPromotedList,
     );
   }
 
@@ -632,10 +632,10 @@
       SuperExpression receiver,
       SimpleIdentifierImpl nameNode,
       String name,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     var enclosingClass = _resolver.enclosingClass;
     if (SuperContext.of(receiver) != SuperContext.valid) {
-      _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+      _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
       return;
     }
 
@@ -652,7 +652,7 @@
       if (target is PropertyAccessorElement) {
         return _rewriteAsFunctionExpressionInvocation(node, target.returnType);
       }
-      _setResolution(node, target.type, whyNotPromotedInfo);
+      _setResolution(node, target.type, whyNotPromotedList);
       return;
     }
 
@@ -662,7 +662,7 @@
     target = _inheritance.getInherited2(enclosingClass, _currentName!);
     if (target != null) {
       nameNode.staticElement = target;
-      _setResolution(node, target.type, whyNotPromotedInfo);
+      _setResolution(node, target.type, whyNotPromotedList);
 
       _resolver.errorReporter.reportErrorForNode(
           CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
@@ -672,7 +672,7 @@
     }
 
     // Nothing help, there is no target at all.
-    _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
     _resolver.errorReporter.reportErrorForNode(
         CompileTimeErrorCode.UNDEFINED_SUPER_METHOD,
         nameNode,
@@ -687,7 +687,7 @@
     required String name,
     required Expression receiverErrorNode,
     required List<Map<DartType, NonPromotionReason> Function()>
-        whyNotPromotedInfo,
+        whyNotPromotedList,
   }) {
     var result = _resolver.typePropertyResolver.resolve(
       receiver: receiver,
@@ -712,10 +712,10 @@
       if (target is PropertyAccessorElement) {
         return _rewriteAsFunctionExpressionInvocation(node, target.returnType);
       }
-      return _setResolution(node, target.type, whyNotPromotedInfo);
+      return _setResolution(node, target.type, whyNotPromotedList);
     }
 
-    _setDynamicResolution(node, whyNotPromotedInfo: whyNotPromotedInfo);
+    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
 
     if (!result.needsGetterError) {
       return;
@@ -742,7 +742,7 @@
       ClassElement receiver,
       SimpleIdentifierImpl nameNode,
       String name,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     if (node.isCascaded) {
       receiver = _typeType.element;
     }
@@ -756,14 +756,14 @@
           return _rewriteAsFunctionExpressionInvocation(
               node, element.returnType);
         }
-        _setResolution(node, element.type, whyNotPromotedInfo);
+        _setResolution(node, element.type, whyNotPromotedList);
       } else {
-        _reportInvocationOfNonFunction(node, whyNotPromotedInfo);
+        _reportInvocationOfNonFunction(node, whyNotPromotedList);
       }
       return;
     }
 
-    _reportUndefinedMethod(node, name, receiver, whyNotPromotedInfo);
+    _reportUndefinedMethod(node, name, receiver, whyNotPromotedList);
   }
 
   /// If the given [type] is a type parameter, replace with its bound.
@@ -825,14 +825,14 @@
   void _setDynamicResolution(MethodInvocationImpl node,
       {bool setNameTypeToDynamic = true,
       required List<Map<DartType, NonPromotionReason> Function()>
-          whyNotPromotedInfo}) {
+          whyNotPromotedList}) {
     if (setNameTypeToDynamic) {
       node.methodName.staticType = _dynamicType;
     }
     node.staticInvokeType = _dynamicType;
     node.staticType = _dynamicType;
     _setExplicitTypeArgumentTypes();
-    _resolveArguments_finishInference(node, whyNotPromotedInfo);
+    _resolveArguments_finishInference(node, whyNotPromotedList);
   }
 
   /// Set explicitly specified type argument types, or empty if not specified.
@@ -852,28 +852,28 @@
   }
 
   void _setResolution(MethodInvocationImpl node, DartType type,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     // TODO(scheglov) We need this for StaticTypeAnalyzer to run inference.
     // But it seems weird. Do we need to know the raw type of a function?!
     node.methodName.staticType = type;
 
     if (type == _dynamicType || _isCoreFunction(type)) {
       _setDynamicResolution(node,
-          setNameTypeToDynamic: false, whyNotPromotedInfo: whyNotPromotedInfo);
+          setNameTypeToDynamic: false, whyNotPromotedList: whyNotPromotedList);
       return;
     }
 
     if (type is FunctionType) {
       _inferenceHelper.resolveMethodInvocation(
-          node: node, rawType: type, whyNotPromotedInfo: whyNotPromotedInfo);
+          node: node, rawType: type, whyNotPromotedList: whyNotPromotedList);
       return;
     }
 
     if (type is VoidType) {
-      return _reportUseOfVoidType(node, node.methodName, whyNotPromotedInfo);
+      return _reportUseOfVoidType(node, node.methodName, whyNotPromotedList);
     }
 
-    _reportInvocationOfNonFunction(node, whyNotPromotedInfo);
+    _reportInvocationOfNonFunction(node, whyNotPromotedList);
   }
 
   /// Resolver visitor is separated from the elements resolver, which calls
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 666cce9..91d1ae7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -1193,6 +1193,10 @@
     visitTypeName(typeName);
     _typeNameResolver.classHierarchy_typeName = null;
 
+    if (_typeNameResolver.hasErrorReported) {
+      return;
+    }
+
     DartType type = typeName.typeOrThrow;
     if (type is InterfaceType) {
       ClassElement element = type.element;
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
index c4c1dfe..4acea06 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/element/scope.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
@@ -52,6 +53,9 @@
   /// [ConstructorName]. Otherwise this field will be set `null`.
   ConstructorName? rewriteResult;
 
+  /// If [resolveTypeName] reported an error, this flag is set to `true`.
+  bool hasErrorReported = false;
+
   TypeNameResolver(this.typeSystem, TypeProvider typeProvider,
       this.isNonNullableByDefault, this.errorReporter)
       : dynamicType = typeProvider.dynamicType;
@@ -71,6 +75,7 @@
   /// The client must set [nameScope] before calling [resolveTypeName].
   void resolveTypeName(TypeNameImpl node) {
     rewriteResult = null;
+    hasErrorReported = false;
 
     var typeIdentifier = node.name;
     if (typeIdentifier is PrefixedIdentifierImpl) {
@@ -386,11 +391,50 @@
     TypeAliasElement element,
     DartType type,
   ) {
+    // If a type alias that expands to a type parameter.
     if (element.aliasedType is TypeParameterType) {
-      var constructorName = node.parent;
-      if (constructorName is ConstructorName) {
-        _ErrorHelper(errorReporter)
-            .reportTypeAliasExpandsToTypeParameter(constructorName, element);
+      var parent = node.parent;
+      if (parent is ConstructorName) {
+        var errorNode = _ErrorHelper._getErrorNode(node);
+        var constructorUsage = parent.parent;
+        if (constructorUsage is InstanceCreationExpression) {
+          errorReporter.reportErrorForNode(
+            CompileTimeErrorCode
+                .INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+            errorNode,
+          );
+        } else if (constructorUsage is ConstructorDeclaration &&
+            constructorUsage.redirectedConstructor == parent) {
+          errorReporter.reportErrorForNode(
+            CompileTimeErrorCode
+                .REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+            errorNode,
+          );
+        } else {
+          throw UnimplementedError('${constructorUsage.runtimeType}');
+        }
+        return dynamicType;
+      }
+
+      // Report if this type is used as a class in hierarchy.
+      ErrorCode? errorCode;
+      if (parent is ExtendsClause) {
+        errorCode =
+            CompileTimeErrorCode.EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER;
+      } else if (parent is ImplementsClause) {
+        errorCode = CompileTimeErrorCode
+            .IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER;
+      } else if (parent is OnClause) {
+        errorCode =
+            CompileTimeErrorCode.MIXIN_ON_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER;
+      } else if (parent is WithClause) {
+        errorCode =
+            CompileTimeErrorCode.MIXIN_OF_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER;
+      }
+      if (errorCode != null) {
+        var errorNode = _ErrorHelper._getErrorNode(node);
+        errorReporter.reportErrorForNode(errorCode, errorNode);
+        hasErrorReported = true;
         return dynamicType;
       }
     }
@@ -550,28 +594,6 @@
     );
   }
 
-  void reportTypeAliasExpandsToTypeParameter(
-    ConstructorName constructorName,
-    TypeAliasElement element,
-  ) {
-    var errorNode = _getErrorNode(constructorName.type);
-    var constructorUsage = constructorName.parent;
-    if (constructorUsage is InstanceCreationExpression) {
-      errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.INSTANTIATE_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
-        errorNode,
-      );
-    } else if (constructorUsage is ConstructorDeclaration &&
-        constructorUsage.redirectedConstructor == constructorName) {
-      errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.REDIRECT_TO_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
-        errorNode,
-      );
-    } else {
-      throw UnimplementedError('${constructorUsage.runtimeType}');
-    }
-  }
-
   /// Returns the simple identifier of the given (maybe prefixed) identifier.
   static Identifier _getErrorNode(TypeName node) {
     Identifier identifier = node.name;
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 05a61d7..6218be8 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -3384,6 +3384,15 @@
       hasPublishedDocs: true,
       isUnresolvedIdentifier: true);
 
+  static const CompileTimeErrorCode
+      EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER = CompileTimeErrorCode(
+          'EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER',
+          "Type aliases that expand to a type parameter can't be used as "
+              "superclasses.",
+          correction:
+              "Try specifying a different superclass, or removing the extends "
+              "clause.");
+
   /**
    * Parameters:
    * 0: the name of the extension
@@ -4913,6 +4922,12 @@
           correction: "Try removing one of the occurrences.",
           hasPublishedDocs: true);
 
+  static const CompileTimeErrorCode
+      IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER = CompileTimeErrorCode(
+          'IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER',
+          "Type aliases that expand to a type parameter can't be implemented.",
+          correction: "Try specifying a class or mixin, or removing the list.");
+
   /**
    * Parameters:
    * 0: the name of the instance member
@@ -7292,6 +7307,17 @@
       'MIXIN_OF_NON_CLASS', "Classes can only mix in mixins and classes.",
       hasPublishedDocs: true);
 
+  static const CompileTimeErrorCode
+      MIXIN_OF_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER = CompileTimeErrorCode(
+          'MIXIN_OF_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER',
+          "Type aliases that expand to a type parameter can't be mixed in.");
+
+  static const CompileTimeErrorCode
+      MIXIN_ON_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER = CompileTimeErrorCode(
+          'MIXIN_ON_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER',
+          "Type aliases that expand to a type parameter can't be used as"
+              "superclass constraints.");
+
   /**
    * No parameters.
    */
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 9b9b7af..a43c330 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -26,7 +26,6 @@
         messageMissingAssignableSelector,
         messageNativeClauseShouldBeAnnotation,
         messageOperatorWithTypeParameters,
-        messageTypedefNotFunction,
         templateDuplicateLabelInSwitchStatement,
         templateExpectedButGot,
         templateExpectedIdentifier,
@@ -1549,7 +1548,15 @@
       var metadata = pop() as List<Annotation>?;
       var comment = _findComment(metadata, typedefKeyword);
       if (type is! GenericFunctionType && !enableNonFunctionTypeAliases) {
-        handleRecoverableError(messageTypedefNotFunction, equals, equals);
+        var feature = Feature.nonfunction_type_aliases;
+        handleRecoverableError(
+          templateExperimentNotEnabled.withArguments(
+            feature.enableString,
+            _versionAsString(ExperimentStatus.currentVersion),
+          ),
+          equals,
+          equals,
+        );
       }
       declarations.add(ast.genericTypeAlias(comment, metadata, typedefKeyword,
           name, templateParameters, equals, type, semicolon));
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 423b5df..ed9e40f 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -397,10 +397,10 @@
   @override
   void visitMethodInvocation(MethodInvocation node,
       {List<Map<DartType, NonPromotionReason> Function()>?
-          whyNotPromotedInfo}) {
-    whyNotPromotedInfo ??= [];
+          whyNotPromotedList}) {
+    whyNotPromotedList ??= [];
     _methodInvocationResolver.resolve(
-        node as MethodInvocationImpl, whyNotPromotedInfo);
+        node as MethodInvocationImpl, whyNotPromotedList);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart
index ff05271..350899c 100644
--- a/pkg/analyzer/lib/src/generated/error_detection_helpers.dart
+++ b/pkg/analyzer/lib/src/generated/error_detection_helpers.dart
@@ -32,7 +32,7 @@
       DartType? expectedStaticType,
       DartType actualStaticType,
       ErrorCode errorCode,
-      {Map<DartType, NonPromotionReason> Function()? whyNotPromotedInfo}) {
+      {Map<DartType, NonPromotionReason> Function()? whyNotPromoted}) {
     // Warning case: test static type information
     if (expectedStaticType != null) {
       if (!expectedStaticType.isVoid && checkForUseOfVoidResult(expression)) {
@@ -41,7 +41,7 @@
 
       _checkForAssignableExpressionAtType(
           expression, actualStaticType, expectedStaticType, errorCode,
-          whyNotPromoted: whyNotPromotedInfo);
+          whyNotPromoted: whyNotPromoted);
     }
   }
 
@@ -54,12 +54,12 @@
   /// See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
   void checkForArgumentTypeNotAssignableForArgument(Expression argument,
       {bool promoteParameterToNullable = false,
-      Map<DartType, NonPromotionReason> Function()? whyNotPromotedInfo}) {
+      Map<DartType, NonPromotionReason> Function()? whyNotPromoted}) {
     checkForArgumentTypeNotAssignableForArgument2(
       argument: argument,
       parameter: argument.staticParameterElement,
       promoteParameterToNullable: promoteParameterToNullable,
-      whyNotPromotedInfo: whyNotPromotedInfo,
+      whyNotPromoted: whyNotPromoted,
     );
   }
 
@@ -67,7 +67,7 @@
     required Expression argument,
     required ParameterElement? parameter,
     required bool promoteParameterToNullable,
-    Map<DartType, NonPromotionReason> Function()? whyNotPromotedInfo,
+    Map<DartType, NonPromotionReason> Function()? whyNotPromoted,
   }) {
     var staticParameterType = parameter?.type;
     if (promoteParameterToNullable && staticParameterType != null) {
@@ -78,7 +78,7 @@
         argument,
         staticParameterType,
         CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
-        whyNotPromotedInfo);
+        whyNotPromoted);
   }
 
   /// Verify that the given constructor field [initializer] has compatible field
@@ -247,10 +247,10 @@
       Expression expression,
       DartType? expectedStaticType,
       ErrorCode errorCode,
-      Map<DartType, NonPromotionReason> Function()? whyNotPromotedInfo) {
+      Map<DartType, NonPromotionReason> Function()? whyNotPromoted) {
     checkForArgumentTypeNotAssignable(
         expression, expectedStaticType, expression.typeOrThrow, errorCode,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromoted: whyNotPromoted);
   }
 
   bool _checkForAssignableExpression(
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index e8136ea..16387ea 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -345,12 +345,6 @@
   void visitAssignmentExpression(AssignmentExpression node) {
     TokenType operatorType = node.operator.type;
     Expression lhs = node.leftHandSide;
-    Expression rhs = node.rightHandSide;
-    if (operatorType == TokenType.EQ ||
-        operatorType == TokenType.QUESTION_QUESTION_EQ) {
-    } else {
-      checkForArgumentTypeNotAssignableForArgument(rhs);
-    }
     if (operatorType == TokenType.QUESTION_QUESTION_EQ) {
       _checkForDeadNullCoalesce(node.readType as TypeImpl, node.rightHandSide);
     }
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index e011889..5684e0e 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -428,12 +428,12 @@
   ///
   /// See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
   void checkForArgumentTypesNotAssignableInList(ArgumentList argumentList,
-      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo) {
+      List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList) {
     var arguments = argumentList.arguments;
     for (int i = 0; i < arguments.length; i++) {
       checkForArgumentTypeNotAssignableForArgument(arguments[i],
-          whyNotPromotedInfo:
-              flowAnalysis?.flow == null ? null : whyNotPromotedInfo[i]);
+          whyNotPromoted:
+              flowAnalysis?.flow == null ? null : whyNotPromotedList[i]);
     }
   }
 
@@ -882,25 +882,25 @@
 
   @override
   void visitAnnotation(covariant AnnotationImpl node) {
-    var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
+    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     AstNode parent = node.parent;
     if (identical(parent, _enclosingClassDeclaration) ||
         identical(parent, _enclosingFunctionTypeAlias) ||
         identical(parent, _enclosingMixinDeclaration)) {
       return;
     }
-    AnnotationResolver(this).resolve(node, whyNotPromotedInfo);
+    AnnotationResolver(this).resolve(node, whyNotPromotedList);
     var arguments = node.arguments;
     if (arguments != null) {
-      checkForArgumentTypesNotAssignableInList(arguments, whyNotPromotedInfo);
+      checkForArgumentTypesNotAssignableInList(arguments, whyNotPromotedList);
     }
   }
 
   @override
   void visitArgumentList(ArgumentList node,
       {bool isIdentical = false,
-      List<Map<DartType, NonPromotionReason> Function()>? whyNotPromotedInfo}) {
-    whyNotPromotedInfo ??= [];
+      List<Map<DartType, NonPromotionReason> Function()>? whyNotPromotedList}) {
+    whyNotPromotedList ??= [];
     var callerType = InferenceContext.getContext(node);
     NodeList<Expression> arguments = node.arguments;
     if (callerType is FunctionType) {
@@ -967,7 +967,7 @@
       }
       arguments[i].accept(this);
       if (flow != null) {
-        whyNotPromotedInfo.add(flow.whyNotPromoted(arguments[i]));
+        whyNotPromotedList.add(flow.whyNotPromoted(arguments[i]));
       }
     }
     if (isIdentical && length > 1) {
@@ -1444,13 +1444,13 @@
 
   @override
   void visitExtensionOverride(ExtensionOverride node) {
-    var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
+    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     node.extensionName.accept(this);
     node.typeArguments?.accept(this);
 
     ExtensionMemberResolver(this).setOverrideReceiverContextType(node);
     visitArgumentList(node.argumentList,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
 
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
@@ -1567,13 +1567,13 @@
 
   @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
+    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     node.function.accept(this);
     _functionExpressionInvocationResolver.resolve(
-        node as FunctionExpressionInvocationImpl, whyNotPromotedInfo);
+        node as FunctionExpressionInvocationImpl, whyNotPromotedList);
     nullShortingTermination(node);
     checkForArgumentTypesNotAssignableInList(
-        node.argumentList, whyNotPromotedInfo);
+        node.argumentList, whyNotPromotedList);
   }
 
   @override
@@ -1719,15 +1719,15 @@
   @override
   void visitInstanceCreationExpression(
       covariant InstanceCreationExpressionImpl node) {
-    var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
+    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     node.constructorName.accept(this);
     _inferArgumentTypesForInstanceCreate(node);
     visitArgumentList(node.argumentList,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
     checkForArgumentTypesNotAssignableInList(
-        node.argumentList, whyNotPromotedInfo);
+        node.argumentList, whyNotPromotedList);
   }
 
   @override
@@ -1792,7 +1792,7 @@
 
   @override
   void visitMethodInvocation(covariant MethodInvocationImpl node) {
-    var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
+    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     var target = node.target;
     target?.accept(this);
 
@@ -1812,18 +1812,18 @@
 
     node.typeArguments?.accept(this);
     elementResolver.visitMethodInvocation(node,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
 
     var functionRewrite = MethodInvocationResolver.getRewriteResult(node);
     if (functionRewrite != null) {
       nullShortingTermination(node, discardType: true);
       _resolveRewrittenFunctionExpressionInvocation(
-          functionRewrite, whyNotPromotedInfo);
+          functionRewrite, whyNotPromotedList);
     } else {
       nullShortingTermination(node);
     }
     checkForArgumentTypesNotAssignableInList(
-        node.argumentList, whyNotPromotedInfo);
+        node.argumentList, whyNotPromotedList);
   }
 
   @override
@@ -1940,14 +1940,14 @@
     // because it needs to be visited in the context of the constructor
     // invocation.
     //
-    var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
+    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     node.accept(elementResolver);
     InferenceContext.setType(node.argumentList, node.staticElement?.type);
     visitArgumentList(node.argumentList,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
     node.accept(typeAnalyzer);
     checkForArgumentTypesNotAssignableInList(
-        node.argumentList, whyNotPromotedInfo);
+        node.argumentList, whyNotPromotedList);
   }
 
   @override
@@ -2001,14 +2001,14 @@
     // because it needs to be visited in the context of the constructor
     // invocation.
     //
-    var whyNotPromotedInfo = <Map<DartType, NonPromotionReason> Function()>[];
+    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
     node.accept(elementResolver);
     InferenceContext.setType(node.argumentList, node.staticElement?.type);
     visitArgumentList(node.argumentList,
-        whyNotPromotedInfo: whyNotPromotedInfo);
+        whyNotPromotedList: whyNotPromotedList);
     node.accept(typeAnalyzer);
     checkForArgumentTypesNotAssignableInList(
-        node.argumentList, whyNotPromotedInfo);
+        node.argumentList, whyNotPromotedList);
   }
 
   @override
@@ -2316,7 +2316,7 @@
   /// as for method invocations.
   void _resolveRewrittenFunctionExpressionInvocation(
     FunctionExpressionInvocation node,
-    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedInfo,
+    List<Map<DartType, NonPromotionReason> Function()> whyNotPromotedList,
   ) {
     var function = node.function;
 
@@ -2334,7 +2334,7 @@
     }
 
     _functionExpressionInvocationResolver.resolve(
-        node as FunctionExpressionInvocationImpl, whyNotPromotedInfo);
+        node as FunctionExpressionInvocationImpl, whyNotPromotedList);
 
     nullShortingTermination(node);
   }
diff --git a/pkg/analyzer/test/generated/error_parser_test.dart b/pkg/analyzer/test/generated/error_parser_test.dart
index c7b7232..9115cc0 100644
--- a/pkg/analyzer/test/generated/error_parser_test.dart
+++ b/pkg/analyzer/test/generated/error_parser_test.dart
@@ -1698,7 +1698,7 @@
         errors: [
           expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 7),
           expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 7),
-          expectedError(ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, 10, 1),
+          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 10, 1),
         ]);
   }
 
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index ceb6903..402d7cc 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -3311,7 +3311,7 @@
   p is F;
 }
 ''', [
-      error(ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE, 10, 1),
+      error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 10, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index 080532a..8251b43 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -552,6 +552,20 @@
     assertThat(element).isReferencedAt('A();', false);
   }
 
+  test_isReferencedBy_ClassElement_inGenericAnnotation() async {
+    await _indexTestUnit('''
+class A<T> {
+  const A();
+}
+
+@A<A>()
+void f() {}
+''');
+    assertThat(findElement.class_('A'))
+      ..isReferencedAt('A<A', false)
+      ..isReferencedAt('A>()', false);
+  }
+
   test_isReferencedBy_ClassElement_inTypeAlias() async {
     await _indexTestUnit('''
 class A<T> {}
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index b053a6f..10ac334 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -303,6 +303,25 @@
     await _verifyReferences(element, expected);
   }
 
+  test_searchReferences_ClassElement_typeArgument_ofGenericAnnotation() async {
+    await resolveTestCode('''
+class A<T> {
+  const A();
+}
+
+class B {}
+
+@A<B>()
+void f() {}
+''');
+
+    var element = findElement.class_('B');
+    var f = findElement.topFunction('f');
+    await _verifyReferences(element, [
+      _expectId(f, SearchResultKind.REFERENCE, 'B>()'),
+    ]);
+  }
+
   test_searchReferences_CompilationUnitElement() async {
     newFile('$testPackageLibPath/foo.dart');
     await resolveTestCode('''
diff --git a/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart b/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart
new file mode 100644
index 0000000..07eeb68
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExperimentNotEnabledTest);
+  });
+}
+
+@reflectiveTest
+class ExperimentNotEnabledTest extends PubPackageResolutionTest {
+  test_nonFunctionTypeAliases_disabled() async {
+    await assertErrorsInCode(r'''
+// @dart = 2.12
+typedef A = int;
+''', [
+      error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 26, 1),
+    ]);
+  }
+
+  test_nonFunctionTypeAliases_disabled_nullable() async {
+    await assertErrorsInCode(r'''
+// @dart = 2.12
+typedef A = int?;
+''', [
+      error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 26, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart b/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
index 95db122..ab697b0 100644
--- a/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/extends_non_class_test.dart
@@ -10,13 +10,19 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ExtendsNonClassTest);
-    defineReflectiveTests(ExtendsNonClassWithNullSafetyTest);
   });
 }
 
 @reflectiveTest
-class ExtendsNonClassTest extends PubPackageResolutionTest
-    with WithoutNullSafetyMixin {
+class ExtendsNonClassTest extends PubPackageResolutionTest {
+  test_Never() async {
+    await assertErrorsInCode('''
+class A extends Never {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 16, 5),
+    ]);
+  }
+
   test_undefined() async {
     await assertErrorsInCode(r'''
 class C extends A {}
@@ -123,15 +129,3 @@
     ]);
   }
 }
-
-@reflectiveTest
-class ExtendsNonClassWithNullSafetyTest extends ExtendsNonClassTest
-    with WithNullSafetyMixin {
-  test_Never() async {
-    await assertErrorsInCode('''
-class A extends Never {}
-''', [
-      error(CompileTimeErrorCode.EXTENDS_NON_CLASS, 16, 5),
-    ]);
-  }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/extends_type_alias_expands_to_type_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/extends_type_alias_expands_to_type_parameter_test.dart
new file mode 100644
index 0000000..9737d88
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/extends_type_alias_expands_to_type_parameter_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExtendsTypeAliasExpandsToTypeParameterTest);
+  });
+}
+
+@reflectiveTest
+class ExtendsTypeAliasExpandsToTypeParameterTest
+    extends PubPackageResolutionTest {
+  test_class() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+typedef T = A;
+class B extends A {}
+''');
+  }
+
+  test_class_noTypeArguments() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef T<X extends A> = X;
+class B extends T {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          55, 1),
+    ]);
+  }
+
+  test_class_withTypeArguments() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef T<X extends A> = X;
+class B extends T<A> {}
+''', [
+      error(CompileTimeErrorCode.EXTENDS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          55, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/implements_type_alias_expands_to_type_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/implements_type_alias_expands_to_type_parameter_test.dart
new file mode 100644
index 0000000..2810170
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/implements_type_alias_expands_to_type_parameter_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ImplementsTypeAliasExpandsToTypeParameterTest);
+  });
+}
+
+@reflectiveTest
+class ImplementsTypeAliasExpandsToTypeParameterTest
+    extends PubPackageResolutionTest {
+  test_class() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+typedef T = A;
+class B implements T {}
+''');
+  }
+
+  test_class_typeParameter_noTypeArguments() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef T<X extends A> = X;
+class B implements T {}
+''', [
+      error(
+          CompileTimeErrorCode.IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          58,
+          1),
+    ]);
+  }
+
+  test_class_typeParameter_withTypeArguments() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef T<X extends A> = X;
+class B implements T<A> {}
+''', [
+      error(
+          CompileTimeErrorCode.IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          58,
+          1),
+    ]);
+  }
+
+  test_mixin_typeParameter_noTypeArguments() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef T<X extends A> = X;
+mixin M implements T {}
+''', [
+      error(
+          CompileTimeErrorCode.IMPLEMENTS_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          58,
+          1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_of_type_alias_expands_to_type_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_of_type_alias_expands_to_type_parameter_test.dart
new file mode 100644
index 0000000..558e767
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/mixin_of_type_alias_expands_to_type_parameter_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MixinOfTypeAliasExpandsToTypeParameterTest);
+  });
+}
+
+@reflectiveTest
+class MixinOfTypeAliasExpandsToTypeParameterTest
+    extends PubPackageResolutionTest {
+  test_class() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+typedef T = A;
+class B with A {}
+''');
+  }
+
+  test_class_noTypeArguments() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef T<X extends A> = X;
+class B with T {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          52, 1),
+    ]);
+  }
+
+  test_class_withTypeArguments() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef T<X extends A> = X;
+class B with T<A> {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_OF_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          52, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_on_type_alias_expands_to_type_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_on_type_alias_expands_to_type_parameter_test.dart
new file mode 100644
index 0000000..26be464
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/mixin_on_type_alias_expands_to_type_parameter_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MixinOnTypeAliasExpandsToTypeParameterTest);
+  });
+}
+
+@reflectiveTest
+class MixinOnTypeAliasExpandsToTypeParameterTest
+    extends PubPackageResolutionTest {
+  test_class() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+typedef T = A;
+mixin M on A {}
+''');
+  }
+
+  test_class_noTypeArguments() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef T<X extends A> = X;
+mixin M on T {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_ON_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          50, 1),
+    ]);
+  }
+
+  test_class_withTypeArguments() async {
+    await assertErrorsInCode(r'''
+class A {}
+typedef T<X extends A> = X;
+mixin M on T<A> {}
+''', [
+      error(CompileTimeErrorCode.MIXIN_ON_TYPE_ALIAS_EXPANDS_TO_TYPE_PARAMETER,
+          50, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 02c71dc..a227e93 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -147,6 +147,7 @@
     as expected_one_set_type_arguments;
 import 'expected_two_map_type_arguments_test.dart'
     as expected_two_map_type_arguments;
+import 'experiment_not_enabled_test.dart' as experiment_not_enabled;
 import 'export_internal_library_test.dart' as export_internal_library;
 import 'export_legacy_symbol_test.dart' as export_legacy_symbol;
 import 'export_of_non_library_test.dart' as export_of_non_library;
@@ -154,6 +155,8 @@
 import 'extends_deferred_class_test.dart' as extends_deferred_class;
 import 'extends_disallowed_class_test.dart' as extends_disallowed_class;
 import 'extends_non_class_test.dart' as extends_non_class;
+import 'extends_type_alias_expands_to_type_parameter_test.dart'
+    as extends_type_alias_expands_to_type_parameter;
 import 'extension_as_expression_test.dart' as extension_as_expression;
 import 'extension_conflicting_static_and_instance_test.dart'
     as extension_conflicting_static_and_instance;
@@ -229,6 +232,8 @@
 import 'implements_disallowed_class_test.dart' as implements_disallowed_class;
 import 'implements_non_class_test.dart' as implements_non_class;
 import 'implements_super_class_test.dart' as implements_super_class;
+import 'implements_type_alias_expands_to_type_parameter_test.dart'
+    as implements_type_alias_expands_to_type_parameter;
 import 'implicit_this_reference_in_initializer_test.dart'
     as implicit_this_reference_in_initializer;
 import 'import_deferred_library_with_load_function_test.dart'
@@ -391,7 +396,11 @@
     as mixin_inherits_from_not_object;
 import 'mixin_of_disallowed_class_test.dart' as mixin_of_disallowed_class;
 import 'mixin_of_non_class_test.dart' as mixin_of_non_class;
+import 'mixin_of_type_alias_expands_to_type_parameter_test.dart'
+    as mixin_of_type_alias_expands_to_type_parameter;
 import 'mixin_on_sealed_class_test.dart' as mixin_on_sealed_class;
+import 'mixin_on_type_alias_expands_to_type_parameter_test.dart'
+    as mixin_on_type_alias_expands_to_type_parameter;
 import 'mixin_super_class_constraint_non_interface_test.dart'
     as mixin_super_class_constraint_non_interface;
 import 'mixin_with_non_class_superclass_test.dart'
@@ -776,6 +785,7 @@
     expected_one_list_type_arguments.main();
     expected_one_set_type_arguments.main();
     expected_two_map_type_arguments.main();
+    experiment_not_enabled.main();
     export_internal_library.main();
     export_legacy_symbol.main();
     export_of_non_library.main();
@@ -783,6 +793,7 @@
     extends_deferred_class.main();
     extends_disallowed_class.main();
     extends_non_class.main();
+    extends_type_alias_expands_to_type_parameter.main();
     extension_as_expression.main();
     extension_conflicting_static_and_instance.main();
     extension_declares_abstract_method.main();
@@ -828,6 +839,7 @@
     implements_disallowed_class.main();
     implements_non_class.main();
     implements_super_class.main();
+    implements_type_alias_expands_to_type_parameter.main();
     implicit_this_reference_in_initializer.main();
     import_deferred_library_with_load_function.main();
     import_internal_library.main();
@@ -931,7 +943,9 @@
     mixin_inherits_from_not_object.main();
     mixin_of_disallowed_class.main();
     mixin_of_non_class.main();
+    mixin_of_type_alias_expands_to_type_parameter.main();
     mixin_on_sealed_class.main();
+    mixin_on_type_alias_expands_to_type_parameter.main();
     mixin_super_class_constraint_non_interface.main();
     mixin_with_non_class_superclass.main();
     mixins_super_class.main();
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/typedef_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/typedef_test.dart
index fc7f670..bd6536c 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/typedef_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/typedef_test.dart
@@ -50,11 +50,11 @@
               [
                 ParserErrorCode.EXPECTED_TYPE_NAME,
                 ParserErrorCode.EXPECTED_TOKEN,
-                ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE
+                ParserErrorCode.EXPERIMENT_NOT_ENABLED
               ],
               "typedef T = _s_;",
               expectedErrorsInValidCode: [
-                ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE
+                ParserErrorCode.EXPERIMENT_NOT_ENABLED
               ],
               failing: ['functionVoid', 'functionNonVoid', 'getter', 'mixin']),
         ],
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index 1a8fcb0..4134ed6 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -182,6 +182,8 @@
       computer._addRegionForNode(name, element);
     }
     computer._addRegionForNode(node.constructorName, element);
+    // type arguments
+    node.typeArguments?.accept(this);
     // arguments
     node.arguments?.accept(this);
   }
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 761427f..aff886a 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -652,7 +652,7 @@
     }
 
     var fragmentsToLoad =
-        compiler.backendStrategy.emitterTask.emitter.fragmentsToLoad;
+        compiler.backendStrategy.emitterTask.emitter.finalizedFragmentsToLoad;
     var fragmentMerger =
         compiler.backendStrategy.emitterTask.emitter.fragmentMerger;
     result.deferredFiles = fragmentMerger.computeDeferredMap(fragmentsToLoad);
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index 4815c6d..3b14775 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -21,7 +21,7 @@
 import '../world.dart' show JClosedWorld;
 import 'program_builder/program_builder.dart';
 import 'startup_emitter/emitter.dart' as startup_js_emitter;
-import 'startup_emitter/fragment_merger.dart' as fragment_merger;
+import 'startup_emitter/fragment_merger.dart';
 
 import 'metadata_collector.dart' show MetadataCollector;
 import 'model.dart';
@@ -211,13 +211,13 @@
 abstract class Emitter implements ModularEmitter {
   Program get programForTesting;
 
-  List<fragment_merger.PreFragment> get preDeferredFragmentsForTesting;
+  List<PreFragment> get preDeferredFragmentsForTesting;
 
   /// A map of loadId to list of [FinalizedFragments].
-  Map<String, List<fragment_merger.FinalizedFragment>> get fragmentsToLoad;
+  Map<String, List<FinalizedFragment>> get finalizedFragmentsToLoad;
 
   /// The [FragmentMerger] itself.
-  fragment_merger.FragmentMerger get fragmentMerger;
+  FragmentMerger get fragmentMerger;
 
   /// Uses the [programBuilder] to generate a model of the program, emits
   /// the program, and returns the size of the generated output.
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 5a878fb..17184dd 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -160,7 +160,7 @@
   List<PreFragment> preDeferredFragmentsForTesting;
 
   @override
-  Map<String, List<FinalizedFragment>> fragmentsToLoad;
+  Map<String, List<FinalizedFragment>> finalizedFragmentsToLoad;
 
   @override
   FragmentMerger fragmentMerger;
@@ -206,9 +206,9 @@
     }
     return _task.measureSubtask('emit program', () {
       var size = _emitter.emitProgram(program, codegenWorld);
-      fragmentsToLoad = _emitter.fragmentsToLoad;
+      finalizedFragmentsToLoad = _emitter.finalizedFragmentsToLoad;
       fragmentMerger = _emitter.fragmentMerger;
-      fragmentsToLoad.values.forEach((fragments) {
+      finalizedFragmentsToLoad.values.forEach((fragments) {
         _task.metrics.hunkListElements.add(fragments.length);
       });
       if (retainDataForTesting) {
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index f5f2d9a..83ccedd 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -713,8 +713,25 @@
     var lazyInitializers = emitLazilyInitializedStatics(fragment);
     // TODO(floitsch): only call emitNativeSupport if we need native.
     var nativeSupport = emitNativeSupport(fragment);
-    return PreFragment(
-        fragment,
+    int size = 0;
+    if (estimateSize) {
+      var estimator = SizeEstimator();
+      estimator.visit(classPrototypes);
+      estimator.visit(closurePrototypes);
+      estimator.visit(inheritance);
+      estimator.visit(methodAliases);
+      estimator.visit(tearOffs);
+      estimator.visit(constants);
+      estimator.visit(typeRules);
+      estimator.visit(variances);
+      estimator.visit(staticNonFinalFields);
+      estimator.visit(lazyInitializers);
+      estimator.visit(nativeSupport);
+      size = estimator.charCount;
+    }
+    var emittedOutputUnit = EmittedOutputUnit(
+        fragment.outputUnit,
+        fragment.libraries,
         classPrototypes,
         closurePrototypes,
         inheritance,
@@ -725,8 +742,8 @@
         variances,
         staticNonFinalFields,
         lazyInitializers,
-        nativeSupport,
-        estimateSize);
+        nativeSupport);
+    return PreFragment(fragment.outputFileName, emittedOutputUnit, size);
   }
 
   js.Statement emitMainFragment(
@@ -832,8 +849,7 @@
     return new js.Block(holderInits);
   }
 
-  js.Expression emitDeferredFragment(
-      FinalizedFragment fragment, List<Holder> holders) {
+  js.Expression emitCodeFragment(CodeFragment fragment, List<Holder> holders) {
     HolderCode holderCode =
         emitHolders(holders, fragment.libraries, initializeEmptyHolders: false);
 
@@ -1876,10 +1892,11 @@
   // array of hashes indexed by part.
   // [deferredLoadHashes] may have missing entries to indicate empty parts.
   void finalizeDeferredLoadingData(
-      Map<String, List<FinalizedFragment>> fragmentsToLoad,
+      Map<String, List<CodeFragment>> codeFragmentsToLoad,
+      Map<CodeFragment, FinalizedFragment> codeFragmentMap,
       Map<FinalizedFragment, String> deferredLoadHashes,
       DeferredLoadingState deferredLoadingState) {
-    if (fragmentsToLoad.isEmpty) return;
+    if (codeFragmentsToLoad.isEmpty) return;
 
     Map<FinalizedFragment, int> fragmentIndexes = {};
     List<String> fragmentUris = [];
@@ -1887,10 +1904,11 @@
 
     List<js.Property> libraryPartsMapEntries = [];
 
-    fragmentsToLoad
-        .forEach((String loadId, List<FinalizedFragment> fragmentList) {
+    codeFragmentsToLoad
+        .forEach((String loadId, List<CodeFragment> codeFragments) {
       List<js.Expression> indexes = [];
-      for (FinalizedFragment fragment in fragmentList) {
+      for (var codeFragment in codeFragments) {
+        var fragment = codeFragmentMap[codeFragment];
         String fragmentHash = deferredLoadHashes[fragment];
         if (fragmentHash == null) continue;
         int index = fragmentIndexes[fragment];
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
index 2a80113..8eefc10 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_merger.dart
@@ -9,85 +9,172 @@
 import '../../elements/entities.dart';
 import '../../deferred_load.dart' show OutputUnit;
 import '../../js/js.dart' as js;
-import '../../js/size_estimator.dart';
 import '../../options.dart';
 import '../model.dart';
 
+/// This file contains a number of abstractions used by dart2js for emitting and
+/// merging deferred fragments.
+///
+/// The initial deferred loading algorithm breaks a program up into multiple
+/// [OutputUnits] where each [OutputUnit] represents part of the user's
+/// program. [OutputUnits] are represented by a unique intersection of imports
+/// known as an import set. Thus, each [OutputUnit] is a node in a deferred
+/// graph. Edges in this graph are dependencies between [OutputUnits].
+///
+/// [OutputUnits] have a notion of successors and predecessors, that is a
+/// successor to an [OutputUnit] is an [OutputUnit] that must be loaded first. A
+/// predecessor to an [OutputUnit] is an [OutputUnit] that must be loaded later.
+///
+/// To load some given deferred library, a list of [OutputUnits] must be loaded
+/// in the correct order, with their successors loaded first, then the given
+/// [OutputUnit], then the [OutputUnits] predecessors.
+///
+/// To give a concrete example, say our graph looks like:
+///    {a}   {b}   {c}
+///
+///     {a, b} {b, c}
+///
+///       {a, b, c}
+///
+/// Where each set above is the import set of an [OutputUnit]. We say that
+/// {a}, {b}, and {c} are root [OutputUnits], i.e. [OutputUnits] with no
+/// predecessors, and {a, b, c} is a leaf [OutputUnit], i.e. [OutputUnits]
+/// with no successors.
+///
+/// We then have three load lists:
+///   a: {a, b, c}, {a, b}, {a}
+///   b: {a, b, c}, {a, b}, {b, c}, {b}
+///   c: {a, b, c}, {b, c}, {c}
+///
+/// In all 3 load lists, {a, b, c} must be loaded first. All of the other
+/// [OutputUnits] are predecessors of {a, b, c}. {a, b, c} is a successor to all
+/// other [OutputUnits].
+///
+/// However, the dart2js deferred loading algorithm generates a very granular
+/// sparse graph of [OutputUnits] and in many cases it is desireable to coalesce
+/// smaller [OutputUnits] together into larger chunks of code to reduce the
+/// number of files which have to be sent to the client. To do this
+/// cleanly, we use various abstractions to merge [OutputUnits].
+///
+/// First, we emit the code for each [OutputUnit] into an [EmittedOutputUnit].
+/// An [EmittedOutputUnit] is the Javascript representation of an [OutputUnit].
+/// [EmittedOutputUnits] map 1:1 to [OutputUnits].
+///
+/// We wrap each [EmittedOutputUnit] in a [PreFragment], which is just a wrapper
+/// to facilitate merging of [EmittedOutputUnits]. Then, we run a merge
+/// algorithm on these [PreFragments], merging them together until some
+/// threshold.
+///
+/// Once we are finished merging [PreFragments], we must now decide on their
+/// final representation in Javascript.
+///
+/// Depending on the results of the merge, we chose one of two representations.
+/// For example, say we merge {a, b} and {a} into {a, b}+{a}. In this case our
+/// new load lists look like:
+///
+///   a: {a, b, c}, {a, b}+{a}
+///   b: {a, b, c}, {a, b}+{a}, {b, c}, {b}
+///   c: {a, b, c}, {b, c}, {c}
+///
+/// This adds a bit of extra code to the 'b' load list, but otherwise there are
+/// no problems. In this case, we will interleave [EmittedOutputUnits] into a
+/// single [CodeFragment], with a single top level initialization function. This
+/// approach results in lower overhead, because the runtime can initialize the
+/// {a, b}+{a} [CodeFragment] with a single invocation of a top level function.
+///
+/// Ideally we would interleave all [EmittedOutputUnits] in each [PreFragment]
+/// into a single [CodeFragment]. We would then write this single
+/// [CodeFragment] into a single [FinalizedFragment], where a
+/// [FinalizedFragment] is just an abstraction representing a single file on
+/// disk. Unfortunately this is not always possible to do efficiently.
+///
+/// Specifically, lets say we decide to merge {a} and {c} into {a}+{c}
+/// In this case, our load lists now look like:
+///
+///   a: {a, b, c}, {a, b}, {a}+{c}
+///   b: {a, b, c}, {a, b}, {b, c}, {b}
+///   c: {a, b, c}, {b, c}, {a}+{c}
+///
+/// Now, load lists 'a' and 'c' are invalid. Specifically, load list 'a' is
+/// missing {c}'s dependency {b, c} and load list 'c' is missing {a}'s
+/// dependency {a, b}. We could bloat both load lists with the necessary
+/// dependencies, but this would negate any performance benefit from
+/// interleaving.
+///
+/// Instead, when this happens we emit {a} and {c} into separate
+/// [CodeFragments], with separate top level initalization functions that are
+/// only called when the necessary dependencies for initialization are
+/// present. These [CodeFragments] end up in a single [FinalizedFragment].
+/// While this approach doesn't have the performance benefits of
+/// interleaving, it at least reduces the total number of files which need to be
+/// sent to the client.
+
+class EmittedOutputUnit {
+  final OutputUnit outputUnit;
+  final List<Library> libraries;
+  final js.Statement classPrototypes;
+  final js.Statement closurePrototypes;
+  final js.Statement inheritance;
+  final js.Statement methodAliases;
+  final js.Statement tearOffs;
+  final js.Statement constants;
+  final js.Statement typeRules;
+  final js.Statement variances;
+  final js.Statement staticNonFinalFields;
+  final js.Statement lazyInitializers;
+  final js.Statement nativeSupport;
+
+  EmittedOutputUnit(
+      this.outputUnit,
+      this.libraries,
+      this.classPrototypes,
+      this.closurePrototypes,
+      this.inheritance,
+      this.methodAliases,
+      this.tearOffs,
+      this.constants,
+      this.typeRules,
+      this.variances,
+      this.staticNonFinalFields,
+      this.lazyInitializers,
+      this.nativeSupport);
+
+  CodeFragment toCodeFragment(Program program) {
+    return CodeFragment(
+        [outputUnit],
+        libraries,
+        classPrototypes,
+        closurePrototypes,
+        inheritance,
+        methodAliases,
+        tearOffs,
+        constants,
+        typeRules,
+        variances,
+        staticNonFinalFields,
+        lazyInitializers,
+        nativeSupport,
+        program.metadataTypesForOutputUnit(outputUnit));
+  }
+}
+
 class PreFragment {
-  final List<DeferredFragment> fragments = [];
-  final List<js.Statement> classPrototypes = [];
-  final List<js.Statement> closurePrototypes = [];
-  final List<js.Statement> inheritance = [];
-  final List<js.Statement> methodAliases = [];
-  final List<js.Statement> tearOffs = [];
-  final List<js.Statement> constants = [];
-  final List<js.Statement> typeRules = [];
-  final List<js.Statement> variances = [];
-  final List<js.Statement> staticNonFinalFields = [];
-  final List<js.Statement> lazyInitializers = [];
-  final List<js.Statement> nativeSupport = [];
+  final String outputFileName;
+  final List<EmittedOutputUnit> emittedOutputUnits = [];
   final Set<PreFragment> successors = {};
   final Set<PreFragment> predecessors = {};
   FinalizedFragment finalizedFragment;
   int size = 0;
+  bool shouldInterleave = true;
 
   PreFragment(
-      Fragment fragment,
-      js.Statement classPrototypes,
-      js.Statement closurePrototypes,
-      js.Statement inheritance,
-      js.Statement methodAliases,
-      js.Statement tearOffs,
-      js.Statement constants,
-      js.Statement typeRules,
-      js.Statement variances,
-      js.Statement staticNonFinalFields,
-      js.Statement lazyInitializers,
-      js.Statement nativeSupport,
-      bool estimateSize) {
-    this.fragments.add(fragment);
-    this.classPrototypes.add(classPrototypes);
-    this.closurePrototypes.add(closurePrototypes);
-    this.inheritance.add(inheritance);
-    this.methodAliases.add(methodAliases);
-    this.tearOffs.add(tearOffs);
-    this.constants.add(constants);
-    this.typeRules.add(typeRules);
-    this.variances.add(variances);
-    this.staticNonFinalFields.add(staticNonFinalFields);
-    this.lazyInitializers.add(lazyInitializers);
-    this.nativeSupport.add(nativeSupport);
-    if (estimateSize) {
-      var estimator = SizeEstimator();
-      estimator.visit(classPrototypes);
-      estimator.visit(closurePrototypes);
-      estimator.visit(inheritance);
-      estimator.visit(methodAliases);
-      estimator.visit(tearOffs);
-      estimator.visit(constants);
-      estimator.visit(typeRules);
-      estimator.visit(variances);
-      estimator.visit(staticNonFinalFields);
-      estimator.visit(lazyInitializers);
-      estimator.visit(nativeSupport);
-      size = estimator.charCount;
-    }
+      this.outputFileName, EmittedOutputUnit emittedOutputUnit, this.size) {
+    emittedOutputUnits.add(emittedOutputUnit);
   }
 
   PreFragment mergeAfter(PreFragment that) {
     assert(this != that);
-    this.fragments.addAll(that.fragments);
-    this.classPrototypes.addAll(that.classPrototypes);
-    this.closurePrototypes.addAll(that.closurePrototypes);
-    this.inheritance.addAll(that.inheritance);
-    this.methodAliases.addAll(that.methodAliases);
-    this.tearOffs.addAll(that.tearOffs);
-    this.constants.addAll(that.constants);
-    this.typeRules.addAll(that.typeRules);
-    this.variances.addAll(that.variances);
-    this.staticNonFinalFields.addAll(that.staticNonFinalFields);
-    this.lazyInitializers.addAll(that.lazyInitializers);
-    this.nativeSupport.addAll(that.nativeSupport);
+    this.emittedOutputUnits.addAll(that.emittedOutputUnits);
     this.successors.remove(that);
     this.predecessors.remove(that);
     that.successors.forEach((fragment) {
@@ -107,46 +194,46 @@
     return this;
   }
 
-  FinalizedFragment finalize(
-      Program program, Map<OutputUnit, FinalizedFragment> outputUnitMap) {
-    assert(finalizedFragment == null);
-    var seedFragment = fragments.first;
-    var seedOutputUnit = seedFragment.outputUnit;
-
-    // If we only have a single fragment, then wen just finalize it by itself.
-    // Otherwise, we finalize an entire group of fragments into a single
-    // merged and finalized fragment.
-    if (fragments.length == 1) {
-      finalizedFragment = FinalizedFragment(
-          seedFragment.outputFileName,
-          [seedOutputUnit],
-          seedFragment.libraries,
-          classPrototypes.first,
-          closurePrototypes.first,
-          inheritance.first,
-          methodAliases.first,
-          tearOffs.first,
-          constants.first,
-          typeRules.first,
-          variances.first,
-          staticNonFinalFields.first,
-          lazyInitializers.first,
-          nativeSupport.first,
-          program.metadataTypesForOutputUnit(seedOutputUnit));
-      outputUnitMap[seedOutputUnit] = finalizedFragment;
+  /// Interleaves the [EmittedOutputUnits] into a single [CodeFragment].
+  CodeFragment interleaveEmittedOutputUnits(Program program) {
+    var seedEmittedOutputUnit = emittedOutputUnits.first;
+    if (emittedOutputUnits.length == 1) {
+      return seedEmittedOutputUnit.toCodeFragment(program);
     } else {
-      List<OutputUnit> outputUnits = [seedOutputUnit];
+      var seedOutputUnit = seedEmittedOutputUnit.outputUnit;
       List<Library> libraries = [];
-      for (var fragment in fragments) {
-        var fragmentOutputUnit = fragment.outputUnit;
-        if (seedOutputUnit != fragmentOutputUnit) {
-          program.mergeOutputUnitMetadata(seedOutputUnit, fragmentOutputUnit);
-          outputUnits.add(fragmentOutputUnit);
+      List<OutputUnit> outputUnits = [seedOutputUnit];
+      List<js.Statement> classPrototypes = [];
+      List<js.Statement> closurePrototypes = [];
+      List<js.Statement> inheritance = [];
+      List<js.Statement> methodAliases = [];
+      List<js.Statement> tearOffs = [];
+      List<js.Statement> constants = [];
+      List<js.Statement> typeRules = [];
+      List<js.Statement> variances = [];
+      List<js.Statement> staticNonFinalFields = [];
+      List<js.Statement> lazyInitializers = [];
+      List<js.Statement> nativeSupport = [];
+      for (var emittedOutputUnit in emittedOutputUnits) {
+        var thatOutputUnit = emittedOutputUnit.outputUnit;
+        if (seedOutputUnit != thatOutputUnit) {
+          program.mergeOutputUnitMetadata(seedOutputUnit, thatOutputUnit);
+          outputUnits.add(thatOutputUnit);
         }
-        libraries.addAll(fragment.libraries);
+        libraries.addAll(emittedOutputUnit.libraries);
+        classPrototypes.add(emittedOutputUnit.classPrototypes);
+        closurePrototypes.add(emittedOutputUnit.closurePrototypes);
+        inheritance.add(emittedOutputUnit.inheritance);
+        methodAliases.add(emittedOutputUnit.methodAliases);
+        tearOffs.add(emittedOutputUnit.tearOffs);
+        constants.add(emittedOutputUnit.constants);
+        typeRules.add(emittedOutputUnit.typeRules);
+        variances.add(emittedOutputUnit.variances);
+        staticNonFinalFields.add(emittedOutputUnit.staticNonFinalFields);
+        lazyInitializers.add(emittedOutputUnit.lazyInitializers);
+        nativeSupport.add(emittedOutputUnit.nativeSupport);
       }
-      finalizedFragment = FinalizedFragment(
-          seedFragment.outputFileName,
+      return CodeFragment(
           outputUnits,
           libraries,
           js.Block(classPrototypes),
@@ -161,10 +248,36 @@
           js.Block(lazyInitializers),
           js.Block(nativeSupport),
           program.metadataTypesForOutputUnit(seedOutputUnit));
-      for (var outputUnit in outputUnits) {
-        outputUnitMap[outputUnit] = finalizedFragment;
-      }
     }
+  }
+
+  /// Bundles [EmittedOutputUnits] into multiple [CodeFragments].
+  List<CodeFragment> bundleEmittedOutputUnits(Program program) {
+    List<CodeFragment> codeFragments = [];
+    for (var emittedOutputUnit in emittedOutputUnits) {
+      codeFragments.add(emittedOutputUnit.toCodeFragment(program));
+    }
+    return codeFragments;
+  }
+
+  /// Finalizes this [PreFragment] into a single [FinalizedFragment] by either
+  /// interleaving [EmittedOutputUnits] into a single [CodeFragment] or by
+  /// bundling [EmittedOutputUnits] into multiple [CodeFragments].
+  FinalizedFragment finalize(
+      Program program,
+      Map<OutputUnit, CodeFragment> outputUnitMap,
+      Map<CodeFragment, FinalizedFragment> codeFragmentMap) {
+    assert(finalizedFragment == null);
+    List<CodeFragment> codeFragments = shouldInterleave
+        ? [interleaveEmittedOutputUnits(program)]
+        : bundleEmittedOutputUnits(program);
+    finalizedFragment = FinalizedFragment(outputFileName, codeFragments);
+    codeFragments.forEach((codeFragment) {
+      codeFragmentMap[codeFragment] = finalizedFragment;
+      codeFragment.outputUnits.forEach((outputUnit) {
+        outputUnitMap[outputUnit] = codeFragment;
+      });
+    });
     return finalizedFragment;
   }
 
@@ -181,13 +294,10 @@
   }
 
   String debugName() {
-    List<String> names = [];
-    this.fragments.forEach(
-        (fragment) => names.add(fragment.outputUnit.imports.toString()));
     var outputUnitStrings = [];
-    for (var fragment in fragments) {
+    for (var emittedOutputUnit in emittedOutputUnits) {
       var importString = [];
-      for (var import in fragment.outputUnit.imports) {
+      for (var import in emittedOutputUnit.outputUnit.imports) {
         importString.add(import.name);
       }
       outputUnitStrings.add('{${importString.join(', ')}}');
@@ -198,26 +308,14 @@
   /// Clears all [PreFragment] data structure and zeros out the size. Should be
   /// used only after merging to GC internal data structures.
   void clearAll() {
-    fragments.clear();
-    classPrototypes.clear();
-    closurePrototypes.clear();
-    inheritance.clear();
-    methodAliases.clear();
-    tearOffs.clear();
-    constants.clear();
-    typeRules.clear();
-    variances.clear();
-    staticNonFinalFields.clear();
-    lazyInitializers.clear();
-    nativeSupport.clear();
+    emittedOutputUnits.clear();
     successors.clear();
     predecessors.clear();
     size = 0;
   }
 }
 
-class FinalizedFragment {
-  final String outputFileName;
+class CodeFragment {
   final List<OutputUnit> outputUnits;
   final List<Library> libraries;
   final js.Statement classPrototypes;
@@ -233,8 +331,7 @@
   final js.Statement nativeSupport;
   final js.Expression deferredTypes;
 
-  FinalizedFragment(
-      this.outputFileName,
+  CodeFragment(
       this.outputUnits,
       this.libraries,
       this.classPrototypes,
@@ -279,11 +376,40 @@
         isEmptyStatement(nativeSupport);
   }
 
+  @override
+  String toString() {
+    List<String> outputUnitStrings = [];
+    for (var outputUnit in outputUnits) {
+      List<String> importStrings = [];
+      for (var import in outputUnit.imports) {
+        importStrings.add(import.name);
+      }
+      outputUnitStrings.add('{${importStrings.join(', ')}}');
+    }
+    return outputUnitStrings.join('+');
+  }
+}
+
+class FinalizedFragment {
+  final String outputFileName;
+  final List<CodeFragment> codeFragments;
+
+  FinalizedFragment(this.outputFileName, this.codeFragments);
+
   // The 'main' [OutputUnit] for this [FinalizedFragment].
   // TODO(joshualitt): Refactor this to more clearly disambiguate between
   // [OutputUnits](units of deferred merging), fragments(units of emitted code),
   // and files.
-  OutputUnit get canonicalOutputUnit => outputUnits.first;
+  OutputUnit get canonicalOutputUnit => codeFragments.first.outputUnits.first;
+
+  @override
+  String toString() {
+    List<String> strings = [];
+    for (var codeFragment in codeFragments) {
+      strings.add(codeFragment.toString());
+    }
+    return 'FinalizedFragment([${strings.join(', ')}])';
+  }
 }
 
 class _Partition {
@@ -305,26 +431,37 @@
 
   FragmentMerger(this._options, this._elementEnvironment, this.outputUnitData);
 
-  // Converts a map of (loadId, List<OutputUnit>) to a map of
-  // (loadId, List<FinalizedFragment>).
-  Map<String, List<FinalizedFragment>> computeFragmentsToLoad(
+  // Converts a map of (loadId, List<OutputUnit>) to two maps.
+  // The first is a map of (loadId, List<FinalizedFragment>), which is used to
+  // compute which files need to be loaded for a given loadId.
+  // The second is a map of (loadId, List<CodeFragment>) which is used to
+  // compute which CodeFragments need to be loaded for a given loadId.
+  void computeFragmentsToLoad(
       Map<String, List<OutputUnit>> outputUnitsToLoad,
-      Map<OutputUnit, FinalizedFragment> outputUnitMap,
-      Set<OutputUnit> omittedOutputUnits) {
-    Map<String, List<FinalizedFragment>> fragmentsToLoad = {};
+      Map<OutputUnit, CodeFragment> outputUnitMap,
+      Map<CodeFragment, FinalizedFragment> codeFragmentMap,
+      Set<OutputUnit> omittedOutputUnits,
+      Map<String, List<CodeFragment>> codeFragmentsToLoad,
+      Map<String, List<FinalizedFragment>> finalizedFragmentsToLoad) {
     outputUnitsToLoad.forEach((loadId, outputUnits) {
-      Set<FinalizedFragment> unique = {};
+      Set<CodeFragment> uniqueCodeFragments = {};
+      Set<FinalizedFragment> uniqueFinalizedFragments = {};
       List<FinalizedFragment> finalizedFragments = [];
-      fragmentsToLoad[loadId] = finalizedFragments;
+      List<CodeFragment> codeFragments = [];
       for (var outputUnit in outputUnits) {
         if (omittedOutputUnits.contains(outputUnit)) continue;
-        var finalizedFragment = outputUnitMap[outputUnit];
-        if (unique.add(finalizedFragment)) {
+        var codeFragment = outputUnitMap[outputUnit];
+        if (uniqueCodeFragments.add(codeFragment)) {
+          codeFragments.add(codeFragment);
+        }
+        var finalizedFragment = codeFragmentMap[codeFragment];
+        if (uniqueFinalizedFragments.add(finalizedFragment)) {
           finalizedFragments.add(finalizedFragment);
         }
       }
+      codeFragmentsToLoad[loadId] = codeFragments;
+      finalizedFragmentsToLoad[loadId] = finalizedFragments;
     });
-    return fragmentsToLoad;
   }
 
   /// Given a list of OutputUnits sorted by their import entites,
@@ -364,24 +501,21 @@
   /// Attachs predecessors and successors to each PreFragment.
   /// Expects outputUnits to be sorted.
   void attachDependencies(
-      List<OutputUnit> outputUnits,
-      Map<Fragment, PreFragment> fragmentMap,
-      List<PreFragment> preDeferredFragments) {
+      List<OutputUnit> outputUnits, List<PreFragment> preDeferredFragments) {
     // Create a map of OutputUnit to Fragment.
-    Map<OutputUnit, Fragment> outputUnitMap = {};
+    Map<OutputUnit, PreFragment> outputUnitMap = {};
     for (var preFragment in preDeferredFragments) {
-      var fragment = preFragment.fragments.single;
-      var outputUnit = fragment.outputUnit;
-      outputUnitMap[outputUnit] = fragment;
+      var outputUnit = preFragment.emittedOutputUnits.single.outputUnit;
+      outputUnitMap[outputUnit] = preFragment;
       totalSize += preFragment.size;
     }
 
     // Get a list of direct edges and then attach them to PreFragments.
     var allEdges = createDirectEdges(outputUnits);
     allEdges.forEach((outputUnit, edges) {
-      var predecessor = fragmentMap[outputUnitMap[outputUnit]];
+      var predecessor = outputUnitMap[outputUnit];
       for (var edge in edges) {
-        var successor = fragmentMap[outputUnitMap[edge]];
+        var successor = outputUnitMap[edge];
         predecessor.successors.add(successor);
         successor.predecessors.add(predecessor);
       }
@@ -411,8 +545,8 @@
         // Sort the fragments in the component so they will be in a canonical
         // order.
         component.sort((a, b) {
-          return a.fragments.single.outputUnit
-              .compareTo(b.fragments.single.outputUnit);
+          return a.emittedOutputUnits.single.outputUnit
+              .compareTo(b.emittedOutputUnits.single.outputUnit);
         });
         components.add(component);
       }
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index a7c42ad..97b7f0d 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -52,6 +52,7 @@
 import '../../io/source_information.dart';
 import '../../io/source_map_builder.dart' show SourceMapBuilder;
 import '../../js/js.dart' as js;
+import '../../js/size_estimator.dart';
 import '../../js_backend/js_backend.dart'
     show Namer, ConstantEmitter, StringBackedName;
 import '../../js_backend/js_interop_analysis.dart' as jsInteropAnalysis;
@@ -84,6 +85,13 @@
 
 part 'fragment_emitter.dart';
 
+class EmittedCodeFragment {
+  final CodeFragment codeFragment;
+  final js.Expression code;
+
+  EmittedCodeFragment(this.codeFragment, this.code);
+}
+
 class ModelEmitter {
   final CompilerOptions _options;
   final DiagnosticReporter _reporter;
@@ -114,7 +122,11 @@
   /// [lib1]]} would mean that in order to load "lib1" first the hunk
   /// lib1_lib2_lib2 should be loaded, then the hunks lib1_lib2 and lib1_lib3
   /// can be loaded in parallel. And fially lib1 can be loaded.
-  Map<String, List<FinalizedFragment>> fragmentsToLoad;
+  final Map<String, List<FinalizedFragment>> finalizedFragmentsToLoad = {};
+
+  /// Similar to the above map, but more granular as each [FinalizedFragment]
+  /// may have multiple CodeFragments.
+  final Map<String, List<CodeFragment>> codeFragmentsToLoad = {};
 
   /// For deferred loading we communicate the initializers via this global var.
   static const String deferredInitializersGlobal =
@@ -226,12 +238,10 @@
     // In order to get size estimates, we partially emit deferred fragments.
     List<OutputUnit> outputUnits = [];
     List<PreFragment> preDeferredFragments = [];
-    Map<DeferredFragment, PreFragment> preFragmentMap = {};
     _task.measureSubtask('emit prefragments', () {
       for (var fragment in deferredFragments) {
         var preFragment =
             fragmentEmitter.emitPreFragment(fragment, shouldMergeFragments);
-        preFragmentMap[fragment] = preFragment;
         outputUnits.add(fragment.outputUnit);
         preDeferredFragments.add(preFragment);
       }
@@ -247,8 +257,7 @@
     // and merge.
     if (shouldMergeFragments) {
       preDeferredFragments = _task.measureSubtask('merge fragments', () {
-        fragmentMerger.attachDependencies(
-            outputUnits, preFragmentMap, preDeferredFragments);
+        fragmentMerger.attachDependencies(outputUnits, preDeferredFragments);
         return fragmentMerger.mergeFragments(preDeferredFragments);
       });
     }
@@ -259,33 +268,47 @@
     }
 
     // Finalize and emit fragments.
-    Map<OutputUnit, FinalizedFragment> outputUnitMap = {};
-    Map<FinalizedFragment, js.Expression> deferredFragmentsCode = {};
+    Map<OutputUnit, CodeFragment> outputUnitMap = {};
+    Map<CodeFragment, FinalizedFragment> codeFragmentMap = {};
+    Map<FinalizedFragment, EmittedCodeFragment> deferredFragmentsCode = {};
     for (var preDeferredFragment in preDeferredFragments) {
       var finalizedFragment =
-          preDeferredFragment.finalize(program, outputUnitMap);
-      js.Expression fragmentCode = fragmentEmitter.emitDeferredFragment(
-          finalizedFragment, program.holders);
+          preDeferredFragment.finalize(program, outputUnitMap, codeFragmentMap);
+      // TODO(joshualitt): Support bundling.
+      assert(finalizedFragment.codeFragments.length == 1);
+      var codeFragment = finalizedFragment.codeFragments.single;
+      js.Expression fragmentCode =
+          fragmentEmitter.emitCodeFragment(codeFragment, program.holders);
       if (fragmentCode != null) {
-        deferredFragmentsCode[finalizedFragment] = fragmentCode;
+        deferredFragmentsCode[finalizedFragment] =
+            EmittedCodeFragment(codeFragment, fragmentCode);
       } else {
-        omittedOutputUnits.addAll(finalizedFragment.outputUnits);
+        finalizedFragment.codeFragments.forEach((codeFragment) {
+          omittedOutputUnits.addAll(codeFragment.outputUnits);
+        });
       }
     }
 
     // With all deferred fragments finalized, we can now compute a map of
     // loadId to the files(FinalizedFragments) which need to be loaded.
-    fragmentsToLoad = fragmentMerger.computeFragmentsToLoad(
-        outputUnitsToLoad, outputUnitMap, omittedOutputUnits);
+    fragmentMerger.computeFragmentsToLoad(
+        outputUnitsToLoad,
+        outputUnitMap,
+        codeFragmentMap,
+        omittedOutputUnits,
+        codeFragmentsToLoad,
+        finalizedFragmentsToLoad);
 
     // Emit main Fragment.
     var deferredLoadingState = new DeferredLoadingState();
     js.Statement mainCode = fragmentEmitter.emitMainFragment(
-        program, fragmentsToLoad, deferredLoadingState);
+        program, finalizedFragmentsToLoad, deferredLoadingState);
 
     // Count tokens and run finalizers.
     js.TokenCounter counter = new js.TokenCounter();
-    deferredFragmentsCode.values.forEach(counter.countTokens);
+    deferredFragmentsCode.values.forEach((emittedCodeFragment) {
+      counter.countTokens(emittedCodeFragment.code);
+    });
     counter.countTokens(mainCode);
 
     program.finalizers.forEach((js.TokenFinalizer f) => f.finalizeTokens());
@@ -302,7 +325,7 @@
     // Now that we have written the deferred hunks, we can create the deferred
     // loading data.
     fragmentEmitter.finalizeDeferredLoadingData(
-        fragmentsToLoad, hunkHashes, deferredLoadingState);
+        codeFragmentsToLoad, codeFragmentMap, hunkHashes, deferredLoadingState);
 
     _task.measureSubtask('write fragments', () {
       writeMainFragment(mainFragment, mainCode,
@@ -346,11 +369,13 @@
   ///
   /// Updates the shared [outputBuffers] field with the output.
   Map<FinalizedFragment, String> writeDeferredFragments(
-      Map<FinalizedFragment, js.Expression> fragmentsCode) {
+      Map<FinalizedFragment, EmittedCodeFragment> fragmentsCode) {
     Map<FinalizedFragment, String> hunkHashes = {};
 
-    fragmentsCode.forEach((FinalizedFragment fragment, js.Expression code) {
-      hunkHashes[fragment] = writeDeferredFragment(fragment, code);
+    fragmentsCode.forEach(
+        (FinalizedFragment fragment, EmittedCodeFragment emittedCodeFragment) {
+      hunkHashes[fragment] =
+          writeDeferredFragment(fragment, emittedCodeFragment.code);
     });
 
     return hunkHashes;
@@ -523,7 +548,7 @@
     // data.
     mapping["_comment"] = "This mapping shows which compiled `.js` files are "
         "needed for a given deferred library import.";
-    mapping.addAll(fragmentMerger.computeDeferredMap(fragmentsToLoad));
+    mapping.addAll(fragmentMerger.computeDeferredMap(finalizedFragmentsToLoad));
     _outputProvider.createOutputSink(
         _options.deferredMapUri.path, '', OutputType.deferredMap)
       ..add(const JsonEncoder.withIndent("  ").convert(mapping))
diff --git a/pkg/compiler/test/deferred/load_graph_segmentation_test.dart b/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
index 660e27b..823899f 100644
--- a/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
+++ b/pkg/compiler/test/deferred/load_graph_segmentation_test.dart
@@ -18,7 +18,9 @@
 List<OutputUnit> collectOutputUnits(List<FinalizedFragment> fragments) {
   List<OutputUnit> outputUnits = [];
   for (var fragment in fragments) {
-    outputUnits.addAll(fragment.outputUnits);
+    for (var codeFragment in fragment.codeFragments) {
+      outputUnits.addAll(codeFragment.outputUnits);
+    }
   }
   return outputUnits;
 }
@@ -68,7 +70,8 @@
     // InputElement is native, so it should be in the mainOutputUnit.
     Expect.equals(mainOutputUnit, outputUnitForClass(inputElement));
 
-    var hunksToLoad = backendStrategy.emitterTask.emitter.fragmentsToLoad;
+    var hunksToLoad =
+        backendStrategy.emitterTask.emitter.finalizedFragmentsToLoad;
     var hunksLib1 = collectOutputUnits(hunksToLoad["lib1"]);
     var hunksLib2 = collectOutputUnits(hunksToLoad["lib2"]);
     var hunksLib4_1 = collectOutputUnits(hunksToLoad["lib4_1"]);
diff --git a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
index 2e74934..374d091 100644
--- a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
+++ b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
@@ -155,7 +155,7 @@
     List<PreFragment> preDeferredFragments = compiler
         .backendStrategy.emitterTask.emitter.preDeferredFragmentsForTesting;
     Map<String, List<FinalizedFragment>> fragmentsToLoad =
-        compiler.backendStrategy.emitterTask.emitter.fragmentsToLoad;
+        compiler.backendStrategy.emitterTask.emitter.finalizedFragmentsToLoad;
     Map<String, List<PreFragment>> preFragmentMap =
         buildPreFragmentMap(fragmentsToLoad, preDeferredFragments);
     PreFragmentsIrComputer(compiler.reporter, actualMap, preFragmentMap)
@@ -213,8 +213,8 @@
         }
       }
 
-      for (var fragment in preFragment.fragments) {
-        supplied.add(fragment.outputUnit);
+      for (var emittedOutputUnit in preFragment.emittedOutputUnits) {
+        supplied.add(emittedOutputUnit.outputUnit);
       }
       var suppliedString = '[${supplied.map(outputUnitString).join(', ')}]';
       features.addElement(Tags.outputUnits,
diff --git a/pkg/dartdev/lib/src/commands/create.dart b/pkg/dartdev/lib/src/commands/create.dart
index 26d6576..58dbb4f 100644
--- a/pkg/dartdev/lib/src/commands/create.dart
+++ b/pkg/dartdev/lib/src/commands/create.dart
@@ -8,10 +8,10 @@
 import 'dart:math' as math;
 
 import 'package:path/path.dart' as p;
-import 'package:stagehand/stagehand.dart' as stagehand;
 
 import '../core.dart';
 import '../sdk.dart';
+import '../templates.dart';
 
 /// A command to create a new project from a set of templates.
 class CreateCommand extends DartdevCommand {
@@ -19,18 +19,8 @@
 
   static String defaultTemplateId = 'console-simple';
 
-  static List<String> legalTemplateIds = [
-    'console-simple',
-    'console-full',
-    'package-simple',
-    'web-simple'
-  ];
-
-  static Iterable<stagehand.Generator> get generators =>
-      legalTemplateIds.map(retrieveTemplateGenerator);
-
-  static stagehand.Generator retrieveTemplateGenerator(String templateId) =>
-      stagehand.getGenerator(templateId);
+  static final List<String> legalTemplateIds =
+      generators.map((generator) => generator.id).toList();
 
   CreateCommand({bool verbose = false})
       : super(cmdName, 'Create a new Dart project.') {
@@ -91,8 +81,8 @@
     );
     log.stdout('');
 
-    var generator = retrieveTemplateGenerator(templateId);
-    await generator.generate(
+    var generator = getGenerator(templateId);
+    generator.generate(
       p.basename(dir),
       DirectoryGeneratorTarget(generator, io.Directory(dir)),
     );
@@ -151,7 +141,7 @@
   }
 
   String _availableTemplatesJson() {
-    var items = generators.map((stagehand.Generator generator) {
+    var items = generators.map((Generator generator) {
       var m = {
         'name': generator.id,
         'label': generator.label,
@@ -171,8 +161,8 @@
   }
 }
 
-class DirectoryGeneratorTarget extends stagehand.GeneratorTarget {
-  final stagehand.Generator generator;
+class DirectoryGeneratorTarget extends GeneratorTarget {
+  final Generator generator;
   final io.Directory dir;
 
   DirectoryGeneratorTarget(this.generator, this.dir) {
@@ -180,13 +170,13 @@
   }
 
   @override
-  Future createFile(String path, List<int> contents) async {
+  void createFile(String path, List<int> contents) {
     io.File file = io.File(p.join(dir.path, path));
 
     String name = p.relative(file.path, from: dir.path);
     log.stdout('  $name');
 
-    await file.create(recursive: true);
-    await file.writeAsBytes(contents);
+    file.createSync(recursive: true);
+    file.writeAsBytesSync(contents);
   }
 }
diff --git a/pkg/dartdev/lib/src/templates.dart b/pkg/dartdev/lib/src/templates.dart
new file mode 100644
index 0000000..0b5aa0d
--- /dev/null
+++ b/pkg/dartdev/lib/src/templates.dart
@@ -0,0 +1,195 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert' show utf8;
+
+import 'package:meta/meta.dart';
+
+import 'templates/console_full.dart';
+import 'templates/console_simple.dart';
+import 'templates/package_simple.dart';
+import 'templates/server_simple.dart';
+import 'templates/web_simple.dart';
+
+final _substituteRegExp = RegExp(r'__([a-zA-Z]+)__');
+final _nonValidSubstituteRegExp = RegExp('[^a-zA-Z]');
+
+final List<Generator> generators = [
+  ConsoleSimpleGenerator(),
+  ConsoleFullGenerator(),
+  PackageSimpleGenerator(),
+  ServerSimpleGenerator(),
+  WebSimpleGenerator(),
+];
+
+Generator getGenerator(String id) =>
+    generators.firstWhere((g) => g.id == id, orElse: () => null);
+
+/// An abstract class which both defines a template generator and can generate a
+/// user project based on this template.
+abstract class Generator implements Comparable<Generator> {
+  final String id;
+  final String label;
+  final String description;
+  final List<String> categories;
+
+  final List<TemplateFile> files = [];
+  TemplateFile _entrypoint;
+
+  Generator(
+    this.id,
+    this.label,
+    this.description, {
+    this.categories = const [],
+  });
+
+  /// The entrypoint of the application; the main file for the project, which an
+  /// IDE might open after creating the project.
+  TemplateFile get entrypoint => _entrypoint;
+
+  TemplateFile addFile(String path, String contents) {
+    return addTemplateFile(TemplateFile(path, contents));
+  }
+
+  /// Add a new template file.
+  TemplateFile addTemplateFile(TemplateFile file) {
+    files.add(file);
+    return file;
+  }
+
+  /// Return the template file wih the given [path].
+  TemplateFile getFile(String path) =>
+      files.firstWhere((file) => file.path == path, orElse: () => null);
+
+  /// Set the main entrypoint of this template. This is the 'most important'
+  /// file of this template. An IDE might use this information to open this file
+  /// after the user's project is generated.
+  void setEntrypoint(TemplateFile entrypoint) {
+    if (_entrypoint != null) throw StateError('entrypoint already set');
+    if (entrypoint == null) throw StateError('entrypoint is null');
+    _entrypoint = entrypoint;
+  }
+
+  void generate(
+    String projectName,
+    GeneratorTarget target, {
+    Map<String, String> additionalVars,
+  }) {
+    final vars = {
+      'projectName': projectName,
+      'description': description,
+      'year': DateTime.now().year.toString(),
+      'author': '<your name>',
+      if (additionalVars != null) ...additionalVars,
+    };
+
+    for (TemplateFile file in files) {
+      final resultFile = file.runSubstitution(vars);
+      final filePath = resultFile.path;
+      target.createFile(filePath, resultFile.content);
+    }
+  }
+
+  int numFiles() => files.length;
+
+  @override
+  int compareTo(Generator other) =>
+      id.toLowerCase().compareTo(other.id.toLowerCase());
+
+  /// Return some user facing instructions about how to finish installation of
+  /// the template.
+  String getInstallInstructions() => '';
+
+  @override
+  String toString() => '[$id: $description]';
+}
+
+/// An abstract implementation of a [Generator].
+abstract class DefaultGenerator extends Generator {
+  DefaultGenerator(
+    String id,
+    String label,
+    String description, {
+    List<String> categories = const [],
+  }) : super(id, label, description, categories: categories);
+}
+
+/// A target for a [Generator]. This class knows how to create files given a
+/// path for the file (relative to the particular [GeneratorTarget] instance),
+/// and the binary content for the file.
+abstract class GeneratorTarget {
+  /// Create a file at the given path with the given contents.
+  void createFile(String path, List<int> contents);
+}
+
+/// This class represents a file in a generator template. The contents could
+/// either be binary or text. If text, the contents may contain mustache
+/// variables that can be substituted (`__myVar__`).
+class TemplateFile {
+  final String path;
+  final String content;
+
+  TemplateFile(this.path, this.content);
+
+  FileContents runSubstitution(Map<String, String> parameters) {
+    if (path == 'pubspec.yaml' && parameters['author'] == '<your name>') {
+      parameters = Map.from(parameters);
+      parameters['author'] = 'Your Name';
+    }
+
+    final newPath = substituteVars(path, parameters);
+    final newContents = _createContent(parameters);
+
+    return FileContents(newPath, newContents);
+  }
+
+  List<int> _createContent(Map<String, String> vars) {
+    return utf8.encode(substituteVars(content, vars));
+  }
+}
+
+class FileContents {
+  final String path;
+  final List<int> content;
+
+  FileContents(this.path, this.content);
+}
+
+/// Given a `String` [str] with mustache templates, and a [Map] of String key /
+/// value pairs, substitute all instances of `__key__` for `value`. I.e.,
+///
+/// ```
+/// Foo __projectName__ baz.
+/// ```
+///
+/// and
+///
+/// ```
+/// {'projectName': 'bar'}
+/// ```
+///
+/// becomes:
+///
+/// ```
+/// Foo bar baz.
+/// ```
+///
+/// A key value can only be an ASCII string made up of letters: A-Z, a-z.
+/// No whitespace, numbers, or other characters are allowed.
+@visibleForTesting
+String substituteVars(String str, Map<String, String> vars) {
+  if (vars.keys.any((element) => element.contains(_nonValidSubstituteRegExp))) {
+    throw ArgumentError('vars.keys can only contain letters.');
+  }
+
+  return str.replaceAllMapped(_substituteRegExp, (match) {
+    final item = vars[match[1]];
+
+    if (item == null) {
+      return match[0];
+    } else {
+      return item;
+    }
+  });
+}
diff --git a/pkg/dartdev/lib/src/templates/common.dart b/pkg/dartdev/lib/src/templates/common.dart
new file mode 100644
index 0000000..b849fdd
--- /dev/null
+++ b/pkg/dartdev/lib/src/templates/common.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+final String gitignore = '''
+# Files and directories created by pub.
+.dart_tool/
+.packages
+
+# Conventional directory for build output.
+build/
+''';
+
+final String analysisOptions = '''
+# Defines a default set of lint rules enforced for projects at Google. For
+# details and rationale, see
+# https://github.com/dart-lang/pedantic#enabled-lints.
+
+include: package:pedantic/analysis_options.yaml
+
+# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.
+
+# Uncomment to specify additional rules.
+# linter:
+#   rules:
+#     - camel_case_types
+
+# analyzer:
+#   exclude:
+#     - path/to/excluded/files/**
+''';
+
+final String changelog = '''
+## 1.0.0
+
+- Initial version.
+''';
diff --git a/pkg/dartdev/lib/src/templates/console_full.dart b/pkg/dartdev/lib/src/templates/console_full.dart
new file mode 100644
index 0000000..78e1670
--- /dev/null
+++ b/pkg/dartdev/lib/src/templates/console_full.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 '../templates.dart';
+import 'common.dart' as common;
+
+/// A generator for a hello world command-line application.
+class ConsoleFullGenerator extends DefaultGenerator {
+  ConsoleFullGenerator()
+      : super('console-full', 'Console Application',
+            'A command-line application sample.',
+            categories: const ['dart', 'console']) {
+    addFile('.gitignore', common.gitignore);
+    addFile('analysis_options.yaml', common.analysisOptions);
+    addFile('CHANGELOG.md', common.changelog);
+    addFile('pubspec.yaml', _pubspec);
+    addFile('README.md', _readme);
+    setEntrypoint(
+      addFile('bin/__projectName__.dart', _mainDart),
+    );
+    addFile('lib/__projectName__.dart', _libDart);
+    addFile('test/__projectName___test.dart', _testDart);
+  }
+
+  @override
+  String getInstallInstructions() => '${super.getInstallInstructions()}\n'
+      'run your app using `dart ${entrypoint.path}`.';
+}
+
+final String _pubspec = '''
+name: __projectName__
+description: A sample command-line application.
+version: 1.0.0
+# homepage: https://www.example.com
+
+environment:
+  sdk: '>=2.12.0 <3.0.0'
+
+# dependencies:
+#   path: ^1.8.0
+
+dev_dependencies:
+  pedantic: ^1.10.0
+  test: ^1.16.0
+''';
+
+final String _readme = '''
+A sample command-line application with an entrypoint in `bin/`, library code
+in `lib/`, and example unit test in `test/`.
+''';
+
+final String _mainDart = r'''
+import 'package:__projectName__/__projectName__.dart' as __projectName__;
+
+void main(List<String> arguments) {
+  print('Hello world: ${__projectName__.calculate()}!');
+}
+''';
+
+final String _libDart = '''
+int calculate() {
+  return 6 * 7;
+}
+''';
+
+final String _testDart = '''
+import 'package:__projectName__/__projectName__.dart';
+import 'package:test/test.dart';
+
+void main() {
+  test('calculate', () {
+    expect(calculate(), 42);
+  });
+}
+''';
diff --git a/pkg/dartdev/lib/src/templates/console_simple.dart b/pkg/dartdev/lib/src/templates/console_simple.dart
new file mode 100644
index 0000000..15384c6
--- /dev/null
+++ b/pkg/dartdev/lib/src/templates/console_simple.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 '../templates.dart';
+import 'common.dart' as common;
+
+/// A generator for a simple command-line application.
+class ConsoleSimpleGenerator extends DefaultGenerator {
+  ConsoleSimpleGenerator()
+      : super('console-simple', 'Simple Console Application',
+            'A simple command-line application.',
+            categories: const ['dart', 'console']) {
+    addFile('.gitignore', common.gitignore);
+    addFile('analysis_options.yaml', common.analysisOptions);
+    addFile('CHANGELOG.md', common.changelog);
+    addFile('pubspec.yaml', _pubspec);
+    addFile('README.md', _readme);
+    setEntrypoint(
+      addFile('bin/__projectName__.dart', main),
+    );
+  }
+
+  @override
+  String getInstallInstructions() => '${super.getInstallInstructions()}\n'
+      'run your app using `dart ${entrypoint.path}`.';
+}
+
+final String _pubspec = '''
+name: __projectName__
+description: A simple command-line application.
+version: 1.0.0
+# homepage: https://www.example.com
+
+environment:
+  sdk: '>=2.12.0 <3.0.0'
+
+# dependencies:
+#   path: ^1.8.0
+
+dev_dependencies:
+  pedantic: ^1.10.0
+''';
+
+final String _readme = '''
+A simple command-line application.
+''';
+
+final String main = '''
+void main(List<String> arguments) {
+  print('Hello world!');
+}
+''';
diff --git a/pkg/dartdev/lib/src/templates/package_simple.dart b/pkg/dartdev/lib/src/templates/package_simple.dart
new file mode 100644
index 0000000..7d013fa
--- /dev/null
+++ b/pkg/dartdev/lib/src/templates/package_simple.dart
@@ -0,0 +1,130 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 '../templates.dart';
+import 'common.dart' as common;
+
+/// A generator for a simple command-line application.
+class PackageSimpleGenerator extends DefaultGenerator {
+  PackageSimpleGenerator()
+      : super('package-simple', 'Dart Package',
+            'A starting point for Dart libraries or applications.',
+            categories: const ['dart']) {
+    addFile('.gitignore', _gitignore);
+    addFile('analysis_options.yaml', common.analysisOptions);
+    addFile('CHANGELOG.md', common.changelog);
+    addFile('pubspec.yaml', _pubspec);
+    addFile('README.md', _readme);
+    addFile('example/__projectName___example.dart', _exampleDart);
+    setEntrypoint(
+      addFile('lib/__projectName__.dart', _libDart),
+    );
+    addFile('lib/src/__projectName___base.dart', _libSrcDart);
+    addFile('test/__projectName___test.dart', _testDart);
+  }
+
+  @override
+  String getInstallInstructions() => '${super.getInstallInstructions()}\n'
+      'run your app using `dart ${entrypoint.path}`.';
+}
+
+final String _gitignore = '''
+# Files and directories created by pub.
+.dart_tool/
+.packages
+
+# Conventional directory for build outputs.
+build/
+
+# Omit committing pubspec.lock for library packages; see
+# https://dart.dev/guides/libraries/private-files#pubspeclock.
+pubspec.lock
+''';
+
+final String _pubspec = '''
+name: __projectName__
+description: A starting point for Dart libraries or applications.
+version: 1.0.0
+# homepage: https://www.example.com
+
+environment:
+  sdk: '>=2.12.0 <3.0.0'
+
+# dependencies:
+#   path: ^1.8.0
+
+dev_dependencies:
+  pedantic: ^1.10.0
+  test: ^1.16.0
+''';
+
+final String _readme = '''
+A library for Dart developers.
+
+## Usage
+
+A simple usage example:
+
+```dart
+import 'package:__projectName__/__projectName__.dart';
+
+main() {
+  var awesome = new Awesome();
+}
+```
+
+## Features and bugs
+
+Please file feature requests and bugs at the [issue tracker][tracker].
+
+[tracker]: http://example.com/issues/replaceme
+''';
+
+final String _exampleDart = r'''
+import 'package:__projectName__/__projectName__.dart';
+
+void main() {
+  var awesome = Awesome();
+  print('awesome: ${awesome.isAwesome}');
+}
+''';
+
+final String _libDart = '''
+/// Support for doing something awesome.
+///
+/// More dartdocs go here.
+library __projectName__;
+
+export 'src/__projectName___base.dart';
+
+// TODO: Export any libraries intended for clients of this package.
+''';
+
+final String _libSrcDart = '''
+// TODO: Put public facing types in this file.
+
+/// Checks if you are awesome. Spoiler: you are.
+class Awesome {
+  bool get isAwesome => true;
+}
+''';
+
+final String _testDart = '''
+import 'package:__projectName__/__projectName__.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('A group of tests', () {
+    final awesome = Awesome();
+
+    setUp(() {
+      // Additional setup goes here.
+    });
+
+    test('First Test', () {
+      expect(awesome.isAwesome, isTrue);
+    });
+  });
+}
+''';
diff --git a/pkg/dartdev/lib/src/templates/server_simple.dart b/pkg/dartdev/lib/src/templates/server_simple.dart
new file mode 100644
index 0000000..6688f23
--- /dev/null
+++ b/pkg/dartdev/lib/src/templates/server_simple.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 '../templates.dart';
+import 'common.dart' as common;
+
+/// A generator for a server app built on `package:shelf`.
+class ServerSimpleGenerator extends DefaultGenerator {
+  ServerSimpleGenerator()
+      : super('server-simple', 'Web Server',
+            'A web server built using package:shelf.',
+            categories: const ['dart', 'server']) {
+    addFile('.gitignore', common.gitignore);
+    addFile('analysis_options.yaml', common.analysisOptions);
+    addFile('CHANGELOG.md', common.changelog);
+    addFile('pubspec.yaml', _pubspec);
+    addFile('README.md', _readme);
+    setEntrypoint(
+      addFile('bin/server.dart', _main),
+    );
+  }
+
+  @override
+  String getInstallInstructions() => '${super.getInstallInstructions()}\n'
+      'run your app using `dart ${entrypoint.path}`.';
+}
+
+final String _pubspec = '''
+name: __projectName__
+description: A web server built using the shelf package.
+version: 1.0.0
+# homepage: https://www.example.com
+
+environment:
+  sdk: ">=2.12.0 <3.0.0"
+
+dependencies:
+  args: ^2.0.0
+  shelf: ^1.1.0
+
+dev_dependencies:
+  pedantic: ^1.10.0
+''';
+
+final String _readme = '''
+A web server built using [Shelf](https://pub.dev/packages/shelf).
+''';
+
+final String _main = r'''
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:shelf/shelf.dart' as shelf;
+import 'package:shelf/shelf_io.dart' as io;
+
+// For Google Cloud Run, set _hostname to '0.0.0.0'.
+const _hostname = 'localhost';
+
+void main(List<String> args) async {
+  var parser = ArgParser()..addOption('port', abbr: 'p');
+  var result = parser.parse(args);
+
+  // For Google Cloud Run, we respect the PORT environment variable
+  var portStr = result['port'] ?? Platform.environment['PORT'] ?? '8080';
+  var port = int.tryParse(portStr);
+
+  if (port == null) {
+    stdout.writeln('Could not parse port value "$portStr" into a number.');
+    // 64: command line usage error
+    exitCode = 64;
+    return;
+  }
+
+  var handler = const shelf.Pipeline()
+      .addMiddleware(shelf.logRequests())
+      .addHandler(_echoRequest);
+
+  var server = await io.serve(handler, _hostname, port);
+  print('Serving at http://${server.address.host}:${server.port}');
+}
+
+shelf.Response _echoRequest(shelf.Request request) =>
+    shelf.Response.ok('Request for "${request.url}"');
+''';
diff --git a/pkg/dartdev/lib/src/templates/web_simple.dart b/pkg/dartdev/lib/src/templates/web_simple.dart
new file mode 100644
index 0000000..0fd6c34
--- /dev/null
+++ b/pkg/dartdev/lib/src/templates/web_simple.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 '../templates.dart';
+import 'common.dart' as common;
+
+/// A generator for a uber-simple web application.
+class WebSimpleGenerator extends DefaultGenerator {
+  WebSimpleGenerator()
+      : super('web-simple', 'Bare-bones Web App',
+            'A web app that uses only core Dart libraries.',
+            categories: const ['dart', 'web']) {
+    addFile('.gitignore', common.gitignore);
+    addFile('analysis_options.yaml', common.analysisOptions);
+    addFile('CHANGELOG.md', common.changelog);
+    addFile('pubspec.yaml', _pubspec);
+    addFile('README.md', _readme);
+    addFile('web/index.html', _index);
+    setEntrypoint(
+      addFile('web/main.dart', _main),
+    );
+    addFile('web/styles.css', _styles);
+  }
+}
+
+final String _pubspec = '''
+name: __projectName__
+description: An absolute bare-bones web app.
+version: 1.0.0
+# homepage: https://www.example.com
+
+environment:
+  sdk: '>=2.10.0 <3.0.0'
+
+# dependencies:
+#   path: ^1.7.0
+
+dev_dependencies:
+  build_runner: ^1.10.0
+  build_web_compilers: ^2.11.0
+  pedantic: ^1.9.0
+''';
+
+final String _readme = '''
+An absolute bare-bones web app.
+''';
+
+final String _index = '''
+<!DOCTYPE html>
+
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <meta name="scaffolded-by" content="https://github.com/dart-lang/sdk">
+    <title>__projectName__</title>
+    <link rel="stylesheet" href="styles.css">
+    <script defer src="main.dart.js"></script>
+</head>
+
+<body>
+
+  <div id="output"></div>
+
+</body>
+</html>
+''';
+
+final String _main = '''
+import 'dart:html';
+
+void main() {
+  querySelector('#output').text = 'Your Dart app is running.';
+}
+''';
+
+final String _styles = '''
+@import url(https://fonts.googleapis.com/css?family=Roboto);
+
+html, body {
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  padding: 0;
+  font-family: 'Roboto', sans-serif;
+}
+
+#output {
+  padding: 20px;
+  text-align: center;
+}
+''';
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index 5acc161..20071f4 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -27,7 +27,6 @@
   path: ^1.0.0
   pedantic: ^1.9.0
   pub: any
-  stagehand: any
   telemetry:
     path: ../telemetry
   usage: ^3.4.0
diff --git a/pkg/dartdev/test/commands/create_integration_test.dart b/pkg/dartdev/test/commands/create_integration_test.dart
new file mode 100644
index 0000000..af112d1
--- /dev/null
+++ b/pkg/dartdev/test/commands/create_integration_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:dartdev/src/commands/create.dart';
+import 'package:test/test.dart';
+
+import '../utils.dart';
+
+void main() {
+  group('create integration', defineCreateTests, timeout: longTimeout);
+}
+
+void defineCreateTests() {
+  TestProject p;
+
+  setUp(() => p = null);
+
+  tearDown(() => p?.dispose());
+
+  // Create tests for each template.
+  for (String templateId in CreateCommand.legalTemplateIds) {
+    test(templateId, () {
+      p = project();
+
+      ProcessResult createResult = p.runSync([
+        'create',
+        '--force',
+        '--template',
+        templateId,
+        p.dir.path,
+      ]);
+      expect(createResult.exitCode, 0, reason: createResult.stderr);
+
+      // Validate that the project analyzes cleanly.
+      // TODO: Should we use --fatal-infos here?
+      ProcessResult analyzeResult =
+          p.runSync(['analyze'], workingDir: p.dir.path);
+      expect(analyzeResult.exitCode, 0, reason: analyzeResult.stdout);
+
+      // Validate that the code is well formatted.
+      ProcessResult formatResult = p.runSync([
+        'format',
+        '--output',
+        'none',
+        '--set-exit-if-changed',
+        p.dir.path,
+      ]);
+      expect(formatResult.exitCode, 0, reason: formatResult.stdout);
+    });
+  }
+}
diff --git a/pkg/dartdev/test/commands/create_test.dart b/pkg/dartdev/test/commands/create_test.dart
index 7f5c846..5429b80 100644
--- a/pkg/dartdev/test/commands/create_test.dart
+++ b/pkg/dartdev/test/commands/create_test.dart
@@ -6,6 +6,7 @@
 import 'dart:io';
 
 import 'package:dartdev/src/commands/create.dart';
+import 'package:dartdev/src/templates.dart' as templates;
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 
@@ -77,14 +78,19 @@
     test('create $templateId', () {
       p = project();
 
-      ProcessResult result = p
-          .runSync(['create', '--force', '--template', templateId, p.dir.path]);
+      ProcessResult result = p.runSync([
+        'create',
+        '--force',
+        '--no-pub',
+        '--template',
+        templateId,
+        p.dir.path,
+      ]);
       expect(result.exitCode, 0);
 
       String projectName = path.basename(p.dir.path);
 
-      String entry =
-          CreateCommand.retrieveTemplateGenerator(templateId).entrypoint.path;
+      String entry = templates.getGenerator(templateId).entrypoint.path;
       entry = entry.replaceAll('__projectName__', projectName);
       File entryFile = File(path.join(p.dir.path, entry));
 
diff --git a/pkg/dartdev/test/templates_test.dart b/pkg/dartdev/test/templates_test.dart
new file mode 100644
index 0000000..3b466c9
--- /dev/null
+++ b/pkg/dartdev/test/templates_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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:dartdev/src/templates.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('templates', () {
+    group('substituteVars', () {
+      test('simple', () {
+        _expect('foo __bar__ baz', {'bar': 'baz'}, 'foo baz baz');
+      });
+
+      test('nosub', () {
+        _expect('foo __bar__ baz', {'aaa': 'bbb'}, 'foo __bar__ baz');
+      });
+
+      test('matching input', () {
+        _expect('foo __bar__ baz', {'bar': '__baz__', 'baz': 'foo'},
+            'foo __baz__ baz');
+      });
+
+      test('vars must be alpha + numeric', () {
+        expect(() => substituteVars('str', {'with space': 'noop'}),
+            throwsArgumentError);
+        expect(() => substituteVars('str', {'with!symbols': 'noop'}),
+            throwsArgumentError);
+        expect(() => substituteVars('str', {'with1numbers': 'noop'}),
+            throwsArgumentError);
+        expect(() => substituteVars('str', {'with_under': 'noop'}),
+            throwsArgumentError);
+      });
+    });
+  });
+}
+
+void _expect(String original, Map<String, String> vars, String result) {
+  expect(substituteVars(original, vars), result);
+}
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index 1f3db17..5a64ced 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -7,7 +7,6 @@
 
 import 'package:path/path.dart' as path;
 import 'package:pub_semver/pub_semver.dart';
-
 import 'package:test/test.dart';
 
 /// A long [Timeout] is provided for tests that start a process on
@@ -54,7 +53,7 @@
       this.name = _defaultProjectName,
       this.logAnalytics = false,
       this.sdkConstraint}) {
-    dir = Directory.systemTemp.createTempSync(name);
+    dir = Directory.systemTemp.createTempSync('a');
     file('pubspec.yaml', '''
 name: $name
 environment:
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_test.dart
index ebc57c1f..95d2fb0 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_test.dart
@@ -256,6 +256,8 @@
   /// Depends on SDK artifacts (such as the sound and unsound dart_sdk.js
   /// files) generated from the 'dartdevc_test' target.
   Future<void> initSource(SetupCompilerOptions setup, String source) async {
+    // Prepend Dart nullability comment.
+    source = '${setup.dartLangComment}\n\n$source';
     this.setup = setup;
     this.source = source;
     testDir = await chromeDir.createTemp('ddc_eval_test');
@@ -460,10 +462,7 @@
         returnByValue: false);
 
     await debugger.removeBreakpoint(bp.breakpointId);
-
-    var value = evalResult.type == 'function'
-        ? evalResult.description
-        : evalResult.value;
+    var value = await stringifyRemoteObject(evalResult);
 
     expect(
         result,
@@ -471,6 +470,41 @@
             .having((_) => '$value', 'result', _matches(expectedResult)));
   }
 
+  /// Generate simple string representation of a RemoteObject that closely
+  /// resembles Chrome's console output.
+  ///
+  /// Examples:
+  /// Class: t.C.new {Symbol(C.field): 5, Symbol(_field): 7}
+  /// Function: function main() {
+  ///             return test.foo(1, {y: 2});
+  ///           }
+  Future<String> stringifyRemoteObject(wip.RemoteObject obj) async {
+    String str;
+    switch (obj.type) {
+      case 'function':
+        str = obj.description;
+        break;
+      case 'object':
+        if (obj.subtype == 'null') {
+          return 'null';
+        }
+        var properties =
+            await connection.runtime.getProperties(obj, ownProperties: true);
+        var filteredProps = <String, String>{};
+        for (var prop in properties) {
+          if (prop.value != null && prop.name != '__proto__') {
+            filteredProps[prop.name] = await stringifyRemoteObject(prop.value);
+          }
+        }
+        str = '${obj.description} $filteredProps';
+        break;
+      default:
+        str = '${obj.value}';
+        break;
+    }
+    return str;
+  }
+
   /// Collects local JS variables visible at a breakpoint during evaluation.
   ///
   /// Adapted from webdev/dwds/lib/src/services/expression_evaluator.dart.
@@ -565,8 +599,6 @@
 
     group('Expression compiler extension symbols tests', () {
       var source = '''
-        ${setup.dartLangComment}
-
         main() {
           List<int> list = [];
           list.add(0);
@@ -597,9 +629,10 @@
 
     group('Expression compiler scope collection tests', () {
       var source = '''
-        ${setup.dartLangComment}
-
         class C {
+          static int staticField = 0;
+          int field;
+
           C(this.field);
 
           void methodFieldAccess(int x) {
@@ -611,9 +644,6 @@
             }
             var notInScope = 3;
           }
-
-          static int staticField = 0;
-          int field;
         }
 
         int global = 42;
@@ -681,7 +711,6 @@
 
     group('Expression compiler tests in extension method:', () {
       var source = '''
-        ${setup.dartLangComment}
         extension NumberParsing on String {
           int parseInt() {
             var ret = int.parse(this);
@@ -725,7 +754,6 @@
 
     group('Expression compiler tests in static function:', () {
       var source = '''
-        ${setup.dartLangComment}
         int foo(int x, {int y}) {
           int z = 3;
           // Breakpoint: bp
@@ -773,6 +801,216 @@
               }''');
       });
     });
+
+    group('Expression compiler tests in method:', () {
+      var source = '''
+          extension NumberParsing on String {
+            int parseInt() {
+              return int.parse(this) + 1;
+            }
+          }
+
+          class C {
+            static int staticField = 1;
+            static int _staticField = 2;
+            static int _unusedStaticField = 3;
+            int field;
+            int _field;
+            int _unusedField = 4;
+
+            C(this.field, this._field);
+
+            int methodFieldAccess(int x) {
+              // Breakpoint: bp
+              return x + _field + _staticField;
+            }
+          }
+
+          void entrypoint() {
+            var c = C(5, 7);
+            // Breakpoint: bp1
+            c.methodFieldAccess(10);
+          }
+
+          int global = 42;
+          main() => entrypoint();
+          ''';
+
+      setUpAll(() async {
+        await driver.initSource(setup, source);
+      });
+
+      tearDownAll(() {
+        driver.cleanupTest();
+      });
+
+      test('compilation error', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: 'typo',
+            expectedError: "The getter 'typo' isn't defined for the class 'C'");
+      });
+
+      test('local', () async {
+        await driver.check(
+            breakpointId: 'bp', expression: 'x', expectedResult: '10');
+      });
+
+      test('this', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: 'this',
+            expectedResult:
+                'test.C.new {Symbol(_unusedField): 4, Symbol(C.field): 5,'
+                ' Symbol(_field): 7}');
+      });
+
+      test('expression using locals', () async {
+        await driver.check(
+            breakpointId: 'bp', expression: 'x + 1', expectedResult: '11');
+      });
+
+      test('expression using static fields', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: 'x + staticField',
+            expectedResult: '11');
+      });
+
+      test('expression using private static fields', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: 'x + _staticField',
+            expectedResult: '12');
+      });
+
+      test('expression using fields', () async {
+        await driver.check(
+            breakpointId: 'bp', expression: 'x + field', expectedResult: '15');
+      });
+
+      test('expression using private fields', () async {
+        await driver.check(
+            breakpointId: 'bp', expression: 'x + _field', expectedResult: '17');
+      });
+
+      test('expression using globals', () async {
+        await driver.check(
+            breakpointId: 'bp', expression: 'x + global', expectedResult: '52');
+      });
+
+      test('expression using fields not referred to in the original  code',
+          () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: '_unusedField + _unusedStaticField',
+            expectedResult: '7');
+      });
+
+      test('method call', () async {
+        await driver.check(
+            breakpointId: 'bp1',
+            expression: 'c.methodFieldAccess(2)',
+            expectedResult: '11');
+      });
+
+      test('extension method call', () async {
+        await driver.check(
+            breakpointId: 'bp1',
+            expression: '"1234".parseInt()',
+            expectedResult: '1235');
+      });
+
+      test('private field modification', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: '() {_field = 2; return _field;}()',
+            expectedResult: '2');
+      });
+
+      test('field modification', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: '() {field = 3; return field;}()',
+            expectedResult: '3');
+      });
+
+      test('private static field modification', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: '() {_staticField = 4; return _staticField;}()',
+            expectedResult: '4');
+      });
+
+      test('static field modification', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: '() {staticField = 5; return staticField;}()',
+            expectedResult: '5');
+      });
+    });
+
+    group('Expression compiler tests in async method:', () {
+      var source = '''
+        class C {
+          static int staticField = 1;
+          static int _staticField = 2;
+          int _field;
+          int field;
+
+          C(this.field, this._field);
+          Future<int> asyncMethod(int x) async {
+            // Breakpoint: bp
+            return x + global + _field + field + staticField + _staticField;
+          }
+        }
+
+        void entrypoint() async {
+          var c = C(5, 7);
+          // Breakpoint: bp1
+          var nop;
+          await c.asyncMethod(1);
+        }
+
+        int global = 42;
+        main() async => await entrypoint();
+        ''';
+
+      setUpAll(() async {
+        await driver.initSource(setup, source);
+      });
+
+      tearDownAll(() {
+        driver.cleanupTest();
+      });
+
+      test('compilation error', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: 'typo',
+            expectedError: "The getter 'typo' isn't defined for the class 'C'");
+      });
+
+      test('local', () async {
+        await driver.check(
+            breakpointId: 'bp', expression: 'x', expectedResult: '1');
+      });
+
+      test('this', () async {
+        await driver.check(
+            breakpointId: 'bp',
+            expression: 'this',
+            expectedResult:
+                'test.C.new {Symbol(C.field): 5, Symbol(_field): 7}');
+      });
+
+      test('async method call', () async {
+        await driver.check(
+            breakpointId: 'bp1',
+            expression: 'await c.asyncMethod(1)',
+            expectedResult: '58');
+      }, skip: "'await' is not yet supported in expression evaluation.");
+    });
   });
 
   group('Sound null safety:', () {
@@ -789,8 +1027,6 @@
 
     group('Expression compiler extension symbols tests', () {
       var source = '''
-        ${setup.dartLangComment}
-
         main() {
           List<int> list = [];
           list.add(0);
@@ -821,8 +1057,6 @@
 
     group('Expression compiler scope collection tests', () {
       var source = '''
-        ${setup.dartLangComment}
-
         class C {
           C(this.field);
 
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 2f32e9a..8d2d698 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -682,7 +682,10 @@
       TypeAliasBuilder aliasBuilder; // Non-null if a type alias is use.
       if (decl is TypeAliasBuilder) {
         aliasBuilder = decl;
-        decl = aliasBuilder.unaliasDeclaration(superClassType.arguments);
+        decl = aliasBuilder.unaliasDeclaration(superClassType.arguments,
+            isUsedAsClass: true,
+            usedAsClassCharOffset: supertypeBuilder.charOffset,
+            usedAsClassFileUri: superClassType.fileUri);
       }
       // TODO(eernst): Should gather 'restricted supertype' checks in one place,
       // e.g., dynamic/int/String/Null and more are checked elsewhere.
@@ -708,7 +711,10 @@
         TypeAliasBuilder aliasBuilder; // Non-null if a type alias is used.
         if (typeDeclaration is TypeAliasBuilder) {
           aliasBuilder = typeDeclaration;
-          decl = aliasBuilder.unaliasDeclaration(type.arguments);
+          decl = aliasBuilder.unaliasDeclaration(type.arguments,
+              isUsedAsClass: true,
+              usedAsClassCharOffset: type.charOffset,
+              usedAsClassFileUri: type.fileUri);
         } else {
           decl = typeDeclaration;
         }
@@ -1149,7 +1155,10 @@
           if (builder is ClassBuilder) return builder;
           if (builder is TypeAliasBuilder) {
             TypeDeclarationBuilder declarationBuilder =
-                builder.unaliasDeclaration(supertype.arguments);
+                builder.unaliasDeclaration(supertype.arguments,
+                    isUsedAsClass: true,
+                    usedAsClassCharOffset: supertype.charOffset,
+                    usedAsClassFileUri: supertype.fileUri);
             if (declarationBuilder is ClassBuilder) return declarationBuilder;
           }
         }
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 86e27d1..1833d4f 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
@@ -244,8 +244,23 @@
       }
     }
 
-    return declaration.buildType(
-        library, nullabilityBuilder, arguments, notInstanceContext);
+    if (library is SourceLibraryBuilder) {
+      int uncheckedTypedefTypeCount = library.uncheckedTypedefTypes.length;
+      DartType builtType = declaration.buildType(
+          library, nullabilityBuilder, arguments, notInstanceContext);
+      // Set locations for new unchecked TypedefTypes for error reporting.
+      for (int i = uncheckedTypedefTypeCount;
+          i < library.uncheckedTypedefTypes.length;
+          ++i) {
+        library.uncheckedTypedefTypes[i]
+          ..fileUri ??= fileUri
+          ..offset ??= charOffset;
+      }
+      return builtType;
+    } else {
+      return declaration.buildType(
+          library, nullabilityBuilder, arguments, notInstanceContext);
+    }
   }
 
   Supertype buildSupertype(
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 0ff9c8e..577265a 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
@@ -6,14 +6,7 @@
 
 library fasta.function_type_alias_builder;
 
-import 'package:kernel/ast.dart'
-    show
-        DartType,
-        DynamicType,
-        InvalidType,
-        Nullability,
-        TypeParameter,
-        Typedef;
+import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart';
 
 import 'package:kernel/type_algebra.dart' show substitute, uniteNullabilities;
@@ -28,11 +21,13 @@
         messageTypedefTypeVariableNotConstructorCause;
 
 import '../problems.dart' show unhandled;
+import '../source/source_library_builder.dart';
 import '../util/helpers.dart';
 
 import 'class_builder.dart';
 import 'library_builder.dart';
 import 'metadata_builder.dart';
+import 'function_type_builder.dart';
 import 'named_type_builder.dart';
 import 'nullability_builder.dart';
 import 'type_builder.dart';
@@ -81,14 +76,14 @@
   /// based on the given [typeArguments]. It expands type aliases repeatedly
   /// until it encounters a builder which is not a [TypeAliasBuilder].
   ///
-  /// If [isInvocation] is false: In this case it is required that
+  /// If [isUsedAsClass] is false: In this case it is required that
   /// `typeArguments.length == typeVariables.length`. The [typeArguments] are
   /// threaded through the expansion if needed, and the resulting declaration
   /// is returned.
   ///
-  /// If [isInvocation] is true: In this case [typeArguments] are ignored, but
-  /// [invocationCharOffset] and [invocationFileUri] must be non-null. If `this`
-  /// type alias expands in one or more steps to a builder which is not a
+  /// If [isUsedAsClass] is true: In this case [typeArguments] are ignored, but
+  /// [usedAsClassCharOffset] and [usedAsClassFileUri] must be non-null. If
+  /// `this` type alias expands in one or more steps to a builder which is not a
   /// [TypeAliasBuilder] nor a [TypeVariableBuilder] then that builder is
   /// returned. If this type alias is cyclic or expands to an invalid type or
   /// a type that does not have a declaration (say, a function type) then `this`
@@ -97,9 +92,9 @@
   /// [TypeVariableBuilder] then the type alias cannot be used in a constructor
   /// invocation. Then an error is emitted and `this` is returned.
   TypeDeclarationBuilder unaliasDeclaration(List<TypeBuilder> typeArguments,
-      {bool isInvocation = false,
-      int invocationCharOffset,
-      Uri invocationFileUri});
+      {bool isUsedAsClass = false,
+      int usedAsClassCharOffset,
+      Uri usedAsClassFileUri});
 
   /// Compute type arguments passed to [ClassBuilder] from unaliasDeclaration.
   /// This method does not check for cycles and may only be called if an
@@ -146,6 +141,17 @@
     for (int i = 0; i < typedef.typeParameters.length; i++) {
       substitution[typedef.typeParameters[i]] = arguments[i];
     }
+    // The following adds the built type to the list of unchecked typedef types
+    // of the client library. It is needed because the type is built unaliased,
+    // and at the time of the check it wouldn't be possible to see if the type
+    // arguments to the generic typedef conform to the bounds without preserving
+    // the TypedefType for the delayed check.
+    if (library is SourceLibraryBuilder &&
+        arguments.isNotEmpty &&
+        type is! FunctionTypeBuilder) {
+      library.uncheckedTypedefTypes.add(new UncheckedTypedefType(
+          new TypedefType(typedef, nullability, arguments)));
+    }
     return substitute(result, substitution);
   }
 
@@ -191,25 +197,32 @@
   /// based on the given [typeArguments]. It expands type aliases repeatedly
   /// until it encounters a builder which is not a [TypeAliasBuilder].
   ///
-  /// If [isInvocation] is false: In this case it is required that
+  /// The parameter [isUsedAsClass] indicates whether the type alias is being
+  /// used as a class, e.g., as the class in an instance creation, as a
+  /// superinterface, in a redirecting factory constructor, or to invoke a
+  /// static member.
+  ///
+  /// If [isUsedAsClass] is false: In this case it is required that
   /// `typeArguments.length == typeVariables.length`. The [typeArguments] are
   /// threaded through the expansion if needed, and the resulting declaration
   /// is returned.
   ///
-  /// If [isInvocation] is true: In this case [typeArguments] are ignored, but
-  /// [invocationCharOffset] and [invocationFileUri] must be non-null. If `this`
+  /// If [isUsedAsClass] is true: In this case [typeArguments] can be null, but
+  /// [usedAsClassCharOffset] and [usedAsClassFileUri] must be non-null. When
+  /// [typeArguments] is null, the returned [TypeDeclarationBuilder] indicates
+  /// which class the type alias denotes, without type arguments. If `this`
   /// type alias expands in one or more steps to a builder which is not a
   /// [TypeAliasBuilder] nor a [TypeVariableBuilder] then that builder is
   /// returned. If this type alias is cyclic or expands to an invalid type or
   /// a type that does not have a declaration (say, a function type) then `this`
   /// is returned (when the type was invalid: with `thisType` set to
   /// `const InvalidType()`). If `this` type alias expands to a
-  /// [TypeVariableBuilder] then the type alias cannot be used in a constructor
-  /// invocation. Then an error is emitted and `this` is returned.
+  /// [TypeVariableBuilder] then the type alias cannot be used as a class, in
+  /// which case an error is emitted and `this` is returned.
   TypeDeclarationBuilder unaliasDeclaration(List<TypeBuilder> typeArguments,
-      {bool isInvocation = false,
-      int invocationCharOffset,
-      Uri invocationFileUri}) {
+      {bool isUsedAsClass = false,
+      int usedAsClassCharOffset,
+      Uri usedAsClassFileUri}) {
     if (_cachedUnaliasedDeclaration != null) return _cachedUnaliasedDeclaration;
     Set<TypeDeclarationBuilder> builders = {this};
     TypeDeclarationBuilder current = this;
@@ -241,15 +254,39 @@
         // `_cachedUnaliasedDeclaration` because it changes from call to call
         // with type aliases of this kind. Note that every `aliasBuilder.type`
         // up to this point is a [NamedTypeBuilder], because only they can have
-        // a non-null `type`. However, a constructor invocation is not admitted.
-        if (isInvocation) {
-          library.addProblem(messageTypedefTypeVariableNotConstructor,
-              invocationCharOffset, noLength, invocationFileUri,
-              context: [
-                messageTypedefTypeVariableNotConstructorCause.withLocation(
-                    current.fileUri, current.charOffset, noLength),
-              ]);
-          return this;
+        // a non-null `type`. However, this type alias can not be used as a
+        // class.
+        if (isUsedAsClass) {
+          List<TypeBuilder> freshTypeArguments = [
+            if (typeVariables != null)
+              for (TypeVariableBuilder typeVariable in typeVariables)
+                new NamedTypeBuilder.fromTypeDeclarationBuilder(
+                  typeVariable,
+                  library.nonNullableBuilder,
+                  const [],
+                  fileUri,
+                  charOffset,
+                ),
+          ];
+          TypeDeclarationBuilder typeDeclarationBuilder =
+              _unaliasDeclaration(freshTypeArguments);
+          bool found = false;
+          for (TypeBuilder typeBuilder in freshTypeArguments) {
+            if (typeBuilder.declaration == typeDeclarationBuilder) {
+              found = true;
+              break;
+            }
+          }
+          if (found) {
+            library.addProblem(messageTypedefTypeVariableNotConstructor,
+                usedAsClassCharOffset, noLength, usedAsClassFileUri,
+                context: [
+                  messageTypedefTypeVariableNotConstructorCause.withLocation(
+                      current.fileUri, current.charOffset, noLength),
+                ]);
+            return this;
+          }
+          if (typeArguments == null) return typeDeclarationBuilder;
         }
         return _unaliasDeclaration(typeArguments);
       }
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 c697bac..927f9e8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1081,6 +1081,7 @@
 
     resolveRedirectingFactoryTargets();
     finishVariableMetadata();
+    libraryBuilder.checkUncheckedTypedefTypes(typeEnvironment);
   }
 
   void checkAsyncReturnType(AsyncMarker asyncModifier, DartType returnType,
@@ -4530,9 +4531,9 @@
                 noLength));
       }
       type = aliasBuilder.unaliasDeclaration(null,
-          isInvocation: true,
-          invocationCharOffset: nameToken.charOffset,
-          invocationFileUri: uri);
+          isUsedAsClass: true,
+          usedAsClassCharOffset: nameToken.charOffset,
+          usedAsClassFileUri: uri);
       List<TypeBuilder> typeArgumentBuilders = [];
       if (typeArguments != null) {
         for (UnresolvedType unresolvedType in typeArguments) {
@@ -4620,6 +4621,23 @@
           }
         }
       }
+
+      List<DartType> typeArgumentsToCheck = const <DartType>[];
+      if (typeArgumentBuilders != null && typeArgumentBuilders.isNotEmpty) {
+        typeArgumentsToCheck = new List.filled(
+            typeArgumentBuilders.length, const DynamicType(),
+            growable: false);
+        for (int i = 0; i < typeArgumentsToCheck.length; ++i) {
+          typeArgumentsToCheck[i] =
+              typeArgumentBuilders[i].build(libraryBuilder);
+        }
+      }
+      DartType typeToCheck = new TypedefType(
+          aliasBuilder.typedef, Nullability.nonNullable, typeArgumentsToCheck);
+      libraryBuilder.checkBoundsInType(
+          typeToCheck, typeEnvironment, uri, charOffset,
+          allowSuperBounded: false);
+
       if (type is ClassBuilder) {
         if (typeArguments != null) {
           int numberOfTypeParameters = aliasBuilder.typeVariables?.length ?? 0;
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 25e0a70..38ee51c 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
@@ -1374,7 +1374,10 @@
       if (mixin is TypeAliasBuilder) {
         TypeAliasBuilder aliasBuilder = mixin;
         NamedTypeBuilder namedBuilder = mixedInTypeBuilder;
-        mixin = aliasBuilder.unaliasDeclaration(namedBuilder.arguments);
+        mixin = aliasBuilder.unaliasDeclaration(namedBuilder.arguments,
+            isUsedAsClass: true,
+            usedAsClassCharOffset: namedBuilder.charOffset,
+            usedAsClassFileUri: namedBuilder.fileUri);
       }
       if (mixin is ClassBuilder) {
         scope = mixin.scope.computeMixinScope();
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 0112d3f..8041794 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -3383,15 +3383,8 @@
 
     if (condition is AbortConstant) {
       return new AbortStatus(condition);
-    } else if (condition is! BoolConstant) {
-      return new AbortStatus(exprEvaluator.createErrorConstant(
-          node.condition,
-          templateConstEvalInvalidType.withArguments(
-              condition,
-              exprEvaluator.typeEnvironment.coreTypes.boolLegacyRawType,
-              condition.getType(exprEvaluator._staticTypeContext),
-              exprEvaluator.isNonNullableByDefault)));
     }
+    assert(condition is BoolConstant);
     return const ProceedStatus();
   }
 
@@ -3399,23 +3392,13 @@
   ExecutionStatus visitIfStatement(IfStatement node) {
     Constant condition = evaluate(node.condition);
     if (condition is AbortConstant) return new AbortStatus(condition);
-    if (condition is BoolConstant) {
-      if (condition.value) {
-        return node.then.accept(this);
-      } else if (node.otherwise != null) {
-        return node.otherwise.accept(this);
-      } else {
-        return const ProceedStatus();
-      }
-    } else {
-      return new AbortStatus(exprEvaluator.createErrorConstant(
-          node.condition,
-          templateConstEvalInvalidType.withArguments(
-              condition,
-              exprEvaluator.typeEnvironment.coreTypes.boolLegacyRawType,
-              condition.getType(exprEvaluator._staticTypeContext),
-              exprEvaluator.isNonNullableByDefault)));
+    assert(condition is BoolConstant);
+    if ((condition as BoolConstant).value) {
+      return node.then.accept(this);
+    } else if (node.otherwise != null) {
+      return node.otherwise.accept(this);
     }
+    return const ProceedStatus();
   }
 
   @override
@@ -3446,6 +3429,7 @@
     }
 
     if (condition is AbortConstant) return new AbortStatus(condition);
+    assert(condition is BoolConstant);
     return const ProceedStatus();
   }
 
@@ -3486,6 +3470,7 @@
       condition = evaluate(node.condition);
     }
     if (condition is AbortConstant) return new AbortStatus(condition);
+    assert(condition is BoolConstant);
     return const ProceedStatus();
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 6f89031..a6e54b2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -3061,9 +3061,9 @@
     if (declarationBuilder is TypeAliasBuilder) {
       TypeAliasBuilder aliasBuilder = declarationBuilder;
       declarationBuilder = aliasBuilder.unaliasDeclaration(null,
-          isInvocation: true,
-          invocationCharOffset: this.fileOffset,
-          invocationFileUri: _uri);
+          isUsedAsClass: true,
+          usedAsClassCharOffset: this.fileOffset,
+          usedAsClassFileUri: _uri);
     }
     if (declarationBuilder is DeclarationBuilder) {
       DeclarationBuilder declaration = declarationBuilder;
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 1bebec8..a178096 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -675,7 +675,10 @@
     if (supertype is TypeAliasBuilder) {
       TypeAliasBuilder aliasBuilder = supertype;
       NamedTypeBuilder namedBuilder = type;
-      supertype = aliasBuilder.unaliasDeclaration(namedBuilder.arguments);
+      supertype = aliasBuilder.unaliasDeclaration(namedBuilder.arguments,
+          isUsedAsClass: true,
+          usedAsClassCharOffset: namedBuilder.charOffset,
+          usedAsClassFileUri: namedBuilder.fileUri);
     }
     if (supertype is SourceClassBuilder && supertype.isMixinApplication) {
       installForwardingConstructors(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 3017856..bf02502 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
@@ -589,8 +589,11 @@
       if (declarationBuilder is TypeAliasBuilder) {
         TypeAliasBuilder aliasBuilder = declarationBuilder;
         NamedTypeBuilder namedBuilder = supertype;
-        declarationBuilder =
-            aliasBuilder.unaliasDeclaration(namedBuilder.arguments);
+        declarationBuilder = aliasBuilder.unaliasDeclaration(
+            namedBuilder.arguments,
+            isUsedAsClass: true,
+            usedAsClassCharOffset: namedBuilder.charOffset,
+            usedAsClassFileUri: namedBuilder.fileUri);
         result[declarationBuilder] = aliasBuilder;
       } else {
         result[declarationBuilder] = null;
@@ -606,8 +609,11 @@
         if (declarationBuilder is TypeAliasBuilder) {
           TypeAliasBuilder aliasBuilder = declarationBuilder;
           NamedTypeBuilder namedBuilder = interface;
-          declarationBuilder =
-              aliasBuilder.unaliasDeclaration(namedBuilder.arguments);
+          declarationBuilder = aliasBuilder.unaliasDeclaration(
+              namedBuilder.arguments,
+              isUsedAsClass: true,
+              usedAsClassCharOffset: namedBuilder.charOffset,
+              usedAsClassFileUri: namedBuilder.fileUri);
           result[declarationBuilder] = aliasBuilder;
         } else {
           result[declarationBuilder] = null;
@@ -621,8 +627,11 @@
       if (declarationBuilder is TypeAliasBuilder) {
         TypeAliasBuilder aliasBuilder = declarationBuilder;
         NamedTypeBuilder namedBuilder = mixedInTypeBuilder;
-        declarationBuilder =
-            aliasBuilder.unaliasDeclaration(namedBuilder.arguments);
+        declarationBuilder = aliasBuilder.unaliasDeclaration(
+            namedBuilder.arguments,
+            isUsedAsClass: true,
+            usedAsClassCharOffset: namedBuilder.charOffset,
+            usedAsClassFileUri: namedBuilder.fileUri);
         result[declarationBuilder] = aliasBuilder;
       } else {
         result[declarationBuilder] = null;
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 51d4375..d13a474 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -188,6 +188,9 @@
   final List<TypeVariableBuilder> boundlessTypeVariables =
       <TypeVariableBuilder>[];
 
+  final List<UncheckedTypedefType> uncheckedTypedefTypes =
+      <UncheckedTypedefType>[];
+
   // A list of alternating forwarders and the procedures they were generated
   // for.  Note that it may not include a forwarder-origin pair in cases when
   // the former does not need to be updated after the body of the latter was
@@ -3778,6 +3781,7 @@
       }
     }
     inferredTypes.clear();
+    checkUncheckedTypedefTypes(typeEnvironment);
   }
 
   void registerImplicitlyTypedField(FieldBuilder fieldBuilder) {
@@ -3829,6 +3833,21 @@
     _pendingNullabilities
         .add(new PendingNullability(fileUri, charOffset, type));
   }
+
+  /// Performs delayed bounds checks on [TypedefType]s for the library
+  ///
+  /// As [TypedefType]s are built, they are eagerly unaliased, making it
+  /// impossible to perform the bounds checks on them at the time when the
+  /// checks can be done. To perform the checks, [TypedefType]s are added to
+  /// [uncheckedTypedefTypes] as they are built.  This method performs the
+  /// checks and clears the list of the types for the delayed check.
+  void checkUncheckedTypedefTypes(TypeEnvironment typeEnvironment) {
+    for (UncheckedTypedefType uncheckedTypedefType in uncheckedTypedefTypes) {
+      checkBoundsInType(uncheckedTypedefType.typeToCheck, typeEnvironment,
+          uncheckedTypedefType.fileUri, uncheckedTypedefType.offset);
+    }
+    uncheckedTypedefTypes.clear();
+  }
 }
 
 // The kind of type parameter scope built by a [TypeParameterScopeBuilder]
@@ -4295,3 +4314,14 @@
 
   PendingNullability(this.fileUri, this.charOffset, this.type);
 }
+
+class UncheckedTypedefType {
+  final TypedefType typeToCheck;
+
+  // TODO(dmitryas): Make these fields nullable when the library is opted-in to
+  // NNBD.
+  int offset;
+  Uri fileUri;
+
+  UncheckedTypedefType(this.typeToCheck);
+}
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 1183386..eed0da7 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -907,7 +907,10 @@
         if (builder is TypeAliasBuilder) {
           TypeAliasBuilder aliasBuilder = builder;
           NamedTypeBuilder namedBuilder = mixedInTypeBuilder;
-          builder = aliasBuilder.unaliasDeclaration(namedBuilder.arguments);
+          builder = aliasBuilder.unaliasDeclaration(namedBuilder.arguments,
+              isUsedAsClass: true,
+              usedAsClassCharOffset: namedBuilder.charOffset,
+              usedAsClassFileUri: namedBuilder.fileUri);
           if (builder is! ClassBuilder) {
             cls.addProblem(
                 templateIllegalMixin.withArguments(builder.fullNameForErrors),
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 c8fbea5e..2d7a818 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
@@ -3425,12 +3425,12 @@
       receiver = _hoist(receiver, receiverType, hoistedExpressions);
     }
 
-    Map<DartType, NonPromotionReason> Function() whyNotPromotedInfo;
+    Map<DartType, NonPromotionReason> Function() whyNotPromoted;
     if (!isTopLevel && target.isNullable) {
       // We won't report the error until later (after we have an
       // invocationResult), but we need to gather "why not promoted" info now,
       // before we tell flow analysis about the property get.
-      whyNotPromotedInfo = flowAnalysis?.whyNotPromoted(receiver);
+      whyNotPromoted = flowAnalysis?.whyNotPromoted(receiver);
     }
 
     Name originalName = field.name;
@@ -3516,7 +3516,7 @@
       // in this scenario?
       List<LocatedMessage> context = getWhyNotPromotedContext(
           receiver,
-          whyNotPromotedInfo(),
+          whyNotPromoted(),
           invocationResult.expression,
           (type) => !type.isPotentiallyNullable);
       invocationResult = wrapExpressionInferenceResultInProblem(
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 7d290ee..912054f 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -3155,6 +3155,7 @@
 unbind
 uncertain
 unchanged
+unchecked
 unclaimed
 unclear
 undeclared
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index f2aa65a..8050222 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -57,6 +57,12 @@
 bail
 bailing
 bailout
+bar1a
+bar1b
+bar2a
+bar2b
+bar3a
+bar3b
 barbar
 bash
 bat
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart
new file mode 100644
index 0000000..84f5324
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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<T> {}
+
+typedef B<X extends A<X>> = A<X>;
+
+foo() {
+  B<A<int>> x1;
+  A<B<A<int>>> x2;
+}
+
+B<A<int>> bar1a() => throw 42;
+A<B<A<int>>> bar1b() => throw 42;
+
+bar2a(B<A<int>> x) => throw 42;
+bar2b(A<B<A<int>>> x) => throw 42;
+
+bar3a<X extends B<A<int>>>() => throw 42;
+bar3b<X extends A<B<A<int>>>>() => throw 42;
+
+class Bar1<X extends B<A<int>>> {
+  B<A<int>> barBar11() => throw 42;
+  barBar12(B<A<int>> x) => throw 42;
+  barBar13<X extends B<A<int>>>() => throw 42;
+}
+
+class Bar2<X extends A<B<A<int>>>> {
+  A<B<A<int>>> barBar21() => throw 42;
+  barBar22(A<B<A<int>>> x) => throw 42;
+  barBar23<X extends A<B<A<int>>>>() => throw 42;
+}
+
+typedef Baz1 = B<A<int>>;
+typedef Baz2 = A<B<A<int>>>;
+
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.strong.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.strong.expect
new file mode 100644
index 0000000..7506643
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.strong.expect
@@ -0,0 +1,216 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:20:17: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3a<X extends B<A<int>>>() => throw 42;
+//                 ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:21:19: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3b<X extends A<B<A<int>>>>() => throw 42;
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:23:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar1<X extends B<A<int>>> {
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:26:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar13<X extends B<A<int>>>() => throw 42;
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:29:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar2<X extends A<B<A<int>>>> {
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:32:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar23<X extends A<B<A<int>>>>() => throw 42;
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:14:1: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// B<A<int>> bar1a() => throw 42;
+// ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:15:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// A<B<A<int>>> bar1b() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:17:7: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2a(B<A<int>> x) => throw 42;
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:18:9: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2b(A<B<A<int>>> x) => throw 42;
+//         ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:24:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<A<int>> barBar11() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:25:12: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar12(B<A<int>> x) => throw 42;
+//            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:30:5: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<B<A<int>>> barBar21() => throw 42;
+//     ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:31:14: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar22(A<B<A<int>>> x) => throw 42;
+//              ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:35:16: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz1 = B<A<int>>;
+//                ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:36:18: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz2 = A<B<A<int>>>;
+//                  ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:10:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<A<int>> x1;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:11:5: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<B<A<int>>> x2;
+//     ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B<X extends self::A<X> = self::A<dynamic>> = self::A<X>;
+typedef Baz1 = self::A<self::A<core::int>>;
+typedef Baz2 = self::A<self::A<self::A<core::int>>>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+}
+class Bar1<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>> extends core::Object {
+  synthetic constructor •() → self::Bar1<self::Bar1::X>
+    : super core::Object::•()
+    ;
+  method barBar11() → self::A<self::A<core::int>>
+    return throw 42;
+  method barBar12(self::A<self::A<core::int>> x) → dynamic
+    return throw 42;
+  method barBar13<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+    return throw 42;
+}
+class Bar2<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>> extends core::Object {
+  synthetic constructor •() → self::Bar2<self::Bar2::X>
+    : super core::Object::•()
+    ;
+  method barBar21() → self::A<self::A<self::A<core::int>>>
+    return throw 42;
+  method barBar22(self::A<self::A<self::A<core::int>>> x) → dynamic
+    return throw 42;
+  method barBar23<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+    return throw 42;
+}
+static method foo() → dynamic {
+  self::A<self::A<core::int>> x1;
+  self::A<self::A<self::A<core::int>>> x2;
+}
+static method bar1a() → self::A<self::A<core::int>>
+  return throw 42;
+static method bar1b() → self::A<self::A<self::A<core::int>>>
+  return throw 42;
+static method bar2a(self::A<self::A<core::int>> x) → dynamic
+  return throw 42;
+static method bar2b(self::A<self::A<self::A<core::int>>> x) → dynamic
+  return throw 42;
+static method bar3a<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+  return throw 42;
+static method bar3b<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+  return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.strong.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.strong.transformed.expect
new file mode 100644
index 0000000..7506643
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.strong.transformed.expect
@@ -0,0 +1,216 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:20:17: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3a<X extends B<A<int>>>() => throw 42;
+//                 ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:21:19: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3b<X extends A<B<A<int>>>>() => throw 42;
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:23:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar1<X extends B<A<int>>> {
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:26:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar13<X extends B<A<int>>>() => throw 42;
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:29:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar2<X extends A<B<A<int>>>> {
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:32:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar23<X extends A<B<A<int>>>>() => throw 42;
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:14:1: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// B<A<int>> bar1a() => throw 42;
+// ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:15:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// A<B<A<int>>> bar1b() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:17:7: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2a(B<A<int>> x) => throw 42;
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:18:9: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2b(A<B<A<int>>> x) => throw 42;
+//         ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:24:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<A<int>> barBar11() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:25:12: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar12(B<A<int>> x) => throw 42;
+//            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:30:5: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<B<A<int>>> barBar21() => throw 42;
+//     ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:31:14: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar22(A<B<A<int>>> x) => throw 42;
+//              ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:35:16: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz1 = B<A<int>>;
+//                ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:36:18: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz2 = A<B<A<int>>>;
+//                  ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:10:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<A<int>> x1;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:11:5: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<B<A<int>>> x2;
+//     ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B<X extends self::A<X> = self::A<dynamic>> = self::A<X>;
+typedef Baz1 = self::A<self::A<core::int>>;
+typedef Baz2 = self::A<self::A<self::A<core::int>>>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+}
+class Bar1<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>> extends core::Object {
+  synthetic constructor •() → self::Bar1<self::Bar1::X>
+    : super core::Object::•()
+    ;
+  method barBar11() → self::A<self::A<core::int>>
+    return throw 42;
+  method barBar12(self::A<self::A<core::int>> x) → dynamic
+    return throw 42;
+  method barBar13<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+    return throw 42;
+}
+class Bar2<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>> extends core::Object {
+  synthetic constructor •() → self::Bar2<self::Bar2::X>
+    : super core::Object::•()
+    ;
+  method barBar21() → self::A<self::A<self::A<core::int>>>
+    return throw 42;
+  method barBar22(self::A<self::A<self::A<core::int>>> x) → dynamic
+    return throw 42;
+  method barBar23<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+    return throw 42;
+}
+static method foo() → dynamic {
+  self::A<self::A<core::int>> x1;
+  self::A<self::A<self::A<core::int>>> x2;
+}
+static method bar1a() → self::A<self::A<core::int>>
+  return throw 42;
+static method bar1b() → self::A<self::A<self::A<core::int>>>
+  return throw 42;
+static method bar2a(self::A<self::A<core::int>> x) → dynamic
+  return throw 42;
+static method bar2b(self::A<self::A<self::A<core::int>>> x) → dynamic
+  return throw 42;
+static method bar3a<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+  return throw 42;
+static method bar3b<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+  return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.textual_outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.textual_outline.expect
new file mode 100644
index 0000000..2836a16
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+class A<T> {}
+typedef B<X extends A<X>> = A<X>;
+foo() {}
+B<A<int>> bar1a() => throw 42;
+A<B<A<int>>> bar1b() => throw 42;
+bar2a(B<A<int>> x) => throw 42;
+bar2b(A<B<A<int>>> x) => throw 42;
+bar3a<X extends B<A<int>>>() => throw 42;
+bar3b<X extends A<B<A<int>>>>() => throw 42;
+class Bar1<X extends B<A<int>>> {
+  B<A<int>> barBar11() => throw 42;
+  barBar12(B<A<int>> x) => throw 42;
+  barBar13<X extends B<A<int>>>() => throw 42;
+}
+class Bar2<X extends A<B<A<int>>>> {
+  A<B<A<int>>> barBar21() => throw 42;
+  barBar22(A<B<A<int>>> x) => throw 42;
+  barBar23<X extends A<B<A<int>>>>() => throw 42;
+}
+typedef Baz1 = B<A<int>>;
+typedef Baz2 = A<B<A<int>>>;
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.weak.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.weak.expect
new file mode 100644
index 0000000..7506643
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.weak.expect
@@ -0,0 +1,216 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:20:17: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3a<X extends B<A<int>>>() => throw 42;
+//                 ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:21:19: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3b<X extends A<B<A<int>>>>() => throw 42;
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:23:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar1<X extends B<A<int>>> {
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:26:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar13<X extends B<A<int>>>() => throw 42;
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:29:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar2<X extends A<B<A<int>>>> {
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:32:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar23<X extends A<B<A<int>>>>() => throw 42;
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:14:1: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// B<A<int>> bar1a() => throw 42;
+// ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:15:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// A<B<A<int>>> bar1b() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:17:7: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2a(B<A<int>> x) => throw 42;
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:18:9: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2b(A<B<A<int>>> x) => throw 42;
+//         ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:24:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<A<int>> barBar11() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:25:12: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar12(B<A<int>> x) => throw 42;
+//            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:30:5: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<B<A<int>>> barBar21() => throw 42;
+//     ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:31:14: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar22(A<B<A<int>>> x) => throw 42;
+//              ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:35:16: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz1 = B<A<int>>;
+//                ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:36:18: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz2 = A<B<A<int>>>;
+//                  ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:10:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<A<int>> x1;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:11:5: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<B<A<int>>> x2;
+//     ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B<X extends self::A<X> = self::A<dynamic>> = self::A<X>;
+typedef Baz1 = self::A<self::A<core::int>>;
+typedef Baz2 = self::A<self::A<self::A<core::int>>>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+}
+class Bar1<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>> extends core::Object {
+  synthetic constructor •() → self::Bar1<self::Bar1::X>
+    : super core::Object::•()
+    ;
+  method barBar11() → self::A<self::A<core::int>>
+    return throw 42;
+  method barBar12(self::A<self::A<core::int>> x) → dynamic
+    return throw 42;
+  method barBar13<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+    return throw 42;
+}
+class Bar2<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>> extends core::Object {
+  synthetic constructor •() → self::Bar2<self::Bar2::X>
+    : super core::Object::•()
+    ;
+  method barBar21() → self::A<self::A<self::A<core::int>>>
+    return throw 42;
+  method barBar22(self::A<self::A<self::A<core::int>>> x) → dynamic
+    return throw 42;
+  method barBar23<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+    return throw 42;
+}
+static method foo() → dynamic {
+  self::A<self::A<core::int>> x1;
+  self::A<self::A<self::A<core::int>>> x2;
+}
+static method bar1a() → self::A<self::A<core::int>>
+  return throw 42;
+static method bar1b() → self::A<self::A<self::A<core::int>>>
+  return throw 42;
+static method bar2a(self::A<self::A<core::int>> x) → dynamic
+  return throw 42;
+static method bar2b(self::A<self::A<self::A<core::int>>> x) → dynamic
+  return throw 42;
+static method bar3a<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+  return throw 42;
+static method bar3b<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+  return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.weak.outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.weak.outline.expect
new file mode 100644
index 0000000..e66dde1
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.weak.outline.expect
@@ -0,0 +1,194 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:20:17: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3a<X extends B<A<int>>>() => throw 42;
+//                 ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:21:19: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3b<X extends A<B<A<int>>>>() => throw 42;
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:23:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar1<X extends B<A<int>>> {
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:26:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar13<X extends B<A<int>>>() => throw 42;
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:29:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar2<X extends A<B<A<int>>>> {
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:32:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar23<X extends A<B<A<int>>>>() => throw 42;
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:14:1: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// B<A<int>> bar1a() => throw 42;
+// ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:15:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// A<B<A<int>>> bar1b() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:17:7: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2a(B<A<int>> x) => throw 42;
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:18:9: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2b(A<B<A<int>>> x) => throw 42;
+//         ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:24:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<A<int>> barBar11() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:25:12: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar12(B<A<int>> x) => throw 42;
+//            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:30:5: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<B<A<int>>> barBar21() => throw 42;
+//     ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:31:14: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar22(A<B<A<int>>> x) => throw 42;
+//              ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:35:16: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz1 = B<A<int>>;
+//                ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:36:18: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz2 = A<B<A<int>>>;
+//                  ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B<X extends self::A<X> = self::A<dynamic>> = self::A<X>;
+typedef Baz1 = self::A<self::A<core::int>>;
+typedef Baz2 = self::A<self::A<self::A<core::int>>>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    ;
+}
+class Bar1<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>> extends core::Object {
+  synthetic constructor •() → self::Bar1<self::Bar1::X>
+    ;
+  method barBar11() → self::A<self::A<core::int>>
+    ;
+  method barBar12(self::A<self::A<core::int>> x) → dynamic
+    ;
+  method barBar13<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+    ;
+}
+class Bar2<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>> extends core::Object {
+  synthetic constructor •() → self::Bar2<self::Bar2::X>
+    ;
+  method barBar21() → self::A<self::A<self::A<core::int>>>
+    ;
+  method barBar22(self::A<self::A<self::A<core::int>>> x) → dynamic
+    ;
+  method barBar23<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+    ;
+}
+static method foo() → dynamic
+  ;
+static method bar1a() → self::A<self::A<core::int>>
+  ;
+static method bar1b() → self::A<self::A<self::A<core::int>>>
+  ;
+static method bar2a(self::A<self::A<core::int>> x) → dynamic
+  ;
+static method bar2b(self::A<self::A<self::A<core::int>>> x) → dynamic
+  ;
+static method bar3a<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+  ;
+static method bar3b<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.weak.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.weak.transformed.expect
new file mode 100644
index 0000000..7506643
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart.weak.transformed.expect
@@ -0,0 +1,216 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:20:17: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3a<X extends B<A<int>>>() => throw 42;
+//                 ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:21:19: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar3b<X extends A<B<A<int>>>>() => throw 42;
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:23:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar1<X extends B<A<int>>> {
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:26:22: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar13<X extends B<A<int>>>() => throw 42;
+//                      ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:29:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class Bar2<X extends A<B<A<int>>>> {
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:32:24: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar23<X extends A<B<A<int>>>>() => throw 42;
+//                        ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:14:1: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// B<A<int>> bar1a() => throw 42;
+// ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:15:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// A<B<A<int>>> bar1b() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:17:7: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2a(B<A<int>> x) => throw 42;
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:18:9: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// bar2b(A<B<A<int>>> x) => throw 42;
+//         ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:24:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<A<int>> barBar11() => throw 42;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:25:12: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar12(B<A<int>> x) => throw 42;
+//            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:30:5: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<B<A<int>>> barBar21() => throw 42;
+//     ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:31:14: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   barBar22(A<B<A<int>>> x) => throw 42;
+//              ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:35:16: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz1 = B<A<int>>;
+//                ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:36:18: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef Baz2 = A<B<A<int>>>;
+//                  ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:10:3: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   B<A<int>> x1;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:11:5: Error: Type argument 'A<int>' doesn't conform to the bound 'A<X>' of the type variable 'X' on 'B'.
+//  - 'A' is from 'pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<B<A<int>>> x2;
+//     ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends A<X>> = A<X>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef B<X extends self::A<X> = self::A<dynamic>> = self::A<X>;
+typedef Baz1 = self::A<self::A<core::int>>;
+typedef Baz2 = self::A<self::A<self::A<core::int>>>;
+class A<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+}
+class Bar1<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>> extends core::Object {
+  synthetic constructor •() → self::Bar1<self::Bar1::X>
+    : super core::Object::•()
+    ;
+  method barBar11() → self::A<self::A<core::int>>
+    return throw 42;
+  method barBar12(self::A<self::A<core::int>> x) → dynamic
+    return throw 42;
+  method barBar13<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+    return throw 42;
+}
+class Bar2<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>> extends core::Object {
+  synthetic constructor •() → self::Bar2<self::Bar2::X>
+    : super core::Object::•()
+    ;
+  method barBar21() → self::A<self::A<self::A<core::int>>>
+    return throw 42;
+  method barBar22(self::A<self::A<self::A<core::int>>> x) → dynamic
+    return throw 42;
+  method barBar23<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+    return throw 42;
+}
+static method foo() → dynamic {
+  self::A<self::A<core::int>> x1;
+  self::A<self::A<self::A<core::int>>> x2;
+}
+static method bar1a() → self::A<self::A<core::int>>
+  return throw 42;
+static method bar1b() → self::A<self::A<self::A<core::int>>>
+  return throw 42;
+static method bar2a(self::A<self::A<core::int>> x) → dynamic
+  return throw 42;
+static method bar2b(self::A<self::A<self::A<core::int>>> x) → dynamic
+  return throw 42;
+static method bar3a<X extends self::A<self::A<core::int>> = self::A<self::A<core::int>>>() → dynamic
+  return throw 42;
+static method bar3b<X extends self::A<self::A<self::A<core::int>>> = self::A<self::A<self::A<core::int>>>>() → dynamic
+  return throw 42;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart
new file mode 100644
index 0000000..1317c74
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+foo() {
+  A<String> a;
+}
+
+typedef A<X extends int> = B<String>;
+typedef B<X extends int> = C<String>;
+typedef C<X extends int> = X;
+
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.strong.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.strong.expect
new file mode 100644
index 0000000..2b7816b
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.strong.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'C'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef B<X extends int> = C<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:11:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef C<X extends int> = X;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:9:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef A<X extends int> = B<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends int> = C<String>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:6:3: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<String> a;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends int> = B<String>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef A<unrelated X extends core::int = core::int> = core::String;
+typedef B<unrelated X extends core::int = core::int> = core::String;
+typedef C<X extends core::int = core::int> = X;
+static method foo() → dynamic {
+  core::String a;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.strong.transformed.expect
new file mode 100644
index 0000000..2b7816b
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.strong.transformed.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'C'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef B<X extends int> = C<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:11:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef C<X extends int> = X;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:9:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef A<X extends int> = B<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends int> = C<String>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:6:3: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<String> a;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends int> = B<String>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef A<unrelated X extends core::int = core::int> = core::String;
+typedef B<unrelated X extends core::int = core::int> = core::String;
+typedef C<X extends core::int = core::int> = X;
+static method foo() → dynamic {
+  core::String a;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.textual_outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.textual_outline.expect
new file mode 100644
index 0000000..ebe8a0b
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+foo() {}
+typedef A<X extends int> = B<String>;
+typedef B<X extends int> = C<String>;
+typedef C<X extends int> = X;
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.weak.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.weak.expect
new file mode 100644
index 0000000..2b7816b
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.weak.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'C'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef B<X extends int> = C<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:11:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef C<X extends int> = X;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:9:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef A<X extends int> = B<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends int> = C<String>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:6:3: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<String> a;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends int> = B<String>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef A<unrelated X extends core::int = core::int> = core::String;
+typedef B<unrelated X extends core::int = core::int> = core::String;
+typedef C<X extends core::int = core::int> = X;
+static method foo() → dynamic {
+  core::String a;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.weak.outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.weak.outline.expect
new file mode 100644
index 0000000..0649b07
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.weak.outline.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'C'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef B<X extends int> = C<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:11:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef C<X extends int> = X;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:9:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef A<X extends int> = B<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends int> = C<String>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef A<unrelated X extends core::int = core::int> = core::String;
+typedef B<unrelated X extends core::int = core::int> = core::String;
+typedef C<X extends core::int = core::int> = X;
+static method foo() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.weak.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.weak.transformed.expect
new file mode 100644
index 0000000..2b7816b
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart.weak.transformed.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'C'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef B<X extends int> = C<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:11:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef C<X extends int> = X;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:9:28: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// typedef A<X extends int> = B<String>;
+//                            ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:10:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends int> = C<String>;
+//           ^
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:6:3: Error: Type argument 'String' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<String> a;
+//   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_in_typedef.dart:9:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends int> = B<String>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef A<unrelated X extends core::int = core::int> = core::String;
+typedef B<unrelated X extends core::int = core::int> = core::String;
+typedef C<X extends core::int = core::int> = X;
+static method foo() → dynamic {
+  core::String a;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart
new file mode 100644
index 0000000..e08489b
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 {}
+
+typedef B<X extends String> = A;
+
+class C<Y extends B<int>> {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart
new file mode 100644
index 0000000..0123a2a
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 './aliased_checks_no_bodies_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.strong.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.strong.expect
new file mode 100644
index 0000000..381925d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.strong.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///aliased_checks_no_bodies_lib.dart";
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:9:19: Error: Type argument 'int' doesn't conform to the bound 'String' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class C<Y extends B<int>> {}
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends String> = A;
+//           ^
+//
+import self as self2;
+import "dart:core" as core;
+
+typedef B<unrelated X extends core::String = core::String> = self2::A;
+class A extends core::Object {
+  synthetic constructor •() → self2::A
+    : super core::Object::•()
+    ;
+}
+class C<Y extends self2::A = self2::A> extends core::Object {
+  synthetic constructor •() → self2::C<self2::C::Y>
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.strong.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.strong.transformed.expect
new file mode 100644
index 0000000..381925d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///aliased_checks_no_bodies_lib.dart";
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:9:19: Error: Type argument 'int' doesn't conform to the bound 'String' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class C<Y extends B<int>> {}
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends String> = A;
+//           ^
+//
+import self as self2;
+import "dart:core" as core;
+
+typedef B<unrelated X extends core::String = core::String> = self2::A;
+class A extends core::Object {
+  synthetic constructor •() → self2::A
+    : super core::Object::•()
+    ;
+}
+class C<Y extends self2::A = self2::A> extends core::Object {
+  synthetic constructor •() → self2::C<self2::C::Y>
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.textual_outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.textual_outline.expect
new file mode 100644
index 0000000..ac7da8d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import './aliased_checks_no_bodies_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ac7da8d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import './aliased_checks_no_bodies_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.weak.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.weak.expect
new file mode 100644
index 0000000..381925d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///aliased_checks_no_bodies_lib.dart";
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:9:19: Error: Type argument 'int' doesn't conform to the bound 'String' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class C<Y extends B<int>> {}
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends String> = A;
+//           ^
+//
+import self as self2;
+import "dart:core" as core;
+
+typedef B<unrelated X extends core::String = core::String> = self2::A;
+class A extends core::Object {
+  synthetic constructor •() → self2::A
+    : super core::Object::•()
+    ;
+}
+class C<Y extends self2::A = self2::A> extends core::Object {
+  synthetic constructor •() → self2::C<self2::C::Y>
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.weak.outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.weak.outline.expect
new file mode 100644
index 0000000..ecbd101
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.weak.outline.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///aliased_checks_no_bodies_lib.dart";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:9:19: Error: Type argument 'int' doesn't conform to the bound 'String' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class C<Y extends B<int>> {}
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends String> = A;
+//           ^
+//
+import self as self2;
+import "dart:core" as core;
+
+typedef B<unrelated X extends core::String = core::String> = self2::A;
+class A extends core::Object {
+  synthetic constructor •() → self2::A
+    ;
+}
+class C<Y extends self2::A = self2::A> extends core::Object {
+  synthetic constructor •() → self2::C<self2::C::Y>
+    ;
+}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.weak.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.weak.transformed.expect
new file mode 100644
index 0000000..381925d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_main.dart.weak.transformed.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///aliased_checks_no_bodies_lib.dart";
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:9:19: Error: Type argument 'int' doesn't conform to the bound 'String' of the type variable 'X' on 'B'.
+// Try changing type arguments so that they conform to the bounds.
+// class C<Y extends B<int>> {}
+//                   ^
+// pkg/front_end/testcases/nonfunction_type_aliases/aliased_checks_no_bodies_lib.dart:7:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef B<X extends String> = A;
+//           ^
+//
+import self as self2;
+import "dart:core" as core;
+
+typedef B<unrelated X extends core::String = core::String> = self2::A;
+class A extends core::Object {
+  synthetic constructor •() → self2::A
+    : super core::Object::•()
+    ;
+}
+class C<Y extends self2::A = self2::A> extends core::Object {
+  synthetic constructor •() → self2::C<self2::C::Y>
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart
new file mode 100644
index 0000000..2da162b
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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<X> {}
+typedef A<X extends num, Y> = C<X>;
+
+foo() {
+  new A<dynamic, String>();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.strong.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.strong.expect
new file mode 100644
index 0000000..0c361f8
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.strong.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart:9:7: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   new A<dynamic, String>();
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart:6:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends num, Y> = C<X>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%>
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  new self::C::•<dynamic>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.strong.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.strong.transformed.expect
new file mode 100644
index 0000000..0c361f8
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart:9:7: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   new A<dynamic, String>();
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart:6:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends num, Y> = C<X>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%>
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  new self::C::•<dynamic>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.textual_outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.textual_outline.expect
new file mode 100644
index 0000000..1eab745
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+class C<X> {}
+typedef A<X extends num, Y> = C<X>;
+foo() {}
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.weak.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.weak.expect
new file mode 100644
index 0000000..0c361f8
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.weak.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart:9:7: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   new A<dynamic, String>();
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart:6:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends num, Y> = C<X>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%>
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  new self::C::•<dynamic>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.weak.outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.weak.outline.expect
new file mode 100644
index 0000000..67117f8
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.weak.outline.expect
@@ -0,0 +1,13 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%>
+    ;
+}
+static method foo() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.weak.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.weak.transformed.expect
new file mode 100644
index 0000000..0c361f8
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart.weak.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart:9:7: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   new A<dynamic, String>();
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls.dart:6:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends num, Y> = C<X>;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%>
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  new self::C::•<dynamic>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart
new file mode 100644
index 0000000..c93b7d9
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 unaliased_bounds_checks_in_constructor_calls_with_parts_lib;
+
+part './unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart';
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart
new file mode 100644
index 0000000..9bf694a
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for 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 './unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.strong.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.strong.expect
new file mode 100644
index 0000000..afdc55d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.strong.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart";
+
+static method main() → dynamic {}
+
+library unaliased_bounds_checks_in_constructor_calls_with_parts_lib /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart:11:7: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   new A<dynamic, String>();
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart:8:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends num, Y> = C<X>;
+//           ^
+//
+import self as self2;
+import "dart:core" as core;
+
+part ./unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart;
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self2::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object { // from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart
+  synthetic constructor •() → self2::C<self2::C::X%>
+    : super core::Object::•()
+    ;
+}
+static method /* from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart */ foo() → dynamic {
+  new self2::C::•<dynamic>();
+}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.strong.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.strong.transformed.expect
new file mode 100644
index 0000000..afdc55d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.strong.transformed.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart";
+
+static method main() → dynamic {}
+
+library unaliased_bounds_checks_in_constructor_calls_with_parts_lib /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart:11:7: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   new A<dynamic, String>();
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart:8:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends num, Y> = C<X>;
+//           ^
+//
+import self as self2;
+import "dart:core" as core;
+
+part ./unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart;
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self2::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object { // from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart
+  synthetic constructor •() → self2::C<self2::C::X%>
+    : super core::Object::•()
+    ;
+}
+static method /* from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart */ foo() → dynamic {
+  new self2::C::•<dynamic>();
+}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.textual_outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.textual_outline.expect
new file mode 100644
index 0000000..c76bce2
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import './unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c76bce2
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import './unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.weak.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.weak.expect
new file mode 100644
index 0000000..afdc55d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.weak.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart";
+
+static method main() → dynamic {}
+
+library unaliased_bounds_checks_in_constructor_calls_with_parts_lib /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart:11:7: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   new A<dynamic, String>();
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart:8:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends num, Y> = C<X>;
+//           ^
+//
+import self as self2;
+import "dart:core" as core;
+
+part ./unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart;
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self2::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object { // from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart
+  synthetic constructor •() → self2::C<self2::C::X%>
+    : super core::Object::•()
+    ;
+}
+static method /* from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart */ foo() → dynamic {
+  new self2::C::•<dynamic>();
+}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.weak.outline.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.weak.outline.expect
new file mode 100644
index 0000000..d3cc16c
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.weak.outline.expect
@@ -0,0 +1,20 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart";
+
+static method main() → dynamic
+  ;
+
+library unaliased_bounds_checks_in_constructor_calls_with_parts_lib /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+part ./unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart;
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self2::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object { // from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart
+  synthetic constructor •() → self2::C<self2::C::X%>
+    ;
+}
+static method /* from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart */ foo() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.weak.transformed.expect b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.weak.transformed.expect
new file mode 100644
index 0000000..afdc55d
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_main.dart.weak.transformed.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_lib.dart";
+
+static method main() → dynamic {}
+
+library unaliased_bounds_checks_in_constructor_calls_with_parts_lib /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart:11:7: Error: Type argument 'dynamic' doesn't conform to the bound 'num' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   new A<dynamic, String>();
+//       ^
+// pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart:8:11: Context: This is the type variable whose bound isn't conformed to.
+// typedef A<X extends num, Y> = C<X>;
+//           ^
+//
+import self as self2;
+import "dart:core" as core;
+
+part ./unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart;
+typedef A<X extends core::num = core::num, unrelated Y extends core::Object? = dynamic> = self2::C<X>;
+class C<X extends core::Object? = dynamic> extends core::Object { // from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart
+  synthetic constructor •() → self2::C<self2::C::X%>
+    : super core::Object::•()
+    ;
+}
+static method /* from org-dartlang-testcase:///unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart */ foo() → dynamic {
+  new self2::C::•<dynamic>();
+}
diff --git a/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart
new file mode 100644
index 0000000..3ccd59b
--- /dev/null
+++ b/pkg/front_end/testcases/nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls_with_parts_part_lib.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of unaliased_bounds_checks_in_constructor_calls_with_parts_lib;
+
+class C<X> {}
+typedef A<X extends num, Y> = C<X>;
+
+foo() {
+  new A<dynamic, String>();
+}
+
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index b703c23..1ca31da 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -124,9 +124,12 @@
 nnbd_mixed/inheritance_from_opt_in: FormatterCrash
 nnbd_mixed/issue41597: FormatterCrash
 nnbd_mixed/null_safety_invalid_language_version: FormatterCrash
+nonfunction_type_aliases/aliased_checks: FormatterCrash
+nonfunction_type_aliases/aliased_checks_in_typedef: FormatterCrash
 nonfunction_type_aliases/issue41501: FormatterCrash
 nonfunction_type_aliases/issue42446: FormatterCrash
 nonfunction_type_aliases/issue45051: FormatterCrash
+nonfunction_type_aliases/unaliased_bounds_checks_in_constructor_calls: FormatterCrash
 rasta/bad_redirection: FormatterCrash
 rasta/issue_000032: FormatterCrash
 rasta/issue_000034: FormatterCrash
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index 0362d62..68492a3 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -187,12 +187,6 @@
         {})[uniqueIdentifierForSpan(node.offset, node.end)];
   }
 
-  /// If the given [node] is preceded by a `/*required*/` hint, returns the
-  /// HintComment for it; otherwise returns `null`.  See [recordRequiredHint].
-  HintComment getRequiredHint(Source source, FormalParameter node) {
-    return (_requiredHints[source] ?? {})[node.offset];
-  }
-
   /// If the given [expression] is followed by a null check hint (`/*!*/`),
   /// returns the HintComment for it; otherwise returns `null`.  See
   /// [recordNullCheckHint].
@@ -201,6 +195,12 @@
         {})[(uniqueIdentifierForSpan(expression.offset, expression.end))];
   }
 
+  /// If the given [node] is preceded by a `/*required*/` hint, returns the
+  /// HintComment for it; otherwise returns `null`.  See [recordRequiredHint].
+  HintComment getRequiredHint(Source source, FormalParameter node) {
+    return (_requiredHints[source] ?? {})[node.offset];
+  }
+
   /// Records conditional discard information for the given AST node (which is
   /// an `if` statement or a conditional (`?:`) expression).
   void recordConditionalDiscard(
@@ -268,12 +268,6 @@
         {})[uniqueIdentifierForSpan(node.offset, node.end)] = hintComment;
   }
 
-  /// Records that the given [node] was preceded by a `/*required*/` hint.
-  void recordRequiredHint(
-      Source source, FormalParameter node, HintComment hint) {
-    (_requiredHints[source] ??= {})[node.offset] = hint;
-  }
-
   /// Records that the given [expression] is followed by a null check hint
   /// (`/*!*/`), for later recall by [hasNullCheckHint].
   void recordNullCheckHint(
@@ -283,6 +277,12 @@
         hintComment;
   }
 
+  /// Records that the given [node] was preceded by a `/*required*/` hint.
+  void recordRequiredHint(
+      Source source, FormalParameter node, HintComment hint) {
+    (_requiredHints[source] ??= {})[node.offset] = hint;
+  }
+
   /// Records the fact that prior to migration, an unnecessary cast existed at
   /// [node].
   void recordUnnecessaryCast(Source source, AsExpression node) {
@@ -371,7 +371,8 @@
   /// Creates a decorated type for the given [element], which should come from
   /// an already-migrated library (or the SDK).
   DecoratedType _createDecoratedElementType(Element element) {
-    if (_graph.isBeingMigrated(element.library.source)) {
+    if (_graph.isBeingMigrated(element.library.source) &&
+        !_isLoadLibraryElement(element)) {
       var description;
       if (ElementTypeProvider.current is MigrationResolutionHooksImpl) {
         // Don't attempt to call toString() on element, or we will overflow.
@@ -429,6 +430,12 @@
     return result;
   }
 
+  bool _isLoadLibraryElement(Element element) =>
+      element.isSynthetic &&
+      element is FunctionElement &&
+      element.enclosingElement is LibraryElement &&
+      element.name == 'loadLibrary';
+
   /// Inverts the logic of [uniqueIdentifierForSpan], producing an (offset, end)
   /// pair.
   static OffsetEndPair spanForUniqueIdentifier(int span) {
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 97bac6d..ff70ada 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -4695,6 +4695,46 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_loadLibrary_call() async {
+    var testPath = convertPath('$testsPath/lib/test.dart');
+    var otherPath = convertPath('$testsPath/lib/other.dart');
+    var content = {
+      testPath: '''
+import 'other.dart' deferred as other;
+Future<Object> f() => other.loadLibrary();
+''',
+      otherPath: ''
+    };
+    var expected = {
+      testPath: '''
+import 'other.dart' deferred as other;
+Future<Object?> f() => other.loadLibrary();
+''',
+      otherPath: ''
+    };
+    await _checkMultipleFileChanges(content, expected);
+  }
+
+  Future<void> test_loadLibrary_tearOff() async {
+    var testPath = convertPath('$testsPath/lib/test.dart');
+    var otherPath = convertPath('$testsPath/lib/other.dart');
+    var content = {
+      testPath: '''
+import 'other.dart' deferred as other;
+Future<Object> Function() f() => other.loadLibrary;
+''',
+      otherPath: ''
+    };
+    var expected = {
+      testPath: '''
+import 'other.dart' deferred as other;
+Future<Object?> Function() f() => other.loadLibrary;
+''',
+      otherPath: ''
+    };
+    await _checkMultipleFileChanges(content, expected);
+  }
+
   Future<void> test_local_function() async {
     var content = '''
 int f(int i) {
diff --git a/pkg/scrape/example/null_aware.dart b/pkg/scrape/example/null_aware.dart
index 392798e..4437bd2 100644
--- a/pkg/scrape/example/null_aware.dart
+++ b/pkg/scrape/example/null_aware.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
-
 import 'package:scrape/scrape.dart';
 
 void main(List<String> arguments) {
@@ -235,7 +234,7 @@
     }
 
     if (parent is BinaryExpression) {
-      recordType('Uncategorized ${parent}');
+      recordType('Uncategorized $parent');
       return;
     }
 
diff --git a/pkg/vm/lib/transformations/pragma.dart b/pkg/vm/lib/transformations/pragma.dart
index d27f3d8..cde363a 100644
--- a/pkg/vm/lib/transformations/pragma.dart
+++ b/pkg/vm/lib/transformations/pragma.dart
@@ -13,6 +13,7 @@
 const kResultTypeUsesPassedTypeArguments =
     "result-type-uses-passed-type-arguments";
 const kRecognizedPragmaName = "vm:recognized";
+const kDisableUnboxedParametetersPragmaName = "vm:disable-unboxed-parameters";
 
 abstract class ParsedPragma {}
 
@@ -46,6 +47,10 @@
   ParsedRecognized(this.type);
 }
 
+class ParsedDisableUnboxedParameters extends ParsedPragma {
+  ParsedDisableUnboxedParameters();
+}
+
 abstract class PragmaAnnotationParser {
   /// May return 'null' if the annotation does not represent a recognized
   /// @pragma.
@@ -142,6 +147,8 @@
               "pragma: $options";
         }
         return new ParsedRecognized(type);
+      case kDisableUnboxedParametetersPragmaName:
+        return new ParsedDisableUnboxedParameters();
       default:
         return null;
     }
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index 7375c51..e24408b 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -233,6 +233,19 @@
         (expectedTypes == null || expectedTypes.contains(type));
   }
 
+  bool hasDisableUnboxedParameters(Member member) {
+    for (var annotation in member.annotations) {
+      ParsedPragma pragma = _matcher.parsePragma(annotation);
+      if (pragma is ParsedDisableUnboxedParameters) {
+        if (member.enclosingLibrary.importUri.scheme != "dart") {
+          throw "ERROR: Cannot use @pragma(vm:disable-unboxed-parameters) outside core libraries.";
+        }
+        return true;
+      }
+    }
+    return false;
+  }
+
   /// Simulate the execution of a native method by adding its entry points
   /// using [entryPointsListener]. Returns result type of the native method.
   TypeExpr handleNativeProcedure(
diff --git a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
index 792dc99..03f7ef2 100644
--- a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
+++ b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
@@ -203,7 +203,8 @@
         _nativeCodeOracle.isRecognized(member, const [
           PragmaRecognizedType.AsmIntrinsic,
           PragmaRecognizedType.Other
-        ]);
+        ]) ||
+        _nativeCodeOracle.hasDisableUnboxedParameters(member);
   }
 
   bool _isNative(Member member) => getExternalName(member) != null;
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index f729ce3..8608b32 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -31,6 +31,7 @@
 pause_on_exceptions_test: SkipByDesign # No incremental compiler available.
 rewind_optimized_out_test: SkipByDesign # No incremental compiler available.
 rewind_test: SkipByDesign # No incremental compiler available.
+sigquit_starts_service_test: SkipByDesign # Spawns a secondary process using Platform.executable.
 
 [ $compiler == dartk ]
 bad_reload_test: RuntimeError # Issue 34025
diff --git a/runtime/observatory_2/tests/service_2/service_2_kernel.status b/runtime/observatory_2/tests/service_2/service_2_kernel.status
index f56c520..227cb0a 100644
--- a/runtime/observatory_2/tests/service_2/service_2_kernel.status
+++ b/runtime/observatory_2/tests/service_2/service_2_kernel.status
@@ -31,6 +31,7 @@
 pause_on_exceptions_test: SkipByDesign # No incremental compiler available.
 rewind_optimized_out_test: SkipByDesign # No incremental compiler available.
 rewind_test: SkipByDesign # No incremental compiler available.
+sigquit_starts_service_test: SkipByDesign # Spawns a secondary process using Platform.executable.
 
 [ $compiler == dartk ]
 bad_reload_test: RuntimeError # Issue 34025
diff --git a/runtime/tools/dartfuzz/dartfuzz.dart b/runtime/tools/dartfuzz/dartfuzz.dart
index af137ed..8322ba6 100644
--- a/runtime/tools/dartfuzz/dartfuzz.dart
+++ b/runtime/tools/dartfuzz/dartfuzz.dart
@@ -16,7 +16,7 @@
 // Version of DartFuzz. Increase this each time changes are made
 // to preserve the property that a given version of DartFuzz yields
 // the same fuzzed program for a deterministic random seed.
-const String version = '1.88';
+const String version = '1.89';
 
 // Restriction on statements and expressions.
 const int stmtDepth = 1;
@@ -792,6 +792,7 @@
     emitLn('// Program generated as:');
     emitLn('//   dart dartfuzz.dart --seed $seed --${fp ? "" : "no-"}fp '
         '--${ffi ? "" : "no-"}ffi --${flatTp ? "" : "no-"}flat');
+    emitLn('// @dart=2.7');
     emitNewline();
     emitImport('dart:async');
     emitImport('dart:cli');
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index de299cd..49bbe05 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -224,33 +224,6 @@
   return false;
 }
 
-static bool HasLikelySmiOperand(InstanceCallInstr* instr) {
-  ASSERT(instr->type_args_len() == 0);
-
-  // If Smi is not assignable to the interface target of the call, the receiver
-  // is definitely not a Smi.
-  if (!instr->CanReceiverBeSmiBasedOnInterfaceTarget(
-          Thread::Current()->zone())) {
-    return false;
-  }
-
-  // Phis with at least one known smi are // guessed to be likely smi as well.
-  for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) {
-    PhiInstr* phi = instr->ArgumentAt(i)->AsPhi();
-    if (phi != NULL) {
-      for (intptr_t j = 0; j < phi->InputCount(); ++j) {
-        if (phi->InputAt(j)->Type()->ToCid() == kSmiCid) return true;
-      }
-    }
-  }
-  // If all of the inputs are known smis or the result of CheckedSmiOp,
-  // we guess the operand to be likely smi.
-  for (intptr_t i = 0; i < instr->ArgumentCount(); ++i) {
-    if (!instr->ArgumentAt(i)->IsCheckedSmiOp()) return false;
-  }
-  return true;
-}
-
 bool AotCallSpecializer::TryInlineFieldAccess(InstanceCallInstr* call) {
   const Token::Kind op_kind = call->token_kind();
   if ((op_kind == Token::kGET) && TryInlineInstanceGetter(call)) {
@@ -798,53 +771,6 @@
     }
   }
 
-  switch (instr->token_kind()) {
-    case Token::kEQ:
-    case Token::kNE:
-    case Token::kLT:
-    case Token::kLTE:
-    case Token::kGT:
-    case Token::kGTE: {
-      if (instr->BinaryFeedback().OperandsAre(kSmiCid) ||
-          HasLikelySmiOperand(instr)) {
-        ASSERT(receiver_idx == 0);
-        Definition* left = instr->ArgumentAt(0);
-        Definition* right = instr->ArgumentAt(1);
-        CheckedSmiComparisonInstr* smi_op = new (Z)
-            CheckedSmiComparisonInstr(instr->token_kind(), new (Z) Value(left),
-                                      new (Z) Value(right), instr);
-        ReplaceCall(instr, smi_op);
-        return;
-      }
-      break;
-    }
-    case Token::kSHL:
-    case Token::kSHR:
-    case Token::kUSHR:
-    case Token::kBIT_OR:
-    case Token::kBIT_XOR:
-    case Token::kBIT_AND:
-    case Token::kADD:
-    case Token::kSUB:
-    case Token::kMUL: {
-      if (instr->BinaryFeedback().OperandsAre(kSmiCid) ||
-          HasLikelySmiOperand(instr)) {
-        ASSERT(receiver_idx == 0);
-        Definition* left = instr->ArgumentAt(0);
-        Definition* right = instr->ArgumentAt(1);
-        CheckedSmiOpInstr* smi_op =
-            new (Z) CheckedSmiOpInstr(instr->token_kind(), new (Z) Value(left),
-                                      new (Z) Value(right), instr);
-
-        ReplaceCall(instr, smi_op);
-        return;
-      }
-      break;
-    }
-    default:
-      break;
-  }
-
   // No IC data checks. Try resolve target using the propagated cid.
   const intptr_t receiver_cid =
       instr->ArgumentValueAt(receiver_idx)->Type()->ToCid();
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index 4dff2a2..101ea94 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -91,179 +91,6 @@
   __ b(not_smi, NE);
 }
 
-void AsmIntrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
-  __ adds(R0, R0, Operand(R1));                      // Adds.
-  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, VC));       // Return if no overflow.
-  // Otherwise fall through.
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ subs(R0, R1, Operand(R0));  // Subtract.
-  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, VC));  // Return if no overflow.
-  // Otherwise fall through.
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
-  __ SmiUntag(R0);           // Untags R0. We only want result shifted by one.
-  __ smull(R0, IP, R0, R1);  // IP:R0 <- R0 * R1.
-  __ cmp(IP, Operand(R0, ASR, 31));
-  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, EQ));
-  __ Bind(normal_ir_body);  // Fall through on overflow.
-}
-
-// Optimizations:
-// - result is 0 if:
-//   - left is 0
-//   - left equals right
-// - result is left if
-//   - left > 0 && left < right
-// R1: Tagged left (dividend).
-// R0: Tagged right (divisor).
-// Returns:
-//   R1: Untagged fallthrough result (remainder to be adjusted), or
-//   R0: Tagged return result (remainder).
-static void EmitRemainderOperation(Assembler* assembler) {
-  Label modulo;
-  const Register left = R1;
-  const Register right = R0;
-  const Register result = R1;
-  const Register tmp = R2;
-  ASSERT(left == result);
-
-  // Check for quick zero results.
-  __ cmp(left, Operand(0));
-  __ mov(R0, Operand(0), EQ);
-  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, EQ));  // left is 0? Return 0.
-  __ cmp(left, Operand(right));
-  __ mov(R0, Operand(0), EQ);
-  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, EQ));  // left == right? Return 0.
-
-  // Check if result should be left.
-  __ cmp(left, Operand(0));
-  __ b(&modulo, LT);
-  // left is positive.
-  __ cmp(left, Operand(right));
-  // left is less than right, result is left.
-  __ mov(R0, Operand(left), LT);
-  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, LT));
-  __ Bind(&modulo);
-  // result <- left - right * (left / right)
-  __ SmiUntag(left);
-  __ SmiUntag(right);
-
-  __ IntegerDivide(tmp, left, right, D1, D0);
-
-  __ mls(result, right, tmp, left);  // result <- left - right * TMP
-}
-
-// Implementation:
-//  res = left % right;
-//  if (res < 0) {
-//    if (right < 0) {
-//      res = res - right;
-//    } else {
-//      res = res + right;
-//    }
-//  }
-void AsmIntrinsifier::Integer_mod(Assembler* assembler, Label* normal_ir_body) {
-  if (!TargetCPUFeatures::can_divide()) {
-    return;
-  }
-  // Check to see if we have integer division
-  __ ldr(R0, Address(SP, +0 * target::kWordSize));
-  __ ldr(R1, Address(SP, +1 * target::kWordSize));
-  __ orr(TMP, R0, Operand(R1));
-  __ tst(TMP, Operand(kSmiTagMask));
-  __ b(normal_ir_body, NE);
-  // R1: Tagged left (dividend).
-  // R0: Tagged right (divisor).
-  // Check if modulo by zero -> exception thrown in main function.
-  __ cmp(R0, Operand(0));
-  __ b(normal_ir_body, EQ);
-  EmitRemainderOperation(assembler);
-  // Untagged right in R0. Untagged remainder result in R1.
-
-  __ cmp(R1, Operand(0));
-  __ mov(R0, Operand(R1, LSL, 1), GE);  // Tag and move result to R0.
-  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, GE));
-  // Result is negative, adjust it.
-  __ cmp(R0, Operand(0));
-  __ sub(R0, R1, Operand(R0), LT);
-  __ add(R0, R1, Operand(R0), GE);
-  __ SmiTag(R0);
-  __ Ret();
-
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_truncDivide(Assembler* assembler,
-                                          Label* normal_ir_body) {
-  if (!TargetCPUFeatures::can_divide()) {
-    return;
-  }
-  // Check to see if we have integer division
-
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ cmp(R0, Operand(0));
-  __ b(normal_ir_body, EQ);  // If b is 0, fall through.
-
-  __ SmiUntag(R0);
-  __ SmiUntag(R1);
-
-  __ IntegerDivide(R0, R1, R0, D1, D0);
-
-  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
-  // cannot tag the result.
-  __ CompareImmediate(R0, 0x40000000);
-  __ SmiTag(R0, NE);  // Not equal. Okay to tag and return.
-  READS_RETURN_ADDRESS_FROM_LR(__ bx(LR, NE));
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_negate(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, +0 * target::kWordSize));  // Grab first argument.
-  __ tst(R0, Operand(kSmiTagMask));                 // Test for Smi.
-  __ b(normal_ir_body, NE);
-  __ rsbs(R0, R0, Operand(0));  // R0 is a Smi. R0 <- 0 - R0.
-  READS_RETURN_ADDRESS_FROM_LR(__ bx(
-      LR, VC));  // Return if there wasn't overflow, fall through otherwise.
-  // R0 is not a Smi. Fall through.
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitAnd(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
-  __ and_(R0, R0, Operand(R1));
-
-  __ Ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitOr(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
-  __ orr(R0, R0, Operand(R1));
-
-  __ Ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitXor(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
-  __ eor(R0, R0, Operand(R1));
-
-  __ Ret();
-  __ Bind(normal_ir_body);
-}
-
 void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
   ASSERT(kSmiTag == 0);
@@ -471,33 +298,6 @@
   Integer_equalToInteger(assembler, normal_ir_body);
 }
 
-void AsmIntrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // Shift amount in R0. Value to shift in R1.
-
-  // Fall through if shift amount is negative.
-  __ SmiUntag(R0);
-  __ CompareImmediate(R0, 0);
-  __ b(normal_ir_body, LT);
-
-  // If shift amount is bigger than 31, set to 31.
-  __ CompareImmediate(R0, 0x1F);
-  __ LoadImmediate(R0, 0x1F, GT);
-  __ SmiUntag(R1);
-  __ mov(R0, Operand(R1, ASR, R0));
-  __ SmiTag(R0);
-  __ Ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Smi_bitNegate(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * target::kWordSize));
-  __ mvn(R0, Operand(R0));
-  __ bic(R0, R0, Operand(kSmiTagMask));  // Remove inverted smi-tag.
-  __ Ret();
-}
-
 void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
                                     Label* normal_ir_body) {
   __ ldr(R0, Address(SP, 0 * target::kWordSize));
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index c3c64be..eede391 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -92,192 +92,6 @@
   __ BranchIfNotSmi(TMP, not_smi);
 }
 
-void AsmIntrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
-  __ adds(R0, R0, Operand(R1), kObjectBytes);        // Add.
-  __ b(normal_ir_body, VS);  // Fall-through on overflow.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ subs(R0, R1, Operand(R0), compiler::kObjectBytes);  // Subtract.
-  __ b(normal_ir_body, VS);  // Fall-through on overflow.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
-  __ SmiUntag(R0);  // Untags R6. We only want result shifted by one.
-
-#if !defined(DART_COMPRESSED_POINTERS)
-  __ mul(TMP, R0, R1);
-  __ smulh(TMP2, R0, R1);
-  // TMP: result bits 64..127.
-#else
-  __ smull(TMP, R0, R1);
-  __ AsrImmediate(TMP2, TMP, 31);
-  // TMP: result bits 32..63.
-#endif
-  __ cmp(TMP2, Operand(TMP, ASR, 63));
-  __ b(normal_ir_body, NE);
-  __ mov(R0, TMP);
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-// Optimizations:
-// - result is 0 if:
-//   - left is 0
-//   - left equals right
-// - result is left if
-//   - left > 0 && left < right
-// R1: Tagged left (dividend).
-// R0: Tagged right (divisor).
-// Returns:
-//   R1: Untagged fallthrough result (remainder to be adjusted), or
-//   R0: Tagged return result (remainder).
-static void EmitRemainderOperation(Assembler* assembler) {
-  Label return_zero, modulo;
-  const Register left = R1;
-  const Register right = R0;
-  const Register result = R1;
-  const Register tmp = R2;
-  ASSERT(left == result);
-
-  // Check for quick zero results.
-  __ CompareObjectRegisters(left, ZR);
-  __ b(&return_zero, EQ);
-  __ CompareObjectRegisters(left, right);
-  __ b(&return_zero, EQ);
-
-  // Check if result should be left.
-  __ CompareObjectRegisters(left, ZR);
-  __ b(&modulo, LT);
-  // left is positive.
-  __ CompareObjectRegisters(left, right);
-  // left is less than right, result is left.
-  __ b(&modulo, GT);
-  __ mov(R0, left);
-  __ ret();
-
-  __ Bind(&return_zero);
-  __ mov(R0, ZR);
-  __ ret();
-
-  __ Bind(&modulo);
-  // result <- left - right * (left / right)
-  __ SmiUntag(left);
-  __ SmiUntag(right);
-
-  __ sdiv(tmp, left, right, kObjectBytes);
-  __ msub(result, right, tmp, left,
-          kObjectBytes);  // result <- left - right * tmp
-}
-
-// Implementation:
-//  res = left % right;
-//  if (res < 0) {
-//    if (right < 0) {
-//      res = res - right;
-//    } else {
-//      res = res + right;
-//    }
-//  }
-void AsmIntrinsifier::Integer_mod(Assembler* assembler, Label* normal_ir_body) {
-  // Check to see if we have integer division
-  Label neg_remainder, fall_through;
-  __ ldr(R0, Address(SP, +0 * target::kWordSize));
-  __ ldr(R1, Address(SP, +1 * target::kWordSize));
-  __ orr(TMP, R0, Operand(R1));
-  __ BranchIfNotSmi(TMP, normal_ir_body);
-  // R1: Tagged left (dividend).
-  // R0: Tagged right (divisor).
-  // Check if modulo by zero -> exception thrown in main function.
-  __ CompareObjectRegisters(R0, ZR);
-  __ b(normal_ir_body, EQ);
-  EmitRemainderOperation(assembler);
-  // Untagged right in R0. Untagged remainder result in R1.
-
-  __ CompareObjectRegisters(R1, ZR);
-  __ b(&neg_remainder, LT);
-  __ SmiTag(R0, R1);  // Tag and move result to R0.
-  __ ret();
-
-  __ Bind(&neg_remainder);
-  // Result is negative, adjust it.
-  __ CompareObjectRegisters(R0, ZR);
-  __ sub(TMP, R1, Operand(R0), kObjectBytes);
-  __ add(TMP2, R1, Operand(R0), kObjectBytes);
-  __ csel(R0, TMP2, TMP, GE);
-  __ SmiTag(R0);
-  __ ret();
-
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_truncDivide(Assembler* assembler,
-                                          Label* normal_ir_body) {
-  // Check to see if we have integer division
-
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ CompareObjectRegisters(R0, ZR);
-  __ b(normal_ir_body, EQ);  // If b is 0, fall through.
-
-  __ SmiUntag(R0);
-  __ SmiUntag(R1);
-
-  __ sdiv(R0, R1, R0, kObjectBytes);
-
-  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
-  // cannot tag the result.
-#if !defined(DART_COMPRESSED_POINTERS)
-  __ CompareImmediate(R0, 0x4000000000000000);
-#else
-  __ CompareImmediate(R0, 0x40000000, compiler::kFourBytes);
-#endif
-  __ b(normal_ir_body, EQ);
-  __ SmiTag(R0);  // Not equal. Okay to tag and return.
-  __ ret();       // Return.
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_negate(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, +0 * target::kWordSize));  // Grab first argument.
-  __ BranchIfNotSmi(R0, normal_ir_body);
-  __ negs(R0, R0, kObjectBytes);
-  __ b(normal_ir_body, VS);
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitAnd(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
-  __ and_(R0, R0, Operand(R1));
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitOr(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
-  __ orr(R0, R0, Operand(R1));
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitXor(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
-  __ eor(R0, R0, Operand(R1));
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
   ASSERT(kSmiTag == 0);
@@ -396,38 +210,6 @@
   Integer_equalToInteger(assembler, normal_ir_body);
 }
 
-void AsmIntrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // Shift amount in R0. Value to shift in R1.
-
-  // Fall through if shift amount is negative.
-  __ SmiUntag(R0);
-  __ CompareObjectRegisters(R0, ZR);
-  __ b(normal_ir_body, LT);
-
-  // If shift amount is bigger than 63/31, set to 63/31.
-#if !defined(DART_COMPRESSED_POINTERS)
-  __ LoadImmediate(TMP, 0x3F);
-#else
-  __ LoadImmediate(TMP, 0x1F);
-#endif
-  __ CompareRegisters(R0, TMP);
-  __ csel(R0, TMP, R0, GT);
-  __ SmiUntag(R1);
-  __ asrv(R0, R1, R0, kObjectBytes);
-  __ SmiTag(R0);
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Smi_bitNegate(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * target::kWordSize));
-  __ mvn(R0, R0);
-  __ andi(R0, R0, Immediate(~kSmiTagMask));  // Remove inverted smi-tag.
-  __ ret();
-}
-
 void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
                                     Label* normal_ir_body) {
   __ ldr(R0, Address(SP, 0 * target::kWordSize));
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index a6d5e20..9cfe941 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -93,188 +93,6 @@
   __ j(NOT_ZERO, not_smi, Assembler::kNearJump);
 }
 
-void AsmIntrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ addl(EAX, Address(ESP, +2 * target::kWordSize));
-  __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
-  // Result is in EAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ movl(EBX, EAX);
-  __ movl(EAX, Address(ESP, +2 * target::kWordSize));
-  __ subl(EAX, EBX);
-  __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
-  // Result is in EAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  ASSERT(kSmiTag == 0);  // Adjust code below if not the case.
-  __ SmiUntag(EAX);
-  __ imull(EAX, Address(ESP, +2 * target::kWordSize));
-  __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
-  // Result is in EAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-// Optimizations:
-// - result is 0 if:
-//   - left is 0
-//   - left equals right
-// - result is left if
-//   - left > 0 && left < right
-// EAX: Tagged left (dividend).
-// EBX: Tagged right (divisor).
-// Returns:
-//   EDX: Untagged fallthrough result (remainder to be adjusted), or
-//   EAX: Tagged return result (remainder).
-static void EmitRemainderOperation(Assembler* assembler) {
-  Label return_zero, modulo;
-  // Check for quick zero results.
-  __ cmpl(EAX, Immediate(0));
-  __ j(EQUAL, &return_zero, Assembler::kNearJump);
-  __ cmpl(EAX, EBX);
-  __ j(EQUAL, &return_zero, Assembler::kNearJump);
-
-  // Check if result equals left.
-  __ cmpl(EAX, Immediate(0));
-  __ j(LESS, &modulo, Assembler::kNearJump);
-  // left is positive.
-  __ cmpl(EAX, EBX);
-  __ j(GREATER, &modulo, Assembler::kNearJump);
-  // left is less than right, result is left (EAX).
-  __ ret();
-
-  __ Bind(&return_zero);
-  __ xorl(EAX, EAX);
-  __ ret();
-
-  __ Bind(&modulo);
-  __ SmiUntag(EBX);
-  __ SmiUntag(EAX);
-  __ cdq();
-  __ idivl(EBX);
-}
-
-// Implementation:
-//  res = left % right;
-//  if (res < 0) {
-//    if (right < 0) {
-//      res = res - right;
-//    } else {
-//      res = res + right;
-//    }
-//  }
-void AsmIntrinsifier::Integer_mod(Assembler* assembler, Label* normal_ir_body) {
-  Label subtract;
-  __ movl(EAX, Address(ESP, +2 * target::kWordSize));
-  __ movl(EBX, Address(ESP, +1 * target::kWordSize));
-  __ orl(EBX, EAX);
-  __ testl(EBX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, normal_ir_body);
-  __ movl(EBX, Address(ESP, +1 * target::kWordSize));
-  // EAX: Tagged left (dividend).
-  // EBX: Tagged right (divisor).
-  // Check if modulo by zero -> exception thrown in main function.
-  __ cmpl(EBX, Immediate(0));
-  __ j(EQUAL, normal_ir_body, Assembler::kNearJump);
-  EmitRemainderOperation(assembler);
-  // Untagged remainder result in EDX.
-  Label done;
-  __ movl(EAX, EDX);
-  __ cmpl(EAX, Immediate(0));
-  __ j(GREATER_EQUAL, &done, Assembler::kNearJump);
-  // Result is negative, adjust it.
-  __ cmpl(EBX, Immediate(0));
-  __ j(LESS, &subtract, Assembler::kNearJump);
-  __ addl(EAX, EBX);
-  __ SmiTag(EAX);
-  __ ret();
-
-  __ Bind(&subtract);
-  __ subl(EAX, EBX);
-
-  __ Bind(&done);
-  // The remainder of two smis is always a smi, no overflow check needed.
-  __ SmiTag(EAX);
-  __ ret();
-
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_truncDivide(Assembler* assembler,
-                                          Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // EAX: right argument (divisor)
-  __ cmpl(EAX, Immediate(0));
-  __ j(EQUAL, normal_ir_body, Assembler::kNearJump);
-  __ movl(EBX, EAX);
-  __ SmiUntag(EBX);
-  __ movl(EAX,
-          Address(ESP, +2 * target::kWordSize));  // Left argument (dividend).
-  __ SmiUntag(EAX);
-  __ pushl(EDX);  // Preserve EDX in case of 'fall_through'.
-  __ cdq();
-  __ idivl(EBX);
-  __ popl(EDX);
-  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
-  // cannot tag the result.
-  __ cmpl(EAX, Immediate(0x40000000));
-  __ j(EQUAL, normal_ir_body);
-  __ SmiTag(EAX);
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_negate(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
-  __ testl(EAX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, normal_ir_body, Assembler::kNearJump);  // Non-smi value.
-  __ negl(EAX);
-  __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
-  // Result is in EAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitAnd(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
-  __ andl(EAX, EBX);
-  // Result is in EAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitOr(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
-  __ orl(EAX, EBX);
-  // Result is in EAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitXor(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
-  __ xorl(EAX, EBX);
-  // Result is in EAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
   ASSERT(kSmiTag == 0);
@@ -483,40 +301,7 @@
   Integer_equalToInteger(assembler, normal_ir_body);
 }
 
-void AsmIntrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
-  Label shift_count_ok;
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // Can destroy ECX since we are not falling through.
-  const Immediate& count_limit = Immediate(0x1F);
-  // Check that the count is not larger than what the hardware can handle.
-  // For shifting right a Smi the result is the same for all numbers
-  // >= count_limit.
-  __ SmiUntag(EAX);
-  // Negative counts throw exception.
-  __ cmpl(EAX, Immediate(0));
-  __ j(LESS, normal_ir_body, Assembler::kNearJump);
-  __ cmpl(EAX, count_limit);
-  __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump);
-  __ movl(EAX, count_limit);
-  __ Bind(&shift_count_ok);
-  __ movl(ECX, EAX);  // Shift amount must be in ECX.
-  __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // Value.
-  __ SmiUntag(EAX);                                    // Value.
-  __ sarl(EAX, ECX);
-  __ SmiTag(EAX);
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 // Argument is Smi (receiver).
-void AsmIntrinsifier::Smi_bitNegate(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  __ movl(EAX, Address(ESP, +1 * target::kWordSize));  // Receiver.
-  __ notl(EAX);
-  __ andl(EAX, Immediate(~kSmiTagMask));  // Remove inverted smi-tag.
-  __ ret();
-}
-
 void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
                                     Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 9cf721d..cf4fcb3 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -90,260 +90,6 @@
   __ j(NOT_ZERO, not_smi);
 }
 
-void AsmIntrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // RAX contains right argument.
-  __ OBJ(add)(RAX, Address(RSP, +2 * target::kWordSize));
-  __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
-  // Result is in RAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // RAX contains right argument, which is the actual subtrahend of subtraction.
-  __ movq(RCX, RAX);
-  __ movq(RAX, Address(RSP, +2 * target::kWordSize));
-  __ OBJ(sub)(RAX, RCX);
-  __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
-  // Result is in RAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // RAX is the right argument.
-  ASSERT(kSmiTag == 0);  // Adjust code below if not the case.
-  __ SmiUntag(RAX);
-  __ OBJ(imul)(RAX, Address(RSP, +2 * target::kWordSize));
-  __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
-  // Result is in RAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-// Optimizations:
-// - result is 0 if:
-//   - left is 0
-//   - left equals right
-// - result is left if
-//   - left > 0 && left < right
-// RAX: Tagged left (dividend).
-// RCX: Tagged right (divisor).
-// Returns:
-//   RAX: Untagged fallthrough result (remainder to be adjusted), or
-//   RAX: Tagged return result (remainder).
-static void EmitRemainderOperation(Assembler* assembler) {
-  Label return_zero, try_modulo, not_32bit, done;
-  // Check for quick zero results.
-  __ OBJ(cmp)(RAX, Immediate(0));
-  __ j(EQUAL, &return_zero, Assembler::kNearJump);
-  __ OBJ(cmp)(RAX, RCX);
-  __ j(EQUAL, &return_zero, Assembler::kNearJump);
-
-  // Check if result equals left.
-  __ OBJ(cmp)(RAX, Immediate(0));
-  __ j(LESS, &try_modulo, Assembler::kNearJump);
-  // left is positive.
-  __ OBJ(cmp)(RAX, RCX);
-  __ j(GREATER, &try_modulo, Assembler::kNearJump);
-  // left is less than right, result is left (RAX).
-  __ ret();
-
-  __ Bind(&return_zero);
-  __ xorq(RAX, RAX);
-  __ ret();
-
-  __ Bind(&try_modulo);
-
-#if !defined(DART_COMPRESSED_POINTERS)
-  // Check if both operands fit into 32bits as idiv with 64bit operands
-  // requires twice as many cycles and has much higher latency. We are checking
-  // this before untagging them to avoid corner case dividing INT_MAX by -1 that
-  // raises exception because quotient is too large for 32bit register.
-  __ movsxd(RBX, RAX);
-  __ cmpq(RBX, RAX);
-  __ j(NOT_EQUAL, &not_32bit, Assembler::kNearJump);
-  __ movsxd(RBX, RCX);
-  __ cmpq(RBX, RCX);
-  __ j(NOT_EQUAL, &not_32bit, Assembler::kNearJump);
-#endif
-
-  // Both operands are 31bit smis. Divide using 32bit idiv.
-  __ SmiUntag(RAX);
-  __ SmiUntag(RCX);
-  __ cdq();
-  __ idivl(RCX);
-  __ movsxd(RAX, RDX);
-#if !defined(DART_COMPRESSED_POINTERS)
-  __ jmp(&done, Assembler::kNearJump);
-
-  // Divide using 64bit idiv.
-  __ Bind(&not_32bit);
-  __ SmiUntag(RAX);
-  __ SmiUntag(RCX);
-  __ cqo();
-  __ idivq(RCX);
-  __ movq(RAX, RDX);
-  __ Bind(&done);
-#endif
-}
-
-// Implementation:
-//  res = left % right;
-//  if (res < 0) {
-//    if (right < 0) {
-//      res = res - right;
-//    } else {
-//      res = res + right;
-//    }
-//  }
-void AsmIntrinsifier::Integer_mod(Assembler* assembler, Label* normal_ir_body) {
-  Label negative_result;
-
-  __ movq(RAX, Address(RSP, +2 * target::kWordSize));
-  __ movq(RCX, Address(RSP, +1 * target::kWordSize));
-  __ orq(RCX, RAX);
-  __ testq(RCX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, normal_ir_body);
-  __ movq(RCX, Address(RSP, +1 * target::kWordSize));
-  // RAX: Tagged left (dividend).
-  // RCX: Tagged right (divisor).
-  __ OBJ(cmp)(RCX, Immediate(0));
-  __ j(EQUAL, normal_ir_body);
-  EmitRemainderOperation(assembler);
-  // Untagged remainder result in RAX.
-  __ OBJ(cmp)(RAX, Immediate(0));
-  __ j(LESS, &negative_result, Assembler::kNearJump);
-  __ SmiTag(RAX);
-  __ ret();
-
-  __ Bind(&negative_result);
-  Label subtract;
-  // RAX: Untagged result.
-  // RCX: Untagged right.
-  __ OBJ(cmp)(RCX, Immediate(0));
-  __ j(LESS, &subtract, Assembler::kNearJump);
-  __ OBJ(add)(RAX, RCX);
-  __ SmiTag(RAX);
-  __ ret();
-
-  __ Bind(&subtract);
-  __ OBJ(sub)(RAX, RCX);
-  __ SmiTag(RAX);
-  __ ret();
-
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_truncDivide(Assembler* assembler,
-                                          Label* normal_ir_body) {
-  Label not_32bit;
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // RAX: right argument (divisor)
-  __ OBJ(cmp)(RAX, Immediate(0));
-  __ j(EQUAL, normal_ir_body, Assembler::kNearJump);
-  __ movq(RCX, RAX);
-  __ movq(RAX,
-          Address(RSP, +2 * target::kWordSize));  // Left argument (dividend).
-
-#if !defined(DART_COMPRESSED_POINTERS)
-  // Check if both operands fit into 32bits as idiv with 64bit operands
-  // requires twice as many cycles and has much higher latency. We are checking
-  // this before untagging them to avoid corner case dividing INT_MAX by -1 that
-  // raises exception because quotient is too large for 32bit register.
-  __ movsxd(RBX, RAX);
-  __ cmpq(RBX, RAX);
-  __ j(NOT_EQUAL, &not_32bit);
-  __ movsxd(RBX, RCX);
-  __ cmpq(RBX, RCX);
-  __ j(NOT_EQUAL, &not_32bit);
-
-  // Both operands are 31bit smis. Divide using 32bit idiv.
-  __ SmiUntag(RAX);
-  __ SmiUntag(RCX);
-  __ cdq();
-  __ idivl(RCX);
-  __ movsxd(RAX, RAX);
-  __ SmiTag(RAX);  // Result is guaranteed to fit into a smi.
-  __ ret();
-
-  // Divide using 64bit idiv.
-  __ Bind(&not_32bit);
-  __ SmiUntag(RAX);
-  __ SmiUntag(RCX);
-  __ pushq(RDX);  // Preserve RDX in case of 'fall_through'.
-  __ cqo();
-  __ idivq(RCX);
-  __ popq(RDX);
-  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
-  // cannot tag the result.
-  __ cmpq(RAX, Immediate(0x4000000000000000));
-  __ j(EQUAL, normal_ir_body);
-  __ SmiTag(RAX);
-  __ ret();
-#else
-  // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
-  // cannot tag the result.
-  __ cmpq(RAX, Immediate(target::ToRawSmi(target::kSmiMin)));
-  __ j(EQUAL, normal_ir_body);
-
-  // Both operands are 31bit smis. Divide using 32bit idiv.
-  __ SmiUntag(RAX);
-  __ SmiUntag(RCX);
-  __ cdq();
-  __ idivl(RCX);
-  __ SmiTag(RAX);  // Result is guaranteed to fit into a smi.
-  __ movsxd(RAX, RAX);
-  __ ret();
-#endif
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_negate(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
-  __ testq(RAX, Immediate(kSmiTagMask));
-  __ j(NOT_ZERO, normal_ir_body, Assembler::kNearJump);  // Non-smi value.
-  __ OBJ(neg)(RAX);
-  __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
-  // Result is in RAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitAnd(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // RAX is the right argument.
-  __ andq(RAX, Address(RSP, +2 * target::kWordSize));
-  // Result is in RAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitOr(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // RAX is the right argument.
-  __ orq(RAX, Address(RSP, +2 * target::kWordSize));
-  // Result is in RAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-void AsmIntrinsifier::Integer_bitXor(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-  // RAX is the right argument.
-  __ xorq(RAX, Address(RSP, +2 * target::kWordSize));
-  // Result is in RAX.
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
 void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
   ASSERT(kSmiTag == 0);
@@ -471,43 +217,6 @@
   Integer_equalToInteger(assembler, normal_ir_body);
 }
 
-void AsmIntrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
-  Label shift_count_ok;
-  TestBothArgumentsSmis(assembler, normal_ir_body);
-#if !defined(DART_COMPRESSED_POINTERS)
-  const Immediate& count_limit = Immediate(0x3F);
-#else
-  const Immediate& count_limit = Immediate(0x1F);
-#endif
-  // Check that the count is not larger than what the hardware can handle.
-  // For shifting right a Smi the result is the same for all numbers
-  // >= count_limit.
-  __ SmiUntag(RAX);
-  // Negative counts throw exception.
-  __ OBJ(cmp)(RAX, Immediate(0));
-  __ j(LESS, normal_ir_body, Assembler::kNearJump);
-  __ OBJ(cmp)(RAX, count_limit);
-  __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump);
-  __ movq(RAX, count_limit);
-  __ Bind(&shift_count_ok);
-  __ movq(RCX, RAX);  // Shift amount must be in RCX.
-  __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // Value.
-  __ SmiUntag(RAX);                                    // Value.
-  __ OBJ(sar)(RAX, RCX);
-  __ SmiTag(RAX);
-  __ ret();
-  __ Bind(normal_ir_body);
-}
-
-// Argument is Smi (receiver).
-void AsmIntrinsifier::Smi_bitNegate(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +1 * target::kWordSize));  // Index.
-  __ OBJ(not )(RAX);
-  __ andq(RAX, Immediate(~kSmiTagMask));  // Remove inverted smi-tag.
-  __ ret();
-}
-
 void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
                                     Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 53ca92a..4f8e3aa 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -3928,18 +3928,19 @@
   intptr_t left_cid = this->left()->Type()->ToCid();
   intptr_t right_cid = this->right()->Type()->ToCid();
   bool combined_smi_check = false;
-  if (this->left()->definition() == this->right()->definition()) {
-    __ tst(left, compiler::Operand(kSmiTagMask));
+  if (FLAG_use_slow_path) {
+    __ b(slow_path->entry_label());
+  } else if (this->left()->definition() == this->right()->definition()) {
+    __ BranchIfNotSmi(left, slow_path->entry_label());
   } else if (left_cid == kSmiCid) {
-    __ tst(right, compiler::Operand(kSmiTagMask));
+    __ BranchIfNotSmi(right, slow_path->entry_label());
   } else if (right_cid == kSmiCid) {
-    __ tst(left, compiler::Operand(kSmiTagMask));
+    __ BranchIfNotSmi(left, slow_path->entry_label());
   } else {
     combined_smi_check = true;
     __ orr(result, left, compiler::Operand(right));
-    __ tst(result, compiler::Operand(kSmiTagMask));
+    __ BranchIfNotSmi(result, slow_path->entry_label());
   }
-  __ b(slow_path->entry_label(), NE);
   switch (op_kind()) {
     case Token::kADD:
       __ adds(result, left, compiler::Operand(right));
@@ -4148,17 +4149,18 @@
   Register temp = locs()->temp(0).reg();                                       \
   intptr_t left_cid = this->left()->Type()->ToCid();                           \
   intptr_t right_cid = this->right()->Type()->ToCid();                         \
-  if (this->left()->definition() == this->right()->definition()) {             \
-    __ tst(left, compiler::Operand(kSmiTagMask));                              \
+  if (FLAG_use_slow_path) {                                                    \
+    __ b(slow_path->entry_label());                                            \
+  } else if (this->left()->definition() == this->right()->definition()) {      \
+    __ BranchIfNotSmi(left, slow_path->entry_label());                         \
   } else if (left_cid == kSmiCid) {                                            \
-    __ tst(right, compiler::Operand(kSmiTagMask));                             \
+    __ BranchIfNotSmi(right, slow_path->entry_label());                        \
   } else if (right_cid == kSmiCid) {                                           \
-    __ tst(left, compiler::Operand(kSmiTagMask));                              \
+    __ BranchIfNotSmi(left, slow_path->entry_label());                         \
   } else {                                                                     \
     __ orr(temp, left, compiler::Operand(right));                              \
-    __ tst(temp, compiler::Operand(kSmiTagMask));                              \
-  }                                                                            \
-  __ b(slow_path->entry_label(), NE)
+    __ BranchIfNotSmi(temp, slow_path->entry_label());                         \
+  }
 
 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
                                                BranchInstr* branch) {
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 8cae728..f8a5f78 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -3492,7 +3492,9 @@
   intptr_t left_cid = this->left()->Type()->ToCid();
   intptr_t right_cid = this->right()->Type()->ToCid();
   bool combined_smi_check = false;
-  if (this->left()->definition() == this->right()->definition()) {
+  if (FLAG_use_slow_path) {
+    __ b(slow_path->entry_label());
+  } else if (this->left()->definition() == this->right()->definition()) {
     __ BranchIfNotSmi(left, slow_path->entry_label());
   } else if (left_cid == kSmiCid) {
     __ BranchIfNotSmi(right, slow_path->entry_label());
@@ -3672,7 +3674,9 @@
   Register temp = locs()->temp(0).reg();                                       \
   intptr_t left_cid = this->left()->Type()->ToCid();                           \
   intptr_t right_cid = this->right()->Type()->ToCid();                         \
-  if (this->left()->definition() == this->right()->definition()) {             \
+  if (FLAG_use_slow_path) {                                                    \
+    __ b(slow_path->entry_label());                                            \
+  } else if (this->left()->definition() == this->right()->definition()) {      \
     __ BranchIfNotSmi(left, slow_path->entry_label());                         \
   } else if (left_cid == kSmiCid) {                                            \
     __ BranchIfNotSmi(right, slow_path->entry_label());                        \
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index d3264b1..55eaf32 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -3600,18 +3600,19 @@
   intptr_t right_cid = right()->Type()->ToCid();
   Register left = locs()->in(0).reg();
   Register right = locs()->in(1).reg();
-  if (this->left()->definition() == this->right()->definition()) {
-    __ testq(left, compiler::Immediate(kSmiTagMask));
+  if (FLAG_use_slow_path) {
+    __ jmp(slow_path->entry_label());
+  } else if (this->left()->definition() == this->right()->definition()) {
+    __ BranchIfNotSmi(left, slow_path->entry_label());
   } else if (left_cid == kSmiCid) {
-    __ testq(right, compiler::Immediate(kSmiTagMask));
+    __ BranchIfNotSmi(right, slow_path->entry_label());
   } else if (right_cid == kSmiCid) {
-    __ testq(left, compiler::Immediate(kSmiTagMask));
+    __ BranchIfNotSmi(left, slow_path->entry_label());
   } else {
     __ movq(TMP, left);
     __ orq(TMP, right);
-    __ testq(TMP, compiler::Immediate(kSmiTagMask));
+    __ BranchIfNotSmi(TMP, slow_path->entry_label());
   }
-  __ j(NOT_ZERO, slow_path->entry_label());
   Register result = locs()->out(0).reg();
   switch (op_kind()) {
     case Token::kADD:
@@ -3791,18 +3792,19 @@
   intptr_t right_cid = right()->Type()->ToCid();                               \
   Register left = locs()->in(0).reg();                                         \
   Register right = locs()->in(1).reg();                                        \
-  if (this->left()->definition() == this->right()->definition()) {             \
-    __ testq(left, compiler::Immediate(kSmiTagMask));                          \
+  if (FLAG_use_slow_path) {                                                    \
+    __ jmp(slow_path->entry_label());                                          \
+  } else if (this->left()->definition() == this->right()->definition()) {      \
+    __ BranchIfNotSmi(left, slow_path->entry_label());                         \
   } else if (left_cid == kSmiCid) {                                            \
-    __ testq(right, compiler::Immediate(kSmiTagMask));                         \
+    __ BranchIfNotSmi(right, slow_path->entry_label());                        \
   } else if (right_cid == kSmiCid) {                                           \
-    __ testq(left, compiler::Immediate(kSmiTagMask));                          \
+    __ BranchIfNotSmi(left, slow_path->entry_label());                         \
   } else {                                                                     \
     __ movq(TMP, left);                                                        \
     __ orq(TMP, right);                                                        \
-    __ testq(TMP, compiler::Immediate(kSmiTagMask));                           \
-  }                                                                            \
-  __ j(NOT_ZERO, slow_path->entry_label())
+    __ BranchIfNotSmi(TMP, slow_path->entry_label());                          \
+  }
 
 void CheckedSmiComparisonInstr::EmitBranchCode(FlowGraphCompiler* compiler,
                                                BranchInstr* branch) {
diff --git a/runtime/vm/compiler/backend/typed_data_aot_test.cc b/runtime/vm/compiler/backend/typed_data_aot_test.cc
index 68bca62..557139a 100644
--- a/runtime/vm/compiler/backend/typed_data_aot_test.cc
+++ b/runtime/vm/compiler/backend/typed_data_aot_test.cc
@@ -208,8 +208,6 @@
           kMatchAndMoveLoadIndexed,
           kMoveGlob,
           // Store 1
-          kMatchAndMoveGenericCheckBound,
-          kMoveGlob,
           kMoveParallelMoves,
           kMatchAndMoveLoadUntagged,
           kMoveParallelMoves,
@@ -253,8 +251,6 @@
           kMatchAndMoveLoadIndexed,
           kMoveGlob,
           // Store 1
-          kMatchAndMoveGenericCheckBound,
-          kMoveGlob,
           kMoveParallelMoves,
           kMatchAndMoveLoadUntagged,
           kMoveParallelMoves,
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index cb294e9..e33e569 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -111,16 +111,7 @@
   }
 
   const Token::Kind op_kind = call->token_kind();
-  if (FLAG_guess_icdata_cid) {
-    if (CompilerState::Current().is_aot()) {
-      // In precompiler speculate that both sides of bitwise operation
-      // are Smi-s.
-      if (Token::IsBinaryBitwiseOperator(op_kind) &&
-          call->CanReceiverBeSmiBasedOnInterfaceTarget(zone())) {
-        class_ids[0] = kSmiCid;
-        class_ids[1] = kSmiCid;
-      }
-    }
+  if (FLAG_guess_icdata_cid && !CompilerState::Current().is_aot()) {
     if (Token::IsRelationalOperator(op_kind) ||
         Token::IsEqualityOperator(op_kind) ||
         Token::IsBinaryOperator(op_kind)) {
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 5397c82..d0ca36b 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -920,6 +920,98 @@
   return true;
 }
 
+static bool BuildUnarySmiOp(FlowGraph* flow_graph, Token::Kind op_kind) {
+  ASSERT(!flow_graph->function().has_unboxed_return());
+  ASSERT(!flow_graph->function().is_unboxed_parameter_at(0));
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+  Definition* left = builder.AddParameter(0, /*with_frame=*/false);
+  builder.AddInstruction(
+      new CheckSmiInstr(new Value(left), DeoptId::kNone, builder.Source()));
+  Definition* result = builder.AddDefinition(
+      new UnarySmiOpInstr(op_kind, new Value(left), DeoptId::kNone));
+  builder.AddReturn(new Value(result));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_Smi_bitNegate(FlowGraph* flow_graph) {
+  return BuildUnarySmiOp(flow_graph, Token::kBIT_NOT);
+}
+
+bool GraphIntrinsifier::Build_Integer_negate(FlowGraph* flow_graph) {
+  return BuildUnarySmiOp(flow_graph, Token::kNEGATE);
+}
+
+static bool BuildBinarySmiOp(FlowGraph* flow_graph, Token::Kind op_kind) {
+  ASSERT(!flow_graph->function().has_unboxed_return());
+  ASSERT(!flow_graph->function().is_unboxed_parameter_at(0));
+  ASSERT(!flow_graph->function().is_unboxed_parameter_at(1));
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+  Definition* left = builder.AddParameter(0, /*with_frame=*/false);
+  Definition* right = builder.AddParameter(1, /*with_frame=*/false);
+  builder.AddInstruction(
+      new CheckSmiInstr(new Value(left), DeoptId::kNone, builder.Source()));
+  builder.AddInstruction(
+      new CheckSmiInstr(new Value(right), DeoptId::kNone, builder.Source()));
+  Definition* result = builder.AddDefinition(new BinarySmiOpInstr(
+      op_kind, new Value(left), new Value(right), DeoptId::kNone));
+  builder.AddReturn(new Value(result));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_Integer_add(FlowGraph* flow_graph) {
+  return BuildBinarySmiOp(flow_graph, Token::kADD);
+}
+
+bool GraphIntrinsifier::Build_Integer_sub(FlowGraph* flow_graph) {
+  return BuildBinarySmiOp(flow_graph, Token::kSUB);
+}
+
+bool GraphIntrinsifier::Build_Integer_mul(FlowGraph* flow_graph) {
+  return BuildBinarySmiOp(flow_graph, Token::kMUL);
+}
+
+bool GraphIntrinsifier::Build_Integer_mod(FlowGraph* flow_graph) {
+#if defined(TARGET_ARCH_ARM)
+  if (!TargetCPUFeatures::can_divide()) {
+    return false;
+  }
+#endif
+  return BuildBinarySmiOp(flow_graph, Token::kMOD);
+}
+
+bool GraphIntrinsifier::Build_Integer_truncDivide(FlowGraph* flow_graph) {
+#if defined(TARGET_ARCH_ARM)
+  if (!TargetCPUFeatures::can_divide()) {
+    return false;
+  }
+#endif
+  return BuildBinarySmiOp(flow_graph, Token::kTRUNCDIV);
+}
+
+bool GraphIntrinsifier::Build_Integer_bitAnd(FlowGraph* flow_graph) {
+  return BuildBinarySmiOp(flow_graph, Token::kBIT_AND);
+}
+
+bool GraphIntrinsifier::Build_Integer_bitOr(FlowGraph* flow_graph) {
+  return BuildBinarySmiOp(flow_graph, Token::kBIT_OR);
+}
+
+bool GraphIntrinsifier::Build_Integer_bitXor(FlowGraph* flow_graph) {
+  return BuildBinarySmiOp(flow_graph, Token::kBIT_XOR);
+}
+
+bool GraphIntrinsifier::Build_Integer_sar(FlowGraph* flow_graph) {
+  return BuildBinarySmiOp(flow_graph, Token::kSHR);
+}
+
+bool GraphIntrinsifier::Build_Integer_shr(FlowGraph* flow_graph) {
+  return BuildBinarySmiOp(flow_graph, Token::kUSHR);
+}
+
 static Definition* ConvertOrUnboxDoubleParameter(BlockBuilder* builder,
                                                  Definition* value,
                                                  intptr_t index,
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 4ee61c5..6c22c21 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -206,7 +206,6 @@
 // List of intrinsics:
 // (class-name, function-name, intrinsification method, fingerprint).
 #define CORE_LIB_INTRINSIC_LIST(V)                                             \
-  V(_Smi, ~, Smi_bitNegate, 0x8254f51b)                                        \
   V(_Smi, get:bitLength, Smi_bitLength, 0x7ab50ceb)                            \
   V(_BigIntImpl, _lsh, Bigint_lsh, 0x3f8b105e)                                 \
   V(_BigIntImpl, _rsh, Bigint_rsh, 0x117ed3f3)                                 \
@@ -257,15 +256,6 @@
   V(::, _setHash, Object_setHash, 0x8f2a5b0b)                                  \
 
 #define CORE_INTEGER_LIB_INTRINSIC_LIST(V)                                     \
-  V(_IntegerImplementation, +, Integer_add, 0xd561008f)                        \
-  V(_IntegerImplementation, -, Integer_sub, 0xc96a0f80)                        \
-  V(_IntegerImplementation, *, Integer_mul, 0xacd9641d)                        \
-  V(_IntegerImplementation, %, Integer_mod, 0xfcf7cc13)                        \
-  V(_IntegerImplementation, ~/, Integer_truncDivide, 0xdda49e7f)               \
-  V(_IntegerImplementation, unary-, Integer_negate, 0xf7a9a696)                \
-  V(_IntegerImplementation, &, Integer_bitAnd, 0x8b9d7c33)                     \
-  V(_IntegerImplementation, |, Integer_bitOr, 0x8f47f5eb)                      \
-  V(_IntegerImplementation, ^, Integer_bitXor, 0xd838bef2)                     \
   V(_IntegerImplementation, >, Integer_greaterThan, 0x402b12df)                \
   V(_IntegerImplementation, ==, Integer_equal, 0x509c9146)                     \
   V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger,           \
@@ -273,8 +263,7 @@
   V(_IntegerImplementation, <, Integer_lessThan, 0x39643178)                   \
   V(_IntegerImplementation, <=, Integer_lessEqualThan, 0x73d2a9f5)             \
   V(_IntegerImplementation, >=, Integer_greaterEqualThan, 0xbc280c13)          \
-  V(_IntegerImplementation, <<, Integer_shl, 0x766f00e5)                       \
-  V(_IntegerImplementation, >>, Integer_sar, 0x931fbb8a)                       \
+  V(_IntegerImplementation, <<, Integer_shl, 0x766f04a6)                       \
   V(_Double, toInt, DoubleToInteger, 0x676f1ce8)                               \
 
 #define MATH_LIB_INTRINSIC_LIST(V)                                             \
@@ -362,6 +351,18 @@
     0x17f90910)                                                                \
   V(_ExternalTwoByteString, codeUnitAt, ExternalTwoByteStringCodeUnitAt,       \
     0x17f90910)                                                                \
+  V(_Smi, ~, Smi_bitNegate, 0x8254f8dc)                                        \
+  V(_IntegerImplementation, +, Integer_add, 0xd5610450)                        \
+  V(_IntegerImplementation, -, Integer_sub, 0xc96a1341)                        \
+  V(_IntegerImplementation, *, Integer_mul, 0xacd967de)                        \
+  V(_IntegerImplementation, %, Integer_mod, 0xfcf7cfd4)                        \
+  V(_IntegerImplementation, ~/, Integer_truncDivide, 0xdda4a240)               \
+  V(_IntegerImplementation, unary-, Integer_negate, 0xf7a9aa57)                \
+  V(_IntegerImplementation, &, Integer_bitAnd, 0x8b9d7ff4)                     \
+  V(_IntegerImplementation, |, Integer_bitOr, 0x8f47f9ac)                      \
+  V(_IntegerImplementation, ^, Integer_bitXor, 0xd838c2b3)                     \
+  V(_IntegerImplementation, >>, Integer_sar, 0x931fbf4b)                       \
+  V(_IntegerImplementation, >>>, Integer_shr, 0x7495fbad)                      \
   V(_Double, unary-, DoubleFlipSignBit, 0x3d39082b)                            \
   V(_Double, truncateToDouble, DoubleTruncate, 0x62d48298)                     \
   V(_Double, roundToDouble, DoubleRound, 0x5649c63f)                           \
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 47dc4cd..eb95276 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -66,13 +66,13 @@
     : debugger_(debugger),
       script_(script.ptr()),
       url_(script.url()),
+      line_number_(-1),  // lazily computed
       token_pos_(token_pos),
       end_token_pos_(end_token_pos),
       next_(NULL),
       conditions_(NULL),
       requested_line_number_(requested_line_number),
       requested_column_number_(requested_column_number),
-      function_(Function::null()),
       code_token_pos_(TokenPosition::kNoSource) {
   ASSERT(!script.IsNull());
   ASSERT(token_pos_.IsReal());
@@ -92,7 +92,6 @@
       conditions_(NULL),
       requested_line_number_(requested_line_number),
       requested_column_number_(requested_column_number),
-      function_(Function::null()),
       code_token_pos_(TokenPosition::kNoSource) {
   ASSERT(requested_line_number_ >= 0);
 }
@@ -116,7 +115,6 @@
   ASSERT(func.script() == script_);
   ASSERT(token_pos.IsWithin(func.token_pos(), func.end_token_pos()));
   ASSERT(func.is_debuggable());
-  function_ = func.ptr();
   token_pos_ = token_pos;
   end_token_pos_ = token_pos;
   code_token_pos_ = token_pos;
@@ -146,7 +144,6 @@
 void BreakpointLocation::VisitObjectPointers(ObjectPointerVisitor* visitor) {
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&script_));
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&url_));
-  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&function_));
 
   Breakpoint* bpt = conditions_;
   while (bpt != NULL) {
@@ -177,6 +174,23 @@
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&saved_value_));
 }
 
+const char* CodeBreakpoint::ToCString() const {
+  if (breakpoint_locations_.length() == 0) {
+    return "unlinked breakpoint";
+  }
+
+  char buffer[1024];
+  BufferFormatter f(buffer, sizeof(buffer));
+  // Pick the first, all other should have same script/line number.
+  BreakpointLocation* breakpoint_location = breakpoint_locations_.At(0);
+  Script& script = Script::Handle(breakpoint_location->script());
+  String& source_url = String::Handle(script.url());
+  intptr_t line_number = breakpoint_location->line_number();
+
+  f.Printf("breakpoint at %s:%" Pd, source_url.ToCString(), line_number);
+  return Thread::Current()->zone()->MakeCopyOfString(buffer);
+}
+
 ActivationFrame::ActivationFrame(uword pc,
                                  uword fp,
                                  uword sp,
@@ -1448,21 +1462,20 @@
                                UntaggedPcDescriptors::kRuntimeCall;
 
 CodeBreakpoint::CodeBreakpoint(const Code& code,
-                               TokenPosition token_pos,
+                               BreakpointLocation* breakpoint_location,
                                uword pc,
                                UntaggedPcDescriptors::Kind kind)
     : code_(code.ptr()),
-      token_pos_(token_pos),
       pc_(pc),
-      line_number_(-1),
       enabled_count_(0),
       next_(NULL),
       breakpoint_kind_(kind),
       saved_value_(Code::null()) {
   ASSERT(!code.IsNull());
-  ASSERT(token_pos_.IsReal());
   ASSERT(pc_ != 0);
   ASSERT((breakpoint_kind_ & kSafepointKind) != 0);
+  AddBreakpointLocation(breakpoint_location);
+  ASSERT(breakpoint_location->token_pos().IsReal());
 }
 
 CodeBreakpoint::~CodeBreakpoint() {
@@ -1477,29 +1490,6 @@
 #endif
 }
 
-FunctionPtr CodeBreakpoint::function() const {
-  return Code::Handle(code_).function();
-}
-
-ScriptPtr CodeBreakpoint::SourceCode() {
-  const Function& func = Function::Handle(this->function());
-  return func.script();
-}
-
-StringPtr CodeBreakpoint::SourceUrl() {
-  const Script& script = Script::Handle(SourceCode());
-  return script.url();
-}
-
-intptr_t CodeBreakpoint::LineNumber() {
-  // Compute line number lazily since it causes scanning of the script.
-  if (line_number_ < 0) {
-    const Script& script = Script::Handle(SourceCode());
-    script.GetTokenLocation(token_pos_, &line_number_);
-  }
-  return line_number_;
-}
-
 void CodeBreakpoint::Enable() {
   if (enabled_count_ == 0) {
     PatchCode();
@@ -2486,6 +2476,45 @@
   return TokenPosition::kNoSource;
 }
 
+bool BreakpointLocation::EnsureIsResolved(const Function& target_function,
+                                          TokenPosition exact_token_pos) {
+  if (IsResolved()) {
+    return true;
+  }
+
+  // Resolve source breakpoint in the newly compiled function.
+  TokenPosition resolved_pos =
+      ResolveBreakpointPos(target_function, token_pos(), end_token_pos(),
+                           requested_column_number(), exact_token_pos);
+  if (!resolved_pos.IsDebugPause()) {
+    if (FLAG_verbose_debug) {
+      OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
+                   target_function.ToFullyQualifiedCString());
+    }
+    return false;
+  }
+  TokenPosition requested_pos = token_pos();
+  TokenPosition requested_end_pos = end_token_pos();
+  SetResolved(target_function, resolved_pos);
+  Breakpoint* breakpoint = breakpoints();
+  while (breakpoint != nullptr) {
+    if (FLAG_verbose_debug) {
+      OS::PrintErr("Resolved breakpoint %" Pd
+                   " to pos %s, function '%s' (requested range %s-%s, "
+                   "requested col %" Pd ")\n",
+                   breakpoint->id(), token_pos().ToCString(),
+                   target_function.ToFullyQualifiedCString(),
+                   requested_pos.ToCString(), requested_end_pos.ToCString(),
+                   requested_column_number());
+    }
+    debugger()->SendBreakpointEvent(ServiceEvent::kBreakpointResolved,
+                                    breakpoint);
+    breakpoint = breakpoint->next();
+  }
+
+  return true;
+}
+
 void GroupDebugger::MakeCodeBreakpointAt(const Function& func,
                                          BreakpointLocation* loc) {
   ASSERT(loc->token_pos_.IsReal());
@@ -2514,8 +2543,7 @@
     CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
     if (code_bpt == nullptr) {
       // No code breakpoint for this code exists; create one.
-      code_bpt =
-          new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind);
+      code_bpt = new CodeBreakpoint(code, loc, lowest_pc, lowest_kind);
       if (FLAG_verbose_debug) {
         OS::PrintErr("Setting code breakpoint at pos %s pc %#" Px
                      " offset %#" Px "\n",
@@ -2531,8 +2559,8 @@
             loc->token_pos_.ToCString(), lowest_pc,
             lowest_pc - code.PayloadStart());
       }
+      code_bpt->AddBreakpointLocation(loc);
     }
-    code_bpt->AddBreakpointLocation(loc);
     if (loc->AnyEnabled()) {
       code_bpt->Enable();
     }
@@ -2777,14 +2805,11 @@
   TokenPosition breakpoint_pos = ResolveBreakpointPos(
       function, token_pos, last_token_pos, requested_column, exact_token_pos);
   if (!breakpoint_pos.IsReal()) {
-    return NULL;
+    return nullptr;
   }
-  // Find an existing resolved breakpoint location.
   BreakpointLocation* loc =
-      GetBreakpointLocation(script, TokenPosition::kNoSource,
-                            /* requested_line = */ -1,
-                            /* requested_column = */ -1, breakpoint_pos);
-  if (loc == NULL) {
+      GetResolvedBreakpointLocation(script, breakpoint_pos);
+  if (loc == nullptr) {
     // Find an existing unresolved breakpoint location.
     loc = GetBreakpointLocation(script, token_pos, requested_line,
                                 requested_column);
@@ -3792,11 +3817,11 @@
     // Hit a synthetic async breakpoint.
     if (FLAG_verbose_debug) {
       OS::PrintErr(
-          ">>> hit synthetic breakpoint at %s:%" Pd
+          ">>> hit synthetic %s"
           " (func %s token %s address %#" Px " offset %#" Px ")\n",
-          String::Handle(cbpt->SourceUrl()).ToCString(), cbpt->LineNumber(),
+          cbpt->ToCString(),
           String::Handle(top_frame->QualifiedFunctionName()).ToCString(),
-          cbpt->token_pos().ToCString(), top_frame->pc(),
+          bpt_location->token_pos().ToCString(), top_frame->pc(),
           top_frame->pc() - top_frame->code().PayloadStart());
     }
 
@@ -3815,12 +3840,12 @@
   }
 
   if (FLAG_verbose_debug) {
-    OS::PrintErr(">>> hit breakpoint %" Pd " at %s:%" Pd
+    OS::PrintErr(">>> hit %" Pd
+                 " %s"
                  " (func %s token %s address %#" Px " offset %#" Px ")\n",
-                 bpt_hit->id(), String::Handle(cbpt->SourceUrl()).ToCString(),
-                 cbpt->LineNumber(),
+                 bpt_hit->id(), cbpt->ToCString(),
                  String::Handle(top_frame->QualifiedFunctionName()).ToCString(),
-                 cbpt->token_pos().ToCString(), top_frame->pc(),
+                 bpt_location->token_pos().ToCString(), top_frame->pc(),
                  top_frame->pc() - top_frame->code().PayloadStart());
   }
 
@@ -3993,37 +4018,10 @@
       // There is no local function within func that contains the
       // breakpoint token position. Resolve the breakpoint if necessary
       // and set the code breakpoints.
-      if (!loc->IsResolved()) {
-        // Resolve source breakpoint in the newly compiled function.
-        TokenPosition bp_pos =
-            ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(),
-                                 loc->requested_column_number(), token_pos);
-        if (!bp_pos.IsDebugPause()) {
-          if (FLAG_verbose_debug) {
-            OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
-                         func.ToFullyQualifiedCString());
-          }
-          continue;
-        }
-        TokenPosition requested_pos = loc->token_pos();
-        TokenPosition requested_end_pos = loc->end_token_pos();
-        loc->SetResolved(func, bp_pos);
-        Breakpoint* bpt = loc->breakpoints();
-        while (bpt != NULL) {
-          if (FLAG_verbose_debug) {
-            OS::PrintErr(
-                "Resolved breakpoint %" Pd
-                " to pos %s, function '%s' (requested range %s-%s, "
-                "requested col %" Pd ")\n",
-                bpt->id(), loc->token_pos().ToCString(),
-                func.ToFullyQualifiedCString(), requested_pos.ToCString(),
-                requested_end_pos.ToCString(), loc->requested_column_number());
-          }
-          SendBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
-          bpt = bpt->next();
-        }
+      if (!loc->EnsureIsResolved(func, token_pos)) {
+        // Failed to resolve breakpoint location for some reason
+        continue;
       }
-      ASSERT(loc->IsResolved());
       if (FLAG_verbose_debug) {
         Breakpoint* bpt = loc->breakpoints();
         while (bpt != NULL) {
@@ -4328,6 +4326,20 @@
   needs_breakpoint_cleanup_ = false;
 }
 
+BreakpointLocation* Debugger::GetResolvedBreakpointLocation(
+    const Script& script,
+    TokenPosition code_token_pos) {
+  BreakpointLocation* loc = breakpoint_locations_;
+  while (loc != nullptr) {
+    if (loc->script_ == script.ptr() &&
+        loc->code_token_pos_ == code_token_pos) {
+      return loc;
+    }
+    loc = loc->next();
+  }
+  return nullptr;
+}
+
 BreakpointLocation* Debugger::GetBreakpointLocation(
     const Script& script,
     TokenPosition token_pos,
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index ff044ed..b1bf176 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -138,8 +138,14 @@
 
   ~BreakpointLocation();
 
-  FunctionPtr function() const { return function_; }
   TokenPosition token_pos() const { return token_pos_; }
+  intptr_t line_number() {
+    // Compute line number lazily since it causes scanning of the script.
+    if (line_number_ < 0) {
+      Script::Handle(script()).GetTokenLocation(token_pos(), &line_number_);
+    }
+    return line_number_;
+  }
   TokenPosition end_token_pos() const { return end_token_pos_; }
 
   ScriptPtr script() const { return script_; }
@@ -160,6 +166,9 @@
   bool IsResolved() const { return code_token_pos_.IsReal(); }
   bool IsLatent() const { return !token_pos_.IsReal(); }
 
+  bool EnsureIsResolved(const Function& target_function,
+                        TokenPosition exact_token_pos);
+
   Debugger* debugger() { return debugger_; }
 
  private:
@@ -181,6 +190,7 @@
   Debugger* debugger_;
   ScriptPtr script_;
   StringPtr url_;
+  intptr_t line_number_;  // lazily computed for token_pos_
   TokenPosition token_pos_;
   TokenPosition end_token_pos_;
   BreakpointLocation* next_;
@@ -189,7 +199,6 @@
   intptr_t requested_column_number_;
 
   // Valid for resolved breakpoints:
-  FunctionPtr function_;
   TokenPosition code_token_pos_;
 
   friend class Debugger;
@@ -211,37 +220,50 @@
 // is synchronized, guarded by mutexes.
 class CodeBreakpoint {
  public:
+  // Unless CodeBreakpoint is unlinked and is no longer used there should be at
+  // least one BreakpointLocation associated with CodeBreakpoint. If there are
+  // more BreakpointLocation added assumption is is that all of them point to
+  // the same source so have the same token pos.
   CodeBreakpoint(const Code& code,
-                 TokenPosition token_pos,
+                 BreakpointLocation* loc,
                  uword pc,
                  UntaggedPcDescriptors::Kind kind);
   ~CodeBreakpoint();
 
-  FunctionPtr function() const;
+  // Used by GroupDebugger to find CodeBreakpoint associated with
+  // particular function.
+  FunctionPtr function() const { return Code::Handle(code_).function(); }
+
   uword pc() const { return pc_; }
-  TokenPosition token_pos() const { return token_pos_; }
   bool HasBreakpointLocation(BreakpointLocation* breakpoint_location);
   bool FindAndDeleteBreakpointLocation(BreakpointLocation* breakpoint_location);
   bool HasNoBreakpointLocations() {
     return breakpoint_locations_.length() == 0;
   }
 
-  ScriptPtr SourceCode();
-  StringPtr SourceUrl();
-  intptr_t LineNumber();
-
   void Enable();
   void Disable();
   bool IsEnabled() const { return enabled_count_ > 0; }
 
   CodePtr OrigStubAddress() const;
 
+  const char* ToCString() const;
+
  private:
   void VisitObjectPointers(ObjectPointerVisitor* visitor);
 
+  // Finds right BreakpointLocation for a given Isolate's debugger.
   BreakpointLocation* FindBreakpointForDebugger(Debugger* debugger);
-  void AddBreakpointLocation(BreakpointLocation* value) {
-    breakpoint_locations_.Add(value);
+  // Adds new BreakpointLocation for another isolate that wants to
+  // break at the same function/code location that this CodeBreakpoint
+  // represents.
+  void AddBreakpointLocation(BreakpointLocation* breakpoint_location) {
+    ASSERT(breakpoint_locations_.length() == 0 ||
+           (breakpoint_location->token_pos() ==
+                breakpoint_locations_.At(0)->token_pos() &&
+            breakpoint_location->script() ==
+                breakpoint_locations_.At(0)->script()));
+    breakpoint_locations_.Add(breakpoint_location);
   }
 
   void set_next(CodeBreakpoint* value) { next_ = value; }
@@ -251,9 +273,7 @@
   void RestoreCode();
 
   CodePtr code_;
-  TokenPosition token_pos_;
   uword pc_;
-  intptr_t line_number_;
   int enabled_count_;  // incremented for every enabled breakpoint location
 
   // Breakpoint locations from different debuggers/isolates that
@@ -716,6 +736,9 @@
                                           intptr_t line,
                                           intptr_t column);
   void RegisterBreakpointLocation(BreakpointLocation* bpt);
+  BreakpointLocation* GetResolvedBreakpointLocation(
+      const Script& script,
+      TokenPosition code_token_pos);
   BreakpointLocation* GetBreakpointLocation(
       const Script& script,
       TokenPosition token_pos,
diff --git a/sdk/lib/_internal/vm/lib/integers.dart b/sdk/lib/_internal/vm/lib/integers.dart
index 123c964..95e3826 100644
--- a/sdk/lib/_internal/vm/lib/integers.dart
+++ b/sdk/lib/_internal/vm/lib/integers.dart
@@ -5,22 +5,26 @@
 // part of "core_patch.dart";
 
 abstract class _IntegerImplementation implements int {
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   num operator +(num other) => other._addFromInteger(this);
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   num operator -(num other) => other._subFromInteger(this);
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   num operator *(num other) => other._mulFromInteger(this);
 
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   int operator ~/(num other) {
     if ((other is int) && (other == 0)) {
       throw const IntegerDivisionByZeroException();
@@ -32,9 +36,10 @@
     return this.toDouble() / other.toDouble();
   }
 
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   num operator %(num other) {
     if ((other is int) && (other == 0)) {
       throw const IntegerDivisionByZeroException();
@@ -42,26 +47,30 @@
     return other._moduloFromInteger(this);
   }
 
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   int operator -() {
     // Issue(https://dartbug.com/39639): The analyzer incorrectly reports the
     // result type as `num`.
     return unsafeCast<int>(0 - this);
   }
 
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   int operator &(int other) => other._bitAndFromInteger(this);
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   int operator |(int other) => other._bitOrFromInteger(this);
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   int operator ^(int other) => other._bitXorFromInteger(this);
 
   num remainder(num other) {
@@ -96,15 +105,20 @@
     return unsafeCast<int>(other - (other ~/ this) * this);
   }
 
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   int operator >>(int other) => other._shrFromInteger(this);
+  @pragma("vm:recognized", "graph-intrinsic")
+  @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   int operator >>>(int other) => other._ushrFromInteger(this);
   @pragma("vm:recognized", "asm-intrinsic")
   @pragma("vm:non-nullable-result-type")
   @pragma("vm:never-inline")
+  @pragma("vm:disable-unboxed-parameters")
   int operator <<(int other) => other._shlFromInteger(this);
 
   @pragma("vm:recognized", "asm-intrinsic")
@@ -540,8 +554,9 @@
 
   int get hashCode => this;
   int get _identityHashCode => this;
-  @pragma("vm:recognized", "asm-intrinsic")
+  @pragma("vm:recognized", "graph-intrinsic")
   @pragma("vm:exact-result-type", "dart:core#_Smi")
+  @pragma("vm:disable-unboxed-parameters")
   int operator ~() native "Smi_bitNegate";
   @pragma("vm:recognized", "asm-intrinsic")
   @pragma("vm:exact-result-type", "dart:core#_Smi")
diff --git a/sdk/lib/core/symbol.dart b/sdk/lib/core/symbol.dart
index d9e2540..6a3566a 100644
--- a/sdk/lib/core/symbol.dart
+++ b/sdk/lib/core/symbol.dart
@@ -29,8 +29,8 @@
   /// * such an identifier followed by "=" (a setter name),
   /// * the name of a declarable operator
   ///   (one of "`+`", "`-`", "`*`", "`/`", "`%`", "`~/`", "`&`", "`|`",
-  ///   "`^`", "`~`", "`<<`", "`>>`", "`<`", "`<=`", "`>`", "`>=`", "`==`",
-  ///   "`[]`", "`[]=`", or "`unary-`"),
+  ///   "`^`", "`~`", "`<<`", "`>>`", "`>>>`", "`<`", "`<=`", "`>`", "`>=`",
+  ///   "`==`", "`[]`", "`[]=`", or "`unary-`"),
   /// * any of the above preceded by any number of qualifiers,
   ///   where a qualifier is a non-private identifier followed by '`.`',
   /// * or the empty string (the default name of a library with no library
diff --git a/sdk/lib/internal/symbol.dart b/sdk/lib/internal/symbol.dart
index bf48493..c65e5e8 100644
--- a/sdk/lib/internal/symbol.dart
+++ b/sdk/lib/internal/symbol.dart
@@ -50,7 +50,7 @@
    * is "unary-".
    */
   static const String operatorRE =
-      r'(?:[\-+*/%&|^]|\[\]=?|==|~/?|<[<=]?|>[>=]?|unary-)';
+      r'(?:[\-+*/%&|^]|\[\]=?|==|~/?|<[<=]?|>(?:|=|>>?)|unary-)';
 
   // Grammar if symbols:
   //    symbol ::= qualifiedName | <empty>
diff --git a/tests/language/const_functions/const_functions_do_statements_error_test.dart b/tests/language/const_functions/const_functions_do_statements_error_test.dart
index f48bab3..38a769f 100644
--- a/tests/language/const_functions/const_functions_do_statements_error_test.dart
+++ b/tests/language/const_functions/const_functions_do_statements_error_test.dart
@@ -33,3 +33,15 @@
   } while (x as dynamic);
   return 2;
 }
+
+const var3 = fn3();
+//           ^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int fn3() {
+  dynamic x = 0;
+  do {
+    x++;
+  } while (x);
+  return 2;
+}
diff --git a/tests/language/const_functions/const_functions_for_statements_error_test.dart b/tests/language/const_functions/const_functions_for_statements_error_test.dart
new file mode 100644
index 0000000..86b9908
--- /dev/null
+++ b/tests/language/const_functions/const_functions_for_statements_error_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests erroneous for statements for const functions.
+
+// SharedOptions=--enable-experiment=const-functions
+
+import "package:expect/expect.dart";
+
+const var1 = fn();
+//           ^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int fn() {
+  int val = 0;
+  for (; val;) {
+    //   ^^^
+    // [analyzer] COMPILE_TIME_ERROR.NON_BOOL_CONDITION
+    // [cfe] A value of type 'int' can't be assigned to a variable of type 'bool'.
+    val += 1;
+  }
+  return val;
+}
+
+const var2 = fn2();
+//           ^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int fn2() {
+  int val = 0;
+  for (; val as dynamic;) {
+    val += 1;
+  }
+  return val;
+}
+
+const var3 = fn3();
+//           ^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int fn3() {
+  dynamic val = 0;
+  for (; val;) {
+    val += 1;
+  }
+  return val;
+}
diff --git a/tests/language/const_functions/const_functions_if_statements_error_test.dart b/tests/language/const_functions/const_functions_if_statements_error_test.dart
new file mode 100644
index 0000000..31a25d5
--- /dev/null
+++ b/tests/language/const_functions/const_functions_if_statements_error_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests erroneous if statements for const functions.
+
+// SharedOptions=--enable-experiment=const-functions
+
+import "package:expect/expect.dart";
+
+const var1 = fn();
+//           ^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int fn() {
+  int val = 0;
+  if (val) {
+    //^^^
+    // [analyzer] COMPILE_TIME_ERROR.NON_BOOL_CONDITION
+    // [cfe] A value of type 'int' can't be assigned to a variable of type 'bool'.
+    val += 1;
+  }
+  return val;
+}
+
+const var2 = fn2();
+//           ^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int fn2() {
+  int val = 0;
+  if (val as dynamic) {
+    val += 1;
+  }
+  return val;
+}
+
+const var3 = fn3();
+//           ^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int fn3() {
+  dynamic val = 0;
+  if (val) {
+    val += 1;
+  }
+  return val;
+}
diff --git a/tests/language/const_functions/const_functions_while_statements_error_test.dart b/tests/language/const_functions/const_functions_while_statements_error_test.dart
new file mode 100644
index 0000000..1b7bc18
--- /dev/null
+++ b/tests/language/const_functions/const_functions_while_statements_error_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests erroneous while statements for const functions.
+
+// SharedOptions=--enable-experiment=const-functions
+
+import "package:expect/expect.dart";
+
+const var1 = fn();
+//           ^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+int fn() {
+  int val = 0;
+  while (val) {
+    //   ^^^
+    // [analyzer] COMPILE_TIME_ERROR.NON_BOOL_CONDITION
+    // [cfe] A value of type 'int' can't be assigned to a variable of type 'bool'.
+    val += 1;
+  }
+  return val;
+}
+
+const var2 = fn2();
+//           ^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int fn2() {
+  int val = 0;
+  while (val as dynamic) {
+    val += 1;
+  }
+  return val;
+}
+
+const var3 = fn3();
+//           ^^^^^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Constant evaluation error:
+int fn3() {
+  dynamic val = 0;
+  while (val) {
+    val += 1;
+  }
+  return val;
+}
diff --git a/tests/language/generic/function_typedef2_test.dart b/tests/language/generic/function_typedef2_test.dart
index 0ad79c5..6d9c0ff 100644
--- a/tests/language/generic/function_typedef2_test.dart
+++ b/tests/language/generic/function_typedef2_test.dart
@@ -11,19 +11,19 @@
 
 typedef G = F;
 //        ^
-// [analyzer] SYNTACTIC_ERROR.INVALID_GENERIC_FUNCTION_TYPE
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] Can't create typedef from non-function type.
 typedef H = int;
 //        ^
-// [analyzer] SYNTACTIC_ERROR.INVALID_GENERIC_FUNCTION_TYPE
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] Can't create typedef from non-function type.
 typedef I = A;
 //        ^
-// [analyzer] SYNTACTIC_ERROR.INVALID_GENERIC_FUNCTION_TYPE
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] Can't create typedef from non-function type.
 typedef J = List<int>;
 //        ^
-// [analyzer] SYNTACTIC_ERROR.INVALID_GENERIC_FUNCTION_TYPE
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] Can't create typedef from non-function type.
 typedef K = Function(Function<A>(A<int>));
 //                               ^^^^^^
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_type_variable_error_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_type_variable_error_test.dart
index 80b22b7..a0ee00c 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_type_variable_error_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_type_variable_error_test.dart
@@ -21,22 +21,45 @@
   // [cfe] unspecified
 }
 
-class D1<X> extends T<X> {}
-//                  ^
+class D {}
+mixin M {}
+
+abstract class D1<X> extends T<D> {}
+//                           ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
-abstract class D2 extends C with T<int> {}
+abstract class D2 extends C with T<M> {}
 //                               ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
-abstract class D3<X, Y> implements T<T> {}
+abstract class D3<X, Y> implements T<T<D>> {}
 //                                 ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
-abstract class D4 = C with T<void>;
+abstract class D4 = C with T<D>;
+//                         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+class D5<X> extends T<X> {}
+//                  ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+abstract class D6 extends C with T<int> {}
+//                               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+abstract class D7<X, Y> implements T<T> {}
+//                                 ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+abstract class D8 = C with T<void>;
 //                         ^
 // [analyzer] unspecified
 // [cfe] unspecified
diff --git a/tests/language/nonfunction_type_aliases/generic_usage_type_variable_test.dart b/tests/language/nonfunction_type_aliases/generic_usage_type_variable_test.dart
index 291fc7d..a9cd0c2 100644
--- a/tests/language/nonfunction_type_aliases/generic_usage_type_variable_test.dart
+++ b/tests/language/nonfunction_type_aliases/generic_usage_type_variable_test.dart
@@ -45,12 +45,6 @@
 }
 
 class D {}
-mixin M {}
-
-abstract class D1<X> extends T<D> {}
-abstract class D2 extends C with T<M> {}
-abstract class D3<X, Y> implements T<T<D>> {}
-abstract class D4 = C with T<D>;
 
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
diff --git a/tests/language/nonfunction_type_aliases/mixed/generic_usage_type_variable_error_test.dart b/tests/language/nonfunction_type_aliases/mixed/generic_usage_type_variable_error_test.dart
index a398f3b..cad1f88 100644
--- a/tests/language/nonfunction_type_aliases/mixed/generic_usage_type_variable_error_test.dart
+++ b/tests/language/nonfunction_type_aliases/mixed/generic_usage_type_variable_error_test.dart
@@ -23,22 +23,45 @@
   // [cfe] unspecified
 }
 
-class D1<X> extends T<X> {}
-//                  ^
+class D {}
+mixin M {}
+
+abstract class D1<X> extends T<D> {}
+//                           ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
-abstract class D2 extends C with T<int> {}
+abstract class D2 extends C with T<M> {}
 //                               ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
-abstract class D3<X, Y> implements T<T> {}
+abstract class D3<X, Y> implements T<T<D>> {}
 //                                 ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
-abstract class D4 = C with T<void>;
+abstract class D4 = C with T<D>;
+//                         ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+class D5<X> extends T<X> {}
+//                  ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+abstract class D6 extends C with T<int> {}
+//                               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+abstract class D7<X, Y> implements T<T> {}
+//                                 ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+abstract class D8 = C with T<void>;
 //                         ^
 // [analyzer] unspecified
 // [cfe] unspecified
diff --git a/tests/language/nonfunction_type_aliases/mixed/generic_usage_type_variable_test.dart b/tests/language/nonfunction_type_aliases/mixed/generic_usage_type_variable_test.dart
index 6e8688f..52b2f4b 100644
--- a/tests/language/nonfunction_type_aliases/mixed/generic_usage_type_variable_test.dart
+++ b/tests/language/nonfunction_type_aliases/mixed/generic_usage_type_variable_test.dart
@@ -47,16 +47,6 @@
 
 class D {}
 
-mixin M {}
-
-abstract class D1<X> extends T<D> {}
-
-abstract class D2 extends C with T<M> {}
-
-abstract class D3<X, Y> implements T<T<D>> {}
-
-abstract class D4 = C with T<D>;
-
 extension E on T<dynamic> {
   T<dynamic> foo(T<dynamic> t) => t;
 }
diff --git a/tests/language/nonfunction_type_aliases/mixed/usage_type_variable_error_test.dart b/tests/language/nonfunction_type_aliases/mixed/usage_type_variable_error_test.dart
index 840809b..a544e21 100644
--- a/tests/language/nonfunction_type_aliases/mixed/usage_type_variable_error_test.dart
+++ b/tests/language/nonfunction_type_aliases/mixed/usage_type_variable_error_test.dart
@@ -22,16 +22,28 @@
   // [cfe] unspecified
 }
 
+class D1 extends T {}
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
 abstract class D2 extends C with T {}
 //             ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
+abstract class D3 implements T {}
+//                           ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
 abstract class D4 = C with T;
 //             ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
+X foo<X>(X x) => x;
+
 main() {
   var v14 = <Set<T>, Set<T>>{{}: {}};
   v14[{}] = {T()};
diff --git a/tests/language/nonfunction_type_aliases/mixed/usage_type_variable_test.dart b/tests/language/nonfunction_type_aliases/mixed/usage_type_variable_test.dart
index d4212df..983f6a6 100644
--- a/tests/language/nonfunction_type_aliases/mixed/usage_type_variable_test.dart
+++ b/tests/language/nonfunction_type_aliases/mixed/usage_type_variable_test.dart
@@ -45,10 +45,6 @@
   noSuchMethod(Invocation invocation) => throw 0;
 }
 
-class D1 extends T {}
-
-abstract class D3 implements T {}
-
 extension E on T {
   T foo(T t) => t;
 }
@@ -60,7 +56,6 @@
 main() {
   var v13 = <T>[];
   var v14 = <Set<T>, Set<T>>{{}: {}};
-  v14[{}] = {D1()};
   var v15 = {v13};
   Set<List<T>> v16 = v15;
   v15 = v16;
diff --git a/tests/language/nonfunction_type_aliases/near_expand_to_type_variable_test.dart b/tests/language/nonfunction_type_aliases/near_expand_to_type_variable_test.dart
new file mode 100644
index 0000000..27c816f
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/near_expand_to_type_variable_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+typedef TB<T extends C> = T;
+typedef AC = C;  // Direct.
+typedef AEC = TB<C>;  // Explicit C argument.
+typedef AIC = TB;  // Implicit instantiate to bounds.
+
+class C {
+  static const c = 42;
+  static int s = 42;
+  final int y;
+  const C(this.y);
+  const C.name(this.y);
+}
+
+main() {
+  const c0 = AC.c;
+  const c1 = AEC.c;
+  const c2 = AIC.c;
+  Expect.equals(42, AC.s);
+  Expect.equals(42, AEC.s);
+  Expect.equals(42, AIC.s);
+  Expect.equals(0, AC(0).y);
+  Expect.equals(0, AEC(0).y);
+  Expect.equals(0, AIC(0).y);
+  Expect.equals(0, AC.name(0).y);
+  Expect.equals(0, AEC.name(0).y);
+  Expect.equals(0, AIC.name(0).y);
+}
diff --git a/tests/language/nonfunction_type_aliases/usage_type_variable_error_test.dart b/tests/language/nonfunction_type_aliases/usage_type_variable_error_test.dart
index b24e824..5a6ffb3 100644
--- a/tests/language/nonfunction_type_aliases/usage_type_variable_error_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_type_variable_error_test.dart
@@ -25,16 +25,29 @@
   // [cfe] unspecified
 }
 
+class D1 extends T {}
+//               ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
 abstract class D2 extends C with T {}
 //             ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
+abstract class D3 implements T {}
+//                           ^
+// [analyzer] unspecified
+// [cfe] unspecified
+
+
 abstract class D4 = C with T;
 //             ^
 // [analyzer] unspecified
 // [cfe] unspecified
 
+X foo<X>(X x) => x;
+
 main() {
   var v14 = <Set<T>, Set<T>>{{}: {}};
   v14[{}] = {T()};
diff --git a/tests/language/nonfunction_type_aliases/usage_type_variable_test.dart b/tests/language/nonfunction_type_aliases/usage_type_variable_test.dart
index 6c1b6c8..2c511b6 100644
--- a/tests/language/nonfunction_type_aliases/usage_type_variable_test.dart
+++ b/tests/language/nonfunction_type_aliases/usage_type_variable_test.dart
@@ -48,9 +48,6 @@
   noSuchMethod(Invocation invocation) => throw 0;
 }
 
-class D1 extends T {}
-abstract class D3 implements T {}
-
 extension E on T {
   T foo(T t) => t;
 }
@@ -62,7 +59,6 @@
 main() {
   var v13 = <T>[];
   var v14 = <Set<T>, Set<T>>{{}: {}};
-  v14[{}] = {D1()};
   var v15 = {v13};
   Set<List<T>> v16 = v15;
   v15 = v16;
diff --git a/tests/language/vm/checked_smi_comparison_test.dart b/tests/language/vm/checked_smi_comparison_test.dart
new file mode 100644
index 0000000..d22cb01
--- /dev/null
+++ b/tests/language/vm/checked_smi_comparison_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_slow_path
+
+import "package:expect/expect.dart";
+
+@pragma("vm:never-inline")
+dynamic hiddenSmi() {
+  try {
+    throw 42;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenMint() {
+  try {
+    throw 0x8000000000000000;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenDouble() {
+  try {
+    throw 3.0;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenCustom() {
+  try {
+    throw new Custom();
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+class Custom {
+  operator <(other) => "lt";
+  operator >(other) => "gt";
+  operator <=(other) => "le";
+  operator >=(other) => "ge";
+  operator ==(other) => false;
+}
+
+main() {
+  Expect.equals(false, hiddenSmi() < 2);
+  Expect.equals(true, hiddenSmi() > 2);
+  Expect.equals(false, hiddenSmi() <= 2);
+  Expect.equals(true, hiddenSmi() >= 2);
+  Expect.equals(false, hiddenSmi() == 2);
+  Expect.equals(true, hiddenSmi() != 2);
+
+  Expect.equals(true, hiddenMint() < 2);
+  Expect.equals(false, hiddenMint() > 2);
+  Expect.equals(true, hiddenMint() <= 2);
+  Expect.equals(false, hiddenMint() >= 2);
+  Expect.equals(false, hiddenMint() == 2);
+  Expect.equals(true, hiddenMint() != 2);
+
+  Expect.equals(false, hiddenDouble() < 2);
+  Expect.equals(true, hiddenDouble() > 2);
+  Expect.equals(false, hiddenDouble() <= 2);
+  Expect.equals(true, hiddenDouble() >= 2);
+  Expect.equals(false, hiddenDouble() == 2);
+  Expect.equals(true, hiddenDouble() != 2);
+
+  Expect.equals("lt", hiddenCustom() < 2);
+  Expect.equals("gt", hiddenCustom() > 2);
+  Expect.equals("le", hiddenCustom() <= 2);
+  Expect.equals("ge", hiddenCustom() >= 2);
+  Expect.equals(false, hiddenCustom() == 2);
+  Expect.equals(true, hiddenCustom() != 2);
+}
diff --git a/tests/language/vm/checked_smi_op_test.dart b/tests/language/vm/checked_smi_op_test.dart
new file mode 100644
index 0000000..f1ae4a6
--- /dev/null
+++ b/tests/language/vm/checked_smi_op_test.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=triple-shift
+// VMOptions=
+// VMOptions=--use_slow_path
+
+import "package:expect/expect.dart";
+
+@pragma("vm:never-inline")
+dynamic hiddenSmi() {
+  try {
+    throw 42;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenMint() {
+  try {
+    throw 0x8000000000000000;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenDouble() {
+  try {
+    throw 3.0;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenCustom() {
+  try {
+    throw new Custom();
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+class Custom {
+  operator +(other) => "add";
+  operator -(other) => "sub";
+  operator *(other) => "mul";
+  operator ~/(other) => "div";
+  operator %(other) => "mod";
+  operator &(other) => "and";
+  operator |(other) => "or";
+  operator ^(other) => "xor";
+  operator <<(other) => "sll";
+  operator >>(other) => "sra";
+  operator >>>(other) => "srl";
+}
+
+main() {
+  Expect.equals(44, hiddenSmi() + 2);
+  Expect.equals(40, hiddenSmi() - 2);
+  Expect.equals(84, hiddenSmi() * 2);
+  Expect.equals(21, hiddenSmi() ~/ 2);
+  Expect.equals(0, hiddenSmi() % 2);
+  Expect.equals(2, hiddenSmi() & 2);
+  Expect.equals(42, hiddenSmi() | 2);
+  Expect.equals(40, hiddenSmi() ^ 2);
+  Expect.equals(168, hiddenSmi() << 2);
+  Expect.equals(10, hiddenSmi() >> 2);
+  Expect.equals(10, hiddenSmi() >>> 2);
+
+  Expect.equals(-9223372036854775806, hiddenMint() + 2);
+  Expect.equals(9223372036854775806, hiddenMint() - 2);
+  Expect.equals(0, hiddenMint() * 2);
+  Expect.equals(-4611686018427387904, hiddenMint() ~/ 2);
+  Expect.equals(0, hiddenMint() % 2);
+  Expect.equals(0, hiddenMint() & 2);
+  Expect.equals(-9223372036854775806, hiddenMint() | 2);
+  Expect.equals(-9223372036854775806, hiddenMint() ^ 2);
+  Expect.equals(0, hiddenMint() << 2);
+  Expect.equals(-2305843009213693952, hiddenMint() >> 2);
+  Expect.equals(2305843009213693952, hiddenMint() >>> 2);
+
+  Expect.equals(5.0, hiddenDouble() + 2);
+  Expect.equals(1.0, hiddenDouble() - 2);
+  Expect.equals(6.0, hiddenDouble() * 2);
+  Expect.equals(1, hiddenDouble() ~/ 2);
+  Expect.equals(1.0, hiddenDouble() % 2);
+  Expect.throws(() => hiddenDouble() & 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() | 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() ^ 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() << 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() >> 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() >>> 2, (e) => e is NoSuchMethodError);
+
+  Expect.equals("add", hiddenCustom() + 2);
+  Expect.equals("sub", hiddenCustom() - 2);
+  Expect.equals("mul", hiddenCustom() * 2);
+  Expect.equals("div", hiddenCustom() ~/ 2);
+  Expect.equals("mod", hiddenCustom() % 2);
+  Expect.equals("and", hiddenCustom() & 2);
+  Expect.equals("or", hiddenCustom() | 2);
+  Expect.equals("xor", hiddenCustom() ^ 2);
+  Expect.equals("sll", hiddenCustom() << 2);
+  Expect.equals("sra", hiddenCustom() >> 2);
+  Expect.equals("srl", hiddenCustom() >>> 2);
+}
diff --git a/tests/language/vm/div_mod_test.dart b/tests/language/vm/div_mod_test.dart
index f534e67..ea22240 100755
--- a/tests/language/vm/div_mod_test.dart
+++ b/tests/language/vm/div_mod_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--deterministic
+// VMOptions=--deterministic --use_slow_path
 
 // Unit tests on DIV and MOV operations by various constants.
 
diff --git a/tests/language/vm/modtruncdiv_int_test.dart b/tests/language/vm/modtruncdiv_int_test.dart
index f5a51ce..9fc5b53 100644
--- a/tests/language/vm/modtruncdiv_int_test.dart
+++ b/tests/language/vm/modtruncdiv_int_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--no_background_compilation --optimization_counter_threshold=10
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/vm/mult_int_test.dart b/tests/language/vm/mult_int_test.dart
index b13cbd5..16df391 100644
--- a/tests/language/vm/mult_int_test.dart
+++ b/tests/language/vm/mult_int_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--no_background_compilation --optimization_counter_threshold=10
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/vm/negate_int_test.dart b/tests/language/vm/negate_int_test.dart
index 8703aef..253756e 100644
--- a/tests/language/vm/negate_int_test.dart
+++ b/tests/language/vm/negate_int_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--no_background_compilation --optimization_counter_threshold=10
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language/vm/shift_special_cases_test.dart b/tests/language/vm/shift_special_cases_test.dart
index 2cba918..b0fd2ed 100644
--- a/tests/language/vm/shift_special_cases_test.dart
+++ b/tests/language/vm/shift_special_cases_test.dart
@@ -1,7 +1,9 @@
 // Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 // VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation --use_slow_path
 
 // Test for special cases of << and >> integer operations with int64.
 
diff --git a/tests/language_2/generic/function_typedef2_test.dart b/tests/language_2/generic/function_typedef2_test.dart
index 704a824..b7ae03a 100644
--- a/tests/language_2/generic/function_typedef2_test.dart
+++ b/tests/language_2/generic/function_typedef2_test.dart
@@ -11,19 +11,19 @@
 
 typedef G = F;
 //        ^
-// [analyzer] SYNTACTIC_ERROR.INVALID_GENERIC_FUNCTION_TYPE
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] Can't create typedef from non-function type.
 typedef H = int;
 //        ^
-// [analyzer] SYNTACTIC_ERROR.INVALID_GENERIC_FUNCTION_TYPE
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] Can't create typedef from non-function type.
 typedef I = A;
 //        ^
-// [analyzer] SYNTACTIC_ERROR.INVALID_GENERIC_FUNCTION_TYPE
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] Can't create typedef from non-function type.
 typedef J = List<int>;
 //        ^
-// [analyzer] SYNTACTIC_ERROR.INVALID_GENERIC_FUNCTION_TYPE
+// [analyzer] SYNTACTIC_ERROR.EXPERIMENT_NOT_ENABLED
 // [cfe] Can't create typedef from non-function type.
 typedef K = Function(Function<A>(A<int>));
 //                               ^^^^^^
diff --git a/tests/language_2/vm/checked_smi_comparison_test.dart b/tests/language_2/vm/checked_smi_comparison_test.dart
new file mode 100644
index 0000000..d22cb01
--- /dev/null
+++ b/tests/language_2/vm/checked_smi_comparison_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_slow_path
+
+import "package:expect/expect.dart";
+
+@pragma("vm:never-inline")
+dynamic hiddenSmi() {
+  try {
+    throw 42;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenMint() {
+  try {
+    throw 0x8000000000000000;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenDouble() {
+  try {
+    throw 3.0;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenCustom() {
+  try {
+    throw new Custom();
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+class Custom {
+  operator <(other) => "lt";
+  operator >(other) => "gt";
+  operator <=(other) => "le";
+  operator >=(other) => "ge";
+  operator ==(other) => false;
+}
+
+main() {
+  Expect.equals(false, hiddenSmi() < 2);
+  Expect.equals(true, hiddenSmi() > 2);
+  Expect.equals(false, hiddenSmi() <= 2);
+  Expect.equals(true, hiddenSmi() >= 2);
+  Expect.equals(false, hiddenSmi() == 2);
+  Expect.equals(true, hiddenSmi() != 2);
+
+  Expect.equals(true, hiddenMint() < 2);
+  Expect.equals(false, hiddenMint() > 2);
+  Expect.equals(true, hiddenMint() <= 2);
+  Expect.equals(false, hiddenMint() >= 2);
+  Expect.equals(false, hiddenMint() == 2);
+  Expect.equals(true, hiddenMint() != 2);
+
+  Expect.equals(false, hiddenDouble() < 2);
+  Expect.equals(true, hiddenDouble() > 2);
+  Expect.equals(false, hiddenDouble() <= 2);
+  Expect.equals(true, hiddenDouble() >= 2);
+  Expect.equals(false, hiddenDouble() == 2);
+  Expect.equals(true, hiddenDouble() != 2);
+
+  Expect.equals("lt", hiddenCustom() < 2);
+  Expect.equals("gt", hiddenCustom() > 2);
+  Expect.equals("le", hiddenCustom() <= 2);
+  Expect.equals("ge", hiddenCustom() >= 2);
+  Expect.equals(false, hiddenCustom() == 2);
+  Expect.equals(true, hiddenCustom() != 2);
+}
diff --git a/tests/language_2/vm/checked_smi_op_test.dart b/tests/language_2/vm/checked_smi_op_test.dart
new file mode 100644
index 0000000..f1ae4a6
--- /dev/null
+++ b/tests/language_2/vm/checked_smi_op_test.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=triple-shift
+// VMOptions=
+// VMOptions=--use_slow_path
+
+import "package:expect/expect.dart";
+
+@pragma("vm:never-inline")
+dynamic hiddenSmi() {
+  try {
+    throw 42;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenMint() {
+  try {
+    throw 0x8000000000000000;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenDouble() {
+  try {
+    throw 3.0;
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+@pragma("vm:never-inline")
+dynamic hiddenCustom() {
+  try {
+    throw new Custom();
+  } catch (e) {
+    return e;
+  }
+  return 0;
+}
+
+class Custom {
+  operator +(other) => "add";
+  operator -(other) => "sub";
+  operator *(other) => "mul";
+  operator ~/(other) => "div";
+  operator %(other) => "mod";
+  operator &(other) => "and";
+  operator |(other) => "or";
+  operator ^(other) => "xor";
+  operator <<(other) => "sll";
+  operator >>(other) => "sra";
+  operator >>>(other) => "srl";
+}
+
+main() {
+  Expect.equals(44, hiddenSmi() + 2);
+  Expect.equals(40, hiddenSmi() - 2);
+  Expect.equals(84, hiddenSmi() * 2);
+  Expect.equals(21, hiddenSmi() ~/ 2);
+  Expect.equals(0, hiddenSmi() % 2);
+  Expect.equals(2, hiddenSmi() & 2);
+  Expect.equals(42, hiddenSmi() | 2);
+  Expect.equals(40, hiddenSmi() ^ 2);
+  Expect.equals(168, hiddenSmi() << 2);
+  Expect.equals(10, hiddenSmi() >> 2);
+  Expect.equals(10, hiddenSmi() >>> 2);
+
+  Expect.equals(-9223372036854775806, hiddenMint() + 2);
+  Expect.equals(9223372036854775806, hiddenMint() - 2);
+  Expect.equals(0, hiddenMint() * 2);
+  Expect.equals(-4611686018427387904, hiddenMint() ~/ 2);
+  Expect.equals(0, hiddenMint() % 2);
+  Expect.equals(0, hiddenMint() & 2);
+  Expect.equals(-9223372036854775806, hiddenMint() | 2);
+  Expect.equals(-9223372036854775806, hiddenMint() ^ 2);
+  Expect.equals(0, hiddenMint() << 2);
+  Expect.equals(-2305843009213693952, hiddenMint() >> 2);
+  Expect.equals(2305843009213693952, hiddenMint() >>> 2);
+
+  Expect.equals(5.0, hiddenDouble() + 2);
+  Expect.equals(1.0, hiddenDouble() - 2);
+  Expect.equals(6.0, hiddenDouble() * 2);
+  Expect.equals(1, hiddenDouble() ~/ 2);
+  Expect.equals(1.0, hiddenDouble() % 2);
+  Expect.throws(() => hiddenDouble() & 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() | 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() ^ 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() << 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() >> 2, (e) => e is NoSuchMethodError);
+  Expect.throws(() => hiddenDouble() >>> 2, (e) => e is NoSuchMethodError);
+
+  Expect.equals("add", hiddenCustom() + 2);
+  Expect.equals("sub", hiddenCustom() - 2);
+  Expect.equals("mul", hiddenCustom() * 2);
+  Expect.equals("div", hiddenCustom() ~/ 2);
+  Expect.equals("mod", hiddenCustom() % 2);
+  Expect.equals("and", hiddenCustom() & 2);
+  Expect.equals("or", hiddenCustom() | 2);
+  Expect.equals("xor", hiddenCustom() ^ 2);
+  Expect.equals("sll", hiddenCustom() << 2);
+  Expect.equals("sra", hiddenCustom() >> 2);
+  Expect.equals("srl", hiddenCustom() >>> 2);
+}
diff --git a/tests/language_2/vm/div_mod_test.dart b/tests/language_2/vm/div_mod_test.dart
index 92fab4f..ff9a88c 100755
--- a/tests/language_2/vm/div_mod_test.dart
+++ b/tests/language_2/vm/div_mod_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--deterministic
+// VMOptions=--deterministic --use_slow_path
 
 // Unit tests on DIV and MOV operations by various constants.
 
diff --git a/tests/language_2/vm/modtruncdiv_int_test.dart b/tests/language_2/vm/modtruncdiv_int_test.dart
index b838b15..018995e 100644
--- a/tests/language_2/vm/modtruncdiv_int_test.dart
+++ b/tests/language_2/vm/modtruncdiv_int_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--no_background_compilation --optimization_counter_threshold=10
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language_2/vm/mult_int_test.dart b/tests/language_2/vm/mult_int_test.dart
index b13cbd5..16df391 100644
--- a/tests/language_2/vm/mult_int_test.dart
+++ b/tests/language_2/vm/mult_int_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--no_background_compilation --optimization_counter_threshold=10
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language_2/vm/negate_int_test.dart b/tests/language_2/vm/negate_int_test.dart
index 8703aef..253756e 100644
--- a/tests/language_2/vm/negate_int_test.dart
+++ b/tests/language_2/vm/negate_int_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--no_background_compilation --optimization_counter_threshold=10
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10 --use_slow_path
 
 import "package:expect/expect.dart";
 
diff --git a/tests/language_2/vm/shift_special_cases_test.dart b/tests/language_2/vm/shift_special_cases_test.dart
index 604a0a3..f854461 100644
--- a/tests/language_2/vm/shift_special_cases_test.dart
+++ b/tests/language_2/vm/shift_special_cases_test.dart
@@ -1,7 +1,9 @@
 // Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
 // VMOptions=--optimization-counter-threshold=10 --no-background-compilation
+// VMOptions=--optimization-counter-threshold=10 --no-background-compilation --use_slow_path
 
 // Test for special cases of << and >> integer operations with int64.
 
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 9069e5b..1c4e7ce 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -39,6 +39,7 @@
 js/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/async_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/jsify_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/promise_reject_null_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/properties_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/method_call_on_object_test: SkipByDesign # Issue 42085.
 js/mock_test/*: SkipByDesign # Issue 42085.
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 5a1d63b..a6d093b 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -39,6 +39,7 @@
 js/instanceof_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/async_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/jsify_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
+js/js_util/promise_reject_null_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/js_util/properties_test: SkipByDesign # Issue 42085. CSP policy disallows injected JS code
 js/method_call_on_object_test: SkipByDesign # Issue 42085.
 js/mock_test/*: SkipByDesign # Issue 42085.
diff --git a/tools/VERSION b/tools/VERSION
index 1d974fb..0d6a30e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 168
+PRERELEASE 169
 PRERELEASE_PATCH 0
\ No newline at end of file