@Override
    public boolean equals(Object other) {
        if (typeStack.contains(this, other)) {
            return true;
        } else if (other instanceof UnionType) {
            Set<Type> types1 = types;
            Set<Type> types2 = ((UnionType) other).types;
            if (types1.size() != types2.size()) {
                return false;
            } else {
                typeStack.push(this, other);
                for (Type t : types2) {
                    if (!types1.contains(t)) {
                        typeStack.pop(this, other);
                        return false;
                    }
                }
                for (Type t : types1) {
                    if (!types2.contains(t)) {
                        typeStack.pop(this, other);
                        return false;
                    }
                }
                typeStack.pop(this, other);
                return true;
            }
        } else {
            return false;
        }
    }