Automated rollback of commit 5bbc6fc6aa2360149550ab009962523129c886fe.

PiperOrigin-RevId: 504594321
diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel
index b5860ac..cf72aaf 100644
--- a/src/google/protobuf/BUILD.bazel
+++ b/src/google/protobuf/BUILD.bazel
@@ -342,6 +342,7 @@
         "//src/google/protobuf/stubs:lite",
         "@com_google_absl//absl/container:btree",
         "@com_google_absl//absl/container:flat_hash_set",
+        "@com_google_absl//absl/hash",
         "@com_google_absl//absl/log:absl_check",
         "@com_google_absl//absl/log:absl_log",
         "@com_google_absl//absl/meta:type_traits",
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 0b335e9..e3bc9ec 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -46,17 +46,15 @@
 #include <type_traits>
 #include <utility>
 
-#if defined(__cpp_lib_string_view)
-#include <string_view>
-#endif  // defined(__cpp_lib_string_view)
-
 #if !defined(GOOGLE_PROTOBUF_NO_RDTSC) && defined(__APPLE__)
 #include <mach/mach_time.h>
 #endif
 
 #include "google/protobuf/stubs/common.h"
 #include "absl/container/btree_map.h"
+#include "absl/hash/hash.h"
 #include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
 #include "google/protobuf/arena.h"
 #include "google/protobuf/generated_enum_util.h"
 #include "google/protobuf/map_type_handler.h"
@@ -229,52 +227,69 @@
   using key_arg = key_type;
 };
 
-#if defined(__cpp_lib_string_view)
-// If std::string_view is available, we add transparent support for std::string
-// keys. We use std::hash<std::string_view> as it supports the input types we
-// care about. The lookup functions accept arbitrary `K`. This will include any
-// key type that is convertible to std::string_view.
+// We add transparent support for std::string keys. We use
+// std::hash<absl::string_view> as it supports the input types we care about.
+// The lookup functions accept arbitrary `K`. This will include any key type
+// that is convertible to absl::string_view.
 template <>
 struct TransparentSupport<std::string> {
-  static std::string_view ImplicitConvert(std::string_view str) { return str; }
-  // If the element is not convertible to std::string_view, try to convert to
-  // std::string first.
-  // The template makes this overload lose resolution when both have the same
-  // rank otherwise.
-  template <typename = void>
-  static std::string_view ImplicitConvert(const std::string& str) {
-    return str;
+  // If the element is not convertible to absl::string_view, try to convert to
+  // std::string first, and then fallback to support for converting from
+  // std::string_view. The ranked overload pattern is used to specify our
+  // order of preference.
+  struct Rank0 {};
+  struct Rank1 : Rank0 {};
+  struct Rank2 : Rank1 {};
+  template <typename T, typename = std::enable_if_t<
+                            std::is_convertible<T, absl::string_view>::value>>
+  static absl::string_view ImplicitConvertImpl(T&& str, Rank2) {
+    absl::string_view ref = str;
+    return ref;
+  }
+  template <typename T, typename = std::enable_if_t<
+                            std::is_convertible<T, const std::string&>::value>>
+  static absl::string_view ImplicitConvertImpl(T&& str, Rank1) {
+    const std::string& ref = str;
+    return ref;
+  }
+  template <typename T>
+  static absl::string_view ImplicitConvertImpl(T&& str, Rank0) {
+    return {str.data(), str.size()};
   }
 
-  struct hash : private std::hash<std::string_view> {
+  template <typename T>
+  static absl::string_view ImplicitConvert(T&& str) {
+    return ImplicitConvertImpl(std::forward<T>(str), Rank2{});
+  }
+
+  struct hash : public absl::Hash<absl::string_view> {
     using is_transparent = void;
 
     template <typename T>
-    size_t operator()(const T& str) const {
-      return base()(ImplicitConvert(str));
+    size_t operator()(T&& str) const {
+      return absl::Hash<absl::string_view>::operator()(
+          ImplicitConvert(std::forward<T>(str)));
     }
-
-   private:
-    const std::hash<std::string_view>& base() const { return *this; }
   };
   struct less {
     using is_transparent = void;
 
     template <typename T, typename U>
-    bool operator()(const T& t, const U& u) const {
-      return ImplicitConvert(t) < ImplicitConvert(u);
+    bool operator()(T&& t, U&& u) const {
+      return ImplicitConvert(std::forward<T>(t)) <
+             ImplicitConvert(std::forward<U>(u));
     }
   };
 
   template <typename T, typename U>
-  static bool Equals(const T& t, const U& u) {
-    return ImplicitConvert(t) == ImplicitConvert(u);
+  static bool Equals(T&& t, U&& u) {
+    return ImplicitConvert(std::forward<T>(t)) ==
+           ImplicitConvert(std::forward<U>(u));
   }
 
   template <typename K>
   using key_arg = K;
 };
-#endif  // defined(__cpp_lib_string_view)
 
 struct NodeBase {
   // Align the node to allow KeyNode to predict the location of the key.
diff --git a/src/google/protobuf/map_test.inc b/src/google/protobuf/map_test.inc
index 98c297f..89f8033 100644
--- a/src/google/protobuf/map_test.inc
+++ b/src/google/protobuf/map_test.inc
@@ -1406,12 +1406,32 @@
   EXPECT_THAT(m, UnorderedElementsAre(Pair("ABC", 1), Pair("DEF", 2)));
 }
 
+// Emulate a non-Abseil string_view (e.g. STL when Abseil's alias is disabled).
+class CustomStringView {
+  public:
+    CustomStringView(absl::string_view str) : str_(std::string(str)) {}
+
+    const char* data() const { return str_.data(); }
+    size_t size() const { return str_.size(); }
+
+    bool operator==(const CustomStringView& other) const {
+      return other.str_ == str_;
+    }
+    bool operator==(absl::string_view other) const { return other == str_; }
+    explicit operator std::string() const { return str_; }
+    friend std::ostream& operator<<(std::ostream& out, const CustomStringView& view) {
+      return out << view.str_;
+    }
+
+  private:
+    std::string str_;
+};
+
 TEST_F(MapImplTest, TransparentLookupForString) {
   TestTransparent("ABC", "LKJ");
   TestTransparent(std::string("ABC"), std::string("LKJ"));
-#if defined(__cpp_lib_string_view)
-  TestTransparent(std::string_view("ABC"), std::string_view("LKJ"));
-#endif  // defined(__cpp_lib_string_view)
+  TestTransparent(absl::string_view("ABC"), absl::string_view("LKJ"));
+  TestTransparent(CustomStringView("ABC"), CustomStringView("LKJ"));
 
   // std::reference_wrapper
   std::string abc = "ABC", lkj = "LKJ";