private static ARecordType generalizeRecordTypes(ARecordType leftType, ARecordType rightType) { boolean knowsAdditonalFieldNames = true; Set<String> allPossibleAdditionalFieldNames = new HashSet<>(); if (leftType.isOpen() && !leftType.knowsAllPossibleAdditonalFieldNames()) { knowsAdditonalFieldNames = false; } else if (leftType.isOpen()) { allPossibleAdditionalFieldNames.addAll(leftType.getAllPossibleAdditonalFieldNames()); } if (rightType.isOpen() && !rightType.knowsAllPossibleAdditonalFieldNames()) { knowsAdditonalFieldNames = false; } else if (rightType.isOpen()) { allPossibleAdditionalFieldNames.addAll(rightType.getAllPossibleAdditonalFieldNames()); } boolean canBeClosed = !leftType.isOpen() && !rightType.isOpen(); List<String> fieldNames = new ArrayList<>(); List<IAType> fieldTypes = new ArrayList<>(); boolean leftAllMatched = generalizeRecordFields(leftType, rightType, allPossibleAdditionalFieldNames, fieldNames, fieldTypes); boolean rightAllMatched = generalizeRecordFields(rightType, leftType, allPossibleAdditionalFieldNames, fieldNames, fieldTypes); return new ARecordType("generalized-record-type", fieldNames.toArray(new String[fieldNames.size()]), fieldTypes.toArray(new IAType[fieldTypes.size()]), !(canBeClosed && leftAllMatched && rightAllMatched), knowsAdditonalFieldNames ? allPossibleAdditionalFieldNames : null); }