static ObjectType meet(ObjectType obj1, ObjectType obj2) { Preconditions.checkState(areRelatedClasses(obj1.nominalType, obj2.nominalType)); if (obj1 == TOP_OBJECT) { return obj2; } else if (obj2 == TOP_OBJECT) { return obj1; } NominalType resultNomType = NominalType.pickSubclass(obj1.nominalType, obj2.nominalType); FunctionType fn = FunctionType.meet(obj1.fn, obj2.fn); if (!FunctionType.isInhabitable(fn)) { return BOTTOM_OBJECT; } boolean isLoose = obj1.isLoose && obj2.isLoose || fn != null && fn.isLoose(); if (resultNomType != null && resultNomType.isFunction() && fn == null) { fn = obj1.fn == null ? obj2.fn : obj1.fn; isLoose = fn.isLoose(); } PersistentMap<String, Property> props; if (isLoose) { props = joinPropsLoosely(obj1.props, obj2.props); } else { props = meetPropsHelper(false, resultNomType, obj1.props, obj2.props); } if (props == BOTTOM_MAP) { return BOTTOM_OBJECT; } ObjectKind ok = ObjectKind.meet(obj1.objectKind, obj2.objectKind); return new ObjectType(resultNomType, props, fn, isLoose, ok); }
public FunctionType getFunType() { if (objs == null) { return null; } if (objs.size() == 1) { // The common case is fast return Iterables.getOnlyElement(objs).getFunType(); } FunctionType result = FunctionType.TOP_FUNCTION; for (ObjectType obj : objs) { result = FunctionType.meet(result, obj.getFunType()); } return result; }