// 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 flatten 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.hasAnySubtype(base) || world.hasOnlySubclasses(base)) {
        flags = (flags & 0x1) | (SUBCLASS << 1);
      }
    }
    if (((flags >> 1) == SUBCLASS) && !world.hasAnySubclass(base)) {
      flags = (flags & 0x1) | (EXACT << 1);
    }
    return 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);
    }
  }

  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.lookupSelector(selector);
  }

  /**
   * 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,
                               World world) {
    assert(invariant(cls,
        world.compiler.resolverWorld.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.subtypesOf(base);
    } else {
      assert(isSubclass);
      subclassesToCheck = classWorld.subclassesOf(base);
    }

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

  Element locateSingleElement(Selector selector, Compiler compiler) {
    if (isEmpty) return null;
    Iterable<Element> targets = compiler.world.allFunctions.filter(selector);
    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 (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;
    Iterable<ClassElement> smallSet, largeSet;
    if (xSubset.length <= ySubset.length) {
      smallSet = xSubset;
      largeSet = ySubset;
    } else {
      smallSet = ySubset;
      largeSet = xSubset;
    }
    var result = smallSet.where((ClassElement each) => largeSet.contains(each));
    return result.toSet();
  }

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