When printing CHECK_XX failures and both types are unprintable, don't bother printing " (UNPRINTABLE vs. UNPRINTABLE)".

PiperOrigin-RevId: 802287138
Change-Id: I8b4815fdc089427be9f276e10f9a72b398ed8f80
diff --git a/absl/log/check_test_impl.inc b/absl/log/check_test_impl.inc
index 7bcedd4..495f85a 100644
--- a/absl/log/check_test_impl.inc
+++ b/absl/log/check_test_impl.inc
@@ -292,8 +292,7 @@
   ExampleTypeThatHasNoStreamOperator a{true};
   ExampleTypeThatHasNoStreamOperator b{false};
   ABSL_TEST_CHECK_EQ(a, a);
-  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b),
-               "Check failed: a == b \\(UNPRINTABLE vs. UNPRINTABLE\\)");
+  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, b), "Check failed: a == b");
   ABSL_TEST_CHECK_EQ(a, true);
   EXPECT_DEATH(ABSL_TEST_CHECK_EQ(a, false),
                "Check failed: a == false \\(UNPRINTABLE vs. 0\\)");
diff --git a/absl/log/internal/check_op.cc b/absl/log/internal/check_op.cc
index 5db98dd..be8ceaf 100644
--- a/absl/log/internal/check_op.cc
+++ b/absl/log/internal/check_op.cc
@@ -101,7 +101,9 @@
   }
 }
 
-void MakeCheckOpUnprintableString(std::ostream& os) { os << "UNPRINTABLE"; }
+std::ostream& operator<<(std::ostream& os, UnprintableWrapper) {
+  return os << "UNPRINTABLE";
+}
 
 // Helper functions for string comparisons.
 #define DEFINE_CHECK_STROP_IMPL(name, func, expected)                          \
diff --git a/absl/log/internal/check_op.h b/absl/log/internal/check_op.h
index c607864..4d0842b 100644
--- a/absl/log/internal/check_op.h
+++ b/absl/log/internal/check_op.h
@@ -225,17 +225,12 @@
 void MakeCheckOpValueString(std::ostream& os, unsigned char v);
 void MakeCheckOpValueString(std::ostream& os, const void* absl_nullable p);
 
-void MakeCheckOpUnprintableString(std::ostream& os);
-
 // A wrapper for types that have no operator<<.
 struct UnprintableWrapper {
   template <typename T>
   explicit UnprintableWrapper(const T&) {}
 
-  friend std::ostream& operator<<(std::ostream& os, const UnprintableWrapper&) {
-    MakeCheckOpUnprintableString(os);
-    return os;
-  }
+  friend std::ostream& operator<<(std::ostream& os, UnprintableWrapper);
 };
 
 namespace detect_specialization {
@@ -400,10 +395,16 @@
 template <typename T1, typename T2>
 const char* absl_nonnull MakeCheckOpString(T1 v1, T2 v2,
                                            const char* absl_nonnull exprtext) {
-  CheckOpMessageBuilder comb(exprtext);
-  MakeCheckOpValueString(comb.ForVar1(), v1);
-  MakeCheckOpValueString(comb.ForVar2(), v2);
-  return comb.NewString();
+  if constexpr (std::is_same_v<CheckOpStreamType<T1>, UnprintableWrapper> &&
+                std::is_same_v<CheckOpStreamType<T2>, UnprintableWrapper>) {
+    // No sense printing " (UNPRINTABLE vs. UNPRINTABLE)"
+    return exprtext;
+  } else {
+    CheckOpMessageBuilder comb(exprtext);
+    MakeCheckOpValueString(comb.ForVar1(), v1);
+    MakeCheckOpValueString(comb.ForVar2(), v2);
+    return comb.NewString();
+  }
 }
 
 // Add a few commonly used instantiations as extern to reduce size of objects