diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index cdb0af1..f00d5d0 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -86,6 +86,7 @@
         "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:hardening",
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/random",
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt
index cd7fa22..eb20132 100644
--- a/absl/algorithm/CMakeLists.txt
+++ b/absl/algorithm/CMakeLists.txt
@@ -37,6 +37,7 @@
   DEPS
     absl::algorithm
     absl::config
+    absl::hardening
     GTest::gmock_main
 )
 
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 6928623..a6b60cb 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -126,14 +126,14 @@
   using OutputIter = ContainerIter<OutputRange>;
 
   if constexpr (base_internal::IsAtLeastForwardIterator<InputIter>::value) {
-    base_internal::HardeningAssert(
-        n <= std::distance(container_algorithm_internal::c_begin(input),
-                           container_algorithm_internal::c_end(input)));
+    base_internal::HardeningAssertLE(
+        n, std::distance(container_algorithm_internal::c_begin(input),
+                         container_algorithm_internal::c_end(input)));
   }
   if constexpr (base_internal::IsAtLeastForwardIterator<OutputIter>::value) {
-    base_internal::HardeningAssert(
-        n <= std::distance(container_algorithm_internal::c_begin(output),
-                           container_algorithm_internal::c_end(output)));
+    base_internal::HardeningAssertLE(
+        n, std::distance(container_algorithm_internal::c_begin(output),
+                         container_algorithm_internal::c_end(output)));
   }
 }
 
@@ -143,9 +143,9 @@
   using OutputIter = ContainerIter<OutputRange>;
   if constexpr (base_internal::IsAtLeastForwardIterator<InputIter>::value &&
                 base_internal::IsAtLeastForwardIterator<OutputIter>::value) {
-    base_internal::HardeningAssert(
+    base_internal::HardeningAssertLE(
         std::distance(container_algorithm_internal::c_begin(input),
-                      container_algorithm_internal::c_end(input)) <=
+                      container_algorithm_internal::c_end(input)),
         std::distance(container_algorithm_internal::c_begin(output),
                       container_algorithm_internal::c_end(output)));
   }
@@ -192,16 +192,6 @@
                              std::remove_reference_t<C>>::value,
                      std::decay_t<OutputIterator>>;
 
-template <typename C, typename OutputRange>
-using ResultOfRangeToRangeTransfer =
-    std::enable_if_t<container_algorithm_internal::HasBeginEnd<
-                         std::add_lvalue_reference_t<OutputRange>>::value &&
-                         !container_algorithm_internal::IsMultidimensionalArray<
-                             std::remove_reference_t<OutputRange>>::value &&
-                         !container_algorithm_internal::IsMultidimensionalArray<
-                             std::remove_reference_t<C>>::value,
-                     void>;
-
 // Similar to std::is_pointer, but for testing if a type is a span.
 //
 // Note that subclasses of spans do not automatically qualify as spans, as they
@@ -231,6 +221,18 @@
     std::conditional_t<std::is_lvalue_reference<C>::value, std::true_type,
                        IsSpan<C>>;
 
+template <typename C, typename OutputRange>
+using ResultOfRangeToRangeTransfer =
+    std::enable_if_t<container_algorithm_internal::HasBeginEnd<
+                         std::add_lvalue_reference_t<OutputRange>>::value &&
+                         !container_algorithm_internal::IsMultidimensionalArray<
+                             std::remove_reference_t<OutputRange>>::value &&
+                         !container_algorithm_internal::IsMultidimensionalArray<
+                             std::remove_reference_t<C>>::value &&
+                         container_algorithm_internal::
+                             IsPermissibleDestinationRange<OutputRange>::value,
+                     void>;
+
 }  // namespace container_algorithm_internal
 
 // PUBLIC API
@@ -632,8 +634,7 @@
     InputSequence, OutputRange>
 c_copy(const InputSequence& input, OutputRange&& output) {
   container_algorithm_internal::AssertCopySize(input, output);
-  absl::c_copy(input, container_algorithm_internal::c_begin(
-                          std::forward<OutputRange>(output)));
+  absl::c_copy(input, container_algorithm_internal::c_begin(output));
 }
 
 // c_copy_n()
@@ -664,9 +665,7 @@
     C, OutputRange>
 c_copy_n(const C& input, Size n, OutputRange&& output) {
   container_algorithm_internal::AssertCopyNSize(input, n, output);
-  absl::c_copy_n(
-      input, n,
-      container_algorithm_internal::c_begin(std::forward<OutputRange>(output)));
+  absl::c_copy_n(input, n, container_algorithm_internal::c_begin(output));
 }
 
 // c_copy_if()
@@ -715,8 +714,8 @@
     C, OutputRange>
 c_move(C&& src, OutputRange&& dest) {
   container_algorithm_internal::AssertCopySize(src, dest);
-  absl::c_move(std::forward<C>(src), container_algorithm_internal::c_begin(
-                                         std::forward<OutputRange>(dest)));
+  absl::c_move(std::forward<C>(src),
+               container_algorithm_internal::c_begin(dest));
 }
 
 // c_move_backward()
@@ -757,33 +756,109 @@
 // result in an iterator pointing to the last transformed element in the output
 // range.
 template <typename InputSequence, typename OutputIterator, typename UnaryOp>
-constexpr OutputIterator c_transform(const InputSequence& input,
-                                     OutputIterator output,
-                                     UnaryOp&& unary_op) {
+constexpr container_algorithm_internal::ResultOfRangeToIteratorTransfer<
+    InputSequence, OutputIterator>
+c_transform(const InputSequence& input, OutputIterator&& output,
+            UnaryOp&& unary_op) {
   return std::transform(container_algorithm_internal::c_begin(input),
-                        container_algorithm_internal::c_end(input), output,
+                        container_algorithm_internal::c_end(input),
+                        std::forward<OutputIterator>(output),
                         std::forward<UnaryOp>(unary_op));
 }
 
+// Performs a transformation using a unary predicate. Stores the result in
+// `output`. `absl::c_transform(input, output, unary_op)` is equivalent to
+// `std::transform(std::begin(input), std::end(input), std::begin(output),
+// unary_op)`.
+//
+// The `output` container must be large enough to hold all elements of `input`;
+// this function does not resize `output`.
+template <typename InputSequence, typename OutputRange, typename UnaryOp>
+constexpr container_algorithm_internal::ResultOfRangeToRangeTransfer<
+    InputSequence, OutputRange>
+c_transform(const InputSequence& input, OutputRange&& output,
+            UnaryOp&& unary_op) {
+  container_algorithm_internal::AssertCopySize(input, output);
+  absl::c_transform(
+      input,
+      container_algorithm_internal::c_begin(std::forward<OutputRange>(output)),
+      std::forward<UnaryOp>(unary_op));
+}
+
 // Overload of c_transform() for performing a transformation using a binary
 // predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,
 // where N = min(size(c1), size(c2)).
 template <typename InputSequence1, typename InputSequence2,
           typename OutputIterator, typename BinaryOp>
-constexpr OutputIterator c_transform(const InputSequence1& input1,
-                                     const InputSequence2& input2,
-                                     OutputIterator output,
-                                     BinaryOp&& binary_op) {
+constexpr container_algorithm_internal::ResultOfRangeToIteratorTransfer<
+    InputSequence1, OutputIterator>
+c_transform(const InputSequence1& input1, const InputSequence2& input2,
+            OutputIterator&& output, BinaryOp&& binary_op) {
   auto first1 = container_algorithm_internal::c_begin(input1);
   auto last1 = container_algorithm_internal::c_end(input1);
   auto first2 = container_algorithm_internal::c_begin(input2);
   auto last2 = container_algorithm_internal::c_end(input2);
-  for (; first1 != last1 && first2 != last2;
-       ++first1, (void)++first2, ++output) {
-    *output = binary_op(*first1, *first2);
+  std::decay_t<OutputIterator> out = std::forward<OutputIterator>(output);
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2, ++out) {
+    *out = binary_op(*first1, *first2);
   }
+  return out;
+}
 
-  return output;
+// Performs a transformation using a binary predicate. Stores the result in
+// `output`. Applies `binary_op` to the first N elements of `input1` and
+// `input2`, where N = min(size(input1), size(input2)).
+//
+// The `output` container must be large enough to hold all N elements;
+// this function does not resize `output`.
+template <typename InputSequence1, typename InputSequence2,
+          typename OutputRange, typename BinaryOp>
+constexpr std::common_type_t<
+    container_algorithm_internal::ResultOfRangeToRangeTransfer<InputSequence1,
+                                                               OutputRange>,
+    container_algorithm_internal::ResultOfRangeToRangeTransfer<InputSequence2,
+                                                               OutputRange>>
+c_transform(const InputSequence1& input1, const InputSequence2& input2,
+            OutputRange&& output, BinaryOp&& binary_op) {
+  using InputIter1 =
+      container_algorithm_internal::ContainerIter<InputSequence1>;
+  using InputIter2 =
+      container_algorithm_internal::ContainerIter<InputSequence2>;
+  using OutputIter = container_algorithm_internal::ContainerIter<OutputRange>;
+  if constexpr (base_internal::IsAtLeastForwardIterator<OutputIter>::value) {
+    constexpr bool input1_has_size =
+        base_internal::IsAtLeastForwardIterator<InputIter1>::value;
+    constexpr bool input2_has_size =
+        base_internal::IsAtLeastForwardIterator<InputIter2>::value;
+    auto output_size =
+        std::distance(container_algorithm_internal::c_begin(output),
+                      container_algorithm_internal::c_end(output));
+
+    if constexpr (input1_has_size && input2_has_size) {
+      base_internal::HardeningAssertLE(
+          (std::min)(std::distance(
+                         container_algorithm_internal::c_begin(input1),
+                         container_algorithm_internal::c_end(input1)),
+                     std::distance(
+                         container_algorithm_internal::c_begin(input2),
+                         container_algorithm_internal::c_end(input2))),
+          output_size);
+    } else if constexpr (input1_has_size) {
+      base_internal::HardeningAssertLE(
+          std::distance(container_algorithm_internal::c_begin(input1),
+                        container_algorithm_internal::c_end(input1)),
+          output_size);
+    } else if constexpr (input2_has_size) {
+      base_internal::HardeningAssertLE(
+          std::distance(container_algorithm_internal::c_begin(input2),
+                        container_algorithm_internal::c_end(input2)),
+          output_size);
+    }
+  }
+  absl::c_transform(
+      input1, input2,
+      container_algorithm_internal::c_begin(std::forward<OutputRange>(output)),
+      std::forward<BinaryOp>(binary_op));
 }
 
 // c_replace()
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 6249e20..2d2fec1 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -36,6 +36,7 @@
 #include "gtest/gtest.h"
 #include "absl/base/casts.h"
 #include "absl/base/config.h"
+#include "absl/base/internal/hardening.h"
 #include "absl/base/macros.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
@@ -762,6 +763,13 @@
   EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5));
 }
 
+TEST(MutatingTest, CopyToSpanRvalue) {
+  const std::vector<int> input = {1, 2, 3};
+  std::vector<int> actual = {0, 0, 0, 4, 5};
+  absl::c_copy(input, absl::MakeSpan(actual));
+  EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5));
+}
+
 TEST(MutatingTest, CopyNToContainer) {
   const std::vector<int> input = {1, 2, 3, 4, 5};
   std::vector<int> actual = {0, 0, 0, 0, 0};
@@ -769,6 +777,13 @@
   EXPECT_THAT(actual, ElementsAre(1, 2, 0, 0, 0));
 }
 
+TEST(MutatingTest, CopyNToSpanRvalue) {
+  const std::vector<int> input = {1, 2, 3, 4, 5};
+  std::vector<int> actual = {0, 0, 0, 0, 0};
+  absl::c_copy_n(input, 2, absl::MakeSpan(actual));
+  EXPECT_THAT(actual, ElementsAre(1, 2, 0, 0, 0));
+}
+
 TEST(MutatingTest, CopyNToContainerWithZeroN) {
   const std::vector<int> input = {1, 2, 3, 4, 5};
   std::vector<int> actual = {0, 0, 0, 0, 0};
@@ -843,7 +858,6 @@
   EXPECT_THAT(actual, ElementsAre(1, 2, 0, 0, 0));
 }
 
-#if GTEST_HAS_DEATH_TEST
 
 bool IsHardened() {
   bool hardened = false;
@@ -857,77 +871,105 @@
 TEST(MutatingTest, CopyToCArrayInvalidSize) {
   const std::vector<int> input = {1, 2, 3};
   int actual[2] = {0, 0};
+  (void)actual;
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_copy(input, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, CopyNToCArrayInvalidSize) {
   const std::vector<int> input = {1, 2, 3};
   int actual[2] = {0, 0};
+  (void)actual;
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_copy_n(input, 3, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, CopyNToCArrayNGreaterThanInput) {
   const std::vector<int> input = {1, 2, 3};
   int actual[4] = {0, 0, 0, 0};
+  (void)actual;
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_copy_n(input, 4, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, CopyToContainerInvalidSize) {
   const std::list<int> input = {1, 2, 3, 4, 5};
   std::list<int> actual = {0, 0, 0};
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_copy(input, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, CopyNToContainerNGreaterThanInput) {
   const std::vector<int> input = {1, 2, 3};
   std::vector<int> actual = {0, 0, 0, 0};
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_copy_n(input, 4, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, CopyNToContainerNGreaterThanOutput) {
   const std::vector<int> input = {1, 2, 3};
   std::vector<int> actual = {0, 0};
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_copy_n(input, 3, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, CopyToForwardListInvalidSize) {
   const std::forward_list<int> input = {1, 2, 3, 4, 5};
   std::forward_list<int> actual = {0, 0, 0};
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_copy(input, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, CopyNToForwardListNGreaterThanInput) {
   const std::forward_list<int> input = {1, 2, 3};
   std::forward_list<int> actual = {0, 0, 0, 0};
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_copy_n(input, 4, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, CopyNToForwardListNGreaterThanOutput) {
   const std::forward_list<int> input = {1, 2, 3};
   std::forward_list<int> actual = {0, 0};
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_copy_n(input, 3, actual), "");
   }
+#endif
 }
 
-#endif  // GTEST_HAS_DEATH_TEST
-
 TEST(MutatingTest, CopyIf) {
   const std::list<int> input = {1, 2, 3};
   std::vector<int> output;
@@ -1008,6 +1050,28 @@
   EXPECT_EQ(actual[3], nullptr);
 }
 
+TEST(MutatingTest, MoveToSpanRvalue) {
+  std::vector<std::unique_ptr<int>> input;
+  input.push_back(std::make_unique<int>(1));
+  input.push_back(std::make_unique<int>(2));
+  input.push_back(std::make_unique<int>(3));
+
+  std::vector<std::unique_ptr<int>> actual(5);
+  absl::c_move(input, absl::MakeSpan(actual));
+
+  EXPECT_EQ(input[0], nullptr);
+  EXPECT_EQ(input[1], nullptr);
+  EXPECT_EQ(input[2], nullptr);
+
+  ASSERT_NE(actual[0], nullptr);
+  EXPECT_EQ(*actual[0], 1);
+  ASSERT_NE(actual[1], nullptr);
+  EXPECT_EQ(*actual[1], 2);
+  ASSERT_NE(actual[2], nullptr);
+  EXPECT_EQ(*actual[2], 3);
+  EXPECT_EQ(actual[3], nullptr);
+}
+
 TEST(MutatingTest, MoveToDifferentContainerType) {
   std::list<std::unique_ptr<int>> input;
   input.push_back(std::make_unique<int>(1));
@@ -1047,34 +1111,41 @@
   EXPECT_EQ(*actual[0], 1);
 }
 
-#if GTEST_HAS_DEATH_TEST
 
 TEST(MutatingTest, MoveToCArrayInvalidSize) {
   std::vector<int> input = {1, 2, 3};
   int actual[2] = {0, 0};
+  (void)actual;
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_move(input, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, MoveToContainerInvalidSize) {
   std::list<int> input = {1, 2, 3, 4, 5};
   std::list<int> actual = {0, 0, 0};
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_move(input, actual), "");
   }
+#endif
 }
 
 TEST(MutatingTest, MoveToForwardListInvalidSize) {
   std::forward_list<int> input = {1, 2, 3, 4, 5};
   std::forward_list<int> actual = {0, 0, 0};
+#if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
     EXPECT_DEATH(absl::c_move(input, actual), "");
   }
+#endif
 }
 
-#endif  // GTEST_HAS_DEATH_TEST
-
 TEST(MutatingTest, SwapRanges) {
   std::vector<int> odds = {2, 4, 6};
   std::vector<int> evens = {1, 3, 5};
@@ -1105,19 +1176,144 @@
   *end = 7;
   EXPECT_EQ(std::vector<int>({1, 5, 4, 7}), z);
 
-  z.clear();
-  y.pop_back();
-  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
-  EXPECT_EQ(std::vector<int>({1, 5}), z);
-  *end = 7;
-  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
+  std::vector<int> x2{1, 2, 3};
+  std::vector<int> y2{10, 20, 30};
+  std::vector<int> z2(3);
+  auto out_it = z2.begin();
+  absl::c_transform(x2, y2, out_it, std::plus<int>());
+  // The caller's iterator should not be modified.
+  EXPECT_EQ(out_it, z2.begin());
+  EXPECT_EQ(z2, std::vector<int>({11, 22, 33}));
+}
 
-  z.clear();
-  std::swap(x, y);
-  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
-  EXPECT_EQ(std::vector<int>({1, 5}), z);
-  *end = 7;
-  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
+TEST(MutatingTest, TransformToContainer) {
+  const std::vector<int> input = {1, 2, 3};
+  std::vector<int> actual = {0, 0, 0, 4, 5};
+  absl::c_transform(input, actual, [](int x) { return x * 2; });
+  EXPECT_THAT(actual, ElementsAre(2, 4, 6, 4, 5));
+}
+
+TEST(MutatingTest, BinaryTransformToContainer) {
+  {
+    const std::vector<int> input1 = {1, 2, 3};
+    const std::vector<int> input2 = {10, 20, 30};
+    std::vector<int> actual = {0, 0, 0, 4, 5};
+    absl::c_transform(input1, input2, actual, std::plus<int>());
+    EXPECT_THAT(actual, ElementsAre(11, 22, 33, 4, 5));
+  }
+  {
+    const std::vector<int> input1 = {1, 2, 3, 4};
+    const std::vector<int> input2 = {10, 20};
+    std::vector<int> actual = {0, 0, 0, 4, 5};
+    absl::c_transform(input1, input2, actual, std::plus<int>());
+    EXPECT_THAT(actual, ElementsAre(11, 22, 0, 4, 5));
+  }
+  {
+    const std::vector<int> input1 = {1, 2};
+    const std::vector<int> input2 = {10, 20, 30, 40};
+    std::vector<int> actual = {0, 0, 0, 4, 5};
+    absl::c_transform(input1, input2, actual, std::plus<int>());
+    EXPECT_THAT(actual, ElementsAre(11, 22, 0, 4, 5));
+  }
+}
+
+TEST(MutatingTest, TransformToDifferentContainerType) {
+  const std::list<int> input = {1, 2, 3};
+  std::array<int, 5> actual = {0, 0, 0, 4, 5};
+  absl::c_transform(input, actual, [](int x) { return x * 2; });
+  EXPECT_THAT(actual, ElementsAre(2, 4, 6, 4, 5));
+}
+
+TEST(MutatingTest, TransformToCArray) {
+  const std::vector<int> input = {1, 2, 3};
+  int actual[5] = {0, 0, 0, 4, 5};
+  absl::c_transform(input, actual, [](int x) { return x * 2; });
+  EXPECT_THAT(actual, ElementsAre(2, 4, 6, 4, 5));
+}
+
+TEST(MutatingTest, TransformFromCArray) {
+  const int input[5] = {1, 2, 3, 4, 5};
+  std::vector<int> actual = {0, 0, 0, 0, 0};
+  absl::c_transform(input, actual, [](int x) { return x * 2; });
+  EXPECT_THAT(actual, ElementsAre(2, 4, 6, 8, 10));
+}
+
+TEST(MutatingTest, TransformToCArrayInvalidSize) {
+  const std::vector<int> input = {1, 2, 3};
+  int actual[2] = {0, 0};
+  (void)actual;
+#if GTEST_HAS_DEATH_TEST
+  if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
+    EXPECT_DEATH(absl::c_transform(input, actual, [](int x) { return x * 2; }),
+                 "");
+  }
+#endif
+}
+
+TEST(MutatingTest, BinaryTransformToCArrayInvalidSize) {
+  const std::vector<int> input1 = {1, 2, 3};
+  const std::vector<int> input2 = {10, 20, 30};
+  int actual[2] = {0, 0};
+  (void)actual;
+#if GTEST_HAS_DEATH_TEST
+  if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
+    EXPECT_DEATH(absl::c_transform(input1, input2, actual, std::plus<int>()),
+                 "");
+  }
+#endif
+}
+
+TEST(MutatingTest, TransformToContainerInvalidSize) {
+  const std::list<int> input = {1, 2, 3, 4, 5};
+  std::list<int> actual = {0, 0, 0};
+#if GTEST_HAS_DEATH_TEST
+  if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
+    EXPECT_DEATH(absl::c_transform(input, actual, [](int x) { return x * 2; }),
+                 "");
+  }
+#endif
+}
+
+TEST(MutatingTest, BinaryTransformToContainerInvalidSize) {
+  const std::vector<int> input1 = {1, 2, 3, 4, 5};
+  const std::vector<int> input2 = {10, 20, 30, 40, 50};
+  std::vector<int> actual = {0, 0, 0};
+#if GTEST_HAS_DEATH_TEST
+  if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
+    EXPECT_DEATH(absl::c_transform(input1, input2, actual, std::plus<int>()),
+                 "");
+  }
+#endif
+}
+
+TEST(MutatingTest, BinaryTransformInput2InvalidSize) {
+  const std::vector<int> input1 = {1, 2, 3};
+  const std::vector<int> input2 = {10, 20};
+  std::vector<int> actual = {0};
+#if GTEST_HAS_DEATH_TEST
+  if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
+    EXPECT_DEATH(absl::c_transform(input1, input2, actual, std::plus<int>()),
+                 "");
+  }
+#endif
+}
+
+TEST(MutatingTest, BinaryTransformInput1InvalidSize) {
+  const std::vector<int> input1 = {1, 2};
+  const std::vector<int> input2 = {10, 20, 30};
+  std::vector<int> actual = {0};
+#if GTEST_HAS_DEATH_TEST
+  if (IsHardened()) {
+    absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
+    EXPECT_DEATH(absl::c_transform(input1, input2, actual, std::plus<int>()),
+                 "");
+  }
+#endif
 }
 
 TEST(MutatingTest, Replace) {
@@ -2597,6 +2793,27 @@
                                                  std::declval<Output>()))>>
     : std::true_type {};
 
+template <typename Container, typename Output, typename UnaryOp,
+          typename = void>
+struct CanTransformUnary : std::false_type {};
+template <typename Container, typename Output, typename UnaryOp>
+struct CanTransformUnary<Container, Output, UnaryOp,
+                         absl::void_t<decltype(absl::c_transform(
+                             std::declval<Container>(), std::declval<Output>(),
+                             std::declval<UnaryOp>()))>> : std::true_type {};
+
+template <typename Container1, typename Container2, typename Output,
+          typename BinaryOp, typename = void>
+struct CanTransformBinary : std::false_type {};
+template <typename Container1, typename Container2, typename Output,
+          typename BinaryOp>
+struct CanTransformBinary<
+    Container1, Container2, Output, BinaryOp,
+    absl::void_t<decltype(absl::c_transform(
+        std::declval<Container1>(), std::declval<Container2>(),
+        std::declval<Output>(), std::declval<BinaryOp>()))>> : std::true_type {
+};
+
 TEST(CanCopyTest, CopyToMultiDimArray) {
   static_assert(CanCopy<std::vector<int>, int (&)[10]>::value);
   static_assert(!CanCopy<std::vector<int>, int (&)[2][2]>::value);
@@ -2624,12 +2841,25 @@
   using Vec = std::vector<int>;
   // Because AmbiguousType is both an iterator and a container,
   // the compiler should fail to resolve the c_copy overload.
-  static_assert(!CanCopy<Vec, AmbiguousType>::value,
+  static_assert(!CanCopy<Vec, AmbiguousType&>::value,
                 "Ambiguous types should not compile!");
-  static_assert(!CanCopyN<Vec, AmbiguousType>::value,
+  static_assert(!CanCopyN<Vec, AmbiguousType&>::value,
                 "Ambiguous types should not compile!");
 }
 
+TEST(CanCopyTest, CopyToRValue) {
+  using Vec = std::vector<int>;
+  using Span = absl::Span<int>;
+  static_assert(CanCopy<Vec, Span>::value,
+                "Should be able to copy to rvalue Span");
+  static_assert(!CanCopy<Vec, Vec>::value,
+                "Should not be able to copy to rvalue vector");
+  static_assert(CanCopyN<Vec, Span>::value,
+                "Should be able to copy_n to rvalue Span");
+  static_assert(!CanCopyN<Vec, Vec>::value,
+                "Should not be able to copy_n to rvalue vector");
+}
+
 TEST(CanMoveTest, MoveToMultiDimArray) {
   static_assert(CanMove<std::vector<int>, int (&)[10]>::value);
   static_assert(!CanMove<std::vector<int>, int (&)[2][2]>::value);
@@ -2644,7 +2874,57 @@
   using Vec = std::vector<int>;
   // Because AmbiguousType is both an iterator and a container,
   // the compiler should fail to resolve the c_move overload.
-  static_assert(!CanMove<Vec, AmbiguousType>::value,
+  static_assert(!CanMove<Vec, AmbiguousType&>::value,
+                "Ambiguous types should not compile!");
+}
+
+TEST(CanMoveTest, MoveToRValue) {
+  using Vec = std::vector<std::unique_ptr<int>>;
+  using Span = absl::Span<std::unique_ptr<int>>;
+  static_assert(CanMove<Vec, Span>::value,
+                "Should be able to move to rvalue Span");
+  static_assert(!CanMove<Vec, Vec>::value,
+                "Should not be able to move to rvalue vector");
+}
+
+TEST(CanTransformTest, TransformToMultiDimArray) {
+  using Negate = std::negate<int>;
+  using Plus = std::plus<int>;
+
+  static_assert(
+      CanTransformUnary<std::vector<int>, int (&)[10], Negate>::value);
+  static_assert(
+      !CanTransformUnary<std::vector<int>, int (&)[2][2], Negate>::value);
+
+  static_assert(CanTransformUnary<int[10], int (&)[10], Negate>::value);
+  static_assert(!CanTransformUnary<int[10], int (&)[2][2], Negate>::value);
+  static_assert(!CanTransformUnary<int[2][2], int (&)[4], Negate>::value);
+  static_assert(!CanTransformUnary<int[2][2], int (&)[2][2], Negate>::value);
+
+  static_assert(CanTransformBinary<std::vector<int>, std::vector<int>,
+                                   int (&)[10], Plus>::value);
+  static_assert(!CanTransformBinary<std::vector<int>, std::vector<int>,
+                                    int (&)[2][2], Plus>::value);
+
+  static_assert(CanTransformBinary<int[10], int[10], int (&)[10], Plus>::value);
+  static_assert(
+      !CanTransformBinary<int[10], int[10], int (&)[2][2], Plus>::value);
+  static_assert(
+      !CanTransformBinary<int[2][2], int[4], int (&)[4], Plus>::value);
+  static_assert(
+      !CanTransformBinary<int[2][2], int[2][2], int (&)[2][2], Plus>::value);
+}
+
+TEST(CanTransformTest, AmbiguousTypeFailsToCompile) {
+  using Vec = std::vector<int>;
+  using Negate = std::negate<int>;
+  using Plus = std::plus<int>;
+
+  // Because AmbiguousType is both an iterator and a container,
+  // the compiler should fail to resolve the c_transform overload.
+  static_assert(!CanTransformUnary<Vec, AmbiguousType&, Negate>::value,
+                "Ambiguous types should not compile!");
+  static_assert(!CanTransformBinary<Vec, Vec, AmbiguousType&, Plus>::value,
                 "Ambiguous types should not compile!");
 }
 
diff --git a/absl/base/internal/hardening.h b/absl/base/internal/hardening.h
index fc86621..ef6d327 100644
--- a/absl/base/internal/hardening.h
+++ b/absl/base/internal/hardening.h
@@ -23,6 +23,8 @@
 #ifndef ABSL_BASE_INTERNAL_HARDENING_H_
 #define ABSL_BASE_INTERNAL_HARDENING_H_
 
+#include <cstddef>
+
 #include "absl/base/config.h"
 #include "absl/base/macros.h"
 #include "absl/base/options.h"
@@ -66,8 +68,8 @@
 #endif
 }
 
-template <typename T>
-constexpr void HardeningAssertGT(T val1, T val2) {
+template <typename T1, typename T2>
+constexpr void HardeningAssertGT(T1 val1, T2 val2) {
   ABSL_ASSERT(val1 > val2);
 #if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)
   if (!ABSL_PREDICT_TRUE(val1 > val2)) {
@@ -76,8 +78,8 @@
 #endif
 }
 
-template <typename T>
-constexpr void HardeningAssertGE(T val1, T val2) {
+template <typename T1, typename T2>
+constexpr void HardeningAssertGE(T1 val1, T2 val2) {
   ABSL_ASSERT(val1 >= val2);
 #if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)
   if (!ABSL_PREDICT_TRUE(val1 >= val2)) {
@@ -86,8 +88,8 @@
 #endif
 }
 
-template <typename T>
-constexpr void HardeningAssertLT(T val1, T val2) {
+template <typename T1, typename T2>
+constexpr void HardeningAssertLT(T1 val1, T2 val2) {
   ABSL_ASSERT(val1 < val2);
 #if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)
   if (!ABSL_PREDICT_TRUE(val1 < val2)) {
@@ -96,8 +98,8 @@
 #endif
 }
 
-template <typename T>
-constexpr void HardeningAssertLE(T val1, T val2) {
+template <typename T1, typename T2>
+constexpr void HardeningAssertLE(T1 val1, T2 val2) {
   ABSL_ASSERT(val1 <= val2);
 #if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)
   if (!ABSL_PREDICT_TRUE(val1 <= val2)) {
@@ -130,6 +132,20 @@
 #endif
 }
 
+class ScopedSetAbslHardeningForTesting {
+ private:
+  bool prev_state_;
+
+ public:
+  explicit ScopedSetAbslHardeningForTesting([[maybe_unused]] bool enabled) {
+    prev_state_ = false;
+    SetAbslHardeningEnabled(enabled);
+  }
+  ~ScopedSetAbslHardeningForTesting() {
+    absl::base_internal::SetAbslHardeningEnabled(prev_state_);
+  }
+};
+
 }  // namespace base_internal
 
 ABSL_NAMESPACE_END
diff --git a/absl/base/macros.h b/absl/base/macros.h
index bfb6402..46432f0 100644
--- a/absl/base/macros.h
+++ b/absl/base/macros.h
@@ -224,13 +224,30 @@
 // `OldType` with `NewType`. Once all replacements have been completed, the old
 // function or type can be deleted.
 //
+// Internal note: Clang also allows `ABSL_REFACTOR_INLINE` to be used on
+// using-declarations, but attributes on using-declarations are invalid in C++.
+// (NOTE: This note refers to `using a::b ABSL_REFACTOR_INLINE;` and not
+// `using b ABSL_REFACTOR_INLINE = a::b;`, which is OK.) Therefore:
+//
+// 1. In OSS: Do not use this on using-declarations. Such usage is invalid and
+//    unsupported usage, and may break at any time.
+// 2. In Google: Avoid such usage except as a last resort. Instead, prefer other
+//    inlining approaches (such as type aliases or forwarding functions,
+//    illustrated above) whenever possible. This is because Clang (currently)
+//    does not honor the [[deprecated]] attribute on using-declarations, and
+//    therefore cannot surface the deprecation to users in the middle of a
+//    migration.
+//
 // See go/cpp-inliner for more information.
 //
 // Note: go/cpp-inliner is Google-internal service for automated refactoring.
 // While open-source users do not have access to this service, the macro is
 // provided for compatibility.
 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
-#define ABSL_REFACTOR_INLINE [[clang::annotate("inline-me")]]
+#define ABSL_REFACTOR_INLINE                                                \
+  _Pragma("clang diagnostic push") /* Avoid errors on using-declarations */ \
+      _Pragma("clang diagnostic ignored \"-Wcxx-attribute-extension\"")     \
+          [[clang::annotate("inline-me")]] _Pragma("clang diagnostic pop")
 #else
 #define ABSL_REFACTOR_INLINE
 #endif
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index e748f04..a386a53 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -89,6 +89,7 @@
         ":test_allocator",
         "//absl/base:config",
         "//absl/base:exception_testing",
+        "//absl/base:hardening",
         "//absl/base:iterator_traits_test_helper",
         "//absl/hash:hash_testing",
         "//absl/memory",
@@ -180,6 +181,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:exception_testing",
+        "//absl/base:hardening",
         "//absl/base:iterator_traits_test_helper",
         "//absl/hash:hash_testing",
         "//absl/log:check",
@@ -1382,6 +1384,7 @@
         ":chunked_queue",
         ":test_allocator",
         "//absl/base:core_headers",
+        "//absl/base:hardening",
         "//absl/strings",
         "@googletest//:gtest",
         "@googletest//:gtest_main",
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 396b944..005548f 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -149,6 +149,7 @@
     absl::fixed_array
     absl::config
     absl::exception_testing
+    absl::hardening
     absl::hash_testing
     absl::iterator_traits_test_helper_internal
     absl::memory
@@ -235,6 +236,7 @@
     absl::config
     absl::core_headers
     absl::exception_testing
+    absl::hardening
     absl::hash_testing
     absl::inlined_vector
     absl::memory
@@ -1234,6 +1236,7 @@
     absl::chunked_queue
     absl::config
     absl::core_headers
+    absl::hardening
     absl::strings
     absl::test_allocator
     GTest::gmock_main
diff --git a/absl/container/chunked_queue_test.cc b/absl/container/chunked_queue_test.cc
index bee7e03..4ba13c9 100644
--- a/absl/container/chunked_queue_test.cc
+++ b/absl/container/chunked_queue_test.cc
@@ -29,6 +29,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/internal/hardening.h"
 #include "absl/base/macros.h"
 #include "absl/container/internal/test_allocator.h"
 #include "absl/strings/str_cat.h"
@@ -755,6 +756,7 @@
     GTEST_SKIP() << "Not a hardened build";
   }
 
+  absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
   absl::chunked_queue<int> q;
   EXPECT_DEATH_IF_SUPPORTED(q.front(), "");
   EXPECT_DEATH_IF_SUPPORTED(q.back(), "");
diff --git a/absl/container/fixed_array_test.cc b/absl/container/fixed_array_test.cc
index 54e5fd6..81fb0e5 100644
--- a/absl/container/fixed_array_test.cc
+++ b/absl/container/fixed_array_test.cc
@@ -31,6 +31,7 @@
 #include "gtest/gtest.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/exception_testing.h"
+#include "absl/base/internal/hardening.h"
 #include "absl/base/internal/iterator_traits_test_helper.h"
 #include "absl/base/options.h"
 #include "absl/container/internal/test_allocator.h"
@@ -196,6 +197,7 @@
 
 TEST(FixedArrayTest, Hardened) {
 #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
   absl::FixedArray<int> a = {1, 2, 3};
   EXPECT_EQ(a[2], 3);
   EXPECT_DEATH_IF_SUPPORTED(a[3], "");
diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc
index 56edf09..d6cc175 100644
--- a/absl/container/inlined_vector_test.cc
+++ b/absl/container/inlined_vector_test.cc
@@ -32,6 +32,7 @@
 #include "gtest/gtest.h"
 #include "absl/base/attributes.h"
 #include "absl/base/internal/exception_testing.h"
+#include "absl/base/internal/hardening.h"
 #include "absl/base/internal/iterator_traits_test_helper.h"
 #include "absl/base/macros.h"
 #include "absl/base/options.h"
@@ -258,6 +259,7 @@
   Fill(&v, 10);
   EXPECT_EQ(v[9], 9);
 #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
   EXPECT_DEATH_IF_SUPPORTED(v[10], "");
   EXPECT_DEATH_IF_SUPPORTED(v[static_cast<size_t>(-1)], "");
   EXPECT_DEATH_IF_SUPPORTED(v.resize(v.max_size() + 1), "");
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index dc58245..80efa1e 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -386,7 +386,8 @@
   if (capacity <= GrowthInfoLowerBound::kMaxGrowthLeftLowerBound) {
     return GetGrowthLeftLowerBound();
   } else {
-    return GetGrowthLeftTotalBigCapacity(full_growth_info_ptr());
+    return static_cast<size_t>(
+        GetGrowthLeftTotalBigCapacity(full_growth_info_ptr()));
   }
 }
 
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index b99d987..7119e10 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -230,9 +230,9 @@
 #include <ranges>  // NOLINT(build/c++20)
 #endif
 
-#ifdef __BMI2__
-#include <bmi2intrin.h>
-#endif  // __BMI2__
+#if defined(__i386__) || defined(__x86_64__)
+#include <immintrin.h>
+#endif
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index 4719364..d364df8 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -94,7 +94,7 @@
 // the C++14's `std::make_unique`. Now that C++11 support has been sunsetted,
 // `absl::make_unique` simply uses the STL-provided implementation. New code
 // should use `std::make_unique`.
-using std::make_unique;
+using std::make_unique ABSL_REFACTOR_INLINE;
 
 #if defined(__cpp_lib_smart_ptr_for_overwrite) && \
     __cpp_lib_smart_ptr_for_overwrite >= 202002L
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 9f52202..be55e52 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -151,6 +151,7 @@
 template <class T>
 using decay_t ABSL_DEPRECATE_AND_INLINE() = std::decay_t<T>;
 
+// Avoid inlining since the inliner cannot handle default arguments well.
 template <bool C, class T = void>
 using enable_if_t [[deprecated("Use std::enable_if_t instead.")]] =
     std::enable_if_t<C, T>;
diff --git a/absl/random/distributions.h b/absl/random/distributions.h
index cfe731e..8a032df 100644
--- a/absl/random/distributions.h
+++ b/absl/random/distributions.h
@@ -283,8 +283,11 @@
 //
 // `absl::Exponential` produces a floating point number representing the
 // distance (time) between two consecutive events in a point process of events
-// occurring continuously and independently at a constant average rate. `T` must
-// be a floating point type, but may be inferred from the type of `lambda`.
+// occurring continuously and independently at a constant average rate `lambda`.
+// `T` must be a floating point type, but may be inferred from the type of
+// `lambda`.
+//
+// The mean of the distribution is 1/`lambda`.
 //
 // See https://en.wikipedia.org/wiki/Exponential_distribution.
 //
diff --git a/absl/status/status.h b/absl/status/status.h
index 88486d3..55802cd 100644
--- a/absl/status/status.h
+++ b/absl/status/status.h
@@ -644,7 +644,7 @@
       absl::SourceLocation loc = absl::SourceLocation::current()) {
     if (ok()) return;
     rep_ = AddSourceLocationImpl(rep_, loc);
-    ABSL_ATTRIBUTE_UNUSED bool okay = ok();
+    [[maybe_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
@@ -1091,7 +1091,7 @@
   Status out = MakeErrorImpl<static_cast<int>(error_code)>(message, loc);
   // -Wassume warning complains about potential side effects of `ok()`, so use a
   // local to avoid that.
-  ABSL_ATTRIBUTE_UNUSED bool ok = out.ok();
+  [[maybe_unused]] bool ok = out.ok();
   ABSL_ASSUME(!ok);
   return out;
 }
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 4c974ce..def78d5 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -1005,6 +1005,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
+        "//absl/base:hardening",
         "//absl/base:no_destructor",
         "//absl/container:fixed_array",
         "//absl/functional:function_ref",
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index 3041e19..e6b5da3 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -1164,6 +1164,7 @@
     absl::endian
     absl::fixed_array
     absl::function_ref
+    absl::hardening
     absl::hash
     absl::hash_testing
     absl::no_destructor
diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc
index 5c773e7..56db8f4 100644
--- a/absl/strings/cord_test.cc
+++ b/absl/strings/cord_test.cc
@@ -38,6 +38,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/endian.h"
+#include "absl/base/internal/hardening.h"
 #include "absl/base/macros.h"
 #include "absl/base/no_destructor.h"
 #include "absl/base/options.h"
@@ -2828,6 +2829,7 @@
   }());
   if (!test_hardening) return;
 
+  absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
   EXPECT_DEATH_IF_SUPPORTED(cord[5], "");
   EXPECT_DEATH_IF_SUPPORTED(*cord.chunk_end(), "");
   EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), "");
diff --git a/absl/strings/internal/stl_type_traits.h b/absl/strings/internal/stl_type_traits.h
index ae8454d..6298921 100644
--- a/absl/strings/internal/stl_type_traits.h
+++ b/absl/strings/internal/stl_type_traits.h
@@ -25,6 +25,8 @@
 #ifndef ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
 #define ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
 
+#include <stddef.h>
+
 #include <array>
 #include <bitset>
 #include <deque>
@@ -43,212 +45,97 @@
 ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
-template <typename C, template <typename...> class T>
-struct IsSpecializationImpl : std::false_type {};
-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<std::decay_t<C>, T>;
+template <typename To, typename From>
+using IsCastableToDerivedSTLContainer =
+    std::enable_if_t<!std::is_same_v<From, To>, std::is_convertible<From, To>>;
 
 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<std::decay_t<C>>;
+std::false_type CastableToDerivedSTLContainer(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<std::decay_t<C>>;
+template <typename C, typename V, size_t N>
+IsCastableToDerivedSTLContainer<C, std::array<typename C::value_type, N>>
+CastableToDerivedSTLContainer(std::array<V, N>*);
 
-template <typename C>
-struct IsSTLContainer
-    : std::disjunction<
-          IsArray<C>, IsBitset<C>, IsSpecialization<C, std::deque>,
-          IsSpecialization<C, std::forward_list>,
-          IsSpecialization<C, std::list>, IsSpecialization<C, std::map>,
-          IsSpecialization<C, std::multimap>, IsSpecialization<C, std::set>,
-          IsSpecialization<C, std::multiset>,
-          IsSpecialization<C, std::unordered_map>,
-          IsSpecialization<C, std::unordered_multimap>,
-          IsSpecialization<C, std::unordered_set>,
-          IsSpecialization<C, std::unordered_multiset>,
-          IsSpecialization<C, std::vector>> {};
+template <typename C, size_t N>
+IsCastableToDerivedSTLContainer<C, std::bitset<N>>
+CastableToDerivedSTLContainer(std::bitset<N>*);
 
-template <typename C, template <typename...> class T, typename = void>
-struct IsBaseOfSpecializationImpl : std::false_type {};
-// IsBaseOfSpecializationImpl needs multiple partial specializations to SFINAE
-// on the existence of container dependent types and plug them into the STL
-// template.
-template <typename C, template <typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
-    C, T, std::void_t<typename C::value_type, typename C::allocator_type>>
-    : std::is_base_of<C,
-                      T<typename C::value_type, typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
-    C, T,
-    std::void_t<typename C::key_type, typename C::key_compare,
-                typename C::allocator_type>>
-    : std::is_base_of<C, T<typename C::key_type, typename C::key_compare,
-                           typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
-    C, T,
-    std::void_t<typename C::key_type, typename C::mapped_type,
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::deque<typename C::value_type, typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::deque<U...>*);
+
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::forward_list<typename C::value_type, typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::forward_list<U...>*);
+
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::list<typename C::value_type, typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::list<U...>*);
+
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::map<typename C::key_type, typename C::mapped_type,
                 typename C::key_compare, typename C::allocator_type>>
-    : std::is_base_of<C,
-                      T<typename C::key_type, typename C::mapped_type,
-                        typename C::key_compare, typename C::allocator_type>> {
-};
-template <typename C, template <typename, typename, typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
-    C, T,
-    // Roundabout equivalent of std::void_t that works around a template
-    // redefinition error from Clang.
-    std::conditional_t<
-        true, void,
-        std::common_type<typename C::key_type, typename C::hasher,
-                         typename C::key_equal, typename C::allocator_type>>>
-    : std::is_base_of<C, T<typename C::key_type, typename C::hasher,
-                           typename C::key_equal, typename C::allocator_type>> {
-};
-template <typename C,
-          template <typename, typename, typename, typename, typename> class T>
-struct IsBaseOfSpecializationImpl<
-    C, T,
-    std::void_t<typename C::key_type, typename C::mapped_type,
-                typename C::hasher, typename C::key_equal,
+CastableToDerivedSTLContainer(std::map<U...>*);
+
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::multimap<typename C::key_type, typename C::mapped_type,
+                     typename C::key_compare, typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::multimap<U...>*);
+
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::set<typename C::value_type, typename C::key_compare,
                 typename C::allocator_type>>
-    : std::is_base_of<C, T<typename C::key_type, typename C::mapped_type,
-                           typename C::hasher, typename C::key_equal,
-                           typename C::allocator_type>> {};
-template <typename C, template <typename...> class T>
-using IsBaseOfSpecialization = IsBaseOfSpecializationImpl<std::decay_t<C>, T>;
+CastableToDerivedSTLContainer(std::set<U...>*);
 
-template <typename C>
-struct IsBaseOfArrayImpl : std::false_type {};
-template <template <typename, size_t> class A, typename T, size_t N>
-struct IsBaseOfArrayImpl<A<T, N>> : std::is_base_of<A<T, N>, std::array<T, N>> {
-};
-template <typename C>
-using IsBaseOfArray = IsBaseOfArrayImpl<std::decay_t<C>>;
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::multiset<typename C::value_type, typename C::key_compare,
+                     typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::multiset<U...>*);
 
-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<std::decay_t<C>>;
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::unordered_map<typename C::key_type, typename C::mapped_type,
+                          typename C::hasher, typename C::key_equal,
+                          typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::unordered_map<U...>*);
 
-template <typename C>
-struct IsBaseOfSTLContainer
-    : std::disjunction<IsBaseOfArray<C>, IsBaseOfBitset<C>,
-                       IsBaseOfSpecialization<C, std::deque>,
-                       IsBaseOfSpecialization<C, std::forward_list>,
-                       IsBaseOfSpecialization<C, std::list>,
-                       IsBaseOfSpecialization<C, std::map>,
-                       IsBaseOfSpecialization<C, std::multimap>,
-                       IsBaseOfSpecialization<C, std::set>,
-                       IsBaseOfSpecialization<C, std::multiset>,
-                       IsBaseOfSpecialization<C, std::unordered_map>,
-                       IsBaseOfSpecialization<C, std::unordered_multimap>,
-                       IsBaseOfSpecialization<C, std::unordered_set>,
-                       IsBaseOfSpecialization<C, std::unordered_multiset>,
-                       IsBaseOfSpecialization<C, std::vector>> {};
-
-template <typename C, template <typename...> class T, typename = void>
-struct IsConvertibleToSpecializationImpl : std::false_type {};
-// IsConvertibleToSpecializationImpl needs multiple partial specializations to
-// SFINAE on the existence of container dependent types and plug them into the
-// STL template.
-template <typename C, template <typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
-    C, T, std::void_t<typename C::value_type, typename C::allocator_type>>
-    : std::is_convertible<
-          C, T<typename C::value_type, typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
-    C, T,
-    std::void_t<typename C::key_type, typename C::key_compare,
-                typename C::allocator_type>>
-    : std::is_convertible<C, T<typename C::key_type, typename C::key_compare,
-                               typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
-    C, T,
-    std::void_t<typename C::key_type, typename C::mapped_type,
-                typename C::key_compare, typename C::allocator_type>>
-    : std::is_convertible<
-          C, T<typename C::key_type, typename C::mapped_type,
-               typename C::key_compare, typename C::allocator_type>> {};
-template <typename C, template <typename, typename, typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
-    C, T,
-    // Roundabout equivalent of std::void_t that works around a template
-    // redefinition error from Clang.
-    std::conditional_t<
-        true, void,
-        std::common_type<typename C::key_type, typename C::hasher,
-                         typename C::key_equal, typename C::allocator_type>>>
-    : std::is_convertible<
-          C, T<typename C::key_type, typename C::hasher, typename C::key_equal,
-               typename C::allocator_type>> {};
-template <typename C,
-          template <typename, typename, typename, typename, typename> class T>
-struct IsConvertibleToSpecializationImpl<
-    C, T,
-    std::void_t<typename C::key_type, typename C::mapped_type,
-                typename C::hasher, typename C::key_equal,
-                typename C::allocator_type>>
-    : std::is_convertible<C, T<typename C::key_type, typename C::mapped_type,
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::unordered_multimap<typename C::key_type, typename C::mapped_type,
                                typename C::hasher, typename C::key_equal,
-                               typename C::allocator_type>> {};
-template <typename C, template <typename...> class T>
-using IsConvertibleToSpecialization =
-    IsConvertibleToSpecializationImpl<std::decay_t<C>, T>;
+                               typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::unordered_multimap<U...>*);
 
-template <typename C>
-struct IsConvertibleToArrayImpl : std::false_type {};
-template <template <typename, size_t> class A, typename T, size_t N>
-struct IsConvertibleToArrayImpl<A<T, N>>
-    : std::is_convertible<A<T, N>, std::array<T, N>> {};
-template <typename C>
-using IsConvertibleToArray = IsConvertibleToArrayImpl<std::decay_t<C>>;
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::unordered_set<typename C::key_type, typename C::hasher,
+                          typename C::key_equal, typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::unordered_set<U...>*);
 
-template <typename C>
-struct IsConvertibleToBitsetImpl : std::false_type {};
-template <template <size_t> class B, size_t N>
-struct IsConvertibleToBitsetImpl<B<N>>
-    : std::is_convertible<B<N>, std::bitset<N>> {};
-template <typename C>
-using IsConvertibleToBitset = IsConvertibleToBitsetImpl<std::decay_t<C>>;
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C,
+    std::unordered_multiset<typename C::key_type, typename C::hasher,
+                            typename C::key_equal, typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::unordered_multiset<U...>*);
 
-template <typename C>
-struct IsConvertibleToSTLContainer
-    : std::disjunction<
-          IsConvertibleToArray<C>, IsConvertibleToBitset<C>,
-          IsConvertibleToSpecialization<C, std::deque>,
-          IsConvertibleToSpecialization<C, std::forward_list>,
-          IsConvertibleToSpecialization<C, std::list>,
-          IsConvertibleToSpecialization<C, std::map>,
-          IsConvertibleToSpecialization<C, std::multimap>,
-          IsConvertibleToSpecialization<C, std::set>,
-          IsConvertibleToSpecialization<C, std::multiset>,
-          IsConvertibleToSpecialization<C, std::unordered_map>,
-          IsConvertibleToSpecialization<C, std::unordered_multimap>,
-          IsConvertibleToSpecialization<C, std::unordered_set>,
-          IsConvertibleToSpecialization<C, std::unordered_multiset>,
-          IsConvertibleToSpecialization<C, std::vector>> {};
+template <typename C, typename... U>
+IsCastableToDerivedSTLContainer<
+    C, std::vector<typename C::value_type, typename C::allocator_type>>
+CastableToDerivedSTLContainer(std::vector<U...>*);
 
 template <typename C>
 struct IsStrictlyBaseOfAndConvertibleToSTLContainer
-    : std::conjunction<std::negation<IsSTLContainer<C>>,
-                       IsBaseOfSTLContainer<C>,
-                       IsConvertibleToSTLContainer<C>> {};
+    : decltype(strings_internal::CastableToDerivedSTLContainer<
+               absl::remove_cvref_t<C>>(
+          std::declval<absl::remove_cvref_t<C>*>())) {};
 
 }  // namespace strings_internal
 ABSL_NAMESPACE_END
diff --git a/absl/time/time.h b/absl/time/time.h
index 03cf67a..fc1456b 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -1064,11 +1064,6 @@
 // the format specified by `absl::ParseTime()`.
 std::string AbslUnparseFlag(Time t);
 
-ABSL_DEPRECATED("Use AbslParseFlag() instead.")
-bool ParseFlag(const std::string& text, Time* t, std::string* error);
-ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
-std::string UnparseFlag(Time t);
-
 // TimeZone
 //
 // The `absl::TimeZone` is an opaque, small, value-type class representing a
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index 2670c0c..1d937e7 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -107,6 +107,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:exception_testing",
+        "//absl/base:hardening",
         "//absl/container:fixed_array",
         "//absl/container:inlined_vector",
         "//absl/hash",
@@ -149,6 +150,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:exception_testing",
+        "//absl/base:hardening",
         "//absl/base:raw_logging_internal",
         "//absl/hash:hash_testing",
         "//absl/meta:type_traits",
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index 79a4c19..28e1fe8 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -58,6 +58,7 @@
     absl::config
     absl::core_headers
     absl::exception_testing
+    absl::hardening
     absl::hash_testing
     absl::raw_logging_internal
     absl::span
@@ -101,6 +102,7 @@
     absl::core_headers
     absl::exception_testing
     absl::fixed_array
+    absl::hardening
     absl::hash
     absl::inlined_vector
     absl::hash_testing
diff --git a/absl/types/any_span_test.cc b/absl/types/any_span_test.cc
index e5960c6..fe12b74 100644
--- a/absl/types/any_span_test.cc
+++ b/absl/types/any_span_test.cc
@@ -30,6 +30,7 @@
 #include "gtest/gtest.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/exception_testing.h"
+#include "absl/base/internal/hardening.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/macros.h"
 #include "absl/hash/hash_testing.h"
@@ -1041,6 +1042,7 @@
   EXPECT_THAT(span.subspan(3, AnySpan<int>::npos), ElementsAre());
 #if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    auto hardener = absl::base_internal::ScopedSetAbslHardeningForTesting(true);
     EXPECT_DEATH(span.subspan(4, AnySpan<int>::npos), "");
     EXPECT_DEATH(span.subspan(AnySpan<int>::npos, AnySpan<int>::npos), "");
   }
@@ -1052,6 +1054,7 @@
   AnySpan<int> span(v);
 #if GTEST_HAS_DEATH_TEST
   if (IsHardened()) {
+    auto hardener = absl::base_internal::ScopedSetAbslHardeningForTesting(true);
     EXPECT_DEATH(span.subspan(5, 0), "");
     EXPECT_DEATH(span.subspan(5, 1), "");
     EXPECT_DEATH(span.subspan(AnySpan<int>::npos, 0), "");
diff --git a/absl/types/optional.h b/absl/types/optional.h
index c70efb1..a5b15b8 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -56,12 +56,13 @@
   return std::make_optional<T>(il, std::forward<Args>(args)...);
 }
 
-using std::nullopt;
+using std::nullopt ABSL_REFACTOR_INLINE;
 
 using nullopt_t ABSL_REFACTOR_INLINE
     = std::nullopt_t;
 
-using std::optional;
+using std::optional ABSL_REFACTOR_INLINE;
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/types/span.h b/absl/types/span.h
index 3b291a9..c33e294 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -719,6 +719,9 @@
 //     return absl::MakeSpan(&array[0], num_elements_);
 //   }
 //
+// NOTE: To avoid undefined behavior if the container is empty, use `.data()`
+// or pass the container directly instead of using `&v[0]` or `&v[v.size()]`.
+//
 template <int&... ExplicitArgumentBarrier, typename T>
 constexpr Span<T> MakeSpan(T* absl_nullable ptr ABSL_ATTRIBUTE_LIFETIME_BOUND,
                            size_t size) noexcept {
diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc
index 5a8b82e..051e673 100644
--- a/absl/types/span_test.cc
+++ b/absl/types/span_test.cc
@@ -27,6 +27,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/exception_testing.h"
+#include "absl/base/internal/hardening.h"
 #include "absl/base/options.h"
 #include "absl/container/fixed_array.h"
 #include "absl/container/inlined_vector.h"
@@ -250,6 +251,7 @@
   EXPECT_EQ(s.back(), s[9]);
 
 #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
   EXPECT_DEATH_IF_SUPPORTED(s[-1], "");
   EXPECT_DEATH_IF_SUPPORTED(s[10], "");
 #endif
@@ -291,6 +293,7 @@
   EXPECT_EQ(v, MakeRamp(20, 1));
 
 #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  absl::base_internal::ScopedSetAbslHardeningForTesting hardener(true);
   absl::Span<int> prefix_death(v);
   EXPECT_DEATH_IF_SUPPORTED(prefix_death.remove_prefix(21), "");
   absl::Span<int> suffix_death(v);