private static @NotNull <T> String recomputeWithLogging(@Nullable T existing,
                                                          @Nullable T fresh,
                                                          @NotNull Computable<? extends T> recomputeValue) {
    ResultWithLog<T> rwl = computeWithLogging(recomputeValue);
    T freshest = rwl.result;
    @NonNls String msg = "\n\nRecomputation gives " + objAndClass(freshest);
    if (checkValueEquivalence(existing, freshest) == null) {
      msg += " which is equivalent to 'existing'";
    }
    else if (checkValueEquivalence(fresh, freshest) == null) {
      msg += " which is equivalent to 'fresh'";
    }
    else {
      msg += " which is different from both values";
    }
    if (!rwl.log.isEmpty() && !(freshest instanceof ResultWithLog)) {
      msg += "\nRecomputation log:\n" + rwl.printLog();
    }
    return msg;
  }
private static @NotNull <T> String recomputeWithLogging(@Nullable T existing,
                                                          @Nullable T fresh,
                                                          @NotNull Computable<? extends T> recomputeValue)