Version 2.10.0-149.0.dev

Merge commit '089a3a0de0cd422888984d404f8abeef23f5adbf' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/element/type_demotion.dart b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
index 37757e7..064cb13 100644
--- a/pkg/analyzer/lib/src/dart/element/type_demotion.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
@@ -5,7 +5,6 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/element/type_visitor.dart';
 import 'package:analyzer/src/dart/element/replacement_visitor.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 
@@ -22,13 +21,6 @@
   }
 }
 
-/// Returns `true` if type contains a promoted type variable.
-bool hasPromotedTypeVariable(DartType type) {
-  return type.accept(
-    const _HasPromotedTypeVariableVisitor(),
-  );
-}
-
 /// Visitor that replaces all promoted type variables the type variable itself
 /// and/or replaces all legacy types with non-nullable types.
 ///
@@ -70,41 +62,3 @@
     );
   }
 }
-
-/// Visitor that returns `true` if a type contains a promoted type variable.
-class _HasPromotedTypeVariableVisitor extends UnifyingTypeVisitor<bool> {
-  const _HasPromotedTypeVariableVisitor();
-
-  @override
-  bool visitDartType(DartType type) => false;
-
-  @override
-  bool visitFunctionType(FunctionType type) {
-    if (type.returnType.accept(this)) {
-      return true;
-    }
-
-    for (var parameter in type.parameters) {
-      if (parameter.type.accept(this)) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  @override
-  bool visitInterfaceType(InterfaceType type) {
-    for (var typeArgument in type.typeArguments) {
-      if (typeArgument.accept(this)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @override
-  bool visitTypeParameterType(TypeParameterType type) {
-    return (type as TypeParameterTypeImpl).promotedBound != null;
-  }
-}
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 fc73415..7b83ca3 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -95,11 +95,6 @@
     Expression right,
     DartType rightType,
   ) {
-    // TODO(scheglov) should not happen
-    if (writeType == null) {
-      return;
-    }
-
     if (!writeType.isVoid && _checkForUseOfVoidResult(right)) {
       return;
     }
@@ -147,11 +142,7 @@
   /// TODO(scheglov) this is duplication
   void _recordStaticType(Expression expression, DartType type) {
     if (_resolver.migrationResolutionHooks != null) {
-      // TODO(scheglov) type cannot be null
-      type = _migrationResolutionHooks.modifyExpressionType(
-        expression,
-        type ?? DynamicTypeImpl.instance,
-      );
+      type = _migrationResolutionHooks.modifyExpressionType(expression, type);
     }
 
     // TODO(scheglov) type cannot be null
@@ -216,62 +207,6 @@
     }
   }
 
-  /// TODO(scheglov) Replace [leftWriteType] with `node.writeType`
-  void _resolve2(AssignmentExpressionImpl node, DartType leftWriteType,
-      {@required bool doNullShortingTermination}) {
-    TokenType operator = node.operator.type;
-    if (operator == TokenType.EQ) {
-      var rightType = node.rightHandSide.staticType;
-      _inferenceHelper.recordStaticType(node, rightType);
-    } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
-      var leftType = node.readType;
-
-      // The LHS value will be used only if it is non-null.
-      if (_isNonNullableByDefault) {
-        leftType = _typeSystem.promoteToNonNull(leftType);
-      }
-
-      var rightType = node.rightHandSide.staticType;
-      var result = _typeSystem.getLeastUpperBound(leftType, rightType);
-
-      _inferenceHelper.recordStaticType(node, result);
-    } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
-        operator == TokenType.BAR_BAR_EQ) {
-      _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
-    } else {
-      var rightType = node.rightHandSide.staticType;
-
-      var leftReadType = node.readType;
-      if (identical(leftReadType, NeverTypeImpl.instance)) {
-        _inferenceHelper.recordStaticType(node, rightType);
-        return;
-      }
-
-      var operatorElement = node.staticElement;
-      var type = operatorElement?.returnType ?? DynamicTypeImpl.instance;
-      type = _typeSystem.refineBinaryExpressionType(
-        leftReadType,
-        operator,
-        rightType,
-        type,
-        operatorElement,
-      );
-      _inferenceHelper.recordStaticType(node, type);
-
-      if (!_typeSystem.isAssignableTo2(type, leftWriteType)) {
-        _resolver.errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVALID_ASSIGNMENT,
-          node.rightHandSide,
-          [type, leftWriteType],
-        );
-      }
-    }
-
-    if (doNullShortingTermination) {
-      _resolver.nullShortingTermination(node);
-    }
-  }
-
   void _resolve3(AssignmentExpressionImpl node, Expression left,
       TokenType operator, Expression right) {
     _resolve1(node);
@@ -292,17 +227,7 @@
     right?.accept(_resolver);
     right = node.rightHandSide;
 
-    _resolve2(node, node.writeType, doNullShortingTermination: false);
-
-    // TODO(scheglov) inline into resolve2().
-    DartType assignedType;
-    if (operator == TokenType.EQ ||
-        operator == TokenType.QUESTION_QUESTION_EQ) {
-      assignedType = right.staticType;
-    } else {
-      assignedType = node.staticType;
-    }
-    _checkForInvalidAssignment(node.writeType, right, assignedType);
+    _resolveTypes(node);
 
     _resolver.nullShortingTermination(node);
 
@@ -414,6 +339,56 @@
     _resolve3(node, left, operator, right);
   }
 
+  void _resolveTypes(AssignmentExpressionImpl node) {
+    DartType assignedType;
+    DartType nodeType;
+
+    var operator = node.operator.type;
+    if (operator == TokenType.EQ) {
+      assignedType = node.rightHandSide.staticType;
+      nodeType = assignedType;
+    } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
+      var leftType = node.readType;
+
+      // The LHS value will be used only if it is non-null.
+      if (_isNonNullableByDefault) {
+        leftType = _typeSystem.promoteToNonNull(leftType);
+      }
+
+      assignedType = node.rightHandSide.staticType;
+      nodeType = _typeSystem.getLeastUpperBound(leftType, assignedType);
+    } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
+        operator == TokenType.BAR_BAR_EQ) {
+      assignedType = _typeProvider.boolType;
+      nodeType = assignedType;
+    } else {
+      var operatorElement = node.staticElement;
+      if (operatorElement != null) {
+        var leftType = node.readType;
+        var rightType = node.rightHandSide.staticType;
+        assignedType = _typeSystem.refineBinaryExpressionType(
+          leftType,
+          operator,
+          rightType,
+          operatorElement.returnType,
+          operatorElement,
+        );
+      } else {
+        assignedType = DynamicTypeImpl.instance;
+      }
+      nodeType = assignedType;
+    }
+
+    _inferenceHelper.recordStaticType(node, nodeType);
+
+    // TODO(scheglov) Remove from ErrorVerifier?
+    _checkForInvalidAssignment(
+      node.writeType,
+      node.rightHandSide,
+      assignedType,
+    );
+  }
+
   /// TODO(scheglov) This is mostly necessary for backward compatibility.
   /// Although we also use `staticElement` for `getType(left)` below.
   void _setBackwardCompatibility(
diff --git a/tools/VERSION b/tools/VERSION
index d990faa..640a299 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 148
+PRERELEASE 149
 PRERELEASE_PATCH 0
\ No newline at end of file