Esempio n. 1
0
ClassSpec ClassSpec::operator&(const ClassSpec& rhs) const {
  auto const& lhs = *this;

  if (lhs <= rhs) return lhs;
  if (rhs <= lhs) return rhs;

  assertx(lhs.cls() && rhs.cls());

  // If neither class is an interface, their intersection is trivial.
  if (isNormalClass(lhs.cls()) && isNormalClass(rhs.cls())) {
    return Bottom;
  }

  // If either is an interface, we'd need to explore all implementing classes
  // in the program to know if they have a non-empty intersection.  Instead,
  // we'll just try to take the "better" of the two.  We consider a normal
  // class better than an interface, because it might influence important
  // things like method dispatch or property accesses better than an interface
  // type could.
  if (isNormalClass(lhs.cls())) return lhs;
  if (isNormalClass(rhs.cls())) return rhs;

  // If they are both interfaces, we have to pick one arbitrarily, but we must
  // do so in a way that is stable regardless of which one was passed as lhs or
  // rhs (to guarantee that operator& is commutative).  We use the class name
  // in this case to ensure that the ordering is dependent only on the source
  // program (Class* or something like that seems less desirable).
  return lhs.cls()->name()->compare(rhs.cls()->name()) < 0 ? lhs : rhs;
}
Esempio n. 2
0
  static folly::Optional<ClassInfo> commonAncestor(ClassInfo a,
                                                   ClassInfo b) {
    if (!isNormalClass(a.get()) || !isNormalClass(b.get())) return folly::none;
    if (auto result = a.get()->commonAncestor(b.get())) {
      return ClassInfo(result, ClassTag::Sub);
    }

    return folly::none;
  }
Esempio n. 3
0
ClassSpec ClassSpec::operator|(const ClassSpec& rhs) const {
  auto const& lhs = *this;

  if (lhs <= rhs) return rhs;
  if (rhs <= lhs) return lhs;

  assertx(lhs.cls() && rhs.cls());

  // We're unwilling to unify with interfaces, so just return Top.
  if (!isNormalClass(lhs.cls()) || !isNormalClass(rhs.cls())) {
    return Top;
  }

  // Unify to a common ancestor if possible.
  if (auto cls = lhs.cls()->commonAncestor(rhs.cls())) {
    return ClassSpec(cls, ClassSpec::SubTag{});
  }

  return Top;
}