Version 2.12.0-166.0.dev

Merge commit '474edbe27f891acf1090f4c5c32b3bcbf94892cb' into 'dev'
diff --git a/DEPS b/DEPS
index 4f282eb..012166d 100644
--- a/DEPS
+++ b/DEPS
@@ -68,7 +68,7 @@
   "gperftools_revision": "180bfa10d7cb38e8b3784d60943d50e8fcef0dcb",
 
   # Revisions of /third_party/* dependencies.
-  "args_rev": "6921e2f63796368bbe65a64ad943df84932dff55",
+  "args_rev": "2c6a221f45e4e0ef447b5d09101bf8a52e1ccd36",
   "async_rev": "695b3ac280f107c84adf7488743abfdfaaeea68f",
   "bazel_worker_rev": "060c55a933d39798681a4f533b161b81dc48d77e",
   "benchmark_harness_rev": "ec6b646f5443faa871e126ac1ba248c94ca06257",
diff --git a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
index 0c9fe04..5cade7b 100644
--- a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
+++ b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
@@ -4,6 +4,8 @@
 
 // ignore_for_file: avoid_function_literals_in_foreach_calls
 
+import 'dart:math' show pow;
+
 import 'package:benchmark_harness/benchmark_harness.dart';
 import 'package:fixnum/fixnum.dart';
 
@@ -31,38 +33,29 @@
 // integers.
 const requiredDigits = 11106;
 
-class Benchmark extends BenchmarkBase {
-  final List<String> strings;
-  Benchmark(String name, int bits)
-      : strings = generateStrings(bits),
+class ParseBigIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final BigInt seed;
+  final List<String> strings = [];
+
+  ParseBigIntBenchmark(String name, this.bits)
+      : seed = (BigInt.one << bits) - BigInt.one,
         super(name);
 
-  static List<String> generateStrings(int bits) {
-    List<String> strings = [];
-    BigInt seed = (BigInt.one << bits) - BigInt.one;
+  @override
+  void setup() {
     var b = seed;
-    var restartDelta = BigInt.zero;
     var totalLength = 0;
     while (totalLength < requiredDigits) {
       if (b.bitLength < bits) {
-        restartDelta += seed >> 20;
-        restartDelta += BigInt.one;
-        // Restart from a slighly reduced seed to generate different numbers.
-        b = seed - restartDelta;
+        b = seed;
       }
       final string = b.toString();
       strings.add(string);
       totalLength += string.length;
-      var delta = b >> 8;
-      if (delta == BigInt.zero) delta = BigInt.one;
-      b = b - delta;
+      b = b - (b >> 8);
     }
-    return strings;
   }
-}
-
-class ParseBigIntBenchmark extends Benchmark {
-  ParseBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void run() {
@@ -75,8 +68,31 @@
   }
 }
 
-class ParseInt64Benchmark extends Benchmark {
-  ParseInt64Benchmark(String name, int bits) : super(name, bits);
+int int64UnsignedBitLength(Int64 i) => i.isNegative ? 64 : i.bitLength;
+
+class ParseInt64Benchmark extends BenchmarkBase {
+  final int bits;
+  final Int64 seed;
+  final List<String> strings = [];
+
+  ParseInt64Benchmark(String name, this.bits)
+      : seed = (Int64.ONE << bits) - Int64.ONE,
+        super(name);
+
+  @override
+  void setup() {
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (int64UnsignedBitLength(b) < bits) {
+        b = seed;
+      }
+      final string = b.toStringUnsigned();
+      strings.add(string);
+      totalLength += string.length;
+      b = b - b.shiftRightUnsigned(8);
+    }
+  }
 
   @override
   void run() {
@@ -89,8 +105,29 @@
   }
 }
 
-class ParseIntBenchmark extends Benchmark {
-  ParseIntBenchmark(String name, int bits) : super(name, bits);
+class ParseIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final int seed;
+  final List<String> strings = [];
+
+  ParseIntBenchmark(String name, this.bits)
+      : seed = (pow(2, bits) as int) - 1,
+        super(name);
+
+  @override
+  void setup() {
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (b.bitLength < bits) {
+        b = seed;
+      }
+      final string = b.toString();
+      strings.add(string);
+      totalLength += string.length;
+      b = b - b ~/ 256;
+    }
+  }
 
   @override
   void run() {
@@ -103,8 +140,33 @@
   }
 }
 
-class ParseJsBigIntBenchmark extends Benchmark {
-  ParseJsBigIntBenchmark(String name, int bits) : super(name, bits);
+class ParseJsBigIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final Object seed;
+  final List<String> strings = [];
+
+  ParseJsBigIntBenchmark(String name, this.bits)
+      : seed = nativeBigInt.subtract(
+            nativeBigInt.shiftLeft(
+                nativeBigInt.one, nativeBigInt.fromInt(bits)),
+            nativeBigInt.one),
+        super(name);
+
+  @override
+  void setup() {
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (nativeBigInt.bitLength(b) < bits) {
+        b = seed;
+      }
+      final string = nativeBigInt.toStringMethod(b);
+      strings.add(string);
+      totalLength += string.length;
+      b = nativeBigInt.subtract(
+          b, nativeBigInt.shiftRight(b, nativeBigInt.eight));
+    }
+  }
 
   @override
   void run() {
@@ -117,16 +179,27 @@
   }
 }
 
-class FormatBigIntBenchmark extends Benchmark {
+class FormatBigIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final BigInt seed;
   final List<BigInt> values = [];
 
-  FormatBigIntBenchmark(String name, int bits) : super(name, bits);
+  FormatBigIntBenchmark(String name, this.bits)
+      : seed = (BigInt.one << bits) - BigInt.one,
+        super(name);
 
   @override
   void setup() {
-    for (String s in strings) {
-      BigInt b = BigInt.parse(s);
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (b.bitLength < bits) {
+        b = seed;
+      }
+      final string = b.toString();
       values.add(b - BigInt.one); // We add 'one' back later.
+      totalLength += string.length;
+      b = b - (b >> 8);
     }
   }
 
@@ -145,16 +218,28 @@
   }
 }
 
-class FormatIntBenchmark extends Benchmark {
+class FormatIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final int seed;
   final List<int> values = [];
 
-  FormatIntBenchmark(String name, int bits) : super(name, bits);
+  FormatIntBenchmark(String name, this.bits)
+      : seed = (pow(2, bits) as int) - 1,
+        super(name);
 
   @override
   void setup() {
-    for (String s in strings) {
-      int b = int.parse(s);
-      values.add(b - 4096); // We add this back later.
+    var b = seed;
+    var totalLength = 0;
+    int kk = b ~/ 100000;
+    while (totalLength < requiredDigits) {
+      if (b.bitLength < bits) {
+        b = seed - ++kk;
+      }
+      final string = b.toString();
+      values.add(b - 4096); // We add 'one' back later.
+      totalLength += string.length;
+      b = b - (b ~/ 256);
     }
   }
 
@@ -162,9 +247,7 @@
   void run() {
     for (final b0 in values) {
       // Instances might cache `toString()`, so use arithmetic to create a new
-      // instance to try to protect against measuring a cached string.  We use
-      // 4096 to avoid the arithmetic being a no-op due to rounding on web
-      // integers (i.e. doubles).
+      // instance to try to protect against measuring a cached string.
       final b = b0 + 4096;
       final s = b.toString();
       sink1 = s;
@@ -174,16 +257,27 @@
   }
 }
 
-class FormatInt64Benchmark extends Benchmark {
+class FormatInt64Benchmark extends BenchmarkBase {
+  final int bits;
+  final Int64 seed;
   final List<Int64> values = [];
 
-  FormatInt64Benchmark(String name, int bits) : super(name, bits);
+  FormatInt64Benchmark(String name, this.bits)
+      : seed = (Int64.ONE << bits) - Int64.ONE,
+        super(name);
 
   @override
   void setup() {
-    for (String s in strings) {
-      final b = Int64.parseInt(s);
-      values.add(b - Int64.ONE); // We add this back later.
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (int64UnsignedBitLength(b) < bits) {
+        b = seed;
+      }
+      final string = b.toStringUnsigned();
+      values.add(b - Int64.ONE);
+      totalLength += string.length;
+      b = b - b.shiftRightUnsigned(8);
     }
   }
 
@@ -202,17 +296,32 @@
   }
 }
 
-class FormatJsBigIntBenchmark extends Benchmark {
+class FormatJsBigIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final Object seed;
   final List<Object> values = [];
 
-  FormatJsBigIntBenchmark(String name, int bits) : super(name, bits);
+  FormatJsBigIntBenchmark(String name, this.bits)
+      : seed = nativeBigInt.subtract(
+            nativeBigInt.shiftLeft(
+                nativeBigInt.one, nativeBigInt.fromInt(bits)),
+            nativeBigInt.one),
+        super(name);
 
   @override
   void setup() {
     final one = nativeBigInt.one;
-    for (String s in strings) {
-      final b = nativeBigInt.parse(s);
-      values.add(nativeBigInt.subtract(b, one)); // We add this back later.
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (nativeBigInt.bitLength(b) < bits) {
+        b = seed;
+      }
+      final string = nativeBigInt.toStringMethod(b);
+      values.add(nativeBigInt.subtract(b, one)); // We add 'one' back later.
+      totalLength += string.length;
+      b = nativeBigInt.subtract(
+          b, nativeBigInt.shiftRight(b, nativeBigInt.eight));
     }
   }
 
@@ -262,9 +371,6 @@
   final benchmarks = [
     () => ParseIntBenchmark('Int.parse.0009.bits', 9),
     () => ParseIntBenchmark('Int.parse.0032.bits', 32),
-    // Use '63' bits to avoid 64-bit arithmetic overflowing to negative. Keep
-    // the name as '64' to help comparisons.  The effect of an incorrect number
-    // is reduced since benchmark results are normalized to a 'per digit' score
     () => ParseIntBenchmark('Int.parse.0064.bits', 63),
     () => ParseInt64Benchmark('Int64.parse.0009.bits', 9),
     () => ParseInt64Benchmark('Int64.parse.0032.bits', 32),
@@ -283,7 +389,7 @@
     selectParseNativeBigIntBenchmark('JsBigInt.parse.4096.bits', 4096),
     () => FormatIntBenchmark('Int.toString.0009.bits', 9),
     () => FormatIntBenchmark('Int.toString.0032.bits', 32),
-    () => FormatIntBenchmark('Int.toString.0064.bits', 63), // '63': See above.
+    () => FormatIntBenchmark('Int.toString.0064.bits', 63),
     () => FormatInt64Benchmark('Int64.toString.0009.bits', 9),
     () => FormatInt64Benchmark('Int64.toString.0032.bits', 32),
     () => FormatInt64Benchmark('Int64.toString.0064.bits', 64),
diff --git a/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart b/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
index 5656eac..26a796f 100644
--- a/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
+++ b/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
@@ -33,38 +33,29 @@
 // integers.
 const requiredDigits = 11106;
 
-class Benchmark extends BenchmarkBase {
-  final List<String> strings;
-  Benchmark(String name, int bits)
-      : strings = generateStrings(bits),
+class ParseBigIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final BigInt seed;
+  final List<String> strings = [];
+
+  ParseBigIntBenchmark(String name, this.bits)
+      : seed = (BigInt.one << bits) - BigInt.one,
         super(name);
 
-  static List<String> generateStrings(int bits) {
-    List<String> strings = [];
-    BigInt seed = (BigInt.one << bits) - BigInt.one;
+  @override
+  void setup() {
     var b = seed;
-    var restartDelta = BigInt.zero;
     var totalLength = 0;
     while (totalLength < requiredDigits) {
       if (b.bitLength < bits) {
-        restartDelta += seed >> 20;
-        restartDelta += BigInt.one;
-        // Restart from a slighly reduced seed to generate different numbers.
-        b = seed - restartDelta;
+        b = seed;
       }
       final string = b.toString();
       strings.add(string);
       totalLength += string.length;
-      var delta = b >> 8;
-      if (delta == BigInt.zero) delta = BigInt.one;
-      b = b - delta;
+      b = b - (b >> 8);
     }
-    return strings;
   }
-}
-
-class ParseBigIntBenchmark extends Benchmark {
-  ParseBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void run() {
@@ -77,8 +68,31 @@
   }
 }
 
-class ParseInt64Benchmark extends Benchmark {
-  ParseInt64Benchmark(String name, int bits) : super(name, bits);
+int int64UnsignedBitLength(Int64 i) => i.isNegative ? 64 : i.bitLength;
+
+class ParseInt64Benchmark extends BenchmarkBase {
+  final int bits;
+  final Int64 seed;
+  final List<String> strings = [];
+
+  ParseInt64Benchmark(String name, this.bits)
+      : seed = (Int64.ONE << bits) - Int64.ONE,
+        super(name);
+
+  @override
+  void setup() {
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (int64UnsignedBitLength(b) < bits) {
+        b = seed;
+      }
+      final string = b.toStringUnsigned();
+      strings.add(string);
+      totalLength += string.length;
+      b = b - b.shiftRightUnsigned(8);
+    }
+  }
 
   @override
   void run() {
@@ -91,22 +105,33 @@
   }
 }
 
-class ParseIntBenchmark extends Benchmark {
-  ParseIntBenchmark(String name, int bits) : super(name, bits);
+class ParseJsBigIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final Object seed;
+  final List<String> strings = [];
+
+  ParseJsBigIntBenchmark(String name, this.bits)
+      : seed = nativeBigInt.subtract(
+            nativeBigInt.shiftLeft(
+                nativeBigInt.one, nativeBigInt.fromInt(bits)),
+            nativeBigInt.one),
+        super(name);
 
   @override
-  void run() {
-    for (final s in strings) {
-      final b = int.parse(s);
-      sink1 = s;
-      sink2 = b;
+  void setup() {
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (nativeBigInt.bitLength(b) < bits) {
+        b = seed;
+      }
+      final string = nativeBigInt.toStringMethod(b);
+      strings.add(string);
+      totalLength += string.length;
+      b = nativeBigInt.subtract(
+          b, nativeBigInt.shiftRight(b, nativeBigInt.eight));
     }
-    check(sink2.isEven);
   }
-}
-
-class ParseJsBigIntBenchmark extends Benchmark {
-  ParseJsBigIntBenchmark(String name, int bits) : super(name, bits);
 
   @override
   void run() {
@@ -119,16 +144,27 @@
   }
 }
 
-class FormatBigIntBenchmark extends Benchmark {
+class FormatBigIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final BigInt seed;
   final List<BigInt> values = [];
 
-  FormatBigIntBenchmark(String name, int bits) : super(name, bits);
+  FormatBigIntBenchmark(String name, this.bits)
+      : seed = (BigInt.one << bits) - BigInt.one,
+        super(name);
 
   @override
   void setup() {
-    for (String s in strings) {
-      BigInt b = BigInt.parse(s);
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (b.bitLength < bits) {
+        b = seed;
+      }
+      final string = b.toString();
       values.add(b - BigInt.one); // We add 'one' back later.
+      totalLength += string.length;
+      b = b - (b >> 8);
     }
   }
 
@@ -147,45 +183,27 @@
   }
 }
 
-class FormatIntBenchmark extends Benchmark {
-  final List<int> values = [];
-
-  FormatIntBenchmark(String name, int bits) : super(name, bits);
-
-  @override
-  void setup() {
-    for (String s in strings) {
-      int b = int.parse(s);
-      values.add(b - 4096); // We add this back later.
-    }
-  }
-
-  @override
-  void run() {
-    for (final b0 in values) {
-      // Instances might cache `toString()`, so use arithmetic to create a new
-      // instance to try to protect against measuring a cached string.  We use
-      // 4096 to avoid the arithmetic being a no-op due to rounding on web
-      // integers (i.e. doubles).
-      final b = b0 + 4096;
-      final s = b.toString();
-      sink1 = s;
-      sink2 = b;
-    }
-    check(sink2.isEven);
-  }
-}
-
-class FormatInt64Benchmark extends Benchmark {
+class FormatInt64Benchmark extends BenchmarkBase {
+  final int bits;
+  final Int64 seed;
   final List<Int64> values = [];
 
-  FormatInt64Benchmark(String name, int bits) : super(name, bits);
+  FormatInt64Benchmark(String name, this.bits)
+      : seed = (Int64.ONE << bits) - Int64.ONE,
+        super(name);
 
   @override
   void setup() {
-    for (String s in strings) {
-      final b = Int64.parseInt(s);
-      values.add(b - Int64.ONE); // We add this back later.
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (int64UnsignedBitLength(b) < bits) {
+        b = seed;
+      }
+      final string = b.toStringUnsigned();
+      values.add(b - Int64.ONE);
+      totalLength += string.length;
+      b = b - b.shiftRightUnsigned(8);
     }
   }
 
@@ -204,17 +222,32 @@
   }
 }
 
-class FormatJsBigIntBenchmark extends Benchmark {
+class FormatJsBigIntBenchmark extends BenchmarkBase {
+  final int bits;
+  final Object seed;
   final List<Object> values = [];
 
-  FormatJsBigIntBenchmark(String name, int bits) : super(name, bits);
+  FormatJsBigIntBenchmark(String name, this.bits)
+      : seed = nativeBigInt.subtract(
+            nativeBigInt.shiftLeft(
+                nativeBigInt.one, nativeBigInt.fromInt(bits)),
+            nativeBigInt.one),
+        super(name);
 
   @override
   void setup() {
     final one = nativeBigInt.one;
-    for (String s in strings) {
-      final b = nativeBigInt.parse(s);
-      values.add(nativeBigInt.subtract(b, one)); // We add this back later.
+    var b = seed;
+    var totalLength = 0;
+    while (totalLength < requiredDigits) {
+      if (nativeBigInt.bitLength(b) < bits) {
+        b = seed;
+      }
+      final string = nativeBigInt.toStringMethod(b);
+      values.add(nativeBigInt.subtract(b, one)); // We add 'one' back later.
+      totalLength += string.length;
+      b = nativeBigInt.subtract(
+          b, nativeBigInt.shiftRight(b, nativeBigInt.eight));
     }
   }
 
@@ -262,12 +295,6 @@
 
 void main() {
   final benchmarks = [
-    () => ParseIntBenchmark('Int.parse.0009.bits', 9),
-    () => ParseIntBenchmark('Int.parse.0032.bits', 32),
-    // Use '63' bits to avoid 64-bit arithmetic overflowing to negative. Keep
-    // the name as '64' to help comparisons.  The effect of an incorrect number
-    // is reduced since benchmark results are normalized to a 'per digit' score
-    () => ParseIntBenchmark('Int.parse.0064.bits', 63),
     () => ParseInt64Benchmark('Int64.parse.0009.bits', 9),
     () => ParseInt64Benchmark('Int64.parse.0032.bits', 32),
     () => ParseInt64Benchmark('Int64.parse.0064.bits', 64),
@@ -283,9 +310,6 @@
     selectParseNativeBigIntBenchmark('JsBigInt.parse.0256.bits', 256),
     selectParseNativeBigIntBenchmark('JsBigInt.parse.1024.bits', 1024),
     selectParseNativeBigIntBenchmark('JsBigInt.parse.4096.bits', 4096),
-    () => FormatIntBenchmark('Int.toString.0009.bits', 9),
-    () => FormatIntBenchmark('Int.toString.0032.bits', 32),
-    () => FormatIntBenchmark('Int.toString.0064.bits', 63), // '63': See above.
     () => FormatInt64Benchmark('Int64.toString.0009.bits', 9),
     () => FormatInt64Benchmark('Int64.toString.0032.bits', 32),
     () => FormatInt64Benchmark('Int64.toString.0064.bits', 64),
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index 818914f..2ef2bf1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -298,7 +298,7 @@
   ExpressionInfo<Variable, Type> invert() =>
       new ExpressionInfo<Variable, Type>(after, ifFalse, ifTrue);
 
-  ExpressionInfo<Variable, Type> rebaseForward(
+  ExpressionInfo<Variable, Type>? rebaseForward(
           TypeOperations<Variable, Type> typeOperations,
           FlowModel<Variable, Type> base) =>
       new ExpressionInfo(base, ifTrue.rebaseForward(typeOperations, base),
@@ -3757,11 +3757,11 @@
     _storeExpressionVariable(expression, variable);
     VariableModel<Variable, Type> variableModel = _current.infoFor(variable);
     if (allowLocalBooleanVarsToPromote) {
-      ExpressionInfo<Variable, Type>? expressionInfo =
-          variableModel.ssaNode?.expressionInfo;
+      ExpressionInfo<Variable, Type>? expressionInfo = variableModel
+          .ssaNode?.expressionInfo
+          ?.rebaseForward(typeOperations, _current);
       if (expressionInfo != null) {
-        _storeExpressionInfo(
-            expression, expressionInfo.rebaseForward(typeOperations, _current));
+        _storeExpressionInfo(expression, expressionInfo);
       }
     }
     return variableModel.promotedTypes?.last;
@@ -3951,10 +3951,10 @@
   }
 
   @override
-  ExpressionInfo<Variable, Type> rebaseForward(
+  ExpressionInfo<Variable, Type>? rebaseForward(
           TypeOperations<Variable, Type> typeOperations,
           FlowModel<Variable, Type> base) =>
-      new _NullInfo(base);
+      null;
 }
 
 /// [_FlowContext] representing a language construct for which flow analysis
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 e9740e2..f8c1de7 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
@@ -2586,18 +2586,11 @@
       ]);
     });
 
-    test('variableRead() restores the notion of whether a value is null', () {
-      // This is not a necessary part of the design of
-      // https://github.com/dart-lang/language/issues/1274; it's more of a happy
-      // accident of how it was implemented: since we store an ExpressionInfo
-      // object in the SSA node to keep track of the consequences of the
-      // variable's value on flow analysis, and since the _NullInfo type is a
-      // subtype of ExpressionInfo, that means that when a literal `null` is
-      // written to a variable, and we read it later, we recognize the value as
-      // being `null` for purposes of comparison to other other variables.  Even
-      // though this feature is a happy accident of the implementation strategy,
-      // it's important to test it to make sure it doesn't regress, since users
-      // might come to rely on it.
+    test("variableRead() doesn't restore the notion of whether a value is null",
+        () {
+      // Note: we have the available infrastructure to do this if we want, but
+      // we think it will give an inconsistent feel because comparisons like
+      // `if (i == null)` *don't* promote.
       var h = Harness(allowLocalBooleanVarsToPromote: true);
       var x = Var('x', 'int?');
       var y = Var('y', 'int?');
@@ -2611,7 +2604,9 @@
           checkNotPromoted(x),
           checkNotPromoted(y),
         ], [
-          checkPromoted(x, 'int'),
+          // Even though x != y and y is known to contain the value `null`, we
+          // don't promote x.
+          checkNotPromoted(x),
           checkNotPromoted(y),
         ]),
       ]);
diff --git a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
index a08df3c..7405b0e 100644
--- a/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/semantic_tokens/mapping.dart
@@ -95,8 +95,8 @@
   HighlightRegionType.ENUM: SemanticTokenTypes.enum_,
   HighlightRegionType.ENUM_CONSTANT: SemanticTokenTypes.enumMember,
   HighlightRegionType.FUNCTION_TYPE_ALIAS: SemanticTokenTypes.type,
-  HighlightRegionType.INSTANCE_FIELD_DECLARATION: SemanticTokenTypes.property,
-  HighlightRegionType.INSTANCE_FIELD_REFERENCE: SemanticTokenTypes.property,
+  HighlightRegionType.INSTANCE_FIELD_DECLARATION: SemanticTokenTypes.variable,
+  HighlightRegionType.INSTANCE_FIELD_REFERENCE: SemanticTokenTypes.variable,
   HighlightRegionType.INSTANCE_GETTER_DECLARATION: SemanticTokenTypes.property,
   HighlightRegionType.INSTANCE_GETTER_REFERENCE: SemanticTokenTypes.property,
   HighlightRegionType.INSTANCE_METHOD_DECLARATION: SemanticTokenTypes.method,
diff --git a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
index 5c6836b..04c0427 100644
--- a/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
+++ b/pkg/analysis_server/test/lsp/semantic_tokens_test.dart
@@ -104,7 +104,7 @@
       _Token('/// field docs', SemanticTokenTypes.comment,
           [SemanticTokenModifiers.documentation]),
       _Token('String', SemanticTokenTypes.class_),
-      _Token('myField', SemanticTokenTypes.property,
+      _Token('myField', SemanticTokenTypes.variable,
           [SemanticTokenModifiers.declaration]),
       _Token("'FieldVal'", SemanticTokenTypes.string),
       _Token('/// static field docs', SemanticTokenTypes.comment,
diff --git a/pkg/compiler/test/inference/data/general.dart b/pkg/compiler/test/inference/data/general.dart
index 209f884..275cd19 100644
--- a/pkg/compiler/test/inference/data/general.dart
+++ b/pkg/compiler/test/inference/data/general.dart
@@ -809,8 +809,9 @@
   return new CascadeHelper()
     .. /*update: [exact=CascadeHelper]*/ a = "hello"
     .. /*update: [exact=CascadeHelper]*/ b = 42
-    .. /*[exact=CascadeHelper]*/ /*update: [exact=CascadeHelper]*/ i
-        /*invoke: [subclass=JSPositiveInt]*/ += 1;
+    .. /*[exact=CascadeHelper]*/ i
+        /*invoke: [subclass=JSPositiveInt]*/ /*update: [exact=CascadeHelper]*/ +=
+        1;
 }
 
 /*member: CascadeHelper.:[exact=CascadeHelper]*/
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 509c236..d42d1d5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -516,7 +516,6 @@
       bool isPostIncDec: false}) {
     return new CompoundPropertySet(receiver, name, binaryOperator, value,
         forEffect: voidContext,
-        readOnlyReceiver: false,
         readOffset: fileOffset,
         binaryOffset: offset,
         writeOffset: fileOffset)
@@ -994,19 +993,16 @@
   Expression buildAssignment(Expression value, {bool voidContext: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
     Expression result = _forest.createIndexSet(
         fileOffset, receiverValue, index, value,
-        forEffect: voidContext, readOnlyReceiver: readOnlyReceiver);
+        forEffect: voidContext);
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
         ..fileOffset = fileOffset;
@@ -1019,23 +1015,19 @@
       {bool voidContext: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
 
     Expression result = new IfNullIndexSet(receiverValue, index, value,
         readOffset: fileOffset,
         testOffset: offset,
         writeOffset: fileOffset,
-        forEffect: voidContext,
-        readOnlyReceiver: readOnlyReceiver)
+        forEffect: voidContext)
       ..fileOffset = offset;
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
@@ -1051,15 +1043,12 @@
       bool isPostIncDec: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
 
     Expression result = new CompoundIndexSet(
@@ -1068,8 +1057,7 @@
         binaryOffset: offset,
         writeOffset: fileOffset,
         forEffect: voidContext,
-        forPostIncDec: isPostIncDec,
-        readOnlyReceiver: readOnlyReceiver);
+        forPostIncDec: isPostIncDec);
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
         ..fileOffset = fileOffset;
@@ -1166,7 +1154,7 @@
     _reportNonNullableInNullAwareWarningIfNeeded();
     Expression receiver = _helper.forest.createThisExpression(fileOffset);
     return _forest.createIndexSet(fileOffset, receiver, index, value,
-        forEffect: voidContext, readOnlyReceiver: true);
+        forEffect: voidContext);
   }
 
   @override
@@ -1178,8 +1166,7 @@
         readOffset: fileOffset,
         testOffset: offset,
         writeOffset: fileOffset,
-        forEffect: voidContext,
-        readOnlyReceiver: true)
+        forEffect: voidContext)
       ..fileOffset = offset;
   }
 
@@ -1195,8 +1182,7 @@
         binaryOffset: offset,
         writeOffset: fileOffset,
         forEffect: voidContext,
-        forPostIncDec: isPostIncDec,
-        readOnlyReceiver: true);
+        forPostIncDec: isPostIncDec);
   }
 
   @override
@@ -1723,8 +1709,7 @@
           _helper.createVariableGet(extensionThis, fileOffset),
           writeTarget,
           value,
-          forEffect: forEffect,
-          readOnlyReceiver: true);
+          forEffect: forEffect);
     }
     write.fileOffset = offset;
     return write;
@@ -2040,24 +2025,22 @@
               _helper.createVariableGet(variable, variable.fileOffset,
                   forNullGuardedAccess: true),
               value,
-              forEffect: voidContext,
-              readOnlyReceiver: true))
+              forEffect: voidContext))
         ..fileOffset = fileOffset;
     } else {
-      return _createWrite(fileOffset, receiver, value,
-          forEffect: voidContext, readOnlyReceiver: false);
+      return _createWrite(fileOffset, receiver, value, forEffect: voidContext);
     }
   }
 
   Expression _createWrite(int offset, Expression receiver, Expression value,
-      {bool readOnlyReceiver, bool forEffect}) {
+      {bool forEffect}) {
     Expression write;
     if (writeTarget == null) {
       write = _makeInvalidWrite(value);
     } else {
       write = new ExtensionSet(
           extension, explicitTypeArguments, receiver, writeTarget, value,
-          readOnlyReceiver: readOnlyReceiver, forEffect: forEffect);
+          forEffect: forEffect);
     }
     write.fileOffset = offset;
     return write;
@@ -2077,8 +2060,7 @@
           _helper.createVariableGet(variable, receiver.fileOffset,
               forNullGuardedAccess: true),
           value,
-          forEffect: voidContext,
-          readOnlyReceiver: true);
+          forEffect: voidContext);
       return new NullAwareExtension(
           variable,
           new IfNullSet(read, write, forEffect: voidContext)
@@ -2113,13 +2095,11 @@
           _helper.createVariableGet(variable, receiver.fileOffset,
               forNullGuardedAccess: true),
           binary,
-          forEffect: voidContext,
-          readOnlyReceiver: true);
+          forEffect: voidContext);
       return new NullAwareExtension(variable, write)..fileOffset = offset;
     } else {
       return new CompoundExtensionSet(extension, explicitTypeArguments,
           receiver, targetName, readTarget, binaryOperator, value, writeTarget,
-          readOnlyReceiver: false,
           forEffect: voidContext,
           readOffset: fileOffset,
           binaryOffset: offset,
@@ -2150,8 +2130,7 @@
               _helper.createVariableGet(variable, receiver.fileOffset,
                   forNullGuardedAccess: true),
               binary,
-              forEffect: voidContext,
-              readOnlyReceiver: true)
+              forEffect: voidContext)
             ..fileOffset = fileOffset);
       return new NullAwareExtension(
           variable, new LocalPostIncDec(read, write)..fileOffset = offset)
@@ -2167,7 +2146,7 @@
       VariableDeclaration write = _helper.forest
           .createVariableDeclarationForValue(_createWrite(fileOffset,
               _helper.createVariableGet(variable, receiver.fileOffset), binary,
-              forEffect: voidContext, readOnlyReceiver: true)
+              forEffect: voidContext)
             ..fileOffset = fileOffset);
       return new PropertyPostIncDec(variable, read, write)..fileOffset = offset;
     }
@@ -2419,15 +2398,12 @@
       {bool voidContext: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
     Expression result = new IfNullExtensionIndexSet(
         extension,
@@ -2440,8 +2416,7 @@
         readOffset: fileOffset,
         testOffset: offset,
         writeOffset: fileOffset,
-        forEffect: voidContext,
-        readOnlyReceiver: readOnlyReceiver)
+        forEffect: voidContext)
       ..fileOffset = offset;
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
@@ -2457,15 +2432,12 @@
       bool isPostIncDec: false}) {
     VariableDeclaration variable;
     Expression receiverValue;
-    bool readOnlyReceiver;
     if (isNullAware) {
       variable = _forest.createVariableDeclarationForValue(receiver);
       receiverValue = _helper.createVariableGet(variable, fileOffset,
           forNullGuardedAccess: true);
-      readOnlyReceiver = true;
     } else {
       receiverValue = receiver;
-      readOnlyReceiver = false;
     }
     Expression result = new CompoundExtensionIndexSet(
         extension,
@@ -2480,8 +2452,7 @@
         binaryOffset: offset,
         writeOffset: fileOffset,
         forEffect: voidContext,
-        forPostIncDec: isPostIncDec,
-        readOnlyReceiver: readOnlyReceiver);
+        forPostIncDec: isPostIncDec);
     if (isNullAware) {
       result = new NullAwareMethodInvocation(variable, result)
         ..fileOffset = fileOffset;
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 273a4e7..75946bb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -706,12 +706,10 @@
 
   IndexSet createIndexSet(
       int fileOffset, Expression receiver, Expression index, Expression value,
-      {bool forEffect, bool readOnlyReceiver}) {
+      {bool forEffect}) {
     assert(fileOffset != null);
     assert(forEffect != null);
-    assert(readOnlyReceiver != null);
-    return new IndexSet(receiver, index, value,
-        forEffect: forEffect, readOnlyReceiver: readOnlyReceiver)
+    return new IndexSet(receiver, index, value, forEffect: forEffect)
       ..fileOffset = fileOffset;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index c5f9600..6dd3745 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -61,20 +61,6 @@
 
   InferenceVisitor(this.inferrer);
 
-  Expression _clone(Expression node) {
-    if (node is ThisExpression) {
-      return new ThisExpression()..fileOffset = node.fileOffset;
-    } else if (node is VariableGet) {
-      assert(
-          node.variable.isFinal,
-          "Trying to clone VariableGet of non-final variable"
-          " ${node.variable}.");
-      return new VariableGet(node.variable, node.promotedType)
-        ..fileOffset = node.fileOffset;
-    }
-    throw new UnsupportedError("Clone not supported for ${node.runtimeType}.");
-  }
-
   ExpressionInferenceResult _unhandledExpression(
       Expression node, DartType typeContext) {
     unhandled("${node.runtimeType}", "InferenceVisitor", node.fileOffset,
@@ -500,7 +486,7 @@
     }
 
     VariableDeclaration receiverVariable;
-    if (node.forEffect || node.readOnlyReceiver) {
+    if (node.forEffect || isPureExpression(receiver)) {
       // No need for receiver variable.
     } else {
       receiverVariable = createVariable(receiver, receiverResult.inferredType);
@@ -551,9 +537,9 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+    if (isPureExpression(receiver)) {
       readReceiver = receiver;
-      writeReceiver = _clone(receiver);
+      writeReceiver = clonePureExpression(receiver);
     } else {
       receiverVariable = createVariable(receiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -2749,9 +2735,9 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+    if (isPureExpression(receiver)) {
       readReceiver = receiver;
-      writeReceiver = _clone(receiver);
+      writeReceiver = clonePureExpression(receiver);
     } else {
       receiverVariable = createVariable(receiver, receiverType);
       inferrer.instrumentation?.record(
@@ -3004,7 +2990,7 @@
     DartType receiverType = receiverResult.nullAwareActionType;
 
     VariableDeclaration receiverVariable;
-    if (!node.forEffect && !node.readOnlyReceiver) {
+    if (!node.forEffect && !isPureExpression(receiver)) {
       receiverVariable = createVariable(receiver, receiverType);
       receiver = createVariableGet(receiverVariable);
     }
@@ -3023,7 +3009,7 @@
     Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
     VariableDeclaration indexVariable;
-    if (!node.forEffect) {
+    if (!node.forEffect && !isPureExpression(index)) {
       indexVariable = createVariable(index, indexResult.inferredType);
       index = createVariableGet(indexVariable);
     }
@@ -3033,9 +3019,14 @@
     Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
 
     VariableDeclaration valueVariable;
-    if (!node.forEffect) {
+    Expression returnedValue;
+    if (node.forEffect) {
+    } else if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
+    } else {
       valueVariable = createVariable(value, valueResult.inferredType);
       value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
     }
 
     // The inferred type is that inferred type of the value expression and not
@@ -3049,14 +3040,15 @@
     if (node.forEffect) {
       replacement = assignment;
     } else {
-      assert(indexVariable != null);
-      assert(valueVariable != null);
       VariableDeclaration assignmentVariable =
           createVariable(assignment, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(valueVariable,
-              createLet(assignmentVariable, createVariableGet(valueVariable))));
+      replacement = createLet(assignmentVariable, returnedValue);
+      if (valueVariable != null) {
+        replacement = createLet(valueVariable, replacement);
+      }
+      if (indexVariable != null) {
+        replacement = createLet(indexVariable, replacement);
+      }
       if (receiverVariable != null) {
         replacement = createLet(receiverVariable, replacement);
       }
@@ -3083,14 +3075,25 @@
 
     Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
-    VariableDeclaration indexVariable =
-        createVariable(index, indexResult.inferredType);
+    VariableDeclaration indexVariable;
+    if (!isPureExpression(index)) {
+      indexVariable = createVariable(index, indexResult.inferredType);
+      index = createVariableGet(indexVariable);
+    }
 
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
     Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
-    VariableDeclaration valueVariable =
-        createVariable(value, valueResult.inferredType);
+
+    VariableDeclaration valueVariable;
+    Expression returnedValue;
+    if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
+    } else {
+      valueVariable = createVariable(value, valueResult.inferredType);
+      value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
+    }
 
     // The inferred type is that inferred type of the value expression and not
     // the type of the value parameter.
@@ -3098,8 +3101,8 @@
 
     Expression assignment;
     if (indexSetTarget.isMissing) {
-      assignment = inferrer.createMissingSuperIndexSet(node.fileOffset,
-          createVariableGet(indexVariable), createVariableGet(valueVariable));
+      assignment =
+          inferrer.createMissingSuperIndexSet(node.fileOffset, index, value);
     } else {
       assert(indexSetTarget.isInstanceMember || indexSetTarget.isObjectMember);
       inferrer.instrumentation?.record(
@@ -3109,21 +3112,20 @@
           new InstrumentationValueForMember(node.setter));
       assignment = new SuperMethodInvocation(
           indexSetName,
-          new Arguments(<Expression>[
-            createVariableGet(indexVariable),
-            createVariableGet(valueVariable)
-          ])
+          new Arguments(<Expression>[index, value])
             ..fileOffset = node.fileOffset,
           indexSetTarget.member)
         ..fileOffset = node.fileOffset;
     }
     VariableDeclaration assignmentVariable =
         createVariable(assignment, const VoidType());
-    Expression replacement = new Let(
-        indexVariable,
-        createLet(valueVariable,
-            createLet(assignmentVariable, createVariableGet(valueVariable))))
-      ..fileOffset = node.fileOffset;
+    Expression replacement = createLet(assignmentVariable, returnedValue);
+    if (valueVariable != null) {
+      replacement = createLet(valueVariable, replacement);
+    }
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
+    }
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -3143,8 +3145,11 @@
     Expression receiver =
         inferrer.ensureAssignableResult(receiverType, receiverResult);
 
-    VariableDeclaration receiverVariable =
-        createVariable(receiver, receiverType);
+    VariableDeclaration receiverVariable;
+    if (!isPureExpression(receiver)) {
+      receiverVariable = createVariable(receiver, receiverType);
+      receiver = createVariableGet(receiverVariable);
+    }
 
     ObjectAccessTarget target = new ExtensionAccessTarget(
         node.setter, null, ProcedureKind.Operator, extensionTypeArguments);
@@ -3157,40 +3162,38 @@
 
     Expression index = inferrer.ensureAssignableResult(indexType, indexResult);
 
-    VariableDeclaration indexVariable =
-        createVariable(index, indexResult.inferredType);
-
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
     Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
-    VariableDeclaration valueVariable =
-        createVariable(value, valueResult.inferredType);
+
+    VariableDeclaration valueVariable;
+    Expression returnedValue;
+    if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
+    } else {
+      valueVariable = createVariable(value, valueResult.inferredType);
+      value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
+    }
 
     // The inferred type is that inferred type of the value expression and not
     // the type of the value parameter.
     DartType inferredType = valueResult.inferredType;
 
-    Expression assignment = _computeIndexSet(
-        node.fileOffset,
-        createVariableGet(receiverVariable),
-        receiverType,
-        target,
-        createVariableGet(indexVariable),
-        indexType,
-        createVariableGet(valueVariable),
-        valueType);
+    Expression assignment = _computeIndexSet(node.fileOffset, receiver,
+        receiverType, target, index, indexType, value, valueType);
 
     VariableDeclaration assignmentVariable =
         createVariable(assignment, const VoidType());
-    Expression replacement = new Let(
-        receiverVariable,
-        createLet(
-            indexVariable,
-            createLet(
-                valueVariable,
-                createLet(
-                    assignmentVariable, createVariableGet(valueVariable)))))
-      ..fileOffset = node.fileOffset;
+    Expression replacement = createLet(assignmentVariable, returnedValue);
+    if (valueVariable != null) {
+      replacement = createLet(valueVariable, replacement);
+    }
+    if (receiverVariable != null) {
+      replacement = createLet(receiverVariable, replacement);
+    }
+    replacement.fileOffset = node.fileOffset;
+
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -3207,8 +3210,8 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver = receiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
-      writeReceiver = _clone(readReceiver);
+    if (isPureExpression(readReceiver)) {
+      writeReceiver = clonePureExpression(readReceiver);
     } else {
       receiverVariable = createVariable(readReceiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -3237,9 +3240,17 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
 
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
 
-    Expression readIndex = createVariableGet(indexVariable);
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
@@ -3261,7 +3272,6 @@
         .findInterfaceMember(readType, equalsName, node.testOffset)
         .member;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -3276,11 +3286,15 @@
             inferrer.library.library);
 
     VariableDeclaration valueVariable;
+    Expression returnedValue;
     if (node.forEffect) {
       // No need for value variable.
+    } else if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
     } else {
       valueVariable = createVariable(value, valueResult.inferredType);
       value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
     }
 
     Expression write = _computeIndexSet(
@@ -3313,7 +3327,7 @@
       ConditionalExpression conditional = new ConditionalExpression(equalsNull,
           write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
         ..fileOffset = node.testOffset;
-      inner = createLet(indexVariable, conditional);
+      inner = conditional;
     } else {
       // Encode `Extension(o)[a] ??= b` as, if `node.readOnlyReceiver` is false,
       // as:
@@ -3339,8 +3353,6 @@
       //        : readVariable
       //
       //
-      assert(valueVariable != null);
-
       VariableDeclaration readVariable = createVariable(read, readType);
       Expression equalsNull = inferrer.createEqualsNull(
           node.testOffset, createVariableGet(readVariable), equalsMember);
@@ -3351,14 +3363,17 @@
           !identical(nonNullableReadType, readType)) {
         variableGet.promotedType = nonNullableReadType;
       }
+      Expression result = createLet(writeVariable, returnedValue);
+      if (valueVariable != null) {
+        result = createLet(valueVariable, result);
+      }
       ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))),
-          variableGet,
-          inferredType)
+          equalsNull, result, variableGet, inferredType)
         ..fileOffset = node.fileOffset;
-      inner = createLet(indexVariable, createLet(readVariable, conditional));
+      inner = createLet(readVariable, conditional);
+    }
+    if (indexVariable != null) {
+      inner = createLet(indexVariable, inner);
     }
 
     Expression replacement;
@@ -3402,13 +3417,20 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
 
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
 
-    Expression readIndex = createVariableGet(indexVariable);
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -3445,11 +3467,15 @@
             inferrer.library.library);
 
     VariableDeclaration valueVariable;
+    Expression returnedValue;
     if (node.forEffect) {
       // No need for a value variable.
+    } else if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
     } else {
       valueVariable = createVariable(value, valueResult.inferredType);
       value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
     }
 
     Expression write;
@@ -3479,12 +3505,12 @@
       //     let v1 = a in
       //        super[v1] == null ? super.[]=(v1, b) : null
       //
+      assert(valueVariable == null);
       Expression equalsNull =
           inferrer.createEqualsNull(node.testOffset, read, equalsMember);
-      ConditionalExpression conditional = new ConditionalExpression(equalsNull,
-          write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
+      replacement = new ConditionalExpression(equalsNull, write,
+          new NullLiteral()..fileOffset = node.testOffset, inferredType)
         ..fileOffset = node.testOffset;
-      replacement = createLet(indexVariable, conditional);
     } else {
       // Encode `o[a] ??= b` as:
       //
@@ -3496,29 +3522,29 @@
       //           v3)
       //        : v2
       //
-      assert(valueVariable != null);
 
       VariableDeclaration readVariable = createVariable(read, readType);
       Expression equalsNull = inferrer.createEqualsNull(
           node.testOffset, createVariableGet(readVariable), equalsMember);
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      VariableGet variableGet = createVariableGet(readVariable);
+      VariableGet readVariableGet = createVariableGet(readVariable);
       if (inferrer.library.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
-        variableGet.promotedType = nonNullableReadType;
+        readVariableGet.promotedType = nonNullableReadType;
+      }
+      Expression result = createLet(writeVariable, returnedValue);
+      if (valueVariable != null) {
+        result = createLet(valueVariable, result);
       }
       ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))),
-          variableGet,
-          inferredType)
+          equalsNull, result, readVariableGet, inferredType)
         ..fileOffset = node.fileOffset;
-      replacement =
-          createLet(indexVariable, createLet(readVariable, conditional));
+      replacement = createLet(readVariable, conditional);
     }
-
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
+    }
     return new ExpressionInferenceResult(inferredType, replacement);
   }
 
@@ -3541,9 +3567,9 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+    if (isPureExpression(receiver)) {
       readReceiver = receiver;
-      writeReceiver = _clone(receiver);
+      writeReceiver = clonePureExpression(receiver);
     } else {
       receiverVariable = createVariable(receiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -3570,9 +3596,17 @@
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
 
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
 
-    Expression readIndex = createVariableGet(indexVariable);
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
@@ -3594,7 +3628,6 @@
         .findInterfaceMember(readType, equalsName, node.testOffset)
         .member;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -3609,11 +3642,15 @@
             inferrer.library.library);
 
     VariableDeclaration valueVariable;
+    Expression returnedValue;
     if (node.forEffect) {
       // No need for a value variable.
+    } else if (isPureExpression(value)) {
+      returnedValue = clonePureExpression(value);
     } else {
       valueVariable = createVariable(value, valueResult.inferredType);
       value = createVariableGet(valueVariable);
+      returnedValue = createVariableGet(valueVariable);
     }
 
     Expression write = _computeIndexSet(
@@ -3635,12 +3672,12 @@
       //        receiverVariable[indexVariable] == null
       //          ? receiverVariable.[]=(indexVariable, b) : null
       //
+      assert(valueVariable == null);
       Expression equalsNull =
           inferrer.createEqualsNull(node.testOffset, read, equalsMember);
-      ConditionalExpression conditional = new ConditionalExpression(equalsNull,
-          write, new NullLiteral()..fileOffset = node.testOffset, inferredType)
+      replacement = new ConditionalExpression(equalsNull, write,
+          new NullLiteral()..fileOffset = node.testOffset, inferredType)
         ..fileOffset = node.testOffset;
-      replacement = createLet(indexVariable, conditional);
     } else {
       // Encode `Extension(o)[a] ??= b` as:
       //
@@ -3654,27 +3691,27 @@
       //           valueVariable)
       //        : readVariable
       //
-      assert(valueVariable != null);
-
       VariableDeclaration readVariable = createVariable(read, readType);
       Expression equalsNull = inferrer.createEqualsNull(
           node.testOffset, createVariableGet(readVariable), equalsMember);
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      VariableGet variableGet = createVariableGet(readVariable);
+      VariableGet readVariableGet = createVariableGet(readVariable);
       if (inferrer.library.isNonNullableByDefault &&
           !identical(nonNullableReadType, readType)) {
-        variableGet.promotedType = nonNullableReadType;
+        readVariableGet.promotedType = nonNullableReadType;
+      }
+      Expression result = createLet(writeVariable, returnedValue);
+      if (valueVariable != null) {
+        result = createLet(valueVariable, result);
       }
       ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))),
-          variableGet,
-          inferredType)
+          equalsNull, result, readVariableGet, inferredType)
         ..fileOffset = node.fileOffset;
-      replacement =
-          createLet(indexVariable, createLet(readVariable, conditional));
+      replacement = createLet(readVariable, conditional);
+    }
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
     }
     if (receiverVariable != null) {
       replacement = new Let(receiverVariable, replacement);
@@ -4384,14 +4421,12 @@
       case ObjectAccessTargetKind.missing:
         write = inferrer.createMissingIndexSet(
             fileOffset, receiver, receiverType, index, value,
-            forEffect: true, readOnlyReceiver: true);
+            forEffect: true);
         break;
       case ObjectAccessTargetKind.ambiguous:
         write = inferrer.createMissingIndexSet(
             fileOffset, receiver, receiverType, index, value,
-            forEffect: true,
-            readOnlyReceiver: true,
-            extensionAccessCandidates: writeTarget.candidates);
+            forEffect: true, extensionAccessCandidates: writeTarget.candidates);
         break;
       case ObjectAccessTargetKind.extensionMember:
       case ObjectAccessTargetKind.nullableExtensionMember:
@@ -4858,8 +4893,8 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver = receiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver) {
-      writeReceiver = _clone(readReceiver);
+    if (isPureExpression(readReceiver)) {
+      writeReceiver = clonePureExpression(readReceiver);
     } else {
       receiverVariable = createVariable(readReceiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -4878,9 +4913,18 @@
 
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
-    Expression readIndex = createVariableGet(indexVariable);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
+
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
@@ -4926,7 +4970,6 @@
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -4960,7 +5003,7 @@
       //
       //     let v1 = o in let v2 = a in v1.[]=(v2, v1.[](v2) + b)
       //
-      inner = createLet(indexVariable, write);
+      inner = write;
     } else if (node.forPostIncDec) {
       // Encode `o[a]++` as:
       //
@@ -4974,10 +5017,8 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      inner = createLet(
-          indexVariable,
-          createLet(leftVariable,
-              createLet(writeVariable, createVariableGet(leftVariable))));
+      inner = createLet(leftVariable,
+          createLet(writeVariable, createVariableGet(leftVariable)));
     } else {
       // Encode `o[a] += b` as:
       //
@@ -4991,10 +5032,11 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      inner = createLet(
-          indexVariable,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))));
+      inner = createLet(valueVariable,
+          createLet(writeVariable, createVariableGet(valueVariable)));
+    }
+    if (indexVariable != null) {
+      inner = createLet(indexVariable, inner);
     }
 
     Expression replacement;
@@ -5156,9 +5198,18 @@
 
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
-    Expression readIndex = createVariableGet(indexVariable);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
+
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
@@ -5213,7 +5264,6 @@
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
 
@@ -5260,7 +5310,7 @@
       //
       //     let v1 = a in super.[]=(v1, super.[](v1) + b)
       //
-      replacement = createLet(indexVariable, write);
+      replacement = write;
     } else if (node.forPostIncDec) {
       // Encode `super[a]++` as:
       //
@@ -5273,10 +5323,8 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(leftVariable,
-              createLet(writeVariable, createVariableGet(leftVariable))));
+      replacement = createLet(leftVariable,
+          createLet(writeVariable, createVariableGet(leftVariable)));
     } else {
       // Encode `super[a] += b` as:
       //
@@ -5290,12 +5338,12 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))));
+      replacement = createLet(valueVariable,
+          createLet(writeVariable, createVariableGet(valueVariable)));
     }
-
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
+    }
     return new ExpressionInferenceResult(
         node.forPostIncDec ? readType : binaryType, replacement);
   }
@@ -5324,9 +5372,9 @@
     VariableDeclaration receiverVariable;
     Expression readReceiver;
     Expression writeReceiver;
-    if (node.readOnlyReceiver && identical(receiver, node.receiver)) {
+    if (isPureExpression(receiver)) {
       readReceiver = receiver;
-      writeReceiver = _clone(receiver);
+      writeReceiver = clonePureExpression(receiver);
     } else {
       receiverVariable = createVariable(receiver, receiverType);
       readReceiver = createVariableGet(receiverVariable);
@@ -5337,9 +5385,18 @@
 
     ExpressionInferenceResult indexResult = inferrer
         .inferExpression(node.index, readIndexType, true, isVoidAllowed: true);
-    VariableDeclaration indexVariable = createVariableForResult(indexResult);
 
-    Expression readIndex = createVariableGet(indexVariable);
+    VariableDeclaration indexVariable;
+    Expression readIndex = indexResult.expression;
+    Expression writeIndex;
+    if (isPureExpression(readIndex)) {
+      writeIndex = clonePureExpression(readIndex);
+    } else {
+      indexVariable = createVariable(readIndex, indexResult.inferredType);
+      readIndex = createVariableGet(indexVariable);
+      writeIndex = createVariableGet(indexVariable);
+    }
+
     readIndex = inferrer.ensureAssignable(
         readIndexType, indexResult.inferredType, readIndex);
 
@@ -5387,7 +5444,6 @@
     Expression binary = binaryResult.expression;
     DartType binaryType = binaryResult.inferredType;
 
-    Expression writeIndex = createVariableGet(indexVariable);
     writeIndex = inferrer.ensureAssignable(
         writeIndexType, indexResult.inferredType, writeIndex);
     binary = inferrer.ensureAssignable(valueType, binaryType, binary,
@@ -5422,7 +5478,7 @@
       //     let indexVariable = a in
       //         receiverVariable.[]=(receiverVariable, o.[](indexVariable) + b)
       //
-      replacement = createLet(indexVariable, write);
+      replacement = write;
     } else if (node.forPostIncDec) {
       // Encode `Extension(o)[a]++` as:
       //
@@ -5438,10 +5494,8 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(leftVariable,
-              createLet(writeVariable, createVariableGet(leftVariable))));
+      replacement = createLet(leftVariable,
+          createLet(writeVariable, createVariableGet(leftVariable)));
     } else {
       // Encode `Extension(o)[a] += b` as:
       //
@@ -5457,12 +5511,12 @@
 
       VariableDeclaration writeVariable =
           createVariable(write, const VoidType());
-      replacement = createLet(
-          indexVariable,
-          createLet(valueVariable,
-              createLet(writeVariable, createVariableGet(valueVariable))));
+      replacement = createLet(valueVariable,
+          createLet(writeVariable, createVariableGet(valueVariable)));
     }
-
+    if (indexVariable != null) {
+      replacement = createLet(indexVariable, replacement);
+    }
     if (receiverVariable != null) {
       replacement = new Let(receiverVariable, replacement);
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 56a9bd8..1f6acdd 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -1785,10 +1785,6 @@
   /// The member used for the write operation.
   final Member setter;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   /// If `true`, the expression is only need for effect and not for its value.
   final bool forEffect;
 
@@ -1810,13 +1806,11 @@
       this.binaryName,
       this.rhs,
       this.setter,
-      {this.readOnlyReceiver,
-      this.forEffect,
+      {this.forEffect,
       this.readOffset,
       this.binaryOffset,
       this.writeOffset})
-      : assert(readOnlyReceiver != null),
-        assert(forEffect != null),
+      : assert(forEffect != null),
         assert(readOffset != null),
         assert(binaryOffset != null),
         assert(writeOffset != null) {
@@ -1885,10 +1879,6 @@
   /// If `true`, the expression is only need for effect and not for its value.
   final bool forEffect;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   /// The file offset for the read operation.
   final int readOffset;
 
@@ -1900,13 +1890,8 @@
 
   CompoundPropertySet(
       this.receiver, this.propertyName, this.binaryName, this.rhs,
-      {this.forEffect,
-      this.readOnlyReceiver,
-      this.readOffset,
-      this.binaryOffset,
-      this.writeOffset})
+      {this.forEffect, this.readOffset, this.binaryOffset, this.writeOffset})
       : assert(forEffect != null),
-        assert(readOnlyReceiver != null),
         assert(readOffset != null),
         assert(binaryOffset != null),
         assert(writeOffset != null) {
@@ -2253,12 +2238,8 @@
 
   final bool forEffect;
 
-  final bool readOnlyReceiver;
-
-  IndexSet(this.receiver, this.index, this.value,
-      {this.forEffect, this.readOnlyReceiver})
-      : assert(forEffect != null),
-        assert(readOnlyReceiver != null) {
+  IndexSet(this.receiver, this.index, this.value, {this.forEffect})
+      : assert(forEffect != null) {
     receiver?.parent = this;
     index?.parent = this;
     value?.parent = this;
@@ -2446,6 +2427,20 @@
   String toString() {
     return "ExtensionIndexSet(${toStringInternal()})";
   }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.write(extension.name);
+    if (explicitTypeArguments != null) {
+      printer.writeTypeArguments(explicitTypeArguments);
+    }
+    printer.write('(');
+    printer.writeExpression(receiver);
+    printer.write(')[');
+    printer.writeExpression(index);
+    printer.write('] = ');
+    printer.writeExpression(value);
+  }
 }
 
 /// Internal expression representing an if-null index assignment.
@@ -2493,16 +2488,8 @@
   /// If `true`, the expression is only need for effect and not for its value.
   final bool forEffect;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   IfNullIndexSet(this.receiver, this.index, this.value,
-      {this.readOffset,
-      this.testOffset,
-      this.writeOffset,
-      this.forEffect,
-      this.readOnlyReceiver: false})
+      {this.readOffset, this.testOffset, this.writeOffset, this.forEffect})
       : assert(readOffset != null),
         assert(testOffset != null),
         assert(writeOffset != null),
@@ -2688,24 +2675,15 @@
   /// If `true`, the expression is only need for effect and not for its value.
   final bool forEffect;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   IfNullExtensionIndexSet(this.extension, this.explicitTypeArguments,
       this.receiver, this.getter, this.setter, this.index, this.value,
-      {this.readOffset,
-      this.testOffset,
-      this.writeOffset,
-      this.forEffect,
-      this.readOnlyReceiver})
+      {this.readOffset, this.testOffset, this.writeOffset, this.forEffect})
       : assert(explicitTypeArguments == null ||
             explicitTypeArguments.length == extension.typeParameters.length),
         assert(readOffset != null),
         assert(testOffset != null),
         assert(writeOffset != null),
-        assert(forEffect != null),
-        assert(readOnlyReceiver != null) {
+        assert(forEffect != null) {
     receiver?.parent = this;
     index?.parent = this;
     value?.parent = this;
@@ -2792,17 +2770,12 @@
   /// If `true`, the expression is a post-fix inc/dec expression.
   final bool forPostIncDec;
 
-  /// If `true`, the receiver is read-only and therefore doesn't need a
-  /// temporary variable for its value.
-  final bool readOnlyReceiver;
-
   CompoundIndexSet(this.receiver, this.index, this.binaryName, this.rhs,
       {this.readOffset,
       this.binaryOffset,
       this.writeOffset,
       this.forEffect,
-      this.forPostIncDec,
-      this.readOnlyReceiver: false})
+      this.forPostIncDec})
       : assert(forEffect != null) {
     receiver?.parent = this;
     index?.parent = this;
@@ -3248,10 +3221,6 @@
   /// If `true`, the expression is a post-fix inc/dec expression.
   final bool forPostIncDec;
 
-  /// If `true` the receiver can be cloned instead of creating a temporary
-  /// variable.
-  final bool readOnlyReceiver;
-
   CompoundExtensionIndexSet(
       this.extension,
       this.explicitTypeArguments,
@@ -3265,16 +3234,14 @@
       this.binaryOffset,
       this.writeOffset,
       this.forEffect,
-      this.forPostIncDec,
-      this.readOnlyReceiver})
+      this.forPostIncDec})
       : assert(explicitTypeArguments == null ||
             explicitTypeArguments.length == extension.typeParameters.length),
         assert(readOffset != null),
         assert(binaryOffset != null),
         assert(writeOffset != null),
         assert(forEffect != null),
-        assert(forPostIncDec != null),
-        assert(readOnlyReceiver != null) {
+        assert(forPostIncDec != null) {
     receiver?.parent = this;
     index?.parent = this;
     rhs?.parent = this;
@@ -3359,16 +3326,11 @@
   /// value.
   final bool forEffect;
 
-  /// If `true` the receiver can be cloned instead of creating a temporary
-  /// variable.
-  final bool readOnlyReceiver;
-
   ExtensionSet(this.extension, this.explicitTypeArguments, this.receiver,
       this.target, this.value,
-      {this.readOnlyReceiver, this.forEffect})
+      {this.forEffect})
       : assert(explicitTypeArguments == null ||
             explicitTypeArguments.length == extension.typeParameters.length),
-        assert(readOnlyReceiver != null),
         assert(forEffect != null) {
     receiver?.parent = this;
     value?.parent = this;
@@ -3776,3 +3738,33 @@
   return new ExpressionStatement(expression)
     ..fileOffset = expression.fileOffset;
 }
+
+/// Returns `true` if [node] is a pure expression.
+///
+/// A pure expression is an expression that is deterministic and side effect
+/// free, such as `this` or a variable get of a final variable.
+bool isPureExpression(Expression node) {
+  if (node is ThisExpression) {
+    return true;
+  } else if (node is VariableGet) {
+    return node.variable.isFinal && !node.variable.isLate;
+  }
+  return false;
+}
+
+/// Returns a clone of [node].
+///
+/// This assumes that `isPureExpression(node)` is `true`.
+Expression clonePureExpression(Expression node) {
+  if (node is ThisExpression) {
+    return new ThisExpression()..fileOffset = node.fileOffset;
+  } else if (node is VariableGet) {
+    assert(
+        node.variable.isFinal && !node.variable.isLate,
+        "Trying to clone VariableGet of non-final variable"
+        " ${node.variable}.");
+    return new VariableGet(node.variable, node.promotedType)
+      ..fileOffset = node.fileOffset;
+  }
+  throw new UnsupportedError("Clone not supported for ${node.runtimeType}.");
+}
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 0324ac4..830562f 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
@@ -3949,13 +3949,11 @@
   Expression createMissingIndexSet(int fileOffset, Expression receiver,
       DartType receiverType, Expression index, Expression value,
       {bool forEffect,
-      bool readOnlyReceiver,
       List<ExtensionAccessCandidate> extensionAccessCandidates}) {
     assert(forEffect != null);
-    assert(readOnlyReceiver != null);
     if (isTopLevel) {
       return engine.forest.createIndexSet(fileOffset, receiver, index, value,
-          forEffect: forEffect, readOnlyReceiver: readOnlyReceiver);
+          forEffect: forEffect);
     } else {
       return _reportMissingOrAmbiguousMember(
           fileOffset,
diff --git a/pkg/front_end/lib/src/fasta/util/textual_outline.dart b/pkg/front_end/lib/src/fasta/util/textual_outline.dart
index 676582d..6b5d823 100644
--- a/pkg/front_end/lib/src/fasta/util/textual_outline.dart
+++ b/pkg/front_end/lib/src/fasta/util/textual_outline.dart
@@ -11,6 +11,9 @@
 
 import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart';
 
+import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
+    show ScannerConfiguration;
+
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show ErrorToken, LanguageVersionToken, Scanner;
 
@@ -418,7 +421,8 @@
 //              "show A, B, C hide A show A" would be empty.
 
 String textualOutline(List<int> rawBytes,
-    {bool throwOnUnexpected: false,
+    {ScannerConfiguration configuration,
+    bool throwOnUnexpected: false,
     bool performModelling: false,
     bool addMarkerForUnknownForTest: false}) {
   Uint8List bytes = new Uint8List(rawBytes.length + 1);
@@ -428,8 +432,9 @@
 
   BoxedInt originalPosition = new BoxedInt(0);
 
-  Utf8BytesScanner scanner = new Utf8BytesScanner(bytes, includeComments: false,
-      languageVersionChanged:
+  Utf8BytesScanner scanner = new Utf8BytesScanner(bytes,
+      includeComments: false,
+      configuration: configuration, languageVersionChanged:
           (Scanner scanner, LanguageVersionToken languageVersion) {
     parsedChunks.add(
         new _LanguageVersionChunk(languageVersion.major, languageVersion.minor)
diff --git a/pkg/front_end/test/fasta/textual_outline_suite.dart b/pkg/front_end/test/fasta/textual_outline_suite.dart
index 702b2fc..f0dbb30 100644
--- a/pkg/front_end/test/fasta/textual_outline_suite.dart
+++ b/pkg/front_end/test/fasta/textual_outline_suite.dart
@@ -6,6 +6,9 @@
 
 import 'dart:io';
 
+import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
+    show ScannerConfiguration;
+
 import 'package:dart_style/dart_style.dart' show DartFormatter;
 
 import 'package:front_end/src/fasta/util/textual_outline.dart';
@@ -78,7 +81,9 @@
       String result = textualOutline(bytes,
           throwOnUnexpected: true,
           performModelling: modelled,
-          addMarkerForUnknownForTest: modelled);
+          addMarkerForUnknownForTest: modelled,
+          configuration:
+              const ScannerConfiguration(enableExtensionMethods: true));
       if (result == null) {
         return new Result(
             null, context.expectationSet["EmptyOutput"], description.uri);
diff --git a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
index 7279fce..c0fd0e7a 100644
--- a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
+++ b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
@@ -588,7 +588,6 @@
           readOffset: TreeNode.noOffset,
           binaryOffset: TreeNode.noOffset,
           writeOffset: TreeNode.noOffset,
-          readOnlyReceiver: false,
           forEffect: false),
       '''
 0.foo += 1''');
@@ -608,7 +607,27 @@
 
 void _testSuperIndexSet() {}
 
-void _testExtensionIndexSet() {}
+void _testExtensionIndexSet() {
+  Library library = new Library(dummyUri);
+  Extension extension = new Extension(
+      name: 'Extension', typeParameters: [new TypeParameter('T')]);
+  library.addExtension(extension);
+  Procedure setter =
+      new Procedure(new Name(''), ProcedureKind.Method, new FunctionNode(null));
+  library.addProcedure(setter);
+
+  testExpression(
+      new ExtensionIndexSet(extension, null, new IntLiteral(0), setter,
+          new IntLiteral(1), new IntLiteral(2)),
+      '''
+Extension(0)[1] = 2''');
+
+  testExpression(
+      new ExtensionIndexSet(extension, [const VoidType()], new IntLiteral(0),
+          setter, new IntLiteral(1), new IntLiteral(2)),
+      '''
+Extension<void>(0)[1] = 2''');
+}
 
 void _testIfNullIndexSet() {}
 
diff --git a/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline.expect
index 94df769..cdead34 100644
--- a/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline.expect
@@ -1,7 +1,24 @@
-extension A ;
-on C (){}
-extension B ;
-on C (){}
+extension A on C {
+  void method() {}
+  int get getter => 42;
+  void set setter(int value) {}
+  int get property => 42;
+  int operator +(int i) => i;
+  int operator -() => 0;
+  int operator [](int i) => i;
+}
+
+extension B on C {
+  void method() {}
+  int get getter => 42;
+  void set setter(int value) {}
+  void set property(int value) {}
+  int operator +(int i) => i;
+  int operator -() => 0;
+  void operator []=(int i, int j) {}
+}
+
 class C {}
+
 errors(C c) {}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..181cba7e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/ambiguous.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+class C {}
+
+errors(C c) {}
+
+extension A on C {
+  int get getter => 42;
+  int get property => 42;
+  int operator +(int i) => i;
+  int operator -() => 0;
+  int operator [](int i) => i;
+  void method() {}
+  void set setter(int value) {}
+}
+
+extension B on C {
+  int get getter => 42;
+  int operator +(int i) => i;
+  int operator -() => 0;
+  void method() {}
+  void operator []=(int i, int j) {}
+  void set property(int value) {}
+  void set setter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/annotations.dart.textual_outline.expect
index dc4aa33..29e0b7f 100644
--- a/pkg/front_end/testcases/extensions/annotations.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/annotations.dart.textual_outline.expect
@@ -4,8 +4,14 @@
   @pragma('dart2js:noInline')
   static staticMethod() {}
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  @pragma('dart2js:noInline')
+  extensionInstanceMethod() {}
+  @pragma('dart2js:noInline')
+  static extensionStaticMethod() {}
+}
+
 @pragma('dart2js:noInline')
 topLevelMethod() {}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/annotations.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ad11530
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/annotations.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class Class {
+  @pragma('dart2js:noInline')
+  instanceMethod() {}
+  @pragma('dart2js:noInline')
+  static staticMethod() {}
+}
+
+extension Extension on Class {
+  @pragma('dart2js:noInline')
+  extensionInstanceMethod() {}
+  @pragma('dart2js:noInline')
+  static extensionStaticMethod() {}
+}
+
+main() {}
+@pragma('dart2js:noInline')
+topLevelMethod() {}
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect
index 49c2279..101e634 100644
--- a/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect
@@ -1,3 +1,7 @@
-extension Extension ;
-on int (){}
+extension Extension on int {
+  syncStarMethod() sync* {}
+  asyncMethod() async {}
+  asyncStarMethod() async* {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..52c36dd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+extension Extension on int {
+  asyncMethod() async {}
+  asyncStarMethod() async* {}
+  syncStarMethod() sync* {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect
index fe2d23d..fe4b2b0 100644
--- a/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline.expect
@@ -1,9 +1,29 @@
-extension Extension1<T extends Object> (){}
-on T (){}
-extension Extension2<T extends String> (){}
-on T (){}
-extension Extension3<T extends dynamic> (){}
-on T (){}
-extension Extension4<T> (){}
-on T (){}
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/bounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fe4b2b0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/bounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,29 @@
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline.expect
index fe33481..3fef925 100644
--- a/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline.expect
@@ -1,7 +1,7 @@
-extension ;
-mixin on int {}
-extension extension ;
-on int (){}
-extension as ;
-on int (){}
+extension mixin on int {}
+
+extension extension on int {}
+
+extension as on int {}
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..94a2d44
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/builtin_identifiers.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+extension as on int {}
+
+extension extension on int {}
+
+extension mixin on int {}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline.expect
index b4fd451..cb13225 100644
--- a/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline.expect
@@ -1,15 +1,23 @@
 class A {
   String get call => "My name is A";
 }
+
 class B {
   String Function() get call => () => "My name is B";
 }
-extension on ;
-int (){}
-extension on ;
-num (){}
-extension on ;
-String (){}
+
+extension on int {
+  String get call => "My name is int";
+}
+
+extension on num {
+  String get call => "My name is num";
+}
+
+extension on String {
+  String Function() get call => () => "My name is String";
+}
+
 main() {}
 var topLevel1 = 1(10);
 var topLevel2 = 1("10");
diff --git a/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..30be637
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/call_methods.dart.textual_outline_modelled.expect
@@ -0,0 +1,32 @@
+A a = new A();
+B b = new B();
+
+class A {
+  String get call => "My name is A";
+}
+
+class B {
+  String Function() get call => () => "My name is B";
+}
+
+errors() {}
+
+extension on String {
+  String Function() get call => () => "My name is String";
+}
+
+extension on int {
+  String get call => "My name is int";
+}
+
+extension on num {
+  String get call => "My name is num";
+}
+
+main() {}
+var topLevel1 = 1(10);
+var topLevel2 = 1("10");
+var topLevel3 = 1.0(10);
+var topLevel4 = 1.0("10");
+var topLevel5 = a(2);
+var topLevel6 = a(2, "3");
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline.expect
index 57b1a20..ee9c440 100644
--- a/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline.expect
@@ -1,9 +1,16 @@
 part 'check_bounds_lib.dart';
+
 class A {}
+
 class B extends A {}
+
 class Class<T extends A> {}
-extension Extension<T extends B> (){}
-on Class<T> (){}
+
+extension Extension<T extends B> on Class<T> {
+  method() {}
+  genericMethod<S extends B>(S s) {}
+}
+
 main() {}
 test() {}
 final A a = new A();
diff --git a/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2b09fba
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/check_bounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,47 @@
+part 'check_bounds_lib.dart';
+
+class A {}
+
+class B extends A {}
+
+class Class<T extends A> {}
+
+extension Extension<T extends B> on Class<T> {
+  genericMethod<S extends B>(S s) {}
+  method() {}
+}
+
+final A a = new A();
+final Class<A> classA = new Class<A>();
+final Class<B> classB = new Class<B>();
+final field1 = classA.method();
+final field10 = Extension<A>(classA).genericMethod<B>(a);
+final field11 = Extension<B>(classA).genericMethod(a);
+final field12 = Extension<B>(classA).genericMethod<A>(a);
+final field13 = Extension<B>(classA).genericMethod<B>(a);
+final field14 = classB.method();
+final field15 = Extension(classB).method();
+final field16 = Extension<A>(classB).method();
+final field17 = Extension<B>(classB).method();
+final field18 = classB.genericMethod(a);
+final field19 = classB.genericMethod<A>(a);
+final field2 = Extension(classA).method();
+final field20 = classB.genericMethod<B>(a);
+final field21 = Extension(classB).genericMethod(a);
+final field22 = Extension(classB).genericMethod<A>(a);
+final field23 = Extension(classB).genericMethod<B>(a);
+final field24 = Extension<A>(classB).genericMethod(a);
+final field25 = Extension<A>(classB).genericMethod<A>(a);
+final field26 = Extension<A>(classB).genericMethod<B>(a);
+final field27 = Extension<B>(classB).genericMethod(a);
+final field28 = Extension<B>(classB).genericMethod<A>(a);
+final field29 = Extension<B>(classB).genericMethod<B>(a);
+final field3 = Extension<A>(classA).method();
+final field4 = Extension<B>(classA).method();
+final field5 = Extension(classA).genericMethod(a);
+final field6 = Extension(classA).genericMethod<A>(a);
+final field7 = Extension(classA).genericMethod<B>(a);
+final field8 = Extension<A>(classA).genericMethod(a);
+final field9 = Extension<A>(classA).genericMethod<A>(a);
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/compounds.dart.textual_outline.expect
index 78776b5..4e5e0d2 100644
--- a/pkg/front_end/testcases/extensions/compounds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/compounds.dart.textual_outline.expect
@@ -5,20 +5,34 @@
   bool operator ==(Object other) => other is Number && value == other.value;
   String toString() => 'Number($value)';
 }
-extension NumberExtension ;
-on Number (){}
+
+extension NumberExtension on Number {
+  Number operator +(Object other) {}
+  Number operator -(Object other) {}
+}
+
 class Class {
   Number field;
   Class(this.field);
 }
-extension ClassExtension ;
-on Class (){}
+
+extension ClassExtension on Class {
+  Number get property => field;
+  void set property(Number value) {}
+  testImplicitProperties() {}
+}
+
 class IntClass {
   int field;
   IntClass(this.field);
 }
-extension IntClassExtension ;
-on IntClass (){}
+
+extension IntClassExtension on IntClass {
+  int get property => field;
+  void set property(int value) {}
+  testImplicitProperties() {}
+}
+
 main() {}
 testLocals() {}
 testProperties() {}
diff --git a/pkg/front_end/testcases/extensions/compounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/compounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fada7bd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/compounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,45 @@
+class Class {
+  Class(this.field);
+  Number field;
+}
+
+class IntClass {
+  IntClass(this.field);
+  int field;
+}
+
+class Number {
+  Number(this.value);
+  String toString() => 'Number($value)';
+  bool operator ==(Object other) => other is Number && value == other.value;
+  final int value;
+  int get hashCode => value.hashCode;
+}
+
+expect(expected, actual, [expectNull = false]) {}
+
+extension ClassExtension on Class {
+  Number get property => field;
+  testImplicitProperties() {}
+  void set property(Number value) {}
+}
+
+extension IntClassExtension on IntClass {
+  int get property => field;
+  testImplicitProperties() {}
+  void set property(int value) {}
+}
+
+extension NumberExtension on Number {
+  Number operator +(Object other) {}
+  Number operator -(Object other) {}
+}
+
+main() {}
+testExplicitIntProperties() {}
+testExplicitNullAwareIntProperties(IntClass v) {}
+testExplicitNullAwareProperties(Class v) {}
+testExplicitProperties() {}
+testIntProperties() {}
+testLocals() {}
+testProperties() {}
diff --git a/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline.expect
index 1550bbb..eb8b109 100644
--- a/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline.expect
@@ -1,5 +1,11 @@
-extension Extension ;
-on String (){}
+extension Extension on String {
+  int get noSuchMethod => 42;
+  void set hashCode(int value) {}
+  int runtimeType() {}
+  operator ==(other) => false;
+  static String toString() => 'Foo';
+}
+
 main() {}
 errors() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f5441b5
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/conflict_with_object.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+errors() {}
+expect(expected, actual) {}
+
+extension Extension on String {
+  int get noSuchMethod => 42;
+  int runtimeType() {}
+  operator ==(other) => false;
+  static String toString() => 'Foo';
+  void set hashCode(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline.expect
index 5a2e29f..0f53c9b 100644
--- a/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline.expect
@@ -1,10 +1,21 @@
 class Class1 {}
+
 class Class2 {}
-extension DuplicateExtensionName ;
-on Class1 (){}
-extension DuplicateExtensionName ;
-on Class2 (){}
-extension UniqueExtensionName ;
-on Class1 (){}
+
+extension DuplicateExtensionName on Class1 {
+  uniqueMethod1() {}
+  duplicateMethodName2() => 1;
+}
+
+extension DuplicateExtensionName on Class2 {
+  uniqueMethod2() {}
+  duplicateMethodName2() => 2;
+}
+
+extension UniqueExtensionName on Class1 {
+  duplicateMethodName1() => 1;
+  duplicateMethodName1() => 2;
+}
+
 main() {}
 errors() {}
diff --git a/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..481736e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/conflicts.dart.textual_outline_modelled.expect
@@ -0,0 +1,22 @@
+class Class1 {}
+
+class Class2 {}
+
+errors() {}
+
+extension DuplicateExtensionName on Class1 {
+  duplicateMethodName2() => 1;
+  uniqueMethod1() {}
+}
+
+extension DuplicateExtensionName on Class2 {
+  duplicateMethodName2() => 2;
+  uniqueMethod2() {}
+}
+
+extension UniqueExtensionName on Class1 {
+  duplicateMethodName1() => 1;
+  duplicateMethodName1() => 2;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/default_values.dart.textual_outline.expect
index aa7d513..76863ce 100644
--- a/pkg/front_end/testcases/extensions/default_values.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/default_values.dart.textual_outline.expect
@@ -1,5 +1,12 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  method0([a]) => a;
+  method1([a = 42]) => a;
+  method2({b = 87}) => b;
+  method3({c = staticMethod}) => c();
+  static staticMethod() => 123;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/default_values.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/default_values.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..dac2c87e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/default_values.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+class Class {}
+
+expect(expected, actual) {}
+
+extension Extension on Class {
+  method0([a]) => a;
+  method1([a = 42]) => a;
+  method2({b = 87}) => b;
+  method3({c = staticMethod}) => c();
+  static staticMethod() => 123;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline.expect
index adb6b12..dd71c14 100644
--- a/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline.expect
@@ -1,11 +1,47 @@
 class Class {
   var field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  readGetter() {}
+  writeSetterRequired(value) {}
+  writeSetterOptional([value]) {}
+  writeSetterNamed({value}) {}
+  get tearOffGetterNoArgs => readGetter;
+  get tearOffGetterRequired => writeSetterRequired;
+  get tearOffGetterOptional => writeSetterOptional;
+  get tearOffGetterNamed => writeSetterNamed;
+  get property => this.field;
+  set property(value) {}
+  invocations(value) {}
+  tearOffs(value) {}
+  getterCalls(value) {}
+}
+
 class GenericClass<T> {
   T field;
 }
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  T readGetter() {}
+  writeSetterRequired(T value) {}
+  writeSetterOptional([T value]) {}
+  writeSetterNamed({T value}) {}
+  genericWriteSetterRequired<S extends T>(S value) {}
+  genericWriteSetterOptional<S extends T>([S value]) {}
+  genericWriteSetterNamed<S extends T>({S value}) {}
+  T get property => this.field;
+  void set property(T value) {}
+  get tearOffGetterNoArgs => readGetter;
+  get tearOffGetterRequired => writeSetterRequired;
+  get tearOffGetterOptional => writeSetterOptional;
+  get tearOffGetterNamed => writeSetterNamed;
+  get tearOffGetterGenericRequired => genericWriteSetterRequired;
+  get tearOffGetterGenericOptional => genericWriteSetterOptional;
+  get tearOffGetterGenericNamed => genericWriteSetterNamed;
+  invocations<S extends T>(S value) {}
+  tearOffs<S extends T>(S value) {}
+  getterCalls<S extends T>(S value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9e4b234
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/direct_instance_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,47 @@
+class Class {
+  var field;
+}
+
+class GenericClass<T> {
+  T field;
+}
+
+extension Extension on Class {
+  get property => this.field;
+  get tearOffGetterNamed => writeSetterNamed;
+  get tearOffGetterNoArgs => readGetter;
+  get tearOffGetterOptional => writeSetterOptional;
+  get tearOffGetterRequired => writeSetterRequired;
+  getterCalls(value) {}
+  invocations(value) {}
+  readGetter() {}
+  set property(value) {}
+  tearOffs(value) {}
+  writeSetterNamed({value}) {}
+  writeSetterOptional([value]) {}
+  writeSetterRequired(value) {}
+}
+
+extension GenericExtension<T> on GenericClass<T> {
+  T get property => this.field;
+  T readGetter() {}
+  genericWriteSetterNamed<S extends T>({S value}) {}
+  genericWriteSetterOptional<S extends T>([S value]) {}
+  genericWriteSetterRequired<S extends T>(S value) {}
+  get tearOffGetterGenericNamed => genericWriteSetterNamed;
+  get tearOffGetterGenericOptional => genericWriteSetterOptional;
+  get tearOffGetterGenericRequired => genericWriteSetterRequired;
+  get tearOffGetterNamed => writeSetterNamed;
+  get tearOffGetterNoArgs => readGetter;
+  get tearOffGetterOptional => writeSetterOptional;
+  get tearOffGetterRequired => writeSetterRequired;
+  getterCalls<S extends T>(S value) {}
+  invocations<S extends T>(S value) {}
+  tearOffs<S extends T>(S value) {}
+  void set property(T value) {}
+  writeSetterNamed({T value}) {}
+  writeSetterOptional([T value]) {}
+  writeSetterRequired(T value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline.expect
index 34dd7dc..44997e9 100644
--- a/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline.expect
@@ -1,6 +1,33 @@
 class Class<T> {
   static var field;
 }
-extension Extension<T> (){}
-on Class<T> (){}
+
+extension Extension<T> on Class<T> {
+  static get property => Class.field;
+  static set property(value) {}
+  static var field;
+  static readGetter() {}
+  static writeSetterRequired(value) {}
+  static writeSetterOptional([value]) {}
+  static writeSetterNamed({value}) {}
+  static genericWriteSetterRequired<S>(S value) {}
+  static genericWriteSetterOptional<S>([S value]) {}
+  static genericWriteSetterNamed<S>({S value}) {}
+  static get tearOffGetterNoArgs => readGetter;
+  static get tearOffGetterRequired => writeSetterRequired;
+  static get tearOffGetterOptional => writeSetterOptional;
+  static get tearOffGetterNamed => writeSetterNamed;
+  static get tearOffGetterGenericRequired => genericWriteSetterRequired;
+  static get tearOffGetterGenericOptional => genericWriteSetterOptional;
+  static get tearOffGetterGenericNamed => genericWriteSetterNamed;
+  static invocationsFromStaticContext(int value) {}
+  static tearOffsFromStaticContext(int value) {}
+  static fieldAccessFromStaticContext() {}
+  static getterCallsFromStaticContext(int value) {}
+  invocationsFromInstanceContext(T value) {}
+  tearOffsFromInstanceContext(T value) {}
+  fieldAccessFromInstanceContext() {}
+  getterCallsFromInstanceContext(T value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cbd1559
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/direct_static_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,33 @@
+class Class<T> {
+  static var field;
+}
+
+extension Extension<T> on Class<T> {
+  fieldAccessFromInstanceContext() {}
+  getterCallsFromInstanceContext(T value) {}
+  invocationsFromInstanceContext(T value) {}
+  static fieldAccessFromStaticContext() {}
+  static genericWriteSetterNamed<S>({S value}) {}
+  static genericWriteSetterOptional<S>([S value]) {}
+  static genericWriteSetterRequired<S>(S value) {}
+  static get property => Class.field;
+  static get tearOffGetterGenericNamed => genericWriteSetterNamed;
+  static get tearOffGetterGenericOptional => genericWriteSetterOptional;
+  static get tearOffGetterGenericRequired => genericWriteSetterRequired;
+  static get tearOffGetterNamed => writeSetterNamed;
+  static get tearOffGetterNoArgs => readGetter;
+  static get tearOffGetterOptional => writeSetterOptional;
+  static get tearOffGetterRequired => writeSetterRequired;
+  static getterCallsFromStaticContext(int value) {}
+  static invocationsFromStaticContext(int value) {}
+  static readGetter() {}
+  static set property(value) {}
+  static tearOffsFromStaticContext(int value) {}
+  static var field;
+  static writeSetterNamed({value}) {}
+  static writeSetterOptional([value]) {}
+  static writeSetterRequired(value) {}
+  tearOffsFromInstanceContext(T value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline.expect
index 2b221a1..5ee7ab2 100644
--- a/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline.expect
@@ -1,9 +1,14 @@
 class Class {
   noSuchMethod(Invocation i) => 123;
 }
-extension ClassExtension ;
-on Class (){}
-extension Extension ;
-on dynamic (){}
+
+extension ClassExtension on Class {
+  int method() => 42;
+}
+
+extension Extension on dynamic {
+  int method() => 87;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..df09e5e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/dynamic_invoke.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class Class {
+  noSuchMethod(Invocation i) => 123;
+}
+
+expect(expected, actual) {}
+
+extension ClassExtension on Class {
+  int method() => 42;
+}
+
+extension Extension on dynamic {
+  int method() => 87;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline.expect
index e338221..0bc2528 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline.expect
@@ -2,9 +2,20 @@
   int field1 = 42;
   int field2 = 87;
 }
-extension Extension1 ;
-on Class (){}
-extension Extension2 ;
-on Class (){}
+
+extension Extension1 on Class {
+  int get field => field1;
+  void set field(int value) {}
+  int method() => field1;
+  int genericMethod<T extends num>(T t) => field1 + t;
+}
+
+extension Extension2 on Class {
+  int get field => field2;
+  void set field(int value) {}
+  int method() => field2;
+  int genericMethod<T extends num>(T t) => field2 + t;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..95799c3
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,22 @@
+class Class {
+  int field1 = 42;
+  int field2 = 87;
+}
+
+expect(expected, actual) {}
+
+extension Extension1 on Class {
+  int genericMethod<T extends num>(T t) => field1 + t;
+  int get field => field1;
+  int method() => field1;
+  void set field(int value) {}
+}
+
+extension Extension2 on Class {
+  int genericMethod<T extends num>(T t) => field2 + t;
+  int get field => field2;
+  int method() => field2;
+  void set field(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline.expect
index 1777e12..076a719 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline.expect
@@ -1,7 +1,15 @@
 class A {}
+
 class B extends A {}
+
 class C extends B {}
+
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  T get property => null;
+  T method(T t) => null;
+  S genericMethod1<S>(S s) => null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..79d6ba0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_extension_inference.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class A {}
+
+class B extends A {}
+
+class C extends B {}
+
+class GenericClass<T> {}
+
+extension GenericExtension<T> on GenericClass<T> {
+  S genericMethod1<S>(S s) => null;
+  T get property => null;
+  T method(T t) => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline.expect
index 7319a83..b8ab337 100644
--- a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline.expect
@@ -3,9 +3,21 @@
   T field2;
   Class(this.field1, this.field2);
 }
-extension Extension1<T extends num> (){}
-on Class<T> (){}
-extension Extension2<T extends num> (){}
-on Class<T> (){}
+
+extension Extension1<T extends num> on Class<T> {
+  static String latestType;
+  T get field {}
+  void set field(T value) {}
+  T method() {}
+  T genericMethod<S extends num>(S t) {}
+}
+
+extension Extension2<T extends num> on Class<T> {
+  T get field => field2;
+  void set field(T value) {}
+  T method() => field2;
+  T genericMethod<S extends num>(S t) => field2 + t;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f800b7a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class Class<T extends num> {
+  Class(this.field1, this.field2);
+  T field1;
+  T field2;
+}
+
+expect(expected, actual) {}
+
+extension Extension1<T extends num> on Class<T> {
+  T genericMethod<S extends num>(S t) {}
+  T get field {}
+  T method() {}
+  static String latestType;
+  void set field(T value) {}
+}
+
+extension Extension2<T extends num> on Class<T> {
+  T genericMethod<S extends num>(S t) => field2 + t;
+  T get field => field2;
+  T method() => field2;
+  void set field(T value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline.expect
index 0425549..c1b8b08 100644
--- a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline.expect
@@ -1,5 +1,6 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {}
+
 errors(Class c) {}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..43c658b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_invalid_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+class Class {}
+
+errors(Class c) {}
+
+extension Extension on Class {}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline.expect
index 7519a03..8efd4bb 100644
--- a/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline.expect
@@ -2,6 +2,11 @@
   Object field;
   void method1() {}
 }
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  void method2() => this.method1();
+  Object method3() => this.field;
+  void method4(Object o) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ca8cb86
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/explicit_this.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class A1 {
+  Object field;
+  void method1() {}
+}
+
+extension A2 on A1 {
+  Object method3() => this.field;
+  void method2() => this.method1();
+  void method4(Object o) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline.expect
index e6e0f3d..3acad15 100644
--- a/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline.expect
@@ -1,7 +1,10 @@
 class Class<T> {
   T method(T a) => a;
 }
-extension Extension<T> (){}
-on Class<T> (){}
+
+extension Extension<T> on Class<T> {
+  T call(T a) => method(a);
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7edde0e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_call.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+class Class<T> {
+  T method(T a) => a;
+}
+
+expect(expected, actual) {}
+
+extension Extension<T> on Class<T> {
+  T call(T a) => method(a);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_constructor.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_constructor.dart.textual_outline.expect
index cc9ad4c..ac6bee2 100644
--- a/pkg/front_end/testcases/extensions/extension_constructor.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_constructor.dart.textual_outline.expect
@@ -1,4 +1,9 @@
 class Class {}
-extension Extension ;
-on Class (){}
+extension Extension on Class {
+  Extension() {}
+  Extension.named() {}
+  factory Extension.fact() => null;
+  factory Extension.redirect() = Extension;
+  method() {}
+}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.textual_outline.expect
index 9179aa3..26dc2e9 100644
--- a/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_field_with_type_parameter_usage.dart.textual_outline.expect
@@ -1,3 +1,10 @@
-extension E<U> (){}
-on String (){}
+extension E<U> on String {
+  U field1 = null;
+  int field2 = () { U x = null; return null; }();
+  List<U> field3 = null;
+  U Function(U) field4 = null;
+  List<U> Function(List<U>) field5 = null;
+  int field6 = <E>() { E x = null; return null; }<String>();
+  int field7 = <E>() { E x = null; return null; }<U>();
+}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect
index 6d262f3..f9f55d9 100644
--- a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect
@@ -1,3 +1,46 @@
-extension Extension<T> (){}
-on int (){}
+extension Extension<T> on int {
+  int get duplicateInstanceGetter => 0;
+  int get duplicateInstanceGetter => 0;
+  void set duplicateInstanceSetter(int value) {}
+  void set duplicateInstanceSetter(int value) {}
+  void duplicateInstanceMethod() {}
+  void duplicateInstanceMethod() {}
+  static int duplicateStaticField = 0;
+  static int duplicateStaticField = 0;
+  static int get duplicateStaticGetter => 0;
+  static int get duplicateStaticGetter => 0;
+  static void set duplicateStaticSetter(int value) {}
+  static void set duplicateStaticSetter(int value) {}
+  static void duplicateStaticMethod() {}
+  static void duplicateStaticMethod() {}
+  int get duplicateInstanceGetterPlusSetter => 0;
+  int get duplicateInstanceGetterPlusSetter => 0;
+  void set duplicateInstanceGetterPlusSetter(int value) {}
+  int get duplicateInstanceSetterPlusGetter => 0;
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+  int get duplicateInstanceGetterAndSetter => 0;
+  int get duplicateInstanceGetterAndSetter => 0;
+  void set duplicateInstanceGetterAndSetter(int value) {}
+  void set duplicateInstanceGetterAndSetter(int value) {}
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static void set duplicateStaticGetterPlusSetter(int value) {}
+  static int get duplicateStaticSetterPlusGetter => 0;
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+  static int get duplicateStaticGetterAndSetter => 0;
+  static int get duplicateStaticGetterAndSetter => 0;
+  static void set duplicateStaticGetterAndSetter(int value) {}
+  static void set duplicateStaticGetterAndSetter(int value) {}
+  int get instanceGetterAndStaticSetter => 0;
+  static void set instanceGetterAndStaticSetter(int value) {}
+  static int get instanceSetterAndStaticGetter => 0;
+  void set instanceSetterAndStaticGetter(int value) {}
+  int get instanceGetterAndStaticField => 0;
+  static int instanceGetterAndStaticField = 0;
+  void set instanceSetterAndStaticField(int value) {}
+  static final int instanceGetterAndStaticField = 0;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..88f38e3
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline_modelled.expect
@@ -0,0 +1,46 @@
+extension Extension<T> on int {
+  int get duplicateInstanceGetter => 0;
+  int get duplicateInstanceGetter => 0;
+  int get duplicateInstanceGetterAndSetter => 0;
+  int get duplicateInstanceGetterAndSetter => 0;
+  int get duplicateInstanceGetterPlusSetter => 0;
+  int get duplicateInstanceGetterPlusSetter => 0;
+  int get duplicateInstanceSetterPlusGetter => 0;
+  int get instanceGetterAndStaticField => 0;
+  int get instanceGetterAndStaticSetter => 0;
+  static final int instanceGetterAndStaticField = 0;
+  static int duplicateStaticField = 0;
+  static int duplicateStaticField = 0;
+  static int get duplicateStaticGetter => 0;
+  static int get duplicateStaticGetter => 0;
+  static int get duplicateStaticGetterAndSetter => 0;
+  static int get duplicateStaticGetterAndSetter => 0;
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static int get duplicateStaticSetterPlusGetter => 0;
+  static int get instanceSetterAndStaticGetter => 0;
+  static int instanceGetterAndStaticField = 0;
+  static void duplicateStaticMethod() {}
+  static void duplicateStaticMethod() {}
+  static void set duplicateStaticGetterAndSetter(int value) {}
+  static void set duplicateStaticGetterAndSetter(int value) {}
+  static void set duplicateStaticGetterPlusSetter(int value) {}
+  static void set duplicateStaticSetter(int value) {}
+  static void set duplicateStaticSetter(int value) {}
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+  static void set instanceGetterAndStaticSetter(int value) {}
+  void duplicateInstanceMethod() {}
+  void duplicateInstanceMethod() {}
+  void set duplicateInstanceGetterAndSetter(int value) {}
+  void set duplicateInstanceGetterAndSetter(int value) {}
+  void set duplicateInstanceGetterPlusSetter(int value) {}
+  void set duplicateInstanceSetter(int value) {}
+  void set duplicateInstanceSetter(int value) {}
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+  void set instanceSetterAndStaticField(int value) {}
+  void set instanceSetterAndStaticGetter(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline.expect
index ee11ab1..5ed8d9d8 100644
--- a/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline.expect
@@ -1,7 +1,11 @@
 import 'package:expect/expect.dart';
+
 class C {
   int get one => 1;
 }
-extension E ;
-on C (){}
+
+extension E on C {
+  int get two => 2;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5ed8d9d8
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_methods.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+import 'package:expect/expect.dart';
+
+class C {
+  int get one => 1;
+}
+
+extension E on C {
+  int get two => 2;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline.expect
index 6785be5..f06572f 100644
--- a/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline.expect
@@ -1,10 +1,24 @@
 class Class {
   int field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  int get simpleSetter => field;
+  set simpleSetter(int value) {}
+  int get mutatingSetter => field;
+  set mutatingSetter(int value) {}
+  int get setterWithReturn => field;
+  set setterWithReturn(int value) {}
+  int get setterWithClosure => field;
+  set setterWithClosure(int value) {}
+  testInternal() {}
+}
+
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  set setter(T value) {}
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..171d483
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,25 @@
+class Class {
+  int field;
+}
+
+class GenericClass<T> {}
+
+expect(expected, actual) {}
+
+extension Extension on Class {
+  int get mutatingSetter => field;
+  int get setterWithClosure => field;
+  int get setterWithReturn => field;
+  int get simpleSetter => field;
+  set mutatingSetter(int value) {}
+  set setterWithClosure(int value) {}
+  set setterWithReturn(int value) {}
+  set simpleSetter(int value) {}
+  testInternal() {}
+}
+
+extension GenericExtension<T> on GenericClass<T> {
+  set setter(T value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline.expect
index ee14f80..1a91b18 100644
--- a/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline.expect
@@ -1,5 +1,8 @@
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  set setter(T value) {}
+}
+
 error() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c2d2db9
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_setter_error.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+class GenericClass<T> {}
+
+error() {}
+expect(expected, actual) {}
+
+extension GenericExtension<T> on GenericClass<T> {
+  set setter(T value) {}
+}
diff --git a/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline.expect
index 6f0f637..c0519a0 100644
--- a/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline.expect
@@ -1,4 +1,7 @@
 class Class<T> {}
-extension Extension<T> (){}
-on Class<T> (){}
+
+extension Extension<T> on Class<T> {
+  R method<R>(T t) => null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c0519a0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/generic_function_in_generic_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+class Class<T> {}
+
+extension Extension<T> on Class<T> {
+  R method<R>(T t) => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline.expect
index 7cb1042..0207a05 100644
--- a/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline.expect
@@ -2,10 +2,19 @@
   int get m1 => 0;
   void set m2(int x) {}
 }
-extension Extension0 ;
-on Class (){}
-extension Extension1 ;
-on Class (){}
+
+extension Extension0 on Class {
+  void set m1(int x) {}
+  int get m2 => 0;
+  void set m3(int x) {}
+  int get m4 => 0;
+}
+
+extension Extension1 on Class {
+  int get m3 => 0;
+  void set m4(int x) {}
+}
+
 main() {}
 errors() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3da20ad
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/getter_setter_conflict.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class Class {
+  int get m1 => 0;
+  void set m2(int x) {}
+}
+
+errors() {}
+expect(expected, actual) {}
+
+extension Extension0 on Class {
+  int get m2 => 0;
+  int get m4 => 0;
+  void set m1(int x) {}
+  void set m3(int x) {}
+}
+
+extension Extension1 on Class {
+  int get m3 => 0;
+  void set m4(int x) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/if_null.dart.textual_outline.expect
index 3220178..473e89a 100644
--- a/pkg/front_end/testcases/extensions/if_null.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/if_null.dart.textual_outline.expect
@@ -1,6 +1,11 @@
 class Class {
   int field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  int get property => field;
+  void set property(int value) {}
+  int method() => field;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/if_null.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f29446e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/if_null.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+class Class {
+  int field;
+}
+
+extension Extension on Class {
+  int get property => field;
+  int method() => field;
+  void set property(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline.expect
index 1777e12..076a719 100644
--- a/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline.expect
@@ -1,7 +1,15 @@
 class A {}
+
 class B extends A {}
+
 class C extends B {}
+
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  T get property => null;
+  T method(T t) => null;
+  S genericMethod1<S>(S s) => null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..79d6ba0
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/implicit_extension_inference.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class A {}
+
+class B extends A {}
+
+class C extends B {}
+
+class GenericClass<T> {}
+
+extension GenericExtension<T> on GenericClass<T> {
+  S genericMethod1<S>(S s) => null;
+  T get property => null;
+  T method(T t) => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline.expect
index 7519a03..89eff23 100644
--- a/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline.expect
@@ -2,6 +2,11 @@
   Object field;
   void method1() {}
 }
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  void method2() => method1();
+  Object method3() => field;
+  void method4(Object o) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..eb7a0dd
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/implicit_this.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class A1 {
+  Object field;
+  void method1() {}
+}
+
+extension A2 on A1 {
+  Object method3() => field;
+  void method2() => method1();
+  void method4(Object o) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.expect b/pkg/front_end/testcases/extensions/index.dart.strong.expect
index f9f0d76..81557be 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.expect
@@ -70,23 +70,23 @@
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
   self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::int* #t44 = 1 in let final core::String* #t45 = "2" in let final void #t46 = self::Extension|[]=<core::int*, core::String*>(#t43, #t44, #t45) in #t45);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::String* #t44 = "2" in let final void #t45 = self::Extension|[]=<core::int*, core::String*>(#t43, 1, #t44) in #t44);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t47 = map1 in let final core::int* #t48 = 1 in self::Extension|[]<core::int*, core::String*>(#t47, #t48).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t47, #t48, "3") : null;
+  let final self::MapLike<core::int*, core::String*>* #t46 = map1 in let final core::int* #t47 = 1 in self::Extension|[]<core::int*, core::String*>(#t46, #t47).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t46, #t47, "3") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t49 = map1 in let final core::int* #t50 = 1 in let final core::String* #t51 = self::Extension|[]<core::int*, core::String*>(#t49, #t50) in #t51.{core::String::==}(null) ?{core::String*} let final core::String* #t52 = "4" in let final void #t53 = self::Extension|[]=<core::int*, core::String*>(#t49, #t50, #t52) in #t52 : #t51);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t48 = map1 in let final core::int* #t49 = 1 in let final core::String* #t50 = self::Extension|[]<core::int*, core::String*>(#t48, #t49) in #t50.{core::String::==}(null) ?{core::String*} let final core::String* #t51 = "4" in let final void #t52 = self::Extension|[]=<core::int*, core::String*>(#t48, #t49, #t51) in #t51 : #t50);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t54 = map1 in let final core::int* #t55 = 2 in self::Extension|[]<core::int*, core::String*>(#t54, #t55).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t54, #t55, "2") : null;
+  let final self::MapLike<core::int*, core::String*>* #t53 = map1 in let final core::int* #t54 = 2 in self::Extension|[]<core::int*, core::String*>(#t53, #t54).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t53, #t54, "2") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
-  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t56 = map1 in let final core::int* #t57 = 3 in let final core::String* #t58 = self::Extension|[]<core::int*, core::String*>(#t56, #t57) in #t58.{core::String::==}(null) ?{core::String*} let final core::String* #t59 = "3" in let final void #t60 = self::Extension|[]=<core::int*, core::String*>(#t56, #t57, #t59) in #t59 : #t58);
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t55 = map1 in let final core::int* #t56 = 3 in let final core::String* #t57 = self::Extension|[]<core::int*, core::String*>(#t55, #t56) in #t57.{core::String::==}(null) ?{core::String*} let final core::String* #t58 = "3" in let final void #t59 = self::Extension|[]=<core::int*, core::String*>(#t55, #t56, #t58) in #t58 : #t57);
   self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
   self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
-  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t61 = map2 in let final core::int* #t62 = 0 in let final core::int* #t63 = 1 in let final void #t64 = self::Extension|[]=<core::int*, core::int*>(#t61, #t62, #t63) in #t63);
-  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t60 = map2 in let final core::int* #t61 = 1 in let final void #t62 = self::Extension|[]=<core::int*, core::int*>(#t60, 0, #t61) in #t61);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t63 = map2 in let final core::int* #t64 = 0 in let final core::int* #t65 = self::Extension|[]<core::int*, core::int*>(#t63, #t64).{core::num::+}(2) in let final void #t66 = self::Extension|[]=<core::int*, core::int*>(#t63, #t64, #t65) in #t65);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t67 = map2 in let final core::int* #t68 = 0 in let final core::int* #t69 = self::Extension|[]<core::int*, core::int*>(#t67, #t68).{core::num::+}(2) in let final void #t70 = self::Extension|[]=<core::int*, core::int*>(#t67, #t68, #t69) in #t69);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t71 = map2 in let final core::int* #t72 = 0 in let final core::int* #t73 = self::Extension|[]<core::int*, core::int*>(#t71, #t72) in let final void #t74 = self::Extension|[]=<core::int*, core::int*>(#t71, #t72, #t73.{core::num::+}(1)) in #t73);
   self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t75 = map2 in let final core::int* #t76 = 0 in let final core::int* #t77 = self::Extension|[]<core::int*, core::int*>(#t75, #t76).{core::num::-}(1) in let final void #t78 = self::Extension|[]=<core::int*, core::int*>(#t75, #t76, #t77) in #t77);
   self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method explicitInferredTypeArguments() → dynamic {
@@ -97,23 +97,23 @@
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
   self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t81 = map1 in let final core::int* #t82 = 1 in let final core::String* #t83 = "2" in let final void #t84 = self::Extension|[]=<core::int*, core::String*>(#t81, #t82, #t83) in #t83);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t79 = map1 in let final core::String* #t80 = "2" in let final void #t81 = self::Extension|[]=<core::int*, core::String*>(#t79, 1, #t80) in #t80);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t85 = map1 in let final core::int* #t86 = 1 in self::Extension|[]<core::int*, core::String*>(#t85, #t86).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t85, #t86, "3") : null;
+  let final self::MapLike<core::int*, core::String*>* #t82 = map1 in let final core::int* #t83 = 1 in self::Extension|[]<core::int*, core::String*>(#t82, #t83).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t82, #t83, "3") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t87 = map1 in let final core::int* #t88 = 1 in let final core::String* #t89 = self::Extension|[]<core::int*, core::String*>(#t87, #t88) in #t89.{core::String::==}(null) ?{core::String*} let final core::String* #t90 = "4" in let final void #t91 = self::Extension|[]=<core::int*, core::String*>(#t87, #t88, #t90) in #t90 : #t89);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t84 = map1 in let final core::int* #t85 = 1 in let final core::String* #t86 = self::Extension|[]<core::int*, core::String*>(#t84, #t85) in #t86.{core::String::==}(null) ?{core::String*} let final core::String* #t87 = "4" in let final void #t88 = self::Extension|[]=<core::int*, core::String*>(#t84, #t85, #t87) in #t87 : #t86);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t92 = map1 in let final core::int* #t93 = 2 in self::Extension|[]<core::int*, core::String*>(#t92, #t93).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t92, #t93, "2") : null;
+  let final self::MapLike<core::int*, core::String*>* #t89 = map1 in let final core::int* #t90 = 2 in self::Extension|[]<core::int*, core::String*>(#t89, #t90).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t89, #t90, "2") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
-  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t94 = map1 in let final core::int* #t95 = 3 in let final core::String* #t96 = self::Extension|[]<core::int*, core::String*>(#t94, #t95) in #t96.{core::String::==}(null) ?{core::String*} let final core::String* #t97 = "3" in let final void #t98 = self::Extension|[]=<core::int*, core::String*>(#t94, #t95, #t97) in #t97 : #t96);
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t91 = map1 in let final core::int* #t92 = 3 in let final core::String* #t93 = self::Extension|[]<core::int*, core::String*>(#t91, #t92) in #t93.{core::String::==}(null) ?{core::String*} let final core::String* #t94 = "3" in let final void #t95 = self::Extension|[]=<core::int*, core::String*>(#t91, #t92, #t94) in #t94 : #t93);
   self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
   self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
-  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = 1 in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
-  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t96 = map2 in let final core::int* #t97 = 1 in let final void #t98 = self::Extension|[]=<core::int*, core::int*>(#t96, 0, #t97) in #t97);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = self::Extension|[]<core::int*, core::int*>(#t99, #t100).{core::num::+}(2) in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109.{core::num::+}(1)) in #t109);
   self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112).{core::num::-}(1) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113) in #t113);
   self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
index 771f107..e570b06 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
@@ -70,23 +70,23 @@
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
   self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::int* #t44 = 1 in let final core::String* #t45 = "2" in let final void #t46 = self::Extension|[]=<core::int*, core::String*>(#t43, #t44, #t45) in #t45);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t43 = map1 in let final core::String* #t44 = "2" in let final void #t45 = self::Extension|[]=<core::int*, core::String*>(#t43, 1, #t44) in #t44);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t47 = map1 in let final core::int* #t48 = 1 in self::Extension|[]<core::int*, core::String*>(#t47, #t48).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t47, #t48, "3") : null;
+  let final self::MapLike<core::int*, core::String*>* #t46 = map1 in let final core::int* #t47 = 1 in self::Extension|[]<core::int*, core::String*>(#t46, #t47).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t46, #t47, "3") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t49 = map1 in let final core::int* #t50 = 1 in let final core::String* #t51 = self::Extension|[]<core::int*, core::String*>(#t49, #t50) in #t51.{core::String::==}(null) ?{core::String*} let final core::String* #t52 = "4" in let final void #t53 = self::Extension|[]=<core::int*, core::String*>(#t49, #t50, #t52) in #t52 : #t51);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t48 = map1 in let final core::int* #t49 = 1 in let final core::String* #t50 = self::Extension|[]<core::int*, core::String*>(#t48, #t49) in #t50.{core::String::==}(null) ?{core::String*} let final core::String* #t51 = "4" in let final void #t52 = self::Extension|[]=<core::int*, core::String*>(#t48, #t49, #t51) in #t51 : #t50);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t54 = map1 in let final core::int* #t55 = 2 in self::Extension|[]<core::int*, core::String*>(#t54, #t55).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t54, #t55, "2") : null;
+  let final self::MapLike<core::int*, core::String*>* #t53 = map1 in let final core::int* #t54 = 2 in self::Extension|[]<core::int*, core::String*>(#t53, #t54).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t53, #t54, "2") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
-  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t56 = map1 in let final core::int* #t57 = 3 in let final core::String* #t58 = self::Extension|[]<core::int*, core::String*>(#t56, #t57) in #t58.{core::String::==}(null) ?{core::String*} let final core::String* #t59 = "3" in let final void #t60 = self::Extension|[]=<core::int*, core::String*>(#t56, #t57, #t59) in #t59 : #t58);
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t55 = map1 in let final core::int* #t56 = 3 in let final core::String* #t57 = self::Extension|[]<core::int*, core::String*>(#t55, #t56) in #t57.{core::String::==}(null) ?{core::String*} let final core::String* #t58 = "3" in let final void #t59 = self::Extension|[]=<core::int*, core::String*>(#t55, #t56, #t58) in #t58 : #t57);
   self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
   self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
-  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t61 = map2 in let final core::int* #t62 = 0 in let final core::int* #t63 = 1 in let final void #t64 = self::Extension|[]=<core::int*, core::int*>(#t61, #t62, #t63) in #t63);
-  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t65 = map2 in let final core::int* #t66 = 0 in let final core::int* #t67 = self::Extension|[]<core::int*, core::int*>(#t65, #t66).{core::num::+}(2) in let final void #t68 = self::Extension|[]=<core::int*, core::int*>(#t65, #t66, #t67) in #t67);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t69 = map2 in let final core::int* #t70 = 0 in let final core::int* #t71 = self::Extension|[]<core::int*, core::int*>(#t69, #t70).{core::num::+}(2) in let final void #t72 = self::Extension|[]=<core::int*, core::int*>(#t69, #t70, #t71) in #t71);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t73 = map2 in let final core::int* #t74 = 0 in let final core::int* #t75 = self::Extension|[]<core::int*, core::int*>(#t73, #t74) in let final void #t76 = self::Extension|[]=<core::int*, core::int*>(#t73, #t74, #t75.{core::num::+}(1)) in #t75);
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t60 = map2 in let final core::int* #t61 = 1 in let final void #t62 = self::Extension|[]=<core::int*, core::int*>(#t60, 0, #t61) in #t61);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t63 = map2 in let final core::int* #t64 = 0 in let final core::int* #t65 = self::Extension|[]<core::int*, core::int*>(#t63, #t64).{core::num::+}(2) in let final void #t66 = self::Extension|[]=<core::int*, core::int*>(#t63, #t64, #t65) in #t65);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t67 = map2 in let final core::int* #t68 = 0 in let final core::int* #t69 = self::Extension|[]<core::int*, core::int*>(#t67, #t68).{core::num::+}(2) in let final void #t70 = self::Extension|[]=<core::int*, core::int*>(#t67, #t68, #t69) in #t69);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t71 = map2 in let final core::int* #t72 = 0 in let final core::int* #t73 = self::Extension|[]<core::int*, core::int*>(#t71, #t72) in let final void #t74 = self::Extension|[]=<core::int*, core::int*>(#t71, #t72, #t73.{core::num::+}(1)) in #t73);
   self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t77 = map2 in let final core::int* #t78 = 0 in let final core::int* #t79 = self::Extension|[]<core::int*, core::int*>(#t77, #t78).{core::num::-}(1) in let final void #t80 = self::Extension|[]=<core::int*, core::int*>(#t77, #t78, #t79) in #t79);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t75 = map2 in let final core::int* #t76 = 0 in let final core::int* #t77 = self::Extension|[]<core::int*, core::int*>(#t75, #t76).{core::num::-}(1) in let final void #t78 = self::Extension|[]=<core::int*, core::int*>(#t75, #t76, #t77) in #t77);
   self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method explicitInferredTypeArguments() → dynamic {
@@ -97,23 +97,23 @@
   self::expect(null, self::Extension|[]<core::int*, core::String*>(map1, 1));
   self::Extension|[]=<core::int*, core::String*>(map1, 1, "1");
   self::expect("1", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t81 = map1 in let final core::int* #t82 = 1 in let final core::String* #t83 = "2" in let final void #t84 = self::Extension|[]=<core::int*, core::String*>(#t81, #t82, #t83) in #t83);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t79 = map1 in let final core::String* #t80 = "2" in let final void #t81 = self::Extension|[]=<core::int*, core::String*>(#t79, 1, #t80) in #t80);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t85 = map1 in let final core::int* #t86 = 1 in self::Extension|[]<core::int*, core::String*>(#t85, #t86).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t85, #t86, "3") : null;
+  let final self::MapLike<core::int*, core::String*>* #t82 = map1 in let final core::int* #t83 = 1 in self::Extension|[]<core::int*, core::String*>(#t82, #t83).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t82, #t83, "3") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t87 = map1 in let final core::int* #t88 = 1 in let final core::String* #t89 = self::Extension|[]<core::int*, core::String*>(#t87, #t88) in #t89.{core::String::==}(null) ?{core::String*} let final core::String* #t90 = "4" in let final void #t91 = self::Extension|[]=<core::int*, core::String*>(#t87, #t88, #t90) in #t90 : #t89);
+  self::expect("2", let final self::MapLike<core::int*, core::String*>* #t84 = map1 in let final core::int* #t85 = 1 in let final core::String* #t86 = self::Extension|[]<core::int*, core::String*>(#t84, #t85) in #t86.{core::String::==}(null) ?{core::String*} let final core::String* #t87 = "4" in let final void #t88 = self::Extension|[]=<core::int*, core::String*>(#t84, #t85, #t87) in #t87 : #t86);
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 1));
-  let final self::MapLike<core::int*, core::String*>* #t92 = map1 in let final core::int* #t93 = 2 in self::Extension|[]<core::int*, core::String*>(#t92, #t93).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t92, #t93, "2") : null;
+  let final self::MapLike<core::int*, core::String*>* #t89 = map1 in let final core::int* #t90 = 2 in self::Extension|[]<core::int*, core::String*>(#t89, #t90).{core::String::==}(null) ?{core::String*} self::Extension|[]=<core::int*, core::String*>(#t89, #t90, "2") : null;
   self::expect("2", self::Extension|[]<core::int*, core::String*>(map1, 2));
-  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t94 = map1 in let final core::int* #t95 = 3 in let final core::String* #t96 = self::Extension|[]<core::int*, core::String*>(#t94, #t95) in #t96.{core::String::==}(null) ?{core::String*} let final core::String* #t97 = "3" in let final void #t98 = self::Extension|[]=<core::int*, core::String*>(#t94, #t95, #t97) in #t97 : #t96);
+  self::expect("3", let final self::MapLike<core::int*, core::String*>* #t91 = map1 in let final core::int* #t92 = 3 in let final core::String* #t93 = self::Extension|[]<core::int*, core::String*>(#t91, #t92) in #t93.{core::String::==}(null) ?{core::String*} let final core::String* #t94 = "3" in let final void #t95 = self::Extension|[]=<core::int*, core::String*>(#t91, #t92, #t94) in #t94 : #t93);
   self::expect("3", self::Extension|[]<core::int*, core::String*>(map1, 3));
   self::MapLike<core::int*, core::int*>* map2 = new self::MapLike::•<core::int*, core::int*>();
-  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = 1 in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
-  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108).{core::num::+}(2) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109) in #t109);
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113.{core::num::+}(1)) in #t113);
+  self::expect(1, let final self::MapLike<core::int*, core::int*>* #t96 = map2 in let final core::int* #t97 = 1 in let final void #t98 = self::Extension|[]=<core::int*, core::int*>(#t96, 0, #t97) in #t97);
+  self::expect(3, let final self::MapLike<core::int*, core::int*>* #t99 = map2 in let final core::int* #t100 = 0 in let final core::int* #t101 = self::Extension|[]<core::int*, core::int*>(#t99, #t100).{core::num::+}(2) in let final void #t102 = self::Extension|[]=<core::int*, core::int*>(#t99, #t100, #t101) in #t101);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t103 = map2 in let final core::int* #t104 = 0 in let final core::int* #t105 = self::Extension|[]<core::int*, core::int*>(#t103, #t104).{core::num::+}(2) in let final void #t106 = self::Extension|[]=<core::int*, core::int*>(#t103, #t104, #t105) in #t105);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t107 = map2 in let final core::int* #t108 = 0 in let final core::int* #t109 = self::Extension|[]<core::int*, core::int*>(#t107, #t108) in let final void #t110 = self::Extension|[]=<core::int*, core::int*>(#t107, #t108, #t109.{core::num::+}(1)) in #t109);
   self::expect(6, self::Extension|[]<core::int*, core::int*>(map2, 0));
-  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t115 = map2 in let final core::int* #t116 = 0 in let final core::int* #t117 = self::Extension|[]<core::int*, core::int*>(#t115, #t116).{core::num::-}(1) in let final void #t118 = self::Extension|[]=<core::int*, core::int*>(#t115, #t116, #t117) in #t117);
+  self::expect(5, let final self::MapLike<core::int*, core::int*>* #t111 = map2 in let final core::int* #t112 = 0 in let final core::int* #t113 = self::Extension|[]<core::int*, core::int*>(#t111, #t112).{core::num::-}(1) in let final void #t114 = self::Extension|[]=<core::int*, core::int*>(#t111, #t112, #t113) in #t113);
   self::expect(5, self::Extension|[]<core::int*, core::int*>(map2, 0));
 }
 static method expect(dynamic expected, dynamic actual) → dynamic {
@@ -150,7 +150,6 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:46:18 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:48:20 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:48:20 -> IntConstant(0)
-Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:60:44 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:60:49 -> StringConstant("2")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:60:49 -> StringConstant("2")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:62:32 -> IntConstant(1)
@@ -165,7 +164,6 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:44 -> IntConstant(3)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:51 -> StringConstant("3")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:51 -> StringConstant("3")
-Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:72:39 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:72:44 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:72:44 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:73:39 -> IntConstant(0)
@@ -176,7 +174,6 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:75:39 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:77:41 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:77:41 -> IntConstant(0)
-Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:89:31 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:89:36 -> StringConstant("2")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:89:36 -> StringConstant("2")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:91:19 -> IntConstant(1)
@@ -191,7 +188,6 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:31 -> IntConstant(3)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:38 -> StringConstant("3")
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:38 -> StringConstant("3")
-Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:101:29 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:101:34 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:101:34 -> IntConstant(1)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:102:29 -> IntConstant(0)
@@ -202,4 +198,4 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:104:29 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:106:31 -> IntConstant(0)
 Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:106:31 -> IntConstant(0)
-Extra constant evaluation: evaluated: 579, effectively constant: 78
+Extra constant evaluation: evaluated: 571, effectively constant: 74
diff --git a/pkg/front_end/testcases/extensions/index.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/index.dart.textual_outline.expect
index ac9d9f4..78005ed 100644
--- a/pkg/front_end/testcases/extensions/index.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.textual_outline.expect
@@ -3,8 +3,12 @@
   V get(Object key) => _map[key];
   V put(K key, V value) => _map[key] = value;
 }
-extension Extension<K, V> (){}
-on MapLike<K, V> (){}
+
+extension Extension<K, V> on MapLike<K, V> {
+  V operator [](Object key) => get(key);
+  void operator []=(K key, V value) => put(key, value);
+}
+
 main() {}
 implicit() {}
 explicitWithTypeArguments() {}
diff --git a/pkg/front_end/testcases/extensions/index.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/index.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d0d5ec9
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/index.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class MapLike<K, V> {
+  V get(Object key) => _map[key];
+  V put(K key, V value) => _map[key] = value;
+  final Map<K, V> _map = {};
+}
+
+expect(expected, actual) {}
+explicitInferredTypeArguments() {}
+explicitWithTypeArguments() {}
+
+extension Extension<K, V> on MapLike<K, V> {
+  V operator [](Object key) => get(key);
+  void operator []=(K key, V value) => put(key, value);
+}
+
+implicit() {}
+main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline.expect
index 296e8e0..a9ea239 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline.expect
@@ -3,15 +3,27 @@
   Class1(this.field);
   String toString() => 'Class1($field)';
 }
+
 class Class2 {
   int field;
   Class2(this.field);
   String toString() => 'Class2($field)';
 }
-extension Extension1 ;
-on Class1 (){}
-extension Extension2 ;
-on Class2 (){}
+
+extension Extension1 on Class1 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  set property(int value) {}
+}
+
+extension Extension2 on Class2 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  set property(int value) {}
+}
+
 main() {}
 testExtension1() {}
 testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e584bee
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,31 @@
+class Class1 {
+  Class1(this.field);
+  String toString() => 'Class1($field)';
+  int field;
+}
+
+class Class2 {
+  Class2(this.field);
+  String toString() => 'Class2($field)';
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension Extension1 on Class1 {
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  int method() {}
+  set property(int value) {}
+}
+
+extension Extension2 on Class2 {
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  int method() {}
+  set property(int value) {}
+}
+
+main() {}
+testExtension1() {}
+testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline.expect
index 9e94fcd..8e3e499 100644
--- a/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline.expect
@@ -1,4 +1,10 @@
 class Class1 {}
-extension Extension1 ;
-on Class1 (){}
+
+extension Extension1 on Class1 {
+  static staticMethod() {}
+  static get staticProperty {}
+  static set staticProperty(int value) {}
+  static var staticField = 42;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d5db1d4
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/instance_access_of_static.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+class Class1 {}
+
+extension Extension1 on Class1 {
+  static get staticProperty {}
+  static set staticProperty(int value) {}
+  static staticMethod() {}
+  static var staticField = 42;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline.expect
index e84610c..1fd012e 100644
--- a/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline.expect
@@ -1,7 +1,17 @@
 class A1 {}
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  A1 method1() {}
+  A1 method2<T>(T o) {}
+  A1 method3<T>([T o]) {}
+  A1 method4<T>({T o}) {}
+}
+
 class B1<T> {}
-extension B2<T> (){}
-on B1<T> (){}
+
+extension B2<T> on B1<T> {
+  B1<T> method1() {}
+  B1<T> method2<S>(S o) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..bfacdaa
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/instance_members.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class A1 {}
+
+class B1<T> {}
+
+extension A2 on A1 {
+  A1 method1() {}
+  A1 method2<T>(T o) {}
+  A1 method3<T>([T o]) {}
+  A1 method4<T>({T o}) {}
+}
+
+extension B2<T> on B1<T> {
+  B1<T> method1() {}
+  B1<T> method2<S>(S o) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline.expect
index 296e8e0..5d3c178 100644
--- a/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline.expect
@@ -3,15 +3,23 @@
   Class1(this.field);
   String toString() => 'Class1($field)';
 }
+
 class Class2 {
   int field;
   Class2(this.field);
   String toString() => 'Class2($field)';
 }
-extension Extension1 ;
-on Class1 (){}
-extension Extension2 ;
-on Class2 (){}
+
+extension Extension1 on Class1 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+}
+
+extension Extension2 on Class2 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+}
+
 main() {}
 testExtension1() {}
 testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ab11e38
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.textual_outline_modelled.expect
@@ -0,0 +1,27 @@
+class Class1 {
+  Class1(this.field);
+  String toString() => 'Class1($field)';
+  int field;
+}
+
+class Class2 {
+  Class2(this.field);
+  String toString() => 'Class2($field)';
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension Extension1 on Class1 {
+  int genericMethod<T extends num>(T t) {}
+  int method() {}
+}
+
+extension Extension2 on Class2 {
+  int genericMethod<T extends num>(T t) {}
+  int method() {}
+}
+
+main() {}
+testExtension1() {}
+testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline.expect
index 3731a57..ad984f3 100644
--- a/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline.expect
@@ -1,9 +1,16 @@
 class Class {
   int field;
 }
-extension on ;
-Class (){}
-extension on ;
-Class (){}
+
+extension on Class {
+  int get property1 => property2;
+  void set property1(int value) => field = value;
+}
+
+extension on Class {
+  int get property2 => field;
+  void set property2(int value) => property1 = value;
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b4a0cb3
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class Class {
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension on Class {
+  int get property1 => property2;
+  void set property1(int value) => field = value;
+}
+
+extension on Class {
+  int get property2 => field;
+  void set property2(int value) => property1 = value;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline.expect
index a8a7820..fda67e5 100644
--- a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline.expect
@@ -1,7 +1,13 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  method(a) {}
+}
+
 class GenericClass<T> {}
-extension GenericExtension<T> (){}
-on GenericClass<T> (){}
+
+extension GenericExtension<T> on GenericClass<T> {
+  method() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..cccd074
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+class Class {}
+
+class GenericClass<T> {}
+
+extension Extension on Class {
+  method(a) {}
+}
+
+extension GenericExtension<T> on GenericClass<T> {
+  method() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline.expect
index ce040db..2654863 100644
--- a/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline.expect
@@ -1,4 +1,11 @@
-extension Extension ;
-on String (){}
+extension Extension on String {
+  static method() {}
+  static get getter => null;
+  static set setter(_) {}
+  static get property => null;
+  static set property(_) {}
+  static var field;
+}
+
 main() {}
 errors() {}
diff --git a/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0abe64c
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/invalid_explicit_static_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+errors() {}
+
+extension Extension on String {
+  static get getter => null;
+  static get property => null;
+  static method() {}
+  static set property(_) {}
+  static set setter(_) {}
+  static var field;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38600.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38600.dart.textual_outline.expect
index fd2b304..43bf0c2 100644
--- a/pkg/front_end/testcases/extensions/issue38600.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38600.dart.textual_outline.expect
@@ -1,4 +1,5 @@
 class Class<T> {}
-extension try<T> (){}
+extension on{}
+try<T> (){}
 on Class<T> (){}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38712.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38712.dart.textual_outline.expect
index 80db8ca..ec4321b 100644
--- a/pkg/front_end/testcases/extensions/issue38712.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38712.dart.textual_outline.expect
@@ -1,2 +1,2 @@
-extension C (){}
+extension C on{}
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline.expect
index 3843d11..07df337 100644
--- a/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline.expect
@@ -1,3 +1,8 @@
-extension C ;
-on int (){}
+extension C on int {
+  static int property2;
+  static void set property2(int x) {}
+  static void set property3(int x) {}
+  int get property3 => 1;
+}
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8b89684
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue38713.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+extension C on int {
+  int get property3 => 1;
+  static int property2;
+  static void set property2(int x) {}
+  static void set property3(int x) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38745.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38745.dart.textual_outline.expect
index 61466b7..d0a4d03 100644
--- a/pkg/front_end/testcases/extensions/issue38745.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38745.dart.textual_outline.expect
@@ -1,5 +1,11 @@
 class C<T> {}
-extension ext<T> (){}
-on C<T> (){}
+extension ext<T> on C<T> {
+  int field;
+  final int property = 42;
+  void set property(int value) {}
+  final int property2 = 42;
+  static void set property2(int value) {}
+  method() {}
+}
 main() {}
 errors() {}
diff --git a/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline.expect
index b013cb4..c52f04b 100644
--- a/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline.expect
@@ -1,4 +1,7 @@
 final list = ["a", "b", "c"].myMap((it) => it);
-extension A<T> (){}
-on List<T> (){}
+
+extension A<T> on List<T> {
+  List<R> myMap<R>(R Function(T) block) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fd90a7a
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue38755.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+extension A<T> on List<T> {
+  List<R> myMap<R>(R Function(T) block) {}
+}
+
+final list = ["a", "b", "c"].myMap((it) => it);
+main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline.expect
index cc9ad4c..349b61f 100644
--- a/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline.expect
@@ -1,4 +1,10 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  void method1({bool b = false, String s = ', '}) => null;
+  void method2([bool b = false, String s = ', ']) => null;
+  void method3(int i, {bool b = false, String s = ', '}) {}
+  void method4(int i, [bool b = false, String s = ', ']) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..349b61f
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue38915.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+class Class {}
+
+extension Extension on Class {
+  void method1({bool b = false, String s = ', '}) => null;
+  void method2([bool b = false, String s = ', ']) => null;
+  void method3(int i, {bool b = false, String s = ', '}) {}
+  void method4(int i, [bool b = false, String s = ', ']) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/issue39527.dart.strong.expect b/pkg/front_end/testcases/extensions/issue39527.dart.strong.expect
index 8131831..16896b4 100644
--- a/pkg/front_end/testcases/extensions/issue39527.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/issue39527.dart.strong.expect
@@ -25,15 +25,15 @@
 }
 static method Extension1|[](lowered final self::C* #this, core::int* index) → self::C*
   return let final self::C* #t1 = #this in block {
-    let final self::C* #t2 = #t1 in #t2.{self::C::value} = #t2.{self::C::value}.{core::num::+}(index.{core::num::+}(1));
+    #t1.{self::C::value} = #t1.{self::C::value}.{core::num::+}(index.{core::num::+}(1));
   } =>#t1;
 static method Extension1|[]=(lowered final self::C* #this, core::int* index, self::C* other) → void
-  return let final self::C* #t3 = #this in #t3.{self::C::value} = #t3.{self::C::value}.{core::num::+}(other.{self::C::value}.{core::num::+}(index).{core::num::+}(1));
+  return #this.{self::C::value} = #this.{self::C::value}.{core::num::+}(other.{self::C::value}.{core::num::+}(index).{core::num::+}(1));
 static method Extension1|-(lowered final self::C* #this, core::int* val) → self::C*
   return #this;
 static method main() → dynamic {
   self::C* c = new self::C::•();
-  let final self::C* #t4 = c in let final core::int* #t5 = 42 in let final self::C* #t6 = self::Extension1|-(self::Extension1|[](#t4, #t5), 1) in let final void #t7 = self::Extension1|[]=(#t4, #t5, #t6) in #t6;
-  let final self::C* #t8 = c in let final core::int* #t9 = 42 in self::Extension1|[]=(#t8, #t9, self::Extension1|-(self::Extension1|[](#t8, #t9), 1));
+  let final self::C* #t2 = c in let final core::int* #t3 = 42 in let final self::C* #t4 = self::Extension1|-(self::Extension1|[](#t2, #t3), 1) in let final void #t5 = self::Extension1|[]=(#t2, #t3, #t4) in #t4;
+  let final self::C* #t6 = c in let final core::int* #t7 = 42 in self::Extension1|[]=(#t6, #t7, self::Extension1|-(self::Extension1|[](#t6, #t7), 1));
   self::Extension1|[]=(c, 42, self::Extension1|-(self::Extension1|[](c, 42), 1));
 }
diff --git a/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect
index 85bc50b..59b0317 100644
--- a/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect
@@ -25,16 +25,16 @@
 }
 static method Extension1|[](lowered final self::C* #this, core::int* index) → self::C*
   return let final self::C* #t1 = #this in block {
-    let final self::C* #t2 = #t1 in #t2.{self::C::value} = #t2.{self::C::value}.{core::num::+}(index.{core::num::+}(1));
+    #t1.{self::C::value} = #t1.{self::C::value}.{core::num::+}(index.{core::num::+}(1));
   } =>#t1;
 static method Extension1|[]=(lowered final self::C* #this, core::int* index, self::C* other) → void
-  return let final self::C* #t3 = #this in #t3.{self::C::value} = #t3.{self::C::value}.{core::num::+}(other.{self::C::value}.{core::num::+}(index).{core::num::+}(1));
+  return #this.{self::C::value} = #this.{self::C::value}.{core::num::+}(other.{self::C::value}.{core::num::+}(index).{core::num::+}(1));
 static method Extension1|-(lowered final self::C* #this, core::int* val) → self::C*
   return #this;
 static method main() → dynamic {
   self::C* c = new self::C::•();
-  let final self::C* #t4 = c in let final core::int* #t5 = 42 in let final self::C* #t6 = self::Extension1|-(self::Extension1|[](#t4, #t5), 1) in let final void #t7 = self::Extension1|[]=(#t4, #t5, #t6) in #t6;
-  let final self::C* #t8 = c in let final core::int* #t9 = 42 in self::Extension1|[]=(#t8, #t9, self::Extension1|-(self::Extension1|[](#t8, #t9), 1));
+  let final self::C* #t2 = c in let final core::int* #t3 = 42 in let final self::C* #t4 = self::Extension1|-(self::Extension1|[](#t2, #t3), 1) in let final void #t5 = self::Extension1|[]=(#t2, #t3, #t4) in #t4;
+  let final self::C* #t6 = c in let final core::int* #t7 = 42 in self::Extension1|[]=(#t6, #t7, self::Extension1|-(self::Extension1|[](#t6, #t7), 1));
   self::Extension1|[]=(c, 42, self::Extension1|-(self::Extension1|[](c, 42), 1));
 }
 
@@ -44,4 +44,4 @@
 Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:19:19 -> IntConstant(42)
 Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:22:17 -> IntConstant(42)
 Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:22:17 -> IntConstant(42)
-Extra constant evaluation: evaluated: 56, effectively constant: 4
+Extra constant evaluation: evaluated: 52, effectively constant: 4
diff --git a/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline.expect
index 7ec2575..586004b 100644
--- a/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline.expect
@@ -1,6 +1,12 @@
 class C {
   int value = 0;
 }
-extension Extension1 ;
-on C (){}
+
+extension Extension1 on C {
+  C operator [](int index) => this..value += index + 1;
+  void operator []=(int index, C other) =>
+      this.value += other.value + index + 1;
+  C operator -(int val) => this;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..56b4c36
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue39527.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class C {
+  int value = 0;
+}
+
+extension Extension1 on C {
+  C operator -(int val) => this;
+  C operator [](int index) => this..value += index + 1;
+  void operator []=(int index, C other) =>
+      this.value += other.value + index + 1;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline.expect
index 9e92bb8..2b64dea 100644
--- a/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline.expect
@@ -1,4 +1,7 @@
 class C {}
-extension E ;
-on C (){}
+
+extension E on C {
+  void f(String b) {}
+}
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2b64dea
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue39889.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+class C {}
+
+extension E on C {
+  void f(String b) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline.expect
index a0ad8ac..ee456e8 100644
--- a/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline.expect
@@ -1,4 +1,7 @@
 import 'dart:async';
+
 void main() {}
-extension Extension<T> (){}
-on Stream<T> (){}
+
+extension Extension<T> on Stream<T> {
+  StreamSubscription<T> call(Function onData) {}
+}
diff --git a/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a5b08bb
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40596.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+import 'dart:async';
+
+extension Extension<T> on Stream<T> {
+  StreamSubscription<T> call(Function onData) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline.expect
index bcdffa4..86e8aaa 100644
--- a/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline.expect
@@ -1,5 +1,7 @@
-extension SafeAccess<T> (){}
-on Iterable<T> (){}
+extension SafeAccess<T> on Iterable<T> {
+  T get safeFirst {}
+}
+
 main() {}
 void test() {}
 void errors() {}
diff --git a/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b4b03d34
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40713.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+extension SafeAccess<T> on Iterable<T> {
+  T get safeFirst {}
+}
+
+main() {}
+void errors() {}
+void test() {}
diff --git a/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline.expect
index e32df9a..e806109 100644
--- a/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline.expect
@@ -1,5 +1,9 @@
 class A {}
+
 class B {}
-extension on ;
-A (){}
+
+extension on A {
+  void foo(A a, B b) {}
+}
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e806109
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue40816.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class A {}
+
+class B {}
+
+extension on A {
+  void foo(A a, B b) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline.expect
index 4eec6f8..c3323e8 100644
--- a/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline.expect
@@ -5,7 +5,10 @@
   int get id => value;
   void set id(int v) {}
 }
-extension Ext ;
-on C (){}
+
+extension Ext on C {
+  int get id => this.value + 1;
+}
+
 test() {}
 main() {}
diff --git a/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6c5f1e6
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/issue43218.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class C {
+  C() : value = 0 {}
+  init() {}
+  int get id => value;
+  int value;
+  void set id(int v) {}
+}
+
+extension Ext on C {
+  int get id => this.value + 1;
+}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline.expect
index 2f9718a..5f989b2 100644
--- a/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline.expect
@@ -1,6 +1,9 @@
-extension Test<T> (){}
-on T (){}
+extension Test<T> on T {
+  T Function(T) get test => (a) => this;
+}
+
 class Foo<S extends num> {
   void test1(S x) {}
 }
+
 void main() {}
diff --git a/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9aaf1c7
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/language_issue1182.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Foo<S extends num> {
+  void test1(S x) {}
+}
+
+extension Test<T> on T {
+  T Function(T) get test => (a) => this;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline.expect
index d11cf6d..83182ff 100644
--- a/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline.expect
@@ -1,6 +1,9 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  void set setter(int value) {}
+}
+
 var c = new Class();
 var missingGetter = c.setter += 42;
 main() {}
diff --git a/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..94e9a17
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/missing_toplevel.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class {}
+
+extension Extension on Class {
+  void set setter(int value) {}
+}
+
+main() {}
+var c = new Class();
+var missingGetter = c.setter += 42;
diff --git a/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline.expect
index c1528bd..8970b3e 100644
--- a/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline.expect
@@ -1,4 +1,8 @@
 class A<T> {}
-extension Extension<T> (){}
-on A<A<T>> (){}
+
+extension Extension<T> on A<A<T>> {
+  method1() {}
+  method2<A>(A a) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8970b3e
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/nested_on_types.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+class A<T> {}
+
+extension Extension<T> on A<A<T>> {
+  method1() {}
+  method2<A>(A a) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline.expect
index 54442ce..378b04c 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline.expect
@@ -1,7 +1,13 @@
 class Class {
   int field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  int get property => field;
+  void set property(int value) {}
+  int method() => field;
+  testImplicitThis() {}
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..dc73414
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class Class {
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension Extension on Class {
+  int get property => field;
+  int method() => field;
+  testImplicitThis() {}
+  void set property(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline.expect
index 72efc6a..7b1f078 100644
--- a/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline.expect
@@ -1,7 +1,14 @@
-extension<R, T> on ;
-R Function(T) {}
+extension<R, T> on R Function(T) {
+  Type get returnType => R;
+  Type get parameterType => T;
+}
+
 class Class<T extends Class<T>> {}
+
 class Subclass extends Class<Subclass> {}
-extension<T extends Class<T>> on ;
-dynamic Function<S extends T>(T, S) {}
+
+extension<T extends Class<T>> on dynamic Function<S extends T>(T, S) {
+  Type get parameterType => T;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d84ff38
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_function_type.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class Class<T extends Class<T>> {}
+
+class Subclass extends Class<Subclass> {}
+
+extension<R, T> on R Function(T) {
+  Type get parameterType => T;
+  Type get returnType => R;
+}
+
+extension<T extends Class<T>> on dynamic Function<S extends T>(T, S) {
+  Type get parameterType => T;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline.expect
index 9edafca..9aa7eba 100644
--- a/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline.expect
@@ -1,7 +1,13 @@
-extension BestCom<T extends num> (){}
-on Iterable<T> (){}
-extension BestList<T> (){}
-on List<T> (){}
-extension BestSpec ;
-on List<num> (){}
+extension BestCom<T extends num> on Iterable<T> {
+  T best() => null;
+}
+
+extension BestList<T> on List<T> {
+  T best() => null;
+}
+
+extension BestSpec on List<num> {
+  num best() => null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9aa7eba
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_type_inference.dart.textual_outline_modelled.expect
@@ -0,0 +1,13 @@
+extension BestCom<T extends num> on Iterable<T> {
+  T best() => null;
+}
+
+extension BestList<T> on List<T> {
+  T best() => null;
+}
+
+extension BestSpec on List<num> {
+  num best() => null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline.expect
index a75ec57..d757af3 100644
--- a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline.expect
@@ -1,8 +1,16 @@
 class Struct {}
+
 class StructA extends Struct {}
+
 class StructB extends Struct {}
+
 class NonStruct {}
-extension Extension<T extends Struct> (){}
-on T (){}
+
+extension Extension<T extends Struct> on T {
+  T method() => this;
+  T get property => this;
+  void set property(T value) {}
+}
+
 main() {}
 testNonStruct() {}
diff --git a/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..16a0644
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/on_type_variable_inference.dart.textual_outline_modelled.expect
@@ -0,0 +1,16 @@
+class NonStruct {}
+
+class Struct {}
+
+class StructA extends Struct {}
+
+class StructB extends Struct {}
+
+extension Extension<T extends Struct> on T {
+  T get property => this;
+  T method() => this;
+  void set property(T value) {}
+}
+
+main() {}
+testNonStruct() {}
diff --git a/pkg/front_end/testcases/extensions/operators.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/operators.dart.textual_outline.expect
index 3ed1892..908102a 100644
--- a/pkg/front_end/testcases/extensions/operators.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/operators.dart.textual_outline.expect
@@ -9,8 +9,13 @@
   bool operator ==(Object other) {}
   String toString() => 'Complex($real,$imaginary)';
 }
-extension Operators ;
-on Complex (){}
+
+extension Operators on Complex {
+  Complex operator +(Complex other) => add(other);
+  Complex operator -(Complex other) => sub(other);
+  Complex operator -() => negate();
+}
+
 main() {}
 implicit() {}
 explicit() {}
diff --git a/pkg/front_end/testcases/extensions/operators.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/operators.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d77488d
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/operators.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class Complex {
+  Complex add(Complex other) {}
+  Complex negate() {}
+  Complex sub(Complex other) {}
+  String toString() => 'Complex($real,$imaginary)';
+  bool operator ==(Object other) {}
+  const Complex(this.real, this.imaginary);
+  final double imaginary;
+  final double real;
+  int get hashCode => real.hashCode * 13 + imaginary.hashCode * 19;
+}
+
+expect(expected, actual) {}
+explicit() {}
+
+extension Operators on Complex {
+  Complex operator +(Complex other) => add(other);
+  Complex operator -() => negate();
+  Complex operator -(Complex other) => sub(other);
+}
+
+implicit() {}
+main() {}
+void errors(Complex c) {}
diff --git a/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline.expect
index bd1c7e9..85d642c 100644
--- a/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline.expect
@@ -6,6 +6,16 @@
   static int getStaticField() => _staticField;
   static void setStaticField(int value) {}
 }
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  int get instanceProperty => getInstanceField();
+  void set instanceProperty(int value) {}
+  int operator +(int value) {}
+  int operator -(int value) {}
+  int operator -() {}
+  static int staticField = A1.getStaticField();
+  static int get staticProperty => A1.getStaticField();
+  static void set staticProperty(int value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1e10a1c
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/other_kinds.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+class A1 {
+  int _instanceField;
+  int getInstanceField() => _instanceField;
+  static int _staticField = 0;
+  static int getStaticField() => _staticField;
+  static void setStaticField(int value) {}
+  void setInstanceField(int value) {}
+}
+
+extension A2 on A1 {
+  int get instanceProperty => getInstanceField();
+  int operator +(int value) {}
+  int operator -() {}
+  int operator -(int value) {}
+  static int get staticProperty => A1.getStaticField();
+  static int staticField = A1.getStaticField();
+  static void set staticProperty(int value) {}
+  void set instanceProperty(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/static_access.dart.textual_outline.expect
index cc9ad4c..af89663 100644
--- a/pkg/front_end/testcases/extensions/static_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/static_access.dart.textual_outline.expect
@@ -1,4 +1,14 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  static method() {}
+  static genericMethod<T>(T t) {}
+  static get property => 42;
+  static set property(value) {}
+  static var field;
+  instanceMethod() {}
+  get instanceProperty => 42;
+  set instanceProperty(value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/static_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/static_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d7a88d1
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/static_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class Class {}
+
+extension Extension on Class {
+  get instanceProperty => 42;
+  instanceMethod() {}
+  set instanceProperty(value) {}
+  static genericMethod<T>(T t) {}
+  static get property => 42;
+  static method() {}
+  static set property(value) {}
+  static var field;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline.expect
index cc9ad4c..38dbcbf 100644
--- a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline.expect
@@ -1,4 +1,9 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  instanceMethod() {}
+  get instanceProperty => 42;
+  set instanceProperty(value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..114f677
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/static_access_of_instance.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class {}
+
+extension Extension on Class {
+  get instanceProperty => 42;
+  instanceMethod() {}
+  set instanceProperty(value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline.expect
index 9c93cbd..45dbc23 100644
--- a/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline.expect
@@ -1,5 +1,11 @@
 class Class {}
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  T id<T>(T t) => t;
+  T Function<T>(T) get getter => id;
+  method() {}
+  errors() {}
+}
+
 main() {}
 errors() {}
diff --git a/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5ce0c980
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/tear_offs.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+class Class {}
+
+errors() {}
+
+extension Extension on Class {
+  T Function<T>(T) get getter => id;
+  T id<T>(T t) => t;
+  errors() {}
+  method() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline.expect
index a9b3ce3..59d5ad1 100644
--- a/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline.expect
@@ -1,10 +1,16 @@
 // @dart = 2.8
-extension Extension<T> (){}
-on T (){}
-extension BoundExtension<T extends Class> (){}
-on T (){}
+extension Extension<T> on T {
+  T method1() => this;
+}
+
+extension BoundExtension<T extends Class> on T {
+  T method2() => this;
+}
+
 class Class {}
+
 class SubClass extends Class {}
+
 Class test1<T>(T t1) {}
 test2<T extends Class>(T t2) {}
 test3<T>(T t3) {}
diff --git a/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a08e473
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/type_variable_bound.dart.textual_outline_modelled.expect
@@ -0,0 +1,18 @@
+// @dart = 2.8
+Class test1<T>(T t1) {}
+
+class Class {}
+
+class SubClass extends Class {}
+
+extension BoundExtension<T extends Class> on T {
+  T method2() => this;
+}
+
+extension Extension<T> on T {
+  T method1() => this;
+}
+
+main() {}
+test2<T extends Class>(T t2) {}
+test3<T>(T t3) {}
diff --git a/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline.expect
index 60b1f69..4f3bfdf 100644
--- a/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline.expect
@@ -1,8 +1,14 @@
 class A1<T> {}
-extension A2<T> (){}
-on A1<T> (){}
-extension A3<T extends A1<T>> (){}
-on A1<T> (){}
-extension A4<T> (){}
-on A1<T> (){}
+
+extension A2<T> on A1<T> {
+  A1<T> method1<S extends T>() {}
+  A1<T> method2<S extends A1<T>>(S o) {}
+}
+
+extension A3<T extends A1<T>> on A1<T> {}
+
+extension A4<T> on A1<T> {
+  method<T>() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4f3bfdf
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/type_variables.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class A1<T> {}
+
+extension A2<T> on A1<T> {
+  A1<T> method1<S extends T>() {}
+  A1<T> method2<S extends A1<T>>(S o) {}
+}
+
+extension A3<T extends A1<T>> on A1<T> {}
+
+extension A4<T> on A1<T> {
+  method<T>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline.expect
index 8641f18..792016b 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline.expect
@@ -3,15 +3,27 @@
   Class1(this.field);
   String toString() => 'Class1($field)';
 }
+
 class Class2 {
   int field;
   Class2(this.field);
   String toString() => 'Class2($field)';
 }
-extension on ;
-Class1 (){}
-extension on ;
-Class2 (){}
+
+extension on Class1 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  set property(int value) {}
+}
+
+extension on Class2 {
+  int method() {}
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  set property(int value) {}
+}
+
 main() {}
 testExtension1() {}
 testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..66a7a5b
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.textual_outline_modelled.expect
@@ -0,0 +1,31 @@
+class Class1 {
+  Class1(this.field);
+  String toString() => 'Class1($field)';
+  int field;
+}
+
+class Class2 {
+  Class2(this.field);
+  String toString() => 'Class2($field)';
+  int field;
+}
+
+expect(expected, actual) {}
+
+extension on Class1 {
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  int method() {}
+  set property(int value) {}
+}
+
+extension on Class2 {
+  int genericMethod<T extends num>(T t) {}
+  int get property {}
+  int method() {}
+  set property(int value) {}
+}
+
+main() {}
+testExtension1() {}
+testExtension2() {}
diff --git a/pkg/front_end/testcases/extensions/use_this.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/use_this.dart.textual_outline.expect
index e84610c..f12590a 100644
--- a/pkg/front_end/testcases/extensions/use_this.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/extensions/use_this.dart.textual_outline.expect
@@ -1,7 +1,15 @@
 class A1 {}
-extension A2 ;
-on A1 (){}
+
+extension A2 on A1 {
+  A1 method1() {}
+  A1 method2<T>(T o) {}
+}
+
 class B1<T> {}
-extension B2<T> (){}
-on B1<T> (){}
+
+extension B2<T> on B1<T> {
+  B1<T> method1() {}
+  B1<T> method2<S>(S o) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/extensions/use_this.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/extensions/use_this.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f79fb58
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/use_this.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class A1 {}
+
+class B1<T> {}
+
+extension A2 on A1 {
+  A1 method1() {}
+  A1 method2<T>(T o) {}
+}
+
+extension B2<T> on B1<T> {
+  B1<T> method1() {}
+  B1<T> method2<S>(S o) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect
index 47e2d86..4c98331 100644
--- a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect
@@ -19,6 +19,7 @@
   static num get property9 => 0;
   static void set property9(String value) {}
 }
+
 abstract class B1 {
   int get property1;
   int get property2;
@@ -28,6 +29,7 @@
   final String property6;
   B1(this.property4, this.property5, this.property6);
 }
+
 abstract class B2 implements B1 {
   void set property1(int i);
   void set property2(String i);
@@ -36,6 +38,7 @@
   void set property5(String i);
   void set property6(int i);
 }
+
 abstract class C1 {
   void set property1(int i);
   void set property2(String i);
@@ -44,6 +47,7 @@
   String property5;
   int property6;
 }
+
 abstract class C2 implements C1 {
   int get property1;
   int get property2;
@@ -52,18 +56,48 @@
   int get property5;
   String get property6;
 }
+
 abstract class D1 {
   int get property1;
   int get property2;
   String get property3;
 }
+
 abstract class D2 {
   void set property1(int i);
   void set property2(String i);
   void set property3(int i);
 }
+
 abstract class D3 implements D1, D2 {}
+
 abstract class D4 implements D3 {}
-extension Extension<T extends num, S extends T> (){}
-on int (){}
+
+extension Extension<T extends num, S extends T> on int {
+  int get property1 => 0;
+  void set property1(int i) {}
+  num get property2a => 0;
+  void set property2a(int i) {}
+  int get property2b => 0;
+  void set property2b(num i) {}
+  String get property3 => '';
+  void set property3(int i) {}
+  S get property4 => 0;
+  void set property4(S i) {}
+  S get property5a => 0;
+  void set property5a(T i) {}
+  T get property5b => 0;
+  void set property5b(S i) {}
+  String get property6 => '';
+  void set property6(S i) {}
+  static int get property7 => 0;
+  static void set property7(int value) {}
+  static int get property8a => 0;
+  static void set property8a(num value) {}
+  static num get property8b => 0;
+  static void set property8b(int value) {}
+  static num get property9 => 0;
+  static void set property9(String value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect
index e2ee020..0d0827c 100644
--- a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect
@@ -73,4 +73,31 @@
 
 abstract class D4 implements D3 {}
 
+extension Extension<T extends num, S extends T> on int {
+  S get property4 => 0;
+  S get property5a => 0;
+  String get property3 => '';
+  String get property6 => '';
+  T get property5b => 0;
+  int get property1 => 0;
+  int get property2b => 0;
+  num get property2a => 0;
+  static int get property7 => 0;
+  static int get property8a => 0;
+  static num get property8b => 0;
+  static num get property9 => 0;
+  static void set property7(int value) {}
+  static void set property8a(num value) {}
+  static void set property8b(int value) {}
+  static void set property9(String value) {}
+  void set property1(int i) {}
+  void set property2a(int i) {}
+  void set property2b(num i) {}
+  void set property3(int i) {}
+  void set property4(S i) {}
+  void set property5a(T i) {}
+  void set property5b(S i) {}
+  void set property6(S i) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/issue40242.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue40242.dart.textual_outline.expect
index c862500..4b76f91 100644
--- a/pkg/front_end/testcases/general/issue40242.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/issue40242.dart.textual_outline.expect
@@ -1,5 +1,8 @@
 class C {}
-extension E ;
-on C (){}
+
+extension E on C {
+  errors() {}
+}
+
 errors() {}
 main() {}
diff --git a/pkg/front_end/testcases/general/issue40242.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue40242.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..91844c5
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue40242.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class C {}
+
+errors() {}
+
+extension E on C {
+  errors() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart b/pkg/front_end/testcases/general/pure_index_expressions.dart
new file mode 100644
index 0000000..975089a
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart
@@ -0,0 +1,215 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.9
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+  Class operator +(Class cls) => cls;
+
+  void indexGetSetForEffect(Map<Class, Class> map) {
+    final Class self = this;
+    map[this] ??= this;
+    map[self] ??= self;
+
+    map[this] = this;
+    map[self] = self;
+
+    map[this];
+    map[self];
+
+    map[this] += this;
+    map[self] += self;
+  }
+
+  void indexGetSetForValue(Map<Class, Class> map) {
+    final Class self = this;
+    var v;
+    v = map[this] ??= this;
+    v = map[self] ??= self;
+
+    v = map[this] = this;
+    v = map[self] = self;
+
+    v = map[this];
+    v = map[self];
+
+    v = map[this] += this;
+    v = map[self] += self;
+  }
+
+  void implicitExtensionGetSetForEffect(int i) {
+    final Class self = this;
+    i[this] ??= this;
+    i[self] ??= self;
+
+    i[this] = this;
+    i[self] = self;
+
+    i[this];
+    i[self];
+
+    i[this] += this;
+    i[self] += self;
+  }
+
+  void implicitExtensionGetSetForValue(int i) {
+    final Class self = this;
+    var v;
+    v = i[this] ??= this;
+    v = i[self] ??= self;
+
+    v = i[this] = this;
+    v = i[self] = self;
+
+    v = i[this];
+    v = i[self];
+
+    v = i[this] += this;
+    v = i[self] += self;
+  }
+
+  void explicitExtensionGetSetForEffect(int i) {
+    final Class self = this;
+    Extension(i)[this] ??= this;
+    Extension(i)[self] ??= self;
+
+    Extension(i)[this] = this;
+    Extension(i)[self] = self;
+
+    Extension(i)[this];
+    Extension(i)[self];
+
+    Extension(i)[this] += this;
+    Extension(i)[self] += self;
+  }
+
+  void explicitExtensionGetSetForValue(int i) {
+    final Class self = this;
+    var v;
+    v = Extension(i)[this] ??= this;
+    v = Extension(i)[self] ??= self;
+
+    v = Extension(i)[this] = this;
+    v = Extension(i)[self] = self;
+
+    v = Extension(i)[this];
+    v = Extension(i)[self];
+
+    v = Extension(i)[this] += this;
+    v = Extension(i)[self] += self;
+  }
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {
+    final Class self = this;
+    super[this] ??= this;
+    super[self] ??= self;
+
+    super[this] = this;
+    super[self] = self;
+
+    super[this];
+    super[self];
+
+    super[this] += this;
+    super[self] += self;
+  }
+
+  void superIndexGetSetForValue() {
+    final Class self = this;
+    var v;
+    v = super[this] ??= this;
+    v = super[self] ??= self;
+
+    v = super[this] = this;
+    v = super[self] = self;
+
+    v = super[this];
+    v = super[self];
+
+    v = super[this] += this;
+    v = super[self] += self;
+  }
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+
+  void implicitExtensionGetSetForEffect() {
+    final Class2 self = this;
+    this[this] ??= this;
+    self[self] ??= self;
+
+    this[this] = this;
+    self[self] = self;
+
+    this[this];
+    self[self];
+
+    this[this] += this;
+    self[self] += self;
+  }
+
+  void implicitExtensionGetSetForValue() {
+    final Class2 self = this;
+    var v;
+    v = this[this] ??= this;
+    v = self[self] ??= self;
+
+    v = this[this] = this;
+    v = self[self] = self;
+
+    v = this[this];
+    v = self[self];
+
+    v = this[this] += this;
+    v = self[self] += self;
+  }
+
+  void explicitExtensionGetSetForEffect() {
+    final Class2 self = this;
+    Extension2(this)[this] ??= this;
+    Extension2(self)[self] ??= self;
+
+    Extension2(this)[this] = this;
+    Extension2(self)[self] = self;
+
+    Extension2(this)[this];
+    Extension2(self)[self];
+
+    Extension2(this)[this] += this;
+    Extension2(self)[self] += self;
+  }
+
+  void explicitExtensionGetSetForValue() {
+    final Class2 self = this;
+    var v;
+    v = Extension2(this)[this] ??= this;
+    v = Extension2(self)[self] ??= self;
+
+    v = Extension2(this)[this] = this;
+    v = Extension2(self)[self] = self;
+
+    v = Extension2(this)[this];
+    v = Extension2(self)[self];
+
+    v = Extension2(this)[this] += this;
+    v = Extension2(self)[self] += self;
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.outline.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.outline.expect
new file mode 100644
index 0000000..df6fc30
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.outline.expect
@@ -0,0 +1,86 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+  operator [](self::Class* cls) → self::Class*
+    ;
+  operator []=(self::Class* cls, self::Class* value) → void
+    ;
+  operator +(self::Class* cls) → self::Class*
+    ;
+  method indexGetSetForEffect(core::Map<self::Class*, self::Class*>* map) → void
+    ;
+  method indexGetSetForValue(core::Map<self::Class*, self::Class*>* map) → void
+    ;
+  method implicitExtensionGetSetForEffect(core::int* i) → void
+    ;
+  method implicitExtensionGetSetForValue(core::int* i) → void
+    ;
+  method explicitExtensionGetSetForEffect(core::int* i) → void
+    ;
+  method explicitExtensionGetSetForValue(core::int* i) → void
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass*
+    ;
+  method superIndexGetSetForEffect() → void
+    ;
+  method superIndexGetSetForValue() → void
+    ;
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2*
+    ;
+  operator +(self::Class2* cls) → self::Class2*
+    ;
+  method implicitExtensionGetSetForEffect() → void
+    ;
+  method implicitExtensionGetSetForValue() → void
+    ;
+  method explicitExtensionGetSetForEffect() → void
+    ;
+  method explicitExtensionGetSetForValue() → void
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+extension Extension on core::int* {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2* {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static method Extension|[](lowered final core::int* #this, self::Class* cls) → self::Class*
+  ;
+static method Extension|[]=(lowered final core::int* #this, self::Class* cls, self::Class* value) → void
+  ;
+static method Extension2|[](lowered final self::Class2* #this, self::Class2* cls) → self::Class2*
+  ;
+static method Extension2|[]=(lowered final self::Class2* #this, self::Class2* cls, self::Class2* value) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.expect
new file mode 100644
index 0000000..ed17f97
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.expect
@@ -0,0 +1,199 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  operator [](self::Class* cls) → self::Class*
+    return new self::Class::•();
+  operator []=(self::Class* cls, self::Class* value) → void {}
+  operator +(self::Class* cls) → self::Class*
+    return cls;
+  method indexGetSetForEffect(core::Map<self::Class*, self::Class*>* map) → void {
+    final self::Class* self = this;
+    let final core::Map<self::Class*, self::Class*>* #t1 = map in #t1.{core::Map::[]}(this).{self::Class::==}(null) ?{self::Class*} #t1.{core::Map::[]=}(this, this) : null;
+    let final core::Map<self::Class*, self::Class*>* #t2 = map in #t2.{core::Map::[]}(self).{self::Class::==}(null) ?{self::Class*} #t2.{core::Map::[]=}(self, self) : null;
+    map.{core::Map::[]=}(this, this);
+    map.{core::Map::[]=}(self, self);
+    map.{core::Map::[]}(this);
+    map.{core::Map::[]}(self);
+    let final core::Map<self::Class*, self::Class*>* #t3 = map in #t3.{core::Map::[]=}(this, #t3.{core::Map::[]}(this).{self::Class::+}(this));
+    let final core::Map<self::Class*, self::Class*>* #t4 = map in #t4.{core::Map::[]=}(self, #t4.{core::Map::[]}(self).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(core::Map<self::Class*, self::Class*>* map) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::Map<self::Class*, self::Class*>* #t5 = map in let final self::Class* #t6 = #t5.{core::Map::[]}(this) in #t6.{self::Class::==}(null) ?{self::Class*} let final void #t7 = #t5.{core::Map::[]=}(this, this) in this : #t6;
+    v = let final core::Map<self::Class*, self::Class*>* #t8 = map in let final self::Class* #t9 = #t8.{core::Map::[]}(self) in #t9.{self::Class::==}(null) ?{self::Class*} let final void #t10 = #t8.{core::Map::[]=}(self, self) in self : #t9;
+    v = let final core::Map<self::Class*, self::Class*>* #t11 = map in let final void #t12 = #t11.{core::Map::[]=}(this, this) in this;
+    v = let final core::Map<self::Class*, self::Class*>* #t13 = map in let final void #t14 = #t13.{core::Map::[]=}(self, self) in self;
+    v = map.{core::Map::[]}(this);
+    v = map.{core::Map::[]}(self);
+    v = let final core::Map<self::Class*, self::Class*>* #t15 = map in let final self::Class* #t16 = #t15.{core::Map::[]}(this).{self::Class::+}(this) in let final void #t17 = #t15.{core::Map::[]=}(this, #t16) in #t16;
+    v = let final core::Map<self::Class*, self::Class*>* #t18 = map in let final self::Class* #t19 = #t18.{core::Map::[]}(self).{self::Class::+}(self) in let final void #t20 = #t18.{core::Map::[]=}(self, #t19) in #t19;
+  }
+  method implicitExtensionGetSetForEffect(core::int* i) → void {
+    final self::Class* self = this;
+    let final core::int* #t21 = i in self::Extension|[](#t21, this).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t21, this, this) : null;
+    let final core::int* #t22 = i in self::Extension|[](#t22, self).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t22, self, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int* #t23 = i in self::Extension|[]=(#t23, this, self::Extension|[](#t23, this).{self::Class::+}(this));
+    let final core::int* #t24 = i in self::Extension|[]=(#t24, self, self::Extension|[](#t24, self).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int* i) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::int* #t25 = i in let final self::Class* #t26 = self::Extension|[](#t25, this) in #t26.{self::Class::==}(null) ?{self::Class*} let final void #t27 = self::Extension|[]=(#t25, this, this) in this : #t26;
+    v = let final core::int* #t28 = i in let final self::Class* #t29 = self::Extension|[](#t28, self) in #t29.{self::Class::==}(null) ?{self::Class*} let final void #t30 = self::Extension|[]=(#t28, self, self) in self : #t29;
+    v = let final core::int* #t31 = i in let final void #t32 = self::Extension|[]=(#t31, this, this) in this;
+    v = let final core::int* #t33 = i in let final void #t34 = self::Extension|[]=(#t33, self, self) in self;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int* #t35 = i in let final self::Class* #t36 = self::Extension|[](#t35, this).{self::Class::+}(this) in let final void #t37 = self::Extension|[]=(#t35, this, #t36) in #t36;
+    v = let final core::int* #t38 = i in let final self::Class* #t39 = self::Extension|[](#t38, self).{self::Class::+}(self) in let final void #t40 = self::Extension|[]=(#t38, self, #t39) in #t39;
+  }
+  method explicitExtensionGetSetForEffect(core::int* i) → void {
+    final self::Class* self = this;
+    let final core::int* #t41 = i in self::Extension|[](#t41, this).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t41, this, this) : null;
+    let final core::int* #t42 = i in self::Extension|[](#t42, self).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t42, self, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int* #t43 = i in self::Extension|[]=(#t43, this, self::Extension|[](#t43, this).{self::Class::+}(this));
+    let final core::int* #t44 = i in self::Extension|[]=(#t44, self, self::Extension|[](#t44, self).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int* i) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::int* #t45 = i in let final self::Class* #t46 = self::Extension|[](#t45, this) in #t46.{self::Class::==}(null) ?{self::Class*} let final void #t47 = self::Extension|[]=(#t45, this, this) in this : #t46;
+    v = let final core::int* #t48 = i in let final self::Class* #t49 = self::Extension|[](#t48, self) in #t49.{self::Class::==}(null) ?{self::Class*} let final void #t50 = self::Extension|[]=(#t48, self, self) in self : #t49;
+    v = let final core::int* #t51 = i in let final void #t52 = self::Extension|[]=(#t51, this, this) in this;
+    v = let final core::int* #t53 = i in let final void #t54 = self::Extension|[]=(#t53, self, self) in self;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int* #t55 = i in let final self::Class* #t56 = self::Extension|[](#t55, this).{self::Class::+}(this) in let final void #t57 = self::Extension|[]=(#t55, this, #t56) in #t56;
+    v = let final core::int* #t58 = i in let final self::Class* #t59 = self::Extension|[](#t58, self).{self::Class::+}(self) in let final void #t60 = self::Extension|[]=(#t58, self, #t59) in #t59;
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass*
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    final self::Class* self = this;
+    super.{self::Class::[]}(this).{self::Class::==}(null) ?{self::Class*} super.{self::Class::[]=}(this, this) : null;
+    super.{self::Class::[]}(self).{self::Class::==}(null) ?{self::Class*} super.{self::Class::[]=}(self, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    super.{self::Class::[]=}(self, super.{self::Class::[]}(self).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final self::Class* #t61 = super.{self::Class::[]}(this) in #t61.{self::Class::==}(null) ?{self::Class*} let final void #t62 = super.{self::Class::[]=}(this, this) in this : #t61;
+    v = let final self::Class* #t63 = super.{self::Class::[]}(self) in #t63.{self::Class::==}(null) ?{self::Class*} let final void #t64 = super.{self::Class::[]=}(self, self) in self : #t63;
+    v = let final void #t65 = super.{self::Class::[]=}(this, this) in this;
+    v = let final void #t66 = super.{self::Class::[]=}(self, self) in self;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class* #t67 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t68 = super.{self::Class::[]=}(this, #t67) in #t67;
+    v = let final self::Class* #t69 = super.{self::Class::[]}(self).{self::Class::+}(self) in let final void #t70 = super.{self::Class::[]=}(self, #t69) in #t69;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2*
+    : super core::Object::•()
+    ;
+  operator +(self::Class2* cls) → self::Class2*
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    final self::Class2* self = this;
+    self::Extension2|[](this, this).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(this, this, this) : null;
+    self::Extension2|[](self, self).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(self, self, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    self::Extension2|[]=(self, self, self::Extension2|[](self, self).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    final self::Class2* self = this;
+    dynamic v;
+    v = let final self::Class2* #t71 = self::Extension2|[](this, this) in #t71.{self::Class2::==}(null) ?{self::Class2*} let final void #t72 = self::Extension2|[]=(this, this, this) in this : #t71;
+    v = let final self::Class2* #t73 = self::Extension2|[](self, self) in #t73.{self::Class2::==}(null) ?{self::Class2*} let final void #t74 = self::Extension2|[]=(self, self, self) in self : #t73;
+    v = let final void #t75 = self::Extension2|[]=(this, this, this) in this;
+    v = let final void #t76 = self::Extension2|[]=(self, self, self) in self;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2* #t77 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t78 = self::Extension2|[]=(this, this, #t77) in #t77;
+    v = let final self::Class2* #t79 = self::Extension2|[](self, self).{self::Class2::+}(self) in let final void #t80 = self::Extension2|[]=(self, self, #t79) in #t79;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    final self::Class2* self = this;
+    self::Extension2|[](this, this).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(this, this, this) : null;
+    self::Extension2|[](self, self).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(self, self, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    self::Extension2|[]=(self, self, self::Extension2|[](self, self).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    final self::Class2* self = this;
+    dynamic v;
+    v = let final self::Class2* #t81 = self::Extension2|[](this, this) in #t81.{self::Class2::==}(null) ?{self::Class2*} let final void #t82 = self::Extension2|[]=(this, this, this) in this : #t81;
+    v = let final self::Class2* #t83 = self::Extension2|[](self, self) in #t83.{self::Class2::==}(null) ?{self::Class2*} let final void #t84 = self::Extension2|[]=(self, self, self) in self : #t83;
+    v = let final void #t85 = self::Extension2|[]=(this, this, this) in this;
+    v = let final void #t86 = self::Extension2|[]=(self, self, self) in self;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2* #t87 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t88 = self::Extension2|[]=(this, this, #t87) in #t87;
+    v = let final self::Class2* #t89 = self::Extension2|[](self, self).{self::Class2::+}(self) in let final void #t90 = self::Extension2|[]=(self, self, #t89) in #t89;
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+extension Extension on core::int* {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2* {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static method Extension|[](lowered final core::int* #this, self::Class* cls) → self::Class*
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int* #this, self::Class* cls, self::Class* value) → void {}
+static method Extension2|[](lowered final self::Class2* #this, self::Class2* cls) → self::Class2*
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2* #this, self::Class2* cls, self::Class2* value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.transformed.expect
new file mode 100644
index 0000000..ed17f97
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.strong.transformed.expect
@@ -0,0 +1,199 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  operator [](self::Class* cls) → self::Class*
+    return new self::Class::•();
+  operator []=(self::Class* cls, self::Class* value) → void {}
+  operator +(self::Class* cls) → self::Class*
+    return cls;
+  method indexGetSetForEffect(core::Map<self::Class*, self::Class*>* map) → void {
+    final self::Class* self = this;
+    let final core::Map<self::Class*, self::Class*>* #t1 = map in #t1.{core::Map::[]}(this).{self::Class::==}(null) ?{self::Class*} #t1.{core::Map::[]=}(this, this) : null;
+    let final core::Map<self::Class*, self::Class*>* #t2 = map in #t2.{core::Map::[]}(self).{self::Class::==}(null) ?{self::Class*} #t2.{core::Map::[]=}(self, self) : null;
+    map.{core::Map::[]=}(this, this);
+    map.{core::Map::[]=}(self, self);
+    map.{core::Map::[]}(this);
+    map.{core::Map::[]}(self);
+    let final core::Map<self::Class*, self::Class*>* #t3 = map in #t3.{core::Map::[]=}(this, #t3.{core::Map::[]}(this).{self::Class::+}(this));
+    let final core::Map<self::Class*, self::Class*>* #t4 = map in #t4.{core::Map::[]=}(self, #t4.{core::Map::[]}(self).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(core::Map<self::Class*, self::Class*>* map) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::Map<self::Class*, self::Class*>* #t5 = map in let final self::Class* #t6 = #t5.{core::Map::[]}(this) in #t6.{self::Class::==}(null) ?{self::Class*} let final void #t7 = #t5.{core::Map::[]=}(this, this) in this : #t6;
+    v = let final core::Map<self::Class*, self::Class*>* #t8 = map in let final self::Class* #t9 = #t8.{core::Map::[]}(self) in #t9.{self::Class::==}(null) ?{self::Class*} let final void #t10 = #t8.{core::Map::[]=}(self, self) in self : #t9;
+    v = let final core::Map<self::Class*, self::Class*>* #t11 = map in let final void #t12 = #t11.{core::Map::[]=}(this, this) in this;
+    v = let final core::Map<self::Class*, self::Class*>* #t13 = map in let final void #t14 = #t13.{core::Map::[]=}(self, self) in self;
+    v = map.{core::Map::[]}(this);
+    v = map.{core::Map::[]}(self);
+    v = let final core::Map<self::Class*, self::Class*>* #t15 = map in let final self::Class* #t16 = #t15.{core::Map::[]}(this).{self::Class::+}(this) in let final void #t17 = #t15.{core::Map::[]=}(this, #t16) in #t16;
+    v = let final core::Map<self::Class*, self::Class*>* #t18 = map in let final self::Class* #t19 = #t18.{core::Map::[]}(self).{self::Class::+}(self) in let final void #t20 = #t18.{core::Map::[]=}(self, #t19) in #t19;
+  }
+  method implicitExtensionGetSetForEffect(core::int* i) → void {
+    final self::Class* self = this;
+    let final core::int* #t21 = i in self::Extension|[](#t21, this).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t21, this, this) : null;
+    let final core::int* #t22 = i in self::Extension|[](#t22, self).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t22, self, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int* #t23 = i in self::Extension|[]=(#t23, this, self::Extension|[](#t23, this).{self::Class::+}(this));
+    let final core::int* #t24 = i in self::Extension|[]=(#t24, self, self::Extension|[](#t24, self).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int* i) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::int* #t25 = i in let final self::Class* #t26 = self::Extension|[](#t25, this) in #t26.{self::Class::==}(null) ?{self::Class*} let final void #t27 = self::Extension|[]=(#t25, this, this) in this : #t26;
+    v = let final core::int* #t28 = i in let final self::Class* #t29 = self::Extension|[](#t28, self) in #t29.{self::Class::==}(null) ?{self::Class*} let final void #t30 = self::Extension|[]=(#t28, self, self) in self : #t29;
+    v = let final core::int* #t31 = i in let final void #t32 = self::Extension|[]=(#t31, this, this) in this;
+    v = let final core::int* #t33 = i in let final void #t34 = self::Extension|[]=(#t33, self, self) in self;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int* #t35 = i in let final self::Class* #t36 = self::Extension|[](#t35, this).{self::Class::+}(this) in let final void #t37 = self::Extension|[]=(#t35, this, #t36) in #t36;
+    v = let final core::int* #t38 = i in let final self::Class* #t39 = self::Extension|[](#t38, self).{self::Class::+}(self) in let final void #t40 = self::Extension|[]=(#t38, self, #t39) in #t39;
+  }
+  method explicitExtensionGetSetForEffect(core::int* i) → void {
+    final self::Class* self = this;
+    let final core::int* #t41 = i in self::Extension|[](#t41, this).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t41, this, this) : null;
+    let final core::int* #t42 = i in self::Extension|[](#t42, self).{self::Class::==}(null) ?{self::Class*} self::Extension|[]=(#t42, self, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int* #t43 = i in self::Extension|[]=(#t43, this, self::Extension|[](#t43, this).{self::Class::+}(this));
+    let final core::int* #t44 = i in self::Extension|[]=(#t44, self, self::Extension|[](#t44, self).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int* i) → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final core::int* #t45 = i in let final self::Class* #t46 = self::Extension|[](#t45, this) in #t46.{self::Class::==}(null) ?{self::Class*} let final void #t47 = self::Extension|[]=(#t45, this, this) in this : #t46;
+    v = let final core::int* #t48 = i in let final self::Class* #t49 = self::Extension|[](#t48, self) in #t49.{self::Class::==}(null) ?{self::Class*} let final void #t50 = self::Extension|[]=(#t48, self, self) in self : #t49;
+    v = let final core::int* #t51 = i in let final void #t52 = self::Extension|[]=(#t51, this, this) in this;
+    v = let final core::int* #t53 = i in let final void #t54 = self::Extension|[]=(#t53, self, self) in self;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int* #t55 = i in let final self::Class* #t56 = self::Extension|[](#t55, this).{self::Class::+}(this) in let final void #t57 = self::Extension|[]=(#t55, this, #t56) in #t56;
+    v = let final core::int* #t58 = i in let final self::Class* #t59 = self::Extension|[](#t58, self).{self::Class::+}(self) in let final void #t60 = self::Extension|[]=(#t58, self, #t59) in #t59;
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass*
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    final self::Class* self = this;
+    super.{self::Class::[]}(this).{self::Class::==}(null) ?{self::Class*} super.{self::Class::[]=}(this, this) : null;
+    super.{self::Class::[]}(self).{self::Class::==}(null) ?{self::Class*} super.{self::Class::[]=}(self, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    super.{self::Class::[]=}(self, super.{self::Class::[]}(self).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    final self::Class* self = this;
+    dynamic v;
+    v = let final self::Class* #t61 = super.{self::Class::[]}(this) in #t61.{self::Class::==}(null) ?{self::Class*} let final void #t62 = super.{self::Class::[]=}(this, this) in this : #t61;
+    v = let final self::Class* #t63 = super.{self::Class::[]}(self) in #t63.{self::Class::==}(null) ?{self::Class*} let final void #t64 = super.{self::Class::[]=}(self, self) in self : #t63;
+    v = let final void #t65 = super.{self::Class::[]=}(this, this) in this;
+    v = let final void #t66 = super.{self::Class::[]=}(self, self) in self;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class* #t67 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t68 = super.{self::Class::[]=}(this, #t67) in #t67;
+    v = let final self::Class* #t69 = super.{self::Class::[]}(self).{self::Class::+}(self) in let final void #t70 = super.{self::Class::[]=}(self, #t69) in #t69;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2*
+    : super core::Object::•()
+    ;
+  operator +(self::Class2* cls) → self::Class2*
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    final self::Class2* self = this;
+    self::Extension2|[](this, this).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(this, this, this) : null;
+    self::Extension2|[](self, self).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(self, self, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    self::Extension2|[]=(self, self, self::Extension2|[](self, self).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    final self::Class2* self = this;
+    dynamic v;
+    v = let final self::Class2* #t71 = self::Extension2|[](this, this) in #t71.{self::Class2::==}(null) ?{self::Class2*} let final void #t72 = self::Extension2|[]=(this, this, this) in this : #t71;
+    v = let final self::Class2* #t73 = self::Extension2|[](self, self) in #t73.{self::Class2::==}(null) ?{self::Class2*} let final void #t74 = self::Extension2|[]=(self, self, self) in self : #t73;
+    v = let final void #t75 = self::Extension2|[]=(this, this, this) in this;
+    v = let final void #t76 = self::Extension2|[]=(self, self, self) in self;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2* #t77 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t78 = self::Extension2|[]=(this, this, #t77) in #t77;
+    v = let final self::Class2* #t79 = self::Extension2|[](self, self).{self::Class2::+}(self) in let final void #t80 = self::Extension2|[]=(self, self, #t79) in #t79;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    final self::Class2* self = this;
+    self::Extension2|[](this, this).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(this, this, this) : null;
+    self::Extension2|[](self, self).{self::Class2::==}(null) ?{self::Class2*} self::Extension2|[]=(self, self, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    self::Extension2|[]=(self, self, self::Extension2|[](self, self).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    final self::Class2* self = this;
+    dynamic v;
+    v = let final self::Class2* #t81 = self::Extension2|[](this, this) in #t81.{self::Class2::==}(null) ?{self::Class2*} let final void #t82 = self::Extension2|[]=(this, this, this) in this : #t81;
+    v = let final self::Class2* #t83 = self::Extension2|[](self, self) in #t83.{self::Class2::==}(null) ?{self::Class2*} let final void #t84 = self::Extension2|[]=(self, self, self) in self : #t83;
+    v = let final void #t85 = self::Extension2|[]=(this, this, this) in this;
+    v = let final void #t86 = self::Extension2|[]=(self, self, self) in self;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2* #t87 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t88 = self::Extension2|[]=(this, this, #t87) in #t87;
+    v = let final self::Class2* #t89 = self::Extension2|[](self, self).{self::Class2::+}(self) in let final void #t90 = self::Extension2|[]=(self, self, #t89) in #t89;
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+extension Extension on core::int* {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2* {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static method Extension|[](lowered final core::int* #this, self::Class* cls) → self::Class*
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int* #this, self::Class* cls, self::Class* value) → void {}
+static method Extension2|[](lowered final self::Class2* #this, self::Class2* cls) → self::Class2*
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2* #this, self::Class2* cls, self::Class2* value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline.expect
new file mode 100644
index 0000000..a529cd5
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline.expect
@@ -0,0 +1,37 @@
+// @dart = 2.9
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+  Class operator +(Class cls) => cls;
+  void indexGetSetForEffect(Map<Class, Class> map) {}
+  void indexGetSetForValue(Map<Class, Class> map) {}
+  void implicitExtensionGetSetForEffect(int i) {}
+  void implicitExtensionGetSetForValue(int i) {}
+  void explicitExtensionGetSetForEffect(int i) {}
+  void explicitExtensionGetSetForValue(int i) {}
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {}
+  void superIndexGetSetForValue() {}
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+  void implicitExtensionGetSetForEffect() {}
+  void implicitExtensionGetSetForValue() {}
+  void explicitExtensionGetSetForEffect() {}
+  void explicitExtensionGetSetForValue() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f0fb925
--- /dev/null
+++ b/pkg/front_end/testcases/general/pure_index_expressions.dart.textual_outline_modelled.expect
@@ -0,0 +1,37 @@
+// @dart = 2.9
+class Class {
+  Class operator +(Class cls) => cls;
+  Class operator [](Class cls) => new Class();
+  void explicitExtensionGetSetForEffect(int i) {}
+  void explicitExtensionGetSetForValue(int i) {}
+  void implicitExtensionGetSetForEffect(int i) {}
+  void implicitExtensionGetSetForValue(int i) {}
+  void indexGetSetForEffect(Map<Class, Class> map) {}
+  void indexGetSetForValue(Map<Class, Class> map) {}
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+  void explicitExtensionGetSetForEffect() {}
+  void explicitExtensionGetSetForValue() {}
+  void implicitExtensionGetSetForEffect() {}
+  void implicitExtensionGetSetForValue() {}
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {}
+  void superIndexGetSetForValue() {}
+}
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline.expect
index 8e696a0..35d1d71 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline.expect
@@ -1,3 +1,24 @@
-extension Foo<U> (){}
-on List (){}
+extension Foo<U> on List {
+  static U foo1() {}
+  static List<U> foo1Prime() {}
+  static void foo2(U x) {}
+  static void foo2Prime(List<U> x) {}
+  static void foo3() {}
+  static U Function() foo8() {}
+  static List<U> Function() foo8Prime() {}
+  static void Function(U) foo9() {}
+  static void Function(List<U>) foo9Prime() {}
+  static void foo10(U Function()) {}
+  static void foo10Prime(List<U> Function()) {}
+  static void foo11(void Function(U)) {}
+  static void foo12(void Function(U) b) {}
+  static void foo12Prime(void Function(List<U>) b) {}
+  static void foo13(void Function(U b)) {}
+  static void foo13Prime(void Function(List<U> b)) {}
+  static U foo14 = null;
+  static List<U> foo14Prime = null;
+  static U Function(U) foo15 = null;
+  static List<U> Function(List<U>) foo15Prime = null;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..72cd4cf
--- /dev/null
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+extension Foo<U> on List {
+  static List<U> Function() foo8Prime() {}
+  static List<U> Function(List<U>) foo15Prime = null;
+  static List<U> foo14Prime = null;
+  static List<U> foo1Prime() {}
+  static U Function() foo8() {}
+  static U Function(U) foo15 = null;
+  static U foo1() {}
+  static U foo14 = null;
+  static void Function(List<U>) foo9Prime() {}
+  static void Function(U) foo9() {}
+  static void foo10(U Function()) {}
+  static void foo10Prime(List<U> Function()) {}
+  static void foo11(void Function(U)) {}
+  static void foo12(void Function(U) b) {}
+  static void foo12Prime(void Function(List<U>) b) {}
+  static void foo13(void Function(U b)) {}
+  static void foo13Prime(void Function(List<U> b)) {}
+  static void foo2(U x) {}
+  static void foo2Prime(List<U> x) {}
+  static void foo3() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline.expect
index bb04737..06dc10a 100644
--- a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline.expect
@@ -1,8 +1,15 @@
 class A<X extends int> {}
+
 class B {
   A<num> fieldOfA;
   static A<num> staticFieldOfA;
 }
-extension E<X extends A<num>> (){}
-on A (){}
+
+extension E<X extends A<num>> on A {
+  static A<num> fieldOfE;
+  A<num> fooOfE() => null;
+  void barOfE(A<num> a) {}
+  void bazOfE<Y extends A<num>>() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4fd7430
--- /dev/null
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.textual_outline_modelled.expect
@@ -0,0 +1,15 @@
+class A<X extends int> {}
+
+class B {
+  A<num> fieldOfA;
+  static A<num> staticFieldOfA;
+}
+
+extension E<X extends A<num>> on A {
+  A<num> fooOfE() => null;
+  static A<num> fieldOfE;
+  void barOfE(A<num> a) {}
+  void bazOfE<Y extends A<num>>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.textual_outline.expect
index e03605b..e124df6 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.textual_outline.expect
@@ -56,6 +56,15 @@
   static late ;
   final int finalStaticFieldWithInitializer = 0;
 }
-extension Extension ;
-on A (){}
+extension Extension on A {
+  @Annotation()
+  static late int ;
+  extensionStaticField;
+  @Annotation()
+  static late ;
+  final int finalExtensionStaticField;
+  @Annotation()
+  static late ;
+  final int finalExtensionStaticFieldWithInitializer = 0;
+}
 main() {}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.textual_outline.expect
index 3c8b258..40fa799 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.textual_outline.expect
@@ -16,7 +16,12 @@
   Class(this.field);
   instanceMethod(T value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static late int ;
+  lateExtensionField1 = 87;
+  static late int ;
+  lateExtensionField2 = 42;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.textual_outline.expect
index a79477b..45d52d8 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.textual_outline.expect
@@ -12,8 +12,13 @@
   T lateGenericInstanceField;
   instanceMethod(T value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static late int ;
+  lateExtensionField1;
+  static late int ;
+  lateExtensionField2;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.textual_outline.expect
index eb122a4..08e1682 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.textual_outline.expect
@@ -34,7 +34,16 @@
   Class(this.field);
   instanceMethod() {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static int? lateExtensionField1Init;
+  static int initLateExtensionField1(int value) {}
+  static late ;
+  final int lateExtensionField1 = initLateExtensionField1(87);
+  static int? lateExtensionField2Init;
+  static int initLateExtensionField2(int value) {}
+  static late ;
+  final int lateExtensionField2 = initLateExtensionField2(42);
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.textual_outline.expect
index e1be8d4..7a7f054 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.textual_outline.expect
@@ -10,8 +10,13 @@
   final int lateInstanceField;
   instanceMethod() {}
 }
-extension Extension ;
-on Class (){}
+extension Extension on Class {
+  static late ;
+  final int lateExtensionField1;
+  static late ;
+  final int lateExtensionField2;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.textual_outline.expect
index 3a9e54e..14bd840 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_with_initializer.dart.textual_outline.expect
@@ -24,7 +24,16 @@
   Class(this.field);
   instanceMethod() {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static int? lateExtensionField1Init;
+  static int? initLateExtensionField1(int value) {}
+  static late ;
+  final int? lateExtensionField1 = initLateExtensionField1(87);
+  static int? lateExtensionField2Init;
+  static int? initLateExtensionField2(int value) {}
+  static late ;
+  final int? lateExtensionField2 = initLateExtensionField2(42);
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.textual_outline.expect
index d82d349..8837f31 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_field_without_initializer.dart.textual_outline.expect
@@ -12,8 +12,13 @@
   final T? lateGenericInstanceField;
   instanceMethod(T value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static late ;
+  final int? lateExtensionField1;
+  static late ;
+  final int? lateExtensionField2;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.textual_outline.expect
index 7804754..83b91b4 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.textual_outline.expect
@@ -21,7 +21,16 @@
   Class(this.field);
   instanceMethod(T? value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static int? lateExtensionField1Init() => 87;
+  static late int;
+  operator? (){}
+  lateExtensionField1 = lateExtensionField1Init();
+  static int? lateExtensionField2Init() => 42;
+  static late int;
+  operator? (){}
+  lateExtensionField2 = lateExtensionField2Init();
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.textual_outline.expect
index aab13f1..d0cb971 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.textual_outline.expect
@@ -14,8 +14,15 @@
   T? lateGenericInstanceField;
   instanceMethod(T? value) {}
 }
-extension Extension<T> (){}
-on Class<T> (){}
+extension Extension<T> on Class<T> {
+  static late int;
+  operator? (){}
+  lateExtensionField1;
+  static late int;
+  operator? (){}
+  lateExtensionField2;
+  static staticMethod() {}
+}
 main() {}
 expect(expected, actual) {}
 throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect
index 69a99ab..a2e1e46 100644
--- a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect
@@ -26,6 +26,10 @@
   external abstract final int externalFinalInstanceField;
   external abstract covariant num externalCovariantInstanceField;
 }
-extension Extension ;
-on A (){}
+extension Extension on A {
+  abstract int extensionInstanceField;
+  abstract final int finalExtensionInstanceField;
+  abstract static int extensionStaticField = 0;
+  abstract static final int finalExtensionStaticField = 0;
+}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect
index ad8ddc8..d7c8546 100644
--- a/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline.expect
@@ -1,11 +1,41 @@
-extension Extension1<T extends Object> (){}
-on T (){}
-extension Extension2<T extends String> (){}
-on T (){}
-extension Extension3<T extends dynamic> (){}
-on T (){}
-extension Extension4<T> (){}
-on T (){}
-extension Extension5<T extends Object?> (){}
-on T (){}
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension5<T extends Object?> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d7c8546
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_bounds.dart.textual_outline_modelled.expect
@@ -0,0 +1,41 @@
+extension Extension1<T extends Object> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension2<T extends String> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension3<T extends dynamic> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension4<T> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+extension Extension5<T extends Object?> on T {
+  method1<S extends Object>() {}
+  method2<S extends String>() {}
+  method3<S extends dynamic>() {}
+  method4<S>() {}
+  method5<S extends Object?>() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline.expect
index 8b38ea1..b573756 100644
--- a/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline.expect
@@ -1,5 +1,7 @@
-extension Extension ;
-on Never (){}
+extension Extension on Never {
+  extensionMethod() {}
+}
+
 implicitAccess(Never never) {}
 explicitAccess(Never never) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..4edd53e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_never.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+explicitAccess(Never never) {}
+
+extension Extension on Never {
+  extensionMethod() {}
+}
+
+implicitAccess(Never never) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline.expect
index 0434002..7f86fba 100644
--- a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline.expect
@@ -1,9 +1,15 @@
-extension Extension<T> (){}
-on T (){}
-extension BoundExtension<T extends Class> (){}
-on T (){}
+extension Extension<T> on T {
+  T method1() => this;
+}
+
+extension BoundExtension<T extends Class> on T {
+  T method2() => this;
+}
+
 class Class {}
+
 class SubClass extends Class {}
+
 Class test1<T>(T t1) {}
 test2<T extends Class>(T t2) {}
 test3<T>(T t3) {}
diff --git a/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..d20dc15
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/extension_type_variable_bound.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+Class test1<T>(T t1) {}
+
+class Class {}
+
+class SubClass extends Class {}
+
+extension BoundExtension<T extends Class> on T {
+  T method2() => this;
+}
+
+extension Extension<T> on T {
+  T method1() => this;
+}
+
+main() {}
+test2<T extends Class>(T t2) {}
+test3<T>(T t3) {}
diff --git a/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline.expect
index cafad59..ac7f418 100644
--- a/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline.expect
@@ -1,6 +1,7 @@
 external int topLevelField = 0;
 external final int finalTopLevelField = 0;
 external const int constField = 0;
+
 abstract class A {
   external int fieldWithInitializer = 0;
   external int initializedField1;
@@ -9,10 +10,17 @@
   external static int staticField = 0;
   external static final int finalStaticField = 0;
 }
+
 mixin B {
   external static int staticField = 0;
   external static final int finalStaticField = 0;
 }
-extension Extension ;
-on A (){}
+
+extension Extension on A {
+  external int extensionInstanceField = 0;
+  external final int finalExtensionInstanceField = 0;
+  external static int extensionStaticField = 0;
+  external static final int finalExtensionStaticField = 0;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..322cf16
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/external_field_errors.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+abstract class A {
+  A(this.initializedField1) : this.initializedField2 = 0;
+  external int fieldWithInitializer = 0;
+  external int initializedField1;
+  external int initializedField2;
+  external static final int finalStaticField = 0;
+  external static int staticField = 0;
+}
+
+extension Extension on A {
+  external final int finalExtensionInstanceField = 0;
+  external int extensionInstanceField = 0;
+  external static final int finalExtensionStaticField = 0;
+  external static int extensionStaticField = 0;
+}
+
+external const int constField = 0;
+external final int finalTopLevelField = 0;
+external int topLevelField = 0;
+main() {}
+mixin B {
+  external static final int finalStaticField = 0;
+  external static int staticField = 0;
+}
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline.expect
index d337a98..e1bc41f 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline.expect
@@ -1,12 +1,14 @@
 class Annotation {
   const Annotation();
 }
+
 @Annotation()
 external int topLevelField;
 @Annotation()
 external final int finalTopLevelField;
 external var untypedTopLevelField;
 external final untypedFinalTopLevelField;
+
 class A {
   @Annotation()
   external int instanceField;
@@ -24,6 +26,7 @@
   external static var untypedStaticField;
   external static final untypedFinalStaticField;
 }
+
 mixin B {
   @Annotation()
   external int instanceField;
@@ -41,8 +44,22 @@
   external static var untypedStaticField;
   external static final untypedFinalStaticField;
 }
-extension Extension ;
-on A (){}
+
+extension Extension on A {
+  @Annotation()
+  external int extensionInstanceField;
+  @Annotation()
+  external final int finalExtensionInstanceField;
+  @Annotation()
+  external static int extensionStaticField;
+  @Annotation()
+  external static final int finalExtensionStaticField;
+  external var untypedExtensionInstanceField;
+  external final untypedFinalExtensionInstanceField;
+  external static var untypedExtensionStaticField;
+  external static final untypedFinalExtensionStaticField;
+}
+
 class C implements A {
   external var instanceField;
   external final finalInstanceField;
@@ -51,4 +68,5 @@
   external final untypedFinalInstanceField;
   external var untypedCovariantInstanceField;
 }
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c5e3169
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.textual_outline_modelled.expect
@@ -0,0 +1,70 @@
+class A {
+  @Annotation()
+  external covariant num covariantInstanceField;
+  external covariant var untypedCovariantInstanceField;
+  @Annotation()
+  external final int finalInstanceField;
+  external final untypedFinalInstanceField;
+  @Annotation()
+  external int instanceField;
+  @Annotation()
+  external static final int finalStaticField;
+  external static final untypedFinalStaticField;
+  @Annotation()
+  external static int staticField;
+  external static var untypedStaticField;
+  external var untypedInstanceField;
+}
+
+class Annotation {
+  const Annotation();
+}
+
+class C implements A {
+  external final finalInstanceField;
+  external final untypedFinalInstanceField;
+  external var covariantInstanceField;
+  external var instanceField;
+  external var untypedCovariantInstanceField;
+  external var untypedInstanceField;
+}
+
+extension Extension on A {
+  @Annotation()
+  external final int finalExtensionInstanceField;
+  external final untypedFinalExtensionInstanceField;
+  @Annotation()
+  external int extensionInstanceField;
+  @Annotation()
+  external static final int finalExtensionStaticField;
+  external static final untypedFinalExtensionStaticField;
+  @Annotation()
+  external static int extensionStaticField;
+  external static var untypedExtensionStaticField;
+  external var untypedExtensionInstanceField;
+}
+
+@Annotation()
+external final int finalTopLevelField;
+external final untypedFinalTopLevelField;
+@Annotation()
+external int topLevelField;
+external var untypedTopLevelField;
+main() {}
+mixin B {
+  @Annotation()
+  external covariant num covariantInstanceField;
+  external covariant var untypedCovariantInstanceField;
+  @Annotation()
+  external final int finalInstanceField;
+  external final untypedFinalInstanceField;
+  @Annotation()
+  external int instanceField;
+  @Annotation()
+  external static final int finalStaticField;
+  external static final untypedFinalStaticField;
+  @Annotation()
+  external static int staticField;
+  external static var untypedStaticField;
+  external var untypedInstanceField;
+}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect
index 806128e..8fae4ef 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect
@@ -4,6 +4,7 @@
 void set property2(num value) {}
 num get property3 => 0;
 void set property3(int value) {}
+
 abstract class A {
   int get property1;
   void set property1(int i);
@@ -21,6 +22,7 @@
   static num get property9 => 0;
   static void set property9(int value) {}
 }
+
 abstract class B1 {
   int get property1;
   int get property2;
@@ -30,6 +32,7 @@
   final num property6;
   B1(this.property4, this.property5, this.property6);
 }
+
 abstract class B2 implements B1 {
   void set property1(int i);
   void set property2(num i);
@@ -38,6 +41,7 @@
   void set property5(num i);
   void set property6(int i);
 }
+
 abstract class C1 {
   void set property1(int i);
   void set property2(num i);
@@ -46,6 +50,7 @@
   num property5 = 0;
   int property6 = 0;
 }
+
 abstract class C2 implements C1 {
   int get property1;
   int get property2;
@@ -54,18 +59,42 @@
   int get property5;
   num get property6;
 }
+
 abstract class D1 {
   int get property1;
   int get property2;
   num get property3;
 }
+
 abstract class D2 {
   void set property1(int i);
   void set property2(num i);
   void set property3(int i);
 }
+
 abstract class D3 implements D1, D2 {}
+
 abstract class D4 implements D3 {}
-extension Extension<T, S extends T> (){}
-on int (){}
+
+extension Extension<T, S extends T> on int {
+  int get property1 => 0;
+  void set property1(int i) {}
+  int get property2 => 0;
+  void set property2(num i) {}
+  num get property3 => 0;
+  void set property3(int i) {}
+  S get property4 => 0;
+  void set property4(S i) {}
+  S get property5 => 0;
+  void set property5(T i) {}
+  T get property6 => 0;
+  void set property6(S i) {}
+  static int get property7 => 0;
+  static void set property7(int value) {}
+  static int get property8 => 0;
+  static void set property8(num value) {}
+  static num get property9 => 0;
+  static void set property9(int value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect
index feb0a3a..75210d1 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect
@@ -69,6 +69,27 @@
 
 abstract class D4 implements D3 {}
 
+extension Extension<T, S extends T> on int {
+  S get property4 => 0;
+  S get property5 => 0;
+  T get property6 => 0;
+  int get property1 => 0;
+  int get property2 => 0;
+  num get property3 => 0;
+  static int get property7 => 0;
+  static int get property8 => 0;
+  static num get property9 => 0;
+  static void set property7(int value) {}
+  static void set property8(num value) {}
+  static void set property9(int value) {}
+  void set property1(int i) {}
+  void set property2(num i) {}
+  void set property3(int i) {}
+  void set property4(S i) {}
+  void set property5(T i) {}
+  void set property6(S i) {}
+}
+
 int get property1 => 0;
 int get property2 => 0;
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect
index 1bfebe7..b5c6ecb 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect
@@ -4,6 +4,7 @@
 void set property2(int? value) {}
 int? get property3 => 0;
 void set property3(int value) {}
+
 abstract class A {
   int get property1;
   void set property1(int i);
@@ -22,6 +23,7 @@
   static int? get property9 => 0;
   static void set property9(int value) {}
 }
+
 abstract class B1 {
   int get property1;
   int get property2;
@@ -31,6 +33,7 @@
   final int? property6;
   B1(this.property4, this.property5, this.property6);
 }
+
 abstract class B2 implements B1 {
   void set property1(int i);
   void set property2(int? i);
@@ -39,6 +42,7 @@
   void set property5(int? i);
   void set property6(int i);
 }
+
 abstract class C1 {
   void set property1(int i);
   void set property2(int? i);
@@ -48,6 +52,7 @@
   int property6;
   C1(this.property4, this.property5, this.property6);
 }
+
 abstract class C2 implements C1 {
   int get property1;
   int get property2;
@@ -56,18 +61,44 @@
   int get property5;
   int? get property6;
 }
+
 abstract class D1 {
   int get property1;
   int get property2;
   int? get property3;
 }
+
 abstract class D2 {
   void set property1(int i);
   void set property2(int? i);
   void set property3(int i);
 }
+
 abstract class D3 implements D1, D2 {}
+
 abstract class D4 implements D3 {}
-extension Extension<T extends num> (){}
-on int (){}
+
+extension Extension<T extends num> on int {
+  int get property1 => 0;
+  void set property1(int i) {}
+  int get property2 => 0;
+  void set property2(int? i) {}
+  int? get property3 => 0;
+  void set property3(int i) {}
+  T get property4a => 0;
+  void set property4a(T i) {}
+  T? get property4b => 0;
+  void set property4b(T? i) {}
+  T get property5 => 0;
+  void set property5(T? i) {}
+  T? get property6 => 0;
+  void set property6(T i) {}
+  static int get property7 => 0;
+  static void set property7(int value) {}
+  static int get property8 => 0;
+  static void set property8(int? value) {}
+  static int? get property9 => 0;
+  static void set property9(int value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect
index 30cbfa9..9aaca1d 100644
--- a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect
@@ -71,6 +71,29 @@
 
 abstract class D4 implements D3 {}
 
+extension Extension<T extends num> on int {
+  T? get property4b => 0;
+  T? get property6 => 0;
+  T get property4a => 0;
+  T get property5 => 0;
+  int? get property3 => 0;
+  int get property1 => 0;
+  int get property2 => 0;
+  static int? get property9 => 0;
+  static int get property7 => 0;
+  static int get property8 => 0;
+  static void set property7(int value) {}
+  static void set property8(int? value) {}
+  static void set property9(int value) {}
+  void set property1(int i) {}
+  void set property2(int? i) {}
+  void set property3(int i) {}
+  void set property4a(T i) {}
+  void set property4b(T? i) {}
+  void set property5(T? i) {}
+  void set property6(T i) {}
+}
+
 int? get property3 => 0;
 int get property1 => 0;
 int get property2 => 0;
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline.expect
index c41c8b4..6e6c210 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline.expect
@@ -1,24 +1,34 @@
 T hest1<T>() => throw "hest";
 test1() {}
+
 class A2 {
   String? foo;
 }
+
 test2(A2 a) {}
 test3() {}
 test4() {}
+
 class A5 {
   void operator []=(int index, String? value) {}
   String? operator [](int index) => null;
 }
+
 class B5 extends A5 {
   test5() {}
 }
-extension E6 ;
-on double (){}
+
+extension E6 on double {
+  void operator []=(int index, String? value) {}
+  String? operator [](int index) => null;
+}
+
 test6() {}
+
 class A7 {
   String foo = "foo";
   String? bar;
 }
+
 test7(A7? a) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1621b7e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.textual_outline_modelled.expect
@@ -0,0 +1,32 @@
+T hest1<T>() => throw "hest";
+
+class A2 {
+  String? foo;
+}
+
+class A5 {
+  String? operator [](int index) => null;
+  void operator []=(int index, String? value) {}
+}
+
+class A7 {
+  String? bar;
+  String foo = "foo";
+}
+
+class B5 extends A5 {
+  test5() {}
+}
+
+extension E6 on double {
+  String? operator [](int index) => null;
+  void operator []=(int index, String? value) {}
+}
+
+main() {}
+test1() {}
+test2(A2 a) {}
+test3() {}
+test4() {}
+test6() {}
+test7(A7? a) {}
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline.expect
index 6fca9a1..3e3ff63 100644
--- a/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline.expect
@@ -1,15 +1,20 @@
 class A {
   foo() => 23;
 }
-extension B ;
-on A;
-? { foo() => 42; bar() => 87; }
-extension C ;
-on A (){}
-extension D ;
-on int ;
-Function(){}
-? { int call() => 76; }
+
+extension B on A? {
+  foo() => 42;
+  bar() => 87;
+}
+
+extension C on A {
+  bar() => 123;
+}
+
+extension D on int Function()? {
+  int call() => 76;
+}
+
 main() {}
 testA(A? a) {}
 testFunction(int Function()? f) {}
diff --git a/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..545b414
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue41349.dart.textual_outline_modelled.expect
@@ -0,0 +1,22 @@
+class A {
+  foo() => 23;
+}
+
+expect(expected, actual) {}
+
+extension B on A? {
+  bar() => 87;
+  foo() => 42;
+}
+
+extension C on A {
+  bar() => 123;
+}
+
+extension D on int Function()? {
+  int call() => 76;
+}
+
+main() {}
+testA(A? a) {}
+testFunction(int Function()? f) {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect
index f38556f..f3d6cdd 100644
--- a/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect
@@ -1,17 +1,24 @@
 class A<X extends A<X>?> {}
+
 class D<X extends num> {}
-extension Extension1<X extends A<X>?> (){}
-on A<X> (){}
-extension ext2<X extends A<Null>?> (){}
-on A<X> (){}
+
+extension Extension1<X extends A<X>?> on A<X> {
+  void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {}
+  void method2<Y extends String>(D<Y> a, D<String>? b) {}
+}
+
+extension ext2<X extends A<Null>?> on A<X> {}
+
 class B<X extends A<Null>?> implements A<X> {
   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {}
   void method2<Y extends String>(D<Y> a, D<String>? b) {}
 }
+
 class C {
   factory C.redirect(A<A<Null>>? a) = C.internal;
   factory C.fact(A<A<Null>>? a) {}
   C.internal(_) {}
 }
+
 test() {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..36a6a66
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class A<X extends A<X>?> {}
+
+class B<X extends A<Null>?> implements A<X> {
+  void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {}
+  void method2<Y extends String>(D<Y> a, D<String>? b) {}
+}
+
+class C {
+  C.internal(_) {}
+  factory C.fact(A<A<Null>>? a) {}
+  factory C.redirect(A<A<Null>>? a) = C.internal;
+}
+
+class D<X extends num> {}
+
+extension Extension1<X extends A<X>?> on A<X> {
+  void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {}
+  void method2<Y extends String>(D<Y> a, D<String>? b) {}
+}
+
+extension ext2<X extends A<Null>?> on A<X> {}
+
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect
index 989f770..c4cdc58 100644
--- a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect
@@ -3,9 +3,16 @@
   A bar;
   A(this.bar);
 }
+
 test<T extends A?>(A? a, T t, dynamic d, int x) {}
+
 class B {}
-extension Extension ;
-on B (){}
+
+extension Extension on B {
+  int? get fooExtension => null;
+  void set fooExtension(int? value) {}
+  B get barExtension => new B();
+}
+
 testExtension<T extends B?>(B? b, T t, int x) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect
index ffcd116..b16d6f7 100644
--- a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect
@@ -1,9 +1,17 @@
-bar<T extends A?>(A? a, T t, dynamic d, int x) {}
-
 class A {
   A(this.bar);
   A bar;
   int? foo;
 }
 
+class B {}
+
+extension Extension on B {
+  B get barExtension => new B();
+  int? get fooExtension => null;
+  void set fooExtension(int? value) {}
+}
+
 main() {}
+test<T extends A?>(A? a, T t, dynamic d, int x) {}
+testExtension<T extends B?>(B? b, T t, int x) {}
diff --git a/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline.expect
index eb34b94..2341156 100644
--- a/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline.expect
@@ -1,5 +1,7 @@
-extension E<T> (){}
-on T (){}
+extension E<T> on T {
+  T Function(T) get f => (T t) => t;
+}
+
 method1<S>(S s) {}
 method2<S extends dynamic>(S s) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c47013a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43591.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+extension E<T> on T {
+  T Function(T) get f => (T t) => t;
+}
+
+main() {}
+method1<S>(S s) {}
+method2<S extends dynamic>(S s) {}
+throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline.expect
index 2f9718a..5f989b2 100644
--- a/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline.expect
@@ -1,6 +1,9 @@
-extension Test<T> (){}
-on T (){}
+extension Test<T> on T {
+  T Function(T) get test => (a) => this;
+}
+
 class Foo<S extends num> {
   void test1(S x) {}
 }
+
 void main() {}
diff --git a/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..9aaf1c7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/language_issue1182.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Foo<S extends num> {
+  void test1(S x) {}
+}
+
+extension Test<T> on T {
+  T Function(T) get test => (a) => this;
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.textual_outline.expect
index d664bd6..98dd013 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.textual_outline.expect
@@ -20,8 +20,9 @@
   X fieldOfN;
   Y fieldOfN2;
 }
-extension P ;
-on Foo (){}
+extension P on Foo {
+  static int staticFieldOfE;
+}
 int? nullableTopLevelField;
 late
 int lateTopLevelField;
@@ -65,6 +66,10 @@
   late
   Y fieldOfM9;
 }
-extension Q ;
-on Foo (){}
+extension Q on Foo {
+  static int? staticFieldOfQ;
+  static late int ;
+  lateStaticFieldOfQ;
+  static int staticFieldOfQInitialized = 42;
+}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline.expect
index 78062c2..abb5f99 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline.expect
@@ -1,6 +1,9 @@
 class Class {
   Class method() => this;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  Class extensionMethod() => this;
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..abb5f99
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_cascade.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class Class {
+  Class method() => this;
+}
+
+extension Extension on Class {
+  Class extensionMethod() => this;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline.expect
index 438dfcd..13b04f9 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline.expect
@@ -4,19 +4,42 @@
   Class1 get property1 => new Class1();
   Class2 get property2 => new Class2();
 }
-extension Extension1 ;
-on Class1 (){}
+
+extension Extension1 on Class1 {
+  Class1? get nullable1 => property1;
+  void set nullable1(Class1? value) {}
+  Class1 nonNullable1Method() => nonNullable1;
+  Class1? operator [](Class1? key) => nullable1;
+  void operator []=(Class1? key, Class1? value) {}
+  Class1? operator +(int value) => nullable1;
+  Class1? operator -() => nullable1;
+  Class1 get nonNullable1 => property1;
+  Class2 get nonNullable2 => property2;
+}
+
 class Class2 {
   Class2 get property => this;
   void set property(Class2 value) {}
 }
-extension Extension2 ;
-on Class2 (){}
+
+extension Extension2 on Class2 {
+  Class2 nonNullable2Method() => nonNullable2;
+  Class2 operator [](Class2? key) => property;
+  void operator []=(Class2? key, Class2? value) => property;
+  Class2 operator +(int value) => property;
+  Class2 operator -() => property;
+  Class2 get nonNullable2 => property;
+  void set nonNullable2(Class2 value) {}
+}
+
 class Class3 {
   Class2? get property => null;
 }
-extension Extension3 ;
-on Class3 (){}
+
+extension Extension3 on Class3 {
+  Class2? operator [](Class3? key) => property;
+}
+
 main() {}
 void propertyAccess(Class1? n1) {}
 void indexAccess(Class1? n1, Class2? n2, Class3? n3) {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..79f7c01
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,48 @@
+class Class1 {
+  Class1? get property => null;
+  Class1 get property1 => new Class1();
+  Class2 get property2 => new Class2();
+  void set property(Class1? value) {}
+}
+
+class Class2 {
+  Class2 get property => this;
+  void set property(Class2 value) {}
+}
+
+class Class3 {
+  Class2? get property => null;
+}
+
+extension Extension1 on Class1 {
+  Class1? get nullable1 => property1;
+  Class1? operator +(int value) => nullable1;
+  Class1? operator -() => nullable1;
+  Class1? operator [](Class1? key) => nullable1;
+  Class1 get nonNullable1 => property1;
+  Class1 nonNullable1Method() => nonNullable1;
+  Class2 get nonNullable2 => property2;
+  void operator []=(Class1? key, Class1? value) {}
+  void set nullable1(Class1? value) {}
+}
+
+extension Extension2 on Class2 {
+  Class2 get nonNullable2 => property;
+  Class2 nonNullable2Method() => nonNullable2;
+  Class2 operator +(int value) => property;
+  Class2 operator -() => property;
+  Class2 operator [](Class2? key) => property;
+  void operator []=(Class2? key, Class2? value) => property;
+  void set nonNullable2(Class2 value) {}
+}
+
+extension Extension3 on Class3 {
+  Class2? operator [](Class3? key) => property;
+}
+
+main() {}
+void ifNull(Class1? n1) {}
+void indexAccess(Class1? n1, Class2? n2, Class3? n3) {}
+void operatorAccess(Class1? n1, Class2? n2) {}
+void propertyAccess(Class1? n1) {}
+void throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline.expect
index 438dfcd..13b04f9 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline.expect
@@ -4,19 +4,42 @@
   Class1 get property1 => new Class1();
   Class2 get property2 => new Class2();
 }
-extension Extension1 ;
-on Class1 (){}
+
+extension Extension1 on Class1 {
+  Class1? get nullable1 => property1;
+  void set nullable1(Class1? value) {}
+  Class1 nonNullable1Method() => nonNullable1;
+  Class1? operator [](Class1? key) => nullable1;
+  void operator []=(Class1? key, Class1? value) {}
+  Class1? operator +(int value) => nullable1;
+  Class1? operator -() => nullable1;
+  Class1 get nonNullable1 => property1;
+  Class2 get nonNullable2 => property2;
+}
+
 class Class2 {
   Class2 get property => this;
   void set property(Class2 value) {}
 }
-extension Extension2 ;
-on Class2 (){}
+
+extension Extension2 on Class2 {
+  Class2 nonNullable2Method() => nonNullable2;
+  Class2 operator [](Class2? key) => property;
+  void operator []=(Class2? key, Class2? value) => property;
+  Class2 operator +(int value) => property;
+  Class2 operator -() => property;
+  Class2 get nonNullable2 => property;
+  void set nonNullable2(Class2 value) {}
+}
+
 class Class3 {
   Class2? get property => null;
 }
-extension Extension3 ;
-on Class3 (){}
+
+extension Extension3 on Class3 {
+  Class2? operator [](Class3? key) => property;
+}
+
 main() {}
 void propertyAccess(Class1? n1) {}
 void indexAccess(Class1? n1, Class2? n2, Class3? n3) {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..79f7c01
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,48 @@
+class Class1 {
+  Class1? get property => null;
+  Class1 get property1 => new Class1();
+  Class2 get property2 => new Class2();
+  void set property(Class1? value) {}
+}
+
+class Class2 {
+  Class2 get property => this;
+  void set property(Class2 value) {}
+}
+
+class Class3 {
+  Class2? get property => null;
+}
+
+extension Extension1 on Class1 {
+  Class1? get nullable1 => property1;
+  Class1? operator +(int value) => nullable1;
+  Class1? operator -() => nullable1;
+  Class1? operator [](Class1? key) => nullable1;
+  Class1 get nonNullable1 => property1;
+  Class1 nonNullable1Method() => nonNullable1;
+  Class2 get nonNullable2 => property2;
+  void operator []=(Class1? key, Class1? value) {}
+  void set nullable1(Class1? value) {}
+}
+
+extension Extension2 on Class2 {
+  Class2 get nonNullable2 => property;
+  Class2 nonNullable2Method() => nonNullable2;
+  Class2 operator +(int value) => property;
+  Class2 operator -() => property;
+  Class2 operator [](Class2? key) => property;
+  void operator []=(Class2? key, Class2? value) => property;
+  void set nonNullable2(Class2 value) {}
+}
+
+extension Extension3 on Class3 {
+  Class2? operator [](Class3? key) => property;
+}
+
+main() {}
+void ifNull(Class1? n1) {}
+void indexAccess(Class1? n1, Class2? n2, Class3? n3) {}
+void operatorAccess(Class1? n1, Class2? n2) {}
+void propertyAccess(Class1? n1) {}
+void throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline.expect
index e3e40af..2be2b70 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline.expect
@@ -3,9 +3,14 @@
   int operator [](int index) => index;
   void operator []=(int index, int value) {}
 }
+
 class Class2 {
   int field = 42;
 }
-extension Extension ;
-on Class2 (){}
+
+extension Extension on Class2 {
+  int operator [](int index) => field;
+  void operator []=(int index, int value) {}
+}
+
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2be2b70
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.textual_outline_modelled.expect
@@ -0,0 +1,16 @@
+class Class1 {
+  Class2? get field => null;
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+class Class2 {
+  int field = 42;
+}
+
+extension Extension on Class2 {
+  int operator [](int index) => field;
+  void operator []=(int index, int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline.expect
index 8bd081e..3eef1e7 100644
--- a/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline.expect
@@ -1,8 +1,10 @@
 class A {
   String text = "";
 }
-extension on ;
-A;
-? { String get text => "Lily was here"; }
+
+extension on A? {
+  String get text => "Lily was here";
+}
+
 void main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ff2587a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+class A {
+  String text = "";
+}
+
+expect(expected, actual) {}
+
+extension on A? {
+  String get text => "Lily was here";
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline.expect
index f75f2e0..ff978cb 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline.expect
@@ -3,8 +3,11 @@
   void set setter(String v) {}
   void operator []=(int index, String value) {}
 }
-extension on ;
-C;
-? { void set setter(String v) { this?.m = v; } void operator []=(int index, String value) { this?.m = '$index$value'; } }
+
+extension on C? {
+  void set setter(String v) {}
+  void operator []=(int index, String value) {}
+}
+
 main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7a84dd6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.textual_outline_modelled.expect
@@ -0,0 +1,14 @@
+class C {
+  String m = "";
+  void operator []=(int index, String value) {}
+  void set setter(String v) {}
+}
+
+expect(expected, actual) {}
+
+extension on C? {
+  void operator []=(int index, String value) {}
+  void set setter(String v) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline.expect
index cbd0809..6f73b5c 100644
--- a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline.expect
@@ -6,8 +6,20 @@
   Function get functionGetter => () {};
   void Function() get functionTypeGetter => () {};
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  int operator +(int value) => 0;
+  int operator -() => 0;
+  int operator [](int index) => 0;
+  void operator []=(int index, int value) {}
+  int call() => 0;
+  int get extensionProperty => 0;
+  void set extensionProperty(int value) {}
+  int extensionMethod() => 0;
+  Function get extensionFunctionGetter => () {};
+  void Function() get extensionFunctionTypeGetter => () {};
+}
+
 Function? get nullableFunction => () {};
 void Function()? get nullableFunctionType => () {};
 int? get nullableInt => 0;
@@ -47,6 +59,7 @@
 var topLevelExtensionFunctionTypeExplicitCall = nullableClass.call();
 var topLevelExtensionFunctionTypeTearOff = nullableClass.call;
 var topLevelExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
-var topLevelExtensionFunctionTypeGetter = nullableClass.extensionFunctionTypeGetter();
+var topLevelExtensionFunctionTypeGetter =
+    nullableClass.extensionFunctionTypeGetter();
 test() {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fe7c996
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/potentially_nullable_access.dart.textual_outline_modelled.expect
@@ -0,0 +1,66 @@
+Class? get nullableClass => new Class();
+Function? get nullableFunction => () {};
+Map<dynamic, dynamic>? get nullableMap => {};
+
+class Class {
+  Function functionField = () {};
+  Function get functionGetter => () {};
+  int method() => 0;
+  int property = 0;
+  void Function() functionTypeField = () {};
+  void Function() get functionTypeGetter => () {};
+}
+
+extension Extension on Class {
+  Function get extensionFunctionGetter => () {};
+  int call() => 0;
+  int extensionMethod() => 0;
+  int get extensionProperty => 0;
+  int operator +(int value) => 0;
+  int operator -() => 0;
+  int operator [](int index) => 0;
+  void Function() get extensionFunctionTypeGetter => () {};
+  void operator []=(int index, int value) {}
+  void set extensionProperty(int value) {}
+}
+
+int? get nullableInt => 0;
+main() {}
+test() {}
+var topLevelBinary = nullableInt + 0;
+var topLevelExtensionBinary = nullableClass + 0;
+var topLevelExtensionFunctionGetter = nullableClass.extensionFunctionGetter();
+var topLevelExtensionFunctionTypeExplicitCall = nullableClass.call();
+var topLevelExtensionFunctionTypeGetter =
+    nullableClass.extensionFunctionTypeGetter();
+var topLevelExtensionFunctionTypeImplicitCall = nullableClass();
+var topLevelExtensionFunctionTypeTearOff = nullableClass.call;
+var topLevelExtensionIndexGet = nullableClass[0];
+var topLevelExtensionIndexGetSet = nullableClass[0] += 1;
+var topLevelExtensionIndexSet = nullableClass[0] = 1;
+var topLevelExtensionMethodInvocation = nullableClass.extensionMethod();
+var topLevelExtensionMethodTearOff = nullableClass.extensionMethod;
+var topLevelExtensionPropertyGet = nullableClass.extensionProperty;
+var topLevelExtensionPropertyGetSet = nullableClass.extensionProperty += 1;
+var topLevelExtensionPropertySet = nullableClass.extensionProperty = 1;
+var topLevelExtensionUnary = -nullableClass;
+var topLevelFunctionExplicitCall = nullableFunction.call();
+var topLevelFunctionField = nullableClass.functionField();
+var topLevelFunctionGetter = nullableClass.functionGetter();
+var topLevelFunctionImplicitCall = nullableFunction();
+var topLevelFunctionTearOff = nullableFunction.call;
+var topLevelFunctionTypeExplicitCall = nullableFunctionType.call();
+var topLevelFunctionTypeField = nullableClass.functionTypeField();
+var topLevelFunctionTypeGetter = nullableClass.functionTypeGetter();
+var topLevelFunctionTypeImplicitCall = nullableFunctionType();
+var topLevelFunctionTypeTearOff = nullableFunctionType.call;
+var topLevelIndexGet = nullableMap[0];
+var topLevelIndexGetSet = nullableMap[0] += 1;
+var topLevelIndexSet = nullableMap[0] = 1;
+var topLevelMethodInvocation = nullableClass.method();
+var topLevelMethodTearOff = nullableClass.method;
+var topLevelPropertyGet = nullableClass.property;
+var topLevelPropertyGetSet = nullableClass.property += 1;
+var topLevelPropertySet = nullableClass.property = 1;
+var topLevelUnary = -nullableInt;
+void Function()? get nullableFunctionType => () {};
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart
new file mode 100644
index 0000000..9b143d6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart
@@ -0,0 +1,232 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+bool b = true;
+
+abstract class Map<K, V> {
+  V operator [](K index);
+  void operator []=(K index, V value);
+}
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+  Class operator +(Class cls) => cls;
+
+  void indexGetSetForEffect(Map<Class, Class> map) {
+    late final Class self;
+    if (b) self = this;
+    map[this] ??= this;
+    map[self] ??= self;
+
+    map[this] = this;
+    map[self] = self;
+
+    map[this];
+    map[self];
+
+    map[this] += this;
+    map[self] += self;
+  }
+
+  void indexGetSetForValue(Map<Class, Class> map) {
+    late final Class self;
+    if (b) self = this;
+    var v;
+    v = map[this] ??= this;
+    v = map[self] ??= self;
+
+    v = map[this] = this;
+    v = map[self] = self;
+
+    v = map[this];
+    v = map[self];
+
+    v = map[this] += this;
+    v = map[self] += self;
+  }
+
+  void implicitExtensionGetSetForEffect(int i) {
+    late final Class self;
+    if (b) self = this;
+    i[this] ??= this;
+    i[self] ??= self;
+
+    i[this] = this;
+    i[self] = self;
+
+    i[this];
+    i[self];
+
+    i[this] += this;
+    i[self] += self;
+  }
+
+  void implicitExtensionGetSetForValue(int i) {
+    late final Class self;
+    if (b) self = this;
+    var v;
+    v = i[this] ??= this;
+    v = i[self] ??= self;
+
+    v = i[this] = this;
+    v = i[self] = self;
+
+    v = i[this];
+    v = i[self];
+
+    v = i[this] += this;
+    v = i[self] += self;
+  }
+
+  void explicitExtensionGetSetForEffect(int i) {
+    late final Class self;
+    if (b) self = this;
+    Extension(i)[this] ??= this;
+    Extension(i)[self] ??= self;
+
+    Extension(i)[this] = this;
+    Extension(i)[self] = self;
+
+    Extension(i)[this];
+    Extension(i)[self];
+
+    Extension(i)[this] += this;
+    Extension(i)[self] += self;
+  }
+
+  void explicitExtensionGetSetForValue(int i) {
+    late final Class self;
+    if (b) self = this;
+    var v;
+    v = Extension(i)[this] ??= this;
+    v = Extension(i)[self] ??= self;
+
+    v = Extension(i)[this] = this;
+    v = Extension(i)[self] = self;
+
+    v = Extension(i)[this];
+    v = Extension(i)[self];
+
+    v = Extension(i)[this] += this;
+    v = Extension(i)[self] += self;
+  }
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {
+    late final Class self;
+    if (b) self = this;
+    super[this] ??= this;
+    super[self] ??= self;
+
+    super[this] = this;
+    super[self] = self;
+
+    super[this];
+    super[self];
+
+    super[this] += this;
+    super[self] += self;
+  }
+
+  void superIndexGetSetForValue() {
+    late final Class self;
+    if (b) self = this;
+    var v;
+    v = super[this] ??= this;
+    v = super[self] ??= self;
+
+    v = super[this] = this;
+    v = super[self] = self;
+
+    v = super[this];
+    v = super[self];
+
+    v = super[this] += this;
+    v = super[self] += self;
+  }
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+
+  void implicitExtensionGetSetForEffect() {
+    late final Class2 self;
+    if (b) self = this;
+    this[this] ??= this;
+    self[self] ??= self;
+
+    this[this] = this;
+    self[self] = self;
+
+    this[this];
+    self[self];
+
+    this[this] += this;
+    self[self] += self;
+  }
+
+  void implicitExtensionGetSetForValue() {
+    late final Class2 self;
+    if (b) self = this;
+    var v;
+    v = this[this] ??= this;
+    v = self[self] ??= self;
+
+    v = this[this] = this;
+    v = self[self] = self;
+
+    v = this[this];
+    v = self[self];
+
+    v = this[this] += this;
+    v = self[self] += self;
+  }
+
+  void explicitExtensionGetSetForEffect() {
+    late final Class2 self;
+    if (b) self = this;
+    Extension2(this)[this] ??= this;
+    Extension2(self)[self] ??= self;
+
+    Extension2(this)[this] = this;
+    Extension2(self)[self] = self;
+
+    Extension2(this)[this];
+    Extension2(self)[self];
+
+    Extension2(this)[this] += this;
+    Extension2(self)[self] += self;
+  }
+
+  void explicitExtensionGetSetForValue() {
+    late final Class2 self;
+    if (b) self = this;
+    var v;
+    v = Extension2(this)[this] ??= this;
+    v = Extension2(self)[self] ??= self;
+
+    v = Extension2(this)[this] = this;
+    v = Extension2(self)[self] = self;
+
+    v = Extension2(this)[this];
+    v = Extension2(self)[self];
+
+    v = Extension2(this)[this] += this;
+    v = Extension2(self)[self] += self;
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.outline.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.outline.expect
new file mode 100644
index 0000000..f44d475
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.outline.expect
@@ -0,0 +1,73 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    ;
+  operator [](self::Class cls) → self::Class
+    ;
+  operator []=(self::Class cls, self::Class value) → void
+    ;
+  operator +(self::Class cls) → self::Class
+    ;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void
+    ;
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void
+    ;
+  method implicitExtensionGetSetForEffect(core::int i) → void
+    ;
+  method implicitExtensionGetSetForValue(core::int i) → void
+    ;
+  method explicitExtensionGetSetForEffect(core::int i) → void
+    ;
+  method explicitExtensionGetSetForValue(core::int i) → void
+    ;
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    ;
+  method superIndexGetSetForEffect() → void
+    ;
+  method superIndexGetSetForValue() → void
+    ;
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    ;
+  method implicitExtensionGetSetForEffect() → void
+    ;
+  method implicitExtensionGetSetForValue() → void
+    ;
+  method explicitExtensionGetSetForEffect() → void
+    ;
+  method explicitExtensionGetSetForValue() → void
+    ;
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  ;
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void
+  ;
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  ;
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.expect
new file mode 100644
index 0000000..84d1907
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.expect
@@ -0,0 +1,334 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:25:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[this] ??= this;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:26:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[self] ??= self;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:42:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[this] ??= this;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:43:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[self] ??= self;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:58:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[this] ??= this;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:59:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[self] ??= self;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:75:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:76:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:91:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[this] ??= this;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:92:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[self] ??= self;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:108:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:109:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:126:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:127:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:143:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[this] ??= this;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:144:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[self] ??= self;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:168:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     this[this] ??= this;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:169:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     self[self] ??= self;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:185:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = this[this] ??= this;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:186:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = self[self] ??= self;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:201:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(this)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:202:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(self)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:218:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(this)[this] ??= this;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:219:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(self)[self] ??= self;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    : super core::Object::•()
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  operator [](self::Class cls) → self::Class
+    return new self::Class::•();
+  operator []=(self::Class cls, self::Class value) → void {}
+  operator +(self::Class cls) → self::Class
+    return cls;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final self::Map<self::Class, self::Class> #t1 = map in #t1.{self::Map::[]}(this).{core::Object::==}(null) ?{self::Class} #t1.{self::Map::[]=}(this, this) : null;
+    let final self::Map<self::Class, self::Class> #t2 = map in let final self::Class #t3 = self in #t2.{self::Map::[]}(#t3).{core::Object::==}(null) ?{self::Class} #t2.{self::Map::[]=}(#t3, self) : null;
+    map.{self::Map::[]=}(this, this);
+    map.{self::Map::[]=}(self, self);
+    map.{self::Map::[]}(this);
+    map.{self::Map::[]}(self);
+    let final self::Map<self::Class, self::Class> #t4 = map in #t4.{self::Map::[]=}(this, #t4.{self::Map::[]}(this).{self::Class::+}(this));
+    let final self::Map<self::Class, self::Class> #t5 = map in let final self::Class #t6 = self in #t5.{self::Map::[]=}(#t6, #t5.{self::Map::[]}(#t6).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Map<self::Class, self::Class> #t7 = map in let final self::Class #t8 = #t7.{self::Map::[]}(this) in #t8.{core::Object::==}(null) ?{self::Class} let final void #t9 = #t7.{self::Map::[]=}(this, this) in this : #t8;
+    v = let final self::Map<self::Class, self::Class> #t10 = map in let final self::Class #t11 = self in let final self::Class #t12 = #t10.{self::Map::[]}(#t11) in #t12.{core::Object::==}(null) ?{self::Class} let final self::Class #t13 = self in let final void #t14 = #t10.{self::Map::[]=}(#t11, #t13) in #t13 : #t12;
+    v = let final self::Map<self::Class, self::Class> #t15 = map in let final void #t16 = #t15.{self::Map::[]=}(this, this) in this;
+    v = let final self::Map<self::Class, self::Class> #t17 = map in let final self::Class #t18 = self in let final self::Class #t19 = self in let final void #t20 = #t17.{self::Map::[]=}(#t18, #t19) in #t19;
+    v = map.{self::Map::[]}(this);
+    v = map.{self::Map::[]}(self);
+    v = let final self::Map<self::Class, self::Class> #t21 = map in let final self::Class #t22 = #t21.{self::Map::[]}(this).{self::Class::+}(this) in let final void #t23 = #t21.{self::Map::[]=}(this, #t22) in #t22;
+    v = let final self::Map<self::Class, self::Class> #t24 = map in let final self::Class #t25 = self in let final self::Class #t26 = #t24.{self::Map::[]}(#t25).{self::Class::+}(self) in let final void #t27 = #t24.{self::Map::[]=}(#t25, #t26) in #t26;
+  }
+  method implicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t28 = i in self::Extension|[](#t28, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t28, this, this) : null;
+    let final core::int #t29 = i in let final self::Class #t30 = self in self::Extension|[](#t29, #t30).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t29, #t30, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t31 = i in self::Extension|[]=(#t31, this, self::Extension|[](#t31, this).{self::Class::+}(this));
+    let final core::int #t32 = i in let final self::Class #t33 = self in self::Extension|[]=(#t32, #t33, self::Extension|[](#t32, #t33).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t34 = i in let final self::Class #t35 = self::Extension|[](#t34, this) in #t35.{core::Object::==}(null) ?{self::Class} let final void #t36 = self::Extension|[]=(#t34, this, this) in this : #t35;
+    v = let final core::int #t37 = i in let final self::Class #t38 = self in let final self::Class #t39 = self::Extension|[](#t37, #t38) in #t39.{core::Object::==}(null) ?{self::Class} let final self::Class #t40 = self in let final void #t41 = self::Extension|[]=(#t37, #t38, #t40) in #t40 : #t39;
+    v = let final core::int #t42 = i in let final void #t43 = self::Extension|[]=(#t42, this, this) in this;
+    v = let final core::int #t44 = i in let final self::Class #t45 = self in let final self::Class #t46 = self in let final void #t47 = self::Extension|[]=(#t44, #t45, #t46) in #t46;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t48 = i in let final self::Class #t49 = self::Extension|[](#t48, this).{self::Class::+}(this) in let final void #t50 = self::Extension|[]=(#t48, this, #t49) in #t49;
+    v = let final core::int #t51 = i in let final self::Class #t52 = self in let final self::Class #t53 = self::Extension|[](#t51, #t52).{self::Class::+}(self) in let final void #t54 = self::Extension|[]=(#t51, #t52, #t53) in #t53;
+  }
+  method explicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t55 = i in self::Extension|[](#t55, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t55, this, this) : null;
+    let final core::int #t56 = i in let final self::Class #t57 = self in self::Extension|[](#t56, #t57).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t56, #t57, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t58 = i in self::Extension|[]=(#t58, this, self::Extension|[](#t58, this).{self::Class::+}(this));
+    let final core::int #t59 = i in let final self::Class #t60 = self in self::Extension|[]=(#t59, #t60, self::Extension|[](#t59, #t60).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t61 = i in let final self::Class #t62 = self::Extension|[](#t61, this) in #t62.{core::Object::==}(null) ?{self::Class} let final void #t63 = self::Extension|[]=(#t61, this, this) in this : #t62;
+    v = let final core::int #t64 = i in let final self::Class #t65 = self in let final self::Class #t66 = self::Extension|[](#t64, #t65) in #t66.{core::Object::==}(null) ?{self::Class} let final self::Class #t67 = self in let final void #t68 = self::Extension|[]=(#t64, #t65, #t67) in #t67 : #t66;
+    v = let final core::int #t69 = i in let final void #t70 = self::Extension|[]=(#t69, this, this) in this;
+    v = let final core::int #t71 = i in let final self::Class #t72 = self in let final void #t73 = self::Extension|[]=(#t71, self, #t72) in #t72;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t74 = i in let final self::Class #t75 = self::Extension|[](#t74, this).{self::Class::+}(this) in let final void #t76 = self::Extension|[]=(#t74, this, #t75) in #t75;
+    v = let final core::int #t77 = i in let final self::Class #t78 = self in let final self::Class #t79 = self::Extension|[](#t77, #t78).{self::Class::+}(self) in let final void #t80 = self::Extension|[]=(#t77, #t78, #t79) in #t79;
+  }
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    super.{self::Class::[]}(this).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(this, this) : null;
+    let final self::Class #t81 = self in super.{self::Class::[]}(#t81).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(#t81, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    let final self::Class #t82 = self in super.{self::Class::[]=}(#t82, super.{self::Class::[]}(#t82).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class #t83 = super.{self::Class::[]}(this) in #t83.{core::Object::==}(null) ?{self::Class} let final void #t84 = super.{self::Class::[]=}(this, this) in this : #t83;
+    v = let final self::Class #t85 = self in let final self::Class #t86 = super.{self::Class::[]}(#t85) in #t86.{core::Object::==}(null) ?{self::Class} let final self::Class #t87 = self in let final void #t88 = super.{self::Class::[]=}(#t85, #t87) in #t87 : #t86;
+    v = let final void #t89 = super.{self::Class::[]=}(this, this) in this;
+    v = let final self::Class #t90 = self in let final self::Class #t91 = self in let final void #t92 = super.{self::Class::[]=}(#t90, #t91) in #t91;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class #t93 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t94 = super.{self::Class::[]=}(this, #t93) in #t93;
+    v = let final self::Class #t95 = self in let final self::Class #t96 = super.{self::Class::[]}(#t95).{self::Class::+}(self) in let final void #t97 = super.{self::Class::[]=}(#t95, #t96) in #t96;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    : super core::Object::•()
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t98 = self in let final self::Class2 #t99 = self in self::Extension2|[](#t98, #t99).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t98, #t99, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t100 = self in let final self::Class2 #t101 = self in self::Extension2|[]=(#t100, #t101, self::Extension2|[](#t100, #t101).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t102 = self::Extension2|[](this, this) in #t102.{core::Object::==}(null) ?{self::Class2} let final void #t103 = self::Extension2|[]=(this, this, this) in this : #t102;
+    v = let final self::Class2 #t104 = self in let final self::Class2 #t105 = self in let final self::Class2 #t106 = self::Extension2|[](#t104, #t105) in #t106.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t107 = self in let final void #t108 = self::Extension2|[]=(#t104, #t105, #t107) in #t107 : #t106;
+    v = let final void #t109 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t110 = self in let final self::Class2 #t111 = self in let final self::Class2 #t112 = self in let final void #t113 = self::Extension2|[]=(#t110, #t111, #t112) in #t112;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t114 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t115 = self::Extension2|[]=(this, this, #t114) in #t114;
+    v = let final self::Class2 #t116 = self in let final self::Class2 #t117 = self in let final self::Class2 #t118 = self::Extension2|[](#t116, #t117).{self::Class2::+}(self) in let final void #t119 = self::Extension2|[]=(#t116, #t117, #t118) in #t118;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t120 = self in let final self::Class2 #t121 = self in self::Extension2|[](#t120, #t121).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t120, #t121, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t122 = self in let final self::Class2 #t123 = self in self::Extension2|[]=(#t122, #t123, self::Extension2|[](#t122, #t123).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t124 = self::Extension2|[](this, this) in #t124.{core::Object::==}(null) ?{self::Class2} let final void #t125 = self::Extension2|[]=(this, this, this) in this : #t124;
+    v = let final self::Class2 #t126 = self in let final self::Class2 #t127 = self in let final self::Class2 #t128 = self::Extension2|[](#t126, #t127) in #t128.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t129 = self in let final void #t130 = self::Extension2|[]=(#t126, #t127, #t129) in #t129 : #t128;
+    v = let final void #t131 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t132 = self in let final self::Class2 #t133 = self in let final void #t134 = self::Extension2|[]=(#t132, self, #t133) in #t133;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t135 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t136 = self::Extension2|[]=(this, this, #t135) in #t135;
+    v = let final self::Class2 #t137 = self in let final self::Class2 #t138 = self in let final self::Class2 #t139 = self::Extension2|[](#t137, #t138).{self::Class2::+}(self) in let final void #t140 = self::Extension2|[]=(#t137, #t138, #t139) in #t139;
+  }
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b = true;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void {}
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.transformed.expect
new file mode 100644
index 0000000..84d1907
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.strong.transformed.expect
@@ -0,0 +1,334 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:25:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[this] ??= this;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:26:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[self] ??= self;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:42:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[this] ??= this;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:43:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[self] ??= self;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:58:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[this] ??= this;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:59:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[self] ??= self;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:75:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:76:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:91:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[this] ??= this;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:92:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[self] ??= self;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:108:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:109:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:126:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:127:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:143:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[this] ??= this;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:144:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[self] ??= self;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:168:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     this[this] ??= this;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:169:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     self[self] ??= self;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:185:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = this[this] ??= this;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:186:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = self[self] ??= self;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:201:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(this)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:202:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(self)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:218:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(this)[this] ??= this;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:219:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(self)[self] ??= self;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    : super core::Object::•()
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  operator [](self::Class cls) → self::Class
+    return new self::Class::•();
+  operator []=(self::Class cls, self::Class value) → void {}
+  operator +(self::Class cls) → self::Class
+    return cls;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final self::Map<self::Class, self::Class> #t1 = map in #t1.{self::Map::[]}(this).{core::Object::==}(null) ?{self::Class} #t1.{self::Map::[]=}(this, this) : null;
+    let final self::Map<self::Class, self::Class> #t2 = map in let final self::Class #t3 = self in #t2.{self::Map::[]}(#t3).{core::Object::==}(null) ?{self::Class} #t2.{self::Map::[]=}(#t3, self) : null;
+    map.{self::Map::[]=}(this, this);
+    map.{self::Map::[]=}(self, self);
+    map.{self::Map::[]}(this);
+    map.{self::Map::[]}(self);
+    let final self::Map<self::Class, self::Class> #t4 = map in #t4.{self::Map::[]=}(this, #t4.{self::Map::[]}(this).{self::Class::+}(this));
+    let final self::Map<self::Class, self::Class> #t5 = map in let final self::Class #t6 = self in #t5.{self::Map::[]=}(#t6, #t5.{self::Map::[]}(#t6).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Map<self::Class, self::Class> #t7 = map in let final self::Class #t8 = #t7.{self::Map::[]}(this) in #t8.{core::Object::==}(null) ?{self::Class} let final void #t9 = #t7.{self::Map::[]=}(this, this) in this : #t8;
+    v = let final self::Map<self::Class, self::Class> #t10 = map in let final self::Class #t11 = self in let final self::Class #t12 = #t10.{self::Map::[]}(#t11) in #t12.{core::Object::==}(null) ?{self::Class} let final self::Class #t13 = self in let final void #t14 = #t10.{self::Map::[]=}(#t11, #t13) in #t13 : #t12;
+    v = let final self::Map<self::Class, self::Class> #t15 = map in let final void #t16 = #t15.{self::Map::[]=}(this, this) in this;
+    v = let final self::Map<self::Class, self::Class> #t17 = map in let final self::Class #t18 = self in let final self::Class #t19 = self in let final void #t20 = #t17.{self::Map::[]=}(#t18, #t19) in #t19;
+    v = map.{self::Map::[]}(this);
+    v = map.{self::Map::[]}(self);
+    v = let final self::Map<self::Class, self::Class> #t21 = map in let final self::Class #t22 = #t21.{self::Map::[]}(this).{self::Class::+}(this) in let final void #t23 = #t21.{self::Map::[]=}(this, #t22) in #t22;
+    v = let final self::Map<self::Class, self::Class> #t24 = map in let final self::Class #t25 = self in let final self::Class #t26 = #t24.{self::Map::[]}(#t25).{self::Class::+}(self) in let final void #t27 = #t24.{self::Map::[]=}(#t25, #t26) in #t26;
+  }
+  method implicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t28 = i in self::Extension|[](#t28, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t28, this, this) : null;
+    let final core::int #t29 = i in let final self::Class #t30 = self in self::Extension|[](#t29, #t30).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t29, #t30, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t31 = i in self::Extension|[]=(#t31, this, self::Extension|[](#t31, this).{self::Class::+}(this));
+    let final core::int #t32 = i in let final self::Class #t33 = self in self::Extension|[]=(#t32, #t33, self::Extension|[](#t32, #t33).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t34 = i in let final self::Class #t35 = self::Extension|[](#t34, this) in #t35.{core::Object::==}(null) ?{self::Class} let final void #t36 = self::Extension|[]=(#t34, this, this) in this : #t35;
+    v = let final core::int #t37 = i in let final self::Class #t38 = self in let final self::Class #t39 = self::Extension|[](#t37, #t38) in #t39.{core::Object::==}(null) ?{self::Class} let final self::Class #t40 = self in let final void #t41 = self::Extension|[]=(#t37, #t38, #t40) in #t40 : #t39;
+    v = let final core::int #t42 = i in let final void #t43 = self::Extension|[]=(#t42, this, this) in this;
+    v = let final core::int #t44 = i in let final self::Class #t45 = self in let final self::Class #t46 = self in let final void #t47 = self::Extension|[]=(#t44, #t45, #t46) in #t46;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t48 = i in let final self::Class #t49 = self::Extension|[](#t48, this).{self::Class::+}(this) in let final void #t50 = self::Extension|[]=(#t48, this, #t49) in #t49;
+    v = let final core::int #t51 = i in let final self::Class #t52 = self in let final self::Class #t53 = self::Extension|[](#t51, #t52).{self::Class::+}(self) in let final void #t54 = self::Extension|[]=(#t51, #t52, #t53) in #t53;
+  }
+  method explicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t55 = i in self::Extension|[](#t55, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t55, this, this) : null;
+    let final core::int #t56 = i in let final self::Class #t57 = self in self::Extension|[](#t56, #t57).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t56, #t57, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t58 = i in self::Extension|[]=(#t58, this, self::Extension|[](#t58, this).{self::Class::+}(this));
+    let final core::int #t59 = i in let final self::Class #t60 = self in self::Extension|[]=(#t59, #t60, self::Extension|[](#t59, #t60).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t61 = i in let final self::Class #t62 = self::Extension|[](#t61, this) in #t62.{core::Object::==}(null) ?{self::Class} let final void #t63 = self::Extension|[]=(#t61, this, this) in this : #t62;
+    v = let final core::int #t64 = i in let final self::Class #t65 = self in let final self::Class #t66 = self::Extension|[](#t64, #t65) in #t66.{core::Object::==}(null) ?{self::Class} let final self::Class #t67 = self in let final void #t68 = self::Extension|[]=(#t64, #t65, #t67) in #t67 : #t66;
+    v = let final core::int #t69 = i in let final void #t70 = self::Extension|[]=(#t69, this, this) in this;
+    v = let final core::int #t71 = i in let final self::Class #t72 = self in let final void #t73 = self::Extension|[]=(#t71, self, #t72) in #t72;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t74 = i in let final self::Class #t75 = self::Extension|[](#t74, this).{self::Class::+}(this) in let final void #t76 = self::Extension|[]=(#t74, this, #t75) in #t75;
+    v = let final core::int #t77 = i in let final self::Class #t78 = self in let final self::Class #t79 = self::Extension|[](#t77, #t78).{self::Class::+}(self) in let final void #t80 = self::Extension|[]=(#t77, #t78, #t79) in #t79;
+  }
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    super.{self::Class::[]}(this).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(this, this) : null;
+    let final self::Class #t81 = self in super.{self::Class::[]}(#t81).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(#t81, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    let final self::Class #t82 = self in super.{self::Class::[]=}(#t82, super.{self::Class::[]}(#t82).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class #t83 = super.{self::Class::[]}(this) in #t83.{core::Object::==}(null) ?{self::Class} let final void #t84 = super.{self::Class::[]=}(this, this) in this : #t83;
+    v = let final self::Class #t85 = self in let final self::Class #t86 = super.{self::Class::[]}(#t85) in #t86.{core::Object::==}(null) ?{self::Class} let final self::Class #t87 = self in let final void #t88 = super.{self::Class::[]=}(#t85, #t87) in #t87 : #t86;
+    v = let final void #t89 = super.{self::Class::[]=}(this, this) in this;
+    v = let final self::Class #t90 = self in let final self::Class #t91 = self in let final void #t92 = super.{self::Class::[]=}(#t90, #t91) in #t91;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class #t93 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t94 = super.{self::Class::[]=}(this, #t93) in #t93;
+    v = let final self::Class #t95 = self in let final self::Class #t96 = super.{self::Class::[]}(#t95).{self::Class::+}(self) in let final void #t97 = super.{self::Class::[]=}(#t95, #t96) in #t96;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    : super core::Object::•()
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t98 = self in let final self::Class2 #t99 = self in self::Extension2|[](#t98, #t99).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t98, #t99, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t100 = self in let final self::Class2 #t101 = self in self::Extension2|[]=(#t100, #t101, self::Extension2|[](#t100, #t101).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t102 = self::Extension2|[](this, this) in #t102.{core::Object::==}(null) ?{self::Class2} let final void #t103 = self::Extension2|[]=(this, this, this) in this : #t102;
+    v = let final self::Class2 #t104 = self in let final self::Class2 #t105 = self in let final self::Class2 #t106 = self::Extension2|[](#t104, #t105) in #t106.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t107 = self in let final void #t108 = self::Extension2|[]=(#t104, #t105, #t107) in #t107 : #t106;
+    v = let final void #t109 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t110 = self in let final self::Class2 #t111 = self in let final self::Class2 #t112 = self in let final void #t113 = self::Extension2|[]=(#t110, #t111, #t112) in #t112;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t114 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t115 = self::Extension2|[]=(this, this, #t114) in #t114;
+    v = let final self::Class2 #t116 = self in let final self::Class2 #t117 = self in let final self::Class2 #t118 = self::Extension2|[](#t116, #t117).{self::Class2::+}(self) in let final void #t119 = self::Extension2|[]=(#t116, #t117, #t118) in #t118;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t120 = self in let final self::Class2 #t121 = self in self::Extension2|[](#t120, #t121).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t120, #t121, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t122 = self in let final self::Class2 #t123 = self in self::Extension2|[]=(#t122, #t123, self::Extension2|[](#t122, #t123).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t124 = self::Extension2|[](this, this) in #t124.{core::Object::==}(null) ?{self::Class2} let final void #t125 = self::Extension2|[]=(this, this, this) in this : #t124;
+    v = let final self::Class2 #t126 = self in let final self::Class2 #t127 = self in let final self::Class2 #t128 = self::Extension2|[](#t126, #t127) in #t128.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t129 = self in let final void #t130 = self::Extension2|[]=(#t126, #t127, #t129) in #t129 : #t128;
+    v = let final void #t131 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t132 = self in let final self::Class2 #t133 = self in let final void #t134 = self::Extension2|[]=(#t132, self, #t133) in #t133;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t135 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t136 = self::Extension2|[]=(this, this, #t135) in #t135;
+    v = let final self::Class2 #t137 = self in let final self::Class2 #t138 = self in let final self::Class2 #t139 = self::Extension2|[](#t137, #t138).{self::Class2::+}(self) in let final void #t140 = self::Extension2|[]=(#t137, #t138, #t139) in #t139;
+  }
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b = true;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void {}
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline.expect
new file mode 100644
index 0000000..beb5b6c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline.expect
@@ -0,0 +1,43 @@
+bool b = true;
+
+abstract class Map<K, V> {
+  V operator [](K index);
+  void operator []=(K index, V value);
+}
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+  Class operator +(Class cls) => cls;
+  void indexGetSetForEffect(Map<Class, Class> map) {}
+  void indexGetSetForValue(Map<Class, Class> map) {}
+  void implicitExtensionGetSetForEffect(int i) {}
+  void implicitExtensionGetSetForValue(int i) {}
+  void explicitExtensionGetSetForEffect(int i) {}
+  void explicitExtensionGetSetForValue(int i) {}
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {}
+  void superIndexGetSetForValue() {}
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+  void implicitExtensionGetSetForEffect() {}
+  void implicitExtensionGetSetForValue() {}
+  void explicitExtensionGetSetForEffect() {}
+  void explicitExtensionGetSetForValue() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5088689
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.textual_outline_modelled.expect
@@ -0,0 +1,43 @@
+abstract class Map<K, V> {
+  V operator [](K index);
+  void operator []=(K index, V value);
+}
+
+bool b = true;
+
+class Class {
+  Class operator +(Class cls) => cls;
+  Class operator [](Class cls) => new Class();
+  void explicitExtensionGetSetForEffect(int i) {}
+  void explicitExtensionGetSetForValue(int i) {}
+  void implicitExtensionGetSetForEffect(int i) {}
+  void implicitExtensionGetSetForValue(int i) {}
+  void indexGetSetForEffect(Map<Class, Class> map) {}
+  void indexGetSetForValue(Map<Class, Class> map) {}
+  void operator []=(Class cls, Class value) {}
+}
+
+class Class2 {
+  Class2 operator +(Class2 cls) => cls;
+  void explicitExtensionGetSetForEffect() {}
+  void explicitExtensionGetSetForValue() {}
+  void implicitExtensionGetSetForEffect() {}
+  void implicitExtensionGetSetForValue() {}
+}
+
+class Subclass extends Class {
+  void superIndexGetSetForEffect() {}
+  void superIndexGetSetForValue() {}
+}
+
+extension Extension on int {
+  Class operator [](Class cls) => new Class();
+  void operator []=(Class cls, Class value) {}
+}
+
+extension Extension2 on Class2 {
+  Class2 operator [](Class2 cls) => new Class2();
+  void operator []=(Class2 cls, Class2 value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.expect
new file mode 100644
index 0000000..84d1907
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.expect
@@ -0,0 +1,334 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:25:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[this] ??= this;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:26:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[self] ??= self;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:42:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[this] ??= this;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:43:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[self] ??= self;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:58:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[this] ??= this;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:59:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[self] ??= self;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:75:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:76:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:91:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[this] ??= this;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:92:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[self] ??= self;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:108:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:109:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:126:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:127:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:143:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[this] ??= this;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:144:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[self] ??= self;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:168:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     this[this] ??= this;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:169:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     self[self] ??= self;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:185:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = this[this] ??= this;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:186:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = self[self] ??= self;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:201:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(this)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:202:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(self)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:218:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(this)[this] ??= this;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:219:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(self)[self] ??= self;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    : super core::Object::•()
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  operator [](self::Class cls) → self::Class
+    return new self::Class::•();
+  operator []=(self::Class cls, self::Class value) → void {}
+  operator +(self::Class cls) → self::Class
+    return cls;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final self::Map<self::Class, self::Class> #t1 = map in #t1.{self::Map::[]}(this).{core::Object::==}(null) ?{self::Class} #t1.{self::Map::[]=}(this, this) : null;
+    let final self::Map<self::Class, self::Class> #t2 = map in let final self::Class #t3 = self in #t2.{self::Map::[]}(#t3).{core::Object::==}(null) ?{self::Class} #t2.{self::Map::[]=}(#t3, self) : null;
+    map.{self::Map::[]=}(this, this);
+    map.{self::Map::[]=}(self, self);
+    map.{self::Map::[]}(this);
+    map.{self::Map::[]}(self);
+    let final self::Map<self::Class, self::Class> #t4 = map in #t4.{self::Map::[]=}(this, #t4.{self::Map::[]}(this).{self::Class::+}(this));
+    let final self::Map<self::Class, self::Class> #t5 = map in let final self::Class #t6 = self in #t5.{self::Map::[]=}(#t6, #t5.{self::Map::[]}(#t6).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Map<self::Class, self::Class> #t7 = map in let final self::Class #t8 = #t7.{self::Map::[]}(this) in #t8.{core::Object::==}(null) ?{self::Class} let final void #t9 = #t7.{self::Map::[]=}(this, this) in this : #t8;
+    v = let final self::Map<self::Class, self::Class> #t10 = map in let final self::Class #t11 = self in let final self::Class #t12 = #t10.{self::Map::[]}(#t11) in #t12.{core::Object::==}(null) ?{self::Class} let final self::Class #t13 = self in let final void #t14 = #t10.{self::Map::[]=}(#t11, #t13) in #t13 : #t12;
+    v = let final self::Map<self::Class, self::Class> #t15 = map in let final void #t16 = #t15.{self::Map::[]=}(this, this) in this;
+    v = let final self::Map<self::Class, self::Class> #t17 = map in let final self::Class #t18 = self in let final self::Class #t19 = self in let final void #t20 = #t17.{self::Map::[]=}(#t18, #t19) in #t19;
+    v = map.{self::Map::[]}(this);
+    v = map.{self::Map::[]}(self);
+    v = let final self::Map<self::Class, self::Class> #t21 = map in let final self::Class #t22 = #t21.{self::Map::[]}(this).{self::Class::+}(this) in let final void #t23 = #t21.{self::Map::[]=}(this, #t22) in #t22;
+    v = let final self::Map<self::Class, self::Class> #t24 = map in let final self::Class #t25 = self in let final self::Class #t26 = #t24.{self::Map::[]}(#t25).{self::Class::+}(self) in let final void #t27 = #t24.{self::Map::[]=}(#t25, #t26) in #t26;
+  }
+  method implicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t28 = i in self::Extension|[](#t28, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t28, this, this) : null;
+    let final core::int #t29 = i in let final self::Class #t30 = self in self::Extension|[](#t29, #t30).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t29, #t30, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t31 = i in self::Extension|[]=(#t31, this, self::Extension|[](#t31, this).{self::Class::+}(this));
+    let final core::int #t32 = i in let final self::Class #t33 = self in self::Extension|[]=(#t32, #t33, self::Extension|[](#t32, #t33).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t34 = i in let final self::Class #t35 = self::Extension|[](#t34, this) in #t35.{core::Object::==}(null) ?{self::Class} let final void #t36 = self::Extension|[]=(#t34, this, this) in this : #t35;
+    v = let final core::int #t37 = i in let final self::Class #t38 = self in let final self::Class #t39 = self::Extension|[](#t37, #t38) in #t39.{core::Object::==}(null) ?{self::Class} let final self::Class #t40 = self in let final void #t41 = self::Extension|[]=(#t37, #t38, #t40) in #t40 : #t39;
+    v = let final core::int #t42 = i in let final void #t43 = self::Extension|[]=(#t42, this, this) in this;
+    v = let final core::int #t44 = i in let final self::Class #t45 = self in let final self::Class #t46 = self in let final void #t47 = self::Extension|[]=(#t44, #t45, #t46) in #t46;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t48 = i in let final self::Class #t49 = self::Extension|[](#t48, this).{self::Class::+}(this) in let final void #t50 = self::Extension|[]=(#t48, this, #t49) in #t49;
+    v = let final core::int #t51 = i in let final self::Class #t52 = self in let final self::Class #t53 = self::Extension|[](#t51, #t52).{self::Class::+}(self) in let final void #t54 = self::Extension|[]=(#t51, #t52, #t53) in #t53;
+  }
+  method explicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t55 = i in self::Extension|[](#t55, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t55, this, this) : null;
+    let final core::int #t56 = i in let final self::Class #t57 = self in self::Extension|[](#t56, #t57).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t56, #t57, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t58 = i in self::Extension|[]=(#t58, this, self::Extension|[](#t58, this).{self::Class::+}(this));
+    let final core::int #t59 = i in let final self::Class #t60 = self in self::Extension|[]=(#t59, #t60, self::Extension|[](#t59, #t60).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t61 = i in let final self::Class #t62 = self::Extension|[](#t61, this) in #t62.{core::Object::==}(null) ?{self::Class} let final void #t63 = self::Extension|[]=(#t61, this, this) in this : #t62;
+    v = let final core::int #t64 = i in let final self::Class #t65 = self in let final self::Class #t66 = self::Extension|[](#t64, #t65) in #t66.{core::Object::==}(null) ?{self::Class} let final self::Class #t67 = self in let final void #t68 = self::Extension|[]=(#t64, #t65, #t67) in #t67 : #t66;
+    v = let final core::int #t69 = i in let final void #t70 = self::Extension|[]=(#t69, this, this) in this;
+    v = let final core::int #t71 = i in let final self::Class #t72 = self in let final void #t73 = self::Extension|[]=(#t71, self, #t72) in #t72;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t74 = i in let final self::Class #t75 = self::Extension|[](#t74, this).{self::Class::+}(this) in let final void #t76 = self::Extension|[]=(#t74, this, #t75) in #t75;
+    v = let final core::int #t77 = i in let final self::Class #t78 = self in let final self::Class #t79 = self::Extension|[](#t77, #t78).{self::Class::+}(self) in let final void #t80 = self::Extension|[]=(#t77, #t78, #t79) in #t79;
+  }
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    super.{self::Class::[]}(this).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(this, this) : null;
+    let final self::Class #t81 = self in super.{self::Class::[]}(#t81).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(#t81, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    let final self::Class #t82 = self in super.{self::Class::[]=}(#t82, super.{self::Class::[]}(#t82).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class #t83 = super.{self::Class::[]}(this) in #t83.{core::Object::==}(null) ?{self::Class} let final void #t84 = super.{self::Class::[]=}(this, this) in this : #t83;
+    v = let final self::Class #t85 = self in let final self::Class #t86 = super.{self::Class::[]}(#t85) in #t86.{core::Object::==}(null) ?{self::Class} let final self::Class #t87 = self in let final void #t88 = super.{self::Class::[]=}(#t85, #t87) in #t87 : #t86;
+    v = let final void #t89 = super.{self::Class::[]=}(this, this) in this;
+    v = let final self::Class #t90 = self in let final self::Class #t91 = self in let final void #t92 = super.{self::Class::[]=}(#t90, #t91) in #t91;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class #t93 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t94 = super.{self::Class::[]=}(this, #t93) in #t93;
+    v = let final self::Class #t95 = self in let final self::Class #t96 = super.{self::Class::[]}(#t95).{self::Class::+}(self) in let final void #t97 = super.{self::Class::[]=}(#t95, #t96) in #t96;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    : super core::Object::•()
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t98 = self in let final self::Class2 #t99 = self in self::Extension2|[](#t98, #t99).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t98, #t99, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t100 = self in let final self::Class2 #t101 = self in self::Extension2|[]=(#t100, #t101, self::Extension2|[](#t100, #t101).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t102 = self::Extension2|[](this, this) in #t102.{core::Object::==}(null) ?{self::Class2} let final void #t103 = self::Extension2|[]=(this, this, this) in this : #t102;
+    v = let final self::Class2 #t104 = self in let final self::Class2 #t105 = self in let final self::Class2 #t106 = self::Extension2|[](#t104, #t105) in #t106.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t107 = self in let final void #t108 = self::Extension2|[]=(#t104, #t105, #t107) in #t107 : #t106;
+    v = let final void #t109 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t110 = self in let final self::Class2 #t111 = self in let final self::Class2 #t112 = self in let final void #t113 = self::Extension2|[]=(#t110, #t111, #t112) in #t112;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t114 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t115 = self::Extension2|[]=(this, this, #t114) in #t114;
+    v = let final self::Class2 #t116 = self in let final self::Class2 #t117 = self in let final self::Class2 #t118 = self::Extension2|[](#t116, #t117).{self::Class2::+}(self) in let final void #t119 = self::Extension2|[]=(#t116, #t117, #t118) in #t118;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t120 = self in let final self::Class2 #t121 = self in self::Extension2|[](#t120, #t121).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t120, #t121, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t122 = self in let final self::Class2 #t123 = self in self::Extension2|[]=(#t122, #t123, self::Extension2|[](#t122, #t123).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t124 = self::Extension2|[](this, this) in #t124.{core::Object::==}(null) ?{self::Class2} let final void #t125 = self::Extension2|[]=(this, this, this) in this : #t124;
+    v = let final self::Class2 #t126 = self in let final self::Class2 #t127 = self in let final self::Class2 #t128 = self::Extension2|[](#t126, #t127) in #t128.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t129 = self in let final void #t130 = self::Extension2|[]=(#t126, #t127, #t129) in #t129 : #t128;
+    v = let final void #t131 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t132 = self in let final self::Class2 #t133 = self in let final void #t134 = self::Extension2|[]=(#t132, self, #t133) in #t133;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t135 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t136 = self::Extension2|[]=(this, this, #t135) in #t135;
+    v = let final self::Class2 #t137 = self in let final self::Class2 #t138 = self in let final self::Class2 #t139 = self::Extension2|[](#t137, #t138).{self::Class2::+}(self) in let final void #t140 = self::Extension2|[]=(#t137, #t138, #t139) in #t139;
+  }
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b = true;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void {}
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.transformed.expect
new file mode 100644
index 0000000..84d1907
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/pure_index_expressions.dart.weak.transformed.expect
@@ -0,0 +1,334 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:25:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[this] ??= this;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:26:8: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     map[self] ??= self;
+//        ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:42:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[this] ??= this;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:43:12: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = map[self] ??= self;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:58:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[this] ??= this;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:59:6: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     i[self] ??= self;
+//      ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:75:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:76:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = i[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:91:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[this] ??= this;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:92:17: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension(i)[self] ??= self;
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:108:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:109:21: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension(i)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:126:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[this] ??= this;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:127:10: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     super[self] ??= self;
+//          ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:143:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[this] ??= this;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:144:14: Warning: Operand of null-aware operation '??=' has type 'Class' which excludes null.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = super[self] ??= self;
+//              ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:168:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     this[this] ??= this;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:169:9: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     self[self] ??= self;
+//         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:185:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = this[this] ??= this;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:186:13: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = self[self] ??= self;
+//             ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:201:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(this)[this] ??= this;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:202:21: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     Extension2(self)[self] ??= self;
+//                     ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:218:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(this)[this] ??= this;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd/pure_index_expressions.dart:219:25: Warning: Operand of null-aware operation '??=' has type 'Class2' which excludes null.
+//  - 'Class2' is from 'pkg/front_end/testcases/nnbd/pure_index_expressions.dart'.
+//     v = Extension2(self)[self] ??= self;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Map<K extends core::Object? = dynamic, V extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::Map<self::Map::K%, self::Map::V%>
+    : super core::Object::•()
+    ;
+  abstract operator [](generic-covariant-impl self::Map::K% index) → self::Map::V%;
+  abstract operator []=(generic-covariant-impl self::Map::K% index, generic-covariant-impl self::Map::V% value) → void;
+}
+class Class extends core::Object {
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  operator [](self::Class cls) → self::Class
+    return new self::Class::•();
+  operator []=(self::Class cls, self::Class value) → void {}
+  operator +(self::Class cls) → self::Class
+    return cls;
+  method indexGetSetForEffect(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final self::Map<self::Class, self::Class> #t1 = map in #t1.{self::Map::[]}(this).{core::Object::==}(null) ?{self::Class} #t1.{self::Map::[]=}(this, this) : null;
+    let final self::Map<self::Class, self::Class> #t2 = map in let final self::Class #t3 = self in #t2.{self::Map::[]}(#t3).{core::Object::==}(null) ?{self::Class} #t2.{self::Map::[]=}(#t3, self) : null;
+    map.{self::Map::[]=}(this, this);
+    map.{self::Map::[]=}(self, self);
+    map.{self::Map::[]}(this);
+    map.{self::Map::[]}(self);
+    let final self::Map<self::Class, self::Class> #t4 = map in #t4.{self::Map::[]=}(this, #t4.{self::Map::[]}(this).{self::Class::+}(this));
+    let final self::Map<self::Class, self::Class> #t5 = map in let final self::Class #t6 = self in #t5.{self::Map::[]=}(#t6, #t5.{self::Map::[]}(#t6).{self::Class::+}(self));
+  }
+  method indexGetSetForValue(self::Map<self::Class, self::Class> map) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Map<self::Class, self::Class> #t7 = map in let final self::Class #t8 = #t7.{self::Map::[]}(this) in #t8.{core::Object::==}(null) ?{self::Class} let final void #t9 = #t7.{self::Map::[]=}(this, this) in this : #t8;
+    v = let final self::Map<self::Class, self::Class> #t10 = map in let final self::Class #t11 = self in let final self::Class #t12 = #t10.{self::Map::[]}(#t11) in #t12.{core::Object::==}(null) ?{self::Class} let final self::Class #t13 = self in let final void #t14 = #t10.{self::Map::[]=}(#t11, #t13) in #t13 : #t12;
+    v = let final self::Map<self::Class, self::Class> #t15 = map in let final void #t16 = #t15.{self::Map::[]=}(this, this) in this;
+    v = let final self::Map<self::Class, self::Class> #t17 = map in let final self::Class #t18 = self in let final self::Class #t19 = self in let final void #t20 = #t17.{self::Map::[]=}(#t18, #t19) in #t19;
+    v = map.{self::Map::[]}(this);
+    v = map.{self::Map::[]}(self);
+    v = let final self::Map<self::Class, self::Class> #t21 = map in let final self::Class #t22 = #t21.{self::Map::[]}(this).{self::Class::+}(this) in let final void #t23 = #t21.{self::Map::[]=}(this, #t22) in #t22;
+    v = let final self::Map<self::Class, self::Class> #t24 = map in let final self::Class #t25 = self in let final self::Class #t26 = #t24.{self::Map::[]}(#t25).{self::Class::+}(self) in let final void #t27 = #t24.{self::Map::[]=}(#t25, #t26) in #t26;
+  }
+  method implicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t28 = i in self::Extension|[](#t28, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t28, this, this) : null;
+    let final core::int #t29 = i in let final self::Class #t30 = self in self::Extension|[](#t29, #t30).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t29, #t30, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t31 = i in self::Extension|[]=(#t31, this, self::Extension|[](#t31, this).{self::Class::+}(this));
+    let final core::int #t32 = i in let final self::Class #t33 = self in self::Extension|[]=(#t32, #t33, self::Extension|[](#t32, #t33).{self::Class::+}(self));
+  }
+  method implicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t34 = i in let final self::Class #t35 = self::Extension|[](#t34, this) in #t35.{core::Object::==}(null) ?{self::Class} let final void #t36 = self::Extension|[]=(#t34, this, this) in this : #t35;
+    v = let final core::int #t37 = i in let final self::Class #t38 = self in let final self::Class #t39 = self::Extension|[](#t37, #t38) in #t39.{core::Object::==}(null) ?{self::Class} let final self::Class #t40 = self in let final void #t41 = self::Extension|[]=(#t37, #t38, #t40) in #t40 : #t39;
+    v = let final core::int #t42 = i in let final void #t43 = self::Extension|[]=(#t42, this, this) in this;
+    v = let final core::int #t44 = i in let final self::Class #t45 = self in let final self::Class #t46 = self in let final void #t47 = self::Extension|[]=(#t44, #t45, #t46) in #t46;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t48 = i in let final self::Class #t49 = self::Extension|[](#t48, this).{self::Class::+}(this) in let final void #t50 = self::Extension|[]=(#t48, this, #t49) in #t49;
+    v = let final core::int #t51 = i in let final self::Class #t52 = self in let final self::Class #t53 = self::Extension|[](#t51, #t52).{self::Class::+}(self) in let final void #t54 = self::Extension|[]=(#t51, #t52, #t53) in #t53;
+  }
+  method explicitExtensionGetSetForEffect(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    let final core::int #t55 = i in self::Extension|[](#t55, this).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t55, this, this) : null;
+    let final core::int #t56 = i in let final self::Class #t57 = self in self::Extension|[](#t56, #t57).{core::Object::==}(null) ?{self::Class} self::Extension|[]=(#t56, #t57, self) : null;
+    self::Extension|[]=(i, this, this);
+    self::Extension|[]=(i, self, self);
+    self::Extension|[](i, this);
+    self::Extension|[](i, self);
+    let final core::int #t58 = i in self::Extension|[]=(#t58, this, self::Extension|[](#t58, this).{self::Class::+}(this));
+    let final core::int #t59 = i in let final self::Class #t60 = self in self::Extension|[]=(#t59, #t60, self::Extension|[](#t59, #t60).{self::Class::+}(self));
+  }
+  method explicitExtensionGetSetForValue(core::int i) → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final core::int #t61 = i in let final self::Class #t62 = self::Extension|[](#t61, this) in #t62.{core::Object::==}(null) ?{self::Class} let final void #t63 = self::Extension|[]=(#t61, this, this) in this : #t62;
+    v = let final core::int #t64 = i in let final self::Class #t65 = self in let final self::Class #t66 = self::Extension|[](#t64, #t65) in #t66.{core::Object::==}(null) ?{self::Class} let final self::Class #t67 = self in let final void #t68 = self::Extension|[]=(#t64, #t65, #t67) in #t67 : #t66;
+    v = let final core::int #t69 = i in let final void #t70 = self::Extension|[]=(#t69, this, this) in this;
+    v = let final core::int #t71 = i in let final self::Class #t72 = self in let final void #t73 = self::Extension|[]=(#t71, self, #t72) in #t72;
+    v = self::Extension|[](i, this);
+    v = self::Extension|[](i, self);
+    v = let final core::int #t74 = i in let final self::Class #t75 = self::Extension|[](#t74, this).{self::Class::+}(this) in let final void #t76 = self::Extension|[]=(#t74, this, #t75) in #t75;
+    v = let final core::int #t77 = i in let final self::Class #t78 = self in let final self::Class #t79 = self::Extension|[](#t77, #t78).{self::Class::+}(self) in let final void #t80 = self::Extension|[]=(#t77, #t78, #t79) in #t79;
+  }
+}
+class Subclass extends self::Class {
+  synthetic constructor •() → self::Subclass
+    : super self::Class::•()
+    ;
+  method superIndexGetSetForEffect() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    super.{self::Class::[]}(this).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(this, this) : null;
+    let final self::Class #t81 = self in super.{self::Class::[]}(#t81).{core::Object::==}(null) ?{self::Class} super.{self::Class::[]=}(#t81, self) : null;
+    super.{self::Class::[]=}(this, this);
+    super.{self::Class::[]=}(self, self);
+    super.{self::Class::[]}(this);
+    super.{self::Class::[]}(self);
+    super.{self::Class::[]=}(this, super.{self::Class::[]}(this).{self::Class::+}(this));
+    let final self::Class #t82 = self in super.{self::Class::[]=}(#t82, super.{self::Class::[]}(#t82).{self::Class::+}(self));
+  }
+  method superIndexGetSetForValue() → void {
+    late final self::Class self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class #t83 = super.{self::Class::[]}(this) in #t83.{core::Object::==}(null) ?{self::Class} let final void #t84 = super.{self::Class::[]=}(this, this) in this : #t83;
+    v = let final self::Class #t85 = self in let final self::Class #t86 = super.{self::Class::[]}(#t85) in #t86.{core::Object::==}(null) ?{self::Class} let final self::Class #t87 = self in let final void #t88 = super.{self::Class::[]=}(#t85, #t87) in #t87 : #t86;
+    v = let final void #t89 = super.{self::Class::[]=}(this, this) in this;
+    v = let final self::Class #t90 = self in let final self::Class #t91 = self in let final void #t92 = super.{self::Class::[]=}(#t90, #t91) in #t91;
+    v = super.{self::Class::[]}(this);
+    v = super.{self::Class::[]}(self);
+    v = let final self::Class #t93 = super.{self::Class::[]}(this).{self::Class::+}(this) in let final void #t94 = super.{self::Class::[]=}(this, #t93) in #t93;
+    v = let final self::Class #t95 = self in let final self::Class #t96 = super.{self::Class::[]}(#t95).{self::Class::+}(self) in let final void #t97 = super.{self::Class::[]=}(#t95, #t96) in #t96;
+  }
+}
+class Class2 extends core::Object {
+  synthetic constructor •() → self::Class2
+    : super core::Object::•()
+    ;
+  operator +(self::Class2 cls) → self::Class2
+    return cls;
+  method implicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t98 = self in let final self::Class2 #t99 = self in self::Extension2|[](#t98, #t99).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t98, #t99, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t100 = self in let final self::Class2 #t101 = self in self::Extension2|[]=(#t100, #t101, self::Extension2|[](#t100, #t101).{self::Class2::+}(self));
+  }
+  method implicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t102 = self::Extension2|[](this, this) in #t102.{core::Object::==}(null) ?{self::Class2} let final void #t103 = self::Extension2|[]=(this, this, this) in this : #t102;
+    v = let final self::Class2 #t104 = self in let final self::Class2 #t105 = self in let final self::Class2 #t106 = self::Extension2|[](#t104, #t105) in #t106.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t107 = self in let final void #t108 = self::Extension2|[]=(#t104, #t105, #t107) in #t107 : #t106;
+    v = let final void #t109 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t110 = self in let final self::Class2 #t111 = self in let final self::Class2 #t112 = self in let final void #t113 = self::Extension2|[]=(#t110, #t111, #t112) in #t112;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t114 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t115 = self::Extension2|[]=(this, this, #t114) in #t114;
+    v = let final self::Class2 #t116 = self in let final self::Class2 #t117 = self in let final self::Class2 #t118 = self::Extension2|[](#t116, #t117).{self::Class2::+}(self) in let final void #t119 = self::Extension2|[]=(#t116, #t117, #t118) in #t118;
+  }
+  method explicitExtensionGetSetForEffect() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    self::Extension2|[](this, this).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(this, this, this) : null;
+    let final self::Class2 #t120 = self in let final self::Class2 #t121 = self in self::Extension2|[](#t120, #t121).{core::Object::==}(null) ?{self::Class2} self::Extension2|[]=(#t120, #t121, self) : null;
+    self::Extension2|[]=(this, this, this);
+    self::Extension2|[]=(self, self, self);
+    self::Extension2|[](this, this);
+    self::Extension2|[](self, self);
+    self::Extension2|[]=(this, this, self::Extension2|[](this, this).{self::Class2::+}(this));
+    let final self::Class2 #t122 = self in let final self::Class2 #t123 = self in self::Extension2|[]=(#t122, #t123, self::Extension2|[](#t122, #t123).{self::Class2::+}(self));
+  }
+  method explicitExtensionGetSetForValue() → void {
+    late final self::Class2 self;
+    if(self::b)
+      self = this;
+    dynamic v;
+    v = let final self::Class2 #t124 = self::Extension2|[](this, this) in #t124.{core::Object::==}(null) ?{self::Class2} let final void #t125 = self::Extension2|[]=(this, this, this) in this : #t124;
+    v = let final self::Class2 #t126 = self in let final self::Class2 #t127 = self in let final self::Class2 #t128 = self::Extension2|[](#t126, #t127) in #t128.{core::Object::==}(null) ?{self::Class2} let final self::Class2 #t129 = self in let final void #t130 = self::Extension2|[]=(#t126, #t127, #t129) in #t129 : #t128;
+    v = let final void #t131 = self::Extension2|[]=(this, this, this) in this;
+    v = let final self::Class2 #t132 = self in let final self::Class2 #t133 = self in let final void #t134 = self::Extension2|[]=(#t132, self, #t133) in #t133;
+    v = self::Extension2|[](this, this);
+    v = self::Extension2|[](self, self);
+    v = let final self::Class2 #t135 = self::Extension2|[](this, this).{self::Class2::+}(this) in let final void #t136 = self::Extension2|[]=(this, this, #t135) in #t135;
+    v = let final self::Class2 #t137 = self in let final self::Class2 #t138 = self in let final self::Class2 #t139 = self::Extension2|[](#t137, #t138).{self::Class2::+}(self) in let final void #t140 = self::Extension2|[]=(#t137, #t138, #t139) in #t139;
+  }
+}
+extension Extension on core::int {
+  operator [] = self::Extension|[];
+  operator []= = self::Extension|[]=;
+}
+extension Extension2 on self::Class2 {
+  operator [] = self::Extension2|[];
+  operator []= = self::Extension2|[]=;
+}
+static field core::bool b = true;
+static method Extension|[](lowered final core::int #this, self::Class cls) → self::Class
+  return new self::Class::•();
+static method Extension|[]=(lowered final core::int #this, self::Class cls, self::Class value) → void {}
+static method Extension2|[](lowered final self::Class2 #this, self::Class2 cls) → self::Class2
+  return new self::Class2::•();
+static method Extension2|[]=(lowered final self::Class2 #this, self::Class2 cls, self::Class2 value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline.expect
index d51e2b9..e5febc5 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline.expect
@@ -1,11 +1,17 @@
-extension E ;
-on String (){}
-class A {
-  String operator[](int index) => "foo";
-  void operator[]=(int index, String value) {}
+extension E on String {
+  int get foo => 42;
+  void operator []=(int index, int value) {}
+  int operator [](int index) => 42;
 }
+
+class A {
+  String operator [](int index) => "foo";
+  void operator []=(int index, String value) {}
+}
+
 class B extends A {
   void test() {}
 }
+
 warning(String s, List<String> l, Map<String, int> m) {}
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..77eca74
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.textual_outline_modelled.expect
@@ -0,0 +1,17 @@
+class A {
+  String operator [](int index) => "foo";
+  void operator []=(int index, String value) {}
+}
+
+class B extends A {
+  void test() {}
+}
+
+extension E on String {
+  int get foo => 42;
+  int operator [](int index) => 42;
+  void operator []=(int index, int value) {}
+}
+
+main() {}
+warning(String s, List<String> l, Map<String, int> m) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline.expect
index 33f6302..14d2d75 100644
--- a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline.expect
@@ -2,8 +2,17 @@
 class Class {
   Class _field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  Class get field => _field;
+  void set field(Class value) {}
+  Class method() => field;
+  Class operator [](Class key) => field;
+  void operator []=(Class key, Class value) {}
+  Class operator +(int value) => field;
+  Class operator -() => field;
+}
+
 main() {}
 void propertyAccess(Class c) {}
 void indexAccess(Class c) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..027cbbc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_explicit_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+// @dart = 2.6
+class Class {
+  Class _field;
+}
+
+extension Extension on Class {
+  Class get field => _field;
+  Class method() => field;
+  Class operator +(int value) => field;
+  Class operator -() => field;
+  Class operator [](Class key) => field;
+  void operator []=(Class key, Class value) {}
+  void set field(Class value) {}
+}
+
+main() {}
+void ifNull(Class c) {}
+void indexAccess(Class c) {}
+void operatorAccess(Class c) {}
+void propertyAccess(Class c) {}
+void throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline.expect
index 33f6302..14d2d75 100644
--- a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline.expect
@@ -2,8 +2,17 @@
 class Class {
   Class _field;
 }
-extension Extension ;
-on Class (){}
+
+extension Extension on Class {
+  Class get field => _field;
+  void set field(Class value) {}
+  Class method() => field;
+  Class operator [](Class key) => field;
+  void operator []=(Class key, Class value) {}
+  Class operator +(int value) => field;
+  Class operator -() => field;
+}
+
 main() {}
 void propertyAccess(Class c) {}
 void indexAccess(Class c) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..027cbbc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/no_null_shorting_extension.dart.textual_outline_modelled.expect
@@ -0,0 +1,21 @@
+// @dart = 2.6
+class Class {
+  Class _field;
+}
+
+extension Extension on Class {
+  Class get field => _field;
+  Class method() => field;
+  Class operator +(int value) => field;
+  Class operator -() => field;
+  Class operator [](Class key) => field;
+  void operator []=(Class key, Class value) {}
+  void set field(Class value) {}
+}
+
+main() {}
+void ifNull(Class c) {}
+void indexAccess(Class c) {}
+void operatorAccess(Class c) {}
+void propertyAccess(Class c) {}
+void throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline.expect
index 72a0f5b..db630d4 100644
--- a/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline.expect
@@ -1,6 +1,8 @@
 import 'nullable_extension_on_opt_out_lib.dart';
-extension on ;
-A;
-? { String get text => "Lily was here"; }
+
+extension on A? {
+  String get text => "Lily was here";
+}
+
 void main() {}
 expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5294531
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/nullable_extension_on_opt_out.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+import 'nullable_extension_on_opt_out_lib.dart';
+
+expect(expected, actual) {}
+
+extension on A? {
+  String get text => "Lily was here";
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect
index 50ce9f2..7298d03 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect
@@ -1,45 +1,60 @@
 // @dart = 2.8
 import 'unsound_checks_lib.dart';
+
 isNullOptOut1(int i) => i == null;
 isNotNullOptOut1(int i) => i != null;
 isNullOptOut2(int i) => null == i;
 isNotNullOptOut2(int i) => null != i;
 ifNullOptOut(int i) => i ?? 42;
+
 class OptOutClass1 {}
-extension OptOutExtension ;
-on OptOutClass1 (){}
+
+extension OptOutExtension on OptOutClass1 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
 extensionIfNullOptOut1(int i) => OptOutExtension(new OptOutClass1())[i] ??= 42;
 extensionIfNullOptOut1ForEffect(int i) {}
 extensionIfNullOptOut2(int i) => new OptOutClass1()[i] ??= 42;
 extensionIfNullOptOut2ForEffect(int i) {}
+
 class OptOutClass2 {
   int operator [](int index) => index;
   void operator []=(int index, int value) {}
 }
+
 ifNullIndexSetOptOut(int i) => new OptOutClass2()[i] ??= 42;
 ifNullIndexSetOptOutForEffect(int i) {}
+
 class OptOutClass3 {
   int field;
   OptOutClass3(this.field);
 }
+
 ifNullPropertySetOptOut(int i) => new OptOutClass3(i).field ??= 42;
 ifNullPropertySetOptOutForEffect(int i) {}
 ifNullSetOptOut(int i) => i ??= 42;
 ifNullSetOptOutForEffect(int i) {}
+
 class OptOutSuperClass4 {
   int operator [](int index) => index;
   void operator []=(int index, int value) {}
 }
+
 class OptOutClass4 extends OptOutSuperClass4 {
   method(int i) => super[i] ??= 42;
   methodForEffect(int i) {}
 }
+
 ifNullSuperIndexSetOptOut(int i) => new OptOutClass4().method(i);
 ifNullSuperIndexSetOptOutForEffect(int i) {}
+
 class OptOutClass5 {
   int field;
   OptOutClass5(this.field);
 }
+
 nullAwareIfNullSetOptOut(int i) {}
 nullAwareIfNullSetOptOutForEffect(int i) {}
 isTestOptOut(int i) => i is int;
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f86f53b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline_modelled.expect
@@ -0,0 +1,60 @@
+// @dart = 2.8
+import 'unsound_checks_lib.dart';
+
+class OptOutClass1 {}
+
+class OptOutClass2 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+class OptOutClass3 {
+  OptOutClass3(this.field);
+  int field;
+}
+
+class OptOutClass4 extends OptOutSuperClass4 {
+  method(int i) => super[i] ??= 42;
+  methodForEffect(int i) {}
+}
+
+class OptOutClass5 {
+  OptOutClass5(this.field);
+  int field;
+}
+
+class OptOutSuperClass4 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+expect(expected, actual) {}
+
+extension OptOutExtension on OptOutClass1 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+extensionIfNullOptOut1(int i) => OptOutExtension(new OptOutClass1())[i] ??= 42;
+extensionIfNullOptOut1ForEffect(int i) {}
+extensionIfNullOptOut2(int i) => new OptOutClass1()[i] ??= 42;
+extensionIfNullOptOut2ForEffect(int i) {}
+ifNullIndexSetOptOut(int i) => new OptOutClass2()[i] ??= 42;
+ifNullIndexSetOptOutForEffect(int i) {}
+ifNullOptOut(int i) => i ?? 42;
+ifNullPropertySetOptOut(int i) => new OptOutClass3(i).field ??= 42;
+ifNullPropertySetOptOutForEffect(int i) {}
+ifNullSetOptOut(int i) => i ??= 42;
+ifNullSetOptOutForEffect(int i) {}
+ifNullSuperIndexSetOptOut(int i) => new OptOutClass4().method(i);
+ifNullSuperIndexSetOptOutForEffect(int i) {}
+isNotNullOptOut1(int i) => i != null;
+isNotNullOptOut2(int i) => null != i;
+isNotTestOptOut(int i) => i is! int;
+isNullOptOut1(int i) => i == null;
+isNullOptOut2(int i) => null == i;
+isTestOptOut(int i) => i is int;
+main() {}
+nullAwareIfNullSetOptOut(int i) {}
+nullAwareIfNullSetOptOutForEffect(int i) {}
+throws(void f(), [bool Function(Object) testException]) {}
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index b946481..901929c 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -20,73 +20,11 @@
 regress/issue_39091_2: EmptyOutput
 regress/utf_16_le_content.crash: EmptyOutput
 
-extensions/ambiguous: FormatterCrash
-extensions/annotations: FormatterCrash
-extensions/async_extensions: FormatterCrash
-extensions/bounds: FormatterCrash
-extensions/builtin_identifiers: FormatterCrash
-extensions/call_methods: FormatterCrash
-extensions/check_bounds: FormatterCrash
-extensions/compounds: FormatterCrash
-extensions/conflict_with_object: FormatterCrash
-extensions/conflicts: FormatterCrash
-extensions/default_values: FormatterCrash
-extensions/direct_instance_access: FormatterCrash
-extensions/direct_static_access: FormatterCrash
-extensions/dynamic_invoke: FormatterCrash
-extensions/explicit_extension_access: FormatterCrash
-extensions/explicit_extension_inference: FormatterCrash
-extensions/explicit_generic_extension_access: FormatterCrash
-extensions/explicit_invalid_access: FormatterCrash
-extensions/explicit_this: FormatterCrash
-extensions/extension_call: FormatterCrash
 extensions/extension_constructor: FormatterCrash
 extensions/extension_field_with_type_parameter_usage: FormatterCrash
-extensions/extension_member_conflict: FormatterCrash
-extensions/extension_methods: FormatterCrash
-extensions/extension_setter: FormatterCrash
-extensions/extension_setter_error: FormatterCrash
-extensions/generic_function_in_generic_extension: FormatterCrash
-extensions/getter_setter_conflict: FormatterCrash
-extensions/if_null: FormatterCrash
-extensions/implicit_extension_inference: FormatterCrash
-extensions/implicit_this: FormatterCrash
-extensions/index: FormatterCrash
-extensions/instance_access: FormatterCrash
-extensions/instance_access_of_static: FormatterCrash
-extensions/instance_members: FormatterCrash
-extensions/instance_tearoff: FormatterCrash
-extensions/internal_resolution: FormatterCrash
-extensions/invalid_explicit_access: FormatterCrash
-extensions/invalid_explicit_static_access: FormatterCrash
 extensions/issue38600: FormatterCrash
 extensions/issue38712: FormatterCrash
-extensions/issue38713: FormatterCrash
 extensions/issue38745: FormatterCrash
-extensions/issue38755: FormatterCrash
-extensions/issue38915: FormatterCrash
-extensions/issue39527: FormatterCrash
-extensions/issue39889: FormatterCrash
-extensions/issue40596: FormatterCrash
-extensions/issue40713: FormatterCrash
-extensions/issue40816: FormatterCrash
-extensions/issue43218: FormatterCrash
-extensions/language_issue1182: FormatterCrash
-extensions/missing_toplevel: FormatterCrash
-extensions/nested_on_types: FormatterCrash
-extensions/null_aware: FormatterCrash
-extensions/on_function_type: FormatterCrash
-extensions/on_type_inference: FormatterCrash
-extensions/on_type_variable_inference: FormatterCrash
-extensions/operators: FormatterCrash
-extensions/other_kinds: FormatterCrash
-extensions/static_access: FormatterCrash
-extensions/static_access_of_instance: FormatterCrash
-extensions/tear_offs: FormatterCrash
-extensions/type_variable_bound: FormatterCrash
-extensions/type_variables: FormatterCrash
-extensions/unnamed_extensions: FormatterCrash
-extensions/use_this: FormatterCrash
 general/annotation_eof: FormatterCrash
 general/bad_setter_abstract: FormatterCrash
 general/bug31124: FormatterCrash
@@ -112,19 +50,15 @@
 general/error_recovery/issue_39230.crash: FormatterCrash
 general/error_recovery/issue_39958_01: FormatterCrash
 general/function_type_default_value: FormatterCrash
-general/getter_vs_setter_type: FormatterCrash
 general/incomplete_field_formal_parameter: FormatterCrash
 general/invalid_operator2: FormatterCrash
 general/invalid_operator: FormatterCrash
-general/issue40242: FormatterCrash
 general/issue42997: FormatterCrash
 general/issue43363: FormatterCrash
 general/many_errors: FormatterCrash
 general/null_safety_invalid_experiment_and_language_version: FormatterCrash
-general/type_parameter_usage_in_static_method_in_extension: FormatterCrash
 general/type_parameters_on_void: FormatterCrash
 general/var_as_type_name: FormatterCrash
-general/well_boundness_checks_in_outline: FormatterCrash
 general_nnbd_opt_out/annotation_eof: FormatterCrash
 general_nnbd_opt_out/bad_setter_abstract: FormatterCrash
 general_nnbd_opt_out/bug31124: FormatterCrash
@@ -173,49 +107,24 @@
 late_lowering/uninitialized_non_nullable_late_fields: FormatterCrash
 nnbd/abstract_field_errors: FormatterCrash
 nnbd/covariant_late_field: FormatterCrash
-nnbd/extension_bounds: FormatterCrash
-nnbd/extension_never: FormatterCrash
-nnbd/extension_type_variable_bound: FormatterCrash
-nnbd/external_field_errors: FormatterCrash
-nnbd/external_fields: FormatterCrash
 nnbd/forbidden_supers: FormatterCrash
-nnbd/getter_vs_setter_type: FormatterCrash
 nnbd/getter_vs_setter_type_late: FormatterCrash
-nnbd/getter_vs_setter_type_nnbd: FormatterCrash
-nnbd/infer_if_null: FormatterCrash
 nnbd/inheritance_from_opt_in: FormatterCrash
 nnbd/issue40805: FormatterCrash
-nnbd/issue41349: FormatterCrash
 nnbd/issue41597: FormatterCrash
 nnbd/issue42967: FormatterCrash
-nnbd/issue43211: FormatterCrash
-nnbd/issue43278: FormatterCrash
 nnbd/issue43354: FormatterCrash
-nnbd/issue43591: FormatterCrash
-nnbd/language_issue1182: FormatterCrash
 nnbd/late: FormatterCrash
 nnbd/later: FormatterCrash
 nnbd/no_null_shorting_explicit_extension: FormatterCrash
 nnbd/no_null_shorting_extension: FormatterCrash
 nnbd/non_nullable_field_initialization: FormatterCrash
-nnbd/null_shorting_cascade: FormatterCrash
-nnbd/null_shorting_explicit_extension: FormatterCrash
-nnbd/null_shorting_extension: FormatterCrash
-nnbd/null_shorting_index: FormatterCrash
-nnbd/nullable_extension: FormatterCrash
-nnbd/nullable_setter: FormatterCrash
 nnbd/opt_out: FormatterCrash
 nnbd/potentially_non_nullable_field: FormatterCrash
-nnbd/potentially_nullable_access: FormatterCrash
-nnbd/strictly_non_nullable_warnings: FormatterCrash
 nnbd/uninitialized_non_nullable_late_fields: FormatterCrash
 nnbd_mixed/inheritance_from_opt_in: FormatterCrash
 nnbd_mixed/issue41597: FormatterCrash
-nnbd_mixed/no_null_shorting_explicit_extension: FormatterCrash
-nnbd_mixed/no_null_shorting_extension: FormatterCrash
 nnbd_mixed/null_safety_invalid_language_version: FormatterCrash
-nnbd_mixed/nullable_extension_on_opt_out: FormatterCrash
-nnbd_mixed/unsound_checks: FormatterCrash
 nonfunction_type_aliases/issue41501: FormatterCrash
 rasta/bad_redirection: FormatterCrash
 rasta/issue_000032: FormatterCrash
diff --git a/tools/VERSION b/tools/VERSION
index 45bf2ca..36ceaf1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 165
+PRERELEASE 166
 PRERELEASE_PATCH 0
\ No newline at end of file