Index: pkg/compiler/lib/src/cps_ir/type_mask_system.dart |
diff --git a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart |
index 6910d46392df3b18538939d2143c30cd88b22459..9c46857f443c731f93226c45914f329cf3dc4bb5 100644 |
--- a/pkg/compiler/lib/src/cps_ir/type_mask_system.dart |
+++ b/pkg/compiler/lib/src/cps_ir/type_mask_system.dart |
@@ -45,6 +45,7 @@ class TypeMaskSystem { |
TypeMask numStringBoolType; |
TypeMask fixedLengthType; |
TypeMask interceptorType; |
+ TypeMask interceptedTypes; // Does not include null. |
TypeMask _indexableTypeTest; |
@@ -71,6 +72,12 @@ class TypeMaskSystem { |
interceptorType = |
new TypeMask.nonNullSubtype(backend.jsInterceptorClass, classWorld); |
+ // We redundantly include subtypes of num/string/bool as intercepted types, |
+ // because the type system does not infer that their implementations are |
+ // all subclasses of Interceptor. |
+ interceptedTypes = new TypeMask.unionOf( |
+ <TypeMask>[interceptorType, numStringBoolType], classWorld); |
+ |
TypeMask typedArray = nonNullSubclass(backend.typedArrayClass); |
fixedLengthType = new TypeMask.unionOf( |
<TypeMask>[stringType, backend.fixedArrayType, typedArray], |
@@ -281,6 +288,24 @@ class TypeMaskSystem { |
return fixedLengthType.containsMask(t.nonNullable(), classWorld); |
} |
+ bool isDefinitelyIntercepted(TypeMask t, {bool allowNull}) { |
+ assert(allowNull != null); |
+ if (!allowNull && t.isNullable) return false; |
+ return interceptedTypes.containsMask(t.nonNullable(), classWorld); |
+ } |
+ |
+ /// Given a class from the interceptor hierarchy, returns a [TypeMask] |
+ /// matching all values with that interceptor (or a subtype thereof). |
+ TypeMask getInterceptorSubtypes(ClassElement class_) { |
+ if (class_ == backend.jsInterceptorClass) { |
+ return interceptorType.nullable(); |
+ } else if (class_ == backend.jsNullClass) { |
+ return nullType; |
+ } else { |
+ return nonNullSubclass(class_); |
+ } |
+ } |
+ |
bool areDisjoint(TypeMask leftType, TypeMask rightType) { |
TypeMask intersection = leftType.intersection(rightType, classWorld); |
return intersection.isEmpty && !intersection.isNullable; |