UnionType implements InferredType { public static InferredType or(InferredType type1, InferredType type2) { if (type1.equals(anyType()) || type2.equals(anyType())) { return anyType(); } if (type1.equals(type2)) { return type1; } Set<InferredType> types = new HashSet<>(); addTypes(type1, types); addTypes(type2, types); return new UnionType(types); } private  UnionType(Set<InferredType> types); static InferredType or(InferredType type1, InferredType type2); @Override boolean isIdentityComparableWith(InferredType other); @Override boolean canHaveMember(String memberName); @Override boolean declaresMember(String memberName); @Override Optional<Symbol> resolveMember(String memberName); @Override Optional<Symbol> resolveDeclaredMember(String memberName); @Override boolean canOnlyBe(String typeName); @Override boolean canBeOrExtend(String typeName); @Override boolean isCompatibleWith(InferredType other); boolean mustBeOrExtend(String fullyQualifiedName); @Override boolean equals(Object o); @Override int hashCode(); @Override String toString();  }
@Test public void construction() { assertThat(or(anyType(), anyType())).isEqualTo(anyType()); assertThat(or(anyType(), a)).isEqualTo(anyType()); assertThat(or(a, anyType())).isEqualTo(anyType()); assertThat(or(a, a)).isEqualTo(a); assertThat(or(a, b)).isNotEqualTo(anyType()); assertThat(or(or(a, b), c)).isEqualTo(or(a, or(b, c))); }