Version 2.11.0-196.0.dev

Merge commit 'e933e91aaa29531ccb32d5adec853270eedbedae' into 'dev'
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 037629d..1a1c1df 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
@@ -1278,8 +1278,7 @@
 /// the state actually leave `this` unchanged and return a new state object.
 @visibleForTesting
 class FlowModel<Variable, Type> {
-  /// Indicates whether this point in the control flow is reachable.
-  final bool reachable;
+  final Reachability reachable;
 
   /// For each variable being tracked by flow analysis, the variable's model.
   ///
@@ -1303,7 +1302,7 @@
   /// Creates a state object with the given [reachable] status.  All variables
   /// are assumed to be unpromoted and already assigned, so joining another
   /// state with this one will have no effect on it.
-  FlowModel(bool reachable)
+  FlowModel(Reachability reachable)
       : this.withInfo(
           reachable,
           const {},
@@ -1312,6 +1311,7 @@
   @visibleForTesting
   FlowModel.withInfo(this.reachable, this.variableInfo)
       : _freshVariableInfo = new VariableModel.fresh() {
+    assert(reachable != null);
     assert(() {
       for (VariableModel<Variable, Type> value in variableInfo.values) {
         assert(value != null);
@@ -1484,7 +1484,8 @@
       TypeOperations<Variable, Type> typeOperations,
       FlowModel<Variable, Type> other,
       Set<Variable> unsafe) {
-    bool newReachable = reachable && other.reachable;
+    Reachability newReachable =
+        Reachability.restrict(reachable, other.reachable);
 
     Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
         <Variable, VariableModel<Variable, Type>>{};
@@ -1528,11 +1529,17 @@
 
   /// Updates the state to indicate that the control flow path is unreachable.
   FlowModel<Variable, Type> setUnreachable() {
-    if (!reachable) return this;
+    if (!reachable.locallyReachable) return this;
 
-    return new FlowModel<Variable, Type>.withInfo(false, variableInfo);
+    return new FlowModel<Variable, Type>.withInfo(
+        reachable.setUnreachable(), variableInfo);
   }
 
+  /// Returns a [FlowModel] indicating the result of creating a control flow
+  /// split.  See [Reachability.split] for more information.
+  FlowModel<Variable, Type> split() =>
+      new FlowModel<Variable, Type>.withInfo(reachable.split(), variableInfo);
+
   @override
   String toString() => '($reachable, $variableInfo)';
 
@@ -1646,6 +1653,11 @@
         this, modelIfSuccessful, modelIfFailed);
   }
 
+  /// Returns a [FlowModel] indicating the result of removing a control flow
+  /// split.  See [Reachability.unsplit] for more information.
+  FlowModel<Variable, Type> unsplit() =>
+      new FlowModel<Variable, Type>.withInfo(reachable.unsplit(), variableInfo);
+
   /// Updates the state to indicate that an assignment was made to the given
   /// [variable].  The variable is marked as definitely assigned, and any
   /// previous type promotion is removed.
@@ -1686,12 +1698,12 @@
     }
 
     List<Type> newPromotedTypes = info.promotedTypes;
-    bool newReachable = reachable;
+    Reachability newReachable = reachable;
     if (promotedType != null) {
       newPromotedTypes =
           VariableModel._addToPromotedTypes(info.promotedTypes, promotedType);
       if (typeOperations.isNever(promotedType)) {
-        newReachable = false;
+        newReachable = reachable.setUnreachable();
       }
     }
 
@@ -1710,7 +1722,7 @@
   /// with [model].
   FlowModel<Variable, Type> _updateVariableInfo(
       Variable variable, VariableModel<Variable, Type> model,
-      {bool reachable}) {
+      {Reachability reachable}) {
     reachable ??= this.reachable;
     Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
         new Map<Variable, VariableModel<Variable, Type>>.from(variableInfo);
@@ -1736,10 +1748,18 @@
     if (first == null) return second;
     if (second == null) return first;
 
-    if (first.reachable && !second.reachable) return first;
-    if (!first.reachable && second.reachable) return second;
+    assert(identical(first.reachable.parent, second.reachable.parent));
+    if (first.reachable.locallyReachable &&
+        !second.reachable.locallyReachable) {
+      return first;
+    }
+    if (!first.reachable.locallyReachable &&
+        second.reachable.locallyReachable) {
+      return second;
+    }
 
-    bool newReachable = first.reachable || second.reachable;
+    Reachability newReachable =
+        Reachability.join(first.reachable, second.reachable);
     Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
         FlowModel.joinVariableInfo(typeOperations, first.variableInfo,
             second.variableInfo, emptyVariableMap);
@@ -1793,7 +1813,7 @@
   static FlowModel<Variable, Type> _identicalOrNew<Variable, Type>(
       FlowModel<Variable, Type> first,
       FlowModel<Variable, Type> second,
-      bool newReachable,
+      Reachability newReachable,
       Map<Variable, VariableModel<Variable, Type>> newVariableInfo) {
     if (first.reachable == newReachable &&
         identical(first.variableInfo, newVariableInfo)) {
@@ -1829,6 +1849,101 @@
   }
 }
 
+/// Immutable data structure modeling the reachability of the given point in the
+/// source code.  Reachability is tracked relative to checkpoints occurring
+/// previously along the control flow path leading up to the current point in
+/// the program.  A given point is said to be "locally reachable" if it is
+/// reachable from the most recent checkpoint, and "overall reachable" if it is
+/// reachable from the top of the function.
+@visibleForTesting
+class Reachability {
+  /// Model of the initial reachability state of the function being analyzed.
+  static const Reachability initial = const Reachability._initial();
+
+  /// Reachability of the checkpoint this reachability is relative to, or `null`
+  /// if there is no checkpoint.  Reachabilities form a tree structure that
+  /// mimics the control flow of the code being analyzed, so this is called the
+  /// "parent".
+  final Reachability parent;
+
+  /// Whether this point in the source code is considered reachable from the
+  /// most recent checkpoint.
+  final bool locallyReachable;
+
+  /// Whether this point in the source code is considered reachable from the
+  /// beginning of the function being analyzed.
+  final bool overallReachable;
+
+  Reachability._(this.parent, this.locallyReachable, this.overallReachable) {
+    assert(overallReachable ==
+        (locallyReachable && (parent?.overallReachable ?? true)));
+  }
+
+  const Reachability._initial()
+      : parent = null,
+        locallyReachable = true,
+        overallReachable = true;
+
+  /// Returns a reachability with the same checkpoint as `this`, but where the
+  /// current point in the program is considered locally unreachable.
+  Reachability setUnreachable() {
+    if (!locallyReachable) return this;
+    return new Reachability._(parent, false, false);
+  }
+
+  /// Returns a new reachability whose checkpoint is the current point of
+  /// execution.  This models flow control within a control flow split, e.g.
+  /// inside an `if` statement.
+  Reachability split() => new Reachability._(this, true, overallReachable);
+
+  @override
+  String toString() {
+    List<bool> values = [];
+    for (Reachability node = this; node != null; node = node.parent) {
+      values.add(node.locallyReachable);
+    }
+    return '[${values.join(', ')}]';
+  }
+
+  /// Returns a reachability that drops the most recent checkpoint but maintains
+  /// the same notion of reachability relative to the previous two checkpoints.
+  Reachability unsplit() {
+    if (locallyReachable) {
+      return parent;
+    } else {
+      return parent.setUnreachable();
+    }
+  }
+
+  /// Combines two reachabilities (both of which must be based on the same
+  /// checkpoint), where the code is considered reachable from the checkpoint
+  /// iff either argument is reachable from the checkpoint.
+  ///
+  /// This is used as part of the "join" operation.
+  static Reachability join(Reachability r1, Reachability r2) {
+    assert(identical(r1.parent, r2.parent));
+    if (r2.locallyReachable) {
+      return r2;
+    } else {
+      return r1;
+    }
+  }
+
+  /// Combines two reachabilities (both of which must be based on the same
+  /// checkpoint), where the code is considered reachable from the checkpoint
+  /// iff both arguments are reachable from the checkpoint.
+  ///
+  /// This is used as part of the "restrict" operation.
+  static Reachability restrict(Reachability r1, Reachability r2) {
+    assert(identical(r1.parent, r2.parent));
+    if (r2.locallyReachable) {
+      return r1;
+    } else {
+      return r2;
+    }
+  }
+}
+
 /// Enum representing the different classifications of types that can be
 /// returned by [TypeOperations.classifyType].
 enum TypeClassification {
@@ -2505,11 +2620,11 @@
   final AssignedVariables<Node, Variable> _assignedVariables;
 
   _FlowAnalysisImpl(this.typeOperations, this._assignedVariables) {
-    _current = new FlowModel<Variable, Type>(true);
+    _current = new FlowModel<Variable, Type>(Reachability.initial);
   }
 
   @override
-  bool get isReachable => _current.reachable;
+  bool get isReachable => _current.reachable.overallReachable;
 
   @override
   void asExpression_end(Expression subExpression, Type type) {
@@ -2671,6 +2786,7 @@
   @override
   void finish() {
     assert(_stack.isEmpty);
+    assert(_current.reachable.parent == null);
   }
 
   @override
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 f90a68a..16ae7ff 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
@@ -1015,8 +1015,8 @@
     });
 
     test(
-        'functionExpression_end does not propagate "definitely unassigned" data',
-        () {
+        'functionExpression_end does not propagate "definitely unassigned" '
+        'data', () {
       var h = _Harness();
       var x = h.addVar('x', 'int');
       var functionNode = _Node();
@@ -2210,14 +2210,96 @@
     });
   });
 
+  group('Reachability', () {
+    test('initial state', () {
+      expect(Reachability.initial.parent, isNull);
+      expect(Reachability.initial.locallyReachable, true);
+      expect(Reachability.initial.overallReachable, true);
+    });
+
+    test('split', () {
+      var reachableSplit = Reachability.initial.split();
+      expect(reachableSplit.parent, same(Reachability.initial));
+      expect(reachableSplit.overallReachable, true);
+      expect(reachableSplit.locallyReachable, true);
+      var unreachable = reachableSplit.setUnreachable();
+      var unreachableSplit = unreachable.split();
+      expect(unreachableSplit.parent, same(unreachable));
+      expect(unreachableSplit.overallReachable, false);
+      expect(unreachableSplit.locallyReachable, true);
+    });
+
+    test('unsplit', () {
+      var base = Reachability.initial.split();
+      var reachableSplit = base.split();
+      var reachableSplitUnsplit = reachableSplit.unsplit();
+      expect(reachableSplitUnsplit.parent, same(base.parent));
+      expect(reachableSplitUnsplit.overallReachable, true);
+      expect(reachableSplitUnsplit.locallyReachable, true);
+      var reachableSplitUnreachable = reachableSplit.setUnreachable();
+      var reachableSplitUnreachableUnsplit =
+          reachableSplitUnreachable.unsplit();
+      expect(reachableSplitUnreachableUnsplit.parent, same(base.parent));
+      expect(reachableSplitUnreachableUnsplit.overallReachable, false);
+      expect(reachableSplitUnreachableUnsplit.locallyReachable, false);
+      var unreachable = base.setUnreachable();
+      var unreachableSplit = unreachable.split();
+      var unreachableSplitUnsplit = unreachableSplit.unsplit();
+      expect(unreachableSplitUnsplit, same(unreachable));
+      var unreachableSplitUnreachable = unreachableSplit.setUnreachable();
+      var unreachableSplitUnreachableUnsplit =
+          unreachableSplitUnreachable.unsplit();
+      expect(unreachableSplitUnreachableUnsplit, same(unreachable));
+    });
+
+    test('setUnreachable', () {
+      var reachable = Reachability.initial.split();
+      var unreachable = reachable.setUnreachable();
+      expect(unreachable.parent, same(reachable.parent));
+      expect(unreachable.locallyReachable, false);
+      expect(unreachable.overallReachable, false);
+      expect(unreachable.setUnreachable(), same(unreachable));
+      var provisionallyReachable = unreachable.split();
+      var provisionallyUnreachable = provisionallyReachable.setUnreachable();
+      expect(
+          provisionallyUnreachable.parent, same(provisionallyReachable.parent));
+      expect(provisionallyUnreachable.locallyReachable, false);
+      expect(provisionallyUnreachable.overallReachable, false);
+      expect(provisionallyUnreachable.setUnreachable(),
+          same(provisionallyUnreachable));
+    });
+
+    test('restrict', () {
+      var previous = Reachability.initial.split();
+      var reachable = previous.split();
+      var unreachable = reachable.setUnreachable();
+      expect(Reachability.restrict(reachable, reachable), same(reachable));
+      expect(Reachability.restrict(reachable, unreachable), same(unreachable));
+      expect(Reachability.restrict(unreachable, reachable), same(unreachable));
+      expect(
+          Reachability.restrict(unreachable, unreachable), same(unreachable));
+    });
+
+    test('join', () {
+      var previous = Reachability.initial.split();
+      var reachable = previous.split();
+      var unreachable = reachable.setUnreachable();
+      expect(Reachability.join(reachable, reachable), same(reachable));
+      expect(Reachability.join(reachable, unreachable), same(reachable));
+      expect(Reachability.join(unreachable, reachable), same(reachable));
+      expect(Reachability.join(unreachable, unreachable), same(unreachable));
+    });
+  });
+
   group('State', () {
     var intVar = _Var('x', _Type('int'));
     var intQVar = _Var('x', _Type('int?'));
     var objectQVar = _Var('x', _Type('Object?'));
     var nullVar = _Var('x', _Type('Null'));
     group('setUnreachable', () {
-      var unreachable = FlowModel<_Var, _Type>(false);
-      var reachable = FlowModel<_Var, _Type>(true);
+      var unreachable =
+          FlowModel<_Var, _Type>(Reachability.initial.setUnreachable());
+      var reachable = FlowModel<_Var, _Type>(Reachability.initial);
       test('unchanged', () {
         expect(unreachable.setUnreachable(), same(unreachable));
       });
@@ -2226,7 +2308,7 @@
         void _check(FlowModel<_Var, _Type> initial) {
           var s = initial.setUnreachable();
           expect(s, isNot(same(initial)));
-          expect(s.reachable, false);
+          expect(s.reachable.overallReachable, false);
           expect(s.variableInfo, same(initial.variableInfo));
         }
 
@@ -2234,33 +2316,45 @@
       });
     });
 
+    test('split', () {
+      var s1 = FlowModel<_Var, _Type>(Reachability.initial);
+      var s2 = s1.split();
+      expect(s2.reachable.parent, same(s1.reachable));
+    });
+
+    test('unsplit', () {
+      var s1 = FlowModel<_Var, _Type>(Reachability.initial.split());
+      var s2 = s1.unsplit();
+      expect(s2.reachable, same(Reachability.initial));
+    });
+
     group('tryPromoteForTypeCheck', () {
       test('unpromoted -> unchanged (same)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('int')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> unchanged (supertype)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('Object')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> unchanged (unrelated)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('String')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> subtype', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryPromoteForTypeCheck(h, intQVar, _Type('int')).ifTrue;
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           intQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int'])
         });
@@ -2268,7 +2362,7 @@
 
       test('promoted -> unchanged (same)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, _Type('int')).ifTrue;
@@ -2277,7 +2371,7 @@
 
       test('promoted -> unchanged (supertype)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 =
@@ -2287,7 +2381,7 @@
 
       test('promoted -> unchanged (unrelated)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 =
@@ -2297,11 +2391,11 @@
 
       test('promoted -> subtype', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
             .ifTrue;
         var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, _Type('int')).ifTrue;
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
               chain: ['int?', 'int'], ofInterest: ['int?', 'int'])
@@ -2315,23 +2409,25 @@
       test('without declaration', () {
         // This should not happen in valid code, but test that we don't crash.
         var h = _Harness();
-        var s =
-            FlowModel<_Var, _Type>(true).write(objectQVar, _Type('Object?'), h);
+        var s = FlowModel<_Var, _Type>(Reachability.initial)
+            .write(objectQVar, _Type('Object?'), h);
         expect(s.variableInfo[objectQVar], isNull);
       });
 
       test('unchanged', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true).declare(objectQVar, true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
+            .declare(objectQVar, true);
         var s2 = s1.write(objectQVar, _Type('Object?'), h);
         expect(s2, same(s1));
       });
 
       test('marks as assigned', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true).declare(objectQVar, false);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
+            .declare(objectQVar, false);
         var s2 = s1.write(objectQVar, _Type('int?'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(
             s2.infoFor(objectQVar),
             _matchVariableModel(
@@ -2343,13 +2439,13 @@
 
       test('un-promotes fully', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         expect(s1.variableInfo, contains(objectQVar));
         var s2 = s1.write(objectQVar, _Type('int?'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
               chain: null,
@@ -2361,7 +2457,7 @@
 
       test('un-promotes partially, when no exact match', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2375,7 +2471,7 @@
               unassigned: false)
         });
         var s2 = s1.write(objectQVar, _Type('num'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
               chain: ['num?', 'num'],
@@ -2387,7 +2483,7 @@
 
       test('un-promotes partially, when exact match', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2403,7 +2499,7 @@
               unassigned: false)
         });
         var s2 = s1.write(objectQVar, _Type('num'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
               chain: ['num?', 'num'],
@@ -2415,7 +2511,7 @@
 
       test('leaves promoted, when exact match', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2429,13 +2525,13 @@
               unassigned: false)
         });
         var s2 = s1.write(objectQVar, _Type('num'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, same(s1.variableInfo));
       });
 
       test('leaves promoted, when writing a subtype', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2449,7 +2545,7 @@
               unassigned: false)
         });
         var s2 = s1.write(objectQVar, _Type('int'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, same(s1.variableInfo));
       });
 
@@ -2458,7 +2554,8 @@
           var h = _Harness();
           var x = _Var('x', _Type('int?'));
 
-          var s1 = FlowModel<_Var, _Type>(true).declare(x, true);
+          var s1 =
+              FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
           expect(s1.variableInfo, {
             x: _matchVariableModel(chain: null),
           });
@@ -2473,7 +2570,8 @@
           var h = _Harness();
           var x = h.addVar('x', 'int?');
 
-          var s1 = FlowModel<_Var, _Type>(true).declare(x, true);
+          var s1 =
+              FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
           expect(s1.variableInfo, {
             x: _matchVariableModel(chain: null),
           });
@@ -2492,7 +2590,7 @@
 
         test('when promoted', () {
           var h = _Harness();
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(objectQVar, true)
               .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
               .ifTrue;
@@ -2513,7 +2611,7 @@
 
         test('when not promoted', () {
           var h = _Harness();
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(objectQVar, true)
               .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
               .ifFalse;
@@ -2535,7 +2633,7 @@
 
       test('Promotes to type of interest when not previously promoted', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifFalse;
@@ -2556,7 +2654,7 @@
 
       test('Promotes to type of interest when previously promoted', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2624,7 +2722,7 @@
           test('; first', () {
             var x = _Var('x', _Type('Object?'));
 
-            var s1 = FlowModel<_Var, _Type>(true)
+            var s1 = FlowModel<_Var, _Type>(Reachability.initial)
                 .declare(x, true)
                 .tryPromoteForTypeCheck(h, x, _Type('B?'))
                 .ifFalse
@@ -2649,7 +2747,7 @@
           test('; second', () {
             var x = _Var('x', _Type('Object?'));
 
-            var s1 = FlowModel<_Var, _Type>(true)
+            var s1 = FlowModel<_Var, _Type>(Reachability.initial)
                 .declare(x, true)
                 .tryPromoteForTypeCheck(h, x, _Type('A?'))
                 .ifFalse
@@ -2674,7 +2772,7 @@
           test('; nullable and non-nullable', () {
             var x = _Var('x', _Type('Object?'));
 
-            var s1 = FlowModel<_Var, _Type>(true)
+            var s1 = FlowModel<_Var, _Type>(Reachability.initial)
                 .declare(x, true)
                 .tryPromoteForTypeCheck(h, x, _Type('A'))
                 .ifFalse
@@ -2700,7 +2798,7 @@
         group('; ambiguous', () {
           test('; no promotion', () {
             var h = _Harness();
-            var s1 = FlowModel<_Var, _Type>(true)
+            var s1 = FlowModel<_Var, _Type>(Reachability.initial)
                 .declare(objectQVar, true)
                 .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
                 .ifFalse
@@ -2721,7 +2819,7 @@
 
         test('exact match', () {
           var h = _Harness();
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(objectQVar, true)
               .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
               .ifFalse
@@ -2752,7 +2850,7 @@
 
         var h = _Harness();
 
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(x, true)
             .tryPromoteForTypeCheck(h, x, _Type('num?'))
             .ifTrue
@@ -2779,14 +2877,16 @@
       var objectQVar = _Var('x', _Type('Object?'));
 
       test('initialized', () {
-        var s = FlowModel<_Var, _Type>(true).declare(objectQVar, true);
+        var s = FlowModel<_Var, _Type>(Reachability.initial)
+            .declare(objectQVar, true);
         expect(s.variableInfo, {
           objectQVar: _matchVariableModel(assigned: true, unassigned: false),
         });
       });
 
       test('not initialized', () {
-        var s = FlowModel<_Var, _Type>(true).declare(objectQVar, false);
+        var s = FlowModel<_Var, _Type>(Reachability.initial)
+            .declare(objectQVar, false);
         expect(s.variableInfo, {
           objectQVar: _matchVariableModel(assigned: false, unassigned: true),
         });
@@ -2796,23 +2896,23 @@
     group('markNonNullable', () {
       test('unpromoted -> unchanged', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryMarkNonNullable(h, intVar).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> promoted', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryMarkNonNullable(h, intQVar).ifTrue;
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.infoFor(intQVar),
             _matchVariableModel(chain: ['int'], ofInterest: []));
       });
 
       test('promoted -> unchanged', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
@@ -2821,11 +2921,11 @@
 
       test('promoted -> re-promoted', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
             .ifTrue;
         var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar:
               _matchVariableModel(chain: ['int?', 'int'], ofInterest: ['int?'])
@@ -2834,9 +2934,9 @@
 
       test('promote to Never', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryMarkNonNullable(h, nullVar).ifTrue;
-        expect(s2.reachable, false);
+        expect(s2.reachable.overallReachable, false);
         expect(s2.infoFor(nullVar),
             _matchVariableModel(chain: ['Never'], ofInterest: []));
       });
@@ -2850,7 +2950,7 @@
           var a = _Var('a', _Type('int'));
           var b = _Var('b', _Type('int'));
 
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(a, false)
               .declare(b, false)
               .write(a, _Type('int'), h);
@@ -2876,7 +2976,7 @@
           var b = _Var('b', _Type('int'));
           var c = _Var('c', _Type('int'));
 
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(a, false)
               .declare(b, false)
               .declare(c, false)
@@ -2907,7 +3007,7 @@
     group('conservativeJoin', () {
       test('unchanged', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(intQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
@@ -2917,13 +3017,13 @@
 
       test('written', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue
             .tryPromoteForTypeCheck(h, intQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.conservativeJoin([intQVar], []);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
           intQVar: _matchVariableModel(chain: null, ofInterest: ['int'])
@@ -2932,13 +3032,13 @@
 
       test('write captured', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue
             .tryPromoteForTypeCheck(h, intQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.conservativeJoin([], [intQVar]);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
           intQVar: _matchVariableModel(
@@ -2950,7 +3050,7 @@
     group('restrict', () {
       test('reachability', () {
         var h = _Harness();
-        var reachable = FlowModel<_Var, _Type>(true);
+        var reachable = FlowModel<_Var, _Type>(Reachability.initial);
         var unreachable = reachable.setUnreachable();
         expect(reachable.restrict(h, reachable, Set()), same(reachable));
         expect(reachable.restrict(h, unreachable, Set()), same(unreachable));
@@ -2964,7 +3064,7 @@
         var b = _Var('b', _Type('int'));
         var c = _Var('c', _Type('int'));
         var d = _Var('d', _Type('int'));
-        var s0 = FlowModel<_Var, _Type>(true)
+        var s0 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(a, false)
             .declare(b, false)
             .declare(c, false)
@@ -2984,7 +3084,7 @@
         var b = _Var('b', _Type('int'));
         var c = _Var('c', _Type('int'));
         var d = _Var('d', _Type('int'));
-        var s0 = FlowModel<_Var, _Type>(true)
+        var s0 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(a, false)
             .declare(b, false)
             .declare(c, false)
@@ -3016,7 +3116,8 @@
             List<String> expectedChain) {
           var h = _Harness();
           var x = _Var('x', _Type('Object?'));
-          var s0 = FlowModel<_Var, _Type>(true).declare(x, true);
+          var s0 =
+              FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
           var s1 = thisType == null
               ? s0
               : s0.tryPromoteForTypeCheck(h, x, _Type(thisType)).ifTrue;
@@ -3068,7 +3169,8 @@
             List<String> inFinally, List<String> expectedResult) {
           var h = _Harness();
           var x = _Var('x', _Type('Object?'));
-          var initialModel = FlowModel<_Var, _Type>(true).declare(x, true);
+          var initialModel =
+              FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
           for (var t in before) {
             initialModel =
                 initialModel.tryPromoteForTypeCheck(h, x, _Type(t)).ifTrue;
@@ -3121,7 +3223,7 @@
       test('variable present in one state but not the other', () {
         var h = _Harness();
         var x = _Var('x', _Type('Object?'));
-        var s0 = FlowModel<_Var, _Type>(true);
+        var s0 = FlowModel<_Var, _Type>(Reachability.initial);
         var s1 = s0.declare(x, true);
         expect(s0.restrict(h, s1, {}), same(s0));
         expect(s0.restrict(h, s1, {x}), same(s0));
@@ -3490,10 +3592,10 @@
 
     test('inherits types of interest from other', () {
       var h = _Harness();
-      var m1 = FlowModel.withInfo(true, {
+      var m1 = FlowModel.withInfo(Reachability.initial, {
         x: model([intType])
       });
-      var m2 = FlowModel.withInfo(true, {
+      var m2 = FlowModel.withInfo(Reachability.initial, {
         x: model([stringType])
       });
       expect(m1.inheritTested(h, m2).variableInfo[x].tested,
@@ -3502,19 +3604,19 @@
 
     test('handles variable missing from other', () {
       var h = _Harness();
-      var m1 = FlowModel.withInfo(true, {
+      var m1 = FlowModel.withInfo(Reachability.initial, {
         x: model([intType])
       });
-      var m2 = FlowModel.withInfo(true, emptyMap);
+      var m2 = FlowModel.withInfo(Reachability.initial, emptyMap);
       expect(m1.inheritTested(h, m2), same(m1));
     });
 
     test('returns identical model when no changes', () {
       var h = _Harness();
-      var m1 = FlowModel.withInfo(true, {
+      var m1 = FlowModel.withInfo(Reachability.initial, {
         x: model([intType])
       });
-      var m2 = FlowModel.withInfo(true, {
+      var m2 = FlowModel.withInfo(Reachability.initial, {
         x: model([intType])
       });
       expect(m1.inheritTested(h, m2), same(m1));
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
index 3d890e8..35f2d63 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
@@ -55,6 +55,18 @@
   x;
 }
 
+localVariable_initialized_nonNull() {
+  num? x = 0;
+  /*num*/ x;
+  x = null;
+  x;
+}
+
+localVariable_initialized_nonNull_final() {
+  final num? x = 0;
+  x;
+}
+
 localVariable_initialized_promoted_type_var<T>(T t) {
   if (t is num) {
     var x = /*T & num*/ t;
@@ -94,13 +106,13 @@
 
 localVariable_initialized_promoted_type_var_typed<T>(T t) {
   if (t is num) {
-    // TODO(paulberry): This should promote to `T & Object`, because that's the
-    // non-nullable version of T, but it shouldn't promote to `T & num`.
+    // This should promote to `T & Object`, because that's the non-nullable
+    // version of T, but it shouldn't promote to `T & num`.
     T x = /*T & num*/ t;
-    x;
+    /*T & Object*/ x;
     // Check that `T & Object` is a type of interest by promoting and then
     // writing to it
-    if (x is int) {
+    if (/*T & Object*/ x is int) {
       /*T & int*/ x;
       x = /*T & num*/ t;
       /*T & Object*/ x;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 931cf38..bc2bbad 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -2004,12 +2004,17 @@
     }
 
     var initializer = node.initializer;
-    var parent = node.parent;
-    TypeAnnotation declaredType = (parent as VariableDeclarationList).type;
-    if (declaredType == null && initializer != null) {
+    var parent = node.parent as VariableDeclarationList;
+    TypeAnnotation declaredType = parent.type;
+    if (initializer != null) {
       var initializerStaticType = initializer.staticType;
-      if (initializerStaticType is TypeParameterType) {
-        _flowAnalysis?.flow?.promote(declaredElement, initializerStaticType);
+      if (declaredType == null) {
+        if (initializerStaticType is TypeParameterType) {
+          _flowAnalysis?.flow?.promote(declaredElement, initializerStaticType);
+        }
+      } else if (!parent.isFinal) {
+        _flowAnalysis?.flow?.write(declaredElement, initializerStaticType,
+            viaInitializer: true);
       }
     }
   }
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 9e96eec..3f0e79b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -5722,8 +5722,17 @@
     }
     if (initializerResult != null) {
       DartType initializerType = initializerResult.inferredType;
-      if (node.isImplicitlyTyped && initializerType is TypeParameterType) {
-        inferrer.flowAnalysis.promote(node, initializerType);
+      if (node.isImplicitlyTyped) {
+        if (initializerType is TypeParameterType) {
+          inferrer.flowAnalysis.promote(node, initializerType);
+        }
+      } else if (!node.isFinal) {
+        // TODO(paulberry): `initializerType` is sometimes `null` during top
+        // level inference.  Figure out how to prevent this.
+        if (initializerType != null) {
+          inferrer.flowAnalysis
+              .write(node, initializerType, viaInitializer: true);
+        }
       }
       Expression initializer = inferrer.ensureAssignableResult(
           node.type, initializerResult,
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index cd83c1b..1f0ca3c 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -555,6 +555,7 @@
 iterating
 iterations
 iterators
+ith
 j
 jacobr
 jakemac
@@ -867,6 +868,7 @@
 rc
 re
 reach
+reachabilities
 reachability
 react
 realign
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 267dd7a..b370368 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -431,6 +431,7 @@
 checked
 checker
 checking
+checkpoints
 checks
 child
 children
@@ -579,6 +580,7 @@
 conformed
 confuse
 confused
+conjunction
 connect
 connected
 connection
@@ -912,6 +914,7 @@
 drop
 dropped
 dropping
+drops
 due
 dump
 dumped
@@ -1773,6 +1776,7 @@
 main
 mainly
 maintain
+maintains
 major
 make
 makes
@@ -1844,6 +1848,7 @@
 might
 millisecond
 milliseconds
+mimics
 minimal
 minimum
 minor
@@ -1865,6 +1870,7 @@
 mock
 mode
 model
+modeling
 models
 modes
 modifiable
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
index 9af8d7f..7b083ef 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
@@ -14,8 +14,8 @@
         main() {
           dynamic x;
           print(x >>> 2);
-          Class? c = new Class();
+          Class? c = new Class() as Class?;
           print(c!);
         }
         class Class {}
-    expectedLibraryCount: 1
\ No newline at end of file
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart b/pkg/front_end/testcases/nnbd/issue41114.dart
index 7db889f..3929126 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 main() async {
-  List<String>? a = <String>[];
+  List<String>? a = <String>[] as List<String>?;
   Iterable<String>? b = a?.map((e) => e);
   Iterable<String>? i = b ?? a;
   print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
index 4b2167b..6fb76f5 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic async {
-  core::List<core::String>? a = <core::String>[];
+  core::List<core::String>? a = <core::String>[] as{ForNonNullableByDefault} core::List<core::String>?;
   core::Iterable<core::String>? b = let final core::List<core::String>? #t1 = a in #t1.{core::List::==}(null) ?{core::Iterable<core::String>?} null : #t1{core::List<core::String>}.{core::Iterable::map}<core::String>((core::String e) → core::String => e);
   core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2.{core::Object::==}(null) ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
   core::print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
index 4b2167b..6fb76f5 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic async {
-  core::List<core::String>? a = <core::String>[];
+  core::List<core::String>? a = <core::String>[] as{ForNonNullableByDefault} core::List<core::String>?;
   core::Iterable<core::String>? b = let final core::List<core::String>? #t1 = a in #t1.{core::List::==}(null) ?{core::Iterable<core::String>?} null : #t1{core::List<core::String>}.{core::Iterable::map}<core::String>((core::String e) → core::String => e);
   core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2.{core::Object::==}(null) ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
   core::print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart b/pkg/front_end/testcases/nnbd/issue41495.dart
index ceaf89a..cca6995 100644
--- a/pkg/front_end/testcases/nnbd/issue41495.dart
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart
@@ -10,7 +10,7 @@
 main() {}
 
 errors() {
-  A? a1 = new A();
+  A? a1 = new A() as A?;
   a1.c1;
   a1.test;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
index ecc36781..4df1b52 100644
--- a/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
@@ -27,7 +27,7 @@
 }
 static method main() → dynamic {}
 static method errors() → dynamic {
-  self::A? a1 = new self::A::•();
+  self::A? a1 = new self::A::•() as{ForNonNullableByDefault} self::A?;
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
 Try accessing using ?. instead.
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
index ecc36781..4df1b52 100644
--- a/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
@@ -27,7 +27,7 @@
 }
 static method main() → dynamic {}
 static method errors() → dynamic {
-  self::A? a1 = new self::A::•();
+  self::A? a1 = new self::A::•() as{ForNonNullableByDefault} self::A?;
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
 Try accessing using ?. instead.
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart b/pkg/front_end/testcases/nnbd/null_aware_chain.dart
index a53cacf..ff589af 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart
@@ -11,6 +11,6 @@
 }
 
 main() {
-  Class? c = new Class();
+  Class? c = new Class() as Class?;
   c?.getter1.getter2?.getter1.getter2?.field = c;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
index 267161a..4c16033 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
@@ -13,7 +13,7 @@
     return this.{self::Class::field};
 }
 static method main() → dynamic {
-  self::Class? c = new self::Class::•();
+  self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
   let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t2 = #t1{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t2.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t3 = #t2{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t3.{core::Object::==}(null) ?{self::Class?} null : #t3{self::Class}.{self::Class::field} = c{self::Class};
 }
 
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
index 267161a..4c16033 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
@@ -13,7 +13,7 @@
     return this.{self::Class::field};
 }
 static method main() → dynamic {
-  self::Class? c = new self::Class::•();
+  self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
   let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t2 = #t1{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t2.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t3 = #t2{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t3.{core::Object::==}(null) ?{self::Class?} null : #t3{self::Class}.{self::Class::field} = c{self::Class};
 }
 
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart b/pkg/front_end/testcases/nnbd/null_check.dart
index 110d74f..4cef88b 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart
+++ b/pkg/front_end/testcases/nnbd/null_check.dart
@@ -9,7 +9,7 @@
 }
 
 main() {
-  Class? c = new Class();
+  Class? c = new Class() as Class?;
   c!;
   c!.field;
   c!.field = 42;
@@ -22,7 +22,7 @@
   c + c!;
   (c + c)!;
 
-  bool? o = true;
+  bool? o = true as bool?;
   !o! ? !o! : !!o!!;
   !(o!) ? (!o)! : (!(!o)!)!;
-}
\ No newline at end of file
+}
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
index 26ca627..a1827fa 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
@@ -99,7 +99,7 @@
     return new self::Class::•();
 }
 static method main() → dynamic {
-  self::Class? c = new self::Class::•();
+  self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
   c!;
   c{self::Class}!.{self::Class::field};
   c{self::Class}!.{self::Class::field} = 42;
@@ -111,7 +111,7 @@
   c{self::Class}!.{self::Class::+}(c{self::Class}!);
   c{self::Class}.{self::Class::+}(c{self::Class}!);
   c{self::Class}.{self::Class::+}(c{self::Class})!;
-  core::bool? o = true;
+  core::bool? o = true as{ForNonNullableByDefault} core::bool?;
   !o! ?{core::bool} !o{core::bool}! : !!o{core::bool}!!;
   !o{core::bool}! ?{core::bool} (!o{core::bool})! : (!(!o{core::bool})!)!;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
index 26ca627..a1827fa 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
@@ -99,7 +99,7 @@
     return new self::Class::•();
 }
 static method main() → dynamic {
-  self::Class? c = new self::Class::•();
+  self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
   c!;
   c{self::Class}!.{self::Class::field};
   c{self::Class}!.{self::Class::field} = 42;
@@ -111,7 +111,7 @@
   c{self::Class}!.{self::Class::+}(c{self::Class}!);
   c{self::Class}.{self::Class::+}(c{self::Class}!);
   c{self::Class}.{self::Class::+}(c{self::Class})!;
-  core::bool? o = true;
+  core::bool? o = true as{ForNonNullableByDefault} core::bool?;
   !o! ?{core::bool} !o{core::bool}! : !!o{core::bool}!!;
   !o{core::bool}! ?{core::bool} (!o{core::bool})! : (!(!o{core::bool})!)!;
 }
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart b/pkg/front_end/testcases/nnbd/nullable_setter.dart
index 8e9d230..f644300 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart
@@ -19,7 +19,7 @@
 }
 
 main() {
-  C? c = new C();
+  C? c = new C() as C?;
   expect("", c?.m);
   c.setter = "42";
   expect("42", c?.m);
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect
index d367854..ac016f2 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect
@@ -21,7 +21,7 @@
   let final self::C? #t2 = #this in #t2.{core::Object::==}(null) ?{core::String?} null : #t2{self::C}.{self::C::m} = "${index}${value}";
 }
 static method main() → dynamic {
-  self::C? c = new self::C::•();
+  self::C? c = new self::C::•() as{ForNonNullableByDefault} self::C?;
   self::expect("", let final self::C? #t3 = c in #t3.{core::Object::==}(null) ?{core::String?} null : #t3{self::C}.{self::C::m});
   self::_extension#0|set#setter(c, "42");
   self::expect("42", let final self::C? #t4 = c in #t4.{core::Object::==}(null) ?{core::String?} null : #t4{self::C}.{self::C::m});
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect
index d367854..ac016f2 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect
@@ -21,7 +21,7 @@
   let final self::C? #t2 = #this in #t2.{core::Object::==}(null) ?{core::String?} null : #t2{self::C}.{self::C::m} = "${index}${value}";
 }
 static method main() → dynamic {
-  self::C? c = new self::C::•();
+  self::C? c = new self::C::•() as{ForNonNullableByDefault} self::C?;
   self::expect("", let final self::C? #t3 = c in #t3.{core::Object::==}(null) ?{core::String?} null : #t3{self::C}.{self::C::m});
   self::_extension#0|set#setter(c, "42");
   self::expect("42", let final self::C? #t4 = c in #t4.{core::Object::==}(null) ?{core::String?} null : #t4{self::C}.{self::C::m});
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
index 919f10f..06a5216 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
@@ -488,11 +488,11 @@
   new uns::OptInClass4::•().{uns::OptInClass4::methodForEffect}(i);
 }
 static method nullAwareIfNullSetOptIn(core::int i) → dynamic {
-  uns::OptInClass5? o = new uns::OptInClass5::•(i);
+  uns::OptInClass5? o = new uns::OptInClass5::•(i) as{ForNonNullableByDefault} uns::OptInClass5?;
   return let final uns::OptInClass5? #t66 = o in #t66.{core::Object::==}(null) ?{core::int?} null : let final core::int #t67 = #t66.{uns::OptInClass5::field} in #t67.{core::num::==}(null) ?{core::int} #t66.{uns::OptInClass5::field} = 42 : #t67;
 }
 static method nullAwareIfNullSetOptInForEffect(core::int i) → dynamic {
-  uns::OptInClass5? o = new uns::OptInClass5::•(i);
+  uns::OptInClass5? o = new uns::OptInClass5::•(i) as{ForNonNullableByDefault} uns::OptInClass5?;
   let final uns::OptInClass5? #t68 = o in #t68.{core::Object::==}(null) ?{core::int?} null : #t68.{uns::OptInClass5::field}.{core::num::==}(null) ?{core::int} #t68.{uns::OptInClass5::field} = 42 : null;
 }
 static method isTestOptIn(core::int i) → dynamic
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart b/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart
index 6dd9b47..738e03a 100644
--- a/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart
@@ -85,12 +85,12 @@
 }
 
 nullAwareIfNullSetOptIn(int i) {
-  OptInClass5? o = new OptInClass5(i);
+  OptInClass5? o = new OptInClass5(i) as OptInClass5?;
   return o?.field ??= 42;
 }
 
 nullAwareIfNullSetOptInForEffect(int i) {
-  OptInClass5? o = new OptInClass5(i);
+  OptInClass5? o = new OptInClass5(i) as OptInClass5?;
   o?.field ??= 42;
 }
 
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index 5a8f2bb..2140235 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -4626,7 +4626,7 @@
   // here non-null is OK.
   int i1 = 0, i2 = i1.gcd(2);
   // here non-null is not OK.
-  int? i3 = 0, i4 = i3!.gcd(2), i5 = null;
+  int? i3 = 0, i4 = i3.gcd(2), i5 = null;
 }
 ''';
 
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 7044628..e9f8516a 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -192,7 +192,7 @@
   V(::, reachabilityFence, ReachabilityFence, 0xad39d0a6)                      \
   V(_Utf8Decoder, _scan, Utf8DecoderScan, 0x78f44c3c)                          \
   V(_Future, timeout, FutureTimeout, 0x010f8ad4)                               \
-  V(Future, wait, FutureWait, 0x9a812df7)                                      \
+  V(Future, wait, FutureWait, 0x6c0c3295)                                      \
 
 // List of intrinsics:
 // (class-name, function-name, intrinsification method, fingerprint).
diff --git a/tests/language/await/null_aware_test.dart b/tests/language/await/null_aware_test.dart
index 819de12..88f16f0 100644
--- a/tests/language/await/null_aware_test.dart
+++ b/tests/language/await/null_aware_test.dart
@@ -13,11 +13,11 @@
 }
 
 main() async {
-  int? x = 1;
+  var x = 1 as int?;
   x ??= await f();
   Expect.equals(1, x);
 
-  int? y = 1;
+  var y = 1 as int?;
   y = y ?? await f();
   Expect.equals(1, y);
 }
diff --git a/tests/language/if_null/assignment_static_test.dart b/tests/language/if_null/assignment_static_test.dart
index 14edd3c..7eee56b 100644
--- a/tests/language/if_null/assignment_static_test.dart
+++ b/tests/language/if_null/assignment_static_test.dart
@@ -141,7 +141,7 @@
   // The static type of e1?.v op= e2 is the static type of e1.v op e2,
   // therefore the static type of e1?.v ??= e2 is the static type of
   // e1.v ?? e2, which is the LUB of NonNull(typeof(e1?.v)) and typeof(e2).
-  ClassWithInstanceGetters? c = new ClassWithInstanceGetters();
+  var c = new ClassWithInstanceGetters() as ClassWithInstanceGetters?;
   (c?.a ??= theA)!.a; //# 36: ok
   (c?.a ??= theA)!.b; //# 37: compile-time error
   (c?.a ??= theB)!.a; //# 38: ok
diff --git a/tests/language/if_null/behavior_test.dart b/tests/language/if_null/behavior_test.dart
index a679108..a55d7f5 100644
--- a/tests/language/if_null/behavior_test.dart
+++ b/tests/language/if_null/behavior_test.dart
@@ -32,8 +32,8 @@
 C? nullC() => null;
 
 main() {
-  int? one = 1;
-  B? b = B('B');
+  var one = 1 as int?;
+  var b = B('B') as B?;
   Expect.equals(1, one ?? 2);
   Expect.equals(1, one ?? null);
   Expect.equals(2, null ?? 2);
diff --git a/tests/language/if_null/evaluation_order_test.dart b/tests/language/if_null/evaluation_order_test.dart
index ca78ab4..c4da142 100644
--- a/tests/language/if_null/evaluation_order_test.dart
+++ b/tests/language/if_null/evaluation_order_test.dart
@@ -27,7 +27,7 @@
 }
 
 main() {
-  int? one = 1;
+  var one = 1 as int?;
   Expect.equals(1, one ?? bad());
   Expect.equals(2, first() ?? second());
 }
diff --git a/tests/language/implicit_downcast_during/if_null_assignment_test.dart b/tests/language/implicit_downcast_during/if_null_assignment_test.dart
index 7c91b32..c29d634 100644
--- a/tests/language/implicit_downcast_during/if_null_assignment_test.dart
+++ b/tests/language/implicit_downcast_during/if_null_assignment_test.dart
@@ -8,7 +8,7 @@
 
 void main() {
   B? b;
-  A? a = new B();
+  var a = new B() as A?;
   b ??= a;
 //      ^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
diff --git a/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart b/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart
index 535c7db..59c115e 100644
--- a/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart
+++ b/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart
@@ -11,7 +11,7 @@
 }
 
 main() {
-  C? c = new C();
+  var c = new C() as C?;
   A a = new B();
   c?.f(a);
 //     ^
diff --git a/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart b/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart
index 4366065..a2a8182 100644
--- a/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart
+++ b/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart
@@ -24,7 +24,7 @@
 class Derived extends Base {
   void test() {
     String string = 'foo';
-    String? stringQuestion = 'foo';
+    var stringQuestion = 'foo' as String?;
     super == string;
     //       ^^^^^^
     // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
diff --git a/tests/language/nnbd/syntax/class_member_declarations_test.dart b/tests/language/nnbd/syntax/class_member_declarations_test.dart
index 3aa7d26..a6c8efd 100644
--- a/tests/language/nnbd/syntax/class_member_declarations_test.dart
+++ b/tests/language/nnbd/syntax/class_member_declarations_test.dart
@@ -46,7 +46,7 @@
 
 main() {
   A? a;
-  String? s = '';
+  var s = '' as String?;
   a
     ?..foo().length
     ..x27 = s!.toString().length;
diff --git a/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart b/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
index b4b357e..131631e 100644
--- a/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
+++ b/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
@@ -43,7 +43,7 @@
   Expect.throws(() {
       x3 = a!;
   });
-  Object? x4 = 0;
+  var x4 = 0 as Object?;
   Expect.throws(() {
       x4 = a!;
   });
@@ -62,7 +62,7 @@
   // ignores its argument, and verify that the appropriate exception is still
   // thrown.
   var x6 = 2;
-  int? i = 2;
+  var i = 2 as int?;
   x6 * i!;
   var x7 = new C();
   i = null;
@@ -73,9 +73,9 @@
   // `-x!` means `-(x!)`, not `(-x)!`.  We check the compile-time behavior by
   // checking that the negation is accepted even though x is nullable.  We check
   // the runtime behavior by using an object whose operator- returns null.
-  int? x8 = 2;
+  var x8 = 2 as int?;
   -x8!;
-  C? x9 = new C();
+  var x9 = new C() as C?;
   var x10 = -x9!;
   Expect.isNull(x10);
 
diff --git a/tests/language/null_aware/access_runtime_2_test.dart b/tests/language/null_aware/access_runtime_2_test.dart
index b67de99..a1ade72 100644
--- a/tests/language/null_aware/access_runtime_2_test.dart
+++ b/tests/language/null_aware/access_runtime_2_test.dart
@@ -28,7 +28,7 @@
 
   // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
 
-  C? c = new C(1);
+  var c = new C(1) as C?;
   Expect.equals(1, c?.v);
 
   // C?.id is equivalent to C.id.
diff --git a/tests/language/null_aware/access_runtime_5_test.dart b/tests/language/null_aware/access_runtime_5_test.dart
index 5984802..6db60ce3 100644
--- a/tests/language/null_aware/access_runtime_5_test.dart
+++ b/tests/language/null_aware/access_runtime_5_test.dart
@@ -35,7 +35,7 @@
 
 
   // The static type of e1?.d is the static type of e1.id.
-  C? c = new C(1);
+  var c = new C(1) as C?;
   { int? i = c?.v; Expect.equals(1, i); }
 
 
diff --git a/tests/language/null_aware/access_test.dart b/tests/language/null_aware/access_test.dart
index 224a794..b2d1bc0 100644
--- a/tests/language/null_aware/access_test.dart
+++ b/tests/language/null_aware/access_test.dart
@@ -70,8 +70,8 @@
   //                           ^^^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
   // [cfe] The getter 'bad' isn't defined for the class 'C'.
-  { B? b = new C(1); Expect.equals(1, b?.v); }
-  //                                     ^
+  { var b = new C(1) as B?; Expect.equals(1, b?.v); }
+  //                                            ^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
   // [cfe] The getter 'v' isn't defined for the class 'B'.
 
diff --git a/tests/language/null_aware/assignment_runtime_11_test.dart b/tests/language/null_aware/assignment_runtime_11_test.dart
index 05b84a6..ca60103 100644
--- a/tests/language/null_aware/assignment_runtime_11_test.dart
+++ b/tests/language/null_aware/assignment_runtime_11_test.dart
@@ -77,7 +77,7 @@
 
 
   // The static type of e1?.v op= e2 is the static type of e1.v op e2.
-  { D? d = new D(new E()); F? f = (d?.v += 1); Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; F? f = (d?.v += 1); Expect.identical(d!.v, f); }
 
 
 
diff --git a/tests/language/null_aware/assignment_runtime_2_test.dart b/tests/language/null_aware/assignment_runtime_2_test.dart
index 825bfc6..bc0cdb6 100644
--- a/tests/language/null_aware/assignment_runtime_2_test.dart
+++ b/tests/language/null_aware/assignment_runtime_2_test.dart
@@ -50,7 +50,7 @@
 
   // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
 
-  { C? c = new C(1); Expect.equals(2, c?.v = 2); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(2, c?.v = 2); Expect.equals(2, c!.v); }
 
   // C?.v = e2 is equivalent to C.v = e2.
 
diff --git a/tests/language/null_aware/assignment_runtime_5_test.dart b/tests/language/null_aware/assignment_runtime_5_test.dart
index abcf60a..9507557 100644
--- a/tests/language/null_aware/assignment_runtime_5_test.dart
+++ b/tests/language/null_aware/assignment_runtime_5_test.dart
@@ -57,7 +57,7 @@
 
 
   // The static type of e1?.v = e2 is the static type of e2.
-  { D? d = new D(new E()); G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
+  { var d = new D(new E()) as D?; G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
 
 
 
diff --git a/tests/language/null_aware/assignment_runtime_9_test.dart b/tests/language/null_aware/assignment_runtime_9_test.dart
index 3c2d6c0..0a16c52 100644
--- a/tests/language/null_aware/assignment_runtime_9_test.dart
+++ b/tests/language/null_aware/assignment_runtime_9_test.dart
@@ -71,7 +71,7 @@
 
   // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
 
-  { C? c = new C(1); Expect.equals(3, c?.v += 2); Expect.equals(3, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(3, c?.v += 2); Expect.equals(3, c!.v); }
 
   // C?.v op= e2 is equivalent to C.v op= e2.
 
diff --git a/tests/language/null_aware/assignment_test.dart b/tests/language/null_aware/assignment_test.dart
index 112b0a6..d7bf2f4 100644
--- a/tests/language/null_aware/assignment_test.dart
+++ b/tests/language/null_aware/assignment_test.dart
@@ -59,9 +59,9 @@
   { h.C.staticInt = 1; Expect.equals(2, h.C?.staticInt = 2); Expect.equals(2, h.C.staticInt); }
 
   // The static type of e1?.v = e2 is the static type of e2.
-  { D? d = new D(new E()); G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
-  { D? d = new D(new E()); E e = new G(); F? f = (d?.v = e); }
-  //                                              ^^^^^^^^
+  { var d = new D(new E()) as D?; G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
+  { var d = new D(new E()) as D?; E e = new G(); F? f = (d?.v = e); }
+  //                                                     ^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   // [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
   { D.staticE = new E(); G g = new G(); F? f = (D?.staticE = g); Expect.identical(f, g); }
diff --git a/tests/language/null_aware/increment_decrement_runtime_12_test.dart b/tests/language/null_aware/increment_decrement_runtime_12_test.dart
index 03986fb..4e9c166 100644
--- a/tests/language/null_aware/increment_decrement_runtime_12_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_12_test.dart
@@ -68,7 +68,7 @@
 
 
   // The static type of e1?.v-- is the same as the static type of e1.v.
-  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v--; Expect.identical(e1, e2); }
+  { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v--; Expect.identical(e1, e2); }
 
 
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_16_test.dart b/tests/language/null_aware/increment_decrement_runtime_16_test.dart
index 1016d22..cfd1b8b 100644
--- a/tests/language/null_aware/increment_decrement_runtime_16_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_16_test.dart
@@ -77,7 +77,7 @@
 
   // ++e1?.v is equivalent to e1?.v += 1.
 
-  { C? c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
 
   // ++C?.v is equivalent to C?.v += 1.
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_19_test.dart b/tests/language/null_aware/increment_decrement_runtime_19_test.dart
index bb8c565..0677ac7 100644
--- a/tests/language/null_aware/increment_decrement_runtime_19_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_19_test.dart
@@ -84,7 +84,7 @@
 
 
   // The static type of ++e1?.v is the same as the static type of e1.v + 1.
-  { D? d = new D(new E()); F? f = ++d?.v; Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; F? f = ++d?.v; Expect.identical(d!.v, f); }
 
 
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_23_test.dart b/tests/language/null_aware/increment_decrement_runtime_23_test.dart
index b2dc6b5..2927351 100644
--- a/tests/language/null_aware/increment_decrement_runtime_23_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_23_test.dart
@@ -93,7 +93,7 @@
 
   // --e1?.v is equivalent to e1?.v -= 1.
 
-  { C? c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
 
   // --C?.v is equivalent to C?.v -= 1.
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_26_test.dart b/tests/language/null_aware/increment_decrement_runtime_26_test.dart
index 4201d15..903c33a 100644
--- a/tests/language/null_aware/increment_decrement_runtime_26_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_26_test.dart
@@ -100,7 +100,7 @@
 
 
   // The static type of --e1?.v is the same as the static type of e1.v - 1.
-  { D? d = new D(new E()); F? f = --d?.v; Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; F? f = --d?.v; Expect.identical(d!.v, f); }
 
 
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_2_test.dart b/tests/language/null_aware/increment_decrement_runtime_2_test.dart
index 67bca4a..3a29ccc 100644
--- a/tests/language/null_aware/increment_decrement_runtime_2_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_2_test.dart
@@ -45,7 +45,7 @@
 
   // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
 
-  { C? c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
 
   // C?.v++ is equivalent to C.v++.
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_5_test.dart b/tests/language/null_aware/increment_decrement_runtime_5_test.dart
index 8ca6c72..0cc85fb 100644
--- a/tests/language/null_aware/increment_decrement_runtime_5_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_5_test.dart
@@ -52,7 +52,7 @@
 
 
   // The static type of e1?.v++ is the same as the static type of e1.v.
-  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v++; Expect.identical(e1, e2); }
+  { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v++; Expect.identical(e1, e2); }
 
 
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_9_test.dart b/tests/language/null_aware/increment_decrement_runtime_9_test.dart
index cd3bd72..7b42679 100644
--- a/tests/language/null_aware/increment_decrement_runtime_9_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_9_test.dart
@@ -61,7 +61,7 @@
 
   // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
 
-  { C? c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
 
   // C?.v-- is equivalent to C.v--.
 
diff --git a/tests/language/null_aware/increment_decrement_test.dart b/tests/language/null_aware/increment_decrement_test.dart
index 0b620fc..7e80690 100644
--- a/tests/language/null_aware/increment_decrement_test.dart
+++ b/tests/language/null_aware/increment_decrement_test.dart
@@ -42,16 +42,16 @@
 
   // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
   Expect.equals(null, nullC()?.v++);
-  { C? c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
 
   // C?.v++ is equivalent to C.v++.
   { C.staticInt = 1; Expect.equals(1, C?.staticInt++); Expect.equals(2, C.staticInt); }
   { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt++); Expect.equals(2, h.C.staticInt); }
 
   // The static type of e1?.v++ is the same as the static type of e1.v.
-  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v++; Expect.identical(e1, e2); }
-  { G g = new G(); D? d = new D(g); F? f = d?.v++; Expect.identical(f, g); }
-  //                                       ^^^^^^
+  { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v++; Expect.identical(e1, e2); }
+  { G g = new G(); var d = new D(g) as D?; F? f = d?.v++; Expect.identical(f, g); }
+  //                                              ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   // [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
   { E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE++; Expect.identical(e1, e2); }
@@ -69,16 +69,16 @@
 
   // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
   Expect.equals(null, nullC()?.v--);
-  { C? c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
 
   // C?.v-- is equivalent to C.v--.
   { C.staticInt = 1; Expect.equals(1, C?.staticInt--); Expect.equals(0, C.staticInt); }
   { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt--); Expect.equals(0, h.C.staticInt); }
 
   // The static type of e1?.v-- is the same as the static type of e1.v.
-  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v--; Expect.identical(e1, e2); }
-  { G g = new G(); D? d = new D(g); F? f = d?.v--; Expect.identical(f, g); }
-  //                                       ^^^^^^
+  { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v--; Expect.identical(e1, e2); }
+  { G g = new G(); var d = new D(g) as D?; F? f = d?.v--; Expect.identical(f, g); }
+  //                                              ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   // [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
   { E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE--; Expect.identical(e1, e2); }
@@ -96,18 +96,18 @@
 
   // ++e1?.v is equivalent to e1?.v += 1.
   Expect.equals(null, ++nullC()?.v);
-  { C? c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
 
   // ++C?.v is equivalent to C?.v += 1.
   { C.staticInt = 1; Expect.equals(2, ++C?.staticInt); Expect.equals(2, C.staticInt); }
   { h.C.staticInt = 1; Expect.equals(2, ++h.C?.staticInt); Expect.equals(2, h.C.staticInt); }
 
   // The static type of ++e1?.v is the same as the static type of e1.v + 1.
-  { D? d = new D(new E()); F? f = ++d?.v; Expect.identical(d!.v, f); }
-  { D? d = new D(new E()); H? h = ++d?.v; Expect.identical(d!.v, h); }
-  //                              ^^^^^^
+  { var d = new D(new E()) as D?; F? f = ++d?.v; Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; H? h = ++d?.v; Expect.identical(d!.v, h); }
+  //                                     ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //                                ^
+  //                                       ^
   // [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
   { D.staticE = new E(); F? f = ++D?.staticE; Expect.identical(D.staticE, f); }
   { h.D.staticE = new h.E(); h.F? f = ++h.D?.staticE; Expect.identical(h.D.staticE, f); }
@@ -124,18 +124,18 @@
 
   // --e1?.v is equivalent to e1?.v -= 1.
   Expect.equals(null, --nullC()?.v);
-  { C? c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
 
   // --C?.v is equivalent to C?.v -= 1.
   { C.staticInt = 1; Expect.equals(0, --C?.staticInt); Expect.equals(0, C.staticInt); }
   { h.C.staticInt = 1; Expect.equals(0, --h.C?.staticInt); Expect.equals(0, h.C.staticInt); }
 
   // The static type of --e1?.v is the same as the static type of e1.v - 1.
-  { D? d = new D(new E()); F? f = --d?.v; Expect.identical(d!.v, f); }
-  { D? d = new D(new E()); H? h = --d?.v; Expect.identical(d!.v, h); }
-  //                              ^^^^^^
+  { var d = new D(new E()) as D?; F? f = --d?.v; Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; H? h = --d?.v; Expect.identical(d!.v, h); }
+  //                                     ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //                                ^
+  //                                       ^
   // [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
   { D.staticE = new E(); F? f = --D?.staticE; Expect.identical(D.staticE, f); }
   { h.D.staticE = new h.E(); h.F? f = --h.D?.staticE; Expect.identical(h.D.staticE, f); }
diff --git a/tests/language/null_aware/invocation_runtime_2_test.dart b/tests/language/null_aware/invocation_runtime_2_test.dart
index 70a36d1..8c11b27 100644
--- a/tests/language/null_aware/invocation_runtime_2_test.dart
+++ b/tests/language/null_aware/invocation_runtime_2_test.dart
@@ -32,7 +32,7 @@
 
   // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
 
-  C? c = C();
+  var c = C() as C?;
   Expect.equals(1, c?.f(() => 1));
 
   // C?.m(...) is equivalent to C.m(...).
diff --git a/tests/language/null_aware/invocation_runtime_6_test.dart b/tests/language/null_aware/invocation_runtime_6_test.dart
index 23559d8..bbabd59 100644
--- a/tests/language/null_aware/invocation_runtime_6_test.dart
+++ b/tests/language/null_aware/invocation_runtime_6_test.dart
@@ -41,7 +41,7 @@
   // The static type of o?.m(...) is the same as the static type of
   // o.m(...).
 
-  C? c = new C();
+  var c = new C() as C?;
   { int? i = c?.g(() => 1); Expect.equals(1, i); }
 
 
diff --git a/tests/language/null_aware/invocation_test.dart b/tests/language/null_aware/invocation_test.dart
index a1515fa..b1f38e6 100644
--- a/tests/language/null_aware/invocation_test.dart
+++ b/tests/language/null_aware/invocation_test.dart
@@ -23,7 +23,7 @@
 C? nullC() => null;
 
 main() {
-  C? c = C();
+  var c = C() as C?;
 
   // Make sure the "none" test fails if method invocation using "?." is not
   // implemented.  This makes status files easier to maintain.
@@ -66,12 +66,12 @@
   // Let T be the static type of o and let y be a fresh variable of type T.
   // Exactly the same static warnings that would be caused by y.m(...) are also
   // generated in the case of o?.m(...).
-  { B? b = new C(); Expect.equals(1, b?.f(() => 1)); }
-  //                                    ^
+  { var b = new C() as B?; Expect.equals(1, b?.f(() => 1)); }
+  //                                           ^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
   // [cfe] The method 'f' isn't defined for the class 'B'.
-  { int? i = 1; Expect.equals(null, nullC()?.f(i)); }
-  //                                           ^
+  { var i = 1 as int?; Expect.equals(null, nullC()?.f(i)); }
+  //                                                  ^
   // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
   // [cfe] The argument type 'int?' can't be assigned to the parameter type 'dynamic Function()?'.
 
diff --git a/tests/language/null_aware/null_shortening_test.dart b/tests/language/null_aware/null_shortening_test.dart
index b3510a5..625bc08 100644
--- a/tests/language/null_aware/null_shortening_test.dart
+++ b/tests/language/null_aware/null_shortening_test.dart
@@ -50,11 +50,11 @@
 
 main() {
   C1 c1 = C1();
-  C1? c1q = c1;
+  var c1q = c1 as C1?;
   C1? c1n = null;
 
   C2 c2 = C2();
-  C2? c2q = c2;
+  var c2q = c2 as C2?;
 
   // All selector operations short on null.
   // .foo
diff --git a/tests/language/null_aware/opt_test.dart b/tests/language/null_aware/opt_test.dart
index c5bb8a7..57f3848 100644
--- a/tests/language/null_aware/opt_test.dart
+++ b/tests/language/null_aware/opt_test.dart
@@ -23,17 +23,17 @@
 
 test() {
   var c;
-  C? d = new C(5);
+  var d = new C(5) as C?;
   Expect.equals(null, c?.m(bomb()));
   Expect.equals(null, getNull()?.anything(bomb()));
   Expect.equals(1, d?.m(1));
 
-  C? c2 = new C(1);
+  var c2 = new C(1) as C?;
   Expect.equals(1, c2?.f);
   Expect.equals(null, c?.v);
   Expect.equals(10, c ?? 10);
   Expect.equals(d, d ?? bomb());
-  List<List<int>>? list = [[3]];
+  var list = [[3]] as List<List<int>>?;
   Expect.equals(
       3,
       list?.expand((i) => i).toList()[0]);
@@ -58,7 +58,7 @@
   e?.f++;
   Expect.equals(201, e.f);
 
-  int? five = 5;
+  var five = 5 as int?;
   var x = five ?? bomb();
 }
 
diff --git a/tests/language/spread_collections/const_test.dart b/tests/language/spread_collections/const_test.dart
index 1eb4d76..cab125f 100644
--- a/tests/language/spread_collections/const_test.dart
+++ b/tests/language/spread_collections/const_test.dart
@@ -43,8 +43,8 @@
       const <int>[...<int>[...<int>[1, 2], ...<int>[3, 4]]]);
 
   // Null-aware.
-  const List<int>? list23 = <int>[2, 3];
-  const List<int>? list4 = <int>[4];
+  const list23 = <int>[2, 3] as List<int>?;
+  const list4 = <int>[4] as List<int>?;
   Expect.identical(list,
       const <int>[1, ...?list23, ...?(null), ...?list4]);
 
@@ -98,8 +98,8 @@
   });
 
   // Null-aware.
-  const Map<int, int>? map23 = <int, int>{2: 2, 3: 3};
-  const Map<int, int>? map4 = <int, int>{4: 4};
+  const map23 = <int, int>{2: 2, 3: 3} as Map<int, int>?;
+  const map4 = <int, int>{4: 4} as Map<int, int>?;
   Expect.identical(map, const <int, int>{
     1: 1,
     ...?map23,
@@ -155,8 +155,8 @@
   Expect.identical(set, const <int>{...<int>{...<int>[1, 2], ...<int>[3, 4]}});
 
   // Null-aware.
-  const List<int>? list23 = <int>[2, 3];
-  const List<int>? list4 = <int>[4];
+  const list23 = <int>[2, 3] as List<int>?;
+  const list4 = <int>[4] as List<int>?;
   Expect.identical(set,
       const <int>{1, ...?list23, ...?(null), ...?list4});
 
diff --git a/tests/language/spread_collections/spread_test.dart b/tests/language/spread_collections/spread_test.dart
index 2a19168..baee04c 100644
--- a/tests/language/spread_collections/spread_test.dart
+++ b/tests/language/spread_collections/spread_test.dart
@@ -43,8 +43,8 @@
   Expect.listEquals(list, <int>[...<int>[...<int>[1, 2], ...<int>[3, 4]]]);
 
   // Null-aware.
-  List<int>? list23 = [2, 3];
-  List<int>? list4 = [4];
+  var list23 = [2, 3] as List<int>?;
+  var list4 = [4] as List<int>?;
   Expect.listEquals(list, <int>[1, ...?list23, ...?(null), ...?list4]);
 
   // Does not deep flatten.
@@ -94,8 +94,8 @@
   });
 
   // Null-aware.
-  Map<int, int>? map23 = {2: 2, 3: 3};
-  Map<int, int>? map4 = {4: 4};
+  var map23 = {2: 2, 3: 3} as Map<int, int>?;
+  var map4 = {4: 4} as Map<int, int>?;
   Expect.mapEquals(map, <int, int>{
     1: 1,
     ...?map23,
@@ -147,8 +147,8 @@
   Expect.setEquals(set, <int>{...<int>{...<int>[1, 2], ...<int>[3, 4]}});
 
   // Null-aware.
-  List<int>? list23 = [2, 3];
-  List<int>? list4 = [4];
+  var list23 = [2, 3] as List<int>?;
+  var list4 = [4] as List<int>?;
   Expect.setEquals(set, <int>{1, ...?list23, ...?(null), ...?list4});
 
   // Does not deep flatten.
diff --git a/tests/language/spread_collections/syntax_test.dart b/tests/language/spread_collections/syntax_test.dart
index aa6a51f..ed6676f 100644
--- a/tests/language/spread_collections/syntax_test.dart
+++ b/tests/language/spread_collections/syntax_test.dart
@@ -17,11 +17,11 @@
 
   var a = [0];
   Expect.listEquals([1, 2, 3], [1, ...a = [2], 3]);
-  List<int>? nullableA = [0];
+  var nullableA = [0] as List<int>?;
   Expect.listEquals([1, 3], [1, ...?nullableA = null, 3]);
 
   var b = [2];
   Expect.listEquals([1, 2, 3, 4], [1, ...b..add(3), 4]);
-  List<int>? nullableB = [2];
+  var nullableB = [2] as List<int>?;
   Expect.listEquals([1, 2, 3, 4], [1, ...?nullableB?..add(3), 4]);
 }
diff --git a/tools/VERSION b/tools/VERSION
index 15ebdcb..e82a042 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 11
 PATCH 0
-PRERELEASE 195
+PRERELEASE 196
 PRERELEASE_PATCH 0
\ No newline at end of file