static ObjectType join(ObjectType obj1, ObjectType obj2) { if (obj1 == TOP_OBJECT || obj2 == TOP_OBJECT) { return TOP_OBJECT; } NominalType nom1 = obj1.nominalType; NominalType nom2 = obj2.nominalType; Preconditions.checkState(areRelatedClasses(nom1, nom2)); if (obj1.equals(obj2)) { return obj1; } boolean isLoose = obj1.isLoose || obj2.isLoose; FunctionType fn = FunctionType.join(obj1.fn, obj2.fn); PersistentMap<String, Property> props; if (isLoose) { fn = fn == null ? null : fn.withLoose(); props = joinPropsLoosely(obj1.props, obj2.props); } else { props = joinProps(obj1.props, obj2.props, nom1, nom2); } NominalType nominal = NominalType.pickSuperclass(nom1, nom2); // TODO(blickly): Split TOP_OBJECT from empty object and remove this case if (nominal == null || !nominal.isFunction()) { fn = null; } return ObjectType.makeObjectType( nominal, props, fn, isLoose, ObjectKind.join(obj1.objectKind, obj2.objectKind)); }