// Copyright (c) 2013, 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.

part of types;

/**
 * A flat type mask is a type mask that has been flattened to contain a
 * base type.
 */
class FlatTypeMask implements TypeMask {
  static const int EMPTY    = 0;
  static const int EXACT    = 1;
  static const int SUBCLASS = 2;
  static const int SUBTYPE  = 3;

  final ClassElement base;
  final int flags;

  FlatTypeMask(ClassElement base, int kind, bool isNullable)
      : this.internal(base, (kind << 1) | (isNullable ? 1 : 0));

  FlatTypeMask.exact(ClassElement base)
      : this.internal(base, (EXACT << 1) | 1);
  FlatTypeMask.subclass(ClassElement base)
      : this.internal(base, (SUBCLASS << 1) | 1);
  FlatTypeMask.subtype(ClassElement base)
      : this.internal(base, (SUBTYPE << 1) | 1);

  const FlatTypeMask.nonNullEmpty(): base = null, flags = 0;
  const FlatTypeMask.empty() : base = null, flags = 1;

  FlatTypeMask.nonNullExact(ClassElement base)
      : this.internal(base, EXACT << 1);
  FlatTypeMask.nonNullSubclass(ClassElement base)
      : this.internal(base, SUBCLASS << 1);
  FlatTypeMask.nonNullSubtype(ClassElement base)
      : this.internal(base, SUBTYPE << 1);

  FlatTypeMask.internal(this.base, this.flags) {
    assert(base == null || base.isDeclaration);
  }

  /**
   * Ensures that the generated mask is normalized, i.e., a call to
   * [TypeMask.assertIsNormalized] with the factory's result returns `true`.
   */
  factory FlatTypeMask.normalized(ClassElement base, int flags, World world) {
    if ((flags >> 1) == EMPTY || ((flags >> 1) == EXACT)) {
      return new FlatTypeMask.internal(base, flags);
    }
    if ((flags >> 1) == SUBTYPE) {
      if (!world.hasAnyStrictSubtype(base) || world.hasOnlySubclasses(base)) {
        flags = (flags & 0x1) | (SUBCLASS << 1);
      }
    }
    if (((flags >> 1) == SUBCLASS) && !world.hasAnyStrictSubclass(base)) {
      flags = (flags & 0x1) | (EXACT << 1);
    }
    Map<ClassElement, TypeMask> cachedMasks =
        world.canonicalizedTypeMasks[flags];
    if (cachedMasks == null) {
      world.canonicalizedTypeMasks[flags] = cachedMasks =
          <ClassElement, TypeMask>{};
    }
    return cachedMasks.putIfAbsent(base,
        () => new FlatTypeMask.internal(base, flags));
  }

  bool get isEmpty => (flags >> 1) == EMPTY;
  bool get isExact => (flags >> 1) == EXACT;
  bool get isNullable => (flags & 1) != 0;

  bool get isUnion => false;
  bool get isContainer => false;
  bool get isMap => false;
  bool get isDictionary => false;
  bool get isForwarding => false;
  bool get isValue => false;

  // TODO(kasperl): Get rid of these. They should not be a visible
  // part of the implementation because they make it hard to add
  // proper union types if we ever want to.
  bool get isSubclass => (flags >> 1) == SUBCLASS;
  bool get isSubtype => (flags >> 1) == SUBTYPE;

  TypeMask nullable() {
    return isNullable ? this : new FlatTypeMask.internal(base, flags | 1);
  }

  TypeMask nonNullable() {
    return isNullable ? new FlatTypeMask.internal(base, flags & ~1) : this;
  }

  bool contains(ClassElement type, ClassWorld classWorld) {
    assert(type.isDeclaration);
    if (isEmpty) {
      return false;
    } else if (identical(base, type)) {
      return true;
    } else if (isExact) {
      return false;
    } else if (isSubclass) {
      return classWorld.isSubclassOf(type, base);
    } else {
      assert(isSubtype);
      return classWorld.isSubtypeOf(type, base);
    }
  }

  bool isSingleImplementationOf(ClassElement cls, ClassWorld classWorld) {
    // Special case basic types so that, for example, JSString is the
    // single implementation of String.
    // The general optimization is to realize there is only one class that
    // implements [base] and [base] is not instantiated. We however do
    // not track correctly the list of truly instantiated classes.
    Backend backend = classWorld.backend;
    if (containsOnlyString(classWorld)) {
      return cls == classWorld.stringClass ||
             cls == backend.stringImplementation;
    }
    if (containsOnlyBool(classWorld)) {
      return cls == classWorld.boolClass || cls == backend.boolImplementation;
    }
    if (containsOnlyInt(classWorld)) {
      return cls == classWorld.intClass
          || cls == backend.intImplementation
          || cls == backend.positiveIntImplementation
          || cls == backend.uint32Implementation
          || cls == backend.uint31Implementation;
    }
    if (containsOnlyDouble(classWorld)) {
      return cls == classWorld.doubleClass
          || cls == backend.doubleImplementation;
    }
    return false;
  }

  bool isInMask(TypeMask other, ClassWorld classWorld) {
    // null is treated separately, so the empty mask might still contain it.
    if (isEmpty) return isNullable ? other.isNullable : true;
    // The empty type contains no classes.
    if (other.isEmpty) return false;
    // Quick check whether to handle null.
    if (isNullable && !other.isNullable) return false;
    other = TypeMask.nonForwardingMask(other);
    // If other is union, delegate to UnionTypeMask.containsMask.
    if (other is! FlatTypeMask) return other.containsMask(this, classWorld);
    // The other must be flat, so compare base and flags.
    FlatTypeMask flatOther = other;
    ClassElement otherBase = flatOther.base;
    // If other is exact, it only contains its base.
    // TODO(herhut): Get rid of isSingleImplementationOf.
    if (flatOther.isExact) {
      return (isExact && base == otherBase)
          || isSingleImplementationOf(otherBase, classWorld);
    }
    // If other is subclass, this has to be subclass, as well. Unless
    // flatOther.base covers all subtypes of this. Currently, we only
    // consider object to behave that way.
    // TODO(herhut): Add check whether flatOther.base is superclass of
    //               all subclasses of this.base.
    if (flatOther.isSubclass) {
      if (isSubtype) return (otherBase == classWorld.objectClass);
      return classWorld.isSubclassOf(base, otherBase);
    }
    assert(flatOther.isSubtype);
    // Check whether this TypeMask satisfies otherBase's interface.
    return satisfies(otherBase, classWorld);
  }

  bool containsMask(TypeMask other, ClassWorld classWorld) {
    return other.isInMask(this, classWorld);
  }

  bool containsOnlyInt(ClassWorld classWorld) {
    Backend backend = classWorld.backend;
    return base == classWorld.intClass
        || base == backend.intImplementation
        || base == backend.positiveIntImplementation
        || base == backend.uint31Implementation
        || base == backend.uint32Implementation;
  }

  bool containsOnlyDouble(ClassWorld classWorld) {
    Backend backend = classWorld.backend;
    return base == classWorld.doubleClass
        || base == backend.doubleImplementation;
  }

  bool containsOnlyNum(ClassWorld classWorld) {
    Backend backend = classWorld.backend;
    return containsOnlyInt(classWorld)
        || containsOnlyDouble(classWorld)
        || base == classWorld.numClass
        || base == backend.numImplementation;
  }

  bool containsOnlyBool(ClassWorld classWorld) {
    Backend backend = classWorld.backend;
    return base == classWorld.boolClass
        || base == backend.boolImplementation;
  }

  bool containsOnlyString(ClassWorld classWorld) {
    Backend backend = classWorld.backend;
    return base == classWorld.stringClass
        || base == backend.stringImplementation;
  }

  bool containsOnly(ClassElement cls) {
    assert(cls.isDeclaration);
    return base == cls;
  }

  bool satisfies(ClassElement cls, ClassWorld classWorld) {
    assert(cls.isDeclaration);
    if (isEmpty) return false;
    if (classWorld.isSubtypeOf(base, cls)) return true;
    return false;
  }

  /**
   * Returns the [ClassElement] if this type represents a single class,
   * otherwise returns `null`.  This method is conservative.
   */
  ClassElement singleClass(ClassWorld classWorld) {
    if (isEmpty) return null;
    if (isNullable) return null;  // It is Null and some other class.
    if (isExact) {
      return base;
    } else if (isSubclass) {
      return classWorld.hasAnyStrictSubclass(base) ? null : base;
    } else {
      assert(isSubtype);
      return null;
    }
  }

  /**
   * Returns whether or not this type mask contains all types.
   */
  bool containsAll(ClassWorld classWorld) {
    if (isEmpty || isExact) return false;
    return identical(base, classWorld.objectClass);
  }

  TypeMask union(TypeMask other, ClassWorld classWorld) {
    assert(other != null);
    assert(TypeMask.assertIsNormalized(this, classWorld));
    assert(TypeMask.assertIsNormalized(other, classWorld));
    if (other is! FlatTypeMask) return other.union(this, classWorld);
    FlatTypeMask flatOther = other;
    if (isEmpty) {
      return isNullable ? flatOther.nullable() : flatOther;
    } else if (flatOther.isEmpty) {
      return flatOther.isNullable ? nullable() : this;
    } else if (base == flatOther.base) {
      return unionSame(flatOther, classWorld);
    } else if (classWorld.isSubclassOf(flatOther.base, base)) {
      return unionStrictSubclass(flatOther, classWorld);
    } else if (classWorld.isSubclassOf(base, flatOther.base)) {
      return flatOther.unionStrictSubclass(this, classWorld);
    } else if (classWorld.isSubtypeOf(flatOther.base, base)) {
      return unionStrictSubtype(flatOther, classWorld);
    } else if (classWorld.isSubtypeOf(base, flatOther.base)) {
      return flatOther.unionStrictSubtype(this, classWorld);
    } else {
      return new UnionTypeMask._internal(<FlatTypeMask>[this, flatOther]);
    }
  }

  TypeMask unionSame(FlatTypeMask other, ClassWorld classWorld) {
    assert(base == other.base);
    assert(TypeMask.assertIsNormalized(this, classWorld));
    assert(TypeMask.assertIsNormalized(other, classWorld));
    // The two masks share the base type, so we must chose the least
    // constraining kind (the highest) of the two. If either one of
    // the masks are nullable the result should be nullable too.
    // As both masks are normalized, the result will be, too.
    int combined = (flags > other.flags)
        ? flags | (other.flags & 1)
        : other.flags | (flags & 1);
    if (flags == combined) {
      return this;
    } else if (other.flags == combined) {
      return other;
    } else {
      return new FlatTypeMask.normalized(base, combined, classWorld);
    }
  }

  TypeMask unionStrictSubclass(FlatTypeMask other, ClassWorld classWorld) {
    assert(base != other.base);
    assert(classWorld.isSubclassOf(other.base, base));
    assert(TypeMask.assertIsNormalized(this, classWorld));
    assert(TypeMask.assertIsNormalized(other, classWorld));
    int combined;
    if ((isExact && other.isExact) || base == classWorld.objectClass) {
      // Since the other mask is a subclass of this mask, we need the
      // resulting union to be a subclass too. If either one of the
      // masks are nullable the result should be nullable too.
      combined = (SUBCLASS << 1) | ((flags | other.flags) & 1);
    } else {
      // Both masks are at least subclass masks, so we pick the least
      // constraining kind (the highest) of the two. If either one of
      // the masks are nullable the result should be nullable too.
      combined = (flags > other.flags)
          ? flags | (other.flags & 1)
          : other.flags | (flags & 1);
    }
    // If we weaken the constraint on this type, we have to make sure that
    // the result is normalized.
    return (flags != combined)
        ? new FlatTypeMask.normalized(base, combined, classWorld)
        : this;
  }

  TypeMask unionStrictSubtype(FlatTypeMask other, ClassWorld classWorld) {
    assert(base != other.base);
    assert(!classWorld.isSubclassOf(other.base, base));
    assert(classWorld.isSubtypeOf(other.base, base));
    assert(TypeMask.assertIsNormalized(this, classWorld));
    assert(TypeMask.assertIsNormalized(other, classWorld));
    // Since the other mask is a subtype of this mask, we need the
    // resulting union to be a subtype too. If either one of the masks
    // are nullable the result should be nullable too.
    int combined = (SUBTYPE << 1) | ((flags | other.flags) & 1);
    // We know there is at least one subtype, [other.base], so no need
    // to normalize.
    return (flags != combined)
        ? new FlatTypeMask.normalized(base, combined, classWorld)
        : this;
  }

  TypeMask intersection(TypeMask other, ClassWorld classWorld) {
    assert(other != null);
    if (other is! FlatTypeMask) return other.intersection(this, classWorld);
    assert(TypeMask.assertIsNormalized(this, classWorld));
    assert(TypeMask.assertIsNormalized(other, classWorld));
    FlatTypeMask flatOther = other;
    if (isEmpty) {
      return flatOther.isNullable ? this : nonNullable();
    } else if (flatOther.isEmpty) {
      return isNullable ? flatOther : other.nonNullable();
    } else if (base == flatOther.base) {
      return intersectionSame(flatOther, classWorld);
    } else if (classWorld.isSubclassOf(flatOther.base, base)) {
      return intersectionStrictSubclass(flatOther, classWorld);
    } else if (classWorld.isSubclassOf(base, flatOther.base)) {
      return flatOther.intersectionStrictSubclass(this, classWorld);
    } else if (classWorld.isSubtypeOf(flatOther.base, base)) {
      return intersectionStrictSubtype(flatOther, classWorld);
    } else if (classWorld.isSubtypeOf(base, flatOther.base)) {
      return flatOther.intersectionStrictSubtype(this, classWorld);
    } else {
      return intersectionDisjoint(flatOther, classWorld);
    }
  }

  bool isDisjoint(TypeMask other, ClassWorld classWorld) {
    if (other is! FlatTypeMask) return other.isDisjoint(this, classWorld);
    FlatTypeMask flatOther = other;

    if (isNullable && flatOther.isNullable) return false;
    if (isEmpty || flatOther.isEmpty) return true;
    if (base == flatOther.base) return false;
    if (isExact && flatOther.isExact) return true;

    if (isExact) return !flatOther.contains(base, classWorld);
    if (flatOther.isExact) return !contains(flatOther.base, classWorld);

    // Normalization guarantees that isExact === !isSubclass && !isSubtype.
    // Both are subclass or subtype masks, so if there is a subclass
    // relationship, they are not disjoint.
    if (classWorld.isSubclassOf(flatOther.base, base)) return false;
    if (classWorld.isSubclassOf(base, flatOther.base)) return false;

    // Two different base classes have no common subclass unless one is a
    // subclass of the other (checked above).
    if (isSubclass && flatOther.isSubclass) return true;

    return _isDisjointHelper(this, flatOther, classWorld);
  }

  static bool _isDisjointHelper(
      FlatTypeMask a, FlatTypeMask b, ClassWorld classWorld) {
    if (!a.isSubclass && b.isSubclass) {
      return _isDisjointHelper(b, a, classWorld);
    }
    assert(a.isSubclass || a.isSubtype);
    assert(b.isSubtype);
    var elements = a.isSubclass
      ? classWorld.strictSubclassesOf(a.base)
      : classWorld.strictSubtypesOf(a.base);
    for (var element in elements) {
      if (classWorld.isSubtypeOf(element, b.base)) return false;
    }
    return true;
  }

  TypeMask intersectionSame(FlatTypeMask other, ClassWorld classWorld) {
    assert(base == other.base);
    // The two masks share the base type, so we must chose the most
    // constraining kind (the lowest) of the two. Only if both masks
    // are nullable, will the result be nullable too.
    // The result will be normalized, as the two inputs are normalized, too.
    int combined = (flags < other.flags)
        ? flags & ((other.flags & 1) | ~1)
        : other.flags & ((flags & 1) | ~1);
    if (flags == combined) {
      return this;
    } else if (other.flags == combined) {
      return other;
    } else {
      return new FlatTypeMask.normalized(base, combined, classWorld);
    }
  }

  TypeMask intersectionStrictSubclass(FlatTypeMask other,
                                      ClassWorld classWorld) {
    assert(base != other.base);
    assert(classWorld.isSubclassOf(other.base, base));
    // If this mask isn't at least a subclass mask, then the
    // intersection with the other mask is empty.
    if (isExact) return intersectionEmpty(other);
    // Only the other mask puts constraints on the intersection mask,
    // so base the combined flags on the other mask. Only if both
    // masks are nullable, will the result be nullable too.
    // The result is guaranteed to be normalized, as the other type
    // was normalized.
    int combined = other.flags & ((flags & 1) | ~1);
    if (other.flags == combined) {
      return other;
    } else {
      return new FlatTypeMask.normalized(other.base, combined, classWorld);
    }
  }

  TypeMask intersectionStrictSubtype(FlatTypeMask other,
                                     ClassWorld classWorld) {
    assert(base != other.base);
    assert(classWorld.isSubtypeOf(other.base, base));
    if (!isSubtype) return intersectionHelper(other, classWorld);
    // Only the other mask puts constraints on the intersection mask,
    // so base the combined flags on the other mask. Only if both
    // masks are nullable, will the result be nullable too.
    // The result is guaranteed to be normalized, as the other type
    // was normalized.
    int combined = other.flags & ((flags & 1) | ~1);
    if (other.flags == combined) {
      return other;
    } else {
      return new FlatTypeMask.normalized(other.base, combined, classWorld);
    }
  }

  TypeMask intersectionDisjoint(FlatTypeMask other, ClassWorld classWorld) {
    assert(base != other.base);
    assert(!classWorld.isSubtypeOf(base, other.base));
    assert(!classWorld.isSubtypeOf(other.base, base));
    return intersectionHelper(other, classWorld);
  }

  TypeMask intersectionHelper(FlatTypeMask other, ClassWorld classWorld) {
    assert(base != other.base);
    assert(!classWorld.isSubclassOf(base, other.base));
    assert(!classWorld.isSubclassOf(other.base, base));
    // If one of the masks are exact or if both of them are subclass
    // masks, then the intersection is empty.
    if (isExact || other.isExact) return intersectionEmpty(other);
    if (isSubclass && other.isSubclass) return intersectionEmpty(other);
    assert(isSubtype || other.isSubtype);
    int kind = (isSubclass || other.isSubclass) ? SUBCLASS : SUBTYPE;
    // Compute the set of classes that are contained in both type masks.
    Set<ClassElement> common = commonContainedClasses(this, other, classWorld);
    if (common == null || common.isEmpty) return intersectionEmpty(other);
    // Narrow down the candidates by only looking at common classes
    // that do not have a superclass or supertype that will be a
    // better candidate.
    Iterable<ClassElement> candidates = common.where((ClassElement each) {
      bool containsSuperclass = common.contains(each.supertype.element);
      // If the superclass is also a candidate, then we don't want to
      // deal with this class. If we're only looking for a subclass we
      // know we don't have to look at the list of interfaces because
      // they can never be in the common set.
      if (containsSuperclass || kind == SUBCLASS) return !containsSuperclass;
      // Run through the direct supertypes of the class. If the common
      // set contains the direct supertype of the class, we ignore the
      // the class because the supertype is a better candidate.
      for (Link link = each.interfaces; !link.isEmpty; link = link.tail) {
        if (common.contains(link.head.element)) return false;
      }
      return true;
    });
    // Run through the list of candidates and compute the union. The
    // result will only be nullable if both masks are nullable. We have
    // to normalize here, as we generate types based on new base classes.
    int combined = (kind << 1) | (flags & other.flags & 1);
    Iterable<TypeMask> masks = candidates.map((ClassElement cls) {
      return new FlatTypeMask.normalized(cls, combined, classWorld);
    });
    return UnionTypeMask.unionOf(masks, classWorld);
  }

  TypeMask intersectionEmpty(FlatTypeMask other) {
    return isNullable && other.isNullable ? new TypeMask.empty()
        : new TypeMask.nonNullEmpty();
  }

  /**
   * Returns whether [element] will be the one used at runtime when being
   * invoked on an instance of [cls]. [selector] is used to ensure library
   * privacy is taken into account.
   */
  static bool hasElementIn(ClassElement cls,
                           Selector selector,
                           Element element) {
    // Use [:implementation:] of [element]
    // because our function set only stores declarations.
    Element result = findMatchIn(cls, selector);
    return result == null
        ? false
        : result.implementation == element.implementation;
  }

  static Element findMatchIn(ClassElement cls,
                             Selector selector) {
    // Use the [:implementation] of [cls] in case the found [element]
    // is in the patch class.
    return cls.implementation.lookupByName(selector.memberName);
  }

  /**
   * Returns whether [element] is a potential target when being
   * invoked on this type mask. [selector] is used to ensure library
   * privacy is taken into account.
   */
  bool canHit(Element element, Selector selector, ClassWorld classWorld) {
    Backend backend = classWorld.backend;
    assert(element.name == selector.name);
    if (isEmpty) {
      if (!isNullable) return false;
      return hasElementIn(backend.nullImplementation, selector, element);
    }

    // TODO(kasperl): Can't we just avoid creating typed selectors
    // based of function types?
    Element self = base;
    if (self.isTypedef) {
      // A typedef is a function type that doesn't have any
      // user-defined members.
      return false;
    }

    ClassElement other = element.enclosingClass;
    if (other == backend.nullImplementation) {
      return isNullable;
    } else if (isExact) {
      return hasElementIn(self, selector, element);
    } else if (isSubclass) {
      assert(classWorld.isClosed);
      return hasElementIn(self, selector, element)
          || other.isSubclassOf(self)
          || classWorld.hasAnySubclassThatMixes(self, other);
    } else {
      assert(isSubtype);
      assert(classWorld.isClosed);
      bool result = hasElementIn(self, selector, element)
          || other.implementsInterface(self)
          || classWorld.hasAnySubclassThatImplements(other, base)
          || classWorld.hasAnySubclassOfMixinUseThatImplements(other, base);
      if (result) return true;
      // If the class is used as a mixin, we have to check if the element
      // can be hit from any of the mixin applications.
      Iterable<ClassElement> mixinUses = classWorld.mixinUsesOf(self);
      return mixinUses.any((mixinApplication) =>
           hasElementIn(mixinApplication, selector, element)
        || other.isSubclassOf(mixinApplication)
        || classWorld.hasAnySubclassThatMixes(mixinApplication, other));
    }
  }

  /**
   * Returns whether a [selector] call on an instance of [cls]
   * will hit a method at runtime, and not go through [noSuchMethod].
   */
  static bool hasConcreteMatch(ClassElement cls,
                               Selector selector,
                               ClassWorld world) {
    assert(invariant(cls, world.isInstantiated(cls),
        message: '$cls has not been instantiated.'));
    Element element = findMatchIn(cls, selector);
    if (element == null) return false;

    if (element.isAbstract) {
      ClassElement enclosingClass = element.enclosingClass;
      return hasConcreteMatch(enclosingClass.superclass, selector, world);
    }
    return selector.appliesUntyped(element, world);
  }

  bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld) {
    // A call on an empty type mask is either dead code, or a call on
    // `null`.
    if (isEmpty) return false;
    // A call on an exact mask for an abstract class is dead code.
    if (isExact && base.isAbstract) return false;
    // If the receiver is guaranteed to have a member that
    // matches what we're looking for, there's no need to
    // introduce a noSuchMethod handler. It will never be called.
    //
    // As an example, consider this class hierarchy:
    //
    //                   A    <-- noSuchMethod
    //                  / \
    //                 C   B  <-- foo
    //
    // If we know we're calling foo on an object of type B we
    // don't have to worry about the noSuchMethod method in A
    // because objects of type B implement foo. On the other hand,
    // if we end up calling foo on something of type C we have to
    // add a handler for it.

    // If the holders of all user-defined noSuchMethod
    // implementations that might be applicable to the receiver
    // type have a matching member for the current name and
    // selector, we avoid introducing a noSuchMethod handler.
    //
    // As an example, consider this class hierarchy:
    //
    //                       A    <-- foo
    //                      / \
    //   noSuchMethod -->  B   C  <-- bar
    //                     |   |
    //                     C   D  <-- noSuchMethod
    //
    // When calling foo on an object of type A, we know that the
    // implementations of noSuchMethod are in the classes B and D
    // that also (indirectly) implement foo, so we do not need a
    // handler for it.
    //
    // If we're calling bar on an object of type D, we don't need
    // the handler either because all objects of type D implement
    // bar through inheritance.
    //
    // If we're calling bar on an object of type A we do need the
    // handler because we may have to call B.noSuchMethod since B
    // does not implement bar.

    /// Returns `true` if [cls] is an instantiated class that does not have
    /// a concrete method matching [selector].
    bool needsNoSuchMethod(ClassElement cls) {
      // We can skip uninstantiated subclasses.
      // TODO(johnniwinther): Put filtering into the (Class)World.
      if (!classWorld.isInstantiated(cls)) {
        return false;
      }
      // We can just skip abstract classes because we know no
      // instance of them will be created at runtime, and
      // therefore there is no instance that will require
      // [noSuchMethod] handling.
      return !cls.isAbstract
          && !hasConcreteMatch(cls, selector, classWorld);
    }

    bool baseNeedsNoSuchMethod = needsNoSuchMethod(base);
    if (isExact || baseNeedsNoSuchMethod) {
      return baseNeedsNoSuchMethod;
    }

    Iterable<ClassElement> subclassesToCheck;
    if (isSubtype) {
      subclassesToCheck = classWorld.strictSubtypesOf(base);
    } else {
      assert(isSubclass);
      subclassesToCheck = classWorld.strictSubclassesOf(base);
    }

    return subclassesToCheck != null &&
           subclassesToCheck.any(needsNoSuchMethod);
  }

  Element locateSingleElement(Selector selector,
                              TypeMask mask,
                              Compiler compiler) {
    if (isEmpty) return null;
    Iterable<Element> targets =
        compiler.world.allFunctions.filter(selector, mask);
    if (targets.length != 1) return null;
    Element result = targets.first;
    ClassElement enclosing = result.enclosingClass;
    // We only return the found element if it is guaranteed to be
    // implemented on the exact receiver type. It could be found in a
    // subclass or in an inheritance-wise unrelated class in case of
    // subtype selectors.
    return (base.isSubclassOf(enclosing)) ? result : null;
  }

  bool operator ==(var other) {
    if (identical(this, other)) return true;
    if (other is !FlatTypeMask) return false;
    FlatTypeMask otherMask = other;
    return (flags == otherMask.flags) && (base == otherMask.base);
  }

  int get hashCode {
    return (base == null ? 0 : base.hashCode) + 31 * flags.hashCode;
  }

  String toString() {
    if (isEmpty) return isNullable ? '[null]' : '[empty]';
    StringBuffer buffer = new StringBuffer();
    if (isNullable) buffer.write('null|');
    if (isExact) buffer.write('exact=');
    if (isSubclass) buffer.write('subclass=');
    if (isSubtype) buffer.write('subtype=');
    buffer.write(base.name);
    return "[$buffer]";
  }

  static Set<ClassElement> commonContainedClasses(FlatTypeMask x,
                                                  FlatTypeMask y,
                                                  ClassWorld classWorld) {
    Iterable<ClassElement> xSubset = containedSubset(x, classWorld);
    if (xSubset == null) return null;
    Iterable<ClassElement> ySubset = containedSubset(y, classWorld);
    if (ySubset == null) return null;
    return xSubset.toSet().intersection(ySubset.toSet());
  }

  static Iterable<ClassElement> containedSubset(FlatTypeMask x,
                                                ClassWorld classWorld) {
    ClassElement element = x.base;
    if (x.isExact) {
      return null;
    } else if (x.isSubclass) {
      return classWorld.strictSubclassesOf(element);
    } else {
      assert(x.isSubtype);
      return classWorld.strictSubtypesOf(element);
    }
  }
}
