[cfe] Include null check in shorting

Change-Id: Id0f96b5a2c40e37ded46c761612f2cbb8828ad18
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/161787
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
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 9d49286..993b176 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -2493,13 +2493,24 @@
       NullCheck node, DartType typeContext) {
     ExpressionInferenceResult operandResult = inferrer.inferExpression(
         node.operand, inferrer.computeNullable(typeContext), true);
-    node.operand = operandResult.expression..parent = node;
+    Link<NullAwareGuard> nullAwareGuards;
+    Expression operand;
+    DartType operandType;
+    if (inferrer.isNonNullableByDefault) {
+      nullAwareGuards = operandResult.nullAwareGuards;
+      operand = operandResult.nullAwareAction;
+      operandType = operandResult.nullAwareActionType;
+    } else {
+      operand = operandResult.expression;
+      operandType = operandResult.inferredType;
+    }
+    node.operand = operand..parent = node;
     reportNonNullableInNullAwareWarningIfNeeded(
-        operandResult.inferredType, "!", node.operand.fileOffset);
+        operandType, "!", node.operand.fileOffset);
     inferrer.flowAnalysis.nonNullAssert_end(node.operand);
-    DartType nonNullableResultType =
-        inferrer.computeNonNullable(operandResult.inferredType);
-    return new ExpressionInferenceResult(nonNullableResultType, node);
+    DartType nonNullableResultType = inferrer.computeNonNullable(operandType);
+    return inferrer.createNullAwareExpressionInferenceResult(
+        nonNullableResultType, node, nullAwareGuards);
   }
 
   ExpressionInferenceResult visitNullAwareMethodInvocation(
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart b/pkg/front_end/testcases/nnbd/null_shorting_index.dart
index ce82366..70f3567 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart
@@ -26,8 +26,6 @@
   c1?[0] = 1 + c1[0];
   c1?[0] += 1;
   c1?[0] += 1 + c1[0];
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
   ++c1?[0];
   c1?[0]++;
   c1?[0] ??= 1;
@@ -39,8 +37,6 @@
   c2?[0] = 1 + c2[0];
   c2?[0] += 1;
   c2?[0] += 1 + c2[0];
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
   ++c2?[0];
   c2?[0]++;
   c2?[0] ??= 1;
@@ -51,8 +47,6 @@
   Extension(c2)?[0] = 1 + Extension(c2)[0];
   Extension(c2)?[0] += 1;
   Extension(c2)?[0] += 1 + Extension(c2)[0];
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
   ++Extension(c2)?[0];
   Extension(c2)?[0]++;
   Extension(c2)?[0] ??= 1;
@@ -63,8 +57,6 @@
   c1?.field?[0] = 1 + c1[0];
   c1?.field?[0] += 1;
   c1?.field?[0] += 1 + c1[0];
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
   ++c1?.field?[0];
   c1?.field?[0]++;
   c1?.field?[0] ??= 1;
@@ -72,13 +64,11 @@
 
   Extension(c1?.field)?[0];
   Extension(c1?.field)?[0] = 1;
-  Extension(c1?.field)?[0] = 1 + Extension(c2)?[0]!;
+  Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
   Extension(c1?.field)?[0] += 1;
-  Extension(c1?.field)?[0] += 1 + Extension(c2)?[0]!;
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
+  Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
   ++Extension(c1?.field)?[0];
   Extension(c1?.field)?[0]++;
   Extension(c1?.field)?[0] ??= 1;
-  Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+  Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
index e1edbab..e391c8f 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
@@ -2,46 +2,58 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:31:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:32:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1 + c1[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:42:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:43:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1 + c2[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:52:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1;
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:53:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1 + Extension(c2)[1];
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:62:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1;
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:63:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1 + c1[1];
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:67:49: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:69:50: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:72:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c1?.field)?[0] ??= 1;
 //                        ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
-//   Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 //                        ^
 //
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:51: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
+//                                                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -111,11 +123,11 @@
   let final self::Class1? #t75 = c1 in #t75.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t76 = #t75{self::Class1}.{self::Class1::field} in #t76.{core::Object::==}(null) ?{core::int?} null : let final core::int #t77 = 0 in self::Extension|[](#t76{self::Class2}, #t77).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t76{self::Class2}, #t77, 1.{core::num::+}(c1{self::Class1}.{self::Class1::[]}(1))) : null;
   let final self::Class1? #t78 = c1 in #t78.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t79 = #t78{self::Class1}.{self::Class1::field} in #t79.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t79{self::Class2}, 0);
   let final self::Class1? #t80 = c1 in #t80.{core::Object::==}(null) ?{void} null : let final self::Class2? #t81 = #t80{self::Class1}.{self::Class1::field} in #t81.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t81{self::Class2}, 0, 1);
-  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0))!));
+  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0)!) as{ForNonNullableByDefault} core::int));
   let final self::Class1? #t85 = c1 in #t85.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t86 = #t85{self::Class1}.{self::Class1::field} in #t86.{core::Object::==}(null) ?{core::int?} null : let final core::int #t87 = 0 in self::Extension|[]=(#t86{self::Class2}, #t87, self::Extension|[](#t86{self::Class2}, #t87).{core::num::+}(1));
-  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0))!)));
+  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0)!) as{ForNonNullableByDefault} core::int)));
   let final self::Class1? #t92 = c1 in #t92.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t93 = #t92{self::Class1}.{self::Class1::field} in #t93.{core::Object::==}(null) ?{core::int?} null : let final core::int #t94 = 0 in let final core::int #t95 = self::Extension|[](#t93{self::Class2}, #t94).{core::num::+}(1) in let final void #t96 = self::Extension|[]=(#t93{self::Class2}, #t94, #t95) in #t95;
   let final self::Class1? #t97 = c1 in #t97.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t98 = #t97{self::Class1}.{self::Class1::field} in #t98.{core::Object::==}(null) ?{core::int?} null : let final core::int #t99 = 0 in self::Extension|[]=(#t98{self::Class2}, #t99, self::Extension|[](#t98{self::Class2}, #t99).{core::num::+}(1));
   let final self::Class1? #t100 = c1 in #t100.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t101 = #t100{self::Class1}.{self::Class1::field} in #t101.{core::Object::==}(null) ?{core::int?} null : let final core::int #t102 = 0 in self::Extension|[](#t101{self::Class2}, #t102).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t101{self::Class2}, #t102, 1) : null;
-  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1))!)) : null;
+  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1)!) as{ForNonNullableByDefault} core::int)) : null;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
index e1edbab..96a333d 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
@@ -2,46 +2,58 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:31:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:32:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1 + c1[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:42:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:43:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1 + c2[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:52:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1;
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:53:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1 + Extension(c2)[1];
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:62:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1;
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:63:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1 + c1[1];
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:67:49: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:69:50: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:72:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c1?.field)?[0] ??= 1;
 //                        ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
-//   Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 //                        ^
 //
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:51: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
+//                                                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -111,11 +123,11 @@
   let final self::Class1? #t75 = c1 in #t75.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t76 = #t75{self::Class1}.{self::Class1::field} in #t76.{core::Object::==}(null) ?{core::int?} null : let final core::int #t77 = 0 in self::Extension|[](#t76{self::Class2}, #t77).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t76{self::Class2}, #t77, 1.{core::num::+}(c1{self::Class1}.{self::Class1::[]}(1))) : null;
   let final self::Class1? #t78 = c1 in #t78.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t79 = #t78{self::Class1}.{self::Class1::field} in #t79.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t79{self::Class2}, 0);
   let final self::Class1? #t80 = c1 in #t80.{core::Object::==}(null) ?{void} null : let final self::Class2? #t81 = #t80{self::Class1}.{self::Class1::field} in #t81.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t81{self::Class2}, 0, 1);
-  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0))!));
-  let final self::Class1? #t85 = c1 in #t85.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t86 = #t85{self::Class1}.{self::Class1::field} in #t86.{core::Object::==}(null) ?{core::int?} null : let final core::int #t87 = 0 in self::Extension|[]=(#t86{self::Class2}, #t87, self::Extension|[](#t86{self::Class2}, #t87).{core::num::+}(1));
-  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0))!)));
-  let final self::Class1? #t92 = c1 in #t92.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t93 = #t92{self::Class1}.{self::Class1::field} in #t93.{core::Object::==}(null) ?{core::int?} null : let final core::int #t94 = 0 in let final core::int #t95 = self::Extension|[](#t93{self::Class2}, #t94).{core::num::+}(1) in let final void #t96 = self::Extension|[]=(#t93{self::Class2}, #t94, #t95) in #t95;
-  let final self::Class1? #t97 = c1 in #t97.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t98 = #t97{self::Class1}.{self::Class1::field} in #t98.{core::Object::==}(null) ?{core::int?} null : let final core::int #t99 = 0 in self::Extension|[]=(#t98{self::Class2}, #t99, self::Extension|[](#t98{self::Class2}, #t99).{core::num::+}(1));
-  let final self::Class1? #t100 = c1 in #t100.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t101 = #t100{self::Class1}.{self::Class1::field} in #t101.{core::Object::==}(null) ?{core::int?} null : let final core::int #t102 = 0 in self::Extension|[](#t101{self::Class2}, #t102).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t101{self::Class2}, #t102, 1) : null;
-  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1))!)) : null;
+  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}(let core::int? #t84 = let final self::Class2? #t85 = c2 in #t85.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t85{self::Class2}, 0)! in #t84.==(null) ?{core::int} #t84 as{ForNonNullableByDefault} core::int : #t84{core::int}));
+  let final self::Class1? #t86 = c1 in #t86.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t87 = #t86{self::Class1}.{self::Class1::field} in #t87.{core::Object::==}(null) ?{core::int?} null : let final core::int #t88 = 0 in self::Extension|[]=(#t87{self::Class2}, #t88, self::Extension|[](#t87{self::Class2}, #t88).{core::num::+}(1));
+  let final self::Class1? #t89 = c1 in #t89.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t90 = #t89{self::Class1}.{self::Class1::field} in #t90.{core::Object::==}(null) ?{core::int?} null : let final core::int #t91 = 0 in self::Extension|[]=(#t90{self::Class2}, #t91, self::Extension|[](#t90{self::Class2}, #t91).{core::num::+}(1.{core::num::+}(let core::int? #t92 = let final self::Class2? #t93 = c2 in #t93.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t93{self::Class2}, 0)! in #t92.==(null) ?{core::int} #t92 as{ForNonNullableByDefault} core::int : #t92{core::int})));
+  let final self::Class1? #t94 = c1 in #t94.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t95 = #t94{self::Class1}.{self::Class1::field} in #t95.{core::Object::==}(null) ?{core::int?} null : let final core::int #t96 = 0 in let final core::int #t97 = self::Extension|[](#t95{self::Class2}, #t96).{core::num::+}(1) in let final void #t98 = self::Extension|[]=(#t95{self::Class2}, #t96, #t97) in #t97;
+  let final self::Class1? #t99 = c1 in #t99.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t100 = #t99{self::Class1}.{self::Class1::field} in #t100.{core::Object::==}(null) ?{core::int?} null : let final core::int #t101 = 0 in self::Extension|[]=(#t100{self::Class2}, #t101, self::Extension|[](#t100{self::Class2}, #t101).{core::num::+}(1));
+  let final self::Class1? #t102 = c1 in #t102.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t103 = #t102{self::Class1}.{self::Class1::field} in #t103.{core::Object::==}(null) ?{core::int?} null : let final core::int #t104 = 0 in self::Extension|[](#t103{self::Class2}, #t104).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t103{self::Class2}, #t104, 1) : null;
+  let final self::Class1? #t105 = c1 in #t105.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t106 = #t105{self::Class1}.{self::Class1::field} in #t106.{core::Object::==}(null) ?{core::int?} null : let final core::int #t107 = 0 in self::Extension|[](#t106{self::Class2}, #t107).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t106{self::Class2}, #t107, 1.{core::num::+}(let core::int? #t108 = let final self::Class2? #t109 = c2 in #t109.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t109{self::Class2}, 1)! in #t108.==(null) ?{core::int} #t108 as{ForNonNullableByDefault} core::int : #t108{core::int})) : null;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect
index e1edbab..e391c8f 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect
@@ -2,46 +2,58 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:31:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:32:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1 + c1[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:42:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:43:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1 + c2[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:52:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1;
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:53:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1 + Extension(c2)[1];
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:62:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1;
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:63:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1 + c1[1];
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:67:49: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:69:50: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:72:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c1?.field)?[0] ??= 1;
 //                        ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
-//   Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 //                        ^
 //
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:51: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
+//                                                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -111,11 +123,11 @@
   let final self::Class1? #t75 = c1 in #t75.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t76 = #t75{self::Class1}.{self::Class1::field} in #t76.{core::Object::==}(null) ?{core::int?} null : let final core::int #t77 = 0 in self::Extension|[](#t76{self::Class2}, #t77).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t76{self::Class2}, #t77, 1.{core::num::+}(c1{self::Class1}.{self::Class1::[]}(1))) : null;
   let final self::Class1? #t78 = c1 in #t78.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t79 = #t78{self::Class1}.{self::Class1::field} in #t79.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t79{self::Class2}, 0);
   let final self::Class1? #t80 = c1 in #t80.{core::Object::==}(null) ?{void} null : let final self::Class2? #t81 = #t80{self::Class1}.{self::Class1::field} in #t81.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t81{self::Class2}, 0, 1);
-  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0))!));
+  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0)!) as{ForNonNullableByDefault} core::int));
   let final self::Class1? #t85 = c1 in #t85.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t86 = #t85{self::Class1}.{self::Class1::field} in #t86.{core::Object::==}(null) ?{core::int?} null : let final core::int #t87 = 0 in self::Extension|[]=(#t86{self::Class2}, #t87, self::Extension|[](#t86{self::Class2}, #t87).{core::num::+}(1));
-  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0))!)));
+  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0)!) as{ForNonNullableByDefault} core::int)));
   let final self::Class1? #t92 = c1 in #t92.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t93 = #t92{self::Class1}.{self::Class1::field} in #t93.{core::Object::==}(null) ?{core::int?} null : let final core::int #t94 = 0 in let final core::int #t95 = self::Extension|[](#t93{self::Class2}, #t94).{core::num::+}(1) in let final void #t96 = self::Extension|[]=(#t93{self::Class2}, #t94, #t95) in #t95;
   let final self::Class1? #t97 = c1 in #t97.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t98 = #t97{self::Class1}.{self::Class1::field} in #t98.{core::Object::==}(null) ?{core::int?} null : let final core::int #t99 = 0 in self::Extension|[]=(#t98{self::Class2}, #t99, self::Extension|[](#t98{self::Class2}, #t99).{core::num::+}(1));
   let final self::Class1? #t100 = c1 in #t100.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t101 = #t100{self::Class1}.{self::Class1::field} in #t101.{core::Object::==}(null) ?{core::int?} null : let final core::int #t102 = 0 in self::Extension|[](#t101{self::Class2}, #t102).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t101{self::Class2}, #t102, 1) : null;
-  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1))!)) : null;
+  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1)!) as{ForNonNullableByDefault} core::int)) : null;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect
index e1edbab..aeb32c1 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect
@@ -2,46 +2,58 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:31:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:32:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1 + c1[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:42:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:43:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1 + c2[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:52:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1;
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:53:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1 + Extension(c2)[1];
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:62:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1;
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:63:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1 + c1[1];
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:67:49: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:69:50: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:72:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c1?.field)?[0] ??= 1;
 //                        ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
-//   Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 //                        ^
 //
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:51: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
+//                                                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -111,11 +123,11 @@
   let final self::Class1? #t75 = c1 in #t75.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t76 = #t75{self::Class1}.{self::Class1::field} in #t76.{core::Object::==}(null) ?{core::int?} null : let final core::int #t77 = 0 in self::Extension|[](#t76{self::Class2}, #t77).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t76{self::Class2}, #t77, 1.{core::num::+}(c1{self::Class1}.{self::Class1::[]}(1))) : null;
   let final self::Class1? #t78 = c1 in #t78.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t79 = #t78{self::Class1}.{self::Class1::field} in #t79.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t79{self::Class2}, 0);
   let final self::Class1? #t80 = c1 in #t80.{core::Object::==}(null) ?{void} null : let final self::Class2? #t81 = #t80{self::Class1}.{self::Class1::field} in #t81.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t81{self::Class2}, 0, 1);
-  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0))!));
+  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}(let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0)!));
   let final self::Class1? #t85 = c1 in #t85.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t86 = #t85{self::Class1}.{self::Class1::field} in #t86.{core::Object::==}(null) ?{core::int?} null : let final core::int #t87 = 0 in self::Extension|[]=(#t86{self::Class2}, #t87, self::Extension|[](#t86{self::Class2}, #t87).{core::num::+}(1));
-  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0))!)));
+  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}(let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0)!)));
   let final self::Class1? #t92 = c1 in #t92.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t93 = #t92{self::Class1}.{self::Class1::field} in #t93.{core::Object::==}(null) ?{core::int?} null : let final core::int #t94 = 0 in let final core::int #t95 = self::Extension|[](#t93{self::Class2}, #t94).{core::num::+}(1) in let final void #t96 = self::Extension|[]=(#t93{self::Class2}, #t94, #t95) in #t95;
   let final self::Class1? #t97 = c1 in #t97.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t98 = #t97{self::Class1}.{self::Class1::field} in #t98.{core::Object::==}(null) ?{core::int?} null : let final core::int #t99 = 0 in self::Extension|[]=(#t98{self::Class2}, #t99, self::Extension|[](#t98{self::Class2}, #t99).{core::num::+}(1));
   let final self::Class1? #t100 = c1 in #t100.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t101 = #t100{self::Class1}.{self::Class1::field} in #t101.{core::Object::==}(null) ?{core::int?} null : let final core::int #t102 = 0 in self::Extension|[](#t101{self::Class2}, #t102).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t101{self::Class2}, #t102, 1) : null;
-  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1))!)) : null;
+  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}(let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1)!)) : null;
 }
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart b/pkg/front_end/testcases/nnbd/shorting_null_check.dart
new file mode 100644
index 0000000..1b45f04
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  int zero;
+  int? zeroOrNull;
+
+  A(this.zero, [this.zeroOrNull]);
+}
+
+int? test1(A? a) => a?.zero!;
+int? test2(A? a) => a?.zeroOrNull!;
+bool? test3(A? a) => a?.zero!.isEven;
+bool? test4(A? a) => a?.zeroOrNull!.isEven;
+
+class Foo {
+  Bar? bar;
+
+  Foo(this.bar);
+
+  Bar? operator [](int? index) => index != null ? new Bar(index) : null;
+}
+
+class Bar {
+  int baz;
+
+  Bar(this.baz);
+
+  int operator [](int index) => index;
+
+  bool operator ==(Object other) => other is Bar && baz == other.baz;
+}
+
+Bar? test5(Foo? foo) => foo?.bar!;
+int? test6(Foo? foo) => foo?.bar!.baz;
+int? test7(Foo? foo, int baz) => foo?.bar![baz];
+Bar? test8(Foo? foo, int? bar) => foo?[bar]!;
+int? test9(Foo? foo, int? bar) => foo?[bar]!.baz;
+test10(Foo? foo, int? bar, int baz) => foo?[bar]![baz];
+
+main() {
+  expect(0, test1(new A(0)));
+  expect(null, test1(null));
+
+  expect(0, test2(new A(0, 0)));
+  expect(null, test2(null));
+  throws(() => test2(new A(0, null)));
+
+  expect(true, test3(new A(0)));
+  expect(null, test3(null));
+
+  expect(true, test4(new A(0, 0)));
+  expect(null, test4(null));
+  throws(() => test4(new A(0, null)));
+
+  expect(new Bar(0), test5(new Foo(new Bar(0))));
+  expect(null, test5(null));
+  throws(() => test5(new Foo(null)));
+
+  expect(0, test6(new Foo(new Bar(0))));
+  expect(null, test6(null));
+  throws(() => test6(new Foo(null)));
+
+  expect(42, test7(new Foo(new Bar(0)), 42));
+  expect(null, test7(null, 42));
+  throws(() => test7(new Foo(null), 42));
+
+  expect(new Bar(42), test8(new Foo(new Bar(0)), 42));
+  expect(null, test8(null, 42));
+  throws(() => test8(new Foo(new Bar(0)), null));
+
+  expect(42, test9(new Foo(new Bar(0)), 42));
+  expect(null, test9(null, 42));
+  throws(() => test9(new Foo(new Bar(0)), null));
+
+  expect(87, test10(new Foo(new Bar(0)), 42, 87));
+  expect(null, test10(null, 42, 87));
+  throws(() => test10(new Foo(new Bar(0)), null, 87));
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(void Function() f) {
+  try {
+    f();
+  } catch (_) {
+    return;
+  }
+  throw 'Missing exception';
+}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.outline.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.outline.expect
new file mode 100644
index 0000000..02e531b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.outline.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull]) → self::A
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    ;
+  operator [](core::int? index) → self::Bar?
+    ;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    ;
+  operator [](core::int index) → core::int
+    ;
+  operator ==(core::Object other) → core::bool
+    ;
+}
+static method test1(self::A? a) → core::int?
+  ;
+static method test2(self::A? a) → core::int?
+  ;
+static method test3(self::A? a) → core::bool?
+  ;
+static method test4(self::A? a) → core::bool?
+  ;
+static method test5(self::Foo? foo) → self::Bar?
+  ;
+static method test6(self::Foo? foo) → core::int?
+  ;
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  ;
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  ;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  ;
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  ;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → void f) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.expect
new file mode 100644
index 0000000..2897025
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.expect
@@ -0,0 +1,107 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:12:24: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// int? test1(A? a) => a?.zero!;
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:14:25: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// bool? test3(A? a) => a?.zero!.isEven;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull = #C1]) → self::A
+    : self::A::zero = zero, self::A::zeroOrNull = zeroOrNull, super core::Object::•()
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    : self::Foo::bar = bar, super core::Object::•()
+    ;
+  operator [](core::int? index) → self::Bar?
+    return !index.{core::num::==}(null) ?{self::Bar?} new self::Bar::•(index{core::int}) : null;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    : self::Bar::baz = baz, super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator ==(core::Object other) → core::bool
+    return other is{ForNonNullableByDefault} self::Bar && this.{self::Bar::baz}.{core::num::==}(other{self::Bar}.{self::Bar::baz});
+}
+static method test1(self::A? a) → core::int?
+  return let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{core::int?} null : #t1{self::A}.{self::A::zero}!;
+static method test2(self::A? a) → core::int?
+  return let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{core::int?} null : #t2{self::A}.{self::A::zeroOrNull}!;
+static method test3(self::A? a) → core::bool?
+  return let final self::A? #t3 = a in #t3.{core::Object::==}(null) ?{core::bool?} null : #t3{self::A}.{self::A::zero}!.{core::int::isEven};
+static method test4(self::A? a) → core::bool?
+  return let final self::A? #t4 = a in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{self::A}.{self::A::zeroOrNull}!.{core::int::isEven};
+static method test5(self::Foo? foo) → self::Bar?
+  return let final self::Foo? #t5 = foo in #t5.{core::Object::==}(null) ?{self::Bar?} null : #t5{self::Foo}.{self::Foo::bar}!;
+static method test6(self::Foo? foo) → core::int?
+  return let final self::Foo? #t6 = foo in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Foo}.{self::Foo::bar}!.{self::Bar::baz};
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  return let final self::Foo? #t7 = foo in #t7.{core::Object::==}(null) ?{core::int?} null : #t7{self::Foo}.{self::Foo::bar}!.{self::Bar::[]}(baz);
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  return let final self::Foo? #t8 = foo in #t8.{core::Object::==}(null) ?{self::Bar?} null : #t8{self::Foo}.{self::Foo::[]}(bar)!;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  return let final self::Foo? #t9 = foo in #t9.{core::Object::==}(null) ?{core::int?} null : #t9{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::baz};
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  return let final self::Foo? #t10 = foo in #t10.{core::Object::==}(null) ?{core::int?} null : #t10{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::[]}(baz);
+static method main() → dynamic {
+  self::expect(0, self::test1(new self::A::•(0)));
+  self::expect(null, self::test1(null));
+  self::expect(0, self::test2(new self::A::•(0, 0)));
+  self::expect(null, self::test2(null));
+  self::throws(() → core::int? => self::test2(new self::A::•(0, null)));
+  self::expect(true, self::test3(new self::A::•(0)));
+  self::expect(null, self::test3(null));
+  self::expect(true, self::test4(new self::A::•(0, 0)));
+  self::expect(null, self::test4(null));
+  self::throws(() → core::bool? => self::test4(new self::A::•(0, null)));
+  self::expect(new self::Bar::•(0), self::test5(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test5(null));
+  self::throws(() → self::Bar? => self::test5(new self::Foo::•(null)));
+  self::expect(0, self::test6(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test6(null));
+  self::throws(() → core::int? => self::test6(new self::Foo::•(null)));
+  self::expect(42, self::test7(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test7(null, 42));
+  self::throws(() → core::int? => self::test7(new self::Foo::•(null), 42));
+  self::expect(new self::Bar::•(42), self::test8(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test8(null, 42));
+  self::throws(() → self::Bar? => self::test8(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(42, self::test9(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test9(null, 42));
+  self::throws(() → core::int? => self::test9(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(87, self::test10(new self::Foo::•(new self::Bar::•(0)), 42, 87));
+  self::expect(null, self::test10(null, 42, 87));
+  self::throws(() → dynamic => self::test10(new self::Foo::•(new self::Bar::•(0)), null, 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.transformed.expect
new file mode 100644
index 0000000..2897025
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.transformed.expect
@@ -0,0 +1,107 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:12:24: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// int? test1(A? a) => a?.zero!;
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:14:25: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// bool? test3(A? a) => a?.zero!.isEven;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull = #C1]) → self::A
+    : self::A::zero = zero, self::A::zeroOrNull = zeroOrNull, super core::Object::•()
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    : self::Foo::bar = bar, super core::Object::•()
+    ;
+  operator [](core::int? index) → self::Bar?
+    return !index.{core::num::==}(null) ?{self::Bar?} new self::Bar::•(index{core::int}) : null;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    : self::Bar::baz = baz, super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator ==(core::Object other) → core::bool
+    return other is{ForNonNullableByDefault} self::Bar && this.{self::Bar::baz}.{core::num::==}(other{self::Bar}.{self::Bar::baz});
+}
+static method test1(self::A? a) → core::int?
+  return let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{core::int?} null : #t1{self::A}.{self::A::zero}!;
+static method test2(self::A? a) → core::int?
+  return let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{core::int?} null : #t2{self::A}.{self::A::zeroOrNull}!;
+static method test3(self::A? a) → core::bool?
+  return let final self::A? #t3 = a in #t3.{core::Object::==}(null) ?{core::bool?} null : #t3{self::A}.{self::A::zero}!.{core::int::isEven};
+static method test4(self::A? a) → core::bool?
+  return let final self::A? #t4 = a in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{self::A}.{self::A::zeroOrNull}!.{core::int::isEven};
+static method test5(self::Foo? foo) → self::Bar?
+  return let final self::Foo? #t5 = foo in #t5.{core::Object::==}(null) ?{self::Bar?} null : #t5{self::Foo}.{self::Foo::bar}!;
+static method test6(self::Foo? foo) → core::int?
+  return let final self::Foo? #t6 = foo in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Foo}.{self::Foo::bar}!.{self::Bar::baz};
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  return let final self::Foo? #t7 = foo in #t7.{core::Object::==}(null) ?{core::int?} null : #t7{self::Foo}.{self::Foo::bar}!.{self::Bar::[]}(baz);
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  return let final self::Foo? #t8 = foo in #t8.{core::Object::==}(null) ?{self::Bar?} null : #t8{self::Foo}.{self::Foo::[]}(bar)!;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  return let final self::Foo? #t9 = foo in #t9.{core::Object::==}(null) ?{core::int?} null : #t9{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::baz};
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  return let final self::Foo? #t10 = foo in #t10.{core::Object::==}(null) ?{core::int?} null : #t10{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::[]}(baz);
+static method main() → dynamic {
+  self::expect(0, self::test1(new self::A::•(0)));
+  self::expect(null, self::test1(null));
+  self::expect(0, self::test2(new self::A::•(0, 0)));
+  self::expect(null, self::test2(null));
+  self::throws(() → core::int? => self::test2(new self::A::•(0, null)));
+  self::expect(true, self::test3(new self::A::•(0)));
+  self::expect(null, self::test3(null));
+  self::expect(true, self::test4(new self::A::•(0, 0)));
+  self::expect(null, self::test4(null));
+  self::throws(() → core::bool? => self::test4(new self::A::•(0, null)));
+  self::expect(new self::Bar::•(0), self::test5(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test5(null));
+  self::throws(() → self::Bar? => self::test5(new self::Foo::•(null)));
+  self::expect(0, self::test6(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test6(null));
+  self::throws(() → core::int? => self::test6(new self::Foo::•(null)));
+  self::expect(42, self::test7(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test7(null, 42));
+  self::throws(() → core::int? => self::test7(new self::Foo::•(null), 42));
+  self::expect(new self::Bar::•(42), self::test8(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test8(null, 42));
+  self::throws(() → self::Bar? => self::test8(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(42, self::test9(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test9(null, 42));
+  self::throws(() → core::int? => self::test9(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(87, self::test10(new self::Foo::•(new self::Bar::•(0)), 42, 87));
+  self::expect(null, self::test10(null, 42, 87));
+  self::throws(() → dynamic => self::test10(new self::Foo::•(new self::Bar::•(0)), null, 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline.expect
new file mode 100644
index 0000000..13961a5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline.expect
@@ -0,0 +1,33 @@
+class A {
+  int zero;
+  int? zeroOrNull;
+  A(this.zero, [this.zeroOrNull]);
+}
+
+int? test1(A? a) => a?.zero!;
+int? test2(A? a) => a?.zeroOrNull!;
+bool? test3(A? a) => a?.zero!.isEven;
+bool? test4(A? a) => a?.zeroOrNull!.isEven;
+
+class Foo {
+  Bar? bar;
+  Foo(this.bar);
+  Bar? operator [](int? index) => index != null ? new Bar(index) : null;
+}
+
+class Bar {
+  int baz;
+  Bar(this.baz);
+  int operator [](int index) => index;
+  bool operator ==(Object other) => other is Bar && baz == other.baz;
+}
+
+Bar? test5(Foo? foo) => foo?.bar!;
+int? test6(Foo? foo) => foo?.bar!.baz;
+int? test7(Foo? foo, int baz) => foo?.bar![baz];
+Bar? test8(Foo? foo, int? bar) => foo?[bar]!;
+int? test9(Foo? foo, int? bar) => foo?[bar]!.baz;
+test10(Foo? foo, int? bar, int baz) => foo?[bar]![baz];
+main() {}
+expect(expected, actual) {}
+throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..58770bf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline_modelled.expect
@@ -0,0 +1,33 @@
+Bar? test5(Foo? foo) => foo?.bar!;
+Bar? test8(Foo? foo, int? bar) => foo?[bar]!;
+bool? test3(A? a) => a?.zero!.isEven;
+bool? test4(A? a) => a?.zeroOrNull!.isEven;
+
+class A {
+  A(this.zero, [this.zeroOrNull]);
+  int? zeroOrNull;
+  int zero;
+}
+
+class Bar {
+  Bar(this.baz);
+  bool operator ==(Object other) => other is Bar && baz == other.baz;
+  int baz;
+  int operator [](int index) => index;
+}
+
+class Foo {
+  Bar? bar;
+  Bar? operator [](int? index) => index != null ? new Bar(index) : null;
+  Foo(this.bar);
+}
+
+expect(expected, actual) {}
+int? test1(A? a) => a?.zero!;
+int? test2(A? a) => a?.zeroOrNull!;
+int? test6(Foo? foo) => foo?.bar!.baz;
+int? test7(Foo? foo, int baz) => foo?.bar![baz];
+int? test9(Foo? foo, int? bar) => foo?[bar]!.baz;
+main() {}
+test10(Foo? foo, int? bar, int baz) => foo?[bar]![baz];
+throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.expect
new file mode 100644
index 0000000..2897025
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.expect
@@ -0,0 +1,107 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:12:24: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// int? test1(A? a) => a?.zero!;
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:14:25: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// bool? test3(A? a) => a?.zero!.isEven;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull = #C1]) → self::A
+    : self::A::zero = zero, self::A::zeroOrNull = zeroOrNull, super core::Object::•()
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    : self::Foo::bar = bar, super core::Object::•()
+    ;
+  operator [](core::int? index) → self::Bar?
+    return !index.{core::num::==}(null) ?{self::Bar?} new self::Bar::•(index{core::int}) : null;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    : self::Bar::baz = baz, super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator ==(core::Object other) → core::bool
+    return other is{ForNonNullableByDefault} self::Bar && this.{self::Bar::baz}.{core::num::==}(other{self::Bar}.{self::Bar::baz});
+}
+static method test1(self::A? a) → core::int?
+  return let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{core::int?} null : #t1{self::A}.{self::A::zero}!;
+static method test2(self::A? a) → core::int?
+  return let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{core::int?} null : #t2{self::A}.{self::A::zeroOrNull}!;
+static method test3(self::A? a) → core::bool?
+  return let final self::A? #t3 = a in #t3.{core::Object::==}(null) ?{core::bool?} null : #t3{self::A}.{self::A::zero}!.{core::int::isEven};
+static method test4(self::A? a) → core::bool?
+  return let final self::A? #t4 = a in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{self::A}.{self::A::zeroOrNull}!.{core::int::isEven};
+static method test5(self::Foo? foo) → self::Bar?
+  return let final self::Foo? #t5 = foo in #t5.{core::Object::==}(null) ?{self::Bar?} null : #t5{self::Foo}.{self::Foo::bar}!;
+static method test6(self::Foo? foo) → core::int?
+  return let final self::Foo? #t6 = foo in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Foo}.{self::Foo::bar}!.{self::Bar::baz};
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  return let final self::Foo? #t7 = foo in #t7.{core::Object::==}(null) ?{core::int?} null : #t7{self::Foo}.{self::Foo::bar}!.{self::Bar::[]}(baz);
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  return let final self::Foo? #t8 = foo in #t8.{core::Object::==}(null) ?{self::Bar?} null : #t8{self::Foo}.{self::Foo::[]}(bar)!;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  return let final self::Foo? #t9 = foo in #t9.{core::Object::==}(null) ?{core::int?} null : #t9{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::baz};
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  return let final self::Foo? #t10 = foo in #t10.{core::Object::==}(null) ?{core::int?} null : #t10{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::[]}(baz);
+static method main() → dynamic {
+  self::expect(0, self::test1(new self::A::•(0)));
+  self::expect(null, self::test1(null));
+  self::expect(0, self::test2(new self::A::•(0, 0)));
+  self::expect(null, self::test2(null));
+  self::throws(() → core::int? => self::test2(new self::A::•(0, null)));
+  self::expect(true, self::test3(new self::A::•(0)));
+  self::expect(null, self::test3(null));
+  self::expect(true, self::test4(new self::A::•(0, 0)));
+  self::expect(null, self::test4(null));
+  self::throws(() → core::bool? => self::test4(new self::A::•(0, null)));
+  self::expect(new self::Bar::•(0), self::test5(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test5(null));
+  self::throws(() → self::Bar? => self::test5(new self::Foo::•(null)));
+  self::expect(0, self::test6(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test6(null));
+  self::throws(() → core::int? => self::test6(new self::Foo::•(null)));
+  self::expect(42, self::test7(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test7(null, 42));
+  self::throws(() → core::int? => self::test7(new self::Foo::•(null), 42));
+  self::expect(new self::Bar::•(42), self::test8(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test8(null, 42));
+  self::throws(() → self::Bar? => self::test8(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(42, self::test9(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test9(null, 42));
+  self::throws(() → core::int? => self::test9(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(87, self::test10(new self::Foo::•(new self::Bar::•(0)), 42, 87));
+  self::expect(null, self::test10(null, 42, 87));
+  self::throws(() → dynamic => self::test10(new self::Foo::•(new self::Bar::•(0)), null, 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.transformed.expect
new file mode 100644
index 0000000..2897025
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.transformed.expect
@@ -0,0 +1,107 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:12:24: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// int? test1(A? a) => a?.zero!;
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:14:25: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// bool? test3(A? a) => a?.zero!.isEven;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull = #C1]) → self::A
+    : self::A::zero = zero, self::A::zeroOrNull = zeroOrNull, super core::Object::•()
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    : self::Foo::bar = bar, super core::Object::•()
+    ;
+  operator [](core::int? index) → self::Bar?
+    return !index.{core::num::==}(null) ?{self::Bar?} new self::Bar::•(index{core::int}) : null;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    : self::Bar::baz = baz, super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator ==(core::Object other) → core::bool
+    return other is{ForNonNullableByDefault} self::Bar && this.{self::Bar::baz}.{core::num::==}(other{self::Bar}.{self::Bar::baz});
+}
+static method test1(self::A? a) → core::int?
+  return let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{core::int?} null : #t1{self::A}.{self::A::zero}!;
+static method test2(self::A? a) → core::int?
+  return let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{core::int?} null : #t2{self::A}.{self::A::zeroOrNull}!;
+static method test3(self::A? a) → core::bool?
+  return let final self::A? #t3 = a in #t3.{core::Object::==}(null) ?{core::bool?} null : #t3{self::A}.{self::A::zero}!.{core::int::isEven};
+static method test4(self::A? a) → core::bool?
+  return let final self::A? #t4 = a in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{self::A}.{self::A::zeroOrNull}!.{core::int::isEven};
+static method test5(self::Foo? foo) → self::Bar?
+  return let final self::Foo? #t5 = foo in #t5.{core::Object::==}(null) ?{self::Bar?} null : #t5{self::Foo}.{self::Foo::bar}!;
+static method test6(self::Foo? foo) → core::int?
+  return let final self::Foo? #t6 = foo in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Foo}.{self::Foo::bar}!.{self::Bar::baz};
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  return let final self::Foo? #t7 = foo in #t7.{core::Object::==}(null) ?{core::int?} null : #t7{self::Foo}.{self::Foo::bar}!.{self::Bar::[]}(baz);
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  return let final self::Foo? #t8 = foo in #t8.{core::Object::==}(null) ?{self::Bar?} null : #t8{self::Foo}.{self::Foo::[]}(bar)!;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  return let final self::Foo? #t9 = foo in #t9.{core::Object::==}(null) ?{core::int?} null : #t9{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::baz};
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  return let final self::Foo? #t10 = foo in #t10.{core::Object::==}(null) ?{core::int?} null : #t10{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::[]}(baz);
+static method main() → dynamic {
+  self::expect(0, self::test1(new self::A::•(0)));
+  self::expect(null, self::test1(null));
+  self::expect(0, self::test2(new self::A::•(0, 0)));
+  self::expect(null, self::test2(null));
+  self::throws(() → core::int? => self::test2(new self::A::•(0, null)));
+  self::expect(true, self::test3(new self::A::•(0)));
+  self::expect(null, self::test3(null));
+  self::expect(true, self::test4(new self::A::•(0, 0)));
+  self::expect(null, self::test4(null));
+  self::throws(() → core::bool? => self::test4(new self::A::•(0, null)));
+  self::expect(new self::Bar::•(0), self::test5(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test5(null));
+  self::throws(() → self::Bar? => self::test5(new self::Foo::•(null)));
+  self::expect(0, self::test6(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test6(null));
+  self::throws(() → core::int? => self::test6(new self::Foo::•(null)));
+  self::expect(42, self::test7(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test7(null, 42));
+  self::throws(() → core::int? => self::test7(new self::Foo::•(null), 42));
+  self::expect(new self::Bar::•(42), self::test8(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test8(null, 42));
+  self::throws(() → self::Bar? => self::test8(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(42, self::test9(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test9(null, 42));
+  self::throws(() → core::int? => self::test9(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(87, self::test10(new self::Foo::•(new self::Bar::•(0)), 42, 87));
+  self::expect(null, self::test10(null, 42, 87));
+  self::throws(() → dynamic => self::test10(new self::Foo::•(new self::Bar::•(0)), null, 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = null
+}