diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index 842c6b3..f7d6b56 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -367,6 +367,7 @@
   "strings/internal/string_constant.h"
   "strings/internal/stringify_sink.cc"
   "strings/internal/stringify_sink.h"
+  "strings/internal/stringify_stream.h"
   "strings/internal/utf8.cc"
   "strings/internal/utf8.h"
   "strings/match.cc"
@@ -450,10 +451,13 @@
   "time/time.cc"
   "time/time.h"
   "types/any.h"
+  "types/any_span.h"
   "types/compare.h"
+  "types/internal/any_span.h"
   "types/internal/span.h"
   "types/optional.h"
   "types/optional_ref.h"
+  "types/source_location.cc"
   "types/source_location.h"
   "types/span.h"
   "types/variant.h"
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index c0b8a10..3636f8e 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -197,8 +197,8 @@
 // Container-based version of the <algorithm> `std::for_each()` function to
 // apply a function to a container's elements.
 template <typename C, typename Function>
-ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<Function> c_for_each(C&& c,
-                                                                 Function&& f) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 std::decay_t<Function> c_for_each(
+    C&& c, Function&& f) {
   return std::for_each(container_algorithm_internal::c_begin(c),
                        container_algorithm_internal::c_end(c),
                        std::forward<Function>(f));
@@ -1758,10 +1758,10 @@
 // accumulation by value.
 //
 // Note: Due to a language technicality this function has return type
-// absl::decay_t<T>. As a user of this function you can casually read
+// std::decay_t<T>. As a user of this function you can casually read
 // this as "returns T by value" and assume it does the right thing.
 template <typename Sequence, typename T>
-ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<T> c_accumulate(
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 std::decay_t<T> c_accumulate(
     const Sequence& sequence, T&& init) {
   return std::accumulate(container_algorithm_internal::c_begin(sequence),
                          container_algorithm_internal::c_end(sequence),
@@ -1771,7 +1771,7 @@
 // Overload of c_accumulate() for using a binary operations other than
 // addition for computing the accumulation.
 template <typename Sequence, typename T, typename BinaryOp>
-ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<T> c_accumulate(
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 std::decay_t<T> c_accumulate(
     const Sequence& sequence, T&& init, BinaryOp&& binary_op) {
   return std::accumulate(container_algorithm_internal::c_begin(sequence),
                          container_algorithm_internal::c_end(sequence),
@@ -1785,10 +1785,10 @@
 // to compute the cumulative inner product of container element pairs.
 //
 // Note: Due to a language technicality this function has return type
-// absl::decay_t<T>. As a user of this function you can casually read
+// std::decay_t<T>. As a user of this function you can casually read
 // this as "returns T by value" and assume it does the right thing.
 template <typename Sequence1, typename Sequence2, typename T>
-ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<T> c_inner_product(
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 std::decay_t<T> c_inner_product(
     const Sequence1& factors1, const Sequence2& factors2, T&& sum) {
   return std::inner_product(container_algorithm_internal::c_begin(factors1),
                             container_algorithm_internal::c_end(factors1),
@@ -1801,7 +1801,7 @@
 // the product between the two container's element pair).
 template <typename Sequence1, typename Sequence2, typename T,
           typename BinaryOp1, typename BinaryOp2>
-ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<T> c_inner_product(
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 std::decay_t<T> c_inner_product(
     const Sequence1& factors1, const Sequence2& factors2, T&& sum,
     BinaryOp1&& op1, BinaryOp2&& op2) {
   return std::inner_product(container_algorithm_internal::c_begin(factors1),
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index c6e4be6..a0e71ed 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -1011,6 +1011,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = [
         "//absl:__subpackages__",
+        "//absl:friends",
     ],
     deps = [
         ":config",
@@ -1040,6 +1041,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = [
         "//absl:__subpackages__",
+        "//absl:friends",
     ],
     deps = [
         "//absl/base:config",
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index 91e552f..327b222 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -531,6 +531,24 @@
 #define ABSL_XRAY_LOG_ARGS(N)
 #endif
 
+// ABSL_ATTRIBUTE_NULL_AFTER_MOVE
+//
+// Indicates that a user-defined smart-pointer-like type makes guarantees on the
+// state of a moved-from object, leaving it in a null state, where it can be
+// used as long as it is not dereferenced. In other words, these are the same
+// semantics that smart pointers from the standard library provide.
+//
+// The clang-tidy check bugprone-use-after-move allows member functions of types
+// marked with this attribute to be called on objects that have been moved from;
+// without the attribute, this would result in a use-after-move warning.
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+#define ABSL_ATTRIBUTE_NULL_AFTER_MOVE                       \
+  [[clang::annotate("clang-tidy", "bugprone-use-after-move", \
+                    "null_after_move")]]
+#else
+#define ABSL_ATTRIBUTE_NULL_AFTER_MOVE
+#endif
+
 // ABSL_ATTRIBUTE_REINITIALIZES
 //
 // Indicates that a member function reinitializes the entire object to a known
diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc
index 55a6fe1..fc7e33e 100644
--- a/absl/base/exception_safety_testing_test.cc
+++ b/absl/base/exception_safety_testing_test.cc
@@ -945,8 +945,8 @@
 }
 
 TEST(ThrowingAllocatorTraitsTest, Assignablility) {
-  EXPECT_TRUE(absl::is_move_assignable<ThrowingAllocator<int>>::value);
-  EXPECT_TRUE(absl::is_copy_assignable<ThrowingAllocator<int>>::value);
+  EXPECT_TRUE(std::is_move_assignable<ThrowingAllocator<int>>::value);
+  EXPECT_TRUE(std::is_copy_assignable<ThrowingAllocator<int>>::value);
   EXPECT_TRUE(std::is_nothrow_move_assignable<ThrowingAllocator<int>>::value);
   EXPECT_TRUE(std::is_nothrow_copy_assignable<ThrowingAllocator<int>>::value);
 }
diff --git a/absl/base/internal/exception_safety_testing.h b/absl/base/internal/exception_safety_testing.h
index c106154..29f934f 100644
--- a/absl/base/internal/exception_safety_testing.h
+++ b/absl/base/internal/exception_safety_testing.h
@@ -14,6 +14,8 @@
 
 // Utilities for testing exception-safety
 
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
 #ifndef ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
 #define ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
 
@@ -38,28 +40,29 @@
 #include "absl/strings/substitute.h"
 #include "absl/utility/utility.h"
 
+// TODO(b/500018833): Update the namespace as appropriate.
 namespace testing {
 
 enum class TypeSpec;
 enum class AllocSpec;
 
 constexpr TypeSpec operator|(TypeSpec a, TypeSpec b) {
-  using T = absl::underlying_type_t<TypeSpec>;
+  using T = std::underlying_type_t<TypeSpec>;
   return static_cast<TypeSpec>(static_cast<T>(a) | static_cast<T>(b));
 }
 
 constexpr TypeSpec operator&(TypeSpec a, TypeSpec b) {
-  using T = absl::underlying_type_t<TypeSpec>;
+  using T = std::underlying_type_t<TypeSpec>;
   return static_cast<TypeSpec>(static_cast<T>(a) & static_cast<T>(b));
 }
 
 constexpr AllocSpec operator|(AllocSpec a, AllocSpec b) {
-  using T = absl::underlying_type_t<AllocSpec>;
+  using T = std::underlying_type_t<AllocSpec>;
   return static_cast<AllocSpec>(static_cast<T>(a) | static_cast<T>(b));
 }
 
 constexpr AllocSpec operator&(AllocSpec a, AllocSpec b) {
-  using T = absl::underlying_type_t<AllocSpec>;
+  using T = std::underlying_type_t<AllocSpec>;
   return static_cast<AllocSpec>(static_cast<T>(a) & static_cast<T>(b));
 }
 
@@ -842,7 +845,7 @@
 
 template <size_t LazyContractsCount, typename LazyFactory,
           typename LazyOperation>
-using EnableIfTestable = typename absl::enable_if_t<
+using EnableIfTestable = typename std::enable_if_t<
     LazyContractsCount != 0 &&
     !std::is_same<LazyFactory, UninitializedT>::value &&
     !std::is_same<LazyOperation, UninitializedT>::value>;
@@ -994,7 +997,7 @@
    * method tester.WithInitialValue(...).
    */
   template <typename NewFactory>
-  ExceptionSafetyTestBuilder<absl::decay_t<NewFactory>, Operation, Contracts...>
+  ExceptionSafetyTestBuilder<std::decay_t<NewFactory>, Operation, Contracts...>
   WithFactory(const NewFactory& new_factory) const {
     return {new_factory, operation_, contracts_};
   }
@@ -1005,7 +1008,7 @@
    * newly created tester.
    */
   template <typename NewOperation>
-  ExceptionSafetyTestBuilder<Factory, absl::decay_t<NewOperation>, Contracts...>
+  ExceptionSafetyTestBuilder<Factory, std::decay_t<NewOperation>, Contracts...>
   WithOperation(const NewOperation& new_operation) const {
     return {factory_, new_operation, contracts_};
   }
@@ -1025,11 +1028,11 @@
    */
   template <typename... MoreContracts>
   ExceptionSafetyTestBuilder<Factory, Operation, Contracts...,
-                             absl::decay_t<MoreContracts>...>
+                             std::decay_t<MoreContracts>...>
   WithContracts(const MoreContracts&... more_contracts) const {
     return {
         factory_, operation_,
-        std::tuple_cat(contracts_, std::tuple<absl::decay_t<MoreContracts>...>(
+        std::tuple_cat(contracts_, std::tuple<std::decay_t<MoreContracts>...>(
                                        more_contracts...))};
   }
 
diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h
index 9baccc0..bba27ef 100644
--- a/absl/base/internal/low_level_scheduling.h
+++ b/absl/base/internal/low_level_scheduling.h
@@ -18,8 +18,11 @@
 #ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
 #define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
 
+#include <atomic>
+
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/scheduling_mode.h"
+#include "absl/base/internal/thread_identity.h"
 #include "absl/base/macros.h"
 
 // The following two declarations exist so SchedulingGuard may friend them with
@@ -64,7 +67,6 @@
   SchedulingGuard(const SchedulingGuard&) = delete;
   SchedulingGuard& operator=(const SchedulingGuard&) = delete;
 
- private:
   // Disable cooperative rescheduling of the calling thread.  It may still
   // initiate scheduling operations (e.g. wake-ups), however, it may not itself
   // reschedule.  Nestable.  The returned result is opaque, clients should not
@@ -96,13 +98,6 @@
    private:
     int scheduling_disabled_depth_;
   };
-
-  // Access to SchedulingGuard is explicitly permitted.
-  friend class absl::CondVar;
-  friend class absl::Mutex;
-  friend class SchedulingHelper;
-  friend class SpinLock;
-  friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode);
 };
 
 //------------------------------------------------------------------------------
@@ -110,21 +105,88 @@
 //------------------------------------------------------------------------------
 
 inline bool SchedulingGuard::ReschedulingIsAllowed() {
-  return false;
+  ThreadIdentity* identity = CurrentThreadIdentityIfPresent();
+  if (identity != nullptr) {
+    ThreadIdentity::SchedulerState* state = &identity->scheduler_state;
+    // For a thread to be eligible for re-scheduling it must have a bound
+    // schedulable (otherwise it's not cooperative) and not be within a
+    // SchedulerGuard region.
+    return state->bound_schedulable.load(std::memory_order_relaxed) !=
+               nullptr &&
+           state->scheduling_disabled_depth.load(std::memory_order_relaxed) ==
+               0;
+  } else {
+    // Cooperative threads always have a ThreadIdentity.
+    return false;
+  }
 }
 
+// We don't use [[nodiscard]] here as some clients (e.g.
+// FinishPotentiallyBlockingRegion()) cannot yet properly consume it.
 inline bool SchedulingGuard::DisableRescheduling() {
-  return false;
+  ThreadIdentity* identity;
+  identity = CurrentThreadIdentityIfPresent();
+  if (identity != nullptr) {
+    // The depth is accessed concurrently from other threads, so it must be
+    // atomic, but it's only mutated from this thread, so we don't need an
+    // atomic increment.
+    int old_val = identity->scheduler_state.scheduling_disabled_depth.load(
+        std::memory_order_relaxed);
+    identity->scheduler_state.scheduling_disabled_depth.store(
+        old_val + 1, std::memory_order_relaxed);
+    return true;
+  } else {
+    return false;
+  }
 }
 
-inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) {
-  return;
+inline void SchedulingGuard::EnableRescheduling(bool disable_result) {
+  if (!disable_result) {
+    // There was no installed thread identity at the time that scheduling was
+    // disabled, so we have nothing to do.  This is an implementation detail
+    // that may change in the future, clients may not depend on it.
+    // EnableRescheduling() must always be called.
+    return;
+  }
+
+  ThreadIdentity* identity;
+  // A thread identity exists, see above
+  identity = CurrentThreadIdentityIfPresent();
+  // The depth is accessed concurrently from other threads, so it must be
+  // atomic, but it's only mutated from this thread, so we don't need an atomic
+  // decrement.
+  int old_val = identity->scheduler_state.scheduling_disabled_depth.load(
+      std::memory_order_relaxed);
+  identity->scheduler_state.scheduling_disabled_depth.store(
+      old_val - 1, std::memory_order_relaxed);
 }
 
-inline SchedulingGuard::ScopedEnable::ScopedEnable()
-    : scheduling_disabled_depth_(0) {}
+inline SchedulingGuard::ScopedEnable::ScopedEnable() {
+  ThreadIdentity* identity;
+  identity = CurrentThreadIdentityIfPresent();
+  if (identity != nullptr) {
+    scheduling_disabled_depth_ =
+        identity->scheduler_state.scheduling_disabled_depth.load(
+            std::memory_order_relaxed);
+    if (scheduling_disabled_depth_ != 0) {
+      // The store below does not need to be compare_exchange because
+      // the value is never modified concurrently (only accessed).
+      identity->scheduler_state.scheduling_disabled_depth.store(
+          0, std::memory_order_relaxed);
+    }
+  } else {
+    scheduling_disabled_depth_ = 0;
+  }
+}
+
 inline SchedulingGuard::ScopedEnable::~ScopedEnable() {
-  ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning");
+  if (scheduling_disabled_depth_ == 0) {
+    return;
+  }
+  ThreadIdentity* identity = CurrentThreadIdentityIfPresent();
+  // itentity is guaranteed to exist, see the constructor above.
+  identity->scheduler_state.scheduling_disabled_depth.store(
+      scheduling_disabled_depth_, std::memory_order_relaxed);
 }
 
 }  // namespace base_internal
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index acfc15a..0c2d619 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -146,6 +146,54 @@
   // ThreadIdentity itself.
   PerThreadSynch per_thread_synch;
 
+  struct SchedulerState {
+    std::atomic<void*> bound_schedulable{nullptr};
+    // Storage space for a SpinLock, which is created through a placement new to
+    // break a dependency cycle.
+    uint32_t association_lock_word;
+    std::atomic<int> scheduling_disabled_depth;
+    int potentially_blocking_depth;
+    uint32_t schedule_next_state;
+
+    // When true, current thread is unlocking a mutex and actively waking a
+    // thread that was previously waiting, but that lock has yet more waiters.
+    // Used to signal to schedulers that work being woken should get an
+    // elevated priority.
+    bool waking_designated_waker;
+
+    inline SpinLock* association_lock() {
+      return reinterpret_cast<SpinLock*>(&association_lock_word);
+    }
+  } scheduler_state;  // Private: Reserved for use in Gloop
+
+  // For worker threads that may not be doing any interesting user work, this
+  // tracks the current state of the worker. This is used to handle those
+  // threads differently e.g. when printing stacktraces.
+  //
+  // It should only be written to by the thread itself.
+  //
+  // Note that this is different from the mutex idle bit - threads running user
+  // work can be waiting but still be active.
+  //
+  // Note: not all parts of the code-base may maintain this field correctly and
+  // therefore this field should only be used to improve debugging/monitoring.
+  //
+  // Put it here to reuse some of the padding space.
+  enum class WaitState : uint8_t {
+    kActive = 0,
+    kWaitingForWork = 1,
+  };
+  std::atomic<WaitState> wait_state;
+  static_assert(std::atomic<WaitState>::is_always_lock_free);
+
+  // Add a padding such that scheduler_state is on a different cache line than
+  // waiter state.  We use padding here, so that the size of the structure does
+  // not substantially grow due to the added padding.
+  static constexpr size_t kToBePaddedSize =
+      sizeof(SchedulerState) + sizeof(std::atomic<WaitState>);
+  static_assert(ABSL_CACHELINE_SIZE >= kToBePaddedSize);
+  char padding[ABSL_CACHELINE_SIZE - kToBePaddedSize];
+
   // Private: Reserved for absl::synchronization_internal::Waiter.
   struct WaiterState {
     alignas(void*) char data[256];
@@ -161,6 +209,10 @@
   std::atomic<int> wait_start;  // Ticker value when thread started waiting.
   std::atomic<bool> is_idle;    // Has thread become idle yet?
 
+  // For tracking depth of __cxa_guard_acquire.  This used to recognize heap
+  // allocations for function static objects.
+  int static_initialization_depth;
+
   ThreadIdentity* next;
 };
 
diff --git a/absl/base/macros.h b/absl/base/macros.h
index 446a445..d42ecf1 100644
--- a/absl/base/macros.h
+++ b/absl/base/macros.h
@@ -108,18 +108,15 @@
 #else
 #define ABSL_ASSERT(expr)                           \
   (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
-                             : [] { assert(false && #expr); }())  // NOLINT
+                             : assert(false && #expr))  // NOLINT
 #endif
 
 // `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()`
 // aborts the program in release mode (when NDEBUG is defined). The
 // implementation should abort the program as quickly as possible and ideally it
 // should not be possible to ignore the abort request.
-#define ABSL_INTERNAL_HARDENING_ABORT()   \
-  do {                                    \
-    ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
-    ABSL_INTERNAL_UNREACHABLE_IMPL();     \
-  } while (false)
+#define ABSL_INTERNAL_HARDENING_ABORT() \
+  ((void)ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(), ABSL_INTERNAL_UNREACHABLE_IMPL())
 
 // ABSL_HARDENING_ASSERT()
 //
@@ -135,7 +132,7 @@
 #if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)
 #define ABSL_HARDENING_ASSERT(expr)                 \
   (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
-                             : [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
+                             : ABSL_INTERNAL_HARDENING_ABORT())
 #else
 #define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr)
 #endif
@@ -154,7 +151,7 @@
 #if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
 #define ABSL_HARDENING_ASSERT_SLOW(expr)            \
   (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
-                             : [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
+                             : ABSL_INTERNAL_HARDENING_ABORT())
 #else
 #define ABSL_HARDENING_ASSERT_SLOW(expr) ABSL_ASSERT(expr)
 #endif
diff --git a/absl/base/optimization.h b/absl/base/optimization.h
index b561128..1fd32c5 100644
--- a/absl/base/optimization.h
+++ b/absl/base/optimization.h
@@ -217,7 +217,7 @@
 #elif defined(_MSC_VER)
 #define ABSL_INTERNAL_UNREACHABLE_IMPL() __assume(false)
 #else
-#define ABSL_INTERNAL_UNREACHABLE_IMPL()
+#define ABSL_INTERNAL_UNREACHABLE_IMPL() ((void)0)
 #endif
 
 // `ABSL_UNREACHABLE()` is an unreachable statement.  A program which reaches
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index c51a19f..e6f1528 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -96,7 +96,7 @@
            absl::allocator_is_nothrow<allocator_type>::value;
   }
   static constexpr bool DefaultConstructorIsNonTrivial() {
-    return !absl::is_trivially_default_constructible<StorageElement>::value;
+    return !std::is_trivially_default_constructible<StorageElement>::value;
   }
 
  public:
@@ -414,14 +414,14 @@
   //     error: call to int __builtin___sprintf_chk(etc...)
   //     will always overflow destination buffer [-Werror]
   //
-  template <typename OuterT, typename InnerT = absl::remove_extent_t<OuterT>,
+  template <typename OuterT, typename InnerT = std::remove_extent_t<OuterT>,
             size_t InnerN = std::extent<OuterT>::value>
   struct StorageElementWrapper {
     InnerT array[InnerN];
   };
 
   using StorageElement =
-      absl::conditional_t<std::is_array<value_type>::value,
+      std::conditional_t<std::is_array<value_type>::value,
                           StorageElementWrapper<value_type>, value_type>;
 
   static pointer AsValueType(pointer ptr) { return ptr; }
@@ -458,7 +458,7 @@
   };
 
   using InlinedStorage =
-      absl::conditional_t<inline_elements == 0, EmptyInlinedStorage,
+      std::conditional_t<inline_elements == 0, EmptyInlinedStorage,
                           NonEmptyInlinedStorage>;
 
   // Storage
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index 1677f6a..e6cea2e 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -614,22 +614,22 @@
 // Erasure and/or insertion of elements in the function is not allowed.
 template <typename K, typename V, typename H, typename E, typename A,
           typename Function>
-decay_t<Function> c_for_each_fast(const flat_hash_map<K, V, H, E, A>& c,
-                                  Function&& f) {
+std::decay_t<Function> c_for_each_fast(const flat_hash_map<K, V, H, E, A>& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
 template <typename K, typename V, typename H, typename E, typename A,
           typename Function>
-decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>& c,
-                                  Function&& f) {
+std::decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
 template <typename K, typename V, typename H, typename E, typename A,
           typename Function>
-decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>&& c,
-                                  Function&& f) {
+std::decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>&& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index f802057..44af56a 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -517,18 +517,20 @@
 // There is no guarantees on the order of the function calls.
 // Erasure and/or insertion of elements in the function is not allowed.
 template <typename T, typename H, typename E, typename A, typename Function>
-decay_t<Function> c_for_each_fast(const flat_hash_set<T, H, E, A>& c,
-                                  Function&& f) {
+std::decay_t<Function> c_for_each_fast(const flat_hash_set<T, H, E, A>& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
 template <typename T, typename H, typename E, typename A, typename Function>
-decay_t<Function> c_for_each_fast(flat_hash_set<T, H, E, A>& c, Function&& f) {
+std::decay_t<Function> c_for_each_fast(flat_hash_set<T, H, E, A>& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
 template <typename T, typename H, typename E, typename A, typename Function>
-decay_t<Function> c_for_each_fast(flat_hash_set<T, H, E, A>&& c, Function&& f) {
+std::decay_t<Function> c_for_each_fast(flat_hash_set<T, H, E, A>&& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index a9c2526..c1b5785 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -192,7 +192,7 @@
     // allocator doesn't do anything fancy, and there is nothing on the heap
     // then we know it is legal for us to simply memcpy the other vector's
     // inlined bytes to form our copy of its elements.
-    if (absl::is_trivially_copy_constructible<value_type>::value &&
+    if (std::is_trivially_copy_constructible<value_type>::value &&
         std::is_same<A, std::allocator<value_type>>::value &&
         !other.storage_.GetIsAllocated()) {
       storage_.MemcpyFrom(other.storage_);
@@ -857,7 +857,7 @@
     // Assumption check: we shouldn't be told to use memcpy to implement move
     // assignment unless we have trivially destructible elements and an
     // allocator that does nothing fancy.
-    static_assert(absl::is_trivially_destructible<value_type>::value, "");
+    static_assert(std::is_trivially_destructible<value_type>::value, "");
     static_assert(std::is_same<A, std::allocator<value_type>>::value, "");
 
     // Throw away our existing heap allocation, if any. There is no need to
diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h
index ed541e7..0fc77f8 100644
--- a/absl/container/internal/btree.h
+++ b/absl/container/internal/btree.h
@@ -231,7 +231,7 @@
     explicit operator Compare() const { return comp(); }
 
     template <typename T, typename U,
-              absl::enable_if_t<
+              std::enable_if_t<
                   std::is_same<bool, compare_result_t<Compare, T, U>>::value,
                   int> = 0>
     bool operator()(const T &lhs, const U &rhs) const {
@@ -247,7 +247,7 @@
 
     template <
         typename T, typename U,
-        absl::enable_if_t<std::is_convertible<compare_result_t<Compare, T, U>,
+        std::enable_if_t<std::is_convertible<compare_result_t<Compare, T, U>,
                                               absl::weak_ordering>::value,
                           int> = 0>
     absl::weak_ordering operator()(const T &lhs, const U &rhs) const {
@@ -270,7 +270,7 @@
       return lhs_comp_rhs;
     }
   };
-  using type = absl::conditional_t<
+  using type = std::conditional_t<
       std::is_base_of<BtreeTestOnlyCheckedCompareOptOutBase, Compare>::value,
       Compare, checked_compare>;
 };
@@ -377,7 +377,7 @@
   // this, then there will be cascading compilation failures that are confusing
   // for users.
   using key_compare =
-      absl::conditional_t<!compare_has_valid_result_type<Compare, Key>(),
+      std::conditional_t<!compare_has_valid_result_type<Compare, Key>(),
                           Compare,
                           typename key_compare_adapter<Compare, Key>::type>;
 
@@ -406,7 +406,7 @@
   using const_reference = const value_type &;
 
   using value_compare =
-      absl::conditional_t<IsMap,
+      std::conditional_t<IsMap,
                           map_value_compare<original_key_compare, value_type>,
                           original_key_compare>;
   using is_map_container = std::integral_constant<bool, IsMap>;
@@ -438,7 +438,7 @@
   // This is an integral type large enough to hold as many slots as will fit a
   // node of TargetNodeSize bytes.
   using node_count_type =
-      absl::conditional_t<(kNodeSlotSpace / sizeof(slot_type) >
+      std::conditional_t<(kNodeSlotSpace / sizeof(slot_type) >
                            (std::numeric_limits<uint8_t>::max)()),
                           uint16_t, uint8_t>;  // NOLINT
 };
@@ -1119,7 +1119,7 @@
   using slot_type = typename params_type::slot_type;
 
   // In sets, all iterators are const.
-  using iterator = absl::conditional_t<
+  using iterator = std::conditional_t<
       is_map_container::value,
       btree_iterator<normal_node, normal_reference, normal_pointer>,
       btree_iterator<normal_node, const_reference, const_pointer>>;
@@ -1146,7 +1146,7 @@
   // const_iterator, but it specifically avoids hiding the copy constructor so
   // that the trivial one will be used when possible.
   template <typename N, typename R, typename P,
-            absl::enable_if_t<
+            std::enable_if_t<
                 std::is_same<btree_iterator<N, R, P>, iterator>::value &&
                     std::is_same<btree_iterator, const_iterator>::value,
                 int> = 0>
@@ -1252,7 +1252,7 @@
   // NOTE: the const_cast is safe because this constructor is only called by
   // non-const methods and the container owns the nodes.
   template <typename N, typename R, typename P,
-            absl::enable_if_t<
+            std::enable_if_t<
                 std::is_same<btree_iterator<N, R, P>, const_iterator>::value &&
                     std::is_same<btree_iterator, iterator>::value,
                 int> = 0>
diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h
index 0ccf9d0..c11620d 100644
--- a/absl/container/internal/btree_container.h
+++ b/absl/container/internal/btree_container.h
@@ -412,8 +412,8 @@
   // `this`, it is left unmodified in `src`.
   template <
       typename T,
-      typename absl::enable_if_t<
-          absl::conjunction<
+      typename std::enable_if_t<
+          std::conjunction<
               std::is_same<value_type, typename T::value_type>,
               std::is_same<allocator_type, typename T::allocator_type>,
               std::is_same<typename params_type::is_map_container,
@@ -431,8 +431,8 @@
 
   template <
       typename T,
-      typename absl::enable_if_t<
-          absl::conjunction<
+      typename std::enable_if_t<
+          std::conjunction<
               std::is_same<value_type, typename T::value_type>,
               std::is_same<allocator_type, typename T::allocator_type>,
               std::is_same<typename params_type::is_map_container,
@@ -474,7 +474,7 @@
                           typename Tree::params_type::mapped_type, M>>;
   template <class K, bool KValue, class M, bool MValue, typename... Dummy>
   using LifetimeBoundKV =
-      absl::conjunction<LifetimeBoundK<K, KValue, absl::void_t<Dummy...>>,
+      std::conjunction<LifetimeBoundK<K, KValue, absl::void_t<Dummy...>>,
                         LifetimeBoundV<M, MValue>>;
 
  public:
@@ -824,8 +824,8 @@
   // Moves all elements from `src` into `this`.
   template <
       typename T,
-      typename absl::enable_if_t<
-          absl::conjunction<
+      typename std::enable_if_t<
+          std::conjunction<
               std::is_same<value_type, typename T::value_type>,
               std::is_same<allocator_type, typename T::allocator_type>,
               std::is_same<typename params_type::is_map_container,
@@ -840,8 +840,8 @@
 
   template <
       typename T,
-      typename absl::enable_if_t<
-          absl::conjunction<
+      typename std::enable_if_t<
+          std::conjunction<
               std::is_same<value_type, typename T::value_type>,
               std::is_same<allocator_type, typename T::allocator_type>,
               std::is_same<typename params_type::is_map_container,
diff --git a/absl/container/internal/common.h b/absl/container/internal/common.h
index 62517af..3bf0c7c 100644
--- a/absl/container/internal/common.h
+++ b/absl/container/internal/common.h
@@ -58,7 +58,7 @@
 using EnableIf = std::enable_if_t<Cond::value, int>;
 
 template <bool Value, class T>
-using HasValue = std::conditional_t<Value, T, absl::negation<T>>;
+using HasValue = std::conditional_t<Value, T, std::negation<T>>;
 
 template <class T>
 struct IfRRef {
diff --git a/absl/container/internal/common_policy_traits.h b/absl/container/internal/common_policy_traits.h
index 86e038e..3b0d505 100644
--- a/absl/container/internal/common_policy_traits.h
+++ b/absl/container/internal/common_policy_traits.h
@@ -81,7 +81,7 @@
   // Note: we use remove_const_t so that the two overloads have different args
   // in the case of sets with explicitly const value_types.
   template <class P = Policy>
-  static auto element(absl::remove_const_t<slot_type>* slot)
+  static auto element(std::remove_const_t<slot_type>* slot)
       -> decltype(P::element(slot)) {
     return P::element(slot);
   }
diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h
index 2dd8d6c..9d5c055 100644
--- a/absl/container/internal/compressed_tuple.h
+++ b/absl/container/internal/compressed_tuple.h
@@ -166,7 +166,7 @@
 template <class... Ts, class... Vs>
 struct TupleMoveConstructible<true, CompressedTuple<Ts...>, Vs...>
     : std::integral_constant<
-          bool, absl::conjunction<
+          bool, std::conjunction<
                     TupleElementMoveConstructible<Ts, Vs&&>...>::value> {};
 
 template <typename T>
@@ -227,11 +227,11 @@
       : CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {}
 
   template <typename First, typename... Vs,
-            absl::enable_if_t<
-                absl::conjunction<
+            std::enable_if_t<
+                std::conjunction<
                     // Ensure we are not hiding default copy/move constructors.
-                    absl::negation<std::is_same<void(CompressedTuple),
-                                                void(absl::decay_t<First>)>>,
+                    std::negation<std::is_same<void(CompressedTuple),
+                                                void(std::decay_t<First>)>>,
                     internal_compressed_tuple::TupleItemsMoveConstructible<
                         CompressedTuple<Ts...>, First, Vs...>>::value,
                 bool> = true>
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h
index 47064a7..dcf0bd2 100644
--- a/absl/container/internal/container_memory.h
+++ b/absl/container/internal/container_memory.h
@@ -350,11 +350,11 @@
   ~map_slot_type() = delete;
   using value_type = std::pair<const K, V>;
   using mutable_value_type =
-      std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;
+      std::pair<std::remove_const_t<K>, std::remove_const_t<V>>;
 
   value_type value;
   mutable_value_type mutable_value;
-  absl::remove_const_t<K> key;
+  std::remove_const_t<K> key;
 };
 
 template <class K, class V>
@@ -362,7 +362,7 @@
   using slot_type = map_slot_type<K, V>;
   using value_type = std::pair<const K, V>;
   using mutable_value_type =
-      std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;
+      std::pair<std::remove_const_t<K>, std::remove_const_t<V>>;
 
  private:
   static void emplace(slot_type* slot) {
diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h
index 82eed2a..7f5f892 100644
--- a/absl/container/internal/hash_policy_traits.h
+++ b/absl/container/internal/hash_policy_traits.h
@@ -38,7 +38,7 @@
  private:
   struct ReturnKey {
     template <class Key,
-              absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
+              std::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
     static key_type& Impl(Key&& k, int) {
       return *std::launder(
           const_cast<key_type*>(std::addressof(std::forward<Key>(k))));
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
index c7b709f..42878ac 100644
--- a/absl/container/internal/inlined_vector.h
+++ b/absl/container/internal/inlined_vector.h
@@ -79,7 +79,7 @@
 
 template <typename A,
           bool IsTriviallyDestructible =
-              absl::is_trivially_destructible<ValueType<A>>::value &&
+              std::is_trivially_destructible<ValueType<A>>::value &&
               std::is_same<A, std::allocator<ValueType<A>>>::value>
 struct DestroyAdapter;
 
@@ -288,14 +288,14 @@
   struct ElementwiseSwapPolicy {};
   struct ElementwiseConstructPolicy {};
 
-  using MoveAssignmentPolicy = absl::conditional_t<
+  using MoveAssignmentPolicy = std::conditional_t<
       // Fast path: if the value type can be trivially move assigned and
       // destroyed, and we know the allocator doesn't do anything fancy, then
       // it's safe for us to simply adopt the contents of the storage for
       // `other` and remove its own reference to them. It's as if we had
       // individually move-assigned each value and then destroyed the original.
-      absl::conjunction<absl::is_trivially_move_assignable<ValueType<A>>,
-                        absl::is_trivially_destructible<ValueType<A>>,
+      std::conjunction<std::is_trivially_move_assignable<ValueType<A>>,
+                        std::is_trivially_destructible<ValueType<A>>,
                         std::is_same<A, std::allocator<ValueType<A>>>>::value,
       MemcpyPolicy,
       // Otherwise we use move assignment if possible. If not, we simulate
@@ -304,21 +304,21 @@
       // Note that this is in contrast to e.g. std::vector and std::optional,
       // which are themselves not move-assignable when their contained type is
       // not.
-      absl::conditional_t<IsMoveAssignOk<A>::value, ElementwiseAssignPolicy,
+      std::conditional_t<IsMoveAssignOk<A>::value, ElementwiseAssignPolicy,
                           ElementwiseConstructPolicy>>;
 
   // The policy to be used specifically when swapping inlined elements.
-  using SwapInlinedElementsPolicy = absl::conditional_t<
+  using SwapInlinedElementsPolicy = std::conditional_t<
       // Fast path: if the value type can be trivially relocated, and we
       // know the allocator doesn't do anything fancy, then it's safe for us
       // to simply swap the bytes in the inline storage. It's as if we had
       // relocated the first vector's elements into temporary storage,
       // relocated the second's elements into the (now-empty) first's,
       // and then relocated from temporary storage into the second.
-      absl::conjunction<absl::is_trivially_relocatable<ValueType<A>>,
+      std::conjunction<absl::is_trivially_relocatable<ValueType<A>>,
                         std::is_same<A, std::allocator<ValueType<A>>>>::value,
       MemcpyPolicy,
-      absl::conditional_t<IsSwapOk<A>::value, ElementwiseSwapPolicy,
+      std::conditional_t<IsSwapOk<A>::value, ElementwiseSwapPolicy,
                           ElementwiseConstructPolicy>>;
 
   static SizeType<A> NextCapacity(SizeType<A> current_capacity) {
@@ -348,7 +348,7 @@
     // Fast path: if no destructors need to be run and we know the allocator
     // doesn't do anything fancy, then all we need to do is deallocate (and
     // maybe not even that).
-    if (absl::is_trivially_destructible<ValueType<A>>::value &&
+    if (std::is_trivially_destructible<ValueType<A>>::value &&
         std::is_same<A, std::allocator<ValueType<A>>>::value) {
       DeallocateIfAllocated();
       return;
@@ -507,11 +507,11 @@
                // First case above
                absl::is_trivially_relocatable<V>::value ||
                // Second case above
-               (absl::is_trivially_move_assignable<V>::value &&
-                absl::is_trivially_destructible<V>::value) ||
+               (std::is_trivially_move_assignable<V>::value &&
+                std::is_trivially_destructible<V>::value) ||
                // Third case above
-               (absl::is_trivially_copy_constructible<V>::value ||
-                absl::is_trivially_copy_assignable<V>::value))));
+               (std::is_trivially_copy_constructible<V>::value ||
+                std::is_trivially_copy_assignable<V>::value))));
     }
 
     GetSizeAndIsAllocated() = other_storage.GetSizeAndIsAllocated();
@@ -596,7 +596,7 @@
   // Fast path: if the value type is trivially copy constructible and we know
   // the allocator doesn't do anything fancy, then we know it is legal for us to
   // simply memcpy the other vector's elements.
-  if (absl::is_trivially_copy_constructible<ValueType<A>>::value &&
+  if (std::is_trivially_copy_constructible<ValueType<A>>::value &&
       std::is_same<A, std::allocator<ValueType<A>>>::value) {
     std::memcpy(reinterpret_cast<char*>(dst),
                 reinterpret_cast<const char*>(src), n * sizeof(ValueType<A>));
diff --git a/absl/container/internal/layout.h b/absl/container/internal/layout.h
index 58c8d4f..f49d272 100644
--- a/absl/container/internal/layout.h
+++ b/absl/container/internal/layout.h
@@ -261,7 +261,7 @@
 
 // Does `Ts...` contain `T`?
 template <class T, class... Ts>
-using Contains = absl::disjunction<std::is_same<T, Ts>...>;
+using Contains = std::disjunction<std::is_same<T, Ts>...>;
 
 template <class From, class To>
 using CopyConst =
@@ -352,7 +352,7 @@
     absl::index_sequence<OffsetSeq...>> {
  private:
   static_assert(sizeof...(Elements) > 0, "At least one field is required");
-  static_assert(absl::conjunction<IsLegalElementType<Elements>...>::value,
+  static_assert(std::conjunction<IsLegalElementType<Elements>...>::value,
                 "Invalid element type (see IsLegalElementType)");
   static_assert(sizeof...(StaticSizeSeq) <= sizeof...(Elements),
                 "Too many static sizes specified");
diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h
index 20b622b..25ed119 100644
--- a/absl/container/internal/raw_hash_map.h
+++ b/absl/container/internal/raw_hash_map.h
@@ -88,7 +88,7 @@
                           typename Policy::mapped_type, V>>;
   template <class K, bool KValue, class V, bool VValue, typename... Dummy>
   using LifetimeBoundKV =
-      absl::conjunction<LifetimeBoundK<K, KValue, absl::void_t<Dummy...>>,
+      std::conjunction<LifetimeBoundK<K, KValue, absl::void_t<Dummy...>>,
                         LifetimeBoundV<V, VValue>>;
 
  public:
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index 15d072a..048d2ee 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -1528,6 +1528,10 @@
   if (common.capacity() == 1) {
     if (common.empty()) {
       IncrementSmallSizeNonSoo(common, policy);
+      if (common.has_infoz()) {
+        common.infoz().RecordInsertMiss(get_hash(common.seed().seed()),
+                                        /*distance_from_desired=*/0);
+      }
       return {SooControl(), common.slot_array()};
     } else {
       return Grow1To3AndPrepareInsert(common, policy, get_hash);
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 1a9fa1d..805ea30 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -1930,7 +1930,7 @@
   // An enabler for insert(T&&): T must be convertible to init_type or be the
   // same as [cv] value_type [ref].
   template <class T>
-  using Insertable = absl::disjunction<
+  using Insertable = std::disjunction<
       std::is_same<absl::remove_cvref_t<reference>, absl::remove_cvref_t<T>>,
       std::is_convertible<T, init_type>>;
   template <class T>
@@ -1970,9 +1970,9 @@
     using iterator_category = std::forward_iterator_tag;
     using value_type = typename raw_hash_set::value_type;
     using reference =
-        absl::conditional_t<PolicyTraits::constant_iterators::value,
+        std::conditional_t<PolicyTraits::constant_iterators::value,
                             const value_type&, value_type&>;
-    using pointer = absl::remove_reference_t<reference>*;
+    using pointer = std::remove_reference_t<reference>*;
     using difference_type = typename raw_hash_set::difference_type;
 
     iterator() {}
diff --git a/absl/container/internal/raw_hash_set_benchmark.cc b/absl/container/internal/raw_hash_set_benchmark.cc
index 2e9a81d..71feffe 100644
--- a/absl/container/internal/raw_hash_set_benchmark.cc
+++ b/absl/container/internal/raw_hash_set_benchmark.cc
@@ -244,6 +244,30 @@
 }
 BENCHMARK(BM_EraseEmplace)->Arg(1)->Arg(2)->Arg(4)->Arg(8)->Arg(16)->Arg(100);
 
+void BM_EraseEmplaceString(benchmark::State& state) {
+  StringTable t;
+  int64_t size = state.range(0);
+  for (int64_t i = 0; i < size; ++i) {
+    std::string s = std::to_string(i);
+    t.emplace(s, s);
+  }
+  while (state.KeepRunningBatch(size)) {
+    for (int64_t i = 0; i < size; ++i) {
+      benchmark::DoNotOptimize(t);
+      std::string s = std::to_string(i);
+      t.erase(s);
+      t.emplace(s, s);
+    }
+  }
+}
+BENCHMARK(BM_EraseEmplaceString)
+    ->Arg(1)
+    ->Arg(2)
+    ->Arg(4)
+    ->Arg(8)
+    ->Arg(16)
+    ->Arg(100);
+
 void BM_EndComparison(benchmark::State& state) {
   StringTable t = {{"a", "a"}, {"b", "b"}};
   auto it = t.begin();
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index 9c33e3c..952399a 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -2878,8 +2878,9 @@
   }
 }
 
-std::vector<const HashtablezInfo*> SampleSooMutation(
-    absl::FunctionRef<void(SooInt32Table&)> mutate_table) {
+template <typename IntTableType>
+std::vector<const HashtablezInfo*> SampleTableMutation(
+    absl::FunctionRef<void(IntTableType&)> mutate_table) {
   // Enable the feature even if the prod default is off.
   SetSamplingRateTo1Percent();
 
@@ -2892,7 +2893,7 @@
     ++start_size;
   });
 
-  std::vector<SooInt32Table> tables;
+  std::vector<IntTableType> tables;
   for (int i = 0; i < 1000000; ++i) {
     tables.emplace_back();
     mutate_table(tables.back());
@@ -2911,6 +2912,16 @@
   return infos;
 }
 
+std::vector<const HashtablezInfo*> SampleSooMutation(
+    absl::FunctionRef<void(SooInt32Table&)> mutate_table) {
+  return SampleTableMutation<SooInt32Table>(mutate_table);
+}
+
+std::vector<const HashtablezInfo*> SampleNonSooMutation(
+    absl::FunctionRef<void(NonSooIntTable&)> mutate_table) {
+  return SampleTableMutation<NonSooIntTable>(mutate_table);
+}
+
 TEST(RawHashSamplerTest, SooTableInsertToEmpty) {
   if (SooInt32Table().capacity() != SooCapacity()) {
     CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
@@ -2956,6 +2967,22 @@
   // instance.
 }
 
+TEST(RawHashSamplerTest, NonSooTableRepeatedInsertEraseCountSizeRight) {
+  ASSERT_EQ(NonSooIntTable().capacity(), 0);
+  std::vector<const HashtablezInfo*> infos =
+      SampleNonSooMutation([](NonSooIntTable& t) {
+        for (int i = 0; i < 10; ++i) {
+          t.insert(1);
+          t.erase(1);
+        }
+      });
+  for (const HashtablezInfo* info : infos) {
+    EXPECT_EQ(info->soo_capacity, 0);
+    ASSERT_EQ(info->capacity, 1);
+    ASSERT_EQ(info->size, 0);
+  }
+}
+
 // Verifies that copy-constructing or copy-assigning an SOO table does not
 // incorrectly trigger new sampling evaluations.
 TEST(RawHashSamplerTest, SooTableCopyDoesNotOversample) {
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index 3ceef32..6fe1d9f 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -604,22 +604,22 @@
 // Erasure and/or insertion of elements in the function is not allowed.
 template <typename K, typename V, typename H, typename E, typename A,
           typename Function>
-decay_t<Function> c_for_each_fast(const node_hash_map<K, V, H, E, A>& c,
-                                  Function&& f) {
+std::decay_t<Function> c_for_each_fast(const node_hash_map<K, V, H, E, A>& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
 template <typename K, typename V, typename H, typename E, typename A,
           typename Function>
-decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>& c,
-                                  Function&& f) {
+std::decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
 template <typename K, typename V, typename H, typename E, typename A,
           typename Function>
-decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>&& c,
-                                  Function&& f) {
+std::decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>&& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index 17aa763..4d58098 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -512,18 +512,20 @@
 // There is no guarantees on the order of the function calls.
 // Erasure and/or insertion of elements in the function is not allowed.
 template <typename T, typename H, typename E, typename A, typename Function>
-decay_t<Function> c_for_each_fast(const node_hash_set<T, H, E, A>& c,
-                                  Function&& f) {
+std::decay_t<Function> c_for_each_fast(const node_hash_set<T, H, E, A>& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
 template <typename T, typename H, typename E, typename A, typename Function>
-decay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>& c, Function&& f) {
+std::decay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
 template <typename T, typename H, typename E, typename A, typename Function>
-decay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>&& c, Function&& f) {
+std::decay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>&& c,
+                                       Function&& f) {
   container_internal::ForEach(f, &c);
   return f;
 }
diff --git a/absl/debugging/internal/demangle_rust.h b/absl/debugging/internal/demangle_rust.h
index 94a9aec..299c17a 100644
--- a/absl/debugging/internal/demangle_rust.h
+++ b/absl/debugging/internal/demangle_rust.h
@@ -32,6 +32,14 @@
 // DemangleRustSymbolEncoding is async-signal-safe and runs in bounded C++
 // call-stack space.  It is suitable for symbolizing stack traces in a signal
 // handler.
+//
+// Note that this demangler purposefully omits some details: generic argument
+// lists become `<>`, function types `fn...`, and long tuples `(t, u, v, ...)`.
+// This simplification suits crash backtracing, where the signal handler must
+// not `malloc`, and the human troubleshooter won't want the `file:line` blame
+// drowned in generic arguments.  Applications better served by a freely
+// allocating detailed demangler might prefer to use Rust's own `rustc-demangle`
+// crate.
 bool DemangleRustSymbolEncoding(const char* mangled, char* out,
                                 size_t out_size);
 
diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h
index bd2c9c7..a994dba 100644
--- a/absl/debugging/internal/symbolize.h
+++ b/absl/debugging/internal/symbolize.h
@@ -78,46 +78,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
-// Legacy stateless symbol decorator API. Will be removed soon.
-struct SymbolDecoratorArgs {
-  // The program counter we are getting symbolic name for.
-  const void *pc;
-  // 0 for main executable, load address for shared libraries.
-  ptrdiff_t relocation;
-  // Read-only file descriptor for ELF image covering "pc",
-  // or -1 if no such ELF image exists in /proc/self/maps.
-  int fd;
-  // Output buffer, size.
-  // Note: the buffer may not be empty -- default symbolizer may have already
-  // produced some output, and earlier decorators may have adorned it in
-  // some way. You are free to replace or augment the contents (within the
-  // symbol_buf_size limit).
-  char *const symbol_buf;
-  size_t symbol_buf_size;
-  // Temporary scratch space, size.
-  // Use that space in preference to allocating your own stack buffer to
-  // conserve stack.
-  char *const tmp_buf;
-  size_t tmp_buf_size;
-  // User-provided argument
-  void* arg;
-};
-using LegacySymbolDecorator = void (*)(const SymbolDecoratorArgs *);
-
-// Installs a function-pointer as a decorator. Returns a value less than zero
-// if the system cannot install the decorator. Otherwise, returns a unique
-// identifier corresponding to the decorator. This identifier can be used to
-// uninstall the decorator - See RemoveSymbolDecorator() below.
-int InstallSymbolDecorator(LegacySymbolDecorator decorator, void* arg);
-
-// Removes a previously installed function-pointer decorator. Parameter "ticket"
-// is the return-value from calling InstallSymbolDecorator().
-bool RemoveSymbolDecorator(int ticket);
-
-// Remove all installed decorators.  Returns true if successful, false if
-// symbolization is currently in progress.
-bool RemoveAllSymbolDecorators();
-
 class SymbolDecorator;
 
 class SymbolDecoratorDeleter {
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index 5630cc2..14b23c1 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -146,17 +146,6 @@
 // pointers and the first one is the function's entry.
 const size_t kFunctionDescriptorSize = sizeof(void *) * 2;
 
-const int kMaxDecorators = 10;  // Seems like a reasonable upper limit.
-
-struct InstalledSymbolDecorator {
-  LegacySymbolDecorator fn;
-  void *arg;
-  int ticket;
-};
-
-int g_num_decorators;
-InstalledSymbolDecorator g_decorators[kMaxDecorators];
-
 std::atomic<SymbolDecorator::Factory*> g_decorator_factory = nullptr;
 
 struct FileMappingHint {
@@ -166,16 +155,6 @@
   const char *filename;
 };
 
-// Protects g_decorators.
-// We are using SpinLock and not a Mutex here, because we may be called
-// from inside Mutex::Lock itself, and it prohibits recursive calls.
-// This happens in e.g. base/stacktrace_syscall_unittest.
-// Moreover, we are using only try_lock(), if the decorator list
-// is being modified (is busy), we skip all decorators, and possibly
-// loose some info. Sorry, that's the best we could do.
-ABSL_CONST_INIT absl::base_internal::SpinLock g_decorators_mu(
-    absl::base_internal::SCHEDULE_KERNEL_ONLY);
-
 const int kMaxFileMappingHints = 8;
 int g_num_file_mapping_hints;
 FileMappingHint g_file_mapping_hints[kMaxFileMappingHints];
@@ -1507,7 +1486,6 @@
 const char *Symbolizer::GetUncachedSymbol(const void *pc) {
   ObjFile *const obj = FindObjFile(pc, 1);
   ptrdiff_t relocation = 0;
-  int fd = -1;
   if (obj != nullptr) {
     if (MaybeInitializeObjFile(obj, decorator_factory_)) {
       const size_t start_addr = reinterpret_cast<size_t>(obj->start_addr);
@@ -1549,7 +1527,6 @@
         }
       }
 
-      fd = obj->fd;
       if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
                                   sizeof(symbol_buf_), tmp_buf_,
                                   sizeof(tmp_buf_)) == SYMBOL_FOUND) {
@@ -1574,18 +1551,6 @@
 #endif
   }
 
-  if (g_decorators_mu.try_lock()) {
-    if (g_num_decorators > 0) {
-      SymbolDecoratorArgs decorator_args = {
-          pc,       relocation,       fd,     symbol_buf_, sizeof(symbol_buf_),
-          tmp_buf_, sizeof(tmp_buf_), nullptr};
-      for (int i = 0; i < g_num_decorators; ++i) {
-        decorator_args.arg = g_decorators[i].arg;
-        g_decorators[i].fn(&decorator_args);
-      }
-    }
-    g_decorators_mu.unlock();
-  }
   if (obj != nullptr && obj->decorator != nullptr) {
     obj->decorator->Decorate(pc, relocation, symbol_buf_, sizeof(symbol_buf_),
                              tmp_buf_, sizeof(tmp_buf_));
@@ -1633,55 +1598,6 @@
 #endif
 }
 
-bool RemoveAllSymbolDecorators() {
-  SetSymbolDecoratorFactory(nullptr);
-
-  if (!g_decorators_mu.try_lock()) {
-    // Someone else is using decorators. Get out.
-    return false;
-  }
-  g_num_decorators = 0;
-  g_decorators_mu.unlock();
-  return true;
-}
-
-bool RemoveSymbolDecorator(int ticket) {
-  if (!g_decorators_mu.try_lock()) {
-    // Someone else is using decorators. Get out.
-    return false;
-  }
-  for (int i = 0; i < g_num_decorators; ++i) {
-    if (g_decorators[i].ticket == ticket) {
-      while (i < g_num_decorators - 1) {
-        g_decorators[i] = g_decorators[i + 1];
-        ++i;
-      }
-      g_num_decorators = i;
-      break;
-    }
-  }
-  g_decorators_mu.unlock();
-  return true;  // Decorator is known to be removed.
-}
-
-int InstallSymbolDecorator(LegacySymbolDecorator decorator, void *arg) {
-  static int ticket = 0;
-
-  if (!g_decorators_mu.try_lock()) {
-    // Someone else is using decorators. Get out.
-    return -2;
-  }
-  int ret = ticket;
-  if (g_num_decorators >= kMaxDecorators) {
-    ret = -1;
-  } else {
-    g_decorators[g_num_decorators] = {decorator, arg, ticket++};
-    ++g_num_decorators;
-  }
-  g_decorators_mu.unlock();
-  return ret;
-}
-
 SymbolDecorator::Factory* SetSymbolDecoratorFactory(
     SymbolDecorator::Factory* factory) {
   return g_decorator_factory.exchange(factory, std::memory_order_acq_rel);
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc
index 5e1e65d..5eb68e0 100644
--- a/absl/debugging/symbolize_test.cc
+++ b/absl/debugging/symbolize_test.cc
@@ -375,48 +375,6 @@
   }
 }
 
-// Appends string(*args->arg) to args->symbol_buf.
-static void DummySymbolDecorator(
-    const absl::debugging_internal::SymbolDecoratorArgs *args) {
-  std::string *message = static_cast<std::string *>(args->arg);
-  strncat(args->symbol_buf, message->c_str(),
-          args->symbol_buf_size - strlen(args->symbol_buf) - 1);
-}
-
-TEST(Symbolize, InstallAndRemoveSymbolDecorators) {
-  int ticket_a;
-  std::string a_message("a");
-  EXPECT_GE(ticket_a = absl::debugging_internal::InstallSymbolDecorator(
-                DummySymbolDecorator, &a_message),
-            0);
-
-  int ticket_b;
-  std::string b_message("b");
-  EXPECT_GE(ticket_b = absl::debugging_internal::InstallSymbolDecorator(
-                DummySymbolDecorator, &b_message),
-            0);
-
-  int ticket_c;
-  std::string c_message("c");
-  EXPECT_GE(ticket_c = absl::debugging_internal::InstallSymbolDecorator(
-                DummySymbolDecorator, &c_message),
-            0);
-
-  // Use addresses 4 and 8 here to ensure that we always use valid addresses
-  // even on systems that require instructions to be 32-bit aligned.
-  char *address = reinterpret_cast<char *>(4);
-  EXPECT_STREQ("abc", TrySymbolize(address));
-
-  EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_b));
-
-  EXPECT_STREQ("ac", TrySymbolize(address + 4));
-
-  // Cleanup: remove all remaining decorators so other stack traces don't
-  // get mystery "ac" decoration.
-  EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_a));
-  EXPECT_TRUE(absl::debugging_internal::RemoveSymbolDecorator(ticket_c));
-}
-
 template <char C>
 class TestSymbolDecorator final
     : public absl::debugging_internal::SymbolDecorator {
diff --git a/absl/debugging/symbolize_unimplemented.inc b/absl/debugging/symbolize_unimplemented.inc
index 1ba5bf4..b0faa9d 100644
--- a/absl/debugging/symbolize_unimplemented.inc
+++ b/absl/debugging/symbolize_unimplemented.inc
@@ -21,10 +21,6 @@
 
 namespace debugging_internal {
 
-int InstallSymbolDecorator(LegacySymbolDecorator, void*) { return -1; }
-bool RemoveSymbolDecorator(int) { return false; }
-bool RemoveAllSymbolDecorators(void) { return false; }
-
 SymbolDecorator::Factory* SetSymbolDecoratorFactory(SymbolDecorator::Factory*) {
   return nullptr;
 }
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index 285d842..e26b2ad 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -608,7 +608,7 @@
     *value = ReadOneBool();
   }
   template <typename T,
-            absl::enable_if_t<flags_internal::StorageKind<T>() ==
+            std::enable_if_t<flags_internal::StorageKind<T>() ==
                                   FlagValueStorageKind::kOneWordAtomic,
                               int> = 0>
   void Read(T* value) const ABSL_LOCKS_EXCLUDED(DataGuard()) {
diff --git a/absl/functional/any_invocable.h b/absl/functional/any_invocable.h
index 6dd72b6..4ba4fe3 100644
--- a/absl/functional/any_invocable.h
+++ b/absl/functional/any_invocable.h
@@ -191,7 +191,7 @@
   // Upon construction, `*this` is only empty if `f` is a function pointer or
   // member pointer type and is null, or if `f` is an `AnyInvocable` that is
   // empty.
-  template <class F, typename = absl::enable_if_t<
+  template <class F, typename = std::enable_if_t<
                          internal_any_invocable::CanConvert<Sig, F>::value>>
   AnyInvocable(F&& f)  // NOLINT
       : Impl(internal_any_invocable::ConversionConstruct(),
@@ -206,25 +206,25 @@
   //       absl::in_place_type<PossiblyImmovableType>, arg1, arg2);
   //
   template <class T, class... Args,
-            typename = absl::enable_if_t<
+            typename = std::enable_if_t<
                 internal_any_invocable::CanEmplace<Sig, T, Args...>::value>>
   explicit AnyInvocable(absl::in_place_type_t<T>, Args&&... args)
-      : Impl(absl::in_place_type<absl::decay_t<T>>,
+      : Impl(absl::in_place_type<std::decay_t<T>>,
              std::forward<Args>(args)...) {
-    static_assert(std::is_same<T, absl::decay_t<T>>::value,
+    static_assert(std::is_same<T, std::decay_t<T>>::value,
                   "The explicit template argument of in_place_type is required "
                   "to be an unqualified object type.");
   }
 
   // Overload of the above constructor to support list-initialization.
   template <class T, class U, class... Args,
-            typename = absl::enable_if_t<internal_any_invocable::CanEmplace<
+            typename = std::enable_if_t<internal_any_invocable::CanEmplace<
                 Sig, T, std::initializer_list<U>&, Args...>::value>>
   explicit AnyInvocable(absl::in_place_type_t<T>,
                         std::initializer_list<U> ilist, Args&&... args)
-      : Impl(absl::in_place_type<absl::decay_t<T>>, ilist,
+      : Impl(absl::in_place_type<std::decay_t<T>>, ilist,
              std::forward<Args>(args)...) {
-    static_assert(std::is_same<T, absl::decay_t<T>>::value,
+    static_assert(std::is_same<T, std::decay_t<T>>::value,
                   "The explicit template argument of in_place_type is required "
                   "to be an unqualified object type.");
   }
@@ -248,7 +248,7 @@
   // Upon assignment, `*this` is only empty if `f` is a function pointer or
   // member pointer type and is null, or if `f` is an `AnyInvocable` that is
   // empty.
-  template <class F, typename = absl::enable_if_t<
+  template <class F, typename = std::enable_if_t<
                          internal_any_invocable::CanAssign<Sig, F>::value>>
   AnyInvocable& operator=(F&& f) {
     *this = AnyInvocable(std::forward<F>(f));
@@ -260,7 +260,7 @@
   // `AnyInvocable` instance.
   template <
       class F,
-      typename = absl::enable_if_t<
+      typename = std::enable_if_t<
           internal_any_invocable::CanAssignReferenceWrapper<Sig, F>::value>>
   AnyInvocable& operator=(std::reference_wrapper<F> f) noexcept {
     *this = AnyInvocable(f);
diff --git a/absl/functional/any_invocable_test.cc b/absl/functional/any_invocable_test.cc
index 7ddfcab..9c5068a 100644
--- a/absl/functional/any_invocable_test.cc
+++ b/absl/functional/any_invocable_test.cc
@@ -41,7 +41,7 @@
 template <class T>
 struct Wrapper {
   template <class U,
-            class = absl::enable_if_t<std::is_convertible<U, T>::value>>
+            class = std::enable_if_t<std::is_convertible<U, T>::value>>
   Wrapper(U&&);  // NOLINT
 };
 
@@ -58,7 +58,7 @@
 struct QualifiersForThisImpl {
   static_assert(std::is_object<This>::value, "");
   using type =
-      absl::conditional_t<std::is_const<Qualifiers>::value, const This, This>&;
+      std::conditional_t<std::is_const<Qualifiers>::value, const This, This>&;
 };
 
 template <class Qualifiers, class This>
@@ -69,7 +69,7 @@
 struct QualifiersForThisImpl<Qualifiers&&, This> {
   static_assert(std::is_object<This>::value, "");
   using type =
-      absl::conditional_t<std::is_const<Qualifiers>::value, const This, This>&&;
+      std::conditional_t<std::is_const<Qualifiers>::value, const This, This>&&;
 };
 
 template <class Qualifiers, class This>
@@ -84,38 +84,38 @@
 template <class T, class R, class... P>
 struct GiveQualifiersToFunImpl<T, R(P...)> {
   using type =
-      absl::conditional_t<std::is_const<T>::value, R(P...) const, R(P...)>;
+      std::conditional_t<std::is_const<T>::value, R(P...) const, R(P...)>;
 };
 
 template <class T, class R, class... P>
 struct GiveQualifiersToFunImpl<T&, R(P...)> {
   using type =
-      absl::conditional_t<std::is_const<T>::value, R(P...) const&, R(P...)&>;
+      std::conditional_t<std::is_const<T>::value, R(P...) const&, R(P...)&>;
 };
 
 template <class T, class R, class... P>
 struct GiveQualifiersToFunImpl<T&&, R(P...)> {
   using type =
-      absl::conditional_t<std::is_const<T>::value, R(P...) const&&, R(P...) &&>;
+      std::conditional_t<std::is_const<T>::value, R(P...) const&&, R(P...) &&>;
 };
 
 template <class T, class R, class... P>
 struct GiveQualifiersToFunImpl<T, R(P...) noexcept> {
-  using type = absl::conditional_t<std::is_const<T>::value,
+  using type = std::conditional_t<std::is_const<T>::value,
                                    R(P...) const noexcept, R(P...) noexcept>;
 };
 
 template <class T, class R, class... P>
 struct GiveQualifiersToFunImpl<T&, R(P...) noexcept> {
   using type =
-      absl::conditional_t<std::is_const<T>::value, R(P...) const & noexcept,
+      std::conditional_t<std::is_const<T>::value, R(P...) const & noexcept,
                           R(P...) & noexcept>;
 };
 
 template <class T, class R, class... P>
 struct GiveQualifiersToFunImpl<T&&, R(P...) noexcept> {
   using type =
-      absl::conditional_t<std::is_const<T>::value, R(P...) const && noexcept,
+      std::conditional_t<std::is_const<T>::value, R(P...) const && noexcept,
                           R(P...) && noexcept>;
 };
 
@@ -367,14 +367,14 @@
   }
 
   using CompatibleAnyInvocableFunType =
-      absl::conditional_t<std::is_rvalue_reference<Qual>::value,
+      std::conditional_t<std::is_rvalue_reference<Qual>::value,
                           GiveQualifiersToFun<const _&&, UnqualifiedFunType>,
                           GiveQualifiersToFun<const _&, UnqualifiedFunType>>;
 
   using CompatibleAnyInvType = AnyInvocable<CompatibleAnyInvocableFunType>;
 
   using IncompatibleInvocable =
-      absl::conditional_t<std::is_rvalue_reference<Qual>::value,
+      std::conditional_t<std::is_rvalue_reference<Qual>::value,
                           GiveQualifiersToFun<_&, UnqualifiedFunType>(_::*),
                           GiveQualifiersToFun<_&&, UnqualifiedFunType>(_::*)>;
 };
@@ -1284,7 +1284,7 @@
   // Just like plain functors, it should work fine to use an AnyInvocable that
   // returns the non-moveable type.
   using UnqualifiedFun =
-      absl::conditional_t<TypeParam::kIsNoexcept, Result() noexcept, Result()>;
+      std::conditional_t<TypeParam::kIsNoexcept, Result() noexcept, Result()>;
 
   using Fun =
       GiveQualifiersToFun<typename TypeParam::Qualifiers, UnqualifiedFun>;
@@ -1364,7 +1364,7 @@
   // Just like plain functors, it should work fine to use an AnyInvocable that
   // returns the non-moveable type.
   using UnqualifiedFun =
-      absl::conditional_t<TypeParam::kIsNoexcept, Result() noexcept, Result()>;
+      std::conditional_t<TypeParam::kIsNoexcept, Result() noexcept, Result()>;
 
   using Fun =
       GiveQualifiersToFun<typename TypeParam::Qualifiers, UnqualifiedFun>;
diff --git a/absl/functional/internal/any_invocable.h b/absl/functional/internal/any_invocable.h
index 597c210..66168c6 100644
--- a/absl/functional/internal/any_invocable.h
+++ b/absl/functional/internal/any_invocable.h
@@ -611,39 +611,39 @@
 
 /*SFINAE constraints for the conversion-constructor.*/
 template <class Sig, class F,
-          class = absl::enable_if_t<
+          class = std::enable_if_t<
               !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>
 using CanConvert = TrueAlias<
-    absl::enable_if_t<!IsInPlaceType<RemoveCVRef<F>>::value>,
-    absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
-    absl::enable_if_t<
+    std::enable_if_t<!IsInPlaceType<RemoveCVRef<F>>::value>,
+    std::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
+    std::enable_if_t<
         Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,
-    absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>;
+    std::enable_if_t<std::is_constructible<std::decay_t<F>, F>::value>>;
 
 /*SFINAE constraints for the std::in_place constructors.*/
 template <class Sig, class F, class... Args>
 using CanEmplace = TrueAlias<
-    absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
-    absl::enable_if_t<
+    std::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
+    std::enable_if_t<
         Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,
-    absl::enable_if_t<std::is_constructible<absl::decay_t<F>, Args...>::value>>;
+    std::enable_if_t<std::is_constructible<std::decay_t<F>, Args...>::value>>;
 
 /*SFINAE constraints for the conversion-assign operator.*/
 template <class Sig, class F,
-          class = absl::enable_if_t<
+          class = std::enable_if_t<
               !std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>
 using CanAssign = TrueAlias<
-    absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
-    absl::enable_if_t<
+    std::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
+    std::enable_if_t<
         Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,
-    absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>;
+    std::enable_if_t<std::is_constructible<std::decay_t<F>, F>::value>>;
 
 /*SFINAE constraints for the reference-wrapper conversion-assign operator.*/
 template <class Sig, class F>
 using CanAssignReferenceWrapper = TrueAlias<
-    absl::enable_if_t<
+    std::enable_if_t<
         Impl<Sig>::template CallIsValid<std::reference_wrapper<F>>::value>,
-    absl::enable_if_t<Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<
+    std::enable_if_t<Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<
         std::reference_wrapper<F>>::value>>;
 
 // The constraint for checking whether or not a call meets the noexcept
@@ -657,17 +657,17 @@
 // don't treat non-moveable result types correctly. For example this was the
 // case in libc++ before commit c3a24882 (2022-05).
 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true(inv_quals)      \
-  absl::enable_if_t<absl::disjunction<                                       \
+  std::enable_if_t<std::disjunction<                                       \
       std::is_nothrow_invocable_r<                                           \
-          ReturnType, UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, \
+          ReturnType, UnwrapStdReferenceWrapper<std::decay_t<F>> inv_quals, \
           P...>,                                                             \
       std::conjunction<                                                      \
           std::is_nothrow_invocable<                                         \
-              UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, P...>,  \
+              UnwrapStdReferenceWrapper<std::decay_t<F>> inv_quals, P...>,  \
           std::is_same<                                                      \
               ReturnType,                                                    \
               std::invoke_result_t<                                          \
-                  UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals,     \
+                  UnwrapStdReferenceWrapper<std::decay_t<F>> inv_quals,     \
                   P...>>>>::value>
 
 #define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false(inv_quals)
@@ -696,11 +696,11 @@
                                                                                \
     /*SFINAE constraint to check if F is invocable with the proper signature*/ \
     template <class F>                                                         \
-    using CallIsValid = TrueAlias<absl::enable_if_t<absl::disjunction<         \
-        std::is_invocable_r<ReturnType, absl::decay_t<F> inv_quals, P...>,     \
+    using CallIsValid = TrueAlias<std::enable_if_t<std::disjunction<         \
+        std::is_invocable_r<ReturnType, std::decay_t<F> inv_quals, P...>,     \
         std::is_same<                                                          \
             ReturnType,                                                        \
-            std::invoke_result_t<absl::decay_t<F> inv_quals, P...>>>::value>>; \
+            std::invoke_result_t<std::decay_t<F> inv_quals, P...>>>::value>>; \
                                                                                \
     /*SFINAE constraint to check if F is nothrow-invocable when necessary*/    \
     template <class F>                                                         \
@@ -723,7 +723,7 @@
     /*Forward along the in-place construction parameters.*/                    \
     template <class T, class... Args>                                          \
     explicit Impl(absl::in_place_type_t<T>, Args&&... args)                    \
-        : Core(absl::in_place_type<absl::decay_t<T> inv_quals>,                \
+        : Core(absl::in_place_type<std::decay_t<T> inv_quals>,                \
                std::forward<Args>(args)...) {}                                 \
                                                                                \
     /*Raises a fatal error when the AnyInvocable is invoked after a move*/     \
diff --git a/absl/functional/internal/front_binder.h b/absl/functional/internal/front_binder.h
index 62f373f..28a15ce 100644
--- a/absl/functional/internal/front_binder.h
+++ b/absl/functional/internal/front_binder.h
@@ -84,7 +84,7 @@
 };
 
 template <class F, class... BoundArgs>
-using bind_front_t = FrontBinder<decay_t<F>, absl::decay_t<BoundArgs>...>;
+using bind_front_t = FrontBinder<std::decay_t<F>, std::decay_t<BoundArgs>...>;
 
 }  // namespace functional_internal
 ABSL_NAMESPACE_END
diff --git a/absl/functional/internal/function_ref.h b/absl/functional/internal/function_ref.h
index 543b30f..46147e9 100644
--- a/absl/functional/internal/function_ref.h
+++ b/absl/functional/internal/function_ref.h
@@ -47,8 +47,8 @@
 template <typename T>
 struct PassByValue<T, /*IsLValueReference=*/false>
     : std::integral_constant<bool,
-                             absl::is_trivially_copy_constructible<T>::value &&
-                                 absl::is_trivially_copy_assignable<
+                             std::is_trivially_copy_constructible<T>::value &&
+                                 std::is_trivially_copy_assignable<
                                      typename std::remove_cv<T>::type>::value &&
                                  std::is_trivially_destructible<T>::value &&
                                  sizeof(T) <= 2 * sizeof(void*)> {};
diff --git a/absl/hash/hash.h b/absl/hash/hash.h
index 23f4e9d..e2bde0c 100644
--- a/absl/hash/hash.h
+++ b/absl/hash/hash.h
@@ -329,7 +329,7 @@
   // users should not define their own HashState types.
   template <
       typename T,
-      absl::enable_if_t<
+      std::enable_if_t<
           std::is_base_of<hash_internal::HashStateBase<T>, T>::value, int> = 0>
   static HashState Create(T* state) {
     HashState s;
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index 039515a..e83fcae 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -803,8 +803,8 @@
   EXPECT_TRUE(std::is_default_constructible<absl::Hash<int>>::value);
   EXPECT_TRUE(std::is_copy_constructible<absl::Hash<int>>::value);
   EXPECT_TRUE(std::is_move_constructible<absl::Hash<int>>::value);
-  EXPECT_TRUE(absl::is_copy_assignable<absl::Hash<int>>::value);
-  EXPECT_TRUE(absl::is_move_assignable<absl::Hash<int>>::value);
+  EXPECT_TRUE(std::is_copy_assignable<absl::Hash<int>>::value);
+  EXPECT_TRUE(std::is_move_assignable<absl::Hash<int>>::value);
   EXPECT_TRUE(IsHashCallable<int>::value);
   EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value);
 }
@@ -815,8 +815,8 @@
   EXPECT_FALSE(std::is_default_constructible<absl::Hash<X>>::value);
   EXPECT_FALSE(std::is_copy_constructible<absl::Hash<X>>::value);
   EXPECT_FALSE(std::is_move_constructible<absl::Hash<X>>::value);
-  EXPECT_FALSE(absl::is_copy_assignable<absl::Hash<X>>::value);
-  EXPECT_FALSE(absl::is_move_assignable<absl::Hash<X>>::value);
+  EXPECT_FALSE(std::is_copy_assignable<absl::Hash<X>>::value);
+  EXPECT_FALSE(std::is_move_assignable<absl::Hash<X>>::value);
   EXPECT_FALSE(IsHashCallable<X>::value);
 #if !defined(__GNUC__) || defined(__clang__)
   // TODO(b/144368551): As of GCC 8.4 this does not compile.
@@ -891,7 +891,7 @@
 
 template <InvokeTag allowed, InvokeTag... tags>
 struct EnableIfContained
-    : std::enable_if<absl::disjunction<
+    : std::enable_if<std::disjunction<
           std::integral_constant<bool, allowed == tags>...>::value> {};
 
 template <
diff --git a/absl/hash/hash_testing.h b/absl/hash/hash_testing.h
index 509df07..3740ba9 100644
--- a/absl/hash/hash_testing.h
+++ b/absl/hash/hash_testing.h
@@ -281,7 +281,7 @@
 
 template <typename... T>
 struct TypeSet {
-  template <typename U, bool = disjunction<std::is_same<T, U>...>::value>
+  template <typename U, bool = std::disjunction<std::is_same<T, U>...>::value>
   struct Insert {
     using type = TypeSet<U, T...>;
   };
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index a6c8313..ae3d9a2 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -404,7 +404,7 @@
 // Convenience function that combines `hash_state` with the byte representation
 // of `value`.
 template <typename H, typename T,
-          absl::enable_if_t<FitsIn64Bits<T>::value, int> = 0>
+          std::enable_if_t<FitsIn64Bits<T>::value, int> = 0>
 H hash_bytes(H hash_state, const T& value) {
   const unsigned char* start = reinterpret_cast<const unsigned char*>(&value);
   uint64_t v;
@@ -421,7 +421,7 @@
   return CombineRaw()(std::move(hash_state), v);
 }
 template <typename H, typename T,
-          absl::enable_if_t<!FitsIn64Bits<T>::value, int> = 0>
+          std::enable_if_t<!FitsIn64Bits<T>::value, int> = 0>
 H hash_bytes(H hash_state, const T& value) {
   const unsigned char* start = reinterpret_cast<const unsigned char*>(&value);
   return H::combine_contiguous(std::move(hash_state), start, sizeof(value));
@@ -601,7 +601,7 @@
 // for now.
 H
 #else   // _MSC_VER
-typename std::enable_if<absl::conjunction<is_hashable<Ts>...>::value, H>::type
+typename std::enable_if<std::conjunction<is_hashable<Ts>...>::value, H>::type
 #endif  // _MSC_VER
 AbslHashValue(H hash_state, const std::tuple<Ts...>& t) {
   return hash_internal::hash_tuple(std::move(hash_state), t,
@@ -650,7 +650,7 @@
 
 // Support std::wstring, std::u16string and std::u32string.
 template <typename Char, typename Alloc, typename H,
-          typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||
+          typename = std::enable_if_t<std::is_same<Char, wchar_t>::value ||
                                        std::is_same<Char, char16_t>::value ||
                                        std::is_same<Char, char32_t>::value>>
 H AbslHashValue(
@@ -661,7 +661,7 @@
 
 // Support std::wstring_view, std::u16string_view and std::u32string_view.
 template <typename Char, typename H,
-          typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||
+          typename = std::enable_if_t<std::is_same<Char, wchar_t>::value ||
                                        std::is_same<Char, char16_t>::value ||
                                        std::is_same<Char, char32_t>::value>>
 H AbslHashValue(H hash_state, std::basic_string_view<Char> str) {
@@ -680,7 +680,7 @@
 // Support std::filesystem::path. The SFINAE is required because some string
 // types are implicitly convertible to std::filesystem::path.
 template <typename Path, typename H,
-          typename = absl::enable_if_t<
+          typename = std::enable_if_t<
               std::is_same_v<Path, std::filesystem::path>>>
 H AbslHashValue(H hash_state, const Path& path) {
   // This is implemented by deferring to the standard library to compute the
@@ -919,7 +919,7 @@
 
 // AbslHashValue for hashing std::variant
 template <typename H, typename... T>
-typename std::enable_if<conjunction<is_hashable<T>...>::value, H>::type
+typename std::enable_if<std::conjunction<is_hashable<T>...>::value, H>::type
 AbslHashValue(H hash_state, const std::variant<T...>& v) {
   if (!v.valueless_by_exception()) {
     hash_state = std::visit(VariantVisitor<H>{std::move(hash_state)}, v);
@@ -1299,14 +1299,14 @@
   struct UniquelyRepresentedProbe {
     template <typename H, typename T>
     static auto Invoke(H state, const T& value)
-        -> absl::enable_if_t<is_uniquely_represented<T>::value, H> {
+        -> std::enable_if_t<is_uniquely_represented<T>::value, H> {
       return hash_internal::hash_bytes(std::move(state), value);
     }
   };
 
   struct HashValueProbe {
     template <typename H, typename T>
-    static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+    static auto Invoke(H state, const T& value) -> std::enable_if_t<
         std::is_same<H,
                      decltype(AbslHashValue(std::move(state), value))>::value,
         H> {
@@ -1317,7 +1317,7 @@
   struct LegacyHashProbe {
 #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
     template <typename H, typename T>
-    static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+    static auto Invoke(H state, const T& value) -> std::enable_if_t<
         std::is_convertible<
             decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>()(value)),
             size_t>::value,
@@ -1332,7 +1332,7 @@
   struct StdHashProbe {
     template <typename H, typename T>
     static auto Invoke(H state, const T& value)
-        -> absl::enable_if_t<type_traits_internal::IsHashable<T>::value, H> {
+        -> std::enable_if_t<type_traits_internal::IsHashable<T>::value, H> {
       return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
     }
   };
@@ -1354,7 +1354,7 @@
   // Probe each implementation in order.
   // disjunction provides short circuiting wrt instantiation.
   template <typename T>
-  using Apply = absl::disjunction<         //
+  using Apply = std::disjunction<         //
       Probe<WeaklyMixedIntegerProbe, T>,   //
       Probe<UniquelyRepresentedProbe, T>,  //
       Probe<HashValueProbe, T>,            //
@@ -1370,8 +1370,8 @@
 class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
   template <typename T>
   using IntegralFastPath =
-      conjunction<std::is_integral<T>, is_uniquely_represented<T>,
-                  FitsIn64Bits<T>>;
+      std::conjunction<std::is_integral<T>, is_uniquely_represented<T>,
+                       FitsIn64Bits<T>>;
 
  public:
   // Move only
@@ -1399,13 +1399,13 @@
   // Otherwise we would be instantiating and calling dozens of functions for
   // something that is just one multiplication and a couple xor's.
   // The result should be the same as running the whole algorithm, but faster.
-  template <typename T, absl::enable_if_t<IntegralFastPath<T>::value, int> = 0>
+  template <typename T, std::enable_if_t<IntegralFastPath<T>::value, int> = 0>
   static size_t hash_with_seed(T value, size_t seed) {
     return static_cast<size_t>(
         CombineRawImpl(seed, static_cast<std::make_unsigned_t<T>>(value)));
   }
 
-  template <typename T, absl::enable_if_t<!IntegralFastPath<T>::value, int> = 0>
+  template <typename T, std::enable_if_t<!IntegralFastPath<T>::value, int> = 0>
   static size_t hash_with_seed(const T& value, size_t seed) {
     return static_cast<size_t>(combine(MixingHashState{seed}, value).state_);
   }
@@ -1527,7 +1527,7 @@
 
 template <typename T>
 struct Hash
-    : absl::conditional_t<is_hashable<T>::value, HashImpl<T>, PoisonedHash> {};
+    : std::conditional_t<is_hashable<T>::value, HashImpl<T>, PoisonedHash> {};
 
 template <typename H>
 template <typename T, typename... Ts>
diff --git a/absl/hash/internal/spy_hash_state.h b/absl/hash/internal/spy_hash_state.h
index 80c9767..0eb9ffe 100644
--- a/absl/hash/internal/spy_hash_state.h
+++ b/absl/hash/internal/spy_hash_state.h
@@ -22,6 +22,7 @@
 #include <optional>
 #include <ostream>
 #include <string>
+#include <type_traits>
 #include <vector>
 
 #include "absl/hash/hash.h"
@@ -269,7 +270,7 @@
 template <
     typename T, typename U,
     // Only trigger for when (T != U),
-    typename = absl::enable_if_t<!std::is_same<T, U>::value>,
+    typename = std::enable_if_t<!std::is_same<T, U>::value>,
     // This statement works in two ways:
     //  - First, it instantiates RunOnStartup and forces the initialization of
     //    `run`, which set the global variable.
diff --git a/absl/log/BUILD.bazel b/absl/log/BUILD.bazel
index ec2fde9..e6793b1 100644
--- a/absl/log/BUILD.bazel
+++ b/absl/log/BUILD.bazel
@@ -209,6 +209,7 @@
         "//absl/strings",
         "//absl/strings:internal",
         "//absl/types:optional",
+        "//absl/types:source_location",
         "//absl/utility",
     ],
 )
@@ -404,6 +405,7 @@
         "//absl/log/internal:test_helpers",
         "//absl/log/internal:test_matchers",
         "//absl/strings",
+        "//absl/types:source_location",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
     ],
@@ -564,6 +566,7 @@
         "//absl/log/internal:test_helpers",
         "//absl/log/internal:test_matchers",
         "//absl/strings",
+        "//absl/types:source_location",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
     ],
@@ -584,6 +587,7 @@
         "//absl/log/internal:test_matchers",
         "//absl/strings",
         "//absl/time",
+        "//absl/types:source_location",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
     ],
diff --git a/absl/log/CMakeLists.txt b/absl/log/CMakeLists.txt
index 609f432..b271d09 100644
--- a/absl/log/CMakeLists.txt
+++ b/absl/log/CMakeLists.txt
@@ -215,6 +215,7 @@
     absl::memory
     absl::nullability
     absl::raw_logging_internal
+    absl::source_location
     absl::span
     absl::strerror
     absl::strings
@@ -632,6 +633,7 @@
     absl::absl_log
     absl::log_severity
     absl::optional
+    absl::source_location
     absl::strings
     absl::strings_internal
     absl::utility
@@ -1079,6 +1081,7 @@
     absl::log_streamer
     absl::log_severity
     absl::scoped_mock_log
+    absl::source_location
     absl::strings
     GTest::gmock_main
 )
@@ -1099,6 +1102,7 @@
     absl::log_internal_test_matchers
     absl::log_sink
     absl::scoped_mock_log
+    absl::source_location
     absl::strings
     absl::time
     GTest::gmock_main
diff --git a/absl/log/internal/BUILD.bazel b/absl/log/internal/BUILD.bazel
index 6635118..ebacbc1 100644
--- a/absl/log/internal/BUILD.bazel
+++ b/absl/log/internal/BUILD.bazel
@@ -216,6 +216,7 @@
         "//absl/strings",
         "//absl/strings:internal",
         "//absl/time",
+        "//absl/types:source_location",
         "//absl/types:span",
     ],
 )
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h
index 5b6eed3..7e2a86a 100644
--- a/absl/log/internal/log_message.h
+++ b/absl/log/internal/log_message.h
@@ -50,6 +50,8 @@
 #include "absl/strings/has_absl_stringify.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/time.h"
+#include "absl/types/source_location.h"
+#include "absl/types/span.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -86,6 +88,11 @@
   // Overrides the location inferred from the callsite.  The string pointed to
   // by `file` must be valid until the end of the statement.
   LogMessage& AtLocation(absl::string_view file, int line);
+  // `loc` doesn't default to `absl::SourceLocation::current()` here since the
+  // callsite is already the default location for `LOG` statements.
+  LogMessage& AtLocation(absl::SourceLocation loc) {
+    return AtLocation(loc.file_name(), static_cast<int>(loc.line()));
+  }
   // Omits the prefix from this line.  The prefix includes metadata about the
   // logged data such as source code location and timestamp.
   LogMessage& NoPrefix();
diff --git a/absl/log/internal/nullstream.h b/absl/log/internal/nullstream.h
index c87f9aa..4eae52e 100644
--- a/absl/log/internal/nullstream.h
+++ b/absl/log/internal/nullstream.h
@@ -125,4 +125,4 @@
 ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_LOG_INTERNAL_GLOBALS_H_
+#endif  // ABSL_LOG_INTERNAL_NULLSTREAM_H_
diff --git a/absl/log/log_modifier_methods_test.cc b/absl/log/log_modifier_methods_test.cc
index 7893557..1c7c35d 100644
--- a/absl/log/log_modifier_methods_test.cc
+++ b/absl/log/log_modifier_methods_test.cc
@@ -28,6 +28,7 @@
 #include "absl/strings/match.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/time.h"
+#include "absl/types/source_location.h"
 
 namespace {
 #if GTEST_HAS_DEATH_TEST
@@ -88,6 +89,23 @@
       << "hello world";
 }
 
+TEST(TailCallsModifiesTest, AtLocationSourceLocation) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+  EXPECT_CALL(test_sink, Send).Times(0);
+
+  const int log_line = __LINE__ + 1;
+  constexpr absl::SourceLocation loc = absl::SourceLocation::current();
+  auto do_log = [loc] { LOG(INFO).AtLocation(loc) << "hello world"; };
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(SourceFilename(Eq(__FILE__)),
+                         SourceBasename(Eq("log_modifier_methods_test.cc")),
+                         SourceLine(Eq(log_line)))));
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
 TEST(TailCallsModifiesTest, NoPrefix) {
   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
   EXPECT_CALL(test_sink, Send).Times(0);
diff --git a/absl/log/log_streamer.h b/absl/log/log_streamer.h
index 32c3402..213e352 100644
--- a/absl/log/log_streamer.h
+++ b/absl/log/log_streamer.h
@@ -35,6 +35,7 @@
 #include "absl/strings/internal/ostringstream.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
+#include "absl/types/source_location.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
@@ -87,6 +88,10 @@
     // To match `LOG`'s defaults:
     stream_->setf(std::ios_base::showbase | std::ios_base::boolalpha);
   }
+  explicit LogStreamer(
+      absl::LogSeverity severity,
+      absl::SourceLocation loc = absl::SourceLocation::current())
+      : LogStreamer(severity, loc.file_name(), static_cast<int>(loc.line())) {}
 
   // A moved-from `absl::LogStreamer` does not `LOG` when destroyed,
   // and a program that streams into one has undefined behavior.
@@ -176,6 +181,27 @@
   return absl::LogStreamer(absl::kLogDebugFatal, file, line);
 }
 
+inline LogStreamer LogInfoStreamer(
+    absl::SourceLocation loc = absl::SourceLocation::current()) {
+  return absl::LogStreamer(absl::LogSeverity::kInfo, loc);
+}
+inline LogStreamer LogWarningStreamer(
+    absl::SourceLocation loc = absl::SourceLocation::current()) {
+  return absl::LogStreamer(absl::LogSeverity::kWarning, loc);
+}
+inline LogStreamer LogErrorStreamer(
+    absl::SourceLocation loc = absl::SourceLocation::current()) {
+  return absl::LogStreamer(absl::LogSeverity::kError, loc);
+}
+inline LogStreamer LogFatalStreamer(
+    absl::SourceLocation loc = absl::SourceLocation::current()) {
+  return absl::LogStreamer(absl::LogSeverity::kFatal, loc);
+}
+inline LogStreamer LogDebugFatalStreamer(
+    absl::SourceLocation loc = absl::SourceLocation::current()) {
+  return absl::LogStreamer(absl::kLogDebugFatal, loc);
+}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/log/log_streamer_test.cc b/absl/log/log_streamer_test.cc
index f226fef..e45a293 100644
--- a/absl/log/log_streamer_test.cc
+++ b/absl/log/log_streamer_test.cc
@@ -30,6 +30,7 @@
 #include "absl/log/log.h"
 #include "absl/log/scoped_mock_log.h"
 #include "absl/strings/string_view.h"
+#include "absl/types/source_location.h"
 
 namespace {
 using ::absl::log_internal::DeathTestExpectedLogging;
@@ -448,4 +449,21 @@
   LOG(INFO) << false << std::hex << 0xdeadbeef;
 }
 
+TEST(LogStreamerTest, AtSourceLocation) {
+  const int log_line = __LINE__ + 2;
+  auto do_log = [] {
+    WriteToStream("foo", &absl::LogInfoStreamer().stream());  //
+  };
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+  EXPECT_CALL(test_sink, Send).Times(0);
+
+  EXPECT_CALL(test_sink,
+              Send(AllOf(SourceFilename(
+                             Eq(absl::SourceLocation::current().file_name())),
+                         SourceLine(Eq(log_line)))));
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
 }  // namespace
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index f0f7aea..bc5d654 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -134,7 +134,7 @@
 template <typename T>
 typename memory_internal::MakeUniqueResult<T>::array
     make_unique_for_overwrite(size_t n) {
-  return std::unique_ptr<T>(new typename absl::remove_extent_t<T>[n]);
+  return std::unique_ptr<T>(new typename std::remove_extent_t<T>[n]);
 }
 
 // `absl::make_unique_for_overwrite` overload for an array T[N] of known bounds.
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 2c651f2..9013aea 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -45,6 +45,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
+#include "absl/base/macros.h"
 
 #ifdef __cpp_lib_span
 #include <span>  // NOLINT(build/c++20)
@@ -115,38 +116,114 @@
 //
 // See the documentation for the STL <type_traits> header for more information:
 // https://en.cppreference.com/w/cpp/header/type_traits
-using std::add_const_t;
-using std::add_cv_t;
-using std::add_lvalue_reference_t;
-using std::add_pointer_t;
-using std::add_rvalue_reference_t;
-using std::add_volatile_t;
-using std::common_type_t;
-using std::conditional_t;
-using std::conjunction;
-using std::decay_t;
-using std::enable_if_t;
-using std::disjunction;
-using std::is_copy_assignable;
-using std::is_function;
-using std::is_move_assignable;
-using std::is_trivially_copy_assignable;
-using std::is_trivially_copy_constructible;
-using std::is_trivially_default_constructible;
-using std::is_trivially_destructible;
-using std::is_trivially_move_assignable;
-using std::is_trivially_move_constructible;
-using std::make_signed_t;
-using std::make_unsigned_t;
-using std::negation;
-using std::remove_all_extents_t;
-using std::remove_const_t;
-using std::remove_cv_t;
-using std::remove_extent_t;
-using std::remove_pointer_t;
-using std::remove_reference_t;
-using std::remove_volatile_t;
-using std::underlying_type_t;
+
+template <class T>
+using add_const_t ABSL_DEPRECATE_AND_INLINE() = std::add_const_t<T>;
+
+template <class T>
+using add_cv_t ABSL_DEPRECATE_AND_INLINE() = std::add_cv_t<T>;
+
+template <class T>
+using add_lvalue_reference_t ABSL_DEPRECATE_AND_INLINE() =
+    std::add_lvalue_reference_t<T>;
+
+template <class T>
+using add_pointer_t ABSL_DEPRECATE_AND_INLINE() = std::add_pointer_t<T>;
+
+template <class T>
+using add_rvalue_reference_t ABSL_DEPRECATE_AND_INLINE() =
+    std::add_rvalue_reference_t<T>;
+
+template <class T>
+using add_volatile_t ABSL_DEPRECATE_AND_INLINE() = std::add_volatile_t<T>;
+
+template <class... T>
+using common_type_t ABSL_DEPRECATE_AND_INLINE() = std::common_type_t<T...>;
+
+template <bool C, class T, class F>
+using conditional_t ABSL_DEPRECATE_AND_INLINE() = std::conditional_t<C, T, F>;
+
+template <class... T>
+using conjunction ABSL_DEPRECATE_AND_INLINE() = std::conjunction<T...>;
+
+template <class T>
+using decay_t ABSL_DEPRECATE_AND_INLINE() = std::decay_t<T>;
+
+template <bool C, class T = void>
+using enable_if_t ABSL_DEPRECATE_AND_INLINE() = std::enable_if_t<C, T>;
+
+template <class... T>
+using disjunction ABSL_DEPRECATE_AND_INLINE() = std::disjunction<T...>;
+
+template <class T>
+using is_copy_assignable ABSL_DEPRECATE_AND_INLINE() =
+    std::is_copy_assignable<T>;
+
+template <class T>
+using is_function ABSL_DEPRECATE_AND_INLINE() = std::is_function<T>;
+
+template <class T>
+using is_move_assignable ABSL_DEPRECATE_AND_INLINE() =
+    std::is_move_assignable<T>;
+
+template <class T>
+using is_trivially_copy_assignable ABSL_DEPRECATE_AND_INLINE() =
+    std::is_trivially_copy_assignable<T>;
+
+template <class T>
+using is_trivially_copy_constructible ABSL_DEPRECATE_AND_INLINE() =
+    std::is_trivially_copy_constructible<T>;
+
+template <class T>
+using is_trivially_default_constructible ABSL_DEPRECATE_AND_INLINE() =
+    std::is_trivially_default_constructible<T>;
+
+template <class T>
+using is_trivially_destructible ABSL_DEPRECATE_AND_INLINE() =
+    std::is_trivially_destructible<T>;
+
+template <class T>
+using is_trivially_move_assignable ABSL_DEPRECATE_AND_INLINE() =
+    std::is_trivially_move_assignable<T>;
+
+template <class T>
+using is_trivially_move_constructible ABSL_DEPRECATE_AND_INLINE() =
+    std::is_trivially_move_constructible<T>;
+
+template <class T>
+using make_signed_t ABSL_DEPRECATE_AND_INLINE() = std::make_signed_t<T>;
+
+template <class T>
+using make_unsigned_t ABSL_DEPRECATE_AND_INLINE() = std::make_unsigned_t<T>;
+
+template <class T>
+using negation ABSL_DEPRECATE_AND_INLINE() = std::negation<T>;
+
+template <class T>
+using remove_all_extents_t ABSL_DEPRECATE_AND_INLINE() =
+    std::remove_all_extents_t<T>;
+
+template <class T>
+using remove_const_t ABSL_DEPRECATE_AND_INLINE() = std::remove_const_t<T>;
+
+template <class T>
+using remove_cv_t ABSL_DEPRECATE_AND_INLINE() = std::remove_cv_t<T>;
+
+template <class T>
+using remove_extent_t ABSL_DEPRECATE_AND_INLINE() = std::remove_extent_t<T>;
+
+template <class T>
+using remove_pointer_t ABSL_DEPRECATE_AND_INLINE() = std::remove_pointer_t<T>;
+
+template <class T>
+using remove_reference_t ABSL_DEPRECATE_AND_INLINE() =
+    std::remove_reference_t<T>;
+
+template <class T>
+using remove_volatile_t ABSL_DEPRECATE_AND_INLINE() = std::remove_volatile_t<T>;
+
+template <class T>
+using underlying_type_t ABSL_DEPRECATE_AND_INLINE() = std::underlying_type_t<T>;
 
 #if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L
 template <typename T>
@@ -218,7 +295,7 @@
 template <typename Key>
 struct IsHashable<
     Key,
-    absl::enable_if_t<std::is_convertible<
+    std::enable_if_t<std::is_convertible<
         decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
         std::size_t>::value>> : std::true_type {};
 
@@ -243,7 +320,7 @@
     static_assert(
         std::is_copy_constructible<std::hash<Key>>::value,
         "std::hash<Key> must be copy constructible when it is enabled");
-    static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
+    static_assert(std::is_copy_assignable<std::hash<Key>>::value,
                   "std::hash<Key> must be copy assignable when it is enabled");
     // is_destructible is unchecked as it's implied by each of the
     // is_constructible checks.
@@ -306,7 +383,7 @@
 //
 // Performs the swap idiom from a namespace where valid candidates may only be
 // found in `std` or via ADL.
-template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
+template <class T, std::enable_if_t<IsSwappable<T>::value, int> = 0>
 void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
   swap(lhs, rhs);
 }
@@ -475,7 +552,7 @@
 struct IsOwnerImpl<
     T,
     std::enable_if_t<std::is_class<typename T::absl_internal_is_view>::value>>
-    : absl::negation<typename T::absl_internal_is_view> {};
+    : std::negation<typename T::absl_internal_is_view> {};
 
 // A trait to determine whether a type is an owner.
 // Do *not* depend on the correctness of this trait for correct code behavior.
@@ -555,7 +632,7 @@
 // Until then, we consider an assignment from an "owner" (such as std::string)
 // to a "view" (such as std::string_view) to be a lifetime-bound assignment.
 template <typename T, typename U>
-using IsLifetimeBoundAssignment = absl::conjunction<
+using IsLifetimeBoundAssignment = std::conjunction<
     std::integral_constant<bool, !std::is_lvalue_reference<U>::value>,
     IsOwner<absl::remove_cvref_t<U>>, IsView<absl::remove_cvref_t<T>>>;
 
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index 9a8262d..6d0085c 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -33,8 +33,8 @@
 
 template <typename T>
 using IsOwnerAndNotView =
-    absl::conjunction<absl::type_traits_internal::IsOwner<T>,
-                      absl::negation<absl::type_traits_internal::IsView<T>>>;
+    std::conjunction<absl::type_traits_internal::IsOwner<T>,
+                      std::negation<absl::type_traits_internal::IsView<T>>>;
 
 static_assert(
     IsOwnerAndNotView<std::pair<std::vector<int>, std::string>>::value,
@@ -70,13 +70,13 @@
 
 struct TypeWithBarFunction {
   template <class T,
-            absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0>
+            std::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0>
   ReturnType bar(T&&, const StructB&, StructC&&) &&;  // NOLINT
 };
 
 struct TypeWithBarFunctionAndConvertibleReturnType {
   template <class T,
-            absl::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0>
+            std::enable_if_t<std::is_same<T&&, StructA&>::value, int> = 0>
   ConvertibleToReturnType bar(T&&, const StructB&, StructC&&) &&;  // NOLINT
 };
 
@@ -160,19 +160,19 @@
 
 struct GetTypeT {
   template <typename T,
-            absl::enable_if_t<std::is_same<T, TypeA>::value, int> = 0>
+            std::enable_if_t<std::is_same<T, TypeA>::value, int> = 0>
   TypeEnum operator()(Wrap<T>) const {
     return TypeEnum::A;
   }
 
   template <typename T,
-            absl::enable_if_t<std::is_same<T, TypeB>::value, int> = 0>
+            std::enable_if_t<std::is_same<T, TypeB>::value, int> = 0>
   TypeEnum operator()(Wrap<T>) const {
     return TypeEnum::B;
   }
 
   template <typename T,
-            absl::enable_if_t<std::is_same<T, TypeC>::value, int> = 0>
+            std::enable_if_t<std::is_same<T, TypeC>::value, int> = 0>
   TypeEnum operator()(Wrap<T>) const {
     return TypeEnum::C;
   }
diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc
index 77ee63c..336db78 100644
--- a/absl/numeric/int128_test.cc
+++ b/absl/numeric/int128_test.cc
@@ -93,11 +93,11 @@
 #endif  // ABSL_HAVE_INTRINSIC_INT128
 
 TEST(Uint128, TrivialTraitsTest) {
-  static_assert(absl::is_trivially_default_constructible<absl::uint128>::value,
+  static_assert(std::is_trivially_default_constructible<absl::uint128>::value,
                 "");
-  static_assert(absl::is_trivially_copy_constructible<absl::uint128>::value,
+  static_assert(std::is_trivially_copy_constructible<absl::uint128>::value,
                 "");
-  static_assert(absl::is_trivially_copy_assignable<absl::uint128>::value, "");
+  static_assert(std::is_trivially_copy_assignable<absl::uint128>::value, "");
   static_assert(std::is_trivially_destructible<absl::uint128>::value, "");
 }
 
@@ -619,10 +619,10 @@
 #endif  // ABSL_HAVE_INTRINSIC_INT128
 
 TEST(Int128, TrivialTraitsTest) {
-  static_assert(absl::is_trivially_default_constructible<absl::int128>::value,
+  static_assert(std::is_trivially_default_constructible<absl::int128>::value,
                 "");
-  static_assert(absl::is_trivially_copy_constructible<absl::int128>::value, "");
-  static_assert(absl::is_trivially_copy_assignable<absl::int128>::value, "");
+  static_assert(std::is_trivially_copy_constructible<absl::int128>::value, "");
+  static_assert(std::is_trivially_copy_assignable<absl::int128>::value, "");
   static_assert(std::is_trivially_destructible<absl::int128>::value, "");
 }
 
diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel
index 8986211..28f6872 100644
--- a/absl/random/BUILD.bazel
+++ b/absl/random/BUILD.bazel
@@ -128,13 +128,14 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":mocking_access",
         ":random",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:fast_type_id",
         "//absl/meta:type_traits",
-        "//absl/random/internal:distribution_caller",
         "//absl/random/internal:fast_uniform_bits",
+        "//absl/random/internal:traits",
     ],
 )
 
@@ -160,6 +161,7 @@
     ],
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":mocking_access",
         ":random",
         "//absl/base:config",
         "//absl/base:fast_type_id",
@@ -171,6 +173,16 @@
     ],
 )
 
+cc_library(
+    name = "mocking_access",
+    hdrs = ["mocking_access.h"],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:fast_type_id",
+        "//absl/meta:type_traits",
+    ],
+)
+
 cc_test(
     name = "bernoulli_distribution_test",
     size = "small",
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index 7382b0d..4a13e84 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -44,9 +44,10 @@
   DEPS
     absl::config
     absl::core_headers
-    absl::random_internal_distribution_caller
     absl::random_internal_fast_uniform_bits
     absl::type_traits
+    absl::random_mocking_access
+    absl::random_internal_traits
 )
 
 absl_cc_test(
@@ -68,6 +69,21 @@
     GTest::gtest_main
 )
 
+absl_cc_library(
+  NAME
+    random_mocking_access
+  HDRS
+    "mocking_access.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::fast_type_id
+    absl::type_traits
+)
+
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
@@ -82,6 +98,7 @@
     absl::config
     absl::fast_type_id
     absl::optional
+    absl::random_mocking_access
 )
 
 # Internal-only target, do not depend on directly.
@@ -118,6 +135,7 @@
     absl::flat_hash_map
     absl::raw_logging_internal
     absl::random_internal_mock_helpers
+    absl::random_mocking_access
     absl::random_random
     absl::type_traits
     absl::utility
@@ -536,6 +554,9 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::config
+    absl::type_traits
+    absl::bits
+    absl::int128
 )
 
 # Internal-only target, do not depend on directly.
@@ -553,6 +574,7 @@
     absl::utility
     absl::fast_type_id
     absl::type_traits
+    absl::random_mocking_access
 )
 
 # Internal-only target, do not depend on directly.
diff --git a/absl/random/benchmarks.cc b/absl/random/benchmarks.cc
index 958dfe4..4cb16e6 100644
--- a/absl/random/benchmarks.cc
+++ b/absl/random/benchmarks.cc
@@ -97,7 +97,7 @@
 template <typename Engine, typename SSeq = DefaultConstructorSeedSeq>
 Engine make_engine() {
   constexpr bool use_default_initialization =
-    std::is_same_v<SSeq, DefaultConstructorSeedSeq>;
+      std::is_same_v<SSeq, DefaultConstructorSeedSeq>;
   if constexpr (use_default_initialization) {
     return Engine();
   } else {
diff --git a/absl/random/beta_distribution.h b/absl/random/beta_distribution.h
index a362345..bedeca6 100644
--- a/absl/random/beta_distribution.h
+++ b/absl/random/beta_distribution.h
@@ -282,7 +282,7 @@
   using random_internal::GeneratePositiveTag;
   using random_internal::GenerateRealFromBits;
   using real_type =
-      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+      std::conditional_t<std::is_same<RealType, float>::value, float, double>;
 
   // Based on Joehnk, M. D. Erzeugung von betaverteilten und gammaverteilten
   // Zufallszahlen. Metrika 8.1 (1964): 5-15.
@@ -340,7 +340,7 @@
   using random_internal::GeneratePositiveTag;
   using random_internal::GenerateRealFromBits;
   using real_type =
-      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+      std::conditional_t<std::is_same<RealType, float>::value, float, double>;
 
   // Based on Cheng, Russell CH. Generating beta variates with nonintegral
   // shape parameters. Communications of the ACM 21.4 (1978): 317-322.
diff --git a/absl/random/bit_gen_ref.h b/absl/random/bit_gen_ref.h
index dfce2c4..262eb9a 100644
--- a/absl/random/bit_gen_ref.h
+++ b/absl/random/bit_gen_ref.h
@@ -27,41 +27,17 @@
 #include <cstdint>
 #include <limits>
 #include <type_traits>
-#include <utility>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/fast_type_id.h"
 #include "absl/meta/type_traits.h"
-#include "absl/random/internal/distribution_caller.h"
 #include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/traits.h"
+#include "absl/random/mocking_access.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
-namespace random_internal {
-
-template <typename URBG, typename = void, typename = void, typename = void>
-struct is_urbg : std::false_type {};
-
-template <typename URBG>
-struct is_urbg<
-    URBG,
-    absl::enable_if_t<std::is_same<
-        typename URBG::result_type,
-        typename std::decay<decltype((URBG::min)())>::type>::value>,
-    absl::enable_if_t<std::is_same<
-        typename URBG::result_type,
-        typename std::decay<decltype((URBG::max)())>::type>::value>,
-    absl::enable_if_t<std::is_same<
-        typename URBG::result_type,
-        typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
-    : std::true_type {};
-
-template <typename>
-struct DistributionCaller;
-class MockHelpers;
-
-}  // namespace random_internal
 
 // -----------------------------------------------------------------------------
 // absl::BitGenRef
@@ -87,24 +63,18 @@
 //    }
 //
 class BitGenRef {
-  // SFINAE to detect whether the URBG type includes a member matching
-  // bool InvokeMock(key_id, args_tuple*, result*).
-  //
-  // These live inside BitGenRef so that they have friend access
-  // to MockingBitGen. (see similar methods in DistributionCaller).
   template <template <class...> class Trait, class AlwaysVoid, class... Args>
   struct detector : std::false_type {};
   template <template <class...> class Trait, class... Args>
   struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
       : std::true_type {};
 
-  template <class T>
-  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
-      std::declval<FastTypeIdType>(), std::declval<void*>(),
-      std::declval<void*>()));
+  template <typename T>
+  using has_conversion_operator_t =
+      decltype(std::declval<T>().operator BitGenRef());
 
   template <typename T>
-  using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
+  using HasConversionOperator = detector<has_conversion_operator_t, void, T>;
 
  public:
   BitGenRef(const BitGenRef&) = default;
@@ -112,23 +82,28 @@
   BitGenRef& operator=(const BitGenRef&) = default;
   BitGenRef& operator=(BitGenRef&&) = default;
 
-  template <
-      typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
-      typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
-                                  random_internal::is_urbg<URBG>::value &&
-                                  !HasInvokeMock<URBG>::value)>* = nullptr>
+  template <typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
+            typename std::enable_if_t<
+                (!std::is_same<URBG, BitGenRef>::value &&
+                 !std::is_base_of<BitGenRef, URBG>::value &&
+                 !HasConversionOperator<URBG>::value &&
+                 random_internal::is_urbg<URBG>::value &&
+                 !RandomMockingAccess::HasInvokeMock<URBG>::value)>* = nullptr>
   BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT
       : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
         mock_call_(NotAMock),
         generate_impl_fn_(ImplFn<URBG>) {}
 
   template <typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
-            typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
-                                        random_internal::is_urbg<URBG>::value &&
-                                        HasInvokeMock<URBG>::value)>* = nullptr>
+            typename std::enable_if_t<
+                (!std::is_same<URBG, BitGenRef>::value &&
+                 !std::is_base_of<BitGenRef, URBG>::value &&
+                 !HasConversionOperator<URBG>::value &&
+                 random_internal::is_urbg<URBG>::value &&
+                 RandomMockingAccess::HasInvokeMock<URBG>::value)>* = nullptr>
   BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT
       : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
-        mock_call_(&MockCall<URBG>),
+        mock_call_(MockCall<URBG>),
         generate_impl_fn_(ImplFn<URBG>) {}
 
   using result_type = uint64_t;
@@ -157,10 +132,10 @@
 
   // Get a type-erased InvokeMock pointer.
   template <typename URBG>
-  static bool MockCall(uintptr_t gen_ptr, FastTypeIdType key_id, void* result,
-                       void* arg_tuple) {
-    return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(key_id, result,
-                                                        arg_tuple);
+  static bool MockCall(uintptr_t gen_ptr, FastTypeIdType key_id,
+                       void* args_tuple, void* result) {
+    return RandomMockingAccess::InvokeMock(reinterpret_cast<URBG*>(gen_ptr),
+                                           key_id, args_tuple, result);
   }
   static bool NotAMock(uintptr_t, FastTypeIdType, void*, void*) {
     return false;
@@ -176,9 +151,7 @@
   mock_call_fn mock_call_;
   impl_fn generate_impl_fn_;
 
-  template <typename>
-  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock
-  friend class ::absl::random_internal::MockHelpers;          // for InvokeMock
+  friend class ::absl::RandomMockingAccess;  // for InvokeMock
 };
 
 ABSL_NAMESPACE_END
diff --git a/absl/random/bit_gen_ref_test.cc b/absl/random/bit_gen_ref_test.cc
index d581352..d04ac3a 100644
--- a/absl/random/bit_gen_ref_test.cc
+++ b/absl/random/bit_gen_ref_test.cc
@@ -17,6 +17,7 @@
 
 #include <cstdint>
 #include <random>
+#include <type_traits>
 #include <vector>
 
 #include "gmock/gmock.h"
@@ -102,6 +103,48 @@
   absl::BitGenRef gen_ref(const_gen);
   EXPECT_EQ(FnTest(gen_ref), 42);  // Copy
 }
+
+struct MinStdRand {
+  // The URBG just returns 0.
+  using result_type = absl::BitGen::result_type;
+  static constexpr result_type(min)() { return (absl::BitGen::min)(); }
+  static constexpr result_type(max)() { return (absl::BitGen::max)(); }
+  result_type operator()() { return 0; }
+
+  // Implicit conversions allow passing MinStdRand to functions taking
+  // absl::BitGenRef as well as explicitly constructing an absl::BitGenRef from
+  // a MinStdRand.
+  operator absl::BitGenRef() const {
+    conversion_count++;
+    return absl::BitGenRef(minstd_gen);
+  }
+
+  std::minstd_rand minstd_gen;
+  mutable int conversion_count = 0;
+};
+
+TEST(BitGenRefTest, IsConvertibleTest) {
+  // Verify that MinStdRandBitGen is convertible to absl::BitGenRef.
+  EXPECT_TRUE((std::is_convertible<MinStdRand, absl::BitGenRef>::value));
+
+  // Explicit construction should trigger the conversion.
+  {
+    MinStdRand minstd;
+    absl::BitGenRef gen_ref(minstd);
+    EXPECT_EQ(minstd.conversion_count, 1);
+    (void)gen_ref;
+  }
+
+  // Calling a function that accepts absl::BitGenRef should trigger the
+  // conversion. This tests implicit conversion.
+  {
+    MinStdRand minstd;
+    auto result = FnTest(minstd);
+    EXPECT_EQ(minstd.conversion_count, 1);
+    EXPECT_GE(result, 1);
+  }
+}
+
 }  // namespace
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/distributions.h b/absl/random/distributions.h
index dced895..01dc978 100644
--- a/absl/random/distributions.h
+++ b/absl/random/distributions.h
@@ -117,11 +117,11 @@
 //   auto x = absl::Uniform<float>(bitgen, 0, 1);
 //
 template <typename R = void, typename TagType, typename URBG>
-typename absl::enable_if_t<!std::is_same<R, void>::value, R>  //
+typename std::enable_if_t<!std::is_same<R, void>::value, R>  //
 Uniform(TagType tag,
         URBG&& urbg,  // NOLINT(runtime/references)
         R lo, R hi) {
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = random_internal::UniformDistributionWrapper<R>;
 
   auto a = random_internal::uniform_lower_bound(tag, lo, hi);
@@ -137,10 +137,10 @@
 // Overload of `Uniform()` using the default closed-open interval of [lo, hi),
 // and returning values of type `T`
 template <typename R = void, typename URBG>
-typename absl::enable_if_t<!std::is_same<R, void>::value, R>  //
+typename std::enable_if_t<!std::is_same<R, void>::value, R>  //
 Uniform(URBG&& urbg,  // NOLINT(runtime/references)
         R lo, R hi) {
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = random_internal::UniformDistributionWrapper<R>;
   constexpr auto tag = absl::IntervalClosedOpen;
 
@@ -159,12 +159,12 @@
 // correctly from the passed types.
 template <typename R = void, typename TagType, typename URBG, typename A,
           typename B>
-typename absl::enable_if_t<std::is_same<R, void>::value,
+typename std::enable_if_t<std::is_same<R, void>::value,
                            random_internal::uniform_inferred_return_t<A, B>>
 Uniform(TagType tag,
         URBG&& urbg,  // NOLINT(runtime/references)
         A lo, B hi) {
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
   using distribution_t = random_internal::UniformDistributionWrapper<return_t>;
 
@@ -183,11 +183,11 @@
 // default closed-open interval of [lo, hi). Note that a compile-error will
 // result if the return type cannot be deduced correctly from the passed types.
 template <typename R = void, typename URBG, typename A, typename B>
-typename absl::enable_if_t<std::is_same<R, void>::value,
+typename std::enable_if_t<std::is_same<R, void>::value,
                            random_internal::uniform_inferred_return_t<A, B>>
 Uniform(URBG&& urbg,  // NOLINT(runtime/references)
         A lo, B hi) {
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
   using distribution_t = random_internal::UniformDistributionWrapper<return_t>;
 
@@ -206,9 +206,9 @@
 // Overload of Uniform() using the minimum and maximum values of a given type
 // `T` (which must be unsigned), returning a value of type `unsigned T`
 template <typename R, typename URBG>
-typename absl::enable_if_t<!std::numeric_limits<R>::is_signed, R>  //
+typename std::enable_if_t<!std::numeric_limits<R>::is_signed, R>  //
 Uniform(URBG&& urbg) {  // NOLINT(runtime/references)
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = random_internal::UniformDistributionWrapper<R>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
@@ -238,7 +238,7 @@
 template <typename URBG>
 bool Bernoulli(URBG&& urbg,  // NOLINT(runtime/references)
                double p) {
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = absl::bernoulli_distribution;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
@@ -270,7 +270,7 @@
       "Template-argument 'RealType' must be a floating-point type, in "
       "absl::Beta<RealType, URBG>(...)");
 
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = typename absl::beta_distribution<RealType>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
@@ -302,7 +302,7 @@
       "Template-argument 'RealType' must be a floating-point type, in "
       "absl::Exponential<RealType, URBG>(...)");
 
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = typename absl::exponential_distribution<RealType>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
@@ -333,7 +333,7 @@
       "Template-argument 'RealType' must be a floating-point type, in "
       "absl::Gaussian<RealType, URBG>(...)");
 
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = typename absl::gaussian_distribution<RealType>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
@@ -375,7 +375,7 @@
                 "Template-argument 'IntType' must be an integral type, in "
                 "absl::LogUniform<IntType, URBG>(...)");
 
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = typename absl::log_uniform_int_distribution<IntType>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
@@ -405,7 +405,7 @@
                 "Template-argument 'IntType' must be an integral type, in "
                 "absl::Poisson<IntType, URBG>(...)");
 
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = typename absl::poisson_distribution<IntType>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
@@ -437,7 +437,7 @@
                 "Template-argument 'IntType' must be an integral type, in "
                 "absl::Zipf<IntType, URBG>(...)");
 
-  using gen_t = absl::decay_t<URBG>;
+  using gen_t = std::decay_t<URBG>;
   using distribution_t = typename absl::zipf_distribution<IntType>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
diff --git a/absl/random/distributions_test.cc b/absl/random/distributions_test.cc
index 4340aeb..1fa3345 100644
--- a/absl/random/distributions_test.cc
+++ b/absl/random/distributions_test.cc
@@ -80,13 +80,13 @@
 template <typename A, typename B, typename Expect>
 void CheckArgsInferType() {
   static_assert(
-      absl::conjunction<
+      std::conjunction<
           std::is_same<Expect, decltype(InferredUniformReturnT<A, B>(0))>,
           std::is_same<Expect,
                        decltype(InferredUniformReturnT<B, A>(0))>>::value,
       "");
   static_assert(
-      absl::conjunction<
+      std::conjunction<
           std::is_same<Expect, decltype(InferredTaggedUniformReturnT<
                                         absl::IntervalOpenOpenTag, A, B>(0))>,
           std::is_same<Expect,
@@ -121,14 +121,14 @@
 template <typename A, typename B, typename Expect>
 void CheckArgsReturnExpectedType() {
   static_assert(
-      absl::conjunction<
+      std::conjunction<
           std::is_same<Expect,
                        decltype(ExplicitUniformReturnT<A, B, Expect>(0))>,
           std::is_same<Expect, decltype(ExplicitUniformReturnT<B, A, Expect>(
                                    0))>>::value,
       "");
   static_assert(
-      absl::conjunction<
+      std::conjunction<
           std::is_same<Expect,
                        decltype(ExplicitTaggedUniformReturnT<
                                 absl::IntervalOpenOpenTag, A, B, Expect>(0))>,
diff --git a/absl/random/exponential_distribution.h b/absl/random/exponential_distribution.h
index 4af2fb4..f0267b2 100644
--- a/absl/random/exponential_distribution.h
+++ b/absl/random/exponential_distribution.h
@@ -124,7 +124,7 @@
   using random_internal::GenerateNegativeTag;
   using random_internal::GenerateRealFromBits;
   using real_type =
-      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+      std::conditional_t<std::is_same<RealType, float>::value, float, double>;
 
   const result_type u = GenerateRealFromBits<real_type, GenerateNegativeTag,
                                              false>(fast_u64_(g));  // U(-1, 0)
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index c2f2c36..56377ed 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -116,6 +116,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         "//absl/base:config",
+        "//absl/meta:type_traits",
         "//absl/numeric:bits",
         "//absl/numeric:int128",
     ],
@@ -130,6 +131,7 @@
         "//absl/base:config",
         "//absl/base:fast_type_id",
         "//absl/meta:type_traits",
+        "//absl/random:mocking_access",
         "//absl/utility",
     ],
 )
@@ -592,7 +594,7 @@
     deps = [
         "//absl/base:config",
         "//absl/base:fast_type_id",
-        "//absl/types:optional",
+        "//absl/random:mocking_access",
     ],
 )
 
diff --git a/absl/random/internal/distribution_caller.h b/absl/random/internal/distribution_caller.h
index e84ec8c..d14fa85 100644
--- a/absl/random/internal/distribution_caller.h
+++ b/absl/random/internal/distribution_caller.h
@@ -24,6 +24,7 @@
 #include "absl/base/config.h"
 #include "absl/base/fast_type_id.h"
 #include "absl/meta/type_traits.h"
+#include "absl/random/mocking_access.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
@@ -37,23 +38,8 @@
 struct DistributionCaller {
   static_assert(!std::is_pointer<URBG>::value,
                 "You must pass a reference, not a pointer.");
-  // SFINAE to detect whether the URBG type includes a member matching
-  // bool InvokeMock(key_id, args_tuple*, result*).
-  //
-  // These live inside BitGenRef so that they have friend access
-  // to MockingBitGen. (see similar methods in DistributionCaller).
-  template <template <class...> class Trait, class AlwaysVoid, class... Args>
-  struct detector : std::false_type {};
-  template <template <class...> class Trait, class... Args>
-  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
-      : std::true_type {};
 
-  template <class T>
-  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
-      std::declval<FastTypeIdType>(), std::declval<void*>(),
-      std::declval<void*>()));
-
-  using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
+  using RandomMockingAccess = ::absl::RandomMockingAccess;
 
   // Default implementation of distribution caller.
   template <typename DistrT, typename... Args>
@@ -69,12 +55,13 @@
   static typename DistrT::result_type Impl(std::true_type, URBG* urbg,
                                            Args&&... args) {
     using ResultT = typename DistrT::result_type;
-    using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
+    using ArgTupleT = std::tuple<std::decay_t<Args>...>;
     using KeyT = ResultT(DistrT, ArgTupleT);
 
     ArgTupleT arg_tuple(std::forward<Args>(args)...);
     ResultT result;
-    if (!urbg->InvokeMock(FastTypeId<KeyT>(), &arg_tuple, &result)) {
+    if (!RandomMockingAccess::InvokeMock<URBG>(urbg, FastTypeId<KeyT>(),
+                                               &arg_tuple, &result)) {
       auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
       result = dist(*urbg);
     }
@@ -84,8 +71,8 @@
   // Default implementation of distribution caller.
   template <typename DistrT, typename... Args>
   static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
-    return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,
-                                 std::forward<Args>(args)...);
+    return Impl<DistrT, Args...>(RandomMockingAccess::HasInvokeMock<URBG>{},
+                                 urbg, std::forward<Args>(args)...);
   }
 };
 
diff --git a/absl/random/internal/fast_uniform_bits.h b/absl/random/internal/fast_uniform_bits.h
index 83ee5c0..7292d1f 100644
--- a/absl/random/internal/fast_uniform_bits.h
+++ b/absl/random/internal/fast_uniform_bits.h
@@ -126,7 +126,7 @@
   static_assert((URBG::max)() > (URBG::min)(),
                 "URBG::max and URBG::min may not be equal.");
 
-  using tag = absl::conditional_t<IsPowerOfTwoOrZero(RangeSize<URBG>()),
+  using tag = std::conditional_t<IsPowerOfTwoOrZero(RangeSize<URBG>()),
                                   SimplifiedLoopTag, RejectionLoopTag>;
   return Generate(g, tag{});
 }
diff --git a/absl/random/internal/generate_real.h b/absl/random/internal/generate_real.h
index 9a6f400..fc35240 100644
--- a/absl/random/internal/generate_real.h
+++ b/absl/random/internal/generate_real.h
@@ -69,7 +69,7 @@
           bool IncludeZero = true>
 inline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 0) {
   using real_type = RealType;
-  using uint_type = absl::conditional_t<std::is_same<real_type, float>::value,
+  using uint_type = std::conditional_t<std::is_same<real_type, float>::value,
                                         uint32_t, uint64_t>;
 
   static_assert(
diff --git a/absl/random/internal/iostream_state_saver.h b/absl/random/internal/iostream_state_saver.h
index 0f56bcb..5556b67 100644
--- a/absl/random/internal/iostream_state_saver.h
+++ b/absl/random/internal/iostream_state_saver.h
@@ -95,7 +95,7 @@
 }
 
 template <typename T>
-typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
+typename std::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
                            null_state_saver<T>>
 make_ostream_state_saver(T& is,  // NOLINT(runtime/references)
                          std::ios_base::fmtflags flags = std::ios_base::dec) {
@@ -159,7 +159,7 @@
 }
 
 template <typename T>
-typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
+typename std::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
                            null_state_saver<T>>
 make_istream_state_saver(T& is,  // NOLINT(runtime/references)
                          std::ios_base::fmtflags flags = std::ios_base::dec) {
diff --git a/absl/random/internal/iostream_state_saver_test.cc b/absl/random/internal/iostream_state_saver_test.cc
index ea9d2af..3c1db21 100644
--- a/absl/random/internal/iostream_state_saver_test.cc
+++ b/absl/random/internal/iostream_state_saver_test.cc
@@ -19,6 +19,7 @@
 
 #include <sstream>
 #include <string>
+#include <type_traits>
 
 #include "gtest/gtest.h"
 
@@ -29,7 +30,7 @@
 using absl::random_internal::stream_precision_helper;
 
 template <typename T>
-typename absl::enable_if_t<std::is_integral<T>::value, T>  //
+typename std::enable_if_t<std::is_integral<T>::value, T>  //
 StreamRoundTrip(T t) {
   std::stringstream ss;
   {
@@ -53,7 +54,7 @@
 }
 
 template <typename T>
-typename absl::enable_if_t<std::is_floating_point<T>::value, T>  //
+typename std::enable_if_t<std::is_floating_point<T>::value, T>  //
 StreamRoundTrip(T t) {
   std::stringstream ss;
   {
diff --git a/absl/random/internal/mock_helpers.h b/absl/random/internal/mock_helpers.h
index 2d66a3b..b73b9cb 100644
--- a/absl/random/internal/mock_helpers.h
+++ b/absl/random/internal/mock_helpers.h
@@ -21,7 +21,7 @@
 
 #include "absl/base/config.h"
 #include "absl/base/fast_type_id.h"
-#include "absl/types/optional.h"
+#include "absl/random/mocking_access.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -50,6 +50,7 @@
 //
 class MockHelpers {
   using IdType = ::absl::FastTypeIdType;
+  using RandomMockingAccess = ::absl::RandomMockingAccess;
 
   // Given a key signature type used to index the mock, extract the components.
   // KeyT is expected to have the form:
@@ -64,39 +65,7 @@
     using arg_tuple_type = ArgTupleT;
   };
 
-  // Detector for InvokeMock.
-  template <class T>
-  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
-      std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));
-
-  // Empty implementation of InvokeMock.
-  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
-            typename... Args>
-  static std::optional<ReturnT> InvokeMockImpl(char, URBG*, Args&&...) {
-    return std::nullopt;
-  }
-
-  // Non-empty implementation of InvokeMock.
-  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
-            typename = invoke_mock_t<URBG>, typename... Args>
-  static std::optional<ReturnT> InvokeMockImpl(int, URBG* urbg,
-                                               Args&&... args) {
-    ArgTupleT arg_tuple(std::forward<Args>(args)...);
-    ReturnT result;
-    if (urbg->InvokeMock(FastTypeId<KeyT>(), &arg_tuple, &result)) {
-      return result;
-    }
-    return std::nullopt;
-  }
-
  public:
-  // InvokeMock is private; this provides access for some specialized use cases.
-  template <typename URBG>
-  static inline bool PrivateInvokeMock(URBG* urbg, IdType key_id,
-                                       void* args_tuple, void* result) {
-    return urbg->InvokeMock(key_id, args_tuple, result);
-  }
-
   // Invoke a mock for the KeyT (may or may not be a signature).
   //
   // KeyT is used to generate a typeid-based lookup key for the mock.
@@ -110,12 +79,16 @@
   template <typename KeyT, typename URBG, typename... Args>
   static auto MaybeInvokeMock(URBG* urbg, Args&&... args)
       -> std::optional<typename KeySignature<KeyT>::result_type> {
-    // Use function overloading to dispatch to the implementation since
-    // more modern patterns (e.g. require + constexpr) are not supported in all
-    // compiler configurations.
-    return InvokeMockImpl<KeyT, typename KeySignature<KeyT>::result_type,
-                          typename KeySignature<KeyT>::arg_tuple_type, URBG>(
-        0, urbg, std::forward<Args>(args)...);
+    if constexpr (RandomMockingAccess::HasInvokeMock<URBG>::value) {
+      typename KeySignature<KeyT>::arg_tuple_type arg_tuple(
+          std::forward<Args>(args)...);
+      typename KeySignature<KeyT>::result_type result;
+      if (RandomMockingAccess::InvokeMock(urbg, FastTypeId<KeyT>(), &arg_tuple,
+                                          &result)) {
+        return result;
+      }
+    }
+    return std::nullopt;
   }
 
   // Acquire a mock for the KeyT (may or may not be a signature), set up to use
diff --git a/absl/random/internal/nonsecure_base.h b/absl/random/internal/nonsecure_base.h
index e8c2bb9..903dbd9 100644
--- a/absl/random/internal/nonsecure_base.h
+++ b/absl/random/internal/nonsecure_base.h
@@ -78,7 +78,7 @@
       // std::contiguous_iterator_tag provides a mechanism for testing this
       // capability, however until Abseil's support requirements allow us to
       // assume C++20, limit checks to a few common cases.
-      using TagType = absl::conditional_t<
+      using TagType = std::conditional_t<
           (std::is_pointer<RandomAccessIterator>::value ||
            std::is_same<RandomAccessIterator,
                         typename std::vector<U>::iterator>::value),
@@ -106,7 +106,7 @@
   NonsecureURBGBase& operator=(NonsecureURBGBase&&) = default;
 
   // Constructor using a seed
-  template <class SSeq, typename = typename absl::enable_if_t<
+  template <class SSeq, typename = typename std::enable_if_t<
                             !std::is_same<SSeq, NonsecureURBGBase>::value>>
   explicit NonsecureURBGBase(SSeq&& seq)
       : urbg_(ConstructURBG(std::forward<SSeq>(seq))) {}
diff --git a/absl/random/internal/nonsecure_base_test.cc b/absl/random/internal/nonsecure_base_test.cc
index 6e3e712..3795563 100644
--- a/absl/random/internal/nonsecure_base_test.cc
+++ b/absl/random/internal/nonsecure_base_test.cc
@@ -77,13 +77,13 @@
   static_assert(!std::is_copy_constructible<E>::value,
                 "NonsecureURBGBase should not be copy constructible");
 
-  static_assert(!absl::is_copy_assignable<E>::value,
+  static_assert(!std::is_copy_assignable<E>::value,
                 "NonsecureURBGBase should not be copy assignable");
 
   static_assert(std::is_move_constructible<E>::value,
                 "NonsecureURBGBase should be move constructible");
 
-  static_assert(absl::is_move_assignable<E>::value,
+  static_assert(std::is_move_assignable<E>::value,
                 "NonsecureURBGBase should be move assignable");
 
   static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
diff --git a/absl/random/internal/pcg_engine.h b/absl/random/internal/pcg_engine.h
index e1f4ef3..2f41d58 100644
--- a/absl/random/internal/pcg_engine.h
+++ b/absl/random/internal/pcg_engine.h
@@ -67,7 +67,7 @@
   explicit pcg_engine(uint64_t seed_value = 0) { seed(seed_value); }
 
   template <class SeedSequence,
-            typename = typename absl::enable_if_t<
+            typename = typename std::enable_if_t<
                 !std::is_same<SeedSequence, pcg_engine>::value>>
   explicit pcg_engine(SeedSequence&& seq) {
     seed(seq);
@@ -90,7 +90,7 @@
   }
 
   template <class SeedSequence>
-  typename absl::enable_if_t<
+  typename std::enable_if_t<
       !std::is_convertible<SeedSequence, uint64_t>::value, void>
   seed(SeedSequence&& seq) {
     reseed(seq);
@@ -105,7 +105,7 @@
   bool operator!=(const pcg_engine& other) const { return !(*this == other); }
 
   template <class CharT, class Traits>
-  friend typename absl::enable_if_t<(sizeof(state_type) == 16),
+  friend typename std::enable_if_t<(sizeof(state_type) == 16),
                                     std::basic_ostream<CharT, Traits>&>
   operator<<(
       std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)
@@ -121,7 +121,7 @@
   }
 
   template <class CharT, class Traits>
-  friend typename absl::enable_if_t<(sizeof(state_type) <= 8),
+  friend typename std::enable_if_t<(sizeof(state_type) <= 8),
                                     std::basic_ostream<CharT, Traits>&>
   operator<<(
       std::basic_ostream<CharT, Traits>& os,  // NOLINT(runtime/references)
@@ -134,7 +134,7 @@
   }
 
   template <class CharT, class Traits>
-  friend typename absl::enable_if_t<(sizeof(state_type) == 16),
+  friend typename std::enable_if_t<(sizeof(state_type) == 16),
                                     std::basic_istream<CharT, Traits>&>
   operator>>(
       std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)
@@ -155,7 +155,7 @@
   }
 
   template <class CharT, class Traits>
-  friend typename absl::enable_if_t<(sizeof(state_type) <= 8),
+  friend typename std::enable_if_t<(sizeof(state_type) <= 8),
                                     std::basic_istream<CharT, Traits>&>
   operator>>(
       std::basic_istream<CharT, Traits>& is,  // NOLINT(runtime/references)
diff --git a/absl/random/internal/pcg_engine_test.cc b/absl/random/internal/pcg_engine_test.cc
index 4d763e8..211a849 100644
--- a/absl/random/internal/pcg_engine_test.cc
+++ b/absl/random/internal/pcg_engine_test.cc
@@ -18,6 +18,7 @@
 #include <bitset>
 #include <random>
 #include <sstream>
+#include <type_traits>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
@@ -169,13 +170,13 @@
   static_assert(std::is_copy_constructible<E>::value,
                 "engine_type must be copy constructible");
 
-  static_assert(absl::is_copy_assignable<E>::value,
+  static_assert(std::is_copy_assignable<E>::value,
                 "engine_type must be copy assignable");
 
   static_assert(std::is_move_constructible<E>::value,
                 "engine_type must be move constructible");
 
-  static_assert(absl::is_move_assignable<E>::value,
+  static_assert(std::is_move_assignable<E>::value,
                 "engine_type must be move assignable");
 
   static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
diff --git a/absl/random/internal/randen_engine.h b/absl/random/internal/randen_engine.h
index 925e1bb..4e4fef9 100644
--- a/absl/random/internal/randen_engine.h
+++ b/absl/random/internal/randen_engine.h
@@ -63,7 +63,7 @@
   explicit randen_engine(result_type seed_value) { seed(seed_value); }
 
   template <class SeedSequence,
-            typename = typename absl::enable_if_t<
+            typename = typename std::enable_if_t<
                 !std::is_same<SeedSequence, randen_engine>::value>>
   explicit randen_engine(SeedSequence&& seq) {
     seed(seq);
@@ -93,7 +93,7 @@
   }
 
   template <class SeedSequence>
-  typename absl::enable_if_t<
+  typename std::enable_if_t<
       !std::is_convertible<SeedSequence, result_type>::value>
   seed(SeedSequence&& seq) {
     // Zeroes the state.
diff --git a/absl/random/internal/randen_engine_test.cc b/absl/random/internal/randen_engine_test.cc
index 122d90b..85c0a2b 100644
--- a/absl/random/internal/randen_engine_test.cc
+++ b/absl/random/internal/randen_engine_test.cc
@@ -18,6 +18,7 @@
 #include <bitset>
 #include <random>
 #include <sstream>
+#include <type_traits>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
@@ -170,13 +171,13 @@
   static_assert(std::is_copy_constructible<E>::value,
                 "randen_engine must be copy constructible");
 
-  static_assert(absl::is_copy_assignable<E>::value,
+  static_assert(std::is_copy_assignable<E>::value,
                 "randen_engine must be copy assignable");
 
   static_assert(std::is_move_constructible<E>::value,
                 "randen_engine must be move constructible");
 
-  static_assert(absl::is_move_assignable<E>::value,
+  static_assert(std::is_move_assignable<E>::value,
                 "randen_engine must be move assignable");
 
   static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
diff --git a/absl/random/internal/randen_test.cc b/absl/random/internal/randen_test.cc
index 92773b8..cf94970 100644
--- a/absl/random/internal/randen_test.cc
+++ b/absl/random/internal/randen_test.cc
@@ -15,6 +15,7 @@
 #include "absl/random/internal/randen.h"
 
 #include <cstring>
+#include <type_traits>
 
 #include "gtest/gtest.h"
 #include "absl/meta/type_traits.h"
@@ -27,13 +28,13 @@
   static_assert(std::is_copy_constructible<Randen>::value,
                 "Randen must be copy constructible");
 
-  static_assert(absl::is_copy_assignable<Randen>::value,
+  static_assert(std::is_copy_assignable<Randen>::value,
                 "Randen must be copy assignable");
 
   static_assert(std::is_move_constructible<Randen>::value,
                 "Randen must be move constructible");
 
-  static_assert(absl::is_move_assignable<Randen>::value,
+  static_assert(std::is_move_assignable<Randen>::value,
                 "Randen must be move assignable");
 }
 
diff --git a/absl/random/internal/salted_seed_seq.h b/absl/random/internal/salted_seed_seq.h
index c374d93..a86c39d 100644
--- a/absl/random/internal/salted_seed_seq.h
+++ b/absl/random/internal/salted_seed_seq.h
@@ -72,7 +72,7 @@
     // The common case is that generate is called with ContiguousIterators
     // to uint arrays. Such contiguous memory regions may be optimized,
     // which we detect here.
-    using TagType = absl::conditional_t<
+    using TagType = std::conditional_t<
         (std::is_same<U, uint32_t>::value &&
          (std::is_pointer<RandomAccessIterator>::value ||
           std::is_same<RandomAccessIterator,
@@ -142,14 +142,14 @@
 // non-salted seed parameters.
 template <
     typename SSeq,  //
-    typename EnableIf = absl::enable_if_t<is_salted_seed_seq<SSeq>::value>>
+    typename EnableIf = std::enable_if_t<is_salted_seed_seq<SSeq>::value>>
 SSeq MakeSaltedSeedSeq(SSeq&& seq) {
   return SSeq(std::forward<SSeq>(seq));
 }
 
 template <
     typename SSeq,  //
-    typename EnableIf = absl::enable_if_t<!is_salted_seed_seq<SSeq>::value>>
+    typename EnableIf = std::enable_if_t<!is_salted_seed_seq<SSeq>::value>>
 SaltedSeedSeq<typename std::decay<SSeq>::type> MakeSaltedSeedSeq(SSeq&& seq) {
   using sseq_type = typename std::decay<SSeq>::type;
   using result_type = typename sseq_type::result_type;
diff --git a/absl/random/internal/traits.h b/absl/random/internal/traits.h
index f874a0f..f23bcd2 100644
--- a/absl/random/internal/traits.h
+++ b/absl/random/internal/traits.h
@@ -20,6 +20,7 @@
 #include <type_traits>
 
 #include "absl/base/config.h"
+#include "absl/meta/type_traits.h"
 #include "absl/numeric/bits.h"
 #include "absl/numeric/int128.h"
 
@@ -27,6 +28,26 @@
 ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
+// is_urbg<URBG>
+//
+// Indicates whether a type URBG is a Uniform Random Bit Generator.
+template <typename URBG, typename = void, typename = void, typename = void>
+struct is_urbg : std::false_type {};
+
+template <typename URBG>
+struct is_urbg<
+    URBG,
+    std::enable_if_t<std::is_same<
+        typename URBG::result_type,
+        typename std::decay<decltype((URBG::min)())>::type>::value>,
+    std::enable_if_t<std::is_same<
+        typename URBG::result_type,
+        typename std::decay<decltype((URBG::max)())>::type>::value>,
+    std::enable_if_t<std::is_same<
+        typename URBG::result_type,
+        typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
+    : std::true_type {};
+
 // random_internal::is_widening_convertible<A, B>
 //
 // Returns whether a type A is widening-convertible to a type B.
diff --git a/absl/random/internal/traits_test.cc b/absl/random/internal/traits_test.cc
index 2164582..100fd9b 100644
--- a/absl/random/internal/traits_test.cc
+++ b/absl/random/internal/traits_test.cc
@@ -15,14 +15,19 @@
 #include "absl/random/internal/traits.h"
 
 #include <cstdint>
+#include <random>
 #include <type_traits>
 
 #include "gtest/gtest.h"
 
 namespace {
 
+using absl::random_internal::is_urbg;
 using absl::random_internal::is_widening_convertible;
 
+static_assert(is_urbg<std::minstd_rand>::value);
+static_assert(!is_urbg<uint64_t>::value);
+
 // CheckWideningConvertsToSelf<T1, T2, ...>()
 //
 // For each type T, checks:
diff --git a/absl/random/internal/uniform_helper.h b/absl/random/internal/uniform_helper.h
index d230073..f50be61 100644
--- a/absl/random/internal/uniform_helper.h
+++ b/absl/random/internal/uniform_helper.h
@@ -76,7 +76,7 @@
 // Return-type for absl::Uniform() when the return-type is inferred.
 template <typename A, typename B>
 using uniform_inferred_return_t =
-    absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
+    std::enable_if_t<std::disjunction<is_widening_convertible<A, B>,
                                         is_widening_convertible<B, A>>::value,
                       typename std::conditional<
                           is_widening_convertible<A, B>::value, B, A>::type>;
@@ -98,10 +98,10 @@
 //               uniform_upper_bound(IntervalOpenClosed, a, b)]
 //
 template <typename IntType, typename Tag>
-typename absl::enable_if_t<
-    absl::conjunction<
+typename std::enable_if_t<
+    std::conjunction<
         IsIntegral<IntType>,
-        absl::disjunction<std::is_same<Tag, IntervalOpenClosedTag>,
+        std::disjunction<std::is_same<Tag, IntervalOpenClosedTag>,
                           std::is_same<Tag, IntervalOpenOpenTag>>>::value,
     IntType>
 uniform_lower_bound(Tag, IntType a, IntType) {
@@ -109,10 +109,10 @@
 }
 
 template <typename FloatType, typename Tag>
-typename absl::enable_if_t<
-    absl::conjunction<
+typename std::enable_if_t<
+    std::conjunction<
         std::is_floating_point<FloatType>,
-        absl::disjunction<std::is_same<Tag, IntervalOpenClosedTag>,
+        std::disjunction<std::is_same<Tag, IntervalOpenClosedTag>,
                           std::is_same<Tag, IntervalOpenOpenTag>>>::value,
     FloatType>
 uniform_lower_bound(Tag, FloatType a, FloatType b) {
@@ -120,8 +120,8 @@
 }
 
 template <typename NumType, typename Tag>
-typename absl::enable_if_t<
-    absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
+typename std::enable_if_t<
+    std::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
                       std::is_same<Tag, IntervalClosedOpenTag>>::value,
     NumType>
 uniform_lower_bound(Tag, NumType a, NumType) {
@@ -129,10 +129,10 @@
 }
 
 template <typename IntType, typename Tag>
-typename absl::enable_if_t<
-    absl::conjunction<
+typename std::enable_if_t<
+    std::conjunction<
         IsIntegral<IntType>,
-        absl::disjunction<std::is_same<Tag, IntervalClosedOpenTag>,
+        std::disjunction<std::is_same<Tag, IntervalClosedOpenTag>,
                           std::is_same<Tag, IntervalOpenOpenTag>>>::value,
     IntType>
 uniform_upper_bound(Tag, IntType, IntType b) {
@@ -140,10 +140,10 @@
 }
 
 template <typename FloatType, typename Tag>
-typename absl::enable_if_t<
-    absl::conjunction<
+typename std::enable_if_t<
+    std::conjunction<
         std::is_floating_point<FloatType>,
-        absl::disjunction<std::is_same<Tag, IntervalClosedOpenTag>,
+        std::disjunction<std::is_same<Tag, IntervalClosedOpenTag>,
                           std::is_same<Tag, IntervalOpenOpenTag>>>::value,
     FloatType>
 uniform_upper_bound(Tag, FloatType, FloatType b) {
@@ -151,10 +151,10 @@
 }
 
 template <typename IntType, typename Tag>
-typename absl::enable_if_t<
-    absl::conjunction<
+typename std::enable_if_t<
+    std::conjunction<
         IsIntegral<IntType>,
-        absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
+        std::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
                           std::is_same<Tag, IntervalOpenClosedTag>>>::value,
     IntType>
 uniform_upper_bound(Tag, IntType, IntType b) {
@@ -162,10 +162,10 @@
 }
 
 template <typename FloatType, typename Tag>
-typename absl::enable_if_t<
-    absl::conjunction<
+typename std::enable_if_t<
+    std::conjunction<
         std::is_floating_point<FloatType>,
-        absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
+        std::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
                           std::is_same<Tag, IntervalOpenClosedTag>>>::value,
     FloatType>
 uniform_upper_bound(Tag, FloatType, FloatType b) {
@@ -195,13 +195,13 @@
 // (0, 0] is not legal, but (0, 0+epsilon] is.
 //
 template <typename FloatType>
-absl::enable_if_t<std::is_floating_point<FloatType>::value, bool>
+std::enable_if_t<std::is_floating_point<FloatType>::value, bool>
 is_uniform_range_valid(FloatType a, FloatType b) {
   return a <= b && std::isfinite(b - a);
 }
 
 template <typename IntType>
-absl::enable_if_t<IsIntegral<IntType>::value, bool> is_uniform_range_valid(
+std::enable_if_t<IsIntegral<IntType>::value, bool> is_uniform_range_valid(
     IntType a, IntType b) {
   return a <= b;
 }
diff --git a/absl/random/internal/uniform_helper_test.cc b/absl/random/internal/uniform_helper_test.cc
index 173c49b..5b20b0b 100644
--- a/absl/random/internal/uniform_helper_test.cc
+++ b/absl/random/internal/uniform_helper_test.cc
@@ -17,6 +17,7 @@
 #include <cmath>
 #include <cstdint>
 #include <random>
+#include <type_traits>
 
 #include "gtest/gtest.h"
 
@@ -214,7 +215,7 @@
 template <typename A, typename B, typename Expect>
 void CheckArgsInferType() {
   static_assert(
-      absl::conjunction<
+      std::conjunction<
           std::is_same<Expect, decltype(InferredUniformReturnT<A, B>(0))>,
           std::is_same<Expect,
                        decltype(InferredUniformReturnT<B, A>(0))>>::value,
diff --git a/absl/random/mocking_access.h b/absl/random/mocking_access.h
new file mode 100644
index 0000000..eb2f98b
--- /dev/null
+++ b/absl/random/mocking_access.h
@@ -0,0 +1,74 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_MOCKING_ACCESS_H_
+#define ABSL_RANDOM_MOCKING_ACCESS_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/base/fast_type_id.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// RandomMockingAccess must be a friend of any class which exposes an InvokeMock
+// method. All calls to InvokeMock should be made through RandomMockingAccess.
+//
+// Any URBG type which wants to participate in mocking should declare
+// RandomMockingAccess as a friend and have a protected or private method with
+// the signature:
+//
+// bool InvokeMock(absl::FastTypeIdType key_id, void* args_tuple, void* result)
+//
+// This method returns false when mocking is not enabled, otherwise it will
+// apply the mock.  Typically this will involve forwarding to an underlying
+// URBG such as absl::MockingBitGen by calling RandomMockingAccess::InvokeMock
+// after checking that RandomMockingAccess::HasInvokeMock<URBG> is true for the
+// underlying URBG type.
+class RandomMockingAccess {
+  template <template <class...> class Trait, class AlwaysVoid, class... Args>
+  struct detector : std::false_type {};
+  template <template <class...> class Trait, class... Args>
+  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
+      : std::true_type {};
+
+  using IdType = ::absl::FastTypeIdType;
+
+  // Detector for `bool InvokeMock(key_id, args_tuple*, result*)`
+  // Lives inside RandomMockingAccess so that it has friend access to private
+  // members of URBG types.
+  template <class T>
+  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+      std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));
+
+ public:
+  // Returns true if the URBG type has an InvokeMock method.
+  template <typename T>
+  using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
+
+  // InvokeMock is private; calls to InvokeMock are proxied by MockingAccess.
+  template <typename URBG>
+  static inline bool InvokeMock(URBG* urbg, IdType key_id, void* args_tuple,
+                                void* result) {
+    return urbg->InvokeMock(key_id, args_tuple, result);
+  }
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_MOCKING_ACCESS_H_
diff --git a/absl/random/mocking_bit_gen.h b/absl/random/mocking_bit_gen.h
index 1680ff4..74aa17d 100644
--- a/absl/random/mocking_bit_gen.h
+++ b/absl/random/mocking_bit_gen.h
@@ -39,20 +39,13 @@
 #include "absl/container/flat_hash_map.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/internal/mock_helpers.h"
+#include "absl/random/mocking_access.h"
 #include "absl/random/random.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-class BitGenRef;
-
-namespace random_internal {
-template <typename>
-struct DistributionCaller;
-class MockHelpers;
-}  // namespace random_internal
-
 // MockingBitGen
 //
 // `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class
@@ -181,13 +174,13 @@
     using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(),
                                               std::declval<ArgTupleT>()));
 
-    using WrappedFnType = absl::conditional_t<
+    using WrappedFnType = std::conditional_t<
         std::is_same<SelfT, ::testing::NiceMock<MockingBitGen>>::value,
         ::testing::NiceMock<MockFnType>,
-        absl::conditional_t<
+        std::conditional_t<
             std::is_same<SelfT, ::testing::NaggyMock<MockingBitGen>>::value,
             ::testing::NaggyMock<MockFnType>,
-            absl::conditional_t<
+            std::conditional_t<
                 std::is_same<SelfT,
                              ::testing::StrictMock<MockingBitGen>>::value,
                 ::testing::StrictMock<MockFnType>, MockFnType>>>;
@@ -224,11 +217,8 @@
   absl::flat_hash_map<FastTypeIdType, std::unique_ptr<FunctionHolder>> mocks_;
   absl::BitGen gen_;
 
-  template <typename>
-  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock
-  friend class ::absl::BitGenRef;                             // for InvokeMock
-  friend class ::absl::random_internal::MockHelpers;  // for RegisterMock,
-                                                      // InvokeMock
+  friend class ::absl::RandomMockingAccess;           // for InvokeMock
+  friend class ::absl::random_internal::MockHelpers;  // for RegisterMock
 };
 
 ABSL_NAMESPACE_END
diff --git a/absl/random/uniform_real_distribution.h b/absl/random/uniform_real_distribution.h
index 8bef946..e5ea6f2 100644
--- a/absl/random/uniform_real_distribution.h
+++ b/absl/random/uniform_real_distribution.h
@@ -159,7 +159,7 @@
   using random_internal::GeneratePositiveTag;
   using random_internal::GenerateRealFromBits;
   using real_type =
-      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+      std::conditional_t<std::is_same<RealType, float>::value, float, double>;
 
   while (true) {
     const result_type sample =
diff --git a/absl/status/BUILD.bazel b/absl/status/BUILD.bazel
index 038f1da..dce316b 100644
--- a/absl/status/BUILD.bazel
+++ b/absl/status/BUILD.bazel
@@ -65,11 +65,13 @@
         "//absl/debugging:stacktrace",
         "//absl/debugging:symbolize",
         "//absl/functional:function_ref",
+        "//absl/hash",
         "//absl/memory",
         "//absl/strings",
         "//absl/strings:cord",
         "//absl/strings:str_format",
         "//absl/types:optional",
+        "//absl/types:source_location",
         "//absl/types:span",
     ],
 )
@@ -84,6 +86,7 @@
         "//absl/strings",
         "//absl/strings:cord",
         "//absl/strings:str_format",
+        "//absl/types:source_location",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
     ],
@@ -96,6 +99,7 @@
     tags = ["benchmark"],
     deps = [
         ":status",
+        "//absl/types:source_location",
         "@google_benchmark//:benchmark_main",
     ],
 )
@@ -122,6 +126,8 @@
         "//absl/strings",
         "//absl/strings:has_ostream_operator",
         "//absl/strings:str_format",
+        "//absl/types:source_location",
+        "//absl/types:span",
         "//absl/types:variant",
         "//absl/utility",
     ],
@@ -139,6 +145,7 @@
         "//absl/memory",
         "//absl/strings",
         "//absl/types:any",
+        "//absl/types:source_location",
         "//absl/types:variant",
         "//absl/utility",
         "@googletest//:gtest",
diff --git a/absl/status/CMakeLists.txt b/absl/status/CMakeLists.txt
index a418bd9..8d519a5 100644
--- a/absl/status/CMakeLists.txt
+++ b/absl/status/CMakeLists.txt
@@ -41,6 +41,7 @@
     absl::nullability
     absl::optional
     absl::raw_logging_internal
+    absl::source_location
     absl::span
     absl::stacktrace
     absl::str_format
@@ -59,6 +60,7 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::status
+    absl::source_location
     absl::str_format
     absl::strings
     GTest::gmock_main
@@ -82,6 +84,7 @@
     absl::nullability
     absl::raw_logging_internal
     absl::status
+    absl::source_location
     absl::str_format
     absl::strings
     absl::type_traits
@@ -101,6 +104,7 @@
     absl::status
     absl::status_matchers
     absl::statusor
+    absl::source_location
     absl::strings
     GTest::gmock_main
 )
diff --git a/absl/status/internal/status_internal.cc b/absl/status/internal/status_internal.cc
index 74bece4..6e79234 100644
--- a/absl/status/internal/status_internal.cc
+++ b/absl/status/internal/status_internal.cc
@@ -32,6 +32,7 @@
 #include "absl/debugging/leak_check.h"
 #include "absl/debugging/stacktrace.h"
 #include "absl/debugging/symbolize.h"
+#include "absl/hash/hash.h"
 #include "absl/memory/memory.h"
 #include "absl/status/status.h"
 #include "absl/status/status_payload_printer.h"
@@ -41,6 +42,8 @@
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
+#include "absl/types/source_location.h"
+#include "absl/types/span.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -130,6 +133,14 @@
   }
 }
 
+absl::Span<const SourceLocation> StatusRep::GetSourceLocations() const {
+  return absl::MakeSpan(source_locations_);
+}
+
+void StatusRep::AddSourceLocation(absl::SourceLocation loc) {
+  source_locations_.push_back(loc);
+}
+
 std::string StatusRep::ToString(StatusToStringMode mode) const {
   std::string text;
   absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message());
@@ -150,6 +161,17 @@
           "']");
     });
   }
+  const bool with_source_location =
+      (mode & StatusToStringMode::kWithSourceLocation) ==
+      StatusToStringMode::kWithSourceLocation;
+  if (with_source_location && !source_locations_.empty()) {
+    absl::string_view whitespace = (absl::Hash<int>{}(42) % 2 == 0) ? "" : " ";
+    absl::StrAppend(&text, "\n=== Source Location Trace: ===", whitespace,
+                    "\n");
+    for (const absl::SourceLocation loc : GetSourceLocations()) {
+      absl::StrAppend(&text, loc.file_name(), ":", loc.line(), "\n");
+    }
+  }
 
   return text;
 }
@@ -204,6 +226,7 @@
     payloads = absl::make_unique<status_internal::Payloads>(*payloads_);
   }
   auto* new_rep = new StatusRep(code_, message_, std::move(payloads));
+  new_rep->source_locations_ = source_locations_;
   Unref();
   return new_rep;
 }
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h
index f2bd83a..cafe160 100644
--- a/absl/status/internal/status_internal.h
+++ b/absl/status/internal/status_internal.h
@@ -17,10 +17,10 @@
 #include <atomic>
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
-
-#include <optional>
+#include <vector>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
@@ -29,6 +29,8 @@
 #include "absl/strings/cord.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
+#include "absl/types/source_location.h"
+#include "absl/types/span.h"
 
 #ifndef SWIG
 // Disabled for SWIG as it doesn't parse attributes correctly.
@@ -57,6 +59,9 @@
 enum class StatusToStringMode : int;
 
 namespace status_internal {
+#ifndef SWIG
+class StatusPrivateAccessor;
+#endif  // !SWIG
 
 // Container for status payloads.
 struct Payload {
@@ -96,6 +101,9 @@
       absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)
       const;
 
+  absl::Span<const SourceLocation> GetSourceLocations() const;
+  void AddSourceLocation(absl::SourceLocation loc);
+
   std::string ToString(StatusToStringMode mode) const;
 
   bool operator==(const StatusRep& other) const;
@@ -114,6 +122,7 @@
   // is non-empty, then the resulting string_view is null terminated.
   // This is required to implement 'StatusMessageAsCStr(...)'
   std::string message_;
+  absl::InlinedVector<absl::SourceLocation, 1> source_locations_;
   std::unique_ptr<status_internal::Payloads> payloads_;
 };
 
diff --git a/absl/status/internal/statusor_internal.h b/absl/status/internal/statusor_internal.h
index 8a4e2f5..ccfdedb 100644
--- a/absl/status/internal/statusor_internal.h
+++ b/absl/status/internal/statusor_internal.h
@@ -60,7 +60,7 @@
 // Detects whether `T` is constructible or convertible from `StatusOr<U>`.
 template <typename T, typename U>
 using IsConstructibleOrConvertibleFromStatusOr =
-    absl::disjunction<std::is_constructible<T, StatusOr<U>&>,
+    std::disjunction<std::is_constructible<T, StatusOr<U>&>,
                       std::is_constructible<T, const StatusOr<U>&>,
                       std::is_constructible<T, StatusOr<U>&&>,
                       std::is_constructible<T, const StatusOr<U>&&>,
@@ -73,7 +73,7 @@
 // `StatusOr<U>`.
 template <typename T, typename U>
 using IsConstructibleOrConvertibleOrAssignableFromStatusOr =
-    absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
+    std::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
                       std::is_assignable<T&, StatusOr<U>&>,
                       std::is_assignable<T&, const StatusOr<U>&>,
                       std::is_assignable<T&, StatusOr<U>&&>,
@@ -83,7 +83,7 @@
 // when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`.
 template <typename T, typename U>
 struct IsDirectInitializationAmbiguous
-    : public absl::conditional_t<
+    : public std::conditional_t<
           std::is_same<absl::remove_cvref_t<U>, U>::value, std::false_type,
           IsDirectInitializationAmbiguous<T, absl::remove_cvref_t<U>>> {};
 
@@ -95,7 +95,7 @@
 // temporaries.
 // REQUIRES: T and U are references.
 template <typename T, typename U>
-using IsReferenceConversionValid = absl::conjunction<  //
+using IsReferenceConversionValid = std::conjunction<  //
     std::is_reference<T>, std::is_reference<U>,
     // The references are convertible. This checks for
     // lvalue/rvalue compatibility.
@@ -108,13 +108,13 @@
 // Checks against the constraints of the direction initialization, i.e. when
 // `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution.
 template <typename T, typename U>
-using IsDirectInitializationValid = absl::disjunction<
+using IsDirectInitializationValid = std::disjunction<
     // Short circuits if T is basically U.
     std::is_same<T, absl::remove_cvref_t<U>>,  //
     std::conditional_t<
         std::is_reference_v<T>,  //
         IsReferenceConversionValid<T, U>,
-        absl::negation<absl::disjunction<
+        std::negation<std::disjunction<
             std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>,
             std::is_same<absl::Status, absl::remove_cvref_t<U>>,
             std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>,
@@ -132,7 +132,7 @@
 //   s1 = s2;  // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`?
 template <typename T, typename U>
 struct IsForwardingAssignmentAmbiguous
-    : public absl::conditional_t<
+    : public std::conditional_t<
           std::is_same<absl::remove_cvref_t<U>, U>::value, std::false_type,
           IsForwardingAssignmentAmbiguous<T, absl::remove_cvref_t<U>>> {};
 
@@ -143,91 +143,91 @@
 // Checks against the constraints of the forwarding assignment, i.e. whether
 // `StatusOr<T>::operator(U&&)` should participate in overload resolution.
 template <typename T, typename U>
-using IsForwardingAssignmentValid = absl::disjunction<
+using IsForwardingAssignmentValid = std::disjunction<
     // Short circuits if T is basically U.
     std::is_same<T, absl::remove_cvref_t<U>>,
-    absl::negation<absl::disjunction<
+    std::negation<std::disjunction<
         std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>,
         std::is_same<absl::Status, absl::remove_cvref_t<U>>,
         std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>,
         IsForwardingAssignmentAmbiguous<T, U>>>>;
 
 template <bool Value, typename T>
-using Equality = std::conditional_t<Value, T, absl::negation<T>>;
+using Equality = std::conditional_t<Value, T, std::negation<T>>;
 
 template <bool Explicit, typename T, typename U, bool Lifetimebound>
-using IsConstructionValid = absl::conjunction<
+using IsConstructionValid = std::conjunction<
     Equality<Lifetimebound,
-             absl::disjunction<
+             std::disjunction<
                  std::is_reference<T>,
                  type_traits_internal::IsLifetimeBoundAssignment<T, U>>>,
     IsDirectInitializationValid<T, U&&>, std::is_constructible<T, U&&>,
     Equality<!Explicit, std::is_convertible<U&&, T>>,
-    absl::disjunction<
+    std::disjunction<
         std::is_same<T, absl::remove_cvref_t<U>>,
-        absl::conjunction<
+        std::conjunction<
             std::conditional_t<
                 Explicit,
-                absl::negation<std::is_constructible<absl::Status, U&&>>,
-                absl::negation<std::is_convertible<U&&, absl::Status>>>,
-            absl::negation<
+                std::negation<std::is_constructible<absl::Status, U&&>>,
+                std::negation<std::is_convertible<U&&, absl::Status>>>,
+            std::negation<
                 internal_statusor::HasConversionOperatorToStatusOr<T, U&&>>>>>;
 
 template <typename T, typename U, bool Lifetimebound>
-using IsAssignmentValid = absl::conjunction<
+using IsAssignmentValid = std::conjunction<
     Equality<Lifetimebound,
-             absl::disjunction<
+             std::disjunction<
                  std::is_reference<T>,
                  type_traits_internal::IsLifetimeBoundAssignment<T, U>>>,
     std::conditional_t<std::is_reference_v<T>,
                        IsReferenceConversionValid<T, U&&>,
-                       absl::conjunction<std::is_constructible<T, U&&>,
+                       std::conjunction<std::is_constructible<T, U&&>,
                                          std::is_assignable<T&, U&&>>>,
-    absl::disjunction<
+    std::disjunction<
         std::is_same<T, absl::remove_cvref_t<U>>,
-        absl::conjunction<
-            absl::negation<std::is_convertible<U&&, absl::Status>>,
-            absl::negation<HasConversionOperatorToStatusOr<T, U&&>>>>,
+        std::conjunction<
+            std::negation<std::is_convertible<U&&, absl::Status>>,
+            std::negation<HasConversionOperatorToStatusOr<T, U&&>>>>,
     IsForwardingAssignmentValid<T, U&&>>;
 
 template <bool Explicit, typename T, typename U>
-using IsConstructionFromStatusValid = absl::conjunction<
-    absl::negation<std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>>,
-    absl::negation<std::is_same<T, absl::remove_cvref_t<U>>>,
-    absl::negation<std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>>,
+using IsConstructionFromStatusValid = std::conjunction<
+    std::negation<std::is_same<absl::StatusOr<T>, absl::remove_cvref_t<U>>>,
+    std::negation<std::is_same<T, absl::remove_cvref_t<U>>>,
+    std::negation<std::is_same<absl::in_place_t, absl::remove_cvref_t<U>>>,
     Equality<!Explicit, std::is_convertible<U, absl::Status>>,
     std::is_constructible<absl::Status, U>,
-    absl::negation<HasConversionOperatorToStatusOr<T, U>>>;
+    std::negation<HasConversionOperatorToStatusOr<T, U>>>;
 
 template <bool Explicit, typename T, typename U, bool Lifetimebound,
           typename UQ>
-using IsConstructionFromStatusOrValid = absl::conjunction<
-    absl::negation<std::is_same<T, U>>,
+using IsConstructionFromStatusOrValid = std::conjunction<
+    std::negation<std::is_same<T, U>>,
     // If `T` is a reference, then U must be a compatible one.
-    absl::disjunction<absl::negation<std::is_reference<T>>,
+    std::disjunction<std::negation<std::is_reference<T>>,
                       IsReferenceConversionValid<T, U>>,
     Equality<Lifetimebound,
              type_traits_internal::IsLifetimeBoundAssignment<T, U>>,
     std::is_constructible<T, UQ>,
     Equality<!Explicit, std::is_convertible<UQ, T>>,
-    absl::negation<IsConstructibleOrConvertibleFromStatusOr<T, U>>>;
+    std::negation<IsConstructibleOrConvertibleFromStatusOr<T, U>>>;
 
 template <typename T, typename U, bool Lifetimebound>
-using IsStatusOrAssignmentValid = absl::conjunction<
-    absl::negation<std::is_same<T, absl::remove_cvref_t<U>>>,
+using IsStatusOrAssignmentValid = std::conjunction<
+    std::negation<std::is_same<T, absl::remove_cvref_t<U>>>,
     Equality<Lifetimebound,
              type_traits_internal::IsLifetimeBoundAssignment<T, U>>,
     std::is_constructible<T, U>, std::is_assignable<T, U>,
-    absl::negation<IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+    std::negation<IsConstructibleOrConvertibleOrAssignableFromStatusOr<
         T, absl::remove_cvref_t<U>>>>;
 
 template <typename T, typename U, bool Lifetimebound>
-using IsValueOrValid = absl::conjunction<
+using IsValueOrValid = std::conjunction<
     // If `T` is a reference, then U must be a compatible one.
-    absl::disjunction<absl::negation<std::is_reference<T>>,
+    std::disjunction<std::negation<std::is_reference<T>>,
                       IsReferenceConversionValid<T, U>>,
     Equality<Lifetimebound,
-             absl::disjunction<
+             std::disjunction<
                  std::is_reference<T>,
                  type_traits_internal::IsLifetimeBoundAssignment<T, U>>>>;
 
@@ -331,7 +331,7 @@
   }
 
   template <typename U,
-            absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
+            std::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
                               int> = 0>
   explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
     EnsureNotOk();
diff --git a/absl/status/status.cc b/absl/status/status.cc
index 479c39f..8cd0a84 100644
--- a/absl/status/status.cc
+++ b/absl/status/status.cc
@@ -37,6 +37,7 @@
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
+#include "absl/types/source_location.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -104,11 +105,36 @@
   return kMovedFrom.get();
 }
 
-Status::Status(absl::StatusCode code, absl::string_view msg)
-    : rep_(CodeToInlinedRep(code)) {
-  if (code != absl::StatusCode::kOk && !msg.empty()) {
-    rep_ = PointerToRep(new status_internal::StatusRep(code, msg, nullptr));
+absl::Status absl::Status::MakeNonOkStatusWithOkCode(
+    absl::string_view message) {
+  return absl::Status(
+      absl::Status::PointerToRep(new absl::status_internal::StatusRep(
+          absl::StatusCode::kOk, message, nullptr)));
+}
+
+uintptr_t Status::MakeRep(uintptr_t inlined_rep, absl::string_view msg,
+                          absl::SourceLocation loc) {
+  bool ok = inlined_rep == CodeToInlinedRep(absl::StatusCode::kOk);
+  if (ok) return inlined_rep;
+  if (msg.empty()
+  ) {
+    return inlined_rep;
   }
+  auto* rep = new status_internal::StatusRep(InlinedRepToCode(inlined_rep), msg,
+                                             nullptr);
+  if (loc.file_name()[0] != '\0') {
+    rep->AddSourceLocation(loc);
+  }
+  return PointerToRep(rep);
+}
+
+uintptr_t Status::AddSourceLocationImpl(uintptr_t rep,
+                                        absl::SourceLocation loc) {
+  if (IsInlined(rep)) return rep;
+  if (loc.file_name()[0] == '\0') return rep;
+  status_internal::StatusRep* rep_ptr = PrepareToModify(rep);
+  rep_ptr->AddSourceLocation(loc);
+  return PointerToRep(rep_ptr);
 }
 
 status_internal::StatusRep* absl_nonnull Status::PrepareToModify(
@@ -132,68 +158,74 @@
   return os;
 }
 
-Status AbortedError(absl::string_view message) {
-  return Status(absl::StatusCode::kAborted, message);
+Status AbortedError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kAborted, message, loc);
 }
 
-Status AlreadyExistsError(absl::string_view message) {
-  return Status(absl::StatusCode::kAlreadyExists, message);
+Status AlreadyExistsError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kAlreadyExists, message, loc);
 }
 
-Status CancelledError(absl::string_view message) {
-  return Status(absl::StatusCode::kCancelled, message);
+Status CancelledError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kCancelled, message, loc);
 }
 
-Status DataLossError(absl::string_view message) {
-  return Status(absl::StatusCode::kDataLoss, message);
+Status DataLossError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kDataLoss, message, loc);
 }
 
-Status DeadlineExceededError(absl::string_view message) {
-  return Status(absl::StatusCode::kDeadlineExceeded, message);
+Status DeadlineExceededError(absl::string_view message,
+                             absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kDeadlineExceeded, message, loc);
 }
 
-Status FailedPreconditionError(absl::string_view message) {
-  return Status(absl::StatusCode::kFailedPrecondition, message);
+Status FailedPreconditionError(absl::string_view message,
+                               absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kFailedPrecondition, message, loc);
 }
 
-Status InternalError(absl::string_view message) {
-  return Status(absl::StatusCode::kInternal, message);
+Status InternalError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kInternal, message, loc);
 }
 
-Status InvalidArgumentError(absl::string_view message) {
-  return Status(absl::StatusCode::kInvalidArgument, message);
+Status InvalidArgumentError(absl::string_view message,
+                            absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kInvalidArgument, message, loc);
 }
 
-Status NotFoundError(absl::string_view message) {
-  return Status(absl::StatusCode::kNotFound, message);
+Status NotFoundError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kNotFound, message, loc);
 }
 
-Status OutOfRangeError(absl::string_view message) {
-  return Status(absl::StatusCode::kOutOfRange, message);
+Status OutOfRangeError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kOutOfRange, message, loc);
 }
 
-Status PermissionDeniedError(absl::string_view message) {
-  return Status(absl::StatusCode::kPermissionDenied, message);
+Status PermissionDeniedError(absl::string_view message,
+                             absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kPermissionDenied, message, loc);
 }
 
-Status ResourceExhaustedError(absl::string_view message) {
-  return Status(absl::StatusCode::kResourceExhausted, message);
+Status ResourceExhaustedError(absl::string_view message,
+                              absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kResourceExhausted, message, loc);
 }
 
-Status UnauthenticatedError(absl::string_view message) {
-  return Status(absl::StatusCode::kUnauthenticated, message);
+Status UnauthenticatedError(absl::string_view message,
+                            absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kUnauthenticated, message, loc);
 }
 
-Status UnavailableError(absl::string_view message) {
-  return Status(absl::StatusCode::kUnavailable, message);
+Status UnavailableError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kUnavailable, message, loc);
 }
 
-Status UnimplementedError(absl::string_view message) {
-  return Status(absl::StatusCode::kUnimplemented, message);
+Status UnimplementedError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kUnimplemented, message, loc);
 }
 
-Status UnknownError(absl::string_view message) {
-  return Status(absl::StatusCode::kUnknown, message);
+Status UnknownError(absl::string_view message, absl::SourceLocation loc) {
+  return Status(absl::StatusCode::kUnknown, message, loc);
 }
 
 bool IsAborted(const Status& status) {
@@ -404,9 +436,10 @@
 }
 }  // namespace
 
-Status ErrnoToStatus(int error_number, absl::string_view message) {
+Status ErrnoToStatus(int error_number, absl::string_view message,
+                     absl::SourceLocation loc) {
   return Status(ErrnoToStatusCode(error_number),
-                MessageForErrnoToStatus(error_number, message));
+                MessageForErrnoToStatus(error_number, message), loc);
 }
 
 const char* absl_nonnull StatusMessageAsCStr(const Status& status) {
diff --git a/absl/status/status.h b/absl/status/status.h
index f81f912..62efd46 100644
--- a/absl/status/status.h
+++ b/absl/status/status.h
@@ -68,6 +68,8 @@
 #include "absl/strings/cord.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
+#include "absl/types/source_location.h"
+#include "absl/types/span.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -306,6 +308,8 @@
   kWithNoExtraData = 0,
   // ToString will contain the payloads.
   kWithPayload = 1 << 0,
+  // ToString will contain the source locations.
+  kWithSourceLocation = 1 << 1,
   // ToString will include all the extra data this Status has.
   kWithEverything = ~kWithNoExtraData,
   // Default mode used by ToString. Its exact value might change in the future.
@@ -444,12 +448,28 @@
   Status();
 
   // Creates a status in the canonical error space with the specified
-  // `absl::StatusCode` and error message.  If `code == absl::StatusCode::kOk`,  // NOLINT
+  // `absl::StatusCode` and error message.  If `code == absl::StatusCode::kOk`,
   // `msg` is ignored and an object identical to an OK status is constructed.
   //
-  // The `msg` string must be in UTF-8. The implementation may complain (e.g.,  // NOLINT
+  // The `msg` string must be in UTF-8. The implementation may complain (e.g.,
   // by printing a warning) if it is not.
-  Status(absl::StatusCode code, absl::string_view msg);
+  //
+  // The `loc` is the SourceLocation of the callsite. It will be stored in the
+  // Status iff `code != absl::StatusCode::kOk` and `!msg.empty()`.
+  Status(absl::StatusCode code, absl::string_view msg,
+         absl::SourceLocation loc = SourceLocation::current());
+
+  // Create a status from a `base_status` and a `loc`. The `loc` will be
+  // appended to the location chain of the new status, iff the `base_status` is
+  // not ok and has non-empty msg.
+  Status(const Status& base_status, absl::SourceLocation loc)
+      : Status(base_status) {
+    AddSourceLocation(loc);
+  }
+  Status(Status&& base_status, absl::SourceLocation loc)
+      : Status(std::move(base_status)) {
+    AddSourceLocation(loc);
+  }
 
   Status(const Status&);
   Status& operator=(const Status& x);
@@ -614,16 +634,88 @@
       absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)
       const;
 
+  absl::Span<const absl::SourceLocation> GetSourceLocations() const {
+    if (IsInlined(rep_)) return {};
+    return RepToPointer(rep_)->GetSourceLocations();
+  }
+  // Appends the `loc` to the current location chain inside the status, iff the
+  // status is non-ok and contains a non-empty message.
+  void AddSourceLocation(
+      absl::SourceLocation loc = absl::SourceLocation::current()) {
+    if (ok()) return;
+    rep_ = AddSourceLocationImpl(rep_, loc);
+    ABSL_ATTRIBUTE_UNUSED bool okay = ok();
+    // This hint tells the optimizer that the status is still not ok after the
+    // AddSourceLocation() call. This is useful when passing a known !ok status
+    // to StatusOr. StatusOr checks for ok() on its constructor and this assume
+    // helps the optimizer remove that check.
+    ABSL_ASSUME(!okay);
+  }
+
+  // Status::WithSourceLocation()
+  //
+  // Returns a copy of the current status, with `loc` appended to its location
+  // chain iff the status is non-ok and contains a non-empty message.
+  //
+  // Example:
+  //
+  //   if (Status status = Foo(); !status.ok()) {
+  //     return status.WithSourceLocation();
+  //   }
+  Status WithSourceLocation(
+      absl::SourceLocation loc = absl::SourceLocation::current()) const& {
+    return Status(*this, loc);
+  }
+
+  // Status::WithSourceLocation()
+  //
+  // Appends the `loc` to the current location chain inside the status iff the
+  // status is non-ok and contains a non-empty message, and returns an rvalue
+  // reference to `*this`.
+  //
+  // Example:
+  //
+  //   Status Finalize(...);
+  //
+  //   Status DoSomething(...) {
+  //     ...
+  //     return Finalize().WithSourceLocation();
+  //   }
+  ABSL_MUST_USE_RESULT Status&& WithSourceLocation(
+      absl::SourceLocation loc = absl::SourceLocation::current()) && {
+    AddSourceLocation(loc);
+    return std::move(*this);
+  }
+
  private:
   friend Status CancelledError();
 
+#ifndef SWIG
+  // Returns a `Status` object which is not `ok()` but
+  // `code() == absl::StatusCode::kOk`. This is necessary to be compatible with
+  // `Status` objects created with an error code in a custom `ErrorSpace` that
+  // is mapped to the canonical code `absl::StatusCode::kOk`.
+  static Status MakeNonOkStatusWithOkCode(absl::string_view message);
+
+  friend class absl::status_internal::StatusPrivateAccessor;
+#endif  // !SWIG
+
   // Creates a status in the canonical error space with the specified
   // code, and an empty error message.
   explicit Status(absl::StatusCode code);
 
+  // Delegate factory in header that ensures CodeToInlinedRep is inlined
+  // where possible.
+  static uintptr_t MakeRep(uintptr_t inlined_rep, absl::string_view msg,
+                           absl::SourceLocation loc);
+
   // Underlying constructor for status from a rep_.
   explicit Status(uintptr_t rep) : rep_(rep) {}
 
+  // An out-of-line AddSourceLocation that mutates rep directly.
+  static uintptr_t AddSourceLocationImpl(uintptr_t rep,
+                                         absl::SourceLocation loc);
+
   static void Ref(uintptr_t rep);
   static void Unref(uintptr_t rep);
 
@@ -741,22 +833,44 @@
 // These convenience functions create an `absl::Status` object with an error
 // code as indicated by the associated function name, using the error message
 // passed in `message`.
-Status AbortedError(absl::string_view message);
-Status AlreadyExistsError(absl::string_view message);
-Status CancelledError(absl::string_view message);
-Status DataLossError(absl::string_view message);
-Status DeadlineExceededError(absl::string_view message);
-Status FailedPreconditionError(absl::string_view message);
-Status InternalError(absl::string_view message);
-Status InvalidArgumentError(absl::string_view message);
-Status NotFoundError(absl::string_view message);
-Status OutOfRangeError(absl::string_view message);
-Status PermissionDeniedError(absl::string_view message);
-Status ResourceExhaustedError(absl::string_view message);
-Status UnauthenticatedError(absl::string_view message);
-Status UnavailableError(absl::string_view message);
-Status UnimplementedError(absl::string_view message);
-Status UnknownError(absl::string_view message);
+Status AbortedError(absl::string_view message,
+                    absl::SourceLocation loc = SourceLocation::current());
+Status AlreadyExistsError(absl::string_view message,
+                          absl::SourceLocation loc = SourceLocation::current());
+Status CancelledError(absl::string_view message,
+                      absl::SourceLocation loc = SourceLocation::current());
+Status DataLossError(absl::string_view message,
+                     absl::SourceLocation loc = SourceLocation::current());
+Status DeadlineExceededError(
+    absl::string_view message,
+    absl::SourceLocation loc = SourceLocation::current());
+Status FailedPreconditionError(
+    absl::string_view message,
+    absl::SourceLocation loc = SourceLocation::current());
+Status InternalError(absl::string_view message,
+                     absl::SourceLocation loc = SourceLocation::current());
+Status InvalidArgumentError(
+    absl::string_view message,
+    absl::SourceLocation loc = SourceLocation::current());
+Status NotFoundError(absl::string_view message,
+                     absl::SourceLocation loc = SourceLocation::current());
+Status OutOfRangeError(absl::string_view message,
+                       absl::SourceLocation loc = SourceLocation::current());
+Status PermissionDeniedError(
+    absl::string_view message,
+    absl::SourceLocation loc = SourceLocation::current());
+Status ResourceExhaustedError(
+    absl::string_view message,
+    absl::SourceLocation loc = SourceLocation::current());
+Status UnauthenticatedError(
+    absl::string_view message,
+    absl::SourceLocation loc = SourceLocation::current());
+Status UnavailableError(absl::string_view message,
+                        absl::SourceLocation loc = SourceLocation::current());
+Status UnimplementedError(absl::string_view message,
+                          absl::SourceLocation loc = SourceLocation::current());
+Status UnknownError(absl::string_view message,
+                    absl::SourceLocation loc = SourceLocation::current());
 
 // ErrnoToStatusCode()
 //
@@ -769,7 +883,8 @@
 //
 // Convenience function that creates a `absl::Status` using an `error_number`,
 // which should be an `errno` value.
-Status ErrnoToStatus(int error_number, absl::string_view message);
+Status ErrnoToStatus(int error_number, absl::string_view message,
+                     absl::SourceLocation loc = SourceLocation::current());
 
 //------------------------------------------------------------------------------
 // Implementation details follow
@@ -779,6 +894,10 @@
 
 inline Status::Status(absl::StatusCode code) : Status(CodeToInlinedRep(code)) {}
 
+inline Status::Status(absl::StatusCode code, absl::string_view msg,
+                      absl::SourceLocation loc)
+    : Status(MakeRep(CodeToInlinedRep(code), msg, loc)) {}
+
 inline Status::Status(const Status& x) : Status(x.rep_) { Ref(rep_); }
 
 inline Status& Status::operator=(const Status& x) {
diff --git a/absl/status/status_benchmark.cc b/absl/status/status_benchmark.cc
index a9146fb..539b783 100644
--- a/absl/status/status_benchmark.cc
+++ b/absl/status/status_benchmark.cc
@@ -13,7 +13,9 @@
 // limitations under the License.
 
 #include <utility>
+
 #include "absl/status/status.h"
+#include "absl/types/source_location.h"
 #include "benchmark/benchmark.h"
 
 namespace {
@@ -34,4 +36,14 @@
 }
 BENCHMARK(BM_CreateBad);
 
+void BM_AppendSourceLocation(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::Status s(absl::StatusCode::kInvalidArgument, "message");
+    benchmark::DoNotOptimize(s);
+    absl::Status s2(std::move(s), absl::SourceLocation::current());
+    benchmark::DoNotOptimize(s2);
+  }
+}
+BENCHMARK(BM_AppendSourceLocation);
+
 }  // namespace
diff --git a/absl/status/status_test.cc b/absl/status/status_test.cc
index f6ac0c0..ddf0be0 100644
--- a/absl/status/status_test.cc
+++ b/absl/status/status_test.cc
@@ -20,12 +20,15 @@
 #include <cstddef>
 #include <sstream>
 #include <utility>
+#include <vector>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/strings/cord.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/source_location.h"
 
 namespace {
 
@@ -46,9 +49,7 @@
 // its creator, and its classifier.
 struct ErrorTest {
   absl::StatusCode code;
-  using Creator = absl::Status (*)(
-      absl::string_view
-  );
+  using Creator = absl::Status (*)(absl::string_view, absl::SourceLocation);
   using Classifier = bool (*)(const absl::Status&);
   Creator creator;
   Classifier classifier;
@@ -90,9 +91,8 @@
     // expected error code and message.
     std::string message =
         absl::StrCat("error code ", test.code, " test message");
-    absl::Status status = test.creator(
-        message
-    );
+    absl::Status status =
+        test.creator(message, absl::SourceLocation::current());
     EXPECT_EQ(test.code, status.code());
     EXPECT_EQ(message, status.message());
 
@@ -342,32 +342,45 @@
   absl::Status status(absl::StatusCode::kInternal, "fail");
   { std::stringstream stream;
     stream << status;
-    EXPECT_EQ("INTERNAL: fail", stream.str());
+    EXPECT_THAT(stream.str(),
+                AllOf(HasSubstr("INTERNAL: fail"),
+                      HasSubstr("status_test.cc:")));
   }
   status.SetPayload("foo", absl::Cord("bar"));
   { std::stringstream stream;
     stream << status;
-    EXPECT_EQ("INTERNAL: fail [foo='bar']", stream.str());
+    EXPECT_THAT(stream.str(),
+                AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+                      HasSubstr("status_test.cc:")));
   }
   status.SetPayload("bar", absl::Cord("\377"));
   { std::stringstream stream;
     stream << status;
     EXPECT_THAT(stream.str(),
                 AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
-                      HasSubstr("[bar='\\xff']")));
+                      HasSubstr("[bar='\\xff']"),
+                      HasSubstr("status_test.cc:")));
   }
 }
 
 TEST(Status, AbslStringify) {
   absl::Status status(absl::StatusCode::kInternal, "fail");
-  EXPECT_EQ("INTERNAL: fail", absl::StrCat(status));
-  EXPECT_EQ("INTERNAL: fail", absl::StrFormat("%v", status));
+  EXPECT_THAT(absl::StrCat(status),
+              AllOf(HasSubstr("INTERNAL: fail"),
+                    HasSubstr("status_test.cc:")));
+  EXPECT_THAT(absl::StrFormat("%v", status),
+              AllOf(HasSubstr("INTERNAL: fail"),
+                    HasSubstr("status_test.cc:")));
+  EXPECT_EQ(absl::StrCat(status), absl::StrFormat("%v", status));
   status.SetPayload("foo", absl::Cord("bar"));
-  EXPECT_EQ("INTERNAL: fail [foo='bar']", absl::StrCat(status));
+  EXPECT_THAT(absl::StrCat(status),
+              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+                    HasSubstr("status_test.cc:")));
   status.SetPayload("bar", absl::Cord("\377"));
   EXPECT_THAT(absl::StrCat(status),
               AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
-                    HasSubstr("[bar='\\xff']")));
+                    HasSubstr("[bar='\\xff']"),
+                    HasSubstr("status_test.cc:")));
 }
 
 TEST(Status, OstreamEqStringify) {
@@ -577,4 +590,421 @@
   EXPECT_EQ(status.message(), "Cannot open 'path': No such file or directory");
 }
 
+#ifdef ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE
+#define GET_SOURCE_LOCATION(offset) __builtin_LINE() - offset
+#else
+#define GET_SOURCE_LOCATION(offset) 1
+#endif
+
+void CheckSourceLocation(
+    const absl::Status& status, std::vector<int> lines = {},
+    absl::SourceLocation loc = absl::SourceLocation::current()) {
+  ASSERT_EQ(status.GetSourceLocations().size(), lines.size())
+      << "Size check failed at " << loc.line();
+  for (size_t i = 0; i < lines.size(); ++i) {
+    EXPECT_EQ(absl::string_view(status.GetSourceLocations()[i].file_name()),
+              absl::string_view(loc.file_name()))
+        << "File name check failed at " << loc.line();
+    EXPECT_EQ(status.GetSourceLocations()[i].line(), lines[i])
+        << "Line check failed at " << loc.line();
+  }
+}
+
+TEST(Status, ConstructorCheckSourceLocation) {
+  {
+    const absl::Status a;
+    const absl::Status b = a;
+    for (const absl::Status& status : {a, b}) {
+      EXPECT_TRUE(status.ok());
+      EXPECT_EQ(absl::StatusCode::kOk, status.code());
+      CheckSourceLocation(status);
+    }
+  }
+  {
+    const absl::Status a(absl::StatusCode::kInternal, "message",
+                         absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+    const absl::Status b = a;
+    for (const absl::Status& status : {a, b}) {
+      EXPECT_FALSE(status.ok());
+      EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+      CheckSourceLocation(status, {line});
+    }
+  }
+  {
+    const absl::Status a(absl::StatusCode::kInternal, "message",
+                         absl::SourceLocation());
+    const absl::Status b = a;
+    for (const absl::Status& status : {a, b}) {
+      EXPECT_FALSE(status.ok());
+      EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+      CheckSourceLocation(status);
+    }
+  }
+  {
+    const absl::Status a(absl::StatusCode::kInternal, "",
+                         absl::SourceLocation::current());
+    const absl::Status b = a;
+    for (const absl::Status& status : {a, b}) {
+      EXPECT_FALSE(status.ok());
+      EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+      CheckSourceLocation(status);
+    }
+  }
+  {
+    const absl::Status a(absl::StatusCode::kInternal, "",
+                         absl::SourceLocation());
+    const absl::Status b = a;
+    for (const absl::Status& status : {a, b}) {
+      EXPECT_FALSE(status.ok());
+      EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+      CheckSourceLocation(status);
+    }
+  }
+}
+
+TEST(Status, SourceLocationConstructor) {
+  {
+    // OK status doesn't save source locations.
+    const absl::Status original;
+    const absl::Status status(original, absl::SourceLocation());
+    EXPECT_TRUE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kOk, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // OK status doesn't save source locations.
+    const absl::Status original;
+    const absl::Status status(original, absl::SourceLocation::current());
+    EXPECT_TRUE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kOk, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // Non-ok Status with non-empty msg can save source locations with
+    // non-nullptr filename.
+    const absl::Status original(absl::StatusCode::kInternal, "message",
+                                absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+    // Default absl::SourceLocation cannot be saved into the chain.
+    const absl::Status status(original, absl::SourceLocation());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status, {line});
+  }
+  {
+    const absl::Status original(absl::StatusCode::kInternal, "message",
+                                absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+
+    const absl::Status status(original, absl::SourceLocation::current());
+    int line2 = GET_SOURCE_LOCATION(1);
+
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status, {line, line2});
+  }
+  {
+    // Non-OK status with empty msg doesn't save source locations.
+    const absl::Status original(absl::StatusCode::kInternal, "",
+                                absl::SourceLocation::current());
+    const absl::Status status(original, absl::SourceLocation());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // Non-OK status with empty msg doesn't save source locations.
+    const absl::Status original(absl::StatusCode::kInternal, "",
+                                absl::SourceLocation::current());
+    const absl::Status status(original, absl::SourceLocation::current());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // Non-OK status with empty msg doesn't save source locations from default
+    // constructor.
+    const absl::Status original(absl::StatusCode::kInternal, "",
+                                absl::SourceLocation());
+    const absl::Status status(original, absl::SourceLocation());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // Non-OK status with empty msg doesn't save source locations.
+    const absl::Status original(absl::StatusCode::kInternal, "",
+                                absl::SourceLocation());
+    const absl::Status status(original, absl::SourceLocation::current());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    const absl::Status original(absl::StatusCode::kInternal, "message",
+                                absl::SourceLocation());
+    const absl::Status status(original, absl::SourceLocation());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    const absl::Status original(absl::StatusCode::kInternal, "message",
+                                absl::SourceLocation());
+    const absl::Status status(original, absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status, {line});
+  }
+}
+
+TEST(Status, SourceLocationWithMoveConstructor) {
+  {
+    // OK status doesn't save source locations.
+    absl::Status original;
+    const absl::Status status(std::move(original), absl::SourceLocation());
+    EXPECT_TRUE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kOk, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // OK status doesn't save source locations.
+    absl::Status original;
+    const absl::Status status(std::move(original),
+                              absl::SourceLocation::current());
+    EXPECT_TRUE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kOk, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // Non-ok Status with non-empty msg can save source locations with
+    // non-nullptr filename.
+    absl::Status original(absl::StatusCode::kInternal, "message",
+                          absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+    // Default absl::SourceLocation cannot be saved into the chain.
+    const absl::Status status(std::move(original), absl::SourceLocation());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status, {line});
+  }
+  {
+    absl::Status original(absl::StatusCode::kInternal, "message",
+                          absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+
+    const absl::Status status(std::move(original),
+                              absl::SourceLocation::current());
+    int line2 = GET_SOURCE_LOCATION(1);
+
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status, {line, line2});
+  }
+  {
+    // Non-OK status with empty msg doesn't save source locations.
+    absl::Status original(absl::StatusCode::kInternal, "",
+                          absl::SourceLocation::current());
+    const absl::Status status(std::move(original), absl::SourceLocation());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // Non-OK status with empty msg doesn't save source locations.
+    absl::Status original(absl::StatusCode::kInternal, "",
+                          absl::SourceLocation::current());
+    const absl::Status status(std::move(original),
+                              absl::SourceLocation::current());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // Non-OK status with empty msg doesn't save source locations from default
+    // constructor.
+    absl::Status original(absl::StatusCode::kInternal, "",
+                          absl::SourceLocation());
+    const absl::Status status(std::move(original), absl::SourceLocation());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    // Non-OK status with empty msg doesn't save source locations.
+    absl::Status original(absl::StatusCode::kInternal, "",
+                          absl::SourceLocation());
+    const absl::Status status(std::move(original),
+                              absl::SourceLocation::current());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    absl::Status original(absl::StatusCode::kInternal, "message",
+                          absl::SourceLocation());
+    const absl::Status status(std::move(original), absl::SourceLocation());
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status);
+  }
+  {
+    absl::Status original(absl::StatusCode::kInternal, "message",
+                          absl::SourceLocation());
+    const absl::Status status(std::move(original),
+                              absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    CheckSourceLocation(status, {line});
+  }
+}
+
+TEST(Status, AddSourceLocation) {
+  int max_iter = 10;
+  {
+    // Status that ignores source location.
+    absl::Status status_ignores_source_location[] = {
+        absl::Status(),
+        absl::Status(absl::StatusCode::kInternal, "")};
+    for (absl::Status& s : status_ignores_source_location) {
+      for (int i = 0; i < max_iter; ++i) {
+        s.AddSourceLocation(absl::SourceLocation::current());
+        s.AddSourceLocation(absl::SourceLocation());
+      }
+      CheckSourceLocation(s);
+    }
+  }
+  {
+    // Default SourceLocation is not added.
+    absl::Status status(absl::StatusCode::kInternal, "foo",
+                        absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+    for (int i = 0; i < max_iter; ++i) {
+      status.AddSourceLocation(absl::SourceLocation());
+    }
+    CheckSourceLocation(status, {line});
+  }
+  {
+    // Default SourceLocation is not added.
+    absl::Status status(absl::StatusCode::kInternal, "foo",
+                        absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+    std::vector<int> lines = {line};
+    lines.reserve(1 + max_iter);
+    for (int i = 0; i < max_iter; ++i) {
+      status.AddSourceLocation(absl::SourceLocation::current());
+      lines.push_back(GET_SOURCE_LOCATION(1));
+    }
+    CheckSourceLocation(status, lines);
+  }
+}
+
+TEST(Status, WithSourceLocationCopy) {
+  absl::Status original(absl::StatusCode::kInternal, "message",
+                        absl::SourceLocation::current());
+  int line = GET_SOURCE_LOCATION(1);
+
+  const absl::Status status =
+      original.WithSourceLocation(absl::SourceLocation::current());
+  int line2 = GET_SOURCE_LOCATION(1);
+
+  CheckSourceLocation(original, {line});
+  CheckSourceLocation(status, {line, line2});
+  EXPECT_EQ(original, status);
+}
+
+absl::Status&& IsRvalueStatus(absl::Status&& s) { return std::move(s); }
+
+TEST(Status, WithSourceLocationMove) {
+  absl::Status original(absl::StatusCode::kInternal, "message",
+                        absl::SourceLocation::current());
+  int line = GET_SOURCE_LOCATION(1);
+
+  const absl::Status status = IsRvalueStatus(
+      std::move(original).WithSourceLocation(absl::SourceLocation::current()));
+  int line2 = GET_SOURCE_LOCATION(1);
+
+  CheckSourceLocation(status, {line, line2});
+  EXPECT_FALSE(status.ok());
+  EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+}
+
+TEST(Status, CopyOnWriteSourceLocations) {
+  absl::Status source(absl::StatusCode::kInvalidArgument, "fail",
+                      absl::SourceLocation::current());
+  EXPECT_EQ(source.GetSourceLocations().size(), 1);
+  absl::Status copy = source;
+  EXPECT_EQ(copy.GetSourceLocations().size(), 1);
+  copy.AddSourceLocation(absl::SourceLocation::current());  // Copy rep.
+  EXPECT_EQ(copy.GetSourceLocations().size(), 2);
+  EXPECT_EQ(source.GetSourceLocations().size(), 1);
+}
+
+TEST(Status, SourceLocationToStringMode) {
+  absl::Status s(absl::StatusCode::kInternal, "fail",
+                 absl::SourceLocation::current());
+  int line = GET_SOURCE_LOCATION(1);
+  std::string source_location_string = "\n=== Source Location Trace: ===";
+  std::string source_location_stack = absl::StrCat(
+      absl::SourceLocation::current().file_name(), ":", line, "\n");
+
+  s.SetPayload("foo", absl::Cord("bar"));
+
+  EXPECT_EQ("INTERNAL: fail",
+            s.ToString(absl::StatusToStringMode::kWithNoExtraData));
+
+  EXPECT_EQ("INTERNAL: fail",
+            s.ToString(~absl::StatusToStringMode::kWithSourceLocation &
+                       ~absl::StatusToStringMode::kWithPayload));
+  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithSourceLocation |
+                         absl::StatusToStringMode::kWithPayload),
+              AllOf(HasSubstr("INTERNAL: fail [foo='bar']"),
+                    HasSubstr(source_location_string),
+                    HasSubstr(source_location_stack)));
+
+  s.SetPayload("bar", absl::Cord("\377"));
+
+  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithEverything),
+              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+                    HasSubstr("[bar='\\xff']"),
+                    HasSubstr(source_location_string),
+                    HasSubstr(source_location_stack)));
+  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload |
+                         absl::StatusToStringMode::kWithSourceLocation),
+              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+                    HasSubstr("[bar='\\xff']"),
+                    HasSubstr(source_location_string),
+                    HasSubstr(source_location_stack)));
+  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithSourceLocation),
+              AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")),
+                    Not(HasSubstr("[bar='\\xff']")),
+                    HasSubstr(source_location_string),
+                    HasSubstr(source_location_stack)));
+  EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload),
+              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+                    HasSubstr("[bar='\\xff']"),
+                    Not(HasSubstr(source_location_string)),
+                    Not(HasSubstr(source_location_stack))));
+}
+
+TEST(Status, StackTracePayloadOverflow) {
+  // Stack must have the same layout as status_internal::StackTracePayload.
+  struct Stack {
+    size_t size;
+    void* frames[20];
+  } stack;
+  stack.size = 200;  // Overflows frames.
+
+  absl::Status status = absl::CancelledError();
+  status.SetPayload("AbslStatusStackTracePayload",
+                    absl::Cord(absl::string_view(
+                        reinterpret_cast<const char*>(&stack), sizeof(stack))));
+
+  // An unchecked overflow should be detected by ASAN/MSAN on the next line.
+  static_cast<void>(status.ToString(absl::StatusToStringMode::kWithEverything));
+}
+
 }  // namespace
diff --git a/absl/status/statusor.h b/absl/status/statusor.h
index 2427d24..0af1d75 100644
--- a/absl/status/statusor.h
+++ b/absl/status/statusor.h
@@ -54,6 +54,8 @@
 #include "absl/strings/has_absl_stringify.h"
 #include "absl/strings/has_ostream_operator.h"
 #include "absl/strings/str_format.h"
+#include "absl/types/source_location.h"
+#include "absl/types/span.h"
 #include "absl/types/variant.h"
 #include "absl/utility/utility.h"
 
@@ -245,50 +247,50 @@
   // is explicit if and only if the corresponding construction of `T` from `U`
   // is explicit. (This constructor inherits its explicitness from the
   // underlying constructor.)
-  template <typename U, absl::enable_if_t<
+  template <typename U, std::enable_if_t<
                             internal_statusor::IsConstructionFromStatusOrValid<
                                 false, T, U, false, const U&>::value,
                             int> = 0>
   StatusOr(const StatusOr<U>& other)  // NOLINT
       : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
-  template <typename U, absl::enable_if_t<
+  template <typename U, std::enable_if_t<
                             internal_statusor::IsConstructionFromStatusOrValid<
                                 false, T, U, true, const U&>::value,
                             int> = 0>
   StatusOr(const StatusOr<U>& other ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT
       : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
-  template <typename U, absl::enable_if_t<
+  template <typename U, std::enable_if_t<
                             internal_statusor::IsConstructionFromStatusOrValid<
                                 true, T, U, false, const U&>::value,
                             int> = 0>
   explicit StatusOr(const StatusOr<U>& other)
       : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
-  template <typename U, absl::enable_if_t<
+  template <typename U, std::enable_if_t<
                             internal_statusor::IsConstructionFromStatusOrValid<
                                 true, T, U, true, const U&>::value,
                             int> = 0>
   explicit StatusOr(const StatusOr<U>& other ABSL_ATTRIBUTE_LIFETIME_BOUND)
       : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
 
-  template <typename U, absl::enable_if_t<
+  template <typename U, std::enable_if_t<
                             internal_statusor::IsConstructionFromStatusOrValid<
                                 false, T, U, false, U&&>::value,
                             int> = 0>
   StatusOr(StatusOr<U>&& other)  // NOLINT
       : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
-  template <typename U, absl::enable_if_t<
+  template <typename U, std::enable_if_t<
                             internal_statusor::IsConstructionFromStatusOrValid<
                                 false, T, U, true, U&&>::value,
                             int> = 0>
   StatusOr(StatusOr<U>&& other ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT
       : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
-  template <typename U, absl::enable_if_t<
+  template <typename U, std::enable_if_t<
                             internal_statusor::IsConstructionFromStatusOrValid<
                                 true, T, U, false, U&&>::value,
                             int> = 0>
   explicit StatusOr(StatusOr<U>&& other)
       : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
-  template <typename U, absl::enable_if_t<
+  template <typename U, std::enable_if_t<
                             internal_statusor::IsConstructionFromStatusOrValid<
                                 true, T, U, true, U&&>::value,
                             int> = 0>
@@ -315,7 +317,7 @@
   // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly
   // assigned from `StatusOr<U>`.
   template <typename U,
-            absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<
+            std::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<
                                   T, const U&, false>::value,
                               int> = 0>
   StatusOr& operator=(const StatusOr<U>& other) {
@@ -323,7 +325,7 @@
     return *this;
   }
   template <typename U,
-            absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<
+            std::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<
                                   T, const U&, true>::value,
                               int> = 0>
   StatusOr& operator=(const StatusOr<U>& other ABSL_ATTRIBUTE_LIFETIME_BOUND) {
@@ -331,7 +333,7 @@
     return *this;
   }
   template <typename U,
-            absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<
+            std::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<
                                   T, U&&, false>::value,
                               int> = 0>
   StatusOr& operator=(StatusOr<U>&& other) {
@@ -339,7 +341,7 @@
     return *this;
   }
   template <typename U,
-            absl::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<
+            std::enable_if_t<internal_statusor::IsStatusOrAssignmentValid<
                                   T, U&&, true>::value,
                               int> = 0>
   StatusOr& operator=(StatusOr<U>&& other ABSL_ATTRIBUTE_LIFETIME_BOUND) {
@@ -359,18 +361,18 @@
   // In optimized builds, passing absl::OkStatus() here will have the effect
   // of passing absl::StatusCode::kInternal as a fallback.
   template <typename U = absl::Status,
-            absl::enable_if_t<internal_statusor::IsConstructionFromStatusValid<
+            std::enable_if_t<internal_statusor::IsConstructionFromStatusValid<
                                   false, T, U>::value,
                               int> = 0>
   StatusOr(U&& v) : Base(std::forward<U>(v)) {}
 
   template <typename U = absl::Status,
-            absl::enable_if_t<internal_statusor::IsConstructionFromStatusValid<
+            std::enable_if_t<internal_statusor::IsConstructionFromStatusValid<
                                   true, T, U>::value,
                               int> = 0>
   explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {}
   template <typename U = absl::Status,
-            absl::enable_if_t<internal_statusor::IsConstructionFromStatusValid<
+            std::enable_if_t<internal_statusor::IsConstructionFromStatusValid<
                                   false, T, U>::value,
                               int> = 0>
   StatusOr& operator=(U&& v) {
@@ -427,26 +429,26 @@
   // ambiguity, this constructor is disabled if `U` is a `StatusOr<J>`, where
   // `J` is convertible to `T`.
   template <typename U = T,
-            absl::enable_if_t<internal_statusor::IsConstructionValid<
+            std::enable_if_t<internal_statusor::IsConstructionValid<
                                   false, T, U, false>::value,
                               int> = 0>
   StatusOr(U&& u)  // NOLINT
       : StatusOr(absl::in_place, std::forward<U>(u)) {}
   template <typename U = T,
-            absl::enable_if_t<internal_statusor::IsConstructionValid<
+            std::enable_if_t<internal_statusor::IsConstructionValid<
                                   false, T, U, true>::value,
                               int> = 0>
   StatusOr(U&& u ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT
       : StatusOr(absl::in_place, std::forward<U>(u)) {}
 
   template <typename U = T,
-            absl::enable_if_t<internal_statusor::IsConstructionValid<
+            std::enable_if_t<internal_statusor::IsConstructionValid<
                                   true, T, U, false>::value,
                               int> = 0>
   explicit StatusOr(U&& u)  // NOLINT
       : StatusOr(absl::in_place, std::forward<U>(u)) {}
   template <typename U = T,
-            absl::enable_if_t<
+            std::enable_if_t<
                 internal_statusor::IsConstructionValid<true, T, U, true>::value,
                 int> = 0>
   explicit StatusOr(U&& u ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT
@@ -476,6 +478,36 @@
   ABSL_MUST_USE_RESULT const Status& status() const&;
   Status status() &&;
 
+  absl::Span<const absl::SourceLocation> GetSourceLocations() const {
+    return this->status_.GetSourceLocations();
+  }
+  // Appends the `loc` to the current location chain inside the status, iff the
+  // status-or is non-ok and contains a non-empty message.
+  void AddSourceLocation(
+      absl::SourceLocation loc = absl::SourceLocation::current()) {
+    this->status_.AddSourceLocation(loc);
+  }
+
+  // StatusOr<T>::WithSourceLocation()
+  //
+  // Appends the `loc` to the current location chain inside the status iff the
+  // status-or is non-ok and contains a non-empty message, and returns an rvalue
+  // reference to `*this`.
+  //
+  // Example:
+  //
+  //   StatusOr<int> Finalize(...);
+  //
+  //   StatusOr<int> DoSomething(...) {
+  //     ...
+  //     return Finalize().WithSourceLocation();
+  //   }
+  ABSL_MUST_USE_RESULT StatusOr<T>&& WithSourceLocation(
+      absl::SourceLocation loc = absl::SourceLocation::current()) && {
+    AddSourceLocation(loc);
+    return std::move(*this);
+  }
+
   // StatusOr<T>::value()
   //
   // Returns a reference to the held value if `this->ok()`. Otherwise, throws
@@ -592,7 +624,7 @@
 
   template <
       typename U, typename... Args,
-      absl::enable_if_t<
+      std::enable_if_t<
           std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
           int> = 0>
   T& emplace(std::initializer_list<U> ilist,
diff --git a/absl/status/statusor_test.cc b/absl/status/statusor_test.cc
index 82cb930..bd2c10e 100644
--- a/absl/status/statusor_test.cc
+++ b/absl/status/statusor_test.cc
@@ -37,6 +37,7 @@
 #include "absl/status/status_matchers.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
+#include "absl/types/source_location.h"
 #include "absl/utility/utility.h"
 
 namespace {
@@ -1800,6 +1801,102 @@
   EXPECT_THAT(absl::StrCat(print_me), error_matcher);
 }
 
+#ifdef ABSL_INTERNAL_HAVE_BUILTIN_LINE_FILE
+#define GET_SOURCE_LOCATION(offset) __builtin_LINE() - offset
+#else
+#define GET_SOURCE_LOCATION(offset) 1
+#endif
+
+template <typename T>
+void CheckSourceLocation(
+    const absl::StatusOr<T>& status_or, std::vector<int> lines = {},
+    absl::SourceLocation loc = absl::SourceLocation::current()) {
+  ASSERT_EQ(status_or.GetSourceLocations().size(), lines.size())
+      << "Size check failed at " << loc.line();
+  for (size_t i = 0; i < lines.size(); ++i) {
+    EXPECT_EQ(absl::string_view(status_or.GetSourceLocations()[i].file_name()),
+              absl::string_view(loc.file_name()))
+        << "File name check failed at " << loc.line();
+    EXPECT_EQ(status_or.GetSourceLocations()[i].line(), lines[i])
+        << "Line check failed at " << loc.line();
+  }
+}
+
+TEST(StatusOr, AddSourceLocation) {
+  constexpr int kMaxIter = 10;
+  {
+    // Status that ignores source location.
+    absl::StatusOr<int> status_ignores_source_location[] = {
+        123, absl::Status(absl::StatusCode::kInternal, "")};
+    for (absl::StatusOr<int>& s : status_ignores_source_location) {
+      for (int i = 0; i < kMaxIter; ++i) {
+        s.AddSourceLocation(absl::SourceLocation::current());
+        s.AddSourceLocation(absl::SourceLocation());
+      }
+      CheckSourceLocation(s);
+    }
+  }
+  {
+    // Default SourceLocation is not added.
+    absl::StatusOr<int> status = absl::Status(
+        absl::StatusCode::kInternal, "foo", absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+    for (int i = 0; i < kMaxIter; ++i) {
+      status.AddSourceLocation(absl::SourceLocation());
+    }
+    CheckSourceLocation(status, {line});
+  }
+  {
+    // Default SourceLocation is not added.
+    absl::StatusOr<int> status = absl::Status(
+        absl::StatusCode::kInternal, "foo", absl::SourceLocation::current());
+    int line = GET_SOURCE_LOCATION(1);
+    std::vector<int> lines = {line};
+    lines.reserve(1 + kMaxIter);
+    for (int i = 0; i < kMaxIter; ++i) {
+      status.AddSourceLocation(absl::SourceLocation::current());
+      lines.push_back(GET_SOURCE_LOCATION(1));
+    }
+    CheckSourceLocation(status, lines);
+  }
+}
+
+absl::StatusOr<int>&& IsRvalueStatus(absl::StatusOr<int>&& s) {
+  return std::move(s);
+}
+
+TEST(StatusOr, WithSourceLocationMove) {
+  absl::StatusOr<int> original = absl::Status(
+      absl::StatusCode::kInternal, "message", absl::SourceLocation::current());
+  int line = GET_SOURCE_LOCATION(1);
+
+  const absl::StatusOr<int> status_or = IsRvalueStatus(
+      std::move(original).WithSourceLocation(absl::SourceLocation::current()));
+  int line2 = GET_SOURCE_LOCATION(1);
+
+  CheckSourceLocation(status_or, {line, line2});
+  EXPECT_FALSE(status_or.ok());
+}
+
+TEST(StatusOr, WithSourceLocationReturn) {
+  absl::SourceLocation loc1 = absl::SourceLocation::current();
+  int line1 = GET_SOURCE_LOCATION(1);
+  absl::SourceLocation loc2 = absl::SourceLocation::current();
+  int line2 = GET_SOURCE_LOCATION(1);
+
+  const auto return_error = [&loc1]() -> absl::StatusOr<int> {
+    return absl::InvalidArgumentError("I am error", loc1);
+  };
+  const auto return_error_with_source_location =
+      [&return_error, &loc2]() -> absl::StatusOr<int> {
+    return return_error().WithSourceLocation(loc2);
+  };
+
+  absl::StatusOr<int> status_or = return_error_with_source_location();
+  CheckSourceLocation(status_or, {line1, line2});
+  EXPECT_FALSE(status_or.ok());
+}
+
 TEST(StatusOr, SupportsReferenceTypes) {
   int i = 1;
   absl::StatusOr<int&> s = i;
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 5f42894..79b6672 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -114,6 +114,7 @@
         "//absl/meta:type_traits",
         "//absl/numeric:bits",
         "//absl/numeric:int128",
+        "//absl/types:source_location",
     ],
 )
 
@@ -400,7 +401,6 @@
     visibility = ["//visibility:private"],
     deps = [
         ":strings",
-        "//absl/meta:type_traits",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
     ],
@@ -423,6 +423,36 @@
     ],
 )
 
+cc_library(
+    name = "stringify_stream",
+    hdrs = ["internal/stringify_stream.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl:friends",
+        "//visibility:private",
+    ],
+    deps = [
+        ":string_view",
+        "//absl/base:config",
+    ],
+)
+
+cc_test(
+    name = "stringify_stream_test",
+    srcs = ["internal/stringify_stream_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":string_view",
+        ":stringify_stream",
+        "//absl/base:config",
+        "//absl/strings:str_format",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
 cc_binary(
     name = "charset_benchmark",
     testonly = True,
@@ -646,6 +676,7 @@
         "//absl/base:endian",
         "//absl/base:nullability",
         "//absl/base:raw_logging_internal",
+        "//absl/cleanup",
         "//absl/container:inlined_vector",
         "//absl/crc:crc32c",
         "//absl/crc:crc_cord_state",
@@ -1084,6 +1115,7 @@
         "//absl/container:btree",
         "//absl/container:flat_hash_map",
         "//absl/container:node_hash_map",
+        "//absl/hash",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
     ],
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index 0e0adfa..9f7f9ef 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -86,6 +86,8 @@
     absl::memory
     absl::nullability
     absl::raw_logging_internal
+    absl::source_location
+    absl::strings
     absl::throw_delegate
     absl::type_traits
   PUBLIC
@@ -116,6 +118,32 @@
   PUBLIC
 )
 
+absl_cc_library(
+  NAME
+    stringify_stream
+  HDRS
+    "internal/stringify_stream.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::string_view
+    absl::config
+)
+
+absl_cc_test(
+  NAME
+    stringify_stream_test
+  SRCS
+    "internal/stringify_stream_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::string_view
+    absl::stringify_stream
+    absl::str_format
+    GTest::gmock_main
+)
+
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
@@ -311,7 +339,6 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::strings
-    absl::type_traits
     GTest::gmock_main
 )
 
@@ -369,6 +396,7 @@
     absl::dynamic_annotations
     absl::btree
     absl::flat_hash_map
+    absl::hash
     absl::node_hash_map
     GTest::gmock_main
 )
diff --git a/absl/strings/cord.h b/absl/strings/cord.h
index 3278296..c2f1ec5 100644
--- a/absl/strings/cord.h
+++ b/absl/strings/cord.h
@@ -174,7 +174,7 @@
  private:
   template <typename T>
   using EnableIfString =
-      absl::enable_if_t<std::is_same<T, std::string>::value, int>;
+      std::enable_if_t<std::is_same<T, std::string>::value, int>;
 
  public:
   // Cord::Cord() Constructors.
@@ -1137,7 +1137,7 @@
 CordRep* absl_nonnull NewExternalRep(absl::string_view data,
                                      Releaser&& releaser) {
   assert(!data.empty());
-  using ReleaserType = absl::decay_t<Releaser>;
+  using ReleaserType = std::decay_t<Releaser>;
   CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
       std::forward<Releaser>(releaser), 0);
   InitializeCordRepExternal(data, rep);
@@ -1162,7 +1162,7 @@
                                    data, std::forward<Releaser>(releaser)),
                                Cord::MethodIdentifier::kMakeCordFromExternal);
   } else {
-    using ReleaserType = absl::decay_t<Releaser>;
+    using ReleaserType = std::decay_t<Releaser>;
     cord_internal::InvokeReleaser(
         cord_internal::Rank1{}, ReleaserType(std::forward<Releaser>(releaser)),
         data);
diff --git a/absl/strings/internal/generic_printer_internal.h b/absl/strings/internal/generic_printer_internal.h
index 1a2d0bd..fc88b27 100644
--- a/absl/strings/internal/generic_printer_internal.h
+++ b/absl/strings/internal/generic_printer_internal.h
@@ -112,6 +112,23 @@
     // would be a fork.
     decltype(T().~ArenaSafeUniquePtr())> = true;
 
+// `proto2::Arena::UniquePtr` is at least as safe as `std::unique_ptr`.
+template <class T>
+inline constexpr bool is_supported_ptr<
+    T,
+    // Check for `proto2::Arena::UniquePtr` without having to include its
+    // header here. This does match any type named `UniquePtr`, regardless
+    // of the scope it is defined in, but we try to restrict by probing some
+    // methods.
+    std::void_t<decltype(
+        // Check the class name using the destructor.
+        T().~UniquePtr(),
+        // Check some other members, to try to duck type into the right class.
+        T().get(), T().reset(), T().try_heap_release(),
+        T().GetOwningArena()
+            ->template MakeUnique<int>(nullptr)
+            .~UniquePtr())>> = true;
+
 // Specialization for floats: print floating point types using their
 // max_digits10 precision. This ensures each distinct underlying values
 // can be represented uniquely, even though it's not (strictly speaking)
@@ -220,6 +237,8 @@
   if constexpr (is_any_string<T> || std::is_same_v<T, absl::string_view>) {
     // Specialization for strings: prints with plausible quoting and escaping.
     return PrintEscapedString(os, v);
+  } else if constexpr (is_supported_ptr<T>) {
+    return (PrintSmartPointerContents)(os, v);
   } else if constexpr (absl::HasAbslStringify<T>::value) {
     // If someone has specified `AbslStringify`, we should prefer that.
     return os << absl::StrCat(v);
@@ -246,8 +265,6 @@
                                                  w)) {})) {
     // For std::variant, use `std::visit(v)`
     return (PrintVariant)(os, v);
-  } else if constexpr (is_supported_ptr<T>) {
-    return (PrintSmartPointerContents)(os, v);
   } else if constexpr (meta_internal::Requires<const T>(
                            [&](auto&& w) -> decltype(w.ok(), w.status(), *w) {
                            })) {
diff --git a/absl/strings/internal/stl_type_traits.h b/absl/strings/internal/stl_type_traits.h
index e50468b..9c63726 100644
--- a/absl/strings/internal/stl_type_traits.h
+++ b/absl/strings/internal/stl_type_traits.h
@@ -48,25 +48,25 @@
 template <template <typename...> class T, typename... Args>
 struct IsSpecializationImpl<T<Args...>, T> : std::true_type {};
 template <typename C, template <typename...> class T>
-using IsSpecialization = IsSpecializationImpl<absl::decay_t<C>, T>;
+using IsSpecialization = IsSpecializationImpl<std::decay_t<C>, T>;
 
 template <typename C>
 struct IsArrayImpl : std::false_type {};
 template <template <typename, size_t> class A, typename T, size_t N>
 struct IsArrayImpl<A<T, N>> : std::is_same<A<T, N>, std::array<T, N>> {};
 template <typename C>
-using IsArray = IsArrayImpl<absl::decay_t<C>>;
+using IsArray = IsArrayImpl<std::decay_t<C>>;
 
 template <typename C>
 struct IsBitsetImpl : std::false_type {};
 template <template <size_t> class B, size_t N>
 struct IsBitsetImpl<B<N>> : std::is_same<B<N>, std::bitset<N>> {};
 template <typename C>
-using IsBitset = IsBitsetImpl<absl::decay_t<C>>;
+using IsBitset = IsBitsetImpl<std::decay_t<C>>;
 
 template <typename C>
 struct IsSTLContainer
-    : absl::disjunction<
+    : std::disjunction<
           IsArray<C>, IsBitset<C>, IsSpecialization<C, std::deque>,
           IsSpecialization<C, std::forward_list>,
           IsSpecialization<C, std::list>, IsSpecialization<C, std::map>,
@@ -123,7 +123,7 @@
                            typename C::hasher, typename C::key_equal,
                            typename C::allocator_type>> {};
 template <typename C, template <typename...> class T>
-using IsBaseOfSpecialization = IsBaseOfSpecializationImpl<absl::decay_t<C>, T>;
+using IsBaseOfSpecialization = IsBaseOfSpecializationImpl<std::decay_t<C>, T>;
 
 template <typename C>
 struct IsBaseOfArrayImpl : std::false_type {};
@@ -131,18 +131,18 @@
 struct IsBaseOfArrayImpl<A<T, N>> : std::is_base_of<A<T, N>, std::array<T, N>> {
 };
 template <typename C>
-using IsBaseOfArray = IsBaseOfArrayImpl<absl::decay_t<C>>;
+using IsBaseOfArray = IsBaseOfArrayImpl<std::decay_t<C>>;
 
 template <typename C>
 struct IsBaseOfBitsetImpl : std::false_type {};
 template <template <size_t> class B, size_t N>
 struct IsBaseOfBitsetImpl<B<N>> : std::is_base_of<B<N>, std::bitset<N>> {};
 template <typename C>
-using IsBaseOfBitset = IsBaseOfBitsetImpl<absl::decay_t<C>>;
+using IsBaseOfBitset = IsBaseOfBitsetImpl<std::decay_t<C>>;
 
 template <typename C>
 struct IsBaseOfSTLContainer
-    : absl::disjunction<IsBaseOfArray<C>, IsBaseOfBitset<C>,
+    : std::disjunction<IsBaseOfArray<C>, IsBaseOfBitset<C>,
                         IsBaseOfSpecialization<C, std::deque>,
                         IsBaseOfSpecialization<C, std::forward_list>,
                         IsBaseOfSpecialization<C, std::list>,
@@ -201,7 +201,7 @@
                                typename C::allocator_type>> {};
 template <typename C, template <typename...> class T>
 using IsConvertibleToSpecialization =
-    IsConvertibleToSpecializationImpl<absl::decay_t<C>, T>;
+    IsConvertibleToSpecializationImpl<std::decay_t<C>, T>;
 
 template <typename C>
 struct IsConvertibleToArrayImpl : std::false_type {};
@@ -209,7 +209,7 @@
 struct IsConvertibleToArrayImpl<A<T, N>>
     : std::is_convertible<A<T, N>, std::array<T, N>> {};
 template <typename C>
-using IsConvertibleToArray = IsConvertibleToArrayImpl<absl::decay_t<C>>;
+using IsConvertibleToArray = IsConvertibleToArrayImpl<std::decay_t<C>>;
 
 template <typename C>
 struct IsConvertibleToBitsetImpl : std::false_type {};
@@ -217,11 +217,11 @@
 struct IsConvertibleToBitsetImpl<B<N>>
     : std::is_convertible<B<N>, std::bitset<N>> {};
 template <typename C>
-using IsConvertibleToBitset = IsConvertibleToBitsetImpl<absl::decay_t<C>>;
+using IsConvertibleToBitset = IsConvertibleToBitsetImpl<std::decay_t<C>>;
 
 template <typename C>
 struct IsConvertibleToSTLContainer
-    : absl::disjunction<
+    : std::disjunction<
           IsConvertibleToArray<C>, IsConvertibleToBitset<C>,
           IsConvertibleToSpecialization<C, std::deque>,
           IsConvertibleToSpecialization<C, std::forward_list>,
@@ -238,7 +238,7 @@
 
 template <typename C>
 struct IsStrictlyBaseOfAndConvertibleToSTLContainer
-    : absl::conjunction<absl::negation<IsSTLContainer<C>>,
+    : std::conjunction<std::negation<IsSTLContainer<C>>,
                         IsBaseOfSTLContainer<C>,
                         IsConvertibleToSTLContainer<C>> {};
 
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index 021013f..0fd3d99 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -133,9 +133,9 @@
                                   std::declval<const FormatConversionSpec&>(),
                                   std::declval<FormatSink*>())) {
   using FormatConversionSpecT =
-      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
+      std::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
   using FormatSinkT =
-      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
+      std::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
   auto fcs = conv.Wrap<FormatConversionSpecT>();
   auto fs = sink->Wrap<FormatSinkT>();
   return AbslFormatConvert(v, fcs, &fs);
@@ -150,7 +150,7 @@
                         IntegralConvertResult> {
   if (conv.conversion_char() == FormatConversionCharInternal::v) {
     using FormatSinkT =
-        absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
+        std::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
     auto fs = sink->Wrap<FormatSinkT>();
     AbslStringify(fs, v);
     return {true};
@@ -169,7 +169,7 @@
                                 std::declval<FormatSink&>(), v))>::value,
                         ArgConvertResult<FormatConversionCharSetInternal::v>> {
   using FormatSinkT =
-      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
+      std::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
   auto fs = sink->Wrap<FormatSinkT>();
   AbslStringify(fs, v);
   return {true};
@@ -345,7 +345,7 @@
 
 // This function needs to be a template due to ambiguity regarding type
 // conversions.
-template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
+template <typename T, std::enable_if_t<std::is_same<T, bool>::value, int> = 0>
 IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink) {
   if (conv.conversion_char() == FormatConversionCharInternal::v) {
@@ -381,7 +381,7 @@
   static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
       const FormatCountCapture& v, FormatConversionSpecImpl conv,
       FormatSinkImpl* sink) {
-    const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
+    const std::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
 
     if (conv.conversion_char() !=
         str_format_internal::FormatConversionCharInternal::n) {
diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc
index 89275d4..265c53d 100644
--- a/absl/strings/internal/str_format/float_conversion.cc
+++ b/absl/strings/internal/str_format/float_conversion.cc
@@ -25,6 +25,7 @@
 #include <limits>
 #include <optional>
 #include <string>
+#include <type_traits>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
@@ -100,7 +101,7 @@
 // Requires: `0 <= carry <= 9`
 template <typename Int>
 inline char MultiplyBy10WithCarry(Int* v, char carry) {
-  using BiggerInt = absl::conditional_t<sizeof(Int) == 4, uint64_t, uint128>;
+  using BiggerInt = std::conditional_t<sizeof(Int) == 4, uint64_t, uint128>;
   BiggerInt tmp =
       10 * static_cast<BiggerInt>(*v) + static_cast<BiggerInt>(carry);
   *v = static_cast<Int>(tmp);
@@ -1184,8 +1185,8 @@
 template <typename Float>
 struct Decomposed {
   using MantissaType =
-      absl::conditional_t<std::is_same<long double, Float>::value, uint128,
-                          uint64_t>;
+      std::conditional_t<std::is_same<long double, Float>::value, uint128,
+                         uint64_t>;
   static_assert(std::numeric_limits<Float>::digits <= sizeof(MantissaType) * 8,
                 "");
   MantissaType mantissa;
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h
index 31f1d65..9bda311 100644
--- a/absl/strings/internal/str_split_internal.h
+++ b/absl/strings/internal/str_split_internal.h
@@ -224,7 +224,7 @@
 
 template <typename C>
 struct SplitterIsConvertibleToImpl<C, true, true>
-    : absl::conjunction<
+    : std::conjunction<
           std::is_constructible<typename C::key_type, absl::string_view>,
           std::is_constructible<typename C::mapped_type, absl::string_view>> {};
 
@@ -494,7 +494,7 @@
     // Inserts the key and an empty value into the map, returning an iterator to
     // the inserted item. We use emplace() if available, otherwise insert().
     template <typename M>
-    static absl::enable_if_t<HasEmplace<M>::value, iterator> InsertOrEmplace(
+    static std::enable_if_t<HasEmplace<M>::value, iterator> InsertOrEmplace(
         M* m, absl::string_view key) {
       // Use piecewise_construct to support old versions of gcc in which pair
       // constructor can't otherwise construct string from string_view.
@@ -502,7 +502,7 @@
                                std::tuple<>()));
     }
     template <typename M>
-    static absl::enable_if_t<!HasEmplace<M>::value, iterator> InsertOrEmplace(
+    static std::enable_if_t<!HasEmplace<M>::value, iterator> InsertOrEmplace(
         M* m, absl::string_view key) {
       return ToIter(m->insert(std::make_pair(First(key), Second(""))));
     }
diff --git a/absl/strings/internal/string_constant_test.cc b/absl/strings/internal/string_constant_test.cc
index 392833c..c8b3591 100644
--- a/absl/strings/internal/string_constant_test.cc
+++ b/absl/strings/internal/string_constant_test.cc
@@ -14,7 +14,8 @@
 
 #include "absl/strings/internal/string_constant.h"
 
-#include "absl/meta/type_traits.h"
+#include <type_traits>
+
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
@@ -34,10 +35,10 @@
 
   EXPECT_TRUE(std::is_empty<T>::value);
   EXPECT_TRUE(std::is_trivial<T>::value);
-  EXPECT_TRUE(absl::is_trivially_default_constructible<T>::value);
-  EXPECT_TRUE(absl::is_trivially_copy_constructible<T>::value);
-  EXPECT_TRUE(absl::is_trivially_move_constructible<T>::value);
-  EXPECT_TRUE(absl::is_trivially_destructible<T>::value);
+  EXPECT_TRUE(std::is_trivially_default_constructible<T>::value);
+  EXPECT_TRUE(std::is_trivially_copy_constructible<T>::value);
+  EXPECT_TRUE(std::is_trivially_move_constructible<T>::value);
+  EXPECT_TRUE(std::is_trivially_destructible<T>::value);
 }
 
 TEST(StringConstant, MakeFromCallable) {
diff --git a/absl/strings/internal/stringify_sink.h b/absl/strings/internal/stringify_sink.h
index fc3747b..6478ea5 100644
--- a/absl/strings/internal/stringify_sink.h
+++ b/absl/strings/internal/stringify_sink.h
@@ -15,11 +15,14 @@
 #ifndef ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_
 #define ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_
 
+#include <array>
 #include <string>
 #include <type_traits>
 #include <utility>
 
+#include "absl/strings/numbers.h"
 #include "absl/strings/string_view.h"
+#include "absl/types/source_location.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -51,6 +54,15 @@
 
 }  // namespace strings_internal
 
+template <typename Sink>
+void AbslStringify(Sink& sink, SourceLocation l) {
+  sink.Append(l.file_name());
+  sink.Append(":");
+  std::array<char, numbers_internal::kFastToBufferSize> buffer;
+  numbers_internal::FastIntToBuffer(l.line(), buffer.data());
+  sink.Append(buffer.data());
+}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/strings/internal/stringify_stream.h b/absl/strings/internal/stringify_stream.h
new file mode 100644
index 0000000..6110b33
--- /dev/null
+++ b/absl/strings/internal/stringify_stream.h
@@ -0,0 +1,119 @@
+// Copyright 2026 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: stringify_stream.h
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_STRINGS_INTERNAL_STRINGIFY_STREAM_H_
+#define ABSL_STRINGS_INTERNAL_STRINGIFY_STREAM_H_
+
+// StringifyStream is an adaptor for any std::ostream, that provides a
+// stream insertion (<<) operator with the following behavior when inserting
+// some value of type T:
+//
+//   - If there is a suitable overload of operator<< already defined for T, it
+//     will be used.
+//
+//   - If there is no operator<< overload, but there is an AbslStringify defined
+//     for T, it will be used as a fallback.
+//
+//   - Otherwise it is a compilation error.
+//
+// For reference, AbslStringify typically has the form:
+//
+//   struct Foo {
+//     template <typename Sink>
+//     friend void AbslStringify(Sink& sink, const Foo& foo) { ... }
+//   };
+//
+// This permits the following usage, for example:
+//
+//   StringifyStream(std::cout) << Foo();
+//
+
+#include <cstddef>
+#include <ostream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace strings_internal {
+
+class StringifyStream {
+ public:
+  // Constructor: adapts (but does not take ownership of) some underlying
+  // std::ostream instance.
+  explicit StringifyStream(std::ostream& os) : sink_{os} {}
+
+  // Stream insertion: delegate to an overload of operator<< if defined for type
+  // T, otherwise fall back to AbslStringify for T.
+  template <typename T>
+  friend StringifyStream& operator<<(StringifyStream& stream, const T& t) {
+    if constexpr (HasStreamInsertion<T>::value) {
+      stream.sink_.os << t;
+    } else {
+      AbslStringify(stream.sink_, t);
+    }
+    return stream;
+  }
+
+  // Rvalue-ref overload, required when the StringifyStream parameter hasn't
+  // been bound to a variable.
+  template <typename T>
+  friend StringifyStream& operator<<(StringifyStream&& stream, const T& t) {
+    return stream << t;
+  }
+
+  // Overload for things like << std::endl which need an explicit type in order
+  // to resolve to the appropriate overload or template instantiation.
+  StringifyStream& operator<<(std::ostream& (*func)(std::ostream&)) {
+    sink_.os << func;
+    return *this;
+  }
+
+ private:
+  // Abseil "stringify sink" concept (stringify_sink.h)
+  struct Sink {
+    std::ostream& os;
+    void Append(size_t count, char ch) { os << std::string(count, ch); }
+    void Append(absl::string_view v) { os << v; }
+    friend void AbslFormatFlush(Sink* sink, absl::string_view v) {
+      sink->Append(v);
+    }
+  } sink_;
+
+  // SFINAE helper to identify types with a defined operator<< overload.
+  template <typename T, typename = void>
+  struct HasStreamInsertion : std::false_type {};
+
+  template <typename T>
+  struct HasStreamInsertion<T,
+                            std::void_t<decltype(std::declval<std::ostream&>()
+                                                 << std::declval<const T&>())>>
+      : std::true_type {};
+};
+
+}  // namespace strings_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_STRINGIFY_STREAM_H_
diff --git a/absl/strings/internal/stringify_stream_test.cc b/absl/strings/internal/stringify_stream_test.cc
new file mode 100644
index 0000000..71a7691
--- /dev/null
+++ b/absl/strings/internal/stringify_stream_test.cc
@@ -0,0 +1,111 @@
+// Copyright 2026 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/internal/stringify_stream.h"
+
+#include <cstddef>
+#include <iomanip>
+#include <ostream>
+#include <sstream>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+namespace {
+
+// Exercises the Append(size_t, char) overload
+struct AppendNCharsTest {
+  size_t count;
+  char ch;
+
+  template <typename Sink>
+  friend void AbslStringify(Sink& sink, const AppendNCharsTest& t) {
+    sink.Append(t.count, t.ch);
+  }
+};
+TEST(StringifyStreamTest, AppendNChars) {
+  std::ostringstream os;
+  StringifyStream(os) << AppendNCharsTest{5, 'a'};
+  EXPECT_EQ(os.str(), "aaaaa");
+}
+
+// Exercises the Append(absl::string_view) overload
+struct AppendStringViewTest {
+  absl::string_view v;
+
+  template <typename Sink>
+  friend void AbslStringify(Sink& sink, const AppendStringViewTest& t) {
+    sink.Append(t.v);
+  }
+};
+TEST(StringifyStreamTest, AppendStringView) {
+  std::ostringstream os;
+  StringifyStream(os) << AppendStringViewTest{"abc"};
+  EXPECT_EQ(os.str(), "abc");
+}
+
+// Exercises AbslFormatFlush(OStringStreamSink*, absl::string_view v)
+struct AbslFormatFlushTest {
+  absl::string_view a, b, c;
+
+  template <typename Sink>
+  friend void AbslStringify(Sink& sink, const AbslFormatFlushTest& t) {
+    absl::Format(&sink, "%s, %s, %s", t.a, t.b, t.c);
+  }
+};
+TEST(StringifyStreamTest, AbslFormatFlush) {
+  std::ostringstream os;
+  StringifyStream(os) << AbslFormatFlushTest{"a", "b", "c"};
+  EXPECT_EQ(os.str(), "a, b, c");
+}
+
+// If overloads of both AbslStringify and operator<< are defined for the type,
+// the operator<< overload should take precedence.
+struct PreferStreamInsertionOverAbslStringifyTest {
+  friend std::ostream& operator<<(  // NOLINT(clang-diagnostic-unused-function)
+      std::ostream& os, const PreferStreamInsertionOverAbslStringifyTest&) {
+    return os << "good";
+  }
+
+  template <typename Sink>
+  friend void AbslStringify  // NOLINT(clang-diagnostic-unused-function)
+      (Sink& sink, const PreferStreamInsertionOverAbslStringifyTest&) {
+    sink.Append("bad");
+  }
+};
+TEST(StringifyStreamTest, PreferStreamInsertionOverAbslStringify) {
+  std::ostringstream os;
+  StringifyStream(os) << PreferStreamInsertionOverAbslStringifyTest{};
+  EXPECT_EQ(os.str(), "good");
+}
+TEST(StringifyStreamTest, SupportEndl) {
+  std::ostringstream os;
+  StringifyStream(os) << std::endl;
+  EXPECT_EQ(os.str(), "\n");
+}
+TEST(StringifyStreamTest, SupportSetbase) {
+  std::ostringstream os;
+  StringifyStream(os) << std::setbase(16) << 255;
+  EXPECT_EQ(os.str(), "ff");
+}
+
+}  // namespace
+}  // namespace strings_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc
index c17c472..aa22ca4 100644
--- a/absl/strings/str_split_test.cc
+++ b/absl/strings/str_split_test.cc
@@ -36,6 +36,7 @@
 #include "absl/container/btree_set.h"
 #include "absl/container/flat_hash_map.h"
 #include "absl/container/node_hash_map.h"
+#include "absl/hash/hash.h"
 #include "absl/strings/string_view.h"
 
 namespace {
@@ -422,6 +423,9 @@
   TestConversionOperator<absl::btree_multiset<absl::string_view>>(splitter);
   TestConversionOperator<absl::btree_multiset<std::string>>(splitter);
   TestConversionOperator<std::unordered_set<std::string>>(splitter);
+  TestConversionOperator<
+      std::unordered_set<absl::string_view, absl::Hash<absl::string_view>>>(
+      splitter);
 
   // Tests conversion to map-like objects.
 
@@ -455,6 +459,15 @@
       splitter);
   TestMapConversionOperator<std::unordered_map<std::string, std::string>>(
       splitter);
+  TestMapConversionOperator<std::unordered_map<
+      absl::string_view, absl::string_view, absl::Hash<absl::string_view>>>(
+      splitter);
+  TestMapConversionOperator<std::unordered_map<absl::string_view, std::string,
+                                               absl::Hash<absl::string_view>>>(
+      splitter);
+  TestMapConversionOperator<std::unordered_map<std::string, absl::string_view,
+                                               absl::Hash<absl::string_view>>>(
+      splitter);
   TestMapConversionOperator<
       absl::node_hash_map<absl::string_view, absl::string_view>>(splitter);
   TestMapConversionOperator<
diff --git a/absl/synchronization/internal/create_thread_identity.cc b/absl/synchronization/internal/create_thread_identity.cc
index 0b0f920..e10d3bc 100644
--- a/absl/synchronization/internal/create_thread_identity.cc
+++ b/absl/synchronization/internal/create_thread_identity.cc
@@ -77,6 +77,16 @@
   identity->ticker.store(0, std::memory_order_relaxed);
   identity->wait_start.store(0, std::memory_order_relaxed);
   identity->is_idle.store(false, std::memory_order_relaxed);
+  // To avoid a circular dependency we declare only the storage in the header
+  // and use placement new to construct the SpinLock.
+  static_assert(
+      sizeof(base_internal::ThreadIdentity::SchedulerState::
+                 association_lock_word) == sizeof(base_internal::SpinLock),
+      "Wrong size for SpinLock");
+  // Protects the association between this identity and its schedulable.  Should
+  // never be cooperative.
+  new (&identity->scheduler_state.association_lock_word)
+      base_internal::SpinLock(base_internal::SCHEDULE_KERNEL_ONLY);
 }
 
 static void ResetThreadIdentityBetweenReuse(
@@ -96,6 +106,17 @@
   pts->wake = false;
   pts->cond_waiter = false;
   pts->all_locks = nullptr;
+  base_internal::ThreadIdentity::SchedulerState* ss =
+      &identity->scheduler_state;
+  ss->bound_schedulable.store(nullptr, std::memory_order_relaxed);
+  ss->association_lock_word = 0;
+  ss->scheduling_disabled_depth.store(0, std::memory_order_relaxed);
+  ss->potentially_blocking_depth = 0;
+  ss->schedule_next_state = 0;
+  ss->waking_designated_waker = false;
+  identity->static_initialization_depth = 0;
+  identity->wait_state.store(base_internal::ThreadIdentity::WaitState::kActive,
+                             std::memory_order_relaxed);
   identity->blocked_count_ptr = nullptr;
   identity->ticker.store(0, std::memory_order_relaxed);
   identity->wait_start.store(0, std::memory_order_relaxed);
diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h
index 144ab3c..704f3da 100644
--- a/absl/synchronization/internal/per_thread_sem.h
+++ b/absl/synchronization/internal/per_thread_sem.h
@@ -31,6 +31,10 @@
 #include "absl/synchronization/internal/create_thread_identity.h"
 #include "absl/synchronization/internal/kernel_timeout.h"
 
+namespace gloop_do_not_use {
+struct SynchronizationBenchmarkPeer;
+}  // namespace gloop_do_not_use
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
@@ -77,6 +81,7 @@
   // Permitted callers.
   friend class PerThreadSemTest;
   friend class absl::Mutex;
+  friend struct ::gloop_do_not_use::SynchronizationBenchmarkPeer;
   friend void OneTimeInitThreadIdentity(absl::base_internal::ThreadIdentity*);
 };
 
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 9b80f1f..2016435 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -2139,6 +2139,8 @@
   intptr_t wr_wait = 0;  // set to kMuWrWait if we wake a reader and a
                          // later writer could have acquired the lock
                          // (starvation avoidance)
+  // When non-null, clear its "woken_has_waiters" field before returning.
+  absl::base_internal::ThreadIdentity* clear_waking_des_waker = nullptr;
   ABSL_RAW_CHECK(waitp == nullptr || waitp->thread->waitp == nullptr ||
                      waitp->thread->suppress_fatal_errors,
                  "detected illegal recursion into Mutex code");
@@ -2382,6 +2384,13 @@
         h->readers = 0;
         h->maybe_unlocking = false;  // finished unlocking
         nv |= wr_wait | kMuWait | reinterpret_cast<intptr_t>(h);
+
+        // Signal to any Scheduler that we are waking from Mutex Unlock
+        // and there are more waiters left, signaling possible contention.
+        ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
+        clear_waking_des_waker = GetOrCreateCurrentThreadIdentity();
+        ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
+        clear_waking_des_waker->scheduler_state.waking_designated_waker = true;
       }
 
       // release both spinlock & lock
@@ -2417,6 +2426,10 @@
       ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
     }
   }
+
+  if (clear_waking_des_waker) {
+    clear_waking_des_waker->scheduler_state.waking_designated_waker = false;
+  }
 }
 
 // Used by CondVar implementation to reacquire mutex after waking from
diff --git a/absl/time/simulated_clock.h b/absl/time/simulated_clock.h
index 2225eee..b394750 100644
--- a/absl/time/simulated_clock.h
+++ b/absl/time/simulated_clock.h
@@ -25,6 +25,7 @@
 #include <optional>
 
 #include "absl/base/config.h"
+#include "absl/base/macros.h"
 #include "absl/base/nullability.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/synchronization/mutex.h"
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index 19709a5..769f830 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
 load("@rules_cc//cc:cc_library.bzl", "cc_library")
 load("@rules_cc//cc:cc_test.bzl", "cc_test")
 load(
@@ -52,11 +53,13 @@
 
 cc_library(
     name = "source_location",
+    srcs = ["source_location.cc"],
     hdrs = ["source_location.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/base:nullability",
     ],
 )
@@ -120,6 +123,62 @@
 )
 
 cc_library(
+    name = "any_span",
+    srcs = ["internal/any_span.h"],
+    hdrs = [
+        "any_span.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:nullability",
+        "//absl/base:raw_logging_internal",
+        "//absl/base:throw_delegate",
+        "//absl/meta:type_traits",
+    ],
+)
+
+cc_test(
+    name = "any_span_test",
+    size = "small",
+    srcs = ["any_span_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":any_span",
+        ":span",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:exception_testing",
+        "//absl/base:raw_logging_internal",
+        "//absl/hash:hash_testing",
+        "//absl/meta:type_traits",
+        "//absl/strings",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_binary(
+    name = "any_span_benchmark",
+    testonly = True,
+    srcs = ["any_span_benchmark.cc"],
+    tags = ["benchmark"],
+    deps = [
+        ":any_span",
+        ":span",
+        "//absl/base:config",
+        "//absl/base:raw_logging_internal",
+        "//absl/flags:flag",
+        "//absl/strings",
+        "//absl/strings:string_view",
+        "@google_benchmark//:benchmark_main",
+    ],
+)
+
+cc_library(
     name = "optional",
     hdrs = ["optional.h"],
     copts = ABSL_DEFAULT_COPTS,
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index f69a1ea..fd2f92f 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -29,6 +29,44 @@
 
 absl_cc_library(
   NAME
+    any_span
+  HDRS
+    "any_span.h"
+  SRCS
+    "internal/any_span.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::nullability
+    absl::raw_logging_internal
+    absl::throw_delegate
+    absl::type_traits
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    any_span_test
+  SRCS
+    "any_span_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::exception_testing
+    absl::hash_testing
+    absl::raw_logging_internal
+    absl::span
+    absl::strings
+    absl::type_traits
+    GTest::gmock_main
+)
+
+absl_cc_library(
+  NAME
     span
   HDRS
     "span.h"
@@ -132,10 +170,13 @@
     source_location
   HDRS
     "source_location.h"
+  SRCS
+    "source_location.cc"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::config
+    absl::core_headers
     absl::nullability
   PUBLIC
 )
diff --git a/absl/types/any_span.h b/absl/types/any_span.h
new file mode 100644
index 0000000..98ad4f9
--- /dev/null
+++ b/absl/types/any_span.h
@@ -0,0 +1,1063 @@
+// Copyright 2026 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: any_span.h
+// -----------------------------------------------------------------------------
+//
+// AnySpan provides a view of a random access container, much like absl::Span
+// (go/totw/93). See also go/totw/145#gtlanyspan for an introduction of AnySpan.
+//
+// The primary differences from absl::Span are:
+//  * AnySpan works with any random access container, whereas Span only works if
+//    elements are contiguous in memory -- both will work with std::vector, but
+//    only AnySpan will work with std::deque.
+//  * AnySpan performs a variety of transformations, such as dereferencing
+//    containers of pointers, or accessing specific members from a collection of
+//    structs, whereas Span does not offer such capability. For example,
+//    AnySpan<std::string> can handle both std::vector<std::string> and
+//    std::vector<std::string*>. Safe implicit conversions for a container's
+//    value type (such as up-casting from child classes, or converting
+//    reference_wrapper<T> to const T&) will happen implicitly.
+//  * AnySpan's generality has some small runtime cost, usually only a
+//    conditional branch per element access, or a function-pointer call in the
+//    worst case. Span may be preferable when the inputs are likely to be
+//    contiguous and performance is critical.
+//
+// AnySpan<T> is a mutable view to the elements and AnySpan<const T> is a
+// read-only view to the elements, similar to absl::Span.
+//
+// AnySpan only requires containers to provide a size() and an operator[] that
+// returns a reference. It will use data() if it returns a pointer to the type
+// returned by operator[], which allows it to perform some internal
+// optimizations (this should apply to many well behaved random access
+// containers that use arrays internally, but notably
+// RepeatedPtrField<T>::data() returns T** instead of T*).
+//
+// Using AnySpan as an input parameter:
+//
+// To write a function that can accept vector<MyMessage>,
+// vector<unique_ptr<MyMessage>>, or RepeatedPtrField<MyMessage> as inputs, you
+// can use AnySpan as the input to the function. AnySpan should be passed by
+// value and it is trivially copyable so it does not need to be moved:
+//
+//   void MyFunction(AnySpan<const MyMessage> messages);
+//
+// You can invoke MyFunction with a vector<MyMessage> or deque<MyMessage>:
+//
+//  std::vector<MyMessage> messages = ...;
+//  MyFunction(messages);
+//
+// Or a container of smart pointers:
+//
+//  std::deque<std::unique_ptr<MyMessage>> message_ptrs = ...;
+//  MyFunction(AnySpan<const MyMessage>(
+//      message_ptrs, any_span_transform::Deref()));
+//
+// Or, you can call the same function with a repeated proto field of type
+// MyMessage:
+//
+//  OtherMessage proto_message = ...;
+//  MyFunction(proto_message.repeated_field());
+//
+//
+// Using AnySpan as an output parameter:
+//
+// To write a function that allows mutation of a fixed-size container of
+// objects, you can use AnySpan with a non-const value type.
+//
+//   void MyMutatingFunction(AnySpan<MyMessage> messages);
+//
+// To bind a mutable AnySpan to a container, callers must construct it
+// explicitly around an lvalue:
+//
+//   std::vector<MyMessage> messages = ...;
+//   MyMutatingFunction(AnySpan<MyMessages>(messages));
+//
+// Or use one of the "Make" functions:
+//
+//   std::vector<MyMessage*> message_ptrs = ...;
+//   MyMutatingFunction(MakeDerefAnySpan(message_ptrs));
+//
+// Or, if you are already dealing with a mutable view-like object, construction
+// can usually be implicit:
+//
+//   absl::Span<MyMessage> mutable_span = ...;
+//   MyMutatingFunction(mutable_span);
+//
+// Transforming Spans:
+//
+// A set of useful transformation functors are provided (see the
+// any_span_transform namespace), but you can provide your own transforms as
+// well.
+//
+// Transforms work for both mutable and const values. When a transform is used
+// for a mutable AnySpan, it will usually have to accept its argument as a
+// mutable reference.
+//
+// Transforms can be any object supported by std::invoke, such as
+// callable objects, function pointers, member function pointers, and even data
+// members. Invoking a transform must return a reference to T or a reference to
+// a compatible object such as a std::reference_wrapper or a child class.
+// Transforms that return value types will not compile and would return
+// dangling references if they did.
+//
+//  struct MyStruct {
+//    int member;
+//  }
+//
+//  std::vector<MyStruct> structs = ...;
+//
+//  // Create an AnySpan<const int> that accesses the members of 'structs':
+//  auto mem_ptr = &MyStruct::member;
+//  AnySpan<const int> members(structs, mem_ptr);
+//
+//  // Or, using a lambda:
+//  auto get_member = [](const MyStruct& s) -> const int& {
+//    return s.member;
+//  };
+//  AnySpan<const int> members_from_lambda(structs, get_member);
+//
+// Transforms must outlive the spans that use them (even member/method pointers,
+// but not function pointer). Callable transforms must provide a const call
+// operator that takes a single argument and returns a reference. Transforms
+// will be executed every time an element is accessed, so complex transforms may
+// have significant performance consequences.
+//
+// Factory Functions:
+//
+// A set of useful functions for constructing common types of AnySpans are
+// provided. Factories with "Const" in the name produce AnySpans of const
+// elements. Factories with "Deref" in the name will dereference elements of the
+// container or array:
+//
+//  AnySpan<T> MakeAnySpan(Container& c);
+//  AnySpan<T> MakeDerefAnySpan(Container& c);
+//  AnySpan<T> MakeAnySpan(T* ptr, std::size_t size);
+//  AnySpan<const T> MakeConstAnySpan(const Container& c);
+//  AnySpan<const T> MakeConstDerefAnySpan(const Container& c);
+//  AnySpan<const T> MakeConstAnySpan(const T* ptr, std::size_t size);
+//
+// Lifetime Gotchas:
+//
+// Take care when constructing spans as named variables! AnySpan captures all
+// arguments by reference, even if it's a pointer:
+//
+//  AnySpan<T> span(v, &MyClass::SomeMethod);  // Dangling reference!
+//
+//  // Also bad! The lambda is destroyed before the span.
+//  AnySpan<T> span(v, [](U& u) { return SomeFunction(u); });
+//
+// Free functions are ok:
+//
+//  AnySpan<T> span(v, SomeFunction);  // This is OK.
+//  AnySpan<T> span(v, &SomeFunction);  // This is OK too.
+//
+// In all other cases, you must ensure that the object used as a transform
+// outlives the span, even if that object is a pointer type.
+//
+// AnySpan is also capable of capturing another AnySpan, so watch out for
+// implicit conversions between types of AnySpans:
+//
+//   // MakeDerefAnySpan() returns an AnySpan<Derived>, leaving 's' pointing to
+//   // a temporary!
+//   vector<Derived*> v;
+//   AnySpan<Base> s = MakeDerefAnySpan(v);
+//
+// Adapting Spans:
+//
+// Since AnySpan only expects operator[] and size(), it is relatively simple to
+// write light-weight adaptor classes that can behave like containers. See the
+// any_span_adaptor namespace for a utility class that does this for iterators
+// and views.
+//
+// Adapters are more powerful than transforms, since they allow you to change
+// the value type and element order of a container, but transforms will
+// generally perform better and leave code with fewer object lifetime concerns.
+//
+//
+// Note about RepeatedPtrField performance:
+//
+// AnySpan will use data() when it returns a pointer to the same type returned
+// by operator[], however RepeatedPtrField's operator[] returns T& and its
+// data() returns a T**. Because of this, AnySpan will fall back to a less
+// efficient version of type-erasure. If you have a performance critical use of
+// RepeatedPtrField, you might find this pattern to have better performance:
+//
+//  MyFunction(AnySpan<const MyMessage>(
+//      proto_message.repeated_field().data(),
+//      proto_message.repeated_field().size(),
+//      any_span_transform::Deref()));
+//
+#ifndef ABSL_TYPES_ANY_SPAN_H_
+#define ABSL_TYPES_ANY_SPAN_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+#include <initializer_list>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/base/nullability.h"
+#include "absl/base/optimization.h"
+#include "absl/base/throw_delegate.h"
+#include "absl/meta/type_traits.h"
+#include "absl/types/internal/any_span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// The accessors in the 'any_span_transform' namespace return references to
+// Transform functors that may be passed to AnySpan. Generally you should
+// prefer to use these functors whenever possible, as they may trigger internal
+// optimizations that are otherwise not possible, and they are valid for the
+// duration of the program, so you do not have to worry about their lifetime.
+namespace any_span_transform {
+
+//
+// Identity() returns a functor that returns whatever is passed to it. Generally
+// you should prefer to use AnySpan's implicit constructor directly, but this
+// may be useful if you are writing templates on top of AnySpan.
+//
+// Returns a const reference so that callers don't have to worry about
+// lifetime of the functor.
+//
+
+struct IdentityT {
+  template <typename T>
+  T& operator()(T& v) const {  // NOLINT(runtime/references)
+    return v;
+  }
+};
+
+inline const IdentityT& Identity() {
+  static const IdentityT f = {};
+  return f;
+}
+
+struct DerefT {
+  template <typename Ptr>
+  auto operator()(Ptr& ptr) const  // NOLINT(runtime/references)
+      -> decltype(*ptr) {
+    ABSL_RAW_DCHECK(ptr, "Cannot dereference null pointer");
+    return *ptr;
+  }
+};
+
+// Deref() returns a functor that dereferences whatever is passed to it. It
+// works for smart and raw pointers, as well as std::optional. Do not use this
+// with containers that may contain elements that cannot be dereferenced, such
+// as null pointers.
+//
+// Returns a const reference so that callers don't have to worry about lifetime
+// of the functor.
+inline const DerefT& Deref() {
+  static const DerefT f = {};
+  return f;
+}
+
+}  // namespace any_span_transform
+
+// Utilities for adapting things to look like the interface that AnySpan
+// expects. For the most part this is based on iterators and views, and is
+// intended to be composed with absl/types/iterator_adaptors.h.
+namespace any_span_adaptor {
+
+// Adapts a pair of iterators into a container-like object that AnySpan can
+// wrap. This is useful if you are faced with a range or view of random access
+// iterators. Iter must be a valid random access iterator.
+template <typename Iter>
+class Range {
+ public:
+  static_assert(
+      std::is_same<typename std::iterator_traits<Iter>::iterator_category,
+                   std::random_access_iterator_tag>::value,
+      "Iter must be a random access iterator.");
+
+  Range(Iter begin, Iter end) {
+    ABSL_HARDENING_ASSERT(begin <= end);
+    begin_ = begin;
+    end_ = end;
+  }
+
+  std::size_t size() const { return end_ - begin_; }
+
+  decltype(std::declval<Iter>()[0]) operator[](std::size_t i) const {
+    ABSL_HARDENING_ASSERT(i < (end_ - begin_));
+    return begin_[i];
+  }
+
+ private:
+  Iter begin_;
+  Iter end_;
+};
+
+// Returns a Range adaptor that wraps the given pair of iterators. The return
+// value of this function must outlive any spans that use it. Iter must be a
+// valid random access iterator.
+template <typename Iter>
+Range<Iter> MakeAdaptorFromRange(Iter begin, Iter end) {
+  return Range<Iter>(begin, end);
+}
+
+// Returns a Range adaptor that wraps the given view. The begin() and end()
+// functions of the given view must return valid random access iterators. The
+// return value of this function must outlive any spans that use it.
+template <typename View>
+auto MakeAdaptorFromView(View& view)  // NOLINT(runtime/references)
+    -> Range<decltype(view.begin())> {
+  return Range<decltype(view.begin())>(view.begin(), view.end());
+}
+
+}  // namespace any_span_adaptor
+
+template <typename T>
+class AnySpan;
+
+template <typename T>
+class ABSL_ATTRIBUTE_VIEW AnySpan {
+ private:
+  template <typename Iter, typename Value>
+  class IteratorBase;
+
+  template <typename U>
+  using EnableIfMutable = std::enable_if_t<!std::is_const<T>::value, U>;
+
+  template <typename U>
+  using EnableIfConst = std::enable_if_t<std::is_const<T>::value, U>;
+
+  static std::true_type CreatesATemporaryImpl(std::decay_t<T>&&);
+  static std::false_type CreatesATemporaryImpl(const T&);
+  template <typename U,
+            typename B = decltype(CreatesATemporaryImpl(std::declval<U>()))>
+  struct CreatesATemporary : B {};
+
+  // Enable if invoke(transform, element) is valid and if a reference to T can
+  // bind to its output. This prevents situations where the constructor may be
+  // ambiguous.
+  // We also verify that the conversion from TransformResult to T& does not
+  // create a temporary. Otherwise, we would get a false positive in the
+  // enabler where `const char*` looks like can be converted to
+  // `const std::string&`.
+  template <typename Transform, typename Element,
+            typename TransformResult = decltype(std::invoke(
+                std::declval<const Transform&>(), std::declval<Element>()))>
+  using EnableIfTransformIsValid =
+      std::enable_if_t<std::is_convertible_v<TransformResult, T&> &&
+                       !CreatesATemporary<TransformResult>::value>;
+
+  // Enable if Container appears to be a valid container. Just checks for size()
+  // and makes sure the class is not an AnySpan for now.
+  template <typename Container>
+  using EnableIfContainer =
+      std::enable_if_t<any_span_internal::HasSize<Container>::value &&
+                       !any_span_internal::IsAnySpan<Container>::value>;
+
+  template <typename Element>
+  using EnableIfDifferentElementType =
+      std::enable_if_t<!std::is_same<T, Element>::value &&
+                       !std::is_same<T, const Element>::value>;
+
+  template <typename Transform>
+  using EnableIfTransformIsByCopy =
+      std::enable_if_t<any_span_internal::kIsTransformCopied<Transform>, bool>;
+  template <typename Transform>
+  using EnableIfTransformIsByRef =
+      std::enable_if_t<!any_span_internal::kIsTransformCopied<Transform>, bool>;
+
+ public:
+  using element_type = T;
+  using value_type = typename std::remove_const<T>::type;
+  using size_type = std::size_t;
+  using difference_type = std::ptrdiff_t;
+  using absl_internal_is_view = std::true_type;
+
+  static const size_type npos = static_cast<size_type>(-1);  // NOLINT
+
+  using reference = T&;
+  using const_reference = typename std::add_const<T>::type&;
+
+  using pointer = T*;
+  using const_pointer = typename std::add_const<T>::type*;
+
+  // Note that iterator will be const if T is const.
+  class iterator;
+  class const_iterator;
+
+  using reverse_iterator = std::reverse_iterator<iterator>;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+  // Null and empty by default.
+  AnySpan() = default;
+
+  // Creates a span that wraps an initializer list. This makes it possible to
+  // pass a brace-enclosed initializer list to a function expecting an AnySpan.
+  //
+  // Example:
+  //
+  //   void Process(AnySpan<const int> x);
+  //   Process({1, 2, 3});
+  //
+  // The initializer_list must outlive this AnySpan.
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      std::initializer_list<value_type> l ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : AnySpan(l.begin(), l.size()) {}
+
+  // Creates a span that wraps an initializer list of a type other than
+  // value_type, or with an explicit transform. Applies the optional transform
+  // to elements before returning them.
+  //
+  // Example:
+  //
+  //   struct Base {};
+  //   struct Derived : Base {};
+  //
+  //   void Process(AnySpan<const Base> x);
+  //   Process({Derived(a), Derived(b), Derived(c)});
+  //
+  //     where the default identity transform would apply an implicit
+  //     derived-to-base  conversion.
+  //
+  // The initializer_list must outlive this AnySpan.
+  template <typename Element, typename Transform,
+            typename = EnableIfTransformIsValid<Transform, const Element&>,
+            EnableIfTransformIsByCopy<Transform> = true>
+  constexpr AnySpan(std::initializer_list<Element> l
+                        ABSL_ATTRIBUTE_LIFETIME_BOUND,
+                    const Transform& transform)
+      : AnySpan(l.begin(), l.size(), transform) {}
+  template <typename Element,
+            typename Transform = any_span_transform::IdentityT,
+            typename = EnableIfTransformIsValid<Transform, const Element&>,
+            EnableIfTransformIsByRef<Transform> = true>
+  constexpr AnySpan(std::initializer_list<Element> l
+                        ABSL_ATTRIBUTE_LIFETIME_BOUND,
+                    const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =
+                        any_span_transform::Identity())
+      : AnySpan(l.begin(), l.size(), transform) {}
+
+  // Creates a span that wraps an array. Applies the optional transform to
+  // elements before returning them.
+  //
+  // Transform must be a function object with a const operator() that takes
+  // Element as an argument and return a reference to T or compatible object.
+  //
+  // Both the transform and array must outlive this span.
+  template <typename Element, typename Transform,
+            typename = EnableIfTransformIsValid<Transform, const Element&>,
+            EnableIfTransformIsByCopy<Transform> = true>
+  constexpr AnySpan(const Element* absl_nullable ptr
+                        ABSL_ATTRIBUTE_LIFETIME_BOUND,
+                    size_type size, const Transform& transform)
+      : AnySpan(any_span_internal::MakeArrayGetter<T>(ptr, transform), size) {}
+  template <typename Element,
+            typename Transform = any_span_transform::IdentityT,
+            typename = EnableIfTransformIsValid<Transform, const Element&>,
+            EnableIfTransformIsByRef<Transform> = true>
+  constexpr AnySpan(const Element* absl_nullable ptr
+                        ABSL_ATTRIBUTE_LIFETIME_BOUND,
+                    size_type size,
+                    const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =
+                        any_span_transform::Identity())
+      : AnySpan(any_span_internal::MakeArrayGetter<T>(ptr, transform), size) {}
+
+  // Creates a span that wraps an array of fixed size. Applies the optional
+  // transform to elements before returning them.
+  //
+  // Transform must be a function object with a const operator() that takes
+  // Element as an argument and return a reference to T or compatible object.
+  //
+  // Both the transform and array must outlive this span.
+  template <typename Element, size_type N, typename Transform,
+            typename = EnableIfTransformIsValid<Transform, const Element&>,
+            EnableIfTransformIsByCopy<Transform> = true>
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      const Element (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N],
+      const Transform& transform)
+      : AnySpan(array, N, transform) {}
+  template <typename Element, size_type N,
+            typename Transform = any_span_transform::IdentityT,
+            typename = EnableIfTransformIsValid<Transform, const Element&>,
+            EnableIfTransformIsByRef<Transform> = true>
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      const Element (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N],
+      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =
+          any_span_transform::Identity())
+      : AnySpan(array, N, transform) {}
+
+  // Creates a span that wraps a const container. Applies the optional transform
+  // to elements before returning them.
+  //
+  // This constructor is enabled even for mutable spans, since some
+  // container-like objects provide mutable element access even when the object
+  // itself is const (such as absl::Span)
+  //
+  // Transform must be a function object with a const operator() that takes the
+  // value type of Container as an argument and return a reference to T or
+  // compatible object.
+  //
+  // The transform, container, and the container's underlying storage must
+  // outlive this span. Any operation that may reallocate the container's
+  // storage or change its size will invalidate the span.
+  template <typename Container, typename Transform,
+            typename = EnableIfContainer<Container>,
+            typename = EnableIfTransformIsValid<
+                Transform, decltype(std::declval<const Container&>()[0])>,
+            EnableIfTransformIsByCopy<std::enable_if_t<
+                absl::type_traits_internal::IsView<Container>::value,
+                Transform>> = true>
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      const Container& container, const Transform& transform)
+      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),
+                container.size()) {}
+  template <typename Container, typename Transform,
+            typename = EnableIfContainer<Container>,
+            typename = EnableIfTransformIsValid<
+                Transform, decltype(std::declval<const Container&>()[0])>,
+            EnableIfTransformIsByCopy<std::enable_if_t<
+                !absl::type_traits_internal::IsView<Container>::value,
+                Transform>> = true>
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      const Container& container ABSL_ATTRIBUTE_LIFETIME_BOUND,
+      const Transform& transform)
+      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),
+                container.size()) {}
+  template <
+      typename Container, typename Transform = any_span_transform::IdentityT,
+      typename = EnableIfContainer<Container>,
+      typename = EnableIfTransformIsValid<
+          Transform, decltype(std::declval<const Container&>()[0])>,
+      EnableIfTransformIsByRef<
+          std::enable_if_t<absl::type_traits_internal::IsView<Container>::value,
+                           Transform>> = true>
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      const Container& container,
+      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =
+          any_span_transform::Identity())
+      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),
+                container.size()) {}
+  template <typename Container,
+            typename Transform = any_span_transform::IdentityT,
+            typename = EnableIfContainer<Container>,
+            typename = EnableIfTransformIsValid<
+                Transform, decltype(std::declval<const Container&>()[0])>,
+            EnableIfTransformIsByRef<std::enable_if_t<
+                !absl::type_traits_internal::IsView<Container>::value,
+                Transform>> = true>
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      const Container& container ABSL_ATTRIBUTE_LIFETIME_BOUND,
+      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =
+          any_span_transform::Identity())
+      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),
+                container.size()) {}
+
+  // Creates a span that wraps a mutable array. Applies the optional transform
+  // to elements before returning them.
+  //
+  // Transform must be a function object with a const operator() that takes
+  // Element as an argument and return a reference to T or compatible object.
+  //
+  // Both the transform and array must outlive this span.
+  template <typename Element, typename Transform,
+            typename = EnableIfMutable<Element>,
+            typename = EnableIfTransformIsValid<Transform, Element&>,
+            EnableIfTransformIsByCopy<Transform> = true>
+  constexpr AnySpan(Element* absl_nullable ptr ABSL_ATTRIBUTE_LIFETIME_BOUND,
+                    size_type size, const Transform& transform)
+      : AnySpan(any_span_internal::MakeArrayGetter<T>(ptr, transform), size) {}
+  template <typename Element,
+            typename Transform = any_span_transform::IdentityT,
+            typename = EnableIfMutable<Element>,
+            typename = EnableIfTransformIsValid<Transform, Element&>,
+            EnableIfTransformIsByRef<Transform> = true>
+  constexpr AnySpan(Element* absl_nullable ptr ABSL_ATTRIBUTE_LIFETIME_BOUND,
+                    size_type size,
+                    const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =
+                        any_span_transform::Identity())
+      : AnySpan(any_span_internal::MakeArrayGetter<T>(ptr, transform), size) {}
+
+  // Creates a span that wraps a mutable array of fixed size. Applies the
+  // optional transform to elements before returning them.
+  //
+  // Transform must be a function object with a const operator() that takes
+  // Element as an argument and return a reference to T or compatible object.
+  //
+  // Both the transform and array must outlive this span.
+  template <typename Element, size_type N, typename Transform,
+            typename = EnableIfMutable<Element>,
+            typename = EnableIfTransformIsValid<Transform, Element&>,
+            EnableIfTransformIsByCopy<Transform> = true>
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      Element (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N],
+      const Transform& transform)
+      : AnySpan(array, N, transform) {}
+  template <typename Element, size_type N,
+            typename Transform = any_span_transform::IdentityT,
+            typename = EnableIfMutable<Element>,
+            typename = EnableIfTransformIsValid<Transform, Element&>,
+            EnableIfTransformIsByRef<Transform> = true>
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      Element (&array ABSL_ATTRIBUTE_LIFETIME_BOUND)[N],
+      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =
+          any_span_transform::Identity())
+      : AnySpan(array, N, transform) {}
+
+  // Creates a span that wraps a mutable container. Only enabled if T is
+  // mutable. Applies the optional transform to elements before returning them.
+  //
+  // Transform must be a function object with a const operator() that takes the
+  // value type of Container as an argument and return a reference to T or
+  // compatible object.
+  //
+  // The transform, container, and the container's underlying storage must
+  // outlive this span. Any operation that may reallocate the container's
+  // storage or change its size will invalidate the span.
+  template <typename Container, typename Transform,
+            typename = EnableIfMutable<Container>,
+            typename = EnableIfContainer<Container>,
+            typename = EnableIfTransformIsValid<
+                Transform, decltype(std::declval<Container&>()[0])>,
+            EnableIfTransformIsByCopy<Transform> = true>
+  constexpr explicit AnySpan(  // NOLINT(google-explicit-constructor)
+      Container& container ABSL_ATTRIBUTE_LIFETIME_BOUND,
+      const Transform& transform)
+      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),
+                container.size()) {}
+  template <typename Container,
+            typename Transform = any_span_transform::IdentityT,
+            typename = EnableIfMutable<Container>,
+            typename = EnableIfContainer<Container>,
+            typename = EnableIfTransformIsValid<
+                Transform, decltype(std::declval<Container&>()[0])>,
+            EnableIfTransformIsByRef<Transform> = true>
+  constexpr explicit AnySpan(  // NOLINT(google-explicit-constructor)
+      Container& container ABSL_ATTRIBUTE_LIFETIME_BOUND,
+      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND =
+          any_span_transform::Identity())
+      : AnySpan(any_span_internal::MakeContainerGetter<T>(container, transform),
+                container.size()) {}
+
+  // Converts a mutable span to a const span by copying the internal state
+  // (rather than wrapping the other span).
+  // TODO(b/179783710): add ABSL_ATTRIBUTE_LIFETIME_BOUND.
+  template <typename LazyT = T, typename = EnableIfConst<LazyT>>
+  constexpr AnySpan(  // NOLINT(google-explicit-constructor)
+      const AnySpan<typename std::remove_const<T>::type>& other)
+      : getter_(other.getter_), size_(other.size()) {}
+
+  // Creates a span that wraps around another span of different type.
+  //
+  // This has performance and lifetime consequences, and can easily happen by
+  // mistake. We make such conversions explicit here.
+  template <typename Element, typename = EnableIfDifferentElementType<Element>,
+            typename = EnableIfTransformIsValid<any_span_transform::IdentityT,
+                                                Element&>>
+  constexpr explicit AnySpan(
+      const AnySpan<Element>& other ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : AnySpan(any_span_internal::MakeContainerGetter<T>(
+                    other, any_span_transform::Identity()),
+                other.size()) {}
+
+  // Creates a span that wraps around another span. Applies the non-optional
+  // transform to elements before returning them.
+  //
+  // This has lifetime consequences, and may happen by mistake. We make it
+  // explicit here.
+  template <typename Element, typename Transform,
+            typename = EnableIfTransformIsValid<Transform, Element&>,
+            EnableIfTransformIsByCopy<Transform> = true>
+  constexpr explicit AnySpan(const AnySpan<Element>& other
+                                 ABSL_ATTRIBUTE_LIFETIME_BOUND,
+                             const Transform& transform)
+      : AnySpan(any_span_internal::MakeContainerGetter<T>(other, transform),
+                other.size()) {}
+  template <typename Element, typename Transform,
+            typename = EnableIfTransformIsValid<Transform, Element&>,
+            EnableIfTransformIsByRef<Transform> = true>
+  constexpr explicit AnySpan(
+      const AnySpan<Element>& other ABSL_ATTRIBUTE_LIFETIME_BOUND,
+      const Transform& transform ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : AnySpan(any_span_internal::MakeContainerGetter<T>(other, transform),
+                other.size()) {}
+
+  // Returns a subspan of this span. This span may become invalid before the
+  // subspan, but both the container and transform must remain valid.
+  // pos must be non-negative and <= size().
+  // len must be non-negative and <= size() - pos, or equal to npos.
+  // If len == npos, the subspan continues till the end of this span.
+
+  constexpr AnySpan subspan(size_type pos, size_type len) const {
+    const size_t this_size = size();
+    if (len == AnySpan<T>::npos) {
+      len = this_size - pos;
+    }
+    ABSL_HARDENING_ASSERT(pos <= this_size && len <= this_size - pos);
+    return AnySpan<T>(getter_.Offset(pos), len);
+  }
+
+  constexpr AnySpan subspan(size_type pos) const {
+    ABSL_HARDENING_ASSERT(pos <= size());
+    return AnySpan(getter_.Offset(pos), size() - pos);
+  }
+
+  // Returns a `AnySpan` containing first `len` elements. Parameter `len`
+  // must be non-negative and <= size().
+  constexpr AnySpan first(size_type len) const {
+    ABSL_HARDENING_ASSERT(len != AnySpan<T>::npos);
+    return subspan(0, len);
+  }
+
+  // Returns a `AnySpan` containing last `len` elements. Parameter `len` must be
+  // non-negative and <= size().
+  constexpr AnySpan last(size_type len) const { return subspan(size() - len); }
+
+  // Size operations.
+  constexpr size_type size() const { return size_; }
+  constexpr bool empty() const { return size() == 0; }
+
+  // Element access.
+  constexpr reference operator[](size_type index) const {
+    ABSL_HARDENING_ASSERT(index < size());
+    return getter_.Get(index);
+  }
+  constexpr reference at(size_type index) const {
+    if (ABSL_PREDICT_FALSE(index >= size())) {
+      absl::ThrowStdOutOfRange("AnySpan::at failed bounds check");
+    }
+    return getter_.Get(index);
+  }
+  constexpr reference front() const {
+    ABSL_HARDENING_ASSERT(size() > 0);
+    return (*this)[0];
+  }
+  constexpr reference back() const {
+    ABSL_HARDENING_ASSERT(size() > 0);
+    return (*this)[size() - 1];
+  }
+
+  // Iterator accessors.
+  constexpr iterator begin() const { return iterator(this, 0); }
+  constexpr iterator end() const { return iterator(this, size_); }
+  constexpr reverse_iterator rbegin() const { return reverse_iterator(end()); }
+  constexpr reverse_iterator rend() const { return reverse_iterator(begin()); }
+  constexpr const_iterator cbegin() const { return const_iterator(this, 0); }
+  constexpr const_iterator cend() const { return const_iterator(this, size_); }
+  constexpr const_reverse_iterator crbegin() const { return rbegin(); }
+  constexpr const_reverse_iterator crend() const { return rend(); }
+
+  // Constructs from a getter and size. Not for external use.
+  AnySpan(any_span_internal::Getter<T> getter, size_type size)
+      : getter_(getter), size_(size) {}
+
+  // Support for absl::Hash.
+  template <typename H>
+  friend constexpr H AbslHashValue(H state, AnySpan any_span) {
+    for (const auto& v : any_span) {
+      state = H::combine(std::move(state), v);
+    }
+    return H::combine(std::move(state), any_span.size());
+  }
+
+ private:
+  template <typename U>
+  friend class AnySpan;
+
+  template <typename U>
+  friend bool any_span_internal::IsCheap(AnySpan<U> s);
+
+  // Getter to access elements.
+  any_span_internal::Getter<T> getter_;
+
+  // The size of this span.
+  size_type size_ = 0;
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wnon-template-friend"
+#endif
+  // The technical reasons we need to declare these friends in this manner are
+  // quite subtle and confusing, but they're necessary on some toolchains to
+  // allow all mutable/const combinations with this & other range types while
+  // avoiding symbol collisions or ODR violations.
+  friend bool operator==(AnySpan<const T> a, AnySpan<const T> b);
+  friend bool operator!=(AnySpan<const T> a, AnySpan<const T> b);
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+  // operator==
+  friend bool operator==(AnySpan a, AnySpan b) {
+    return any_span_internal::EqualImpl<const T>(a, b);
+  }
+  friend bool operator!=(AnySpan a, AnySpan b) { return !(a == b); }
+};
+
+// Constructs an AnySpan from a container or array.
+template <int&... ExplicitArgumentBarrier, typename Container,
+          typename T = any_span_internal::ElementType<Container>>
+std::enable_if_t<
+    absl::type_traits_internal::IsView<std::remove_cv_t<Container>>::value,
+    AnySpan<T>>
+MakeAnySpan(Container& c) {
+  return AnySpan<T>(c);
+}
+template <int&... ExplicitArgumentBarrier, typename Container,
+          typename T = any_span_internal::ElementType<Container>>
+std::enable_if_t<
+    !absl::type_traits_internal::IsView<std::remove_cv_t<Container>>::value,
+    AnySpan<T>>
+MakeAnySpan(Container& c ABSL_ATTRIBUTE_LIFETIME_BOUND) {
+  return AnySpan<T>(c);
+}
+
+// Constructs an AnySpan that dereferences a container or array of pointers.
+template <int&... ExplicitArgumentBarrier, typename Container,
+          typename T = any_span_internal::DerefElementType<Container>>
+std::enable_if_t<
+    absl::type_traits_internal::IsView<std::remove_cv_t<Container>>::value,
+    AnySpan<T>>
+MakeDerefAnySpan(Container& c) {
+  return AnySpan<T>(c, any_span_transform::Deref());
+}
+template <int&... ExplicitArgumentBarrier, typename Container,
+          typename T = any_span_internal::DerefElementType<Container>>
+std::enable_if_t<
+    !absl::type_traits_internal::IsView<std::remove_cv_t<Container>>::value,
+    AnySpan<T>>
+MakeDerefAnySpan(Container& c ABSL_ATTRIBUTE_LIFETIME_BOUND) {
+  return AnySpan<T>(c, any_span_transform::Deref());
+}
+
+// Constructs an AnySpan from a pointer and size.
+template <int&... ExplicitArgumentBarrier, typename T>
+AnySpan<T> MakeAnySpan(T* absl_nullable ptr ABSL_ATTRIBUTE_LIFETIME_BOUND,
+                       std::size_t size) {
+  return AnySpan<T>(ptr, size);
+}
+
+// Constructs a const AnySpan from a container or array.
+template <int&... ExplicitArgumentBarrier, typename Container,
+          typename T = any_span_internal::ElementType<const Container>>
+std::enable_if_t<absl::type_traits_internal::IsView<Container>::value,
+                 AnySpan<const T>>
+MakeConstAnySpan(const Container& c) {
+  return AnySpan<const T>(c);
+}
+template <int&... ExplicitArgumentBarrier, typename Container,
+          typename T = any_span_internal::ElementType<const Container>>
+std::enable_if_t<!absl::type_traits_internal::IsView<Container>::value,
+                 AnySpan<const T>>
+MakeConstAnySpan(const Container& c ABSL_ATTRIBUTE_LIFETIME_BOUND) {
+  return AnySpan<const T>(c);
+}
+
+// Constructs a const AnySpan that dereferences a container or array of
+// pointers.
+template <int&... ExplicitArgumentBarrier, typename Container,
+          typename T = any_span_internal::DerefElementType<const Container>>
+std::enable_if_t<absl::type_traits_internal::IsView<Container>::value,
+                 AnySpan<const T>>
+MakeConstDerefAnySpan(const Container& c) {
+  return AnySpan<const T>(c, any_span_transform::Deref());
+}
+template <int&... ExplicitArgumentBarrier, typename Container,
+          typename T = any_span_internal::DerefElementType<const Container>>
+std::enable_if_t<!absl::type_traits_internal::IsView<Container>::value,
+                 AnySpan<const T>>
+MakeConstDerefAnySpan(const Container& c ABSL_ATTRIBUTE_LIFETIME_BOUND) {
+  return AnySpan<const T>(c, any_span_transform::Deref());
+}
+
+// Constructs an AnySpan from a pointer and size.
+template <int&... ExplicitArgumentBarrier, typename T>
+AnySpan<const T> MakeConstAnySpan(const T* absl_nullable ptr,
+                                  std::size_t size) {
+  return AnySpan<const T>(ptr, size);
+}
+
+//
+// Implementation details follow.
+//
+
+template <typename T>
+const typename AnySpan<T>::size_type AnySpan<T>::npos;
+
+// Iterator base class. Uses CRTP (Iter should be the child class). Constness of
+// the iterator is determined by the constness of Value.
+template <typename T>
+template <typename Iter, typename Value>
+class ABSL_ATTRIBUTE_VIEW AnySpan<T>::IteratorBase {
+ private:
+  // Returns a reference to this as the child class.
+  const Iter& self() const { return static_cast<const Iter&>(*this); }
+  Iter& self() { return static_cast<Iter&>(*this); }
+
+ public:
+  using iterator_category = std::random_access_iterator_tag;
+  using value_type = typename std::remove_const<Value>::type;
+  using difference_type = std::ptrdiff_t;
+  using reference = Value&;
+  using pointer = Value*;
+
+  // Constructs an invalid iterator.
+  IteratorBase() = default;
+
+  reference operator*() const { return (*container_)[index_]; }
+
+  pointer absl_nonnull operator->() const { return &(*container_)[index_]; }
+
+  reference operator[](difference_type i) const {
+    return (*container_)[index_ + i];
+  }
+
+  Iter& operator+=(difference_type d) {
+    index_ += d;
+    return self();
+  }
+
+  Iter& operator-=(difference_type d) { return self() += -d; }
+
+  Iter& operator++() {
+    self() += 1;
+    return self();
+  }
+
+  Iter operator++(int) {
+    Iter copy(self());
+    ++self();
+    return copy;
+  }
+
+  Iter& operator--() {
+    self() -= 1;
+    return self();
+  }
+
+  Iter operator--(int) {
+    Iter copy(self());
+    --self();
+    return copy;
+  }
+
+  Iter operator+(difference_type d) const {
+    Iter tmp = self();
+    tmp += d;
+    return tmp;
+  }
+
+  friend Iter operator+(difference_type d, Iter i) { return i + d; }
+
+  Iter operator-(difference_type d) const { return self() + (-d); }
+
+  difference_type operator-(const Iter& other) const {
+    return index_ - other.index_;
+  }
+
+  friend bool operator==(const Iter& a, const Iter& b) {
+    return a.index_ == b.index_;
+  }
+
+  friend bool operator!=(const Iter& a, const Iter& b) {
+    return a.index_ != b.index_;
+  }
+
+  friend bool operator<(const Iter& a, const Iter& b) {
+    return a.index_ < b.index_;
+  }
+
+  friend bool operator<=(const Iter& a, const Iter& b) {
+    return a.index_ <= b.index_;
+  }
+
+  friend bool operator>(const Iter& a, const Iter& b) {
+    return a.index_ > b.index_;
+  }
+
+  friend bool operator>=(const Iter& a, const Iter& b) {
+    return a.index_ >= b.index_;
+  }
+
+ protected:
+  // Constructs an iterator that points to the given index of the given span.
+  IteratorBase(const AnySpan* absl_nullable container, size_type index)
+      : container_(container), index_(index) {}
+
+  const AnySpan* absl_nullable container_ = nullptr;
+  size_type index_ = 0;
+};
+
+// iterator implementation. This mostly just forwards to IteratorBase.
+template <typename T>
+class ABSL_ATTRIBUTE_VIEW AnySpan<T>::iterator
+    : public IteratorBase<iterator, T> {
+ private:
+  using Base = IteratorBase<iterator, T>;
+
+ public:
+  using typename Base::difference_type;
+  using typename Base::iterator_category;
+  using typename Base::pointer;
+  using typename Base::reference;
+  using typename Base::value_type;
+
+  iterator() = default;
+
+ private:
+  // Only let AnySpan construct valid instances.
+  friend class AnySpan;
+
+  iterator(const AnySpan* absl_nullable container, size_type index)
+      : Base(container, index) {}
+};
+
+// const_iterator implementation. This mostly just forwards to IteratorBase,
+// but also provides conversion from MutableIterator.
+template <typename T>
+class AnySpan<T>::const_iterator
+    : public IteratorBase<const_iterator, typename std::add_const<T>::type> {
+ private:
+  using Base = IteratorBase<const_iterator, typename std::add_const<T>::type>;
+
+ public:
+  using typename Base::difference_type;
+  using typename Base::iterator_category;
+  using typename Base::pointer;
+  using typename Base::reference;
+  using typename Base::value_type;
+
+  const_iterator() = default;
+
+  // Support conversion from mutable iterators.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  const_iterator(const iterator& other)  // NOLINT(runtime/explicit)
+      : Base(other.container_, other.index_) {}
+
+ private:
+  // Only let AnySpan construct valid instances.
+  friend class AnySpan;
+
+  const_iterator(const AnySpan* absl_nullable container, size_type index)
+      : Base(container, index) {}
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_TYPES_ANY_SPAN_H_
diff --git a/absl/types/any_span_benchmark.cc b/absl/types/any_span_benchmark.cc
new file mode 100644
index 0000000..24e9644
--- /dev/null
+++ b/absl/types/any_span_benchmark.cc
@@ -0,0 +1,258 @@
+// Copyright 2026 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cstddef>
+#include <cstdint>
+#include <deque>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/flags/flag.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/any_span.h"
+#include "absl/types/span.h"
+#include "benchmark/benchmark.h"
+
+ABSL_FLAG(uint64_t, benchmark_container_size, 2000,
+          "The size of the containers to use for benchmarking.");
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+//
+// Benchmarks and supporting code follows.
+//
+
+template <typename T>
+T MakeElement(int) {
+  ABSL_RAW_LOG(FATAL, "Not implemented.");
+}
+
+template <>
+std::string MakeElement<std::string>(int i) {
+  return absl::StrCat(i, i, i);
+}
+
+template <>
+int MakeElement<int>(int i) {
+  return i;
+}
+
+template <typename Container>
+Container MakeContainer() {
+  const size_t container_size = absl::GetFlag(FLAGS_benchmark_container_size);
+  Container c;
+  for (size_t i = 0; i < container_size; ++i) {
+    c.push_back(
+        MakeElement<typename Container::value_type>(static_cast<int>(i)));
+  }
+  return c;
+}
+
+template <typename Container, typename SourceContainer>
+Container MakePointerContainer(SourceContainer* source) {
+  Container c;
+  for (auto& value : *source) {
+    c.push_back(&value);
+  }
+  return c;
+}
+
+//
+// Sequential Access Benchmarks
+//
+
+// Control run, iterating original container.
+template <typename Container>
+void BM_Sequential(benchmark::State& state) {
+  auto a = MakeContainer<Container>();
+  benchmark::DoNotOptimize(a);
+  for (auto _ : state) {
+    for (auto& v : a) {
+      benchmark::DoNotOptimize(v);
+    }
+  }
+}
+
+// Wraps the container with a Span.
+template <typename Container>
+void BM_Sequential_Span(benchmark::State& state) {
+  auto container = MakeContainer<Container>();
+  absl::Span<typename Container::value_type> array_span(container);
+  benchmark::DoNotOptimize(array_span);
+  for (auto _ : state) {
+    for (auto& v : array_span) {
+      benchmark::DoNotOptimize(v);
+    }
+  }
+}
+
+// Same as BM_Sequential_Span, but uses a container of pointers and
+// dereferences it.
+template <typename Container>
+void BM_Sequential_DerefSpan(benchmark::State& state) {
+  using T = typename std::remove_pointer<typename Container::value_type>::type;
+  auto values = MakeContainer<std::vector<T>>();
+  const auto container = MakePointerContainer<Container>(&values);
+  absl::Span<T* const> array_span(container);
+  benchmark::DoNotOptimize(array_span);
+  for (auto _ : state) {
+    for (const auto& v : array_span) {
+      benchmark::DoNotOptimize(*v);
+    }
+  }
+}
+
+// Wraps a AnySpan<const T> around a Container. Sequentially reads the
+// entire span.
+template <typename Container>
+void BM_Sequential_AnySpan(benchmark::State& state) {
+  using T = typename Container::value_type;
+  auto container = MakeContainer<Container>();
+  AnySpan<T> span(container);
+  benchmark::DoNotOptimize(span);
+  for (auto _ : state) {
+    for (T& s : span) {
+      benchmark::DoNotOptimize(s);
+    }
+  }
+}
+
+// Same as BM_Sequential_AnySpan, but dereferences the elements.
+template <typename Container>
+void BM_Sequential_AnySpanDeref(benchmark::State& state) {
+  using T = typename std::remove_pointer<typename Container::value_type>::type;
+  auto values = MakeContainer<std::vector<T>>();
+  auto container = MakePointerContainer<Container>(&values);
+  AnySpan<T> span(container, any_span_transform::Deref());
+  benchmark::DoNotOptimize(span);
+  for (auto _ : state) {
+    for (auto& s : span) {
+      benchmark::DoNotOptimize(s);
+    }
+  }
+}
+
+//
+// Random Access Benchmarks
+//
+
+// Control run, accessing the original container.
+template <typename Container>
+void BM_Random(benchmark::State& state) {
+  auto a = MakeContainer<Container>();
+  auto* b = &a;
+  benchmark::DoNotOptimize(a);
+  benchmark::DoNotOptimize(b);
+  for (auto _ : state) {
+    uint64_t index_seed = 0;
+    for (size_t j = 0; j < a.size(); ++j) {
+      index_seed += 5623;
+      const uint64_t index = index_seed % a.size();
+      benchmark::DoNotOptimize((*b)[index]);
+    }
+  }
+}
+
+// Wraps a Span around a Container. Randomly reads the span.
+template <typename Container>
+void BM_Random_Span(benchmark::State& state) {
+  using T = typename Container::value_type;
+  auto v = MakeContainer<Container>();
+  absl::Span<T> array_span(v);
+  benchmark::DoNotOptimize(array_span);
+  for (auto _ : state) {
+    uint64_t index_seed = 0;
+    for (size_t j = 0; j < v.size(); ++j) {
+      index_seed += 5623;
+      const uint64_t index = index_seed % v.size();
+      benchmark::DoNotOptimize(array_span[index]);
+    }
+  }
+}
+
+// Wraps a AnySpan around a Container. Randomly reads the span.
+template <typename Container>
+void BM_Random_AnySpan(benchmark::State& state) {
+  using T = typename Container::value_type;
+  auto container = MakeContainer<Container>();
+  AnySpan<T> span(container);
+  benchmark::DoNotOptimize(span);
+  for (auto _ : state) {
+    uint64_t index_seed = 0;
+    for (size_t j = 0; j < container.size(); ++j) {
+      index_seed += 5623;
+      const uint64_t index = index_seed % span.size();
+      benchmark::DoNotOptimize(span[index]);
+    }
+  }
+}
+
+// Same as BM_Random_AnySpan, but dereferences elements.
+template <typename Container>
+void BM_Random_AnySpanDeref(benchmark::State& state) {
+  using T = typename std::remove_pointer<typename Container::value_type>::type;
+  auto values = MakeContainer<std::vector<T>>();
+  auto container = MakePointerContainer<Container>(&values);
+  AnySpan<T> span(container, any_span_transform::Deref());
+  benchmark::DoNotOptimize(span);
+  for (auto _ : state) {
+    uint64_t index_seed = 0;
+    for (size_t j = 0; j < container.size(); ++j) {
+      index_seed += 5623;
+      const uint64_t index = index_seed % span.size();
+      benchmark::DoNotOptimize(span[index]);
+    }
+  }
+}
+
+// Sequential access int.
+BENCHMARK_TEMPLATE(BM_Sequential, std::vector<int>);
+BENCHMARK_TEMPLATE(BM_Sequential, std::deque<int>);
+BENCHMARK_TEMPLATE(BM_Sequential_Span, std::vector<int>);
+BENCHMARK_TEMPLATE(BM_Sequential_AnySpan, std::vector<int>);
+BENCHMARK_TEMPLATE(BM_Sequential_AnySpan, std::deque<int>);
+
+// Sequential access string.
+BENCHMARK_TEMPLATE(BM_Sequential, std::vector<std::string>);
+BENCHMARK_TEMPLATE(BM_Sequential, std::deque<std::string>);
+BENCHMARK_TEMPLATE(BM_Sequential_Span, std::vector<std::string>);
+BENCHMARK_TEMPLATE(BM_Sequential_AnySpan, std::vector<std::string>);
+BENCHMARK_TEMPLATE(BM_Sequential_AnySpan, std::deque<std::string>);
+BENCHMARK_TEMPLATE(BM_Sequential_DerefSpan, std::vector<std::string*>);
+BENCHMARK_TEMPLATE(BM_Sequential_AnySpanDeref, std::vector<std::string*>);
+
+// Random access int.
+BENCHMARK_TEMPLATE(BM_Random, std::vector<int>);
+BENCHMARK_TEMPLATE(BM_Random, std::deque<int>);
+BENCHMARK_TEMPLATE(BM_Random_Span, std::vector<int>);
+BENCHMARK_TEMPLATE(BM_Random_AnySpan, std::vector<int>);
+BENCHMARK_TEMPLATE(BM_Random_AnySpan, std::deque<int>);
+
+// Random access string.
+BENCHMARK_TEMPLATE(BM_Random, std::vector<std::string>);
+BENCHMARK_TEMPLATE(BM_Random, std::deque<std::string>);
+BENCHMARK_TEMPLATE(BM_Random_Span, std::vector<std::string>);
+BENCHMARK_TEMPLATE(BM_Random_AnySpan, std::vector<std::string>);
+BENCHMARK_TEMPLATE(BM_Random_AnySpan, std::deque<std::string>);
+BENCHMARK_TEMPLATE(BM_Random_AnySpanDeref, std::vector<std::string*>);
+
+}  // namespace
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/types/any_span_test.cc b/absl/types/any_span_test.cc
new file mode 100644
index 0000000..8ff1fdd
--- /dev/null
+++ b/absl/types/any_span_test.cc
@@ -0,0 +1,1210 @@
+// Copyright 2026 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/types/any_span.h"
+
+#include <cstddef>
+#include <deque>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/exception_testing.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/hash/hash_testing.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+using testing::ElementsAre;
+
+static_assert(!absl::type_traits_internal::IsOwner<AnySpan<int>>::value &&
+                  absl::type_traits_internal::IsView<AnySpan<int>>::value,
+              "AnySpan is a view, not an owner");
+
+bool IsHardened() {
+  bool hardened = false;
+  ABSL_HARDENING_ASSERT([&hardened]() {
+    hardened = true;
+    return true;
+  }());
+  return hardened;
+}
+
+// Tests that the span points to all of the elements of the given container.
+template <typename T, typename Container>
+void ExpectSpanEqualsContainer(AnySpan<T> span, const Container& c) {
+  EXPECT_EQ(span.size(), c.size());
+  typename AnySpan<const T>::size_type index = 0;
+  for (const T& s : span) {
+    SCOPED_TRACE(index);
+    const T& expected = c[index];
+    EXPECT_EQ(expected, s);
+    EXPECT_EQ(expected, span[index]);
+    EXPECT_EQ(&expected, &span[index]);
+    ++index;
+  }
+  EXPECT_EQ(index, span.size());
+}
+
+// AnySpanTest covers parts of AnySpan that make sense for both const and
+// non-const elements. How the given tests will run is determined by whether or
+// not ElementsAreConst is true_type or false_type.
+template <typename ElementsAreConst>
+class AnySpanTest : public ::testing::Test {
+ public:
+  using IsConstTest = ElementsAreConst;
+
+  // Const T if this test instantiation is supposed to cover const AnySpans.
+  // T if this test instantiation is supposed to cover mutable AnySpans.
+  template <typename T>
+  using MaybeConst =
+      typename std::conditional<IsConstTest::value, const T, T>::type;
+
+  // Initalizes a AnySpan around the given container and tests for
+  // equality in a variety of ways.
+  template <typename T, typename Container, typename Transform>
+  static void TestContainer(Container c, const Transform& t) {
+    AnySpan<MaybeConst<T>> span(c, t);
+    EXPECT_NO_FATAL_FAILURE(ExpectSpanEqualsContainer(span, c));
+  }
+
+  // Initializes a dereferencing AnySpan around the given container of pointers
+  // and tests for equality in a variety of ways.
+  template <typename T, typename Container>
+  static void TestPointerContainer(Container* c) {
+    AnySpan<const T> span(*c, any_span_transform::Deref());
+    EXPECT_EQ(span.size(), c->size());
+    int index = 0;
+    for (const T& s : span) {
+      const T& expected = *(*c)[index];
+      EXPECT_EQ(expected, s);
+      EXPECT_EQ(expected, span[index]);
+      EXPECT_EQ(&expected, &span[index]);
+      index++;
+    }
+    EXPECT_EQ(index, span.size());
+  }
+};
+
+using ElementsAreConst = ::testing::Types<std::true_type, std::false_type>;
+
+TYPED_TEST_SUITE(AnySpanTest, ElementsAreConst);
+
+TYPED_TEST(AnySpanTest, NullAndEmpty) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  AnySpan<T> empty;
+  EXPECT_TRUE(empty.empty());
+  EXPECT_EQ(empty.size(), 0);
+  for (const std::string& a : empty) {
+    (void)a;
+    ABSL_RAW_LOG(FATAL, "Empty container should not iterate.");
+  }
+  EXPECT_EQ(empty.begin(), empty.end());
+}
+
+TYPED_TEST(AnySpanTest, Ptr) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  AnySpan<T> span1(v.data(), v.size());
+  EXPECT_EQ(&span1[0], &v[0]);
+  AnySpan<T> span2(v.data(), v.size());
+  EXPECT_EQ(&span2[0], &v[0]);
+}
+
+TYPED_TEST(AnySpanTest, PtrPtr) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  int i;
+  std::vector<int*> v = {&i};
+  AnySpan<T> span(v.data(), v.size(), any_span_transform::Deref());
+  EXPECT_EQ(&span[0], &i);
+}
+
+TYPED_TEST(AnySpanTest, DerefOptional) {
+  const std::vector<std::optional<int>> v = {17, 19};
+  const AnySpan<const int> span = absl::MakeDerefAnySpan(v);
+  EXPECT_THAT(span, ElementsAre(17, 19));
+}
+
+TYPED_TEST(AnySpanTest, ArrayOfKnownSize) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::string a[] = {"a", "b", "c", "d"};
+
+  AnySpan<T> span(a);
+  EXPECT_EQ(span.size(), 4);
+  EXPECT_EQ(&span[0], &a[0]);
+}
+
+// This gets its own test because AnySpan(array, size) has the potential to be
+// ambiguous with AnySpan(array, transform).
+TYPED_TEST(AnySpanTest, ArrayWithExplicitSize) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::string a[] = {"a", "b", "c", "d"};
+
+  AnySpan<T> span(a, 4);
+  EXPECT_EQ(span.size(), 4);
+  EXPECT_EQ(&span[0], &a[0]);
+}
+
+TYPED_TEST(AnySpanTest, PtrArrayOfKnownSize) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::string s;
+  std::string* a[] = {&s, &s, &s, &s};
+
+  AnySpan<T> span(a, any_span_transform::Deref());
+  EXPECT_EQ(span.size(), 4);
+  EXPECT_EQ(&span[0], &s);
+}
+
+TYPED_TEST(AnySpanTest, Range) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> a = {"a", "b", "c", "d"};
+  auto range = any_span_adaptor::MakeAdaptorFromRange(a.begin(), a.end());
+  AnySpan<T> span(range);
+  EXPECT_NO_FATAL_FAILURE(ExpectSpanEqualsContainer(span, a));
+}
+
+TYPED_TEST(AnySpanTest, View) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> a = {"a", "b", "c", "d"};
+  auto range = any_span_adaptor::MakeAdaptorFromView(a);
+  AnySpan<T> span(range);
+  EXPECT_NO_FATAL_FAILURE(ExpectSpanEqualsContainer(span, a));
+}
+
+TYPED_TEST(AnySpanTest, VectorString) {
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<std::string>(
+      std::vector<std::string>{"a", "b", "c", "d"},
+      any_span_transform::Identity()));
+}
+
+TYPED_TEST(AnySpanTest, VectorInt) {
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<int>(
+      std::vector<int>{1, 2, 3, 4}, any_span_transform::Identity()));
+}
+
+TYPED_TEST(AnySpanTest, VectorStringPointer) {
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  std::vector<std::string*> vp;
+  for (std::string& s : v) {
+    vp.push_back(&s);
+  }
+  TestFixture::template TestPointerContainer<std::string>(&vp);
+}
+
+TYPED_TEST(AnySpanTest, VectorStringUniquePointer) {
+  std::vector<std::unique_ptr<std::string>> v;
+  for (const std::string& s : std::vector<std::string>{"a", "b", "c", "d"}) {
+    v.emplace_back(new std::string(s));
+  }
+  TestFixture::template TestPointerContainer<std::string>(&v);
+}
+
+TYPED_TEST(AnySpanTest, VectorIntPointer) {
+  std::vector<int> v = {1, 2, 3, 4};
+  std::vector<int*> vp;
+  for (int& i : v) {
+    vp.push_back(&i);
+  }
+  TestFixture::template TestPointerContainer<int>(&vp);
+}
+
+TYPED_TEST(AnySpanTest, DequeString) {
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<std::string>(
+      std::deque<std::string>{"a", "b", "c", "d"},
+      any_span_transform::Identity()));
+}
+
+TYPED_TEST(AnySpanTest, DequeInt) {
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<int>(
+      std::deque<int>{1, 2, 3, 4}, any_span_transform::Identity()));
+}
+
+TYPED_TEST(AnySpanTest, DequeStringPtr) {
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  std::deque<std::string*> dp;
+  for (std::string& s : v) {
+    dp.push_back(&s);
+  }
+  TestFixture::template TestPointerContainer<std::string>(&dp);
+}
+
+TYPED_TEST(AnySpanTest, ImplicitConversions) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::string one = "1";
+  std::string two = "2";
+  std::vector<std::reference_wrapper<std::string>> v(
+      {std::ref(one), std::ref(two)});
+  AnySpan<T> span(v);
+
+  EXPECT_THAT(span, ElementsAre("1", "2"));
+}
+
+TYPED_TEST(AnySpanTest, TrivialSubspan) {
+  EXPECT_EQ(AnySpan<int>().subspan(0).size(), 0);
+}
+
+TYPED_TEST(AnySpanTest, TrivialFirst) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  EXPECT_EQ(AnySpan<T>().first(0).size(), 0);
+}
+
+TYPED_TEST(AnySpanTest, TrivialLast) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  EXPECT_EQ(AnySpan<T>().last(0).size(), 0);
+}
+
+struct Base1 {
+  virtual ~Base1() = default;
+  bool operator==(const Base1& other) const { return this == &other; }
+  int b1 = 1;
+};
+struct Base2 {
+  virtual ~Base2() = default;
+  bool operator==(const Base2& other) const { return this == &other; }
+  int b2 = 2;
+};
+struct Child : public Base1, public Base2 {
+  bool operator==(const Child& other) const { return this == &other; }
+};
+
+TYPED_TEST(AnySpanTest, VectorBaseClass) {
+  std::vector<Child> v;
+  v.resize(20);
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base1>(
+      v, any_span_transform::Identity()));
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base2>(
+      v, any_span_transform::Identity()));
+}
+
+TYPED_TEST(AnySpanTest, AnySpanVectorBaseClass) {
+  std::vector<Child> v;
+  v.resize(20);
+  AnySpan<Child> span(v);
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base1>(
+      span, any_span_transform::Identity()));
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base2>(
+      span, any_span_transform::Identity()));
+}
+
+TYPED_TEST(AnySpanTest, DerefAnySpanVectorBaseClass) {
+  Child c;
+  std::vector<Child*> v_ptrs(20, &c);
+  AnySpan<Child> span(v_ptrs, any_span_transform::Deref());
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base1>(
+      span, any_span_transform::Identity()));
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base2>(
+      span, any_span_transform::Identity()));
+}
+
+TYPED_TEST(AnySpanTest, AnySpanDequeBaseClass) {
+  std::deque<Child> v;
+  v.resize(20);
+  AnySpan<Child> span(v);
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base1>(
+      span, any_span_transform::Identity()));
+  EXPECT_NO_FATAL_FAILURE(TestFixture::template TestContainer<Base2>(
+      span, any_span_transform::Identity()));
+}
+
+TYPED_TEST(AnySpanTest, VectorSubspan) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::vector<int> v = {1, 2, 3, 4};
+  auto span = AnySpan<T>(v).subspan(1, 2);
+  EXPECT_EQ(span.size(), 2);
+  EXPECT_EQ(span[0], 2);
+  EXPECT_EQ(span[1], 3);
+  span = AnySpan<T>(v).subspan(1);
+  EXPECT_EQ(span.size(), 3);
+  EXPECT_EQ(span[2], 4);
+
+  std::vector<int> zero_length_vector;
+  auto zero_length_subspan = AnySpan<T>(zero_length_vector).subspan(0);
+  EXPECT_EQ(zero_length_subspan.size(), 0);
+}
+
+TYPED_TEST(AnySpanTest, DequeSubspan) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::deque<int> v = {1, 2, 3, 4};
+  auto span = AnySpan<T>(v).subspan(1, 2);
+  EXPECT_EQ(span.size(), 2);
+  EXPECT_EQ(span[0], 2);
+  EXPECT_EQ(span[1], 3);
+}
+
+TYPED_TEST(AnySpanTest, VectorFirst) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::vector<int> v = {1, 2, 3, 4};
+  auto span = AnySpan<T>(v).first(2);
+  EXPECT_THAT(span, ElementsAre(1, 2));
+  span = AnySpan<T>(v).first(4);
+  EXPECT_THAT(span, ElementsAre(1, 2, 3, 4));
+
+  std::vector<int> zero_length_vector;
+  auto zero_length_subspan = AnySpan<T>(zero_length_vector).first(0);
+  EXPECT_EQ(zero_length_subspan.size(), 0);
+}
+
+TYPED_TEST(AnySpanTest, DequeFirst) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::deque<int> v = {1, 2, 3, 4};
+  auto span = AnySpan<T>(v).first(2);
+  EXPECT_THAT(span, ElementsAre(1, 2));
+}
+
+TYPED_TEST(AnySpanTest, VectorLast) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::vector<int> v = {1, 2, 3, 4};
+  auto span = AnySpan<T>(v).last(2);
+  EXPECT_THAT(span, ElementsAre(3, 4));
+  span = AnySpan<T>(v).last(4);
+  EXPECT_THAT(span, ElementsAre(1, 2, 3, 4));
+
+  std::vector<int> zero_length_vector;
+  auto zero_length_subspan = AnySpan<T>(zero_length_vector).last(0);
+  EXPECT_EQ(zero_length_subspan.size(), 0);
+}
+
+TYPED_TEST(AnySpanTest, DequeLast) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::deque<int> v = {1, 2, 3, 4};
+  auto span = AnySpan<T>(v).last(2);
+  EXPECT_THAT(span, ElementsAre(3, 4));
+}
+
+TYPED_TEST(AnySpanTest, LambdaTransformFromVector) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> v = {"b", "a", "d", "c"};
+  std::vector<int> alphabetical_order = {1, 0, 3, 2};
+  auto subscript_v = [&v](size_t i) -> std::string& { return v[i]; };
+  AnySpan<T> span(alphabetical_order, subscript_v);
+  EXPECT_EQ(span[0], "a");
+  EXPECT_EQ(span[1], "b");
+  EXPECT_EQ(span[2], "c");
+  EXPECT_EQ(span[3], "d");
+}
+
+TYPED_TEST(AnySpanTest, LambdaTransformFromSpanOfDifferentType) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  using U = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> v = {"b", "a", "d", "c"};
+  std::vector<int> alphabetical_order = {1, 0, 3, 2};
+  AnySpan<T> alphabetical_order_as_span(alphabetical_order);
+  auto subscript_v = [&v](size_t i) -> std::string& { return v[i]; };
+  AnySpan<U> span(alphabetical_order_as_span, subscript_v);
+  EXPECT_EQ(span[0], "a");
+  EXPECT_EQ(span[1], "b");
+  EXPECT_EQ(span[2], "c");
+  EXPECT_EQ(span[3], "d");
+}
+
+TYPED_TEST(AnySpanTest, LambdaTransformFromSpanOfSameType) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::vector<int> v = {2, 1, 4, 3};
+  std::vector<int> sorted_order = {1, 0, 3, 2};
+  AnySpan<T> sorted_order_as_span(sorted_order);
+  auto subscript_v = [&v](size_t i) -> int& { return v[i]; };
+  AnySpan<T> span(sorted_order_as_span, subscript_v);
+  EXPECT_EQ(span[0], 1);
+  EXPECT_EQ(span[1], 2);
+  EXPECT_EQ(span[2], 3);
+  EXPECT_EQ(span[3], 4);
+}
+
+TYPED_TEST(AnySpanTest, MakeAnySpanFromVector) {
+  using V = typename TestFixture::template MaybeConst<std::vector<int>>;
+  using T = typename TestFixture::template MaybeConst<int>;
+  V v = {1, 2, 3, 4};
+  auto span = MakeAnySpan(v);
+  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<T>>()));
+  EXPECT_EQ(span.size(), 4);
+  for (size_t i = 0; i < 4; ++i) {
+    EXPECT_EQ(&span[i], &v[i]);
+  }
+}
+
+TYPED_TEST(AnySpanTest, MakeAnySpanFromPtrAndSize) {
+  using V = typename TestFixture::template MaybeConst<std::vector<int>>;
+  using T = typename TestFixture::template MaybeConst<int>;
+  V v = {1, 2, 3, 4};
+  auto span = MakeAnySpan(v.data(), v.size());
+  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<T>>()));
+  EXPECT_EQ(span.size(), 4);
+  for (int i = 0; i < 4; ++i) {
+    EXPECT_EQ(&span[i], &v[i]);
+  }
+}
+
+TYPED_TEST(AnySpanTest, MakeAnySpanFromArray) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  T a[] = {1, 2, 3, 4};
+  auto span = MakeAnySpan(a);
+  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<T>>()));
+  EXPECT_EQ(span.size(), 4);
+  for (int i = 0; i < 4; ++i) {
+    EXPECT_EQ(&span[i], &a[i]);
+  }
+}
+
+TYPED_TEST(AnySpanTest, MakeDerefAnySpanFromArray) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  T v = 0;
+  T* a[] = {&v, &v, &v};
+  auto span = MakeDerefAnySpan(a);
+  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<T>>()));
+  EXPECT_EQ(span.size(), 3);
+  for (int i = 0; i < 3; ++i) {
+    EXPECT_EQ(&span[i], a[i]);
+  }
+}
+
+// Tests transforms that are supported by std::invoke.
+TYPED_TEST(AnySpanTest, InvokableTransforms) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  struct S;
+  using SRef = typename TestFixture::template MaybeConst<S>&;
+  struct S {
+    std::string a, b;
+    static T& Fun(SRef p) { return p.a; }
+    std::string& MemFun() { return a; }
+    const std::string& MemFun() const { return a; }
+  };
+
+  // For const span tests, we need a pointer to constant member function. We
+  // choose the correct type of member function here.
+  using MemFunPtr =
+      typename std::conditional<TestFixture::IsConstTest::value,
+                                T& (S::*)() const, T& (S::*)()>::type;
+
+  std::vector<S> v = {{"1", "2"}, {"3", "4"}};
+  S a[] = {{"1", "2"}, {"3", "4"}};
+  T& (*fun_ptr)(SRef) = &S::Fun;
+  MemFunPtr mem_fun_ptr = &S::MemFun;
+  T S::* mem_ptr = &S::a;
+
+  AnySpan<T> spans[] = {
+      // Function reference.
+      AnySpan<T>(v, S::Fun),
+      AnySpan<T>(a, S::Fun),
+      AnySpan<T>(a, 2, S::Fun),
+
+      // Function pointer prvalue.
+      AnySpan<T>(v, &S::Fun),
+      AnySpan<T>(a, &S::Fun),
+      AnySpan<T>(a, 2, &S::Fun),
+
+      // Function pointer lvalue.
+      AnySpan<T>(v, fun_ptr),
+      AnySpan<T>(a, fun_ptr),
+      AnySpan<T>(a, 2, fun_ptr),
+
+      // Dereferenced function pointer variable.
+      AnySpan<T>(v, *fun_ptr),
+      AnySpan<T>(a, *fun_ptr),
+      AnySpan<T>(a, 2, *fun_ptr),
+
+      // Member function pointer.
+      AnySpan<T>(v, mem_fun_ptr),
+      AnySpan<T>(a, mem_fun_ptr),
+      AnySpan<T>(a, 2, mem_fun_ptr),
+
+      // Data member.
+      AnySpan<T>(v, mem_ptr),
+      AnySpan<T>(a, mem_ptr),
+      AnySpan<T>(a, 2, mem_ptr),
+  };
+
+  for (const auto& span : spans) {
+    EXPECT_EQ(span[0], "1");
+    EXPECT_EQ(span[1], "3");
+  }
+}
+
+TYPED_TEST(AnySpanTest, VectorPtrSubspan) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::vector<int> v = {1, 2, 3, 4};
+  std::vector<int*> vp;
+  for (int& i : v) {
+    vp.push_back(&i);
+  }
+  AnySpan<T> span = AnySpan<T>(vp, any_span_transform::Deref()).subspan(1, 2);
+  EXPECT_EQ(span.size(), 2);
+  EXPECT_EQ(span[0], 2);
+  EXPECT_EQ(span[1], 3);
+}
+
+TYPED_TEST(AnySpanTest, VectorPtrFirst) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::vector<int> v = {1, 2, 3, 4};
+  std::vector<int*> vp;
+  for (int& i : v) {
+    vp.push_back(&i);
+  }
+  AnySpan<T> span = AnySpan<T>(vp, any_span_transform::Deref()).first(2);
+  EXPECT_THAT(span, ElementsAre(1, 2));
+}
+
+TYPED_TEST(AnySpanTest, VectorPtrLast) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  std::vector<int> v = {1, 2, 3, 4};
+  std::vector<int*> vp;
+  for (int& i : v) {
+    vp.push_back(&i);
+  }
+  AnySpan<T> span = AnySpan<T>(vp, any_span_transform::Deref()).last(2);
+  EXPECT_THAT(span, ElementsAre(3, 4));
+}
+
+TYPED_TEST(AnySpanTest, Iterator) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> v = {"0", "1", "2", "3"};
+  AnySpan<T> span(v);
+
+  // Dereference.
+  auto it = span.begin();
+  EXPECT_EQ("0", *it);
+
+  // Postfix increment.
+  EXPECT_EQ("0", *(it++));
+  EXPECT_EQ("1", *(it++));
+
+  // Postfix decrement.
+  EXPECT_EQ("2", *(it--));
+  EXPECT_EQ("1", *(it--));
+
+  // Prefix increment.
+  EXPECT_EQ(it, span.begin());
+  EXPECT_EQ("1", *(++it));
+  EXPECT_EQ("2", *(++it));
+
+  // Postfix decrement.
+  EXPECT_EQ("1", *(--it));
+  EXPECT_EQ("0", *(--it));
+
+  // Increment by integer.
+  EXPECT_EQ(it, span.begin());
+  it += 3;
+  EXPECT_EQ("3", *it);
+
+  // Decrement by integer.
+  it = span.end();
+  it -= 4;
+  EXPECT_EQ("0", *it);
+
+  // Add and subtract.
+  EXPECT_EQ(v.begin() + 2, v.end() - 2);
+  EXPECT_EQ(2 + v.begin(), v.end() - 2);
+
+  // Index.
+  it = span.begin();
+  EXPECT_EQ("3", v[3]);
+
+  // Relational operators.
+  EXPECT_TRUE(span.begin() != span.end());
+  EXPECT_TRUE(span.begin() == span.begin());
+  EXPECT_TRUE(span.begin() < span.end());
+  EXPECT_TRUE(span.begin() <= span.end());
+  EXPECT_TRUE(span.end() > span.begin());
+  EXPECT_TRUE(span.end() >= span.begin());
+}
+
+TYPED_TEST(AnySpanTest, ConstIterator) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> v = {"0", "1", "2", "3"};
+  AnySpan<T> span(v);
+
+  // Dereference.
+  auto it = span.cbegin();
+  EXPECT_EQ("0", *it);
+
+  // Postfix increment.
+  EXPECT_EQ("0", *(it++));
+  EXPECT_EQ("1", *(it++));
+
+  // Postfix decrement.
+  EXPECT_EQ("2", *(it--));
+  EXPECT_EQ("1", *(it--));
+
+  // Prefix increment.
+  EXPECT_EQ(it, span.cbegin());
+  EXPECT_EQ("1", *(++it));
+  EXPECT_EQ("2", *(++it));
+
+  // Postfix decrement.
+  EXPECT_EQ("1", *(--it));
+  EXPECT_EQ("0", *(--it));
+
+  // Increment by integer.
+  EXPECT_EQ(it, span.cbegin());
+  it += 3;
+  EXPECT_EQ("3", *it);
+
+  // Decrement by integer.
+  it = span.cend();
+  it -= 4;
+  EXPECT_EQ("0", *it);
+
+  // Add and subtract.
+  EXPECT_EQ(v.cbegin() + 2, v.cend() - 2);
+  EXPECT_EQ(2 + v.cbegin(), v.cend() - 2);
+
+  // Index.
+  it = span.cbegin();
+  EXPECT_EQ("3", v[3]);
+
+  // Relational operators.
+  EXPECT_TRUE(span.cbegin() != span.cend());
+  EXPECT_TRUE(span.cbegin() == span.cbegin());
+  EXPECT_TRUE(span.cbegin() < span.cend());
+  EXPECT_TRUE(span.cbegin() <= span.cend());
+  EXPECT_TRUE(span.cend() > span.cbegin());
+  EXPECT_TRUE(span.cend() >= span.cbegin());
+}
+
+TYPED_TEST(AnySpanTest, ReverseIterator) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  AnySpan<T> span(v);
+  auto v_it = v.rbegin();
+  for (auto it = span.rbegin(); it != span.rend(); ++it, ++v_it) {
+    EXPECT_EQ(*v_it, *it);
+  }
+}
+
+TYPED_TEST(AnySpanTest, IndexingAt) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  AnySpan<T> span(v);
+  EXPECT_EQ(&v.at(0), &v.at(0));
+  EXPECT_EQ(&v.at(1), &v.at(1));
+  EXPECT_EQ(&v.at(3), &v.at(3));
+}
+
+TYPED_TEST(AnySpanTest, AtThrows) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  AnySpan<T> span(v);
+  ABSL_BASE_INTERNAL_EXPECT_FAIL(span.at(4), std::out_of_range,
+                                 "failed bounds check");
+}
+
+TYPED_TEST(AnySpanTest, FrontBack) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  AnySpan<T> span(v);
+  EXPECT_EQ(&v.front(), &span.front());
+  EXPECT_EQ("a", span.front());
+  EXPECT_EQ(&v.back(), &span.back());
+  EXPECT_EQ("d", span.back());
+}
+
+// Returns a reference to a default constructed instance of the given type.
+template <typename Container>
+Container& DefaultInstance() {
+  static auto* c = new Container;
+  return *c;
+}
+
+// This test reaches into the implementation a bit, but it buys a lot of
+// confidence that the flat-array optimizations are working correctly.
+TYPED_TEST(AnySpanTest, CheapTypes) {
+  using T = typename TestFixture::template MaybeConst<int>;
+  using any_span_internal::IsCheap;
+  EXPECT_FALSE(IsCheap(AnySpan<T>(DefaultInstance<std::deque<int>>())));
+  EXPECT_FALSE(
+      IsCheap(AnySpan<T>(DefaultInstance<std::vector<std::unique_ptr<int>>>(),
+                         any_span_transform::Deref())));
+  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<std::vector<int>>())));
+  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<absl::Span<int>>())));
+  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<std::vector<int>>())));
+  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<std::vector<int*>>(),
+                                 any_span_transform::Deref())));
+  EXPECT_TRUE(IsCheap(AnySpan<T>(DefaultInstance<std::vector<int*>>(),
+                                 any_span_transform::Deref())));
+  struct SomeContainer {
+    int& operator[](std::size_t) { ABSL_RAW_LOG(FATAL, "Not implemented"); }
+    const int& operator[](std::size_t) const {
+      ABSL_RAW_LOG(FATAL, "Not implemented");
+    }
+    std::size_t size() const { return 1; }
+  };
+  EXPECT_FALSE(IsCheap(AnySpan<T>(DefaultInstance<SomeContainer>())));
+  struct SomeCheapMutableContainer {
+    int& operator[](std::size_t) const {
+      ABSL_RAW_LOG(FATAL, "Not implemented");
+    }
+    int* data() const { return nullptr; }
+    std::size_t size() const { return 1; }
+  };
+  EXPECT_TRUE(
+      IsCheap(AnySpan<T>(DefaultInstance<SomeCheapMutableContainer>())));
+
+  struct SomeWonkyContainer {
+    int& operator[](std::size_t) const {
+      ABSL_RAW_LOG(FATAL, "Not implemented");
+    }
+    const int** data() const { return nullptr; }
+    std::size_t size() const { return 1; }
+  };
+  EXPECT_FALSE(IsCheap(AnySpan<T>(DefaultInstance<SomeWonkyContainer>())));
+}
+
+TYPED_TEST(AnySpanTest, TriviallyCopyable) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  // Note: we could use is_trivially_copyable, but it is not implemented in
+  // Crosstool v18 which is the current version at the time of writing.
+  EXPECT_TRUE(std::is_trivially_copy_constructible<AnySpan<T>>::value);
+  EXPECT_TRUE(std::is_trivially_copy_assignable<AnySpan<T>>::value);
+  EXPECT_TRUE(std::is_trivially_destructible<AnySpan<T>>::value);
+}
+
+TYPED_TEST(AnySpanTest, IsConstructible) {
+  using T = typename TestFixture::template MaybeConst<std::string>;
+  using U = typename TestFixture::template MaybeConst<int>;
+  using VectorT =
+      typename TestFixture::template MaybeConst<std::vector<std::string>>;
+  using VectorU = typename TestFixture::template MaybeConst<std::vector<int>>;
+  EXPECT_FALSE((std::is_constructible<AnySpan<T>, T>::value));
+  EXPECT_FALSE((std::is_constructible<AnySpan<T>, T*>::value));
+  EXPECT_FALSE((std::is_constructible<AnySpan<T>, U>::value));
+  EXPECT_FALSE((std::is_constructible<AnySpan<T>, U(&)[5]>::value));
+  EXPECT_FALSE((std::is_constructible<AnySpan<T>, U*, std::size_t>::value));
+  EXPECT_FALSE((std::is_constructible<AnySpan<T>, VectorU&>::value));
+
+  EXPECT_TRUE((std::is_constructible<AnySpan<T>, VectorT&>::value));
+  EXPECT_TRUE((std::is_constructible<AnySpan<T>, T(&)[5]>::value));
+  EXPECT_TRUE((std::is_constructible<AnySpan<T>, T*, std::size_t>::value));
+}
+
+//
+// ConstAnySpanTest covers parts of AnySpan interface that are only valid for
+// AnySpans with const elements.
+//
+
+TEST(ConstAnySpanTest, ImplicitConversion) {
+  std::vector<int> v = {1, 2, 3};
+  ExpectSpanEqualsContainer<const int>(v, v);
+}
+
+TEST(ConstAnySpanTest, TemporaryArrayOfKnownSize) {
+  const int i = 5;
+  EXPECT_THAT(AnySpan<const int>({&i, &i, &i}, any_span_transform::Deref()),
+              testing::ElementsAre(5, 5, 5));
+}
+
+TEST(ConstAnySpanTest, CheapTypes) {
+  using any_span_internal::IsCheap;
+  EXPECT_TRUE(IsCheap(AnySpan<const int>(std::vector<const int*>(),
+                                         any_span_transform::Deref())));
+  EXPECT_TRUE(IsCheap(AnySpan<const int>(std::vector<const int*>(),
+                                         any_span_transform::Deref())));
+  EXPECT_TRUE(
+      IsCheap(AnySpan<const int>(DefaultInstance<absl::Span<const int>>())));
+  struct SomeCheapConstContainer {
+    const int& operator[](std::size_t) const {
+      ABSL_RAW_LOG(FATAL, "Not implemented");
+    }
+    const int* data() const { return nullptr; }
+    std::size_t size() const { return 1; }
+  };
+  EXPECT_TRUE(IsCheap(AnySpan<const int>(SomeCheapConstContainer())));
+}
+
+TEST(ConstAnySpanTest, InitializerListInt) {
+  auto test = [](AnySpan<const int> span) {
+    int expected = 1;
+    for (int i : span) {
+      EXPECT_EQ(expected++, i);
+    }
+    EXPECT_EQ(expected, 5);
+  };
+  test({1, 2, 3, 4});
+}
+
+TEST(ConstAnySpanTest, InitializerListString) {
+  auto test = [](AnySpan<const std::string> span) {
+    int expected = 1;
+    for (const std::string& i : span) {
+      EXPECT_EQ(absl::StrCat(expected++), i);
+    }
+    EXPECT_EQ(expected, 5);
+  };
+  test({"1", "2", "3", "4"});
+}
+
+TEST(ConstAnySpanTest, InitializerListDerivedToBase) {
+  // Derived to base, implicit conversion.
+  [](AnySpan<const Base2> bases) {
+    for (const Base2& b : bases) {
+      EXPECT_EQ(b.b2, 2);
+      // Make sure the value was not sliced.
+      EXPECT_EQ(typeid(b), typeid(Child));
+    }
+  }({Child{}, Child{}, Child{}});
+
+  // Derived to base with explicit transform.
+  Child children[3];
+  [](AnySpan<const Base2> bases) {
+    for (const Base2& b : bases) {
+      EXPECT_EQ(b.b2, 2);
+      // Make sure the value was not sliced.
+      EXPECT_EQ(typeid(b), typeid(Child));
+    }
+  }({{Child{}, Child{}, Child{}},
+     [](auto& obj) -> const Base2& { return obj; }});
+}
+
+TEST(ConstAnySpanTest,
+     InitializerListUsesValueTypeWhenConversionNeedsTemporaries) {
+  // If this were to call the initializer_list<Element> overload it would fail
+  // when it tries to make an lvalue transform from std::string to
+  // std::string_view.
+  // Instead, it must be calling the initializer_list<value_type> overload,
+  // doing the conversion on the call site.
+  [](AnySpan<const std::string_view> s) {
+    EXPECT_THAT(s, ElementsAre("A", "B", "C"));
+  }({"A", "B", "C"});
+}
+
+TEST(ConstAnySpanTest, MakeAnySpanFromVector) {
+  std::vector<int> v = {1, 2, 3, 4};
+  auto span = MakeConstAnySpan(v);
+  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<const int>>()));
+  EXPECT_EQ(span.size(), 4);
+  for (size_t i = 0; i < 4; ++i) {
+    EXPECT_EQ(&span[i], &v[i]);
+  }
+}
+
+TEST(ConstAnySpanTest, MakeAnySpanFromPtrAndSize) {
+  std::vector<int> v = {1, 2, 3, 4};
+  auto span = MakeConstAnySpan(v.data(), v.size());
+  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<const int>>()));
+  EXPECT_EQ(span.size(), 4);
+  for (size_t i = 0; i < 4; ++i) {
+    EXPECT_EQ(&span[i], &v[i]);
+  }
+}
+
+TEST(ConstAnySpanTest, MakeAnySpanFromArray) {
+  int a[] = {1, 2, 3, 4};
+  auto span = MakeConstAnySpan(a);
+  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<const int>>()));
+  EXPECT_EQ(span.size(), 4);
+  for (size_t i = 0; i < 4; ++i) {
+    EXPECT_EQ(&span[i], &a[i]);
+  }
+}
+
+TEST(ConstAnySpanTest, MakeDerefAnySpanFromArray) {
+  int v = 0;
+  int* a[] = {&v, &v, &v};
+  auto span = MakeConstDerefAnySpan(a);
+  EXPECT_TRUE((std::is_same<decltype(span), AnySpan<const int>>()));
+  EXPECT_EQ(span.size(), 3);
+  for (size_t i = 0; i < 3; ++i) {
+    EXPECT_EQ(&span[i], a[i]);
+  }
+}
+
+//
+// MutableAnySpanTest covers parts of AnySpan interface that are only valid for
+// AnySpans with mutable elements.
+//
+
+TEST(MutableAnySpanTest, MutableVectorString) {
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  AnySpan<std::string> span(v);
+  span[0] = "e";
+  EXPECT_EQ(v[0], "e");
+}
+
+TEST(MutableAnySpanTest, MutableToConstConversion) {
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  AnySpan<std::string> mutable_span(v);
+  AnySpan<const std::string> const_span(mutable_span);
+  EXPECT_TRUE(any_span_internal::IsCheap(const_span));
+  mutable_span[0] = "e";
+  EXPECT_EQ(const_span[0], "e");
+  mutable_span.subspan(1)[0] = "f";
+  EXPECT_EQ(const_span[1], "f");
+
+  std::vector<std::string> v2 = {"a"};
+  mutable_span = AnySpan<std::string>(v2);
+  EXPECT_EQ(const_span[0], "e");
+}
+
+TEST(MutableAnySpanTest, DerefMutableToConstConversion) {
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  std::vector<std::string*> v_ptrs;
+  for (std::string& s : v) {
+    v_ptrs.push_back(&s);
+  }
+  AnySpan<std::string> mutable_span(v_ptrs, any_span_transform::Deref());
+  AnySpan<const std::string> const_span(mutable_span);
+  EXPECT_TRUE(any_span_internal::IsCheap(const_span));
+  mutable_span[0] = "e";
+  EXPECT_EQ(const_span[0], "e");
+  EXPECT_EQ(v[0], "e");
+  mutable_span.subspan(1)[0] = "f";
+  EXPECT_EQ(const_span[1], "f");
+}
+
+TEST(MutableAnySpanTest, MutableToConstDeque) {
+  std::deque<std::string> d = {"a", "b", "c", "d"};
+  AnySpan<std::string> mutable_span(d);
+  AnySpan<const std::string> const_span(mutable_span);
+  EXPECT_FALSE(any_span_internal::IsCheap(const_span));
+  mutable_span[0] = "e";
+  EXPECT_EQ(const_span[0], "e");
+  mutable_span.subspan(1)[0] = "f";
+  EXPECT_EQ(const_span[1], "f");
+}
+
+TEST(MutableAnySpanTest, Deref) {
+  std::string s = "a";
+  AnySpan<std::string>({&s}, any_span_transform::Deref())[0] = "b";
+  EXPECT_EQ(s, "b");
+}
+
+// Checks that recommended usage works.
+TEST(MutableAnySpanTest, AsFunctionArgument) {
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  auto set_all_to_e = [](AnySpan<std::string> span) {
+    for (std::string& s : span) {
+      s = "e";
+    }
+  };
+  set_all_to_e(AnySpan<std::string>(v));
+  for (const std::string& e : v) {
+    EXPECT_EQ(e, "e");
+  }
+}
+
+TEST(MutableAnySpanTest, MutateThroughIterator) {
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  AnySpan<std::string> span(v);
+  AnySpan<std::string>::iterator it = span.begin();
+  it[2] = "e";
+  EXPECT_EQ(v[2], "e");
+  ++it;
+  *it = "f";
+  EXPECT_EQ(v[1], "f");
+  for (std::string& s : span) {
+    s = "g";
+  }
+  for (const std::string& e : v) {
+    EXPECT_EQ(e, "g");
+  }
+}
+
+TEST(MutableAnySpanTest, MutateThroughSubSpan) {
+  std::vector<int> v = {1, 2, 3, 4};
+  AnySpan<int> span(v);
+  span = span.subspan(1, 2);
+  for (int& i : span) {
+    i = 42;
+  }
+  EXPECT_THAT(v, ElementsAre(1, 42, 42, 4));
+}
+
+TYPED_TEST(AnySpanTest, SubspanToEnd) {
+  int arr[] = {0, 1, 2};
+  AnySpan<int> span(arr);
+  EXPECT_THAT(span.subspan(0, AnySpan<int>::npos), ElementsAre(0, 1, 2));
+  EXPECT_THAT(span.subspan(1, AnySpan<int>::npos), ElementsAre(1, 2));
+  EXPECT_THAT(span.subspan(2, AnySpan<int>::npos), ElementsAre(2));
+  EXPECT_THAT(span.subspan(3, AnySpan<int>::npos), ElementsAre());
+#if GTEST_HAS_DEATH_TEST
+  if (IsHardened()) {
+    EXPECT_DEATH(span.subspan(4, AnySpan<int>::npos), "");
+    EXPECT_DEATH(span.subspan(AnySpan<int>::npos, AnySpan<int>::npos), "");
+  }
+#endif
+}
+
+TEST(MutableAnySpanTest, NonTruncatingSubspan) {
+  std::vector<int> v = {1, 2, 3, 4};
+  AnySpan<int> span(v);
+#if GTEST_HAS_DEATH_TEST
+  if (IsHardened()) {
+    EXPECT_DEATH(span.subspan(5, 0), "");
+    EXPECT_DEATH(span.subspan(5, 1), "");
+    EXPECT_DEATH(span.subspan(AnySpan<int>::npos, 0), "");
+    EXPECT_DEATH(span.subspan(AnySpan<int>::npos, 1), "");
+      EXPECT_DEATH(span.subspan(0, 5), "");
+      EXPECT_DEATH(span.first(5), "");
+      EXPECT_DEATH(span.first(AnySpan<int>::npos), "");
+  }
+#endif
+}
+
+TEST(MutableAnySpanTest, IteratorToConstIteratorConversion) {
+  std::vector<int> v = {1};
+  AnySpan<int> span(v);
+  AnySpan<int>::iterator it = span.begin();
+  AnySpan<int>::const_iterator cit = it;
+  EXPECT_EQ(&*it, &*cit);
+}
+
+// Checks that implicit conversion from a mutable view works.
+TEST(MutableAnySpanTest, ImplicitConversionFromMutableSpan) {
+  std::vector<std::string> v = {"a", "b", "c", "d"};
+  absl::Span<std::string> mutable_slice(v);
+  auto set_all_to_e = [](AnySpan<std::string> span) {
+    for (std::string& s : span) {
+      s = "e";
+    }
+  };
+  set_all_to_e(mutable_slice);
+  for (const std::string& s : v) {
+    EXPECT_EQ(s, "e");
+  }
+}
+
+bool WantsStringOrAnySpan(absl::string_view /* ignored */) { return false; }
+bool WantsStringOrAnySpan(AnySpan<std::string> /* ignored */) { return true; }
+bool WantsStringOrConstAnySpan(absl::string_view /* ignored */) {
+  return false;
+}
+bool WantsStringOrConstAnySpan(AnySpan<const std::string> /* ignored */) {
+  return true;
+}
+// Checks that AnySpan(char (&array)[N]) is not used in the overload
+// resolution when building an AnySpan<string> (it would not compile anyway).
+TEST(MutableAnySpanTest, ResolveAmbiguityWithAnySpanOfChars) {
+  std::string foo;
+  AnySpan<std::string> bar;
+  EXPECT_FALSE(WantsStringOrAnySpan("abc"));
+  EXPECT_FALSE(WantsStringOrAnySpan(foo));
+  EXPECT_TRUE(WantsStringOrAnySpan(bar));
+  EXPECT_FALSE(WantsStringOrConstAnySpan("abc"));
+  EXPECT_FALSE(WantsStringOrConstAnySpan(foo));
+  EXPECT_TRUE(WantsStringOrConstAnySpan(bar));
+}
+
+TEST(AnySpanTest, SupportsAbslHash) {
+  std::vector<size_t> v = {1, 2, 3};
+  std::vector<std::string> vs = {"1", "2", "3"};
+  std::vector<std::unique_ptr<size_t>> vu;
+  vu.push_back(std::make_unique<size_t>(1));
+  vu.push_back(std::make_unique<size_t>(2));
+  vu.push_back(std::make_unique<size_t>(3));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      // {1, 2, 3}
+      AnySpan<const size_t>(v),
+      AnySpan<const size_t>(vu, any_span_transform::Deref()),
+      // {1, 2}
+      AnySpan<const size_t>(std::vector<size_t>({1, 2})),
+      AnySpan<const size_t>(std::deque<size_t>({1, 2})),
+      // {1, 2, 4}
+      AnySpan<const size_t>(std::vector<size_t>({1, 2, 4})),
+      AnySpan<const size_t>(std::deque<size_t>({1, 2, 4})),
+      // Empty.
+      AnySpan<const size_t>(),
+      AnySpan<const size_t>(std::vector<size_t>()),
+  }));
+}
+
+// This is necessary to avoid a bunch of lint warnings suggesting that we use
+// EXPECT_EQ/etc.
+bool Identity(bool b) { return b; }
+
+template <typename T, typename U, typename V>
+void TestEquality(T&& orig, U&& eq, V&& diff) {
+  EXPECT_TRUE(Identity(std::forward<T>(orig) == std::forward<U>(eq)));
+  EXPECT_TRUE(Identity(std::forward<U>(eq) == std::forward<T>(orig)));
+  EXPECT_FALSE(Identity(std::forward<T>(orig) != std::forward<U>(eq)));
+  EXPECT_FALSE(Identity(std::forward<U>(eq) != std::forward<T>(orig)));
+
+  EXPECT_FALSE(Identity(std::forward<T>(orig) == std::forward<V>(diff)));
+  EXPECT_FALSE(Identity(std::forward<V>(diff) == std::forward<T>(orig)));
+  EXPECT_TRUE(Identity(std::forward<T>(orig) != std::forward<V>(diff)));
+  EXPECT_TRUE(Identity(std::forward<V>(diff) != std::forward<T>(orig)));
+}
+
+TEST(AnySpanTest, Equals) {
+  int arr[] = {1, 2, 3};
+  std::vector<int> eq(std::begin(arr), std::end(arr));
+  int diff[] = {1, 2, 4};
+  TestEquality(AnySpan<int>(arr), AnySpan<int>(eq), AnySpan<int>(diff));
+  TestEquality(AnySpan<const int>(arr), AnySpan<int>(eq), AnySpan<int>(diff));
+  TestEquality(AnySpan<int>(arr), AnySpan<const int>(eq),
+               AnySpan<const int>(diff));
+  TestEquality(AnySpan<const int>(arr), AnySpan<const int>(eq),
+               AnySpan<const int>(diff));
+
+  TestEquality(AnySpan<const int>(arr), eq, diff);
+  TestEquality(AnySpan<int>(arr), eq, diff);
+}
+
+// If an object is copied, mark the bool pointed by `copied` true.
+class MarkIfCopied {
+ public:
+  explicit MarkIfCopied(bool* copied) : copied_(copied) {}
+
+  // NOLINT_NEXT_LINE(google-explicit-constructor)
+  MarkIfCopied(const MarkIfCopied& other) { *this = other; }
+
+  MarkIfCopied& operator=(const MarkIfCopied& other) {
+    copied_ = other.copied_;
+    *copied_ = true;
+    return *this;
+  }
+
+ private:
+  bool* copied_;
+};
+
+TEST(MarkIfCopied, EnsureWorks) {
+  bool copied = false;
+  MarkIfCopied item(&copied);
+  ASSERT_FALSE(copied);
+  MarkIfCopied _unused_copied_item(item);
+  EXPECT_TRUE(copied);
+}
+
+TEST(AnySpanTest, ReferenceWrapperNotCopied) {
+  bool copied1 = false;
+  bool copied2 = false;
+  MarkIfCopied item1(&copied1);
+  MarkIfCopied item2(&copied2);
+  std::vector<std::reference_wrapper<const MarkIfCopied>> items;
+  items.push_back(std::cref(item1));
+  items.push_back(std::cref(item2));
+  AnySpan<const MarkIfCopied> span(items);
+  EXPECT_EQ(2, span.size());
+  EXPECT_FALSE(copied1);
+  EXPECT_FALSE(copied2);
+}
+
+}  // namespace
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/types/compare.h b/absl/types/compare.h
index edf1039..abc8616 100644
--- a/absl/types/compare.h
+++ b/absl/types/compare.h
@@ -449,7 +449,7 @@
 // or three-way comparator.
 // SFINAE prevents implicit conversions to bool (such as from int).
 template <typename BoolT,
-          absl::enable_if_t<std::is_same<bool, BoolT>::value, int> = 0>
+          std::enable_if_t<std::is_same<bool, BoolT>::value, int> = 0>
 constexpr bool compare_result_as_less_than(const BoolT r) {
   return r;
 }
@@ -467,7 +467,7 @@
 // three-way comparator.
 // SFINAE prevents implicit conversions to int (such as from bool).
 template <typename Int,
-          absl::enable_if_t<std::is_same<int, Int>::value, int> = 0>
+          std::enable_if_t<std::is_same<int, Int>::value, int> = 0>
 constexpr absl::weak_ordering compare_result_as_ordering(const Int c) {
   return c < 0    ? absl::weak_ordering::less
          : c == 0 ? absl::weak_ordering::equivalent
@@ -479,7 +479,7 @@
 }
 
 template <typename Compare, typename K, typename LK,
-          absl::enable_if_t<
+          std::enable_if_t<
               !std::is_same<
                   bool, absl::result_of_t<Compare(const K&, const LK&)>>::value,
               int> = 0>
@@ -488,7 +488,7 @@
   return compare_result_as_ordering(compare(x, y));
 }
 template <typename Compare, typename K, typename LK,
-          absl::enable_if_t<
+          std::enable_if_t<
               std::is_same<
                   bool, absl::result_of_t<Compare(const K&, const LK&)>>::value,
               int> = 0>
diff --git a/absl/types/internal/any_span.h b/absl/types/internal/any_span.h
new file mode 100644
index 0000000..50843bf
--- /dev/null
+++ b/absl/types/internal/any_span.h
@@ -0,0 +1,477 @@
+// Copyright 2026 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: internal/any_span.h
+// -----------------------------------------------------------------------------
+//
+// Helper types and functions used by AnySpan. This file should only be
+// included by any_span.h.
+#ifndef ABSL_TYPES_INTERNAL_ANY_SPAN_H_
+#define ABSL_TYPES_INTERNAL_ANY_SPAN_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <functional>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/optimization.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+template <typename T>
+class AnySpan;
+
+namespace any_span_transform {
+struct IdentityT;
+struct DerefT;
+}  // namespace any_span_transform
+
+namespace any_span_internal {
+
+//
+// IsAnySpan inherits from true_type if T is an instance of AnySpan.
+//
+
+template <typename T>
+struct IsAnySpan : public std::false_type {};
+
+template <typename T>
+struct IsAnySpan<AnySpan<T>> : public std::true_type {};
+
+// A type suitable for storing any function pointer. The standard allows
+// function pointers to round-trip through other function pointers, but void* is
+// implementation defined.
+using FunPtr = void (*)();
+
+// Whether a transform will be copied and therefore does not have to outlive
+// the AnySpan.
+template <typename Transform>
+constexpr bool kIsTransformCopied =
+    std::is_function_v<std::remove_pointer_t<Transform>>;
+
+// Type to pass as extra argument to TransformPtr to ensure that our
+// assumption about Transform copyability is valid.
+template <typename Transform>
+using IsTransformCopied =
+    std::integral_constant<bool, kIsTransformCopied<Transform>>;
+
+// A pointer to the transform function or functor that should be applied to
+// elements of the container.
+class TransformPtr {
+ public:
+  TransformPtr() = default;
+
+  // Construct from ptr to function.
+  template <typename R, typename... Args, typename CopiedTransform>
+  explicit TransformPtr(R (*f)(Args...),
+                        CopiedTransform copied_transform [[maybe_unused]])
+      : fun_ptr_(reinterpret_cast<FunPtr>(f)) {
+    static_assert(CopiedTransform::value);
+  }
+
+  // Construct from any other invokable object.
+  template <typename T, typename CopiedTransform>
+  explicit TransformPtr(const T& t,
+                        CopiedTransform copied_transform [[maybe_unused]])
+      : ptr_(&t) {
+    static_assert(!CopiedTransform::value);
+  }
+
+  // Casts the pointer to the given type.
+  template <typename Transform>
+  auto get() const {
+    if constexpr (std::is_function_v<Transform>) {
+      return reinterpret_cast<const Transform*>(fun_ptr_);
+    } else if constexpr (std::is_function_v<std::remove_pointer_t<Transform>>) {
+      return reinterpret_cast<const Transform>(fun_ptr_);
+    } else {
+      return static_cast<const Transform*>(ptr_);
+    }
+  }
+
+ private:
+  union {
+    const void* ptr_ = nullptr;
+    FunPtr fun_ptr_;
+  };
+};
+
+// A void* pointer to the container and transform functor. These are always cast
+// to the correct type since we create this object and the GetterFunction at the
+// same time (from one of the Make*Getter functions below).
+struct TransformedContainer {
+  // The container or array.
+  void* ptr;
+
+  // The transform being applied to the container.
+  TransformPtr transform;
+};
+
+// Applies transform (at the correct type) to the argument and returns the
+// result. Does some validity checking to make sure the result is not a
+// temporary (proxy containers are not allowed).
+template <typename T, typename Transform, typename U>
+T& ApplyTransform(TransformPtr transform, U& u) {  // NOLINT(runtime/references)
+  const auto t = transform.get<Transform>();
+  ABSL_RAW_DCHECK(t != nullptr, "pointer cannot be null");
+
+  // If compilation fails here due to dropping a const qualifier, it usually
+  // means you tried to wrap a const container with a non-const AnySpan.
+  //
+  // If compilation fails here due to a reference to a temporary, it usually
+  // means that the container or transform cannot be converted to a reference to
+  // T. AnySpan requires that a valid instance of T exists, conversion to a
+  // value type (such as string -> StringPiece or int -> float) is not
+  // supported.
+  //
+  // If compilation fails here due to taking the address of a temporary object,
+  // it means that the transform is returning a temporary. This is disallowed.
+  // Transforms must return a reference to T, or a reference to an object that
+  // can be safely converted to a reference to T (such as a reference_wrapper or
+  // a class that inherits from T).
+  return *&std::invoke(*t, u);  // Failed compilation? See above.
+}
+
+// The return type of GetterFunction<T>. GetterFunctions return non-const
+// references to support mutable -> const conversion of spans without additional
+// indirection.
+template <typename T>
+using GetterFunctionResult = std::remove_const_t<T>&;
+
+// A type of function pointer that can return an element of a
+// TransformedContainer.  This is used so that we can type-erase with a simple
+// function pointer instead of a vtable. Doing things this way has less pointer
+// indirection.
+template <typename T>
+using GetterFunction = GetterFunctionResult<T> (*)(const TransformedContainer&,
+                                                   std::size_t);
+
+// A GetterFunction that works on arrays.
+template <typename T, typename Element, typename Transform>
+GetterFunctionResult<T> GetFromArray(const TransformedContainer& container,
+                                     std::size_t i) {
+  ABSL_RAW_DCHECK(container.ptr != nullptr, "cannot dereference null pointer");
+  auto* array = static_cast<Element*>(container.ptr);
+  return const_cast<GetterFunctionResult<T>>(
+      ApplyTransform<T, Transform>(container.transform, array[i]));
+}
+
+// A GetterFunction that works on containers.
+template <typename T, typename Container, typename Transform>
+GetterFunctionResult<T> GetFromContainer(const TransformedContainer& container,
+                                         std::size_t i) {
+  ABSL_RAW_DCHECK(container.ptr != nullptr, "cannot dereference null pointer");
+  Container& c = *static_cast<Container*>(container.ptr);
+  return const_cast<GetterFunctionResult<T>>(
+      ApplyTransform<T, Transform>(container.transform, c[i]));
+}
+
+// A GetterFunction that crashes, indicating an invalid AnySpan has been
+// accessed..
+template <typename T>
+GetterFunctionResult<T> GetFromUninitialized(const TransformedContainer&,
+                                             std::size_t) {
+  ABSL_RAW_LOG(FATAL, "Uninitialized AnySpan access.");
+}
+
+//
+// ArrayTag and PtrArrayTag are GetterFunctions that are never called. They are
+// used as a tag so Getter::Get can access flat arrays without a function
+// pointer.
+//
+
+template <typename T>
+GetterFunctionResult<T> ArrayTag(const TransformedContainer&, std::size_t) {
+  ABSL_RAW_LOG(FATAL, "ArrayTag should never be called.");
+}
+
+template <typename T>
+GetterFunctionResult<T> PtrArrayTag(const TransformedContainer&, std::size_t) {
+  ABSL_RAW_LOG(FATAL, "PtrArrayTag should never be called.");
+}
+
+//
+// HasSize<Container> inherets from true_type if Container has a size() member.
+// false_type otherwise.
+//
+
+template <typename, typename = void>
+struct HasSize : public std::false_type {};
+
+template <class Container>
+struct HasSize<Container,
+               absl::void_t<decltype(std::declval<Container&>().size())>>
+    : public std::true_type {};
+
+//
+// TypeOfData<Container>::type is the return type of data() if Container has a
+// data() member. It is NoData otherwise.
+//
+
+struct NoData {};
+
+template <typename, typename = void>
+struct TypeOfData {
+  using type = NoData;
+};
+
+template <class Container>
+struct TypeOfData<Container,
+                  absl::void_t<decltype(std::declval<Container&>().data())>> {
+  using type = decltype(std::declval<Container&>().data());
+};
+
+// Element type of container based on operator[].
+template <class Container>
+using ElementType = typename std::remove_reference<
+    decltype(std::declval<Container&>()[0])>::type;
+
+// Element type of container when elements are dereferenced.
+template <class Container>
+using DerefElementType = typename std::remove_reference<
+    decltype(*std::declval<ElementType<Container>>())>::type;
+
+// DataIsValid is true_type if Container has a data() member that returns a
+// pointer to the type returned by operator[], false_type if there is no data()
+// member or if the types disagree.
+template <class Container>
+using DataIsValid =
+    std::is_same<ElementType<Container>*, typename TypeOfData<Container>::type>;
+
+// Used to access elements of a container or array.
+template <typename T>
+struct Getter {
+  Getter() {}
+
+  // Handle mutable -> const conversion.
+  template <typename LazyT = T, typename = typename std::enable_if<
+                                    std::is_const<LazyT>::value>::type>
+  explicit Getter(const Getter<std::remove_const_t<T>>& other) {
+    using MutableT = std::remove_const_t<T>;
+    if (other.fun == &ArrayTag<MutableT>) {
+      ABSL_RAW_DCHECK(other.offset == 0u, "offset must be zero");
+      fun = &ArrayTag<T>;
+      array = other.array;
+      offset = 0;
+    } else if (other.fun == &PtrArrayTag<MutableT>) {
+      ABSL_RAW_DCHECK(other.offset == 0u, "offset must be zero");
+      fun = &PtrArrayTag<T>;
+      ptr_array = other.ptr_array;
+      offset = 0;
+    } else {
+      fun = other.fun;
+      container = other.container;
+      offset = other.offset;
+    }
+  }
+
+  // Returns the element at the given index.
+  T& Get(std::size_t index) const {
+    ABSL_RAW_DCHECK(fun != nullptr, "pointer cannot be null");
+    if (ABSL_PREDICT_TRUE(fun == &ArrayTag<T>)) {
+      ABSL_RAW_DCHECK(array != nullptr, "pointer cannot be null");
+      return array[index];
+    }
+    if (fun == &PtrArrayTag<T>) {
+      ABSL_RAW_DCHECK(ptr_array != nullptr, "pointer cannot be null");
+      return *ptr_array[index];
+    }
+    return fun(container, index + offset);
+  }
+
+  // Returns a Getter offset into this one by pos.
+  Getter Offset(std::size_t pos) const {
+    // Special case when offset is zero. This safely handles empty spans and
+    // empty containers where data() can be null.
+    if (pos == 0) {
+      return *this;
+    }
+    ABSL_RAW_DCHECK(fun != nullptr, "pointer cannot be null");
+    Getter result;
+    result.fun = fun;
+    if (fun == &ArrayTag<T>) {
+      ABSL_RAW_DCHECK(array != nullptr, "pointer cannot be null");
+      ABSL_RAW_DCHECK(offset == 0u, "offset must be zero");
+      result.array = array + pos;
+      result.offset = 0;
+    } else if (fun == &PtrArrayTag<T>) {
+      ABSL_RAW_DCHECK(ptr_array != nullptr, "pointer cannot be null");
+      ABSL_RAW_DCHECK(offset == 0u, "offset must be zero");
+      result.ptr_array = ptr_array + pos;
+      result.offset = 0;
+    } else {
+      ABSL_RAW_DCHECK(container.ptr != nullptr, "pointer cannot be null");
+      result.container = container;
+      result.offset = offset + pos;
+    }
+    return result;
+  }
+
+  // A pointer to a function (or tag function) that specifies how to get an
+  // element from the array or container.
+  GetterFunction<T> fun = &GetFromUninitialized<T>;
+
+  union {
+    T* array;                        // Active if fun == ArrayTag<T>.
+    T* const* ptr_array;             // Active if fun == PtrArrayTag<T>.
+    TransformedContainer container;  // Active for all other fun.
+  };
+
+  // Offset into container. Always 0 for array or ptr_array.
+  std::size_t offset = 0;
+};
+
+//
+// MakeArrayGetter returns a Getter for an array.
+//
+// MakeArrayGetterImpl is specialised to use ArrayTag<T> when Element == T and
+// Transform == IdentityT, and to use PtrArrayTag<T> when Element == T* and
+// Transform == DerefT.
+//
+
+template <typename SpanElement, typename ArrayElement, typename Transform>
+struct MakeArrayGetterImpl {
+  template <typename U>
+  static Getter<U> Make(ArrayElement* array, const Transform& transform) {
+    Getter<U> result;
+    result.fun = &GetFromArray<U, ArrayElement, Transform>;
+    result.container.ptr = const_cast<void*>(static_cast<const void*>(array));
+    result.container.transform =
+        TransformPtr(transform, IsTransformCopied<Transform>{});
+    return result;
+  }
+};
+
+// When the span and the array are the same type.
+template <typename T>
+struct MakeArrayGetterImpl<T, T, any_span_transform::IdentityT> {
+  template <typename U>
+  static Getter<U> Make(T* array, const any_span_transform::IdentityT&) {
+    Getter<U> result;
+    result.fun = &ArrayTag<U>;
+    result.array = array;
+    return result;
+  }
+};
+
+// If we are dereferencing an array of mutable elements (T*), it is safe to add
+// constness (const T*).
+template <typename T>
+struct MakeArrayGetterImpl<const T, T, any_span_transform::IdentityT>
+    : public MakeArrayGetterImpl<const T, const T,
+                                 any_span_transform::IdentityT> {};
+
+// When the array is of pointers to elements of the same type as the span.
+template <typename T>
+struct MakeArrayGetterImpl<T, T*, any_span_transform::DerefT> {
+  template <typename U>
+  static Getter<U> Make(T* const* ptr_array,
+                        const any_span_transform::DerefT&) {
+    Getter<U> result;
+    result.fun = &PtrArrayTag<U>;
+    result.ptr_array = ptr_array;
+    return result;
+  }
+};
+
+// If we are dereferencing an array that is mutable along any extent, it is safe
+// to add constness.
+template <typename T>
+struct MakeArrayGetterImpl<const T, T*, any_span_transform::DerefT>
+    : public MakeArrayGetterImpl<const T, const T*,
+                                 any_span_transform::DerefT> {};
+
+template <typename T>
+struct MakeArrayGetterImpl<const T, T* const, any_span_transform::DerefT>
+    : public MakeArrayGetterImpl<const T, const T*,
+                                 any_span_transform::DerefT> {};
+
+template <typename T>
+struct MakeArrayGetterImpl<const T, const T* const, any_span_transform::DerefT>
+    : public MakeArrayGetterImpl<const T, const T*,
+                                 any_span_transform::DerefT> {};
+
+template <typename T, typename Element, typename Transform>
+Getter<T> MakeArrayGetter(Element* array, const Transform& transform) {
+  return MakeArrayGetterImpl<T, Element, Transform>::template Make<T>(
+      array, transform);
+}
+
+//
+// MakeContainerGetter returns a Getter for a given container. It will pass
+// container.data() to MakeArrayGetter if possible, which allows element access
+// to be inline.
+//
+// The first argument to MakeArrayGetterImpl is expected to be of type
+// DataIsValid<container>.
+//
+
+template <typename T, typename Container, typename Transform>
+Getter<T> MakeContainerGetterImpl(
+    std::true_type /* DataIsValid<Container> */,
+    Container& container,  // NOLINT(runtime/references)
+    const Transform& transform) {
+  return MakeArrayGetter<T, ElementType<Container>, Transform>(container.data(),
+                                                               transform);
+}
+
+template <typename T, typename Container, typename Transform>
+Getter<T> MakeContainerGetterImpl(
+    std::false_type /* DataIsValid<Container> */,
+    Container& container,  // NOLINT(runtime/references)
+    const Transform& transform) {
+  Getter<T> result;
+  result.fun = &GetFromContainer<T, Container, Transform>;
+  result.container.ptr =
+      const_cast<void*>(static_cast<const void*>(&container));
+  result.container.transform =
+      TransformPtr(transform, IsTransformCopied<Transform>{});
+
+  return result;
+}
+
+template <typename T, typename Container, typename Transform>
+Getter<T> MakeContainerGetter(
+    Container& container,  // NOLINT(runtime/references)
+    const Transform& transform) {
+  static_assert(std::is_reference<decltype(container[0])>::value,
+                "AnySpan only works with containers that return a reference "
+                "(no vector<bool>, or containers that return by value).");
+  return MakeContainerGetterImpl<T>(DataIsValid<Container>(), container,
+                                    transform);
+}
+
+// Used for testing. Returns true if the given AnySpan performs inline element
+// access.
+template <typename T>
+bool IsCheap(AnySpan<T> s) {
+  return s.getter_.fun == &ArrayTag<T> || s.getter_.fun == &PtrArrayTag<T>;
+}
+
+template <typename T>
+bool EqualImpl(AnySpan<T> a, AnySpan<T> b) {
+  static_assert(std::is_const<T>::value, "");
+  return std::equal(a.begin(), a.end(), b.begin(), b.end());
+}
+
+}  // namespace any_span_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_TYPES_INTERNAL_ANY_SPAN_H_
diff --git a/absl/types/internal/span.h b/absl/types/internal/span.h
index 9e8e418..8448cd7 100644
--- a/absl/types/internal/span.h
+++ b/absl/types/internal/span.h
@@ -54,7 +54,7 @@
 // Detection idioms for size() and data().
 template <typename C>
 using HasSize =
-    std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>;
+    std::is_integral<std::decay_t<decltype(std::declval<C&>().size())>>;
 
 // We want to enable conversion from vector<T*> to Span<const T* const> but
 // disable conversion from vector<Derived> to Span<Base>. Here we use
@@ -64,13 +64,13 @@
 // which returns a reference.
 template <typename T, typename C>
 using HasData =
-    std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*,
+    std::is_convertible<std::decay_t<decltype(GetData(std::declval<C&>()))>*,
                         T* const*>;
 
 // Extracts value type from a Container
 template <typename C>
 struct ElementType {
-  using type = typename absl::remove_reference_t<C>::value_type;
+  using type = typename std::remove_reference_t<C>::value_type;
 };
 
 template <typename T, size_t N>
diff --git a/absl/types/source_location.cc b/absl/types/source_location.cc
new file mode 100644
index 0000000..47028a5
--- /dev/null
+++ b/absl/types/source_location.cc
@@ -0,0 +1,18 @@
+// Copyright 2026 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/types/source_location.h"
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
diff --git a/absl/types/span.h b/absl/types/span.h
index b9f6b74..8c5736c 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -204,7 +204,7 @@
 
  public:
   using element_type = T;
-  using value_type = absl::remove_cv_t<T>;
+  using value_type = std::remove_cv_t<T>;
   // TODO(b/316099902) - pointer should be absl_nullable, but this makes it hard
   // to recognize foreach loops as safe. absl_nullability_unknown is currently
   // used to suppress -Wnullability-completeness warnings.