Prevent pdfium::Contains() from falling back to linear search.

(Code taken from upstream chromium file)

Breaks compilation when a container supports find(), but not with
the particular type of key being passed to it. Otherwise, this
silently compiles but does not provide the performance expected
from the container.

-- fix instances where this was happening.

Change-Id: I47647a1708d1c3c782195aeaf2c31b0c3789a45f
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/98390
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index be8e867..f8f10ef 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -448,7 +448,7 @@
       nPagesToGo -= nPages;
       continue;
     }
-    if (pdfium::Contains(*pVisited, pKid))
+    if (pdfium::Contains(*pVisited, pKid.Get()))
       return false;
 
     ScopedSetInsertion<CPDF_Dictionary*> insertion(pVisited, pKid.Get());
diff --git a/core/fxge/win32/cfx_psfonttracker.h b/core/fxge/win32/cfx_psfonttracker.h
index 51a5bd7..e1bf212 100644
--- a/core/fxge/win32/cfx_psfonttracker.h
+++ b/core/fxge/win32/cfx_psfonttracker.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <functional>
 #include <set>
 
 #include "core/fxcrt/unowned_ptr.h"
@@ -28,7 +29,7 @@
 
   // For fonts without valid tags, e.g. ones created in-memory, track them by
   // pointer.
-  std::set<UnownedPtr<const CFX_Font>> seen_font_ptrs_;
+  std::set<UnownedPtr<const CFX_Font>, std::less<>> seen_font_ptrs_;
 };
 
 #endif  // CORE_FXGE_WIN32_CFX_PSFONTTRACKER_H_
diff --git a/third_party/base/containers/contains.h b/third_party/base/containers/contains.h
index fd2ca35..63a06ef 100644
--- a/third_party/base/containers/contains.h
+++ b/third_party/base/containers/contains.h
@@ -15,6 +15,14 @@
 
 namespace internal {
 
+// Small helper to detect whether a given type has a nested `key_type` typedef.
+// Used below to catch misuses of the API for associative containers.
+template <typename T, typename SFINAE = void>
+struct HasKeyType : std::false_type {};
+
+template <typename T>
+struct HasKeyType<T, std::void_t<typename T::key_type>> : std::true_type {};
+
 // Utility type traits used for specializing base::Contains() below.
 template <typename Container, typename Element, typename = void>
 struct HasFindWithNpos : std::false_type {};
@@ -59,6 +67,11 @@
               !internal::HasFindWithEnd<Container, Value>::value &&
               !internal::HasContains<Container, Value>::value>* = nullptr>
 bool Contains(const Container& container, const Value& value) {
+  static_assert(
+      !internal::HasKeyType<Container>::value,
+      "Error: About to perform linear search on an associative container. "
+      "Either use a more generic comparator (e.g. std::less<>) or, if a linear "
+      "search is desired, provide an explicit projection parameter.");
   using std::begin;
   using std::end;
   return std::find(begin(container), end(container), value) != end(container);