Version 2.10.0-41.0.dev

Merge commit '7af5788a5f4f27c956576aa5649d7aa0302d2d2b' into 'dev'
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 48db7fd..59261b0 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -212,15 +212,6 @@
   /// If no type argument is provided, the canonical raw type is returned.
   InterfaceType streamType([DartType elementType]);
 
-  /// Returns `true` if [element] is a superclass of `String` or `num`.
-  bool isNumberOrStringSupertype(ClassEntity element);
-
-  /// Returns `true` if [element] is a superclass of `String`.
-  bool isStringOnlySupertype(ClassEntity element);
-
-  /// Returns `true` if [element] is a superclass of `List`.
-  bool isListSupertype(ClassEntity element);
-
   InterfaceType getConstantListTypeFor(InterfaceType sourceType);
 
   InterfaceType getConstantMapTypeFor(InterfaceType sourceType,
@@ -982,19 +973,6 @@
     return _createInterfaceType(streamClass, [elementType]);
   }
 
-  @override
-  bool isNumberOrStringSupertype(ClassEntity element) {
-    return element == _findClass(coreLibrary, 'Comparable', required: false);
-  }
-
-  @override
-  bool isStringOnlySupertype(ClassEntity element) {
-    return element == _findClass(coreLibrary, 'Pattern', required: false);
-  }
-
-  @override
-  bool isListSupertype(ClassEntity element) => element == iterableClass;
-
   ClassEntity _findClass(LibraryEntity library, String name,
       {bool required: true}) {
     if (library == null) return null;
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index baa2c18..9dc19fc 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -46,6 +46,26 @@
 
   static AbstractBool maybeOrFalse(bool value) => value ? Maybe : False;
 
+  AbstractBool operator &(AbstractBool other) {
+    if (isDefinitelyTrue) return other;
+    if (other.isDefinitelyTrue) return this;
+    if (isDefinitelyFalse || other.isDefinitelyFalse) return False;
+    return Maybe;
+  }
+
+  AbstractBool operator |(AbstractBool other) {
+    if (isDefinitelyFalse) return other;
+    if (other.isDefinitelyFalse) return this;
+    if (isDefinitelyTrue || other.isDefinitelyTrue) return True;
+    return Maybe;
+  }
+
+  AbstractBool operator ~() {
+    if (isDefinitelyTrue) return AbstractBool.False;
+    if (isDefinitelyFalse) return AbstractBool.True;
+    return AbstractBool.Maybe;
+  }
+
   @override
   String toString() =>
       'AbstractBool.${_value == null ? 'Maybe' : (_value ? 'True' : 'False')}';
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index a657685..5c25132 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -310,7 +310,7 @@
 
     AbstractValueWithPrecision finish(TypeMask value, bool isPrecise) {
       return AbstractValueWithPrecision(
-          nullable ? value : value.nonNullable(), isPrecise);
+          nullable ? value.nullable() : value, isPrecise);
     }
 
     bool isPrecise = true;
@@ -363,25 +363,27 @@
       }
       switch (classRelation) {
         case ClassRelation.exact:
-          return finish(TypeMask.exact(cls, _closedWorld), isPrecise);
+          return finish(TypeMask.nonNullExact(cls, _closedWorld), isPrecise);
         case ClassRelation.thisExpression:
           if (!_closedWorld.isUsedAsMixin(cls)) {
-            return finish(TypeMask.subclass(cls, _closedWorld), isPrecise);
+            return finish(
+                TypeMask.nonNullSubclass(cls, _closedWorld), isPrecise);
           }
           break;
         case ClassRelation.subtype:
           break;
       }
-      return finish(TypeMask.subtype(cls, _closedWorld), isPrecise);
+      return finish(TypeMask.nonNullSubtype(cls, _closedWorld), isPrecise);
     }
 
     if (type is FunctionType) {
       return finish(
-          TypeMask.subtype(commonElements.functionClass, _closedWorld), false);
+          TypeMask.nonNullSubtype(commonElements.functionClass, _closedWorld),
+          false);
     }
 
     if (type is NeverType) {
-      return finish(nullType, isPrecise);
+      return finish(emptyType, isPrecise);
     }
 
     return AbstractValueWithPrecision(dynamicType, false);
@@ -426,7 +428,7 @@
   AbstractBool isInstanceOf(
       covariant TypeMask expressionMask, ClassEntity cls) {
     AbstractValue typeMask = (cls == commonElements.nullClass)
-        ? createNullableSubtype(cls)
+        ? nullType
         : createNonNullSubtype(cls);
     if (expressionMask.union(typeMask, this) == typeMask) {
       return AbstractBool.True;
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 72631d5..c950e0c 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -19,6 +19,7 @@
 import '../js_model/type_recipe.dart'
     show TypeEnvironmentStructure, TypeRecipe, TypeExpressionRecipe;
 import '../native/behavior.dart';
+import '../options.dart';
 import '../universe/selector.dart' show Selector;
 import '../universe/side_effects.dart' show SideEffects;
 import '../util/util.dart';
@@ -4071,9 +4072,10 @@
   HInstruction get typeInput => inputs[0];
   HInstruction get checkedInput => inputs[1];
 
-  AbstractBool evaluate(JClosedWorld closedWorld, {bool useNullSafety}) =>
-      _typeTest(checkedInput, dartType, checkedAbstractValue, closedWorld,
-          isCast: false, useNullSafety: useNullSafety);
+  AbstractBool evaluate(JClosedWorld closedWorld, CompilerOptions options) =>
+      _typeTest(
+          checkedInput, dartType, checkedAbstractValue, closedWorld, options,
+          isCast: false);
 
   @override
   accept(HVisitor visitor) => visitor.visitIsTest(this);
@@ -4106,9 +4108,10 @@
 
   HInstruction get checkedInput => inputs[0];
 
-  AbstractBool evaluate(JClosedWorld closedWorld, {bool useNullSafety}) =>
-      _typeTest(checkedInput, dartType, checkedAbstractValue, closedWorld,
-          isCast: false, useNullSafety: useNullSafety);
+  AbstractBool evaluate(JClosedWorld closedWorld, CompilerOptions options) =>
+      _typeTest(
+          checkedInput, dartType, checkedAbstractValue, closedWorld, options,
+          isCast: false);
 
   @override
   accept(HVisitor visitor) => visitor.visitIsTestSimple(this);
@@ -4126,18 +4129,24 @@
   String toString() => 'HIsTestSimple()';
 }
 
-AbstractBool _typeTest(HInstruction expression, DartType dartType,
-    AbstractValueWithPrecision checkedAbstractValue, JClosedWorld closedWorld,
-    {bool isCast, bool useNullSafety}) {
+AbstractBool _typeTest(
+    HInstruction expression,
+    DartType dartType,
+    AbstractValueWithPrecision checkedAbstractValue,
+    JClosedWorld closedWorld,
+    CompilerOptions options,
+    {bool isCast}) {
+  JCommonElements commonElements = closedWorld.commonElements;
+  DartTypes dartTypes = closedWorld.dartTypes;
   AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
   AbstractValue subsetType = expression.instructionType;
   AbstractValue supersetType = checkedAbstractValue.abstractValue;
   AbstractBool expressionIsNull = expression.isNull(abstractValueDomain);
 
-  if (!isCast && useNullSafety) {
+  if (!isCast && options.useNullSafety) {
     if (expressionIsNull.isDefinitelyTrue) {
       if (dartType.isObject) return AbstractBool.False;
-      if (closedWorld.dartTypes.isTopType(dartType) ||
+      if (dartTypes.isTopType(dartType) ||
           dartType is NullableType ||
           dartType.isNull) {
         return AbstractBool.True;
@@ -4163,74 +4172,89 @@
     return AbstractBool.True;
   }
 
+  if (abstractValueDomain
+      .areDisjoint(subsetType, supersetType)
+      .isDefinitelyTrue) {
+    return AbstractBool.False;
+  }
+
   // TODO(39287): Let the abstract value domain fully handle this.
   // Currently, the abstract value domain cannot (soundly) state that an is-test
   // is definitely false, so we reuse some of the case-by-case logic from the
   // old [HIs] optimization.
-  if (closedWorld.dartTypes.isTopType(dartType)) return AbstractBool.True;
 
-  InterfaceType type;
-  if (dartType is InterfaceType) {
-    type = dartType;
-  } else if (dartType is LegacyType) {
-    DartType base = dartType.baseType;
-    if (base is! InterfaceType) return AbstractBool.Maybe;
-    assert(!base.isObject); // Top type handled above;
-    type = base;
-  } else {
+  AbstractBool checkInterface(InterfaceType interface) {
+    if (expression.isInteger(abstractValueDomain).isDefinitelyTrue) {
+      if (dartTypes.isSubtype(commonElements.intType, interface)) {
+        return AbstractBool.True;
+      }
+      if (interface == commonElements.doubleType) {
+        // We let the JS semantics decide for that check. Currently the code we
+        // emit will always return true.
+        return AbstractBool.Maybe;
+      }
+      return AbstractBool.False;
+    }
+
+    if (expression.isDouble(abstractValueDomain).isDefinitelyTrue) {
+      if (dartTypes.isSubtype(commonElements.doubleType, interface)) {
+        return AbstractBool.True;
+      }
+      if (interface == commonElements.intType) {
+        // We let the JS semantics decide for that check. Currently the code we
+        // emit will return true for a double that can be represented as a 31-bit
+        // integer and for -0.0.
+        return AbstractBool.Maybe;
+      }
+      return AbstractBool.False;
+    }
+
+    if (expression.isNumber(abstractValueDomain).isDefinitelyTrue) {
+      if (dartTypes.isSubtype(commonElements.numType, interface)) {
+        return AbstractBool.True;
+      }
+      // We cannot just return false, because the expression may be of type int or
+      // double.
+      return AbstractBool.Maybe;
+    }
+
+    // We need the raw check because we don't have the notion of generics in the
+    // backend. For example, `this` in a class `A<T>` is currently always
+    // considered to have the raw type.
+    if (dartTypes.treatAsRawType(interface)) {
+      return abstractValueDomain.isInstanceOf(subsetType, interface.element);
+    }
+
     return AbstractBool.Maybe;
   }
 
-  ClassEntity element = type.element;
-  if (type.typeArguments.isNotEmpty) return AbstractBool.Maybe;
-  JCommonElements commonElements = closedWorld.commonElements;
-  if (expression.isInteger(abstractValueDomain).isDefinitelyTrue) {
-    if (element == commonElements.intClass ||
-        element == commonElements.numClass ||
-        commonElements.isNumberOrStringSupertype(element)) {
-      return AbstractBool.True;
+  AbstractBool isNullAsCheck = !options.useLegacySubtyping && isCast
+      ? expressionIsNull
+      : AbstractBool.False;
+  AbstractBool isNullIsTest =
+      options.useNullSafety && !isCast ? expressionIsNull : AbstractBool.False;
+
+  AbstractBool unwrapAndCheck(DartType type) {
+    if (dartTypes.isTopType(dartType)) return AbstractBool.True;
+    if (type is NeverType) return AbstractBool.False;
+    if (type is InterfaceType) {
+      if (type.isNull) return expressionIsNull;
+      return ~(isNullAsCheck | isNullIsTest) & checkInterface(type);
     }
-    if (element == commonElements.doubleClass) {
-      // We let the JS semantics decide for that check. Currently the code we
-      // emit will always return true.
-      return AbstractBool.Maybe;
+    if (type is LegacyType) {
+      assert(!type.baseType.isObject);
+      return ~isNullIsTest & unwrapAndCheck(type.baseType);
     }
-    return AbstractBool.False;
-  }
-  if (expression.isDouble(abstractValueDomain).isDefinitelyTrue) {
-    if (element == commonElements.doubleClass ||
-        element == commonElements.numClass ||
-        commonElements.isNumberOrStringSupertype(element)) {
-      return AbstractBool.True;
+    if (type is NullableType) {
+      return unwrapAndCheck(type.baseType);
     }
-    if (element == commonElements.intClass) {
-      // We let the JS semantics decide for that check. Currently the code we
-      // emit will return true for a double that can be represented as a 31-bit
-      // integer and for -0.0.
-      return AbstractBool.Maybe;
+    if (type is FutureOrType) {
+      return unwrapAndCheck(type.typeArgument) | AbstractBool.Maybe;
     }
-    return AbstractBool.False;
-  }
-  if (expression.isNumber(abstractValueDomain).isDefinitelyTrue) {
-    if (element == commonElements.numClass) {
-      return AbstractBool.True;
-    }
-    // We cannot just return false, because the expression may be of type int or
-    // double.
     return AbstractBool.Maybe;
   }
-  if (expression.isPrimitiveNumber(abstractValueDomain).isPotentiallyTrue &&
-      element == commonElements.intClass) {
-    // We let the JS semantics decide for that check.
-    return AbstractBool.Maybe;
-  }
-  // We need the raw check because we don't have the notion of generics in the
-  // backend. For example, `this` in a class `A<T>` is currently always
-  // considered to have the raw type.
-  if (closedWorld.dartTypes.treatAsRawType(type)) {
-    return abstractValueDomain.isInstanceOf(subsetType, element);
-  }
-  return AbstractBool.Maybe;
+
+  return unwrapAndCheck(dartType);
 }
 
 /// Type cast or type check using Rti form of type expression.
@@ -4271,9 +4295,10 @@
     return isTypeError == other.isTypeError;
   }
 
-  bool isRedundant(JClosedWorld closedWorld, {bool useNullSafety}) =>
+  bool isRedundant(JClosedWorld closedWorld, CompilerOptions options) =>
       _typeTest(checkedInput, checkedTypeExpression, checkedType, closedWorld,
-              isCast: true, useNullSafety: useNullSafety)
+              options,
+              isCast: true)
           .isDefinitelyTrue;
 
   @override
@@ -4305,9 +4330,9 @@
   @override
   accept(HVisitor visitor) => visitor.visitAsCheckSimple(this);
 
-  bool isRedundant(JClosedWorld closedWorld, {bool useNullSafety}) =>
-      _typeTest(checkedInput, dartType, checkedType, closedWorld,
-              isCast: true, useNullSafety: useNullSafety)
+  bool isRedundant(JClosedWorld closedWorld, CompilerOptions options) =>
+      _typeTest(checkedInput, dartType, checkedType, closedWorld, options,
+              isCast: true)
           .isDefinitelyTrue;
 
   @override
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 0d00347..acb8cbc 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -1871,7 +1871,7 @@
       node.checkedTypeExpression = recipe.type;
     }
 
-    if (node.isRedundant(_closedWorld, useNullSafety: _options.useNullSafety)) {
+    if (node.isRedundant(_closedWorld, _options)) {
       return node.checkedInput;
     }
 
@@ -1896,7 +1896,7 @@
 
   @override
   HInstruction visitAsCheckSimple(HAsCheckSimple node) {
-    if (node.isRedundant(_closedWorld, useNullSafety: _options.useNullSafety)) {
+    if (node.isRedundant(_closedWorld, _options)) {
       return node.checkedInput;
     }
     return node;
@@ -1910,8 +1910,7 @@
       node.dartType = recipe.type;
     }
 
-    AbstractBool result =
-        node.evaluate(_closedWorld, useNullSafety: _options.useNullSafety);
+    AbstractBool result = node.evaluate(_closedWorld, _options);
     if (result.isDefinitelyFalse) {
       return _graph.addConstantBool(false, _closedWorld);
     }
@@ -1947,8 +1946,7 @@
 
   @override
   HInstruction visitIsTestSimple(HIsTestSimple node) {
-    AbstractBool result =
-        node.evaluate(_closedWorld, useNullSafety: _options.useNullSafety);
+    AbstractBool result = node.evaluate(_closedWorld, _options);
     if (result.isDefinitelyFalse) {
       return _graph.addConstantBool(false, _closedWorld);
     }
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index 7a176fa..e12559c 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -83,7 +83,8 @@
     // `buildAsCheck` in `SsaBuilder.visitAs` should also be followed by a
     // similar operation on `registry`; otherwise, this one might not be needed.
     builder.registry?.registerTypeUse(new TypeUse.isCheck(type));
-    if (other is HAsCheck && other.isRedundant(builder.closedWorld)) {
+    if (other is HAsCheck &&
+        other.isRedundant(builder.closedWorld, builder.options)) {
       return original;
     }
     return other;
diff --git a/pkg/compiler/test/rti/emission/jsinterop_generic.dart b/pkg/compiler/test/rti/emission/jsinterop_generic.dart
index cc2d44a..d409967 100644
--- a/pkg/compiler/test/rti/emission/jsinterop_generic.dart
+++ b/pkg/compiler/test/rti/emission/jsinterop_generic.dart
@@ -33,7 +33,7 @@
   external factory C();
 }
 
-/*class: D:checkedInstance*/
+/*class: D:*/
 class D<T> {}
 
 /*class: E:checks=[],instance,onlyForRti*/
diff --git a/tools/VERSION b/tools/VERSION
index 7306b60..686f446 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 40
+PRERELEASE 41
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/patches/flutter-engine/apply.sh b/tools/patches/flutter-engine/apply.sh
index e8b7ae2..91918a1 100755
--- a/tools/patches/flutter-engine/apply.sh
+++ b/tools/patches/flutter-engine/apply.sh
@@ -15,6 +15,9 @@
 # then it stops applying patches atomically as there isn't a patch available yet
 # for the new roll.
 #
+# Additionally, this script updates the flutter engine DEPS file with the
+# Dart SDK dependencies.
+#
 # Usage: src/third_party/dart/tools/patches/flutter-engine/apply.sh
 # (run inside the root of a flutter engine checkout)
 
@@ -39,6 +42,12 @@
   need_runhooks=true
 fi
 
+# Update the flutter DEPS with the revisions in the Dart SDK DEPS.
+src/tools/dart/create_updated_flutter_deps.py
+if ! (cd src/flutter && git diff --exit-code DEPS); then
+  need_runhooks=true
+fi
+
 if [ $need_runhooks = true ]; then
   # Check if .gclient configuration specifies a cache_dir. Local caches are used
   # by bots to reduce amount of Git traffic. .gclient configuration file