Result join(Result r1, Result r2) {
    Result result = checkFinal(r1, r2);
    if (result != null) return result;
    result = checkFinal(r1, r2);
    if (result != null) return result;
    if (r1 instanceof Value && r2 instanceof Value) {
      return lattice.join((Value)r1, (Value)r2);
    }
    if (r1 instanceof Value && r2 instanceof Pending) {
      return addSingle((Pending)r2, (Value)r1);
    }
    if (r1 instanceof Pending && r2 instanceof Value) {
      return addSingle((Pending)r1, (Value)r2);
    }
    assert r1 instanceof Pending && r2 instanceof Pending;
    Pending pending1 = (Pending)r1;
    Pending pending2 = (Pending)r2;
    List<Component> left = Arrays.asList(pending1.delta);
    List<Component> right = Arrays.asList(pending2.delta);
    if (left.containsAll(right)) return pending1;
    if (right.containsAll(left)) return pending2;
    Set<Component> sum = new HashSet<>();
    sum.addAll(left);
    sum.addAll(right);
    return new Pending(DfaUtil.upwardsAntichain(sum, (l, r) -> r.isSuperStateOf(l)));
  }
Result join(Result r1, Result r2)