Version 2.10.0-92.0.dev

Merge commit '0c5f2a35328fc0b285c01710b6ea7f3a7d2e0713' 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 8c4699a..e6e8921 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
@@ -362,7 +362,16 @@
   void doStatement_end(Expression condition);
 
   /// Call this method just after visiting a binary `==` or `!=` expression.
-  void equalityOp_end(Expression wholeExpression, Expression rightOperand,
+  ///
+  /// Return value indicates whether flow analysis believes that a successful
+  /// equality check is reachable.  If `false` is returned, the client should
+  /// ensure that the `==` test behaves like `x == y && throw ...`.
+  ///
+  /// Note that if `notEqual` is `true`, then the return value describes the
+  /// behavior of the underlying `==` test.  So if `notEqual` is `true` and
+  /// `false` is returned, the client should ensure that the `!=` test behaves
+  /// like `!(x == y && throw ...)`.
+  bool equalityOp_end(Expression wholeExpression, Expression rightOperand,
       Type rightOperandType,
       {bool notEqual = false});
 
@@ -475,7 +484,13 @@
 
   /// Call this method after visiting the LHS of an if-null expression ("??")
   /// or if-null assignment ("??=").
-  void ifNullExpression_rightBegin(Expression leftHandSide);
+  ///
+  /// Return value indicates whether flow analysis believes that the right hand
+  /// side is reachable.  If `false` is returned, the client should ensure that
+  /// `x ?? y` behaves like `x ?? throw ...` (or, correspondingly, that
+  /// `x ??= y` behaves like `x ??= throw ...`).
+  bool ifNullExpression_rightBegin(
+      Expression leftHandSide, Type leftHandSideType);
 
   /// Call this method after visiting the "then" part of an if statement, and
   /// before visiting the "else" part.
@@ -511,7 +526,16 @@
   /// be the expression to which the "is" check was applied.  [isNot] should be
   /// a boolean indicating whether this is an "is" or an "is!" expression.
   /// [type] should be the type being checked.
-  void isExpression_end(
+  ///
+  /// Return value indicates whether flow analysis believes that a failure of
+  /// the `is` test is reachable.  If `false` is returned, the client should
+  /// ensure that the `is` test behaves like `x is T || throw ...`.
+  ///
+  /// Note that if `isNot` is `true`, then the return value describes the
+  /// behavior of the underlying `if` test.  So if `isNot` is `true` and `false`
+  /// is returned, the client should ensure that the `is!` test behaves like
+  /// `!(x is T || throw ...)`.
+  bool isExpression_end(
       Expression isExpression, Expression subExpression, bool isNot, Type type);
 
   /// Return whether the [variable] is definitely unassigned in the current
@@ -558,12 +582,22 @@
   /// [target] should be the expression just before the null-aware operator, or
   /// `null` if the null-aware access starts a cascade section.
   ///
+  /// [targetType] should be the type of the expression just before the
+  /// null-aware operator, and should be non-null even if the null-aware access
+  /// starts a cascade section.
+  ///
   /// Note that [nullAwareAccess_end] should be called after the conclusion
   /// of any null-shorting that is caused by the `?.`.  So, for example, if the
   /// code being analyzed is `x?.y?.z(x)`, [nullAwareAccess_rightBegin] should
   /// be called once upon reaching each `?.`, but [nullAwareAccess_end] should
   /// not be called until after processing the method call to `z(x)`.
-  void nullAwareAccess_rightBegin(Expression target);
+  ///
+  /// Return value indicates whether flow analysis believes that a null target
+  /// is reachable.  If `false` is returned, the client should ensure that
+  /// `x?.y` behaves like `x!.y`.  (Note that this is necessary even if `y`
+  /// exists on `Object`--see
+  /// https://github.com/dart-lang/language/issues/1143#issuecomment-682096575.)
+  bool nullAwareAccess_rightBegin(Expression target, Type targetType);
 
   /// Call this method when encountering an expression that is a `null` literal.
   void nullLiteral(Expression expression);
@@ -811,15 +845,17 @@
   }
 
   @override
-  void equalityOp_end(Expression wholeExpression, Expression rightOperand,
+  bool equalityOp_end(Expression wholeExpression, Expression rightOperand,
       Type rightOperandType,
       {bool notEqual = false}) {
-    _wrap(
+    return _wrap(
         'equalityOp_end($wholeExpression, $rightOperand, $rightOperandType, '
         'notEqual: $notEqual)',
         () => _wrapped.equalityOp_end(
             wholeExpression, rightOperand, rightOperandType,
-            notEqual: notEqual));
+            notEqual: notEqual),
+        isQuery: true,
+        isPure: false);
   }
 
   @override
@@ -902,9 +938,14 @@
   }
 
   @override
-  void ifNullExpression_rightBegin(Expression leftHandSide) {
-    return _wrap('ifNullExpression_rightBegin($leftHandSide)',
-        () => _wrapped.ifNullExpression_rightBegin(leftHandSide));
+  bool ifNullExpression_rightBegin(
+      Expression leftHandSide, Type leftHandSideType) {
+    return _wrap(
+        'ifNullExpression_rightBegin($leftHandSide, $leftHandSideType)',
+        () => _wrapped.ifNullExpression_rightBegin(
+            leftHandSide, leftHandSideType),
+        isQuery: true,
+        isPure: false);
   }
 
   @override
@@ -931,12 +972,14 @@
   }
 
   @override
-  void isExpression_end(Expression isExpression, Expression subExpression,
+  bool isExpression_end(Expression isExpression, Expression subExpression,
       bool isNot, Type type) {
-    _wrap(
+    return _wrap(
         'isExpression_end($isExpression, $subExpression, $isNot, $type)',
-        () => _wrapped.isExpression_end(
-            isExpression, subExpression, isNot, type));
+        () =>
+            _wrapped.isExpression_end(isExpression, subExpression, isNot, type),
+        isQuery: true,
+        isPure: false);
   }
 
   @override
@@ -991,9 +1034,10 @@
   }
 
   @override
-  void nullAwareAccess_rightBegin(Expression target) {
-    _wrap('nullAwareAccess_rightBegin($target)',
-        () => _wrapped.nullAwareAccess_rightBegin(target));
+  bool nullAwareAccess_rightBegin(Expression target, Type targetType) {
+    return _wrap('nullAwareAccess_rightBegin($target, $targetType)',
+        () => _wrapped.nullAwareAccess_rightBegin(target, targetType),
+        isQuery: true, isPure: false);
   }
 
   @override
@@ -2456,7 +2500,7 @@
   }
 
   @override
-  void equalityOp_end(Expression wholeExpression, Expression rightOperand,
+  bool equalityOp_end(Expression wholeExpression, Expression rightOperand,
       Type rightOperandType,
       {bool notEqual = false}) {
     _EqualityOpContext<Variable, Type> context =
@@ -2471,14 +2515,16 @@
         typeOperations.classifyType(rightOperandType);
     if (leftOperandTypeClassification == TypeClassification.nullOrEquivalent &&
         rightOperandTypeClassification == TypeClassification.nullOrEquivalent) {
-      return booleanLiteral(wholeExpression, !notEqual);
+      booleanLiteral(wholeExpression, !notEqual);
+      return true;
     } else if ((leftOperandTypeClassification ==
                 TypeClassification.nullOrEquivalent &&
             rightOperandTypeClassification == TypeClassification.nonNullable) ||
         (rightOperandTypeClassification ==
                 TypeClassification.nullOrEquivalent &&
             leftOperandTypeClassification == TypeClassification.nonNullable)) {
-      return booleanLiteral(wholeExpression, notEqual);
+      booleanLiteral(wholeExpression, notEqual);
+      return false;
     } else if (lhsInfo is _NullInfo<Variable, Type> &&
         rhsInfo is _VariableReadInfo<Variable, Type>) {
       assert(
@@ -2490,10 +2536,11 @@
       equalityInfo =
           _current.tryMarkNonNullable(typeOperations, lhsInfo._variable);
     } else {
-      return;
+      return true;
     }
     _storeExpressionInfo(wholeExpression,
         notEqual ? equalityInfo : ExpressionInfo.invert(equalityInfo));
+    return equalityInfo.ifFalse.reachable;
   }
 
   @override
@@ -2619,7 +2666,8 @@
   }
 
   @override
-  void ifNullExpression_rightBegin(Expression leftHandSide) {
+  bool ifNullExpression_rightBegin(
+      Expression leftHandSide, Type leftHandSideType) {
     ExpressionInfo<Variable, Type> lhsInfo = _getExpressionInfo(leftHandSide);
     FlowModel<Variable, Type> promoted;
     if (lhsInfo is _VariableReadInfo<Variable, Type>) {
@@ -2630,7 +2678,12 @@
     } else {
       promoted = _current;
     }
+    if (typeOperations.classifyType(leftHandSideType) ==
+        TypeClassification.nonNullable) {
+      _current = _current.setReachable(false);
+    }
     _stack.add(new _SimpleContext<Variable, Type>(promoted));
+    return _current.reachable;
   }
 
   @override
@@ -2670,7 +2723,7 @@
   }
 
   @override
-  void isExpression_end(Expression isExpression, Expression subExpression,
+  bool isExpression_end(Expression isExpression, Expression subExpression,
       bool isNot, Type type) {
     ExpressionInfo<Variable, Type> subExpressionInfo =
         _getExpressionInfo(subExpression);
@@ -2678,12 +2731,13 @@
     if (subExpressionInfo is _VariableReadInfo<Variable, Type>) {
       variable = subExpressionInfo._variable;
     } else {
-      return;
+      return true;
     }
     ExpressionInfo<Variable, Type> expressionInfo =
         _current.tryPromoteForTypeCheck(typeOperations, variable, type);
     _storeExpressionInfo(isExpression,
         isNot ? ExpressionInfo.invert(expressionInfo) : expressionInfo);
+    return expressionInfo.ifFalse.reachable;
   }
 
   @override
@@ -2760,8 +2814,16 @@
   }
 
   @override
-  void nullAwareAccess_rightBegin(Expression target) {
-    _stack.add(new _SimpleContext<Variable, Type>(_current));
+  bool nullAwareAccess_rightBegin(Expression target, Type targetType) {
+    assert(targetType != null);
+    bool shortingIsReachable = true;
+    FlowModel<Variable, Type> shortingModel = _current;
+    if (typeOperations.classifyType(targetType) ==
+        TypeClassification.nonNullable) {
+      shortingModel = shortingModel.setReachable(false);
+      shortingIsReachable = false;
+    }
+    _stack.add(new _SimpleContext<Variable, Type>(shortingModel));
     if (target != null) {
       ExpressionInfo<Variable, Type> targetInfo = _getExpressionInfo(target);
       if (targetInfo is _VariableReadInfo<Variable, Type>) {
@@ -2770,6 +2832,7 @@
             .ifTrue;
       }
     }
+    return shortingIsReachable;
   }
 
   @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 09e6023..d512956 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
@@ -185,15 +185,76 @@
         var nullExpr = _Expression();
         flow.nullLiteral(nullExpr);
         var expr = _Expression();
-        flow.equalityOp_end(expr, nullExpr, _Type('Null'), notEqual: true);
+        var successIsReachable =
+            flow.equalityOp_end(expr, nullExpr, _Type('Null'), notEqual: true);
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x).type, 'int');
         flow.ifStatement_elseBegin();
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x), isNull);
         flow.ifStatement_end(true);
       });
     });
 
+    test('equalityOp(x != null) when x is non-nullable', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var varExpr = _Expression();
+        flow.variableRead(varExpr, x);
+        flow.equalityOp_rightBegin(varExpr, _Type('int'));
+        var nullExpr = _Expression();
+        flow.nullLiteral(nullExpr);
+        var expr = _Expression();
+        var successIsReachable =
+            flow.equalityOp_end(expr, nullExpr, _Type('Null'), notEqual: true);
+        expect(successIsReachable, false);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.isReachable, true);
+        expect(flow.promotedType(x), isNull);
+        flow.ifStatement_elseBegin();
+        expect(flow.isReachable, false);
+        expect(flow.promotedType(x), isNull);
+        flow.ifStatement_end(true);
+      });
+    });
+
+    test('equalityOp(<expr> == <expr>) has no special effect', () {
+      var h = _Harness();
+      h.run((flow) {
+        flow.equalityOp_rightBegin(_Expression(), _Type('int?'));
+        var expr = _Expression();
+        var successIsReachable = flow.equalityOp_end(
+            expr, _Expression(), _Type('int?'),
+            notEqual: false);
+        expect(successIsReachable, true);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.isReachable, true);
+        flow.ifStatement_elseBegin();
+        expect(flow.isReachable, true);
+        flow.ifStatement_end(true);
+      });
+    });
+
+    test('equalityOp(<expr> != <expr>) has no special effect', () {
+      var h = _Harness();
+      h.run((flow) {
+        flow.equalityOp_rightBegin(_Expression(), _Type('int?'));
+        var expr = _Expression();
+        var successIsReachable = flow
+            .equalityOp_end(expr, _Expression(), _Type('int?'), notEqual: true);
+        expect(successIsReachable, true);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.isReachable, true);
+        flow.ifStatement_elseBegin();
+        expect(flow.isReachable, true);
+        flow.ifStatement_end(true);
+      });
+    });
+
     test('equalityOp(x != <null expr>) does not promote', () {
       var h = _Harness();
       var x = h.addVar('x', 'int?');
@@ -224,15 +285,43 @@
         var nullExpr = _Expression();
         flow.nullLiteral(nullExpr);
         var expr = _Expression();
-        flow.equalityOp_end(expr, nullExpr, _Type('Null'), notEqual: false);
+        var successIsReachable =
+            flow.equalityOp_end(expr, nullExpr, _Type('Null'), notEqual: false);
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x), isNull);
         flow.ifStatement_elseBegin();
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x).type, 'int');
         flow.ifStatement_end(true);
       });
     });
 
+    test('equalityOp(x == null) when x is non-nullable', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var varExpr = _Expression();
+        flow.variableRead(varExpr, x);
+        flow.equalityOp_rightBegin(varExpr, _Type('int'));
+        var nullExpr = _Expression();
+        flow.nullLiteral(nullExpr);
+        var expr = _Expression();
+        var successIsReachable =
+            flow.equalityOp_end(expr, nullExpr, _Type('Null'), notEqual: false);
+        expect(successIsReachable, false);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.isReachable, false);
+        expect(flow.promotedType(x), isNull);
+        flow.ifStatement_elseBegin();
+        expect(flow.isReachable, true);
+        expect(flow.promotedType(x), isNull);
+        flow.ifStatement_end(true);
+      });
+    });
+
     test('equalityOp(null != x) promotes true branch', () {
       var h = _Harness();
       var x = h.addVar('x', 'int?');
@@ -299,7 +388,9 @@
         flow.equalityOp_rightBegin(null1, _Type('Null'));
         var null2 = _Expression();
         var expr = _Expression();
-        flow.equalityOp_end(expr, null2, _Type('Null'));
+        var successIsReachable =
+            flow.equalityOp_end(expr, null2, _Type('Null'));
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
         expect(flow.isReachable, true);
         flow.ifStatement_elseBegin();
@@ -315,7 +406,9 @@
         flow.equalityOp_rightBegin(null1, _Type('Null'));
         var null2 = _Expression();
         var expr = _Expression();
-        flow.equalityOp_end(expr, null2, _Type('Null'), notEqual: true);
+        var successIsReachable =
+            flow.equalityOp_end(expr, null2, _Type('Null'), notEqual: true);
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
         expect(flow.isReachable, false);
         flow.ifStatement_elseBegin();
@@ -331,7 +424,8 @@
         flow.equalityOp_rightBegin(null1, _Type('Null'));
         var null2 = _Expression();
         var expr = _Expression();
-        flow.equalityOp_end(expr, null2, _Type('int'));
+        var successIsReachable = flow.equalityOp_end(expr, null2, _Type('int'));
+        expect(successIsReachable, false);
         flow.ifStatement_thenBegin(expr);
         expect(flow.isReachable, false);
         flow.ifStatement_elseBegin();
@@ -347,7 +441,9 @@
         flow.equalityOp_rightBegin(null1, _Type('Null'));
         var null2 = _Expression();
         var expr = _Expression();
-        flow.equalityOp_end(expr, null2, _Type('int'), notEqual: true);
+        var successIsReachable =
+            flow.equalityOp_end(expr, null2, _Type('int'), notEqual: true);
+        expect(successIsReachable, false);
         flow.ifStatement_thenBegin(expr);
         expect(flow.isReachable, true);
         flow.ifStatement_elseBegin();
@@ -363,7 +459,9 @@
         flow.equalityOp_rightBegin(null1, _Type('int'));
         var null2 = _Expression();
         var expr = _Expression();
-        flow.equalityOp_end(expr, null2, _Type('Null'));
+        var successIsReachable =
+            flow.equalityOp_end(expr, null2, _Type('Null'));
+        expect(successIsReachable, false);
         flow.ifStatement_thenBegin(expr);
         expect(flow.isReachable, false);
         flow.ifStatement_elseBegin();
@@ -379,7 +477,9 @@
         flow.equalityOp_rightBegin(null1, _Type('int'));
         var null2 = _Expression();
         var expr = _Expression();
-        flow.equalityOp_end(expr, null2, _Type('Null'), notEqual: true);
+        var successIsReachable =
+            flow.equalityOp_end(expr, null2, _Type('Null'), notEqual: true);
+        expect(successIsReachable, false);
         flow.ifStatement_thenBegin(expr);
         expect(flow.isReachable, true);
         flow.ifStatement_elseBegin();
@@ -885,10 +985,14 @@
       h.assignedVariables((vars) => vars.write(x));
       h.run((flow) {
         h.declare(x, initialized: true);
-        flow.ifNullExpression_rightBegin(h.variableRead(x)());
+        var rhsIsReachable = flow.ifNullExpression_rightBegin(
+            h.variableRead(x)(), _Type('int?'));
+        expect(rhsIsReachable, true);
+        expect(flow.isReachable, true);
         flow.write(x, _Type('int'));
         expect(flow.promotedType(x).type, 'int');
         flow.ifNullExpression_end();
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x).type, 'int');
       });
     });
@@ -898,10 +1002,14 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
-        flow.ifNullExpression_rightBegin(h.variableRead(x)());
+        var rhsIsReachable = flow.ifNullExpression_rightBegin(
+            h.variableRead(x)(), _Type('int?'));
+        expect(rhsIsReachable, true);
+        expect(flow.isReachable, true);
         h.promote(x, 'int');
         expect(flow.promotedType(x).type, 'int');
         flow.ifNullExpression_end();
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x).type, 'int');
       });
     });
@@ -911,14 +1019,43 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
-        flow.ifNullExpression_rightBegin(h.expr());
+        var rhsIsReachable =
+            flow.ifNullExpression_rightBegin(h.expr(), _Type('int?'));
+        expect(rhsIsReachable, true);
+        expect(flow.isReachable, true);
         h.promote(x, 'int');
         expect(flow.promotedType(x).type, 'int');
         flow.ifNullExpression_end();
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x), null);
       });
     });
 
+    test('ifNullExpression detects when RHS is unreachable', () {
+      var h = _Harness();
+      h.run((flow) {
+        var rhsIsReachable =
+            flow.ifNullExpression_rightBegin(h.expr(), _Type('int'));
+        expect(rhsIsReachable, false);
+        expect(flow.isReachable, false);
+        flow.ifNullExpression_end();
+        expect(flow.isReachable, true);
+      });
+    });
+
+    test('ifNullExpression determines reachability correctly for `Null` type',
+        () {
+      var h = _Harness();
+      h.run((flow) {
+        var rhsIsReachable =
+            flow.ifNullExpression_rightBegin(h.expr(), _Type('Null'));
+        expect(rhsIsReachable, true);
+        expect(flow.isReachable, true);
+        flow.ifNullExpression_end();
+        expect(flow.isReachable, true);
+      });
+    });
+
     test('ifStatement_end(false) keeps else branch if then branch exits', () {
       var h = _Harness();
       var x = h.addVar('x', 'int?');
@@ -932,11 +1069,12 @@
     });
 
     void _checkIs(
-      String declaredType,
-      String tryPromoteType,
-      String expectedPromotedTypeThen,
-      String expectedPromotedTypeElse,
-    ) {
+        String declaredType,
+        String tryPromoteType,
+        String expectedPromotedTypeThen,
+        String expectedPromotedTypeElse,
+        bool expectedFailureReachable,
+        {bool inverted = false}) {
       var h = _Harness();
       var x = h.addVar('x', declaredType);
       h.run((flow) {
@@ -944,14 +1082,18 @@
         var read = _Expression();
         flow.variableRead(read, x);
         var expr = _Expression();
-        flow.isExpression_end(expr, read, false, _Type(tryPromoteType));
+        var failureReachable =
+            flow.isExpression_end(expr, read, inverted, _Type(tryPromoteType));
+        expect(failureReachable, expectedFailureReachable);
         flow.ifStatement_thenBegin(expr);
+        expect(flow.isReachable, inverted ? expectedFailureReachable : true);
         if (expectedPromotedTypeThen == null) {
           expect(flow.promotedType(x), isNull);
         } else {
           expect(flow.promotedType(x).type, expectedPromotedTypeThen);
         }
         flow.ifStatement_elseBegin();
+        expect(flow.isReachable, inverted ? true : expectedFailureReachable);
         if (expectedPromotedTypeElse == null) {
           expect(flow.promotedType(x), isNull);
         } else {
@@ -962,15 +1104,61 @@
     }
 
     test('isExpression_end promotes to a subtype', () {
-      _checkIs('int?', 'int', 'int', 'Never?');
+      _checkIs('int?', 'int', 'int', 'Never?', true);
+    });
+
+    test('isExpression_end promotes to a subtype, inverted', () {
+      _checkIs('int?', 'int', 'Never?', 'int', true, inverted: true);
     });
 
     test('isExpression_end does not promote to a supertype', () {
-      _checkIs('int', 'int?', null, 'Never');
+      _checkIs('int', 'int?', null, 'Never', false);
+    });
+
+    test('isExpression_end does not promote to a supertype, inverted', () {
+      _checkIs('int', 'int?', 'Never', null, false, inverted: true);
     });
 
     test('isExpression_end does not promote to an unrelated type', () {
-      _checkIs('int', 'String', null, null);
+      _checkIs('int', 'String', null, null, true);
+    });
+
+    test('isExpression_end does not promote to an unrelated type, inverted',
+        () {
+      _checkIs('int', 'String', null, null, true, inverted: true);
+    });
+
+    test('isExpression_end does nothing if applied to a non-variable', () {
+      var h = _Harness();
+      h.run((flow) {
+        var subExpr = _Expression();
+        var expr = _Expression();
+        var failureReachable =
+            flow.isExpression_end(expr, subExpr, false, _Type('int'));
+        expect(failureReachable, true);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.isReachable, true);
+        flow.ifStatement_elseBegin();
+        expect(flow.isReachable, true);
+        flow.ifStatement_end(true);
+      });
+    });
+
+    test('isExpression_end does nothing if applied to a non-variable, inverted',
+        () {
+      var h = _Harness();
+      h.run((flow) {
+        var subExpr = _Expression();
+        var expr = _Expression();
+        var failureReachable =
+            flow.isExpression_end(expr, subExpr, true, _Type('int'));
+        expect(failureReachable, true);
+        flow.ifStatement_thenBegin(expr);
+        expect(flow.isReachable, true);
+        flow.ifStatement_elseBegin();
+        expect(flow.isReachable, true);
+        flow.ifStatement_end(true);
+      });
     });
 
     test('isExpression_end() does not promote write-captured vars', () {
@@ -1153,7 +1341,10 @@
         h.declare(x, initialized: true);
         var varExpr = _Expression();
         flow.variableRead(varExpr, x);
-        flow.nullAwareAccess_rightBegin(varExpr);
+        var shortIsReachable =
+            flow.nullAwareAccess_rightBegin(varExpr, _Type('int?'));
+        expect(shortIsReachable, true);
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x).type, 'int');
         flow.nullAwareAccess_end();
         expect(flow.promotedType(x), isNull);
@@ -1167,7 +1358,10 @@
         h.declare(x, initialized: true);
         var varExpr = _Expression();
         flow.variableRead(varExpr, x);
-        flow.nullAwareAccess_rightBegin(null);
+        var shortIsReachable =
+            flow.nullAwareAccess_rightBegin(null, _Type('int?'));
+        expect(shortIsReachable, true);
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x), isNull);
         flow.nullAwareAccess_end();
       });
@@ -1181,7 +1375,10 @@
         h.declare(x, initialized: true);
         h.promote(x, 'int');
         var lhs = _Expression();
-        flow.nullAwareAccess_rightBegin(lhs);
+        var shortIsReachable =
+            flow.nullAwareAccess_rightBegin(lhs, _Type('int'));
+        expect(shortIsReachable, false);
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x).type, 'int');
         flow.write(x, _Type('int?'));
         expect(flow.promotedType(x), isNull);
@@ -1190,6 +1387,24 @@
       });
     });
 
+    test('nullAwareAccess_end ignores shorting if target is non-nullable', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        var shortIsReachable =
+            flow.nullAwareAccess_rightBegin(_Expression(), _Type('int'));
+        expect(shortIsReachable, false);
+        expect(flow.isReachable, true);
+        h.promote(x, 'int');
+        expect(flow.promotedType(x).type, 'int');
+        flow.nullAwareAccess_end();
+        // `x` should still be promoted because the target was non-nullable, so
+        // the null shorting path was unreachable.
+        expect(flow.promotedType(x).type, 'int');
+      });
+    });
+
     test('parenthesizedExpression preserves promotion behaviors', () {
       var h = _Harness();
       var x = h.addVar('x', 'int?');
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/if_null.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/if_null.dart
new file mode 100644
index 0000000..0cc336e
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/if_null.dart
@@ -0,0 +1,331 @@
+// 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.
+
+void variable_if_null_reachable(int? i) {
+  i ?? 0;
+}
+
+void variable_if_null_assign_reachable(int? i) {
+  i ??= 0;
+}
+
+void variable_if_null_unreachable(int i) {
+  i ?? /*unreachable*/ 0;
+}
+
+void variable_if_null_assign_unreachable(int i) {
+  // Note: CFE reports that the update to `i` is unreachable; analyzer does not.
+  // This is ok; what matters is that the RHS is unreachable.
+  /*cfe.update: unreachable*/ i ??= /*unreachable*/ 0;
+}
+
+void variable_if_null_assign_unreachable_due_to_promotion(int? i) {
+  if (i == null) return;
+  // Note: CFE reports that the update to `i` is unreachable; analyzer does not.
+  // This is ok; what matters is that the RHS is unreachable.
+  /*cfe.update: unreachable*/ i ??= /*unreachable*/ 0;
+}
+
+/*member: topLevelNullable:doesNotComplete*/
+int? get topLevelNullable => 0;
+void set topLevelNullable(int? value) {}
+
+/*member: topLevelNonNullGet:doesNotComplete*/
+int get topLevelNonNullGet => 0;
+void set topLevelNonNullGet(int? value) {}
+
+void top_level_if_null_reachable() {
+  topLevelNullable ?? 0;
+}
+
+void top_level_if_null_assign_reachable() {
+  topLevelNullable ??= 0;
+}
+
+void top_level_if_null_unreachable() {
+  topLevelNonNullGet ?? /*unreachable*/ 0;
+}
+
+void top_level_if_null_assign_unreachable() {
+  // Note: CFE reports that the update to `topLevelNonNullGet` is unreachable;
+  // analyzer does not.  This is ok; what matters is that the RHS is
+  // unreachable.
+  topLevelNonNullGet /*cfe.update: unreachable*/ ??= /*unreachable*/ 0;
+}
+
+class HasProperty<T> {
+  /*member: HasProperty.prop:doesNotComplete*/
+  T get prop => throw '';
+  set prop(T? value) {}
+}
+
+void property_if_null_reachable(HasProperty<int?> x) {
+  x.prop ?? 0;
+}
+
+void property_if_null_assign_reachable(HasProperty<int?> x) {
+  x.prop ??= 0;
+}
+
+void property_if_null_unreachable(HasProperty<int> x) {
+  x.prop ?? /*unreachable*/ 0;
+}
+
+void property_if_null_assign_unreachable(HasProperty<int> x) {
+  x.prop ??= /*unreachable*/ 0;
+}
+
+void null_aware_property_if_null_reachable(HasProperty<int?>? x) {
+  x?.prop ?? 0;
+}
+
+void null_aware_property_if_null_assign_reachable(HasProperty<int?>? x) {
+  x?.prop ??= 0;
+}
+
+void null_aware_property_if_null_not_shortened(HasProperty<int>? x) {
+  // If `??` participated in null-shortening, `0` would be unreachable.
+  x?.prop ?? 0;
+}
+
+void null_aware_property_if_null_assign_unreachable(HasProperty<int>? x) {
+  x?.prop ??= /*unreachable*/ 0;
+}
+
+class SuperIntQuestionProperty extends HasProperty<int?> {
+  void if_null_reachable() {
+    super.prop ?? 0;
+  }
+
+  void if_null_assign_reachable() {
+    super.prop ??= 0;
+  }
+}
+
+class SuperIntProperty extends HasProperty<int> {
+  void if_null_unreachable() {
+    super.prop ?? /*unreachable*/ 0;
+  }
+
+  void if_null_assign_unreachable() {
+    super.prop ??= /*unreachable*/ 0;
+  }
+}
+
+extension ExtensionProperty<T> on HasProperty<T> {
+  /*member: ExtensionProperty|get#extendedProp:doesNotComplete*/
+  T get extendedProp => prop;
+  set extendedProp(T? value) {
+    prop = value;
+  }
+}
+
+void extended_property_if_null_reachable(HasProperty<int?> x) {
+  x.extendedProp ?? 0;
+}
+
+void extended_property_if_null_assign_reachable(HasProperty<int?> x) {
+  x.extendedProp ??= 0;
+}
+
+void extended_property_if_null_unreachable(HasProperty<int> x) {
+  x.extendedProp ?? /*unreachable*/ 0;
+}
+
+void extended_property_if_null_assign_unreachable(HasProperty<int> x) {
+  x.extendedProp ??= /*unreachable*/ 0;
+}
+
+void null_aware_extended_property_if_null_reachable(HasProperty<int?>? x) {
+  x?.extendedProp ?? 0;
+}
+
+void null_aware_extended_property_if_null_assign_reachable(
+    HasProperty<int?>? x) {
+  x?.extendedProp ??= 0;
+}
+
+void null_aware_extended_property_if_null_not_shortened(HasProperty<int>? x) {
+  // If `??` participated in null-shortening, `0` would be unreachable.
+  x?.extendedProp ?? 0;
+}
+
+void null_aware_extended_property_if_null_assign_unreachable(
+    HasProperty<int>? x) {
+  x?.extendedProp ??= /*unreachable*/ 0;
+}
+
+void explicit_extended_property_if_null_reachable(HasProperty<int?> x) {
+  ExtensionProperty(x).extendedProp ?? 0;
+}
+
+void explicit_extended_property_if_null_assign_reachable(HasProperty<int?> x) {
+  ExtensionProperty(x).extendedProp ??= 0;
+}
+
+void explicit_extended_property_if_null_unreachable(HasProperty<int> x) {
+  ExtensionProperty(x).extendedProp ?? /*unreachable*/ 0;
+}
+
+void explicit_extended_property_if_null_assign_unreachable(HasProperty<int> x) {
+  ExtensionProperty(x).extendedProp ??= /*unreachable*/ 0;
+}
+
+void null_aware_explicit_extended_property_if_null_reachable(
+    HasProperty<int?>? x) {
+  ExtensionProperty(x)?.extendedProp ?? 0;
+}
+
+void null_aware_explicit_extended_property_if_null_assign_reachable(
+    HasProperty<int?>? x) {
+  ExtensionProperty(x)?.extendedProp ??= 0;
+}
+
+void null_aware_explicit_extended_property_if_null_not_shortened(
+    HasProperty<int>? x) {
+  // If `??` participated in null-shortening, `0` would be unreachable.
+  ExtensionProperty(x)?.extendedProp ?? 0;
+}
+
+void null_aware_explicit_extended_property_if_null_assign_unreachable(
+    HasProperty<int>? x) {
+  ExtensionProperty(x)?.extendedProp ??= /*unreachable*/ 0;
+}
+
+class Indexable<T> {
+  /*member: Indexable.[]:doesNotComplete*/
+  T operator [](int index) => throw '';
+  operator []=(int index, T? value) {}
+}
+
+void index_if_null_reachable(Indexable<int?> x) {
+  x[0] ?? 0;
+}
+
+void index_if_null_unreachable(Indexable<int> x) {
+  x[0] ?? /*unreachable*/ 0;
+}
+
+void index_if_null_assign_reachable(Indexable<int?> x) {
+  x[0] ??= 0;
+}
+
+void index_if_null_assign_unreachable(Indexable<int> x) {
+  x[0] ??= /*unreachable*/ 0;
+}
+
+void null_aware_index_if_null_reachable(Indexable<int?>? x) {
+  x?[0] ?? 0;
+}
+
+void null_aware_index_if_null_unreachable(Indexable<int>? x) {
+  // If `??` participated in null-shortening, `0` would be unreachable.
+  x?[0] ?? 0;
+}
+
+void null_aware_index_if_null_assign_reachable(Indexable<int?>? x) {
+  x?[0] ??= 0;
+}
+
+void null_aware_index_if_null_assign_unreachable(Indexable<int>? x) {
+  x?[0] ??= /*unreachable*/ 0;
+}
+
+class SuperIntQuestionIndex extends Indexable<int?> {
+  void if_null_reachable() {
+    super[0] ?? 0;
+  }
+
+  void if_null_assign_reachable() {
+    super[0] ??= 0;
+  }
+}
+
+class SuperIntIndex extends Indexable<int> {
+  void if_null_unreachable() {
+    super[0] ?? /*unreachable*/ 0;
+  }
+
+  void if_null_assign_unreachable() {
+    super[0] ??= /*unreachable*/ 0;
+  }
+}
+
+extension ExtensionIndex<T> on HasProperty<T> {
+  /*member: ExtensionIndex|[]:doesNotComplete*/
+  T operator [](int index) => prop;
+  operator []=(int index, T? value) {
+    prop = value;
+  }
+}
+
+void extended_index_if_null_reachable(HasProperty<int?> x) {
+  x[0] ?? 0;
+}
+
+void extended_index_if_null_assign_reachable(HasProperty<int?> x) {
+  x[0] ??= 0;
+}
+
+void extended_index_if_null_unreachable(HasProperty<int> x) {
+  x[0] ?? /*unreachable*/ 0;
+}
+
+void extended_index_if_null_assign_unreachable(HasProperty<int> x) {
+  x[0] ??= /*unreachable*/ 0;
+}
+
+void null_aware_extended_index_if_null_reachable(HasProperty<int?>? x) {
+  x?[0] ?? 0;
+}
+
+void null_aware_extended_index_if_null_assign_reachable(HasProperty<int?>? x) {
+  x?[0] ??= 0;
+}
+
+void null_aware_extended_index_if_null_not_shortened(HasProperty<int>? x) {
+  // If `??` participated in null-shortening, `0` would be unreachable.
+  x?[0] ?? 0;
+}
+
+void null_aware_extended_index_if_null_assign_unreachable(HasProperty<int>? x) {
+  x?[0] ??= /*unreachable*/ 0;
+}
+
+void explicit_extended_index_if_null_reachable(HasProperty<int?> x) {
+  ExtensionIndex(x)[0] ?? 0;
+}
+
+void explicit_extended_index_if_null_assign_reachable(HasProperty<int?> x) {
+  ExtensionIndex(x)[0] ??= 0;
+}
+
+void explicit_extended_index_if_null_unreachable(HasProperty<int> x) {
+  ExtensionIndex(x)[0] ?? /*unreachable*/ 0;
+}
+
+void explicit_extended_index_if_null_assign_unreachable(HasProperty<int> x) {
+  ExtensionIndex(x)[0] ??= /*unreachable*/ 0;
+}
+
+void null_aware_explicit_extended_index_if_null_reachable(
+    HasProperty<int?>? x) {
+  ExtensionIndex(x)?[0] ?? 0;
+}
+
+void null_aware_explicit_extended_index_if_null_assign_reachable(
+    HasProperty<int?>? x) {
+  ExtensionIndex(x)?[0] ??= 0;
+}
+
+void null_aware_explicit_extended_index_if_null_not_shortened(
+    HasProperty<int>? x) {
+  // If `??` participated in null-shortening, `0` would be unreachable.
+  ExtensionIndex(x)?[0] ?? 0;
+}
+
+void null_aware_explicit_extended_index_if_null_assign_unreachable(
+    HasProperty<int>? x) {
+  ExtensionIndex(x)?[0] ??= /*unreachable*/ 0;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access.dart
new file mode 100644
index 0000000..a204bf8
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access.dart
@@ -0,0 +1,131 @@
+// 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.
+
+void index_reachable(List<int>? f()) {
+  f()?[throw ''];
+  0;
+}
+
+/*member: index_unreachable:doesNotComplete*/
+void index_unreachable(List<int> f()) {
+  f()?[throw ''];
+  /*stmt: unreachable*/ 0;
+}
+
+void cascaded_index_reachable(List<int>? f()) {
+  f()?..[throw ''];
+  0;
+}
+
+/*member: cascaded_index_unreachable:doesNotComplete*/
+void cascaded_index_unreachable(List<int> f()) {
+  f()?..[throw ''];
+  /*stmt: unreachable*/ 0;
+}
+
+void method_invocation_reachable(int? f()) {
+  f()?.remainder(throw '');
+  0;
+}
+
+/*member: method_invocation_unreachable:doesNotComplete*/
+void method_invocation_unreachable(int f()) {
+  f()?.remainder(throw '');
+  /*stmt: unreachable*/ 0;
+}
+
+void cascaded_method_invocation_reachable(int? f()) {
+  f()?..remainder(throw '');
+  0;
+}
+
+/*member: cascaded_method_invocation_unreachable:doesNotComplete*/
+void cascaded_method_invocation_unreachable(int f()) {
+  f()?..remainder(throw '');
+  /*stmt: unreachable*/ 0;
+}
+
+void property_get_reachable(int? f()) {
+  f()?.hashCode.remainder(throw '');
+  0;
+}
+
+/*member: property_get_unreachable:doesNotComplete*/
+void property_get_unreachable(int f()) {
+  f()?.hashCode.remainder(throw '');
+  /*stmt: unreachable*/ 0;
+}
+
+void cascaded_property_get_reachable(int? f()) {
+  f()?..hashCode.remainder(throw '');
+  0;
+}
+
+/*member: cascaded_property_get_unreachable:doesNotComplete*/
+void cascaded_property_get_unreachable(int f()) {
+  f()?..hashCode.remainder(throw '');
+  /*stmt: unreachable*/ 0;
+}
+
+void property_get_invocation_reachable(List<void Function(dynamic)>? f()) {
+  // We need a special test case for this because it parses like a method
+  // invocation but the analyzer rewrites it as a property access followed by a
+  // function expression invocation.
+  f()?.first(throw '');
+  0;
+}
+
+/*member: property_get_invocation_unreachable:doesNotComplete*/
+void property_get_invocation_unreachable(List<void Function(dynamic)> f()) {
+  // We need a special test case for this because it parses like a method
+  // invocation but the analyzer rewrites it as a property access followed by a
+  // function expression invocation.
+  f()?.first(throw '');
+  /*stmt: unreachable*/ 0;
+}
+
+void cascaded_property_get_invocation_reachable(
+    List<void Function(dynamic)>? f()) {
+  // We need a special test case for this because it parses like a method
+  // invocation but the analyzer rewrites it as a property access followed by a
+  // function expression invocation.
+  f()?..first(throw '');
+  0;
+}
+
+/*member: cascaded_property_get_invocation_unreachable:doesNotComplete*/
+void cascaded_property_get_invocation_unreachable(
+    List<void Function(dynamic)> f()) {
+  // We need a special test case for this because it parses like a method
+  // invocation but the analyzer rewrites it as a property access followed by a
+  // function expression invocation.
+  f()?..first(throw '');
+  /*stmt: unreachable*/ 0;
+}
+
+class C {
+  int field = 0;
+}
+
+void property_set_reachable(C? f()) {
+  f()?.field = throw '';
+  0;
+}
+
+/*member: property_set_unreachable:doesNotComplete*/
+void property_set_unreachable(C f()) {
+  f()?.field = throw '';
+  /*stmt: unreachable*/ 0;
+}
+
+void cascaded_property_set_reachable(C? f()) {
+  f()?..field = throw '';
+  0;
+}
+
+/*member: cascaded_property_set_unreachable:doesNotComplete*/
+void cascaded_property_set_unreachable(C f()) {
+  f()?..field = throw '';
+  /*stmt: unreachable*/ 0;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access_static.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access_static.dart
new file mode 100644
index 0000000..4edebe4
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access_static.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C {
+  static void staticMethod(dynamic d) {}
+  /*member: C.staticGetter:doesNotComplete*/
+  static int get staticGetter => 0;
+  /*member: C.staticInvokableGetter:doesNotComplete*/
+  static void Function(dynamic d) get staticInvokableGetter => (_) {};
+  static void set staticSetter(int value) {}
+}
+
+/*member: method_invocation_unreachable:doesNotComplete*/
+void method_invocation_unreachable() {
+  C?.staticMethod(throw '');
+  /*stmt: unreachable*/ 0;
+}
+
+/*member: property_get_unreachable:doesNotComplete*/
+void property_get_unreachable() {
+  C?.staticGetter.remainder(throw '');
+  /*stmt: unreachable*/ 0;
+}
+
+/*member: property_get_invocation_unreachable:doesNotComplete*/
+void property_get_invocation_unreachable() {
+  // We need a special test case for this because it parses like a method
+  // invocation but the analyzer rewrites it as a property access followed by a
+  // function expression invocation.
+  C?.staticInvokableGetter(throw '');
+  /*stmt: unreachable*/ 0;
+}
+
+/*member: property_set_unreachable:doesNotComplete*/
+void property_set_unreachable() {
+  C?.staticSetter = throw '';
+  /*stmt: unreachable*/ 0;
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
index d6330c2..f5e89d2 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -16,22 +16,63 @@
 class TransformSetParser {
   static const String _changesKey = 'changes';
 
-  static const String _componentsKey = 'components';
+  static const String _classKey = 'class';
+
+  static const String _constructorKey = 'constructor';
 
   static const String _elementKey = 'element';
 
+  static const String _enumConstantKey = 'constant';
+
+  static const String _enumKey = 'enum';
+
+  static const String _extensionKey = 'extension';
+
+  static const String _fieldKey = 'field';
+
+  static const String _functionKey = 'function';
+
+  static const String _getterKey = 'getter';
+
+  static const String _inClassKey = 'inClass';
+
+  static const String _inEnumKey = 'inEnum';
+
+  static const String _inExtensionKey = 'inExtension';
+
+  static const String _inMixinKey = 'inMixin';
+
   static const String _kindKey = 'kind';
 
+  static const String _methodKey = 'method';
+
+  static const String _mixinKey = 'mixin';
+
   static const String _newNameKey = 'newName';
 
+  static const String _setterKey = 'setter';
+
   static const String _titleKey = 'title';
 
   static const String _transformsKey = 'transforms';
 
+  static const String _typedefKey = 'typedef';
+
   static const String _urisKey = 'uris';
 
   static const String _versionKey = 'version';
 
+  /// A table mapping top-level keys for member elements to the list of keys for
+  /// the possible containers of that element.
+  static const Map<String, List<String>> _containerKeyMap = {
+    _constructorKey: [_inClassKey],
+    _enumConstantKey: [_inEnumKey],
+    _fieldKey: [_inClassKey, _inExtensionKey, _inMixinKey],
+    _getterKey: [_inClassKey, _inExtensionKey, _inMixinKey],
+    _methodKey: [_inClassKey, _inExtensionKey, _inMixinKey],
+    _setterKey: [_inClassKey, _inExtensionKey, _inMixinKey],
+  };
+
   static const String _renameKind = 'rename';
 
   static const int currentVersion = 1;
@@ -91,6 +132,34 @@
     }
   }
 
+  /// Given a [map] and a set of [validKeys], ensure that only one of those keys
+  /// is in the map and return it. If more than one of the keys is in the map,
+  /// report a diagnostic.
+  String _singleKey(YamlMap map, List<String> validKeys) {
+    if (validKeys == null) {
+      return null;
+    }
+    var foundKeys = <String>[];
+    var keyToNodeMap = <String, YamlNode>{};
+    for (var keyNode in map.nodes.keys) {
+      if (keyNode is YamlScalar) {
+        var key = _translateString(keyNode);
+        if (key != null && validKeys.contains(key)) {
+          foundKeys.add(key);
+          keyToNodeMap[key] = keyNode;
+        }
+      }
+    }
+    if (foundKeys.isEmpty) {
+      return null;
+    }
+    for (var i = 1; i < foundKeys.length; i++) {
+      // var invalidNode = keyToNodeMap[foundKeys[i]];
+      // TODO(brianwilkerson) Report the invalid key.
+    }
+    return foundKeys[0];
+  }
+
   /// Translate the [node] into a change. Return the resulting change, or `null`
   /// if the [node] does not represent a valid change.
   Change _translateChange(YamlNode node) {
@@ -118,15 +187,42 @@
     if (node is YamlMap) {
       var uris = _translateList(node.valueAt(_urisKey), _translateString);
       if (uris == null) {
+        // TODO(brianwilkerson) Returning here prevents other errors from being
+        //  reported.
         // The error has already been reported.
         return null;
       }
-      var components =
-          _translateList(node.valueAt(_componentsKey), _translateString);
-      if (components == null) {
+      var elementKey = _singleKey(node, [
+        _classKey,
+        _enumConstantKey,
+        _constructorKey,
+        _enumKey,
+        _extensionKey,
+        _fieldKey,
+        _functionKey,
+        _getterKey,
+        _methodKey,
+        _mixinKey,
+        _setterKey,
+        _typedefKey
+      ]);
+      var elementName = _translateString(node.valueAt(elementKey));
+      if (elementName == null) {
         // The error has already been reported.
         return null;
       }
+      var components = [elementName];
+      var containerKey = _singleKey(node, _containerKeyMap[elementKey]);
+      var containerName = _translateString(node.valueAt(containerKey));
+      if (containerName == null) {
+        if ([_constructorKey, _enumConstantKey, _methodKey, _fieldKey]
+            .contains(elementKey)) {
+          // TODO(brianwilkerson) Report that no container was found.
+          return null;
+        }
+      } else {
+        components.insert(0, containerName);
+      }
       return ElementDescriptor(libraryUris: uris, components: components);
     } else if (node == null) {
       // TODO(brianwilkerson) Report the missing YAML.
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/end_to_end_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/end_to_end_test.dart
index e483534..58dd53a 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/end_to_end_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/end_to_end_test.dart
@@ -25,8 +25,7 @@
   element:
     uris:
       - '$importUri'
-    components:
-      - 'Old'
+    class: 'Old'
   changes:
     - kind: 'rename'
       newName: 'New'
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
index 336979b..f36fef5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
@@ -18,6 +18,59 @@
 
 @reflectiveTest
 class TransformSetParserTest extends AbstractTransformSetParserTest {
+  void test_element_getter_inMixin() {
+    parse('''
+version: 1
+transforms:
+- title: 'Rename g'
+  element:
+    uris: ['test.dart']
+    getter: 'g'
+    inMixin: 'A'
+  changes: []
+''');
+    var transforms = result.transformsFor('g', ['test.dart']);
+    expect(transforms, hasLength(1));
+    var transform = transforms[0];
+    expect(transform.title, 'Rename g');
+    expect(transform.changes, isEmpty);
+  }
+
+  void test_element_getter_topLevel() {
+    parse('''
+version: 1
+transforms:
+- title: 'Rename g'
+  element:
+    uris: ['test.dart']
+    getter: 'g'
+  changes: []
+''');
+    var transforms = result.transformsFor('g', ['test.dart']);
+    expect(transforms, hasLength(1));
+    var transform = transforms[0];
+    expect(transform.title, 'Rename g');
+    expect(transform.changes, isEmpty);
+  }
+
+  void test_element_method_inClass() {
+    parse('''
+version: 1
+transforms:
+- title: 'Rename m'
+  element:
+    uris: ['test.dart']
+    method: 'm'
+    inClass: 'A'
+  changes: []
+''');
+    var transforms = result.transformsFor('m', ['test.dart']);
+    expect(transforms, hasLength(1));
+    var transform = transforms[0];
+    expect(transform.title, 'Rename m');
+    expect(transform.changes, isEmpty);
+  }
+
   void test_incomplete() {
     parse('''
 version: 1
@@ -46,8 +99,7 @@
   element:
     uris:
       - 'test.dart'
-    components:
-      - 'A'
+    class: 'A'
   changes:
     - kind: 'rename'
       newName: 'B'
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart
index 32b927a..28948d0 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart
@@ -5,6 +5,7 @@
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -31,7 +32,10 @@
 ''');
     await assertHasFix('''
 int f(int a, int b) => a;
-''');
+''', errorFilter: (e) {
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      return e.errorCode != HintCode.DEAD_CODE;
+    });
   }
 
   Future<void> test_nestedChild() async {
@@ -40,7 +44,10 @@
 ''');
     await assertHasFix('''
 int f(int a, int b) => a;
-''');
+''', errorFilter: (e) {
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      return e.errorCode != HintCode.DEAD_CODE;
+    });
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index 3cf8743..0cacd29 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -466,7 +466,7 @@
 
     var flow = _flowAnalysis?.flow;
     if (flow != null && operator == TokenType.QUESTION_QUESTION_EQ) {
-      flow.ifNullExpression_rightBegin(left);
+      flow.ifNullExpression_rightBegin(left, node.readType);
     }
 
     right?.accept(_resolver);
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index fe41371..ddab194 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -178,7 +178,7 @@
     }
     InferenceContext.setType(right, rightContextType);
 
-    flow?.ifNullExpression_rightBegin(left);
+    flow?.ifNullExpression_rightBegin(left, leftType);
     right.accept(_resolver);
     right = node.rightOperand;
     flow?.ifNullExpression_end();
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index 1c2938f1..915f509 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -85,7 +85,7 @@
     if (flow == null) return null;
 
     if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
-      flow.ifNullExpression_rightBegin(node.leftHandSide);
+      flow.ifNullExpression_rightBegin(node.leftHandSide, node.readType);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 0c60e48..d1fedd3 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -850,7 +850,8 @@
     node.target.accept(this);
 
     if (node.isNullAware && _isNonNullableByDefault) {
-      _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
+      _flowAnalysis.flow.nullAwareAccess_rightBegin(
+          node.target, node.target.staticType ?? typeProvider.dynamicType);
       _unfinishedNullShorts.add(node.nullShortingTermination);
     }
 
@@ -1447,7 +1448,8 @@
     node.target?.accept(this);
     if (_migratableAstInfoProvider.isIndexExpressionNullAware(node) &&
         _isNonNullableByDefault) {
-      _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
+      _flowAnalysis.flow.nullAwareAccess_rightBegin(
+          node.target, node.realTarget.staticType ?? typeProvider.dynamicType);
       _unfinishedNullShorts.add(node.nullShortingTermination);
     }
     node.accept(elementResolver);
@@ -1534,12 +1536,18 @@
 
   @override
   void visitMethodInvocation(MethodInvocation node) {
-    node.target?.accept(this);
+    var target = node.target;
+    target?.accept(this);
 
     if (_migratableAstInfoProvider.isMethodInvocationNullAware(node) &&
         _isNonNullableByDefault) {
-      _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
-      _unfinishedNullShorts.add(node.nullShortingTermination);
+      if (target is SimpleIdentifier && target.staticElement is ClassElement) {
+        // `?.` to access static methods is equivalent to `.`, so do nothing.
+      } else {
+        _flowAnalysis.flow.nullAwareAccess_rightBegin(
+            target, node.realTarget.staticType ?? typeProvider.dynamicType);
+        _unfinishedNullShorts.add(node.nullShortingTermination);
+      }
     }
 
     node.typeArguments?.accept(this);
@@ -1632,11 +1640,17 @@
     // We visit the target, but do not visit the property name because it needs
     // to be visited in the context of the property access node.
     //
-    node.target?.accept(this);
+    var target = node.target;
+    target?.accept(this);
     if (_migratableAstInfoProvider.isPropertyAccessNullAware(node) &&
         _isNonNullableByDefault) {
-      _flowAnalysis.flow.nullAwareAccess_rightBegin(node.target);
-      _unfinishedNullShorts.add(node.nullShortingTermination);
+      if (target is SimpleIdentifier && target.staticElement is ClassElement) {
+        // `?.` to access static methods is equivalent to `.`, so do nothing.
+      } else {
+        _flowAnalysis.flow.nullAwareAccess_rightBegin(
+            target, node.realTarget.staticType ?? typeProvider.dynamicType);
+        _unfinishedNullShorts.add(node.nullShortingTermination);
+      }
     }
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
@@ -2006,8 +2020,14 @@
     if (function is PropertyAccess &&
         _migratableAstInfoProvider.isPropertyAccessNullAware(function) &&
         _isNonNullableByDefault) {
-      _flowAnalysis.flow.nullAwareAccess_rightBegin(function);
-      _unfinishedNullShorts.add(node.nullShortingTermination);
+      var target = function.target;
+      if (target is SimpleIdentifier && target.staticElement is ClassElement) {
+        // `?.` to access static methods is equivalent to `.`, so do nothing.
+      } else {
+        _flowAnalysis.flow.nullAwareAccess_rightBegin(function,
+            function.realTarget.staticType ?? typeProvider.dynamicType);
+        _unfinishedNullShorts.add(node.nullShortingTermination);
+      }
     }
 
     _functionExpressionInvocationResolver.resolve(node);
diff --git a/pkg/analyzer/lib/src/util/ast_data_extractor.dart b/pkg/analyzer/lib/src/util/ast_data_extractor.dart
index 06fdab9..2147db8 100644
--- a/pkg/analyzer/lib/src/util/ast_data_extractor.dart
+++ b/pkg/analyzer/lib/src/util/ast_data_extractor.dart
@@ -84,6 +84,13 @@
       var memberName = element.name;
       var className = element.enclosingElement.name;
       return MemberId.internal(memberName, className: className);
+    } else if (element.enclosingElement is ExtensionElement) {
+      var memberName = element.name;
+      var extensionName = element.enclosingElement.name;
+      if (element is PropertyAccessorElement) {
+        memberName = '${element.isGetter ? 'get' : 'set'}#$memberName';
+      }
+      return MemberId.internal('$extensionName|$memberName');
     }
     throw UnimplementedError(
         'TODO(paulberry): $element (${element.runtimeType})');
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index c616675..95d7b3e 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -445,19 +445,17 @@
 
   test_async_expression_function_type() async {
     await assertErrorsInCode('''
-import 'dart:async';
 typedef Future<int> F(int i);
 main() {
   F f = (int i) async => i;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 64, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
     ]);
   }
 
   test_async_flattened() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 typedef Future<int> CreatesFutureInt();
 main() {
   CreatesFutureInt createFutureInt = () async => f();
@@ -470,7 +468,6 @@
 
   test_async_future_dynamic_with_return() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future<dynamic> f() async {
   return;
 }
@@ -479,7 +476,6 @@
 
   test_async_future_dynamic_with_return_value() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future<dynamic> f() async {
   return 5;
 }
@@ -488,14 +484,12 @@
 
   test_async_future_dynamic_without_return() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future<dynamic> f() async {}
 ''');
   }
 
   test_async_future_int_with_return_future_int() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future<int> f() async {
   return new Future<int>.value(5);
 }
@@ -504,7 +498,6 @@
 
   test_async_future_int_with_return_value() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future<int> f() async {
   return 5;
 }
@@ -513,7 +506,6 @@
 
   test_async_future_null_with_return() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future<Null> f() async {
   return;
 }
@@ -522,14 +514,12 @@
 
   test_async_future_null_without_return() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future<Null> f() async {}
 ''');
   }
 
   test_async_future_object_with_return_value() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future<Object> f() async {
   return 5;
 }
@@ -538,7 +528,6 @@
 
   test_async_future_with_return() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future f() async {
   return;
 }
@@ -547,7 +536,6 @@
 
   test_async_future_with_return_value() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future f() async {
   return 5;
 }
@@ -556,7 +544,6 @@
 
   test_async_future_without_return() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future f() async {}
 ''');
   }
@@ -607,25 +594,23 @@
 
   test_await_flattened() async {
     await assertErrorsInCode('''
-import 'dart:async';
 Future<Future<int>> ffi() => null;
 f() async {
   Future<int> b = await ffi();
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 82, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 61, 1),
     ]);
   }
 
   test_await_simple() async {
     await assertErrorsInCode('''
-import 'dart:async';
 Future<int> fi() => null;
 f() async {
   int a = await fi();
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 65, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 44, 1),
     ]);
   }
 
@@ -1099,7 +1084,6 @@
 
   test_empty_generator_async() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Stream<int> f() async* {
 }
 ''');
@@ -2147,8 +2131,6 @@
 
   test_issue_24191() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
-
 abstract class S extends Stream {}
 f(S s) async {
   await for (var v in s) {
diff --git a/pkg/analyzer/test/generated/static_type_warning_code_test.dart b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
index 0256b50..e29bb22 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code_test.dart
@@ -40,126 +40,116 @@
 
   test_await_flattened() async {
     await assertErrorsInCode('''
-import 'dart:async';
 Future<Future<int>> ffi() => null;
 f() async {
   Future<int> b = await ffi(); 
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 82, 1),
-    ]);
-  }
-
-  test_await_simple() async {
-    await assertErrorsInCode('''
-import 'dart:async';
-Future<int> fi() => null;
-f() async {
-  String a = await fi(); // Warning: int not assignable to String
-}
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 68, 1),
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 72, 10),
-    ]);
-  }
-
-  test_awaitForIn_declaredVariableRightType() async {
-    await assertErrorsInCode('''
-import 'dart:async';
-f() async {
-  Stream<int> stream;
-  await for (int i in stream) {}
-}
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 72, 1),
-    ]);
-  }
-
-  test_awaitForIn_declaredVariableWrongType() async {
-    await assertErrorsInCode('''
-import 'dart:async';
-f() async {
-  Stream<String> stream;
-  await for (int i in stream) {}
-}
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 75, 1),
-      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 80, 6),
-    ]);
-  }
-
-  test_awaitForIn_downcast() async {
-    await assertErrorsInCode('''
-import 'dart:async';
-f() async {
-  Stream<num> stream;
-  await for (int i in stream) {}
-}
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 72, 1),
-    ]);
-  }
-
-  test_awaitForIn_dynamicVariable() async {
-    await assertErrorsInCode('''
-import 'dart:async';
-f() async {
-  Stream<int> stream;
-  await for (var i in stream) {}
-}
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 72, 1),
-    ]);
-  }
-
-  test_awaitForIn_existingVariableRightType() async {
-    await assertErrorsInCode('''
-import 'dart:async';
-f() async {
-  Stream<int> stream;
-  int i;
-  await for (i in stream) {}
-}
-''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 61, 1),
     ]);
   }
 
+  test_await_simple() async {
+    await assertErrorsInCode('''
+Future<int> fi() => null;
+f() async {
+  String a = await fi(); // Warning: int not assignable to String
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 1),
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 51, 10),
+    ]);
+  }
+
+  test_awaitForIn_declaredVariableRightType() async {
+    await assertErrorsInCode('''
+f() async {
+  Stream<int> stream;
+  await for (int i in stream) {}
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 51, 1),
+    ]);
+  }
+
+  test_awaitForIn_declaredVariableWrongType() async {
+    await assertErrorsInCode('''
+f() async {
+  Stream<String> stream;
+  await for (int i in stream) {}
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 54, 1),
+      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 59, 6),
+    ]);
+  }
+
+  test_awaitForIn_downcast() async {
+    await assertErrorsInCode('''
+f() async {
+  Stream<num> stream;
+  await for (int i in stream) {}
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 51, 1),
+    ]);
+  }
+
+  test_awaitForIn_dynamicVariable() async {
+    await assertErrorsInCode('''
+f() async {
+  Stream<int> stream;
+  await for (var i in stream) {}
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 51, 1),
+    ]);
+  }
+
+  test_awaitForIn_existingVariableRightType() async {
+    await assertErrorsInCode('''
+f() async {
+  Stream<int> stream;
+  int i;
+  await for (i in stream) {}
+}
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 40, 1),
+    ]);
+  }
+
   test_awaitForIn_existingVariableWrongType() async {
     await assertErrorsInCode('''
-import 'dart:async';
 f() async {
   Stream<String> stream;
   int i;
   await for (i in stream) {}
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 64, 1),
-      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 85, 6),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
+      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 64, 6),
     ]);
   }
 
   test_awaitForIn_streamOfDynamic() async {
     await assertErrorsInCode('''
-import 'dart:async';
 f() async {
   Stream stream;
   await for (int i in stream) {}
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 67, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 46, 1),
     ]);
   }
 
   test_awaitForIn_upcast() async {
     await assertErrorsInCode('''
-import 'dart:async';
 f() async {
   Stream<int> stream;
   await for (num i in stream) {}
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 72, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 51, 1),
     ]);
   }
 
@@ -600,7 +590,6 @@
 class StrongModeStaticTypeWarningCodeTest extends PubPackageResolutionTest {
   test_legalAsyncGeneratorReturnType_function_supertypeOfStream() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 f() async* { yield 42; }
 dynamic f2() async* { yield 42; }
 Object f3() async* { yield 42; }
@@ -614,7 +603,6 @@
 
   test_legalAsyncReturnType_function_supertypeOfFuture() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 f() async { return 42; }
 dynamic f2() async { return 42; }
 Object f3() async { return 42; }
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index e46eb3b..f219504 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -87,7 +87,6 @@
 
   test_async_method_propagation() async {
     String code = r'''
-      import "dart:async";
       class A {
         Future f0() => new Future.value(3);
         Future f1() async => new Future.value(3);
@@ -144,8 +143,6 @@
 
   test_async_propagation() async {
     String code = r'''
-      import "dart:async";
-
       Future f0() => new Future.value(3);
       Future f1() async => new Future.value(3);
       Future f2() async => await new Future.value(3);
@@ -3378,14 +3375,13 @@
 
   test_genericMethod_then() async {
     await assertErrorsInCode(r'''
-import 'dart:async';
 String toString(int x) => x.toString();
 main() {
   Future<int> bar = null;
   var foo = bar.then(toString);
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 102, 3),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 81, 3),
     ]);
 
     expectInitializerType('foo', 'Future<String>');
@@ -3408,14 +3404,13 @@
   test_genericMethod_then_propagatedType() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/25482.
     await assertErrorsInCode(r'''
-import 'dart:async';
 void main() {
   Future<String> p;
   var foo = p.then((r) => new Future<String>.value(3));
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 61, 3),
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 106, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 40, 3),
+      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 85, 1),
     ]);
     // Note: this correctly reports the error
     // CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE when run with the driver;
@@ -3978,7 +3973,6 @@
 
   test_foreachInference_var_stream() async {
     await resolveTestCode(r'''
-import 'dart:async';
 main() async {
   Stream<int> stream = null;
   await for (var v in stream) {
diff --git a/pkg/analyzer/test/src/dart/resolution/await_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/await_expression_test.dart
index fe0faac..e2baade 100644
--- a/pkg/analyzer/test/src/dart/resolution/await_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/await_expression_test.dart
@@ -17,8 +17,6 @@
 class AwaitExpressionResolutionTest extends PubPackageResolutionTest {
   test_future() async {
     await assertNoErrorsInCode(r'''
-import 'dart:async';
-
 f(Future<int> a) async {
   await a;
 }
@@ -57,8 +55,6 @@
 
   test_futureQ() async {
     await assertNoErrorsInCode(r'''
-import 'dart:async';
-
 f(Future<int>? a) async {
   await a;
 }
diff --git a/pkg/analyzer/test/src/diagnostics/dead_null_aware_expression_test.dart b/pkg/analyzer/test/src/diagnostics/dead_null_aware_expression_test.dart
index c1e4746..e60e478 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_null_aware_expression_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_null_aware_expression_test.dart
@@ -22,13 +22,16 @@
 var x = 0;
 ''');
 
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode('''
 import 'a.dart';
 
 f() {
   x ??= 0;
 }
-''');
+''', [
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      error(HintCode.DEAD_CODE, 32, 2),
+    ]);
   }
 
   test_assignCompound_map() async {
@@ -51,6 +54,8 @@
 }
 ''', [
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 19, 1),
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      error(HintCode.DEAD_CODE, 19, 2),
     ]);
   }
 
@@ -68,13 +73,16 @@
 var x = 0;
 ''');
 
-    await assertNoErrorsInCode('''
+    await assertErrorsInCode('''
 import 'a.dart';
 
 f() {
   x ?? 0;
 }
-''');
+''', [
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      error(HintCode.DEAD_CODE, 31, 2),
+    ]);
   }
 
   test_binary_nonNullable() async {
@@ -84,6 +92,8 @@
 }
 ''', [
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 18, 1),
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      error(HintCode.DEAD_CODE, 18, 2),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_element_type_test.dart b/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_element_type_test.dart
index 916d47f..3875476 100644
--- a/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_element_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_element_type_test.dart
@@ -17,28 +17,26 @@
 class ForInOfInvalidElementTypeTest extends PubPackageResolutionTest {
   test_await_declaredVariableWrongType() async {
     await assertErrorsInCode('''
-import 'dart:async';
 f() async {
   Stream<String> stream;
   await for (int i in stream) {}
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 75, 1),
-      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 80, 6),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 54, 1),
+      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 59, 6),
     ]);
   }
 
   test_await_existingVariableWrongType() async {
     await assertErrorsInCode('''
-import 'dart:async';
 f() async {
   Stream<String> stream;
   int i;
   await for (i in stream) {}
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 64, 1),
-      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 85, 6),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 43, 1),
+      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 64, 6),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/illegal_async_generator_return_type_test.dart b/pkg/analyzer/test/src/diagnostics/illegal_async_generator_return_type_test.dart
index ac52b34..c60b913 100644
--- a/pkg/analyzer/test/src/diagnostics/illegal_async_generator_return_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/illegal_async_generator_return_type_test.dart
@@ -31,11 +31,10 @@
 
   test_function_subtypeOfStream() async {
     await assertErrorsInCode('''
-import 'dart:async';
 abstract class SubStream<T> implements Stream<T> {}
 SubStream<int> f() async* {}
 ''', [
-      error(CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 73, 14),
+      error(CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 52, 14),
     ]);
   }
 
@@ -59,13 +58,12 @@
 
   test_method_subtypeOfStream() async {
     await assertErrorsInCode('''
-import 'dart:async';
 abstract class SubStream<T> implements Stream<T> {}
 class C {
   SubStream<int> f() async* {}
 }
 ''', [
-      error(CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 85, 14),
+      error(CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE, 64, 14),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/illegal_async_return_type_test.dart b/pkg/analyzer/test/src/diagnostics/illegal_async_return_type_test.dart
index 3302326..01e30f0 100644
--- a/pkg/analyzer/test/src/diagnostics/illegal_async_return_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/illegal_async_return_type_test.dart
@@ -41,13 +41,12 @@
 
   test_function_subtypeOfFuture() async {
     await assertErrorsInCode('''
-import 'dart:async';
 abstract class SubFuture<T> implements Future<T> {}
 SubFuture<int> f() async {
   return 0;
 }
 ''', [
-      error(CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE, 73, 14),
+      error(CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE, 52, 14),
     ]);
   }
 
@@ -71,7 +70,6 @@
 
   test_method_subtypeOfFuture() async {
     await assertErrorsInCode('''
-import 'dart:async';
 abstract class SubFuture<T> implements Future<T> {}
 class C {
   SubFuture<int> m() async {
@@ -79,7 +77,7 @@
   }
 }
 ''', [
-      error(CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE, 85, 14),
+      error(CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE, 64, 14),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
index 7a58e23..eda7bec 100644
--- a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
@@ -170,7 +170,6 @@
   test_overriddenWithFuture() async {
     // https://github.com/flutter/flutter/issues/11646
     await assertNoErrorsInCode(r'''
-import 'dart:async';
 import 'package:meta/meta.dart';
 class A {
   @mustCallSuper
@@ -191,7 +190,6 @@
   test_overriddenWithFuture2() async {
     // https://github.com/flutter/flutter/issues/11646
     await assertNoErrorsInCode(r'''
-import 'dart:async';
 import 'package:meta/meta.dart';
 class A {
   @mustCallSuper
diff --git a/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart b/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
index 1caa9cc..df5882b 100644
--- a/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
@@ -84,6 +84,8 @@
 }
 ''', [
       _notAssignedError(22, 1),
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      error(HintCode.DEAD_CODE, 28, 2),
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 28, 1),
     ]);
   }
@@ -96,6 +98,8 @@
 }
 ''', [
       _notAssignedError(22, 1),
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      error(HintCode.DEAD_CODE, 28, 2),
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 28, 1),
       _notAssignedError(28, 1),
     ]);
@@ -118,7 +122,11 @@
   (v = 0) ?? 0;
   v;
 }
-''', [error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 33, 1)]);
+''', [
+      error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 33, 1),
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      error(HintCode.DEAD_CODE, 33, 7),
+    ]);
   }
 
   test_binaryExpression_ifNull_right() async {
@@ -130,6 +138,8 @@
 }
 ''', [
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 32, 7),
+      // See https://github.com/dart-lang/sdk/issues/43263.
+      error(HintCode.DEAD_CODE, 32, 13),
       _notAssignedError(43, 1),
     ]);
   }
diff --git a/pkg/analyzer/test/src/diagnostics/return_in_generator_test.dart b/pkg/analyzer/test/src/diagnostics/return_in_generator_test.dart
index bdc49f3..748f963 100644
--- a/pkg/analyzer/test/src/diagnostics/return_in_generator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/return_in_generator_test.dart
@@ -36,7 +36,6 @@
 
   test_asyncStar_blockBody_noValue() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Stream<int> f() async* {
   return;
 }
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
index 0552343..a668a46 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
@@ -409,10 +409,4 @@
 int f() => A.x;
 ''');
   }
-
-  @override
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/42957')
-  test_typeLiteral_conditionalAccess() {
-    return super.test_typeLiteral_conditionalAccess();
-  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart
index 862460e..f89e480 100644
--- a/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart
@@ -19,15 +19,13 @@
   test_none_asyncStar_dynamic_to_streamInt() async {
     await assertErrorsInCode(
         '''
-import 'dart:async';
-
 Stream<int> f() async* {
   dynamic a = 0;
   yield a;
 }
 ''',
         expectedErrorsByNullability(nullable: [
-          error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 72, 1),
+          error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 50, 1),
         ], legacy: []));
   }
 
@@ -63,8 +61,6 @@
 
   test_none_asyncStar_int_to_streamDynamic() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
-
 Stream f() async* {
   yield 0;
 }
@@ -73,8 +69,6 @@
 
   test_none_asyncStar_int_to_streamInt() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
-
 Stream<int> f() async* {
   yield 0;
 }
@@ -83,13 +77,11 @@
 
   test_none_asyncStar_int_to_streamString() async {
     await assertErrorsInCode('''
-import 'dart:async';
-
 Stream<String> f() async* {
   yield 0;
 }
 ''', [
-      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 58, 1),
+      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 36, 1),
     ]);
   }
 
@@ -161,14 +153,12 @@
 
   test_none_syncStar_int_to_stream() async {
     await assertErrorsInCode('''
-import 'dart:async';
-
 Stream<int> f() sync* {
   yield 0;
 }
 ''', [
-      error(CompileTimeErrorCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 22, 11),
-      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 54, 1),
+      error(CompileTimeErrorCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 0, 11),
+      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 32, 1),
     ]);
   }
 
@@ -192,8 +182,6 @@
 
   test_star_asyncStar_dynamic_to_streamDynamic() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
-
 Stream f() async* {
   yield* g();
 }
@@ -204,8 +192,6 @@
 
   test_star_asyncStar_dynamic_to_streamInt() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
-
 Stream<int> f() async* {
   yield* g();
 }
@@ -237,34 +223,28 @@
 
   test_star_asyncStar_iterableInt_to_streamInt() async {
     await assertErrorsInCode('''
-import 'dart:async';
-
 Stream<int> f() async* {
   var a = <int>[];
   yield* a;
 }
 ''', [
-      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 75, 1),
+      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 53, 1),
     ]);
   }
 
   test_star_asyncStar_iterableString_to_streamInt() async {
     await assertErrorsInCode('''
-import 'dart:async';
-
 Stream<int> f() async* {
   var a = <String>[];
   yield* a;
 }
 ''', [
-      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 78, 1),
+      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 56, 1),
     ]);
   }
 
   test_star_asyncStar_streamDynamic_to_dynamic() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
-
 f() async* {
   yield* g();
 }
@@ -276,8 +256,6 @@
   test_star_asyncStar_streamDynamic_to_streamInt() async {
     await assertErrorsInCode(
         '''
-import 'dart:async';
-
 Stream<int> f() async* {
   yield* g();
 }
@@ -285,14 +263,12 @@
 Stream g() => throw 0;
 ''',
         expectedErrorsByNullability(nullable: [
-          error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 56, 3),
+          error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 34, 3),
         ], legacy: []));
   }
 
   test_star_asyncStar_streamInt_to_dynamic() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
-
 f() async* {
   yield* g();
 }
@@ -303,8 +279,6 @@
 
   test_star_asyncStar_streamInt_to_streamInt() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
-
 Stream<int> f() async* {
   yield* g();
 }
@@ -315,15 +289,13 @@
 
   test_star_asyncStar_streamString_to_streamInt() async {
     await assertErrorsInCode('''
-import 'dart:async';
-
 Stream<int> f() async* {
   yield* g();
 }
 
 Stream<String> g() => throw 0;
 ''', [
-      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 56, 3),
+      error(CompileTimeErrorCode.YIELD_OF_INVALID_TYPE, 34, 3),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 366c696..41ea625 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -18,8 +18,6 @@
 class CheckerTest extends PubPackageResolutionTest {
   test_awaitForInCastsStreamElementToVariable() async {
     await assertErrorsInCode('''
-import 'dart:async';
-
 abstract class MyStream<T> extends Stream<T> {
   factory MyStream() => throw 0;
 }
@@ -41,12 +39,12 @@
   await for (int i in new MyStream<num>()) {}
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 181, 1),
-      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE, 186, 4),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 235, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 309, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 373, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 438, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 159, 1),
+      error(CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE, 164, 4),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 213, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 287, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 351, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 416, 1),
     ]);
   }
 
@@ -1008,7 +1006,6 @@
 
   test_functionModifiers_async() async {
     await assertErrorsInCode('''
-import 'dart:async';
 import 'dart:math' show Random;
 
 dynamic x;
@@ -1053,13 +1050,13 @@
   return ((1 > 0) ? new Future<String>.value('hello') : "world");
 }
 ''', [
-      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 224, 27),
-      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 454, 27),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 529, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 548, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 567, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 589, 1),
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 593, 7),
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 203, 27),
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 433, 27),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 508, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 527, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 546, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 568, 1),
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 572, 7),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 6c8f375..b7e1600 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -28,7 +28,6 @@
 
   test_asyncClosureReturnType_flatten() async {
     await assertNoErrorsInCode('''
-import 'dart:async';
 Future<int> futureInt = null;
 var f = () => futureInt;
 var g = () async => futureInt;
@@ -73,7 +72,6 @@
 
   test_blockBodiedLambdas_async_allReturnsAreFutures() async {
     await assertErrorsInCode(r'''
-import 'dart:async';
 import 'dart:math' show Random;
 main() {
   var f = () async {
@@ -87,8 +85,8 @@
   Future<int> h = f();
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 239, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 262, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 218, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 241, 1),
     ]);
 
     var f = findLocalVariable(_resultUnit, 'f');
@@ -97,7 +95,6 @@
 
   test_blockBodiedLambdas_async_allReturnsAreValues() async {
     await assertErrorsInCode(r'''
-import 'dart:async';
 import 'dart:math' show Random;
 main() {
   var f = () async {
@@ -111,8 +108,8 @@
   Future<int> h = f();
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 190, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 213, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 169, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 192, 1),
     ]);
 
     var f = findLocalVariable(_resultUnit, 'f');
@@ -121,7 +118,6 @@
 
   test_blockBodiedLambdas_async_mixOfValuesAndFutures() async {
     await assertErrorsInCode(r'''
-import 'dart:async';
 import 'dart:math' show Random;
 main() {
   var f = () async {
@@ -135,8 +131,8 @@
   Future<int> h = f();
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 213, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 236, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 192, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 215, 1),
     ]);
 
     var f = findLocalVariable(_resultUnit, 'f');
@@ -145,7 +141,6 @@
 
   test_blockBodiedLambdas_asyncStar() async {
     await assertErrorsInCode(r'''
-import 'dart:async';
 main() {
   var f = () async* {
     yield 1;
@@ -156,8 +151,8 @@
   Stream<int> h = f();
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 120, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 143, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 99, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 122, 1),
     ]);
 
     var f = findLocalVariable(_resultUnit, 'f');
@@ -203,7 +198,6 @@
 
   test_blockBodiedLambdas_inferBottom_async() async {
     await assertErrorsInCode(r'''
-import 'dart:async';
 main() async {
   var f = () async { return null; };
   Future y = f();
@@ -211,9 +205,9 @@
   String s = await f();
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 82, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 108, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 126, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 61, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 87, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 105, 1),
     ]);
 
     var f = findLocalVariable(_resultUnit, 'f');
@@ -222,7 +216,6 @@
 
   test_blockBodiedLambdas_inferBottom_asyncStar() async {
     await assertErrorsInCode(r'''
-import 'dart:async';
 main() async {
   var f = () async* { yield null; };
   Stream y = f();
@@ -230,9 +223,9 @@
   String s = await f().first;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 82, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 108, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 126, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 61, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 87, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 105, 1),
     ]);
 
     var f = findLocalVariable(_resultUnit, 'f');
@@ -844,22 +837,19 @@
 
   test_downwardsInferenceAsyncAwait() async {
     await assertErrorsInCode('''
-import 'dart:async';
 Future test() async {
   dynamic d;
   List<int> l0 = await [d];
   List<int> l1 = await new Future.value([d]);
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 68, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 96, 2),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 47, 2),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 75, 2),
     ]);
   }
 
   test_downwardsInferenceForEach() async {
     await assertErrorsInCode('''
-import 'dart:async';
-
 abstract class MyStream<T> extends Stream<T> {
   factory MyStream() => throw 0;
 }
@@ -869,8 +859,8 @@
   await for(int x in new MyStream()) {}
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 137, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 172, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 115, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 150, 1),
     ]);
   }
 
@@ -1689,7 +1679,6 @@
 
   test_futureOr_subtyping() async {
     await assertErrorsInCode(r'''
-import 'dart:async';
 void add(int x) {}
 add2(int y) {}
 main() {
@@ -1698,14 +1687,15 @@
   var b = f.then(add2);
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 87, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 110, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 66, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 89, 1),
     ]);
   }
 
   test_futureThen() async {
     String build({String declared, String downwards, String upwards}) => '''
 import 'dart:async';
+
 class MyFuture<T> implements Future<T> {
   MyFuture() {}
   MyFuture.value(T x) {}
@@ -1793,7 +1783,6 @@
   test_futureThen_downwardsMethodTarget() async {
     // Not working yet, see: https://github.com/dart-lang/sdk/issues/27114
     await assertErrorsInCode(r'''
-import 'dart:async';
 main() {
   Future<int> f;
   Future<List<int>> b = f
@@ -1802,13 +1791,12 @@
   b = f.then((x) => []);
 }
   ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 67, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 46, 1),
     ]);
   }
 
   test_futureThen_explicitFuture() async {
     await assertErrorsInCode(r'''
-import "dart:async";
 m1() {
   Future<int> f;
   var x = f.then<Future<List<int>>>((x) => []);
@@ -1820,10 +1808,10 @@
   Future<List<int>> y = x;
 }
 ''', [
-      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE, 88, 2),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 113, 1),
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 117, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 206, 1),
+      error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_CLOSURE, 67, 2),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 92, 1),
+      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 96, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 185, 1),
     ]);
   }
 
@@ -1887,7 +1875,6 @@
   test_futureThen_upwardsFromBlock() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/27113.
     await assertErrorsInCode(r'''
-import 'dart:async';
 main() {
   Future<int> base;
   var f = base.then((x) { return x == 0; });
@@ -1896,7 +1883,7 @@
   b = g;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 146, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 125, 1),
     ]);
   }
 
@@ -2018,8 +2005,6 @@
     // We need to take a future union into account for both directions of
     // generic method inference.
     await assertErrorsInCode(r'''
-import 'dart:async';
-
 foo() async {
   Future<List<A>> f1 = null;
   Future<List<A>> f2 = null;
@@ -2028,15 +2013,13 @@
 
 class A {}
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 110, 6),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 88, 6),
     ]);
   }
 
   test_futureUnion_downwardsGenericMethodWithGenericReturn() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/27284
     await assertErrorsInCode(r'''
-import 'dart:async';
-
 T id<T>(T x) => x;
 
 main() async {
@@ -2044,15 +2027,13 @@
   String s = await id(f);
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 86, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 64, 1),
     ]);
   }
 
   test_futureUnion_upwardsGenericMethods() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/27151
     await assertErrorsInCode(r'''
-import 'dart:async';
-
 main() async {
   var b = new Future<B>.value(new B());
   var c = new Future<C>.value(new C());
@@ -2067,7 +2048,7 @@
 class B extends A {}
 class C extends A {}
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 229, 4),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 207, 4),
     ]);
   }
 
@@ -2287,8 +2268,6 @@
 
   test_genericMethods_IterableAndFuture() async {
     await assertErrorsInCode('''
-import 'dart:async';
-
 Future<int> make(int x) => (new Future(() => x));
 
 main() {
@@ -2304,11 +2283,11 @@
     => list.fold<String>('', (x, y) => x + y.toString()));
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 205, 8),
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 279, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 315, 8),
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 377, 33),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 432, 8),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 183, 8),
+      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 257, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 293, 8),
+      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 355, 33),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 410, 8),
     ]);
   }
 
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 74b894e..ec7bc61 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -1159,7 +1159,8 @@
             lhsResult.inferredType, equalsName, node.fileOffset)
         .member;
 
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(node.left);
+    inferrer.flowAnalysis
+        .ifNullExpression_rightBegin(node.left, lhsResult.inferredType);
     // - Let J = T0 if K is `?` else K.
     // - Infer e1 in context J to get T1
     ExpressionInferenceResult rhsResult;
@@ -2670,7 +2671,7 @@
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
 
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read);
+    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
     ExpressionInferenceResult writeResult = inferrer
         .inferExpression(node.write, typeContext, true, isVoidAllowed: true);
     inferrer.flowAnalysis.ifNullExpression_end();
@@ -2742,7 +2743,7 @@
       read = readResult.expression;
       readType = readResult.inferredType;
     }
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read);
+    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
     ExpressionInferenceResult writeResult = inferrer
         .inferExpression(node.write, typeContext, true, isVoidAllowed: true);
     inferrer.flowAnalysis.ifNullExpression_end();
@@ -3098,7 +3099,7 @@
         readResult.inferredType, "??=", node.readOffset);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read);
+    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
 
     Member equalsMember = inferrer
         .findInterfaceMember(readType, equalsName, node.testOffset)
@@ -3269,7 +3270,7 @@
         ..fileOffset = node.readOffset;
     }
 
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read);
+    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
     ExpressionInferenceResult valueResult = inferrer
         .inferExpression(node.value, valueType, true, isVoidAllowed: true);
     Expression value = inferrer.ensureAssignableResult(valueType, valueResult);
@@ -3423,7 +3424,7 @@
         readResult.inferredType, "??=", node.readOffset);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read);
+    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
 
     Member equalsMember = inferrer
         .findInterfaceMember(readType, equalsName, node.testOffset)
@@ -4903,7 +4904,7 @@
         isThisReceiver: node.receiver is ThisExpression);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
-    inferrer.flowAnalysis.ifNullExpression_rightBegin(read);
+    inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
 
     Member readEqualsMember = inferrer
         .findInterfaceMember(readType, equalsName, node.testOffset)
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 0603833..2d855ee8 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -3814,14 +3814,15 @@
         assert(_inferrer != null) {
     // Ensure the initializer of [_nullAwareVariable] is promoted to
     // non-nullable.
-    _inferrer.flowAnalysis
-        .nullAwareAccess_rightBegin(_nullAwareVariable.initializer);
+    _inferrer.flowAnalysis.nullAwareAccess_rightBegin(
+        _nullAwareVariable.initializer, _nullAwareVariable.type);
     // Ensure [_nullAwareVariable] is promoted to non-nullable.
     // TODO(johnniwinther): Avoid creating a [VariableGet] to promote the
     // variable.
     VariableGet read = new VariableGet(_nullAwareVariable);
     _inferrer.flowAnalysis.variableRead(read, _nullAwareVariable);
-    _inferrer.flowAnalysis.nullAwareAccess_rightBegin(read);
+    _inferrer.flowAnalysis
+        .nullAwareAccess_rightBegin(read, _nullAwareVariable.type);
   }
 
   /// Creates the null-guarded application of [nullAwareAction] with the
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 81e9982..c9f67ed 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -276,6 +276,7 @@
 behaviors
 behind
 being
+believes
 belong
 belongs
 below
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index c61bc53..b59c9c5 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -456,7 +456,7 @@
     } else if (operatorType == TokenType.QUESTION_QUESTION) {
       DecoratedType expressionType;
       var leftType = _dispatch(leftOperand);
-      _flowAnalysis.ifNullExpression_rightBegin(node.leftOperand);
+      _flowAnalysis.ifNullExpression_rightBegin(node.leftOperand, leftType);
       try {
         _guards.add(leftType.node);
         DecoratedType rightType;
@@ -2210,8 +2210,8 @@
 
     if (questionAssignNode != null) {
       _guards.add(destinationType.node);
-      _flowAnalysis
-          .ifNullExpression_rightBegin(questionAssignNode.leftHandSide);
+      _flowAnalysis.ifNullExpression_rightBegin(
+          questionAssignNode.leftHandSide, destinationType);
     }
     DecoratedType sourceType;
     try {
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 848036a..21f8df2 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -886,15 +886,22 @@
     result = kDoesNotExist;
   } else if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
     if (follow_links) {
-      HANDLE dir_handle =
+      HANDLE target_handle =
           CreateFileW(name.wide(), 0,
                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                       NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
-      if (dir_handle == INVALID_HANDLE_VALUE) {
+      if (target_handle == INVALID_HANDLE_VALUE) {
         result = File::kIsLink;
       } else {
-        CloseHandle(dir_handle);
-        result = File::kIsDirectory;
+        BY_HANDLE_FILE_INFORMATION info;
+        if (!GetFileInformationByHandle(target_handle, &info)) {
+          CloseHandle(target_handle);
+          return File::kIsLink;
+        }
+        CloseHandle(target_handle);
+        return ((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+                   ? File::kIsDirectory
+                   : File::kIsFile;
       }
     } else {
       result = kIsLink;
diff --git a/tests/language/constructor/missing_initializer_test.dart b/tests/language/constructor/missing_initializer_test.dart
index 3604aa8..3736c5f 100644
--- a/tests/language/constructor/missing_initializer_test.dart
+++ b/tests/language/constructor/missing_initializer_test.dart
@@ -32,6 +32,8 @@
 }
 
 class C = Object with A;
+  //  ^
+  // [analyzer] COMPILE_TIME_ERROR.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER
 
 // Has a generative constructor: default.
 abstract class D {
diff --git a/tests/language/nnbd/const/regress43281_test.dart b/tests/language/nnbd/const/regress43281_test.dart
new file mode 100644
index 0000000..e2a400a
--- /dev/null
+++ b/tests/language/nnbd/const/regress43281_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+// Regression test for https://github.com/dart-lang/sdk/issues/43281.
+
+void main() {
+  const s = {1, 2, 3, null};
+  Expect.equals(4, s.length);
+  Expect.isTrue(s is Set<int?>);
+}
diff --git a/tests/standalone/io/windows_file_system_links_test.dart b/tests/standalone/io/windows_file_system_links_test.dart
index ccf38e5..dcbc571 100644
--- a/tests/standalone/io/windows_file_system_links_test.dart
+++ b/tests/standalone/io/windows_file_system_links_test.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:expect/expect.dart';
 import "dart:io";
-import "dart:isolate";
+
+import 'package:expect/expect.dart';
 
 testJunctionTypeDelete() {
   var temp =
@@ -75,9 +75,57 @@
   });
 }
 
+void testLinkToFile() {
+  final temp =
+      Directory.systemTemp.createTempSync('dart_windows_file_system_links');
+  // Create file
+  File file = new File(temp.path + Platform.pathSeparator + "test-file.tmp");
+  file.createSync();
+  // Create link pointing to the file above
+  Link link = new Link(temp.path + Platform.pathSeparator + "test-link.lnk");
+  link.createSync(file.path);
+
+  Link link2 = new Link(temp.path + Platform.pathSeparator + "test-link2.lnk");
+  link2.createSync(link.path);
+
+  try {
+    Expect.isTrue(FileSystemEntity.isLinkSync(link.path));
+    Expect.isTrue(FileSystemEntity.isLinkSync(link2.path));
+    Expect.isTrue(FileSystemEntity.isFileSync(link2.path));
+    Expect.isFalse(FileSystemEntity.isDirectorySync(link2.path));
+  } finally {
+    temp.deleteSync(recursive: true);
+  }
+}
+
+void testLinkToDirectory() {
+  final temp =
+      Directory.systemTemp.createTempSync('dart_windows_file_system_links');
+  // Create file
+  Directory dir = Directory(temp.path + Platform.pathSeparator + "test-dir");
+  dir.createSync();
+  // Create link pointing to the file above
+  Link link = Link(temp.path + Platform.pathSeparator + "test-link.lnk");
+  link.createSync(dir.path);
+
+  Link link2 = Link(temp.path + Platform.pathSeparator + "test-link2.lnk");
+  link2.createSync(link.path);
+
+  try {
+    Expect.isTrue(FileSystemEntity.isLinkSync(link.path));
+    Expect.isTrue(FileSystemEntity.isLinkSync(link2.path));
+    Expect.isFalse(FileSystemEntity.isFileSync(link2.path));
+    Expect.isTrue(FileSystemEntity.isDirectorySync(link2.path));
+  } finally {
+    temp.deleteSync(recursive: true);
+  }
+}
+
 main() {
   // Links on other platforms are tested by file_system_[async_]links_test.
   if (Platform.operatingSystem == 'windows') {
     testJunctionTypeDelete();
+    testLinkToFile();
+    testLinkToDirectory();
   }
 }
diff --git a/tests/standalone_2/io/windows_file_system_links_test.dart b/tests/standalone_2/io/windows_file_system_links_test.dart
index ccf38e5..dcbc571 100644
--- a/tests/standalone_2/io/windows_file_system_links_test.dart
+++ b/tests/standalone_2/io/windows_file_system_links_test.dart
@@ -2,9 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:expect/expect.dart';
 import "dart:io";
-import "dart:isolate";
+
+import 'package:expect/expect.dart';
 
 testJunctionTypeDelete() {
   var temp =
@@ -75,9 +75,57 @@
   });
 }
 
+void testLinkToFile() {
+  final temp =
+      Directory.systemTemp.createTempSync('dart_windows_file_system_links');
+  // Create file
+  File file = new File(temp.path + Platform.pathSeparator + "test-file.tmp");
+  file.createSync();
+  // Create link pointing to the file above
+  Link link = new Link(temp.path + Platform.pathSeparator + "test-link.lnk");
+  link.createSync(file.path);
+
+  Link link2 = new Link(temp.path + Platform.pathSeparator + "test-link2.lnk");
+  link2.createSync(link.path);
+
+  try {
+    Expect.isTrue(FileSystemEntity.isLinkSync(link.path));
+    Expect.isTrue(FileSystemEntity.isLinkSync(link2.path));
+    Expect.isTrue(FileSystemEntity.isFileSync(link2.path));
+    Expect.isFalse(FileSystemEntity.isDirectorySync(link2.path));
+  } finally {
+    temp.deleteSync(recursive: true);
+  }
+}
+
+void testLinkToDirectory() {
+  final temp =
+      Directory.systemTemp.createTempSync('dart_windows_file_system_links');
+  // Create file
+  Directory dir = Directory(temp.path + Platform.pathSeparator + "test-dir");
+  dir.createSync();
+  // Create link pointing to the file above
+  Link link = Link(temp.path + Platform.pathSeparator + "test-link.lnk");
+  link.createSync(dir.path);
+
+  Link link2 = Link(temp.path + Platform.pathSeparator + "test-link2.lnk");
+  link2.createSync(link.path);
+
+  try {
+    Expect.isTrue(FileSystemEntity.isLinkSync(link.path));
+    Expect.isTrue(FileSystemEntity.isLinkSync(link2.path));
+    Expect.isFalse(FileSystemEntity.isFileSync(link2.path));
+    Expect.isTrue(FileSystemEntity.isDirectorySync(link2.path));
+  } finally {
+    temp.deleteSync(recursive: true);
+  }
+}
+
 main() {
   // Links on other platforms are tested by file_system_[async_]links_test.
   if (Platform.operatingSystem == 'windows') {
     testJunctionTypeDelete();
+    testLinkToFile();
+    testLinkToDirectory();
   }
 }
diff --git a/tools/VERSION b/tools/VERSION
index ba3ae6a..b464eb3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 91
+PRERELEASE 92
 PRERELEASE_PATCH 0
\ No newline at end of file