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