Type::Type(const RuntimeType& rtt) : m_bits(bitsFromDataType(rtt.outerType(), rtt.innerType())) , m_hasConstVal(false) , m_class(nullptr) { if (rtt.outerType() == KindOfObject && rtt.hasKnownClass()) { m_class = rtt.knownClass(); } else if (rtt.outerType() == KindOfArray && rtt.hasArrayKind()) { m_arrayInfo = makeArrayInfo(rtt.arrayKind(), nullptr); } }
static folly::Optional<ArrayInfo> intersect(ArrayInfo a, ArrayInfo b) { assert(a != b); auto const aka = okind(a); auto const akb = okind(b); auto const ata = arrayType(a); auto const atb = arrayType(b); if (aka == akb) { // arrayType must be non-equal by above assertion. Since the // kinds are the same, as long as one is null we can keep the // other. assert(ata != atb); if (ata && atb) return makeArrayInfo(aka, nullptr); return makeArrayInfo(aka, ata ? ata : atb); } if (aka && akb) { assert(aka != akb); if (ata == atb) { return makeArrayInfo(folly::none, ata); } return folly::none; } assert(aka.hasValue() || akb.hasValue()); assert(!(aka.hasValue() && akb.hasValue())); if (akb && !aka) return intersect(b, a); assert(aka.hasValue() && !akb.hasValue()); if (!atb) return makeArrayInfo(aka, ata /* could be null */); if (!ata) return makeArrayInfo(aka, atb /* could be null */); return makeArrayInfo(aka, ata == atb ? ata : nullptr); }
static folly::Optional<ArrayInfo> commonAncestor(ArrayInfo a, ArrayInfo b) { if (a == b) return a; auto const sameKind = [&]() -> folly::Optional<ArrayData::ArrayKind> { if (arrayKindValid(a)) { if (arrayKindValid(b)) { if (a == b) return kind(a); return folly::none; } return kind(a); } if (arrayKindValid(b)) return kind(b); return folly::none; }(); auto const ty = [&]() -> const RepoAuthType::Array* { auto ata = arrayType(a); auto atb = arrayType(b); return ata && atb ? (ata == atb ? ata : nullptr) : ata ? ata : atb; }(); if (ty || sameKind) return makeArrayInfo(sameKind, ty); return folly::none; }