diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index 47d0efd..1d55240 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -153,6 +153,14 @@
   "debugging/internal/utf8_for_code_point.h"
   "debugging/internal/vdso_support.cc"
   "debugging/internal/vdso_support.h"
+  "extend/internal/aggregate.h"
+  "extend/internal/dependencies.h"
+  "extend/internal/is_tuple_hashable.h"
+  "extend/internal/num_bases.h"
+  "extend/internal/num_initializers.h"
+  "extend/internal/reflection.cc"
+  "extend/internal/reflection.h"
+  "extend/internal/tuple.h"
   "functional/any_invocable.h"
   "functional/internal/front_binder.h"
   "functional/bind_front.h"
@@ -421,8 +429,12 @@
   "time/civil_time.h"
   "time/clock.cc"
   "time/clock.h"
+  "time/clock_interface.cc"
+  "time/clock_interface.h"
   "time/duration.cc"
   "time/format.cc"
+  "time/simulated_clock.cc"
+  "time/simulated_clock.h"
   "time/time.cc"
   "time/time.h"
   "time/internal/cctz/include/cctz/civil_time.h"
diff --git a/MODULE.bazel b/MODULE.bazel
index 00a1083..edb49d0 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -39,5 +39,5 @@
 # intended to be used by Abseil users depend on GoogleTest.
 bazel_dep(
     name = "googletest",
-    version = "1.17.0",
+    version = "1.17.0.bcr.2",
 )
diff --git a/absl/CMakeLists.txt b/absl/CMakeLists.txt
index 810d7f3..2a986c3 100644
--- a/absl/CMakeLists.txt
+++ b/absl/CMakeLists.txt
@@ -20,6 +20,7 @@
 add_subdirectory(container)
 add_subdirectory(crc)
 add_subdirectory(debugging)
+add_subdirectory(extend)
 add_subdirectory(flags)
 add_subdirectory(functional)
 add_subdirectory(hash)
diff --git a/absl/extend/CMakeLists.txt b/absl/extend/CMakeLists.txt
new file mode 100644
index 0000000..dba0c5c
--- /dev/null
+++ b/absl/extend/CMakeLists.txt
@@ -0,0 +1,140 @@
+# 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.
+
+absl_cc_library(
+  NAME
+    dependencies_internal
+  HDRS
+    "internal/dependencies.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_test(
+  NAME
+    dependencies_internal_test
+  SRCS
+    "internal/dependencies_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::dependencies_internal
+    GTest::gmock_main
+)
+
+absl_cc_library(
+  NAME
+    num_initializers_internal
+  HDRS
+    "internal/num_initializers.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+)
+
+absl_cc_test(
+  NAME
+    num_initializers_internal_test
+  SRCS
+    "internal/num_initializers_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::num_initializers_internal
+    GTest::gmock_main
+)
+
+absl_cc_library(
+  NAME
+    num_bases_internal
+  HDRS
+    "internal/num_bases.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::num_initializers_internal
+    absl::type_traits
+    absl::optional
+)
+
+absl_cc_test(
+  NAME
+    num_bases_internal_test
+  SRCS
+    "internal/num_bases_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::num_bases_internal
+    GTest::gmock_main
+)
+
+absl_cc_library(
+  NAME
+    aggregate_internal
+  HDRS
+    "internal/aggregate.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::num_bases_internal
+    absl::num_initializers_internal
+)
+
+absl_cc_test(
+  NAME
+    aggregate_internal_test
+  SRCS
+    "internal/aggregate_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::aggregate_internal
+    GTest::gmock_main
+)
+
+absl_cc_library(
+  NAME
+    tuple_internal
+  HDRS
+    "internal/tuple.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_library(
+  NAME
+    is_tuple_hashable_internal
+  HDRS
+    "internal/is_tuple_hashable.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::hash
+)
+
+absl_cc_library(
+  NAME
+    reflection_internal
+  HDRS
+    "internal/reflection.h"
+  SRCS
+    "internal/reflection.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::strings
+    absl::span
+)
diff --git a/absl/extend/internal/BUILD.bazel b/absl/extend/internal/BUILD.bazel
new file mode 100644
index 0000000..79b8361
--- /dev/null
+++ b/absl/extend/internal/BUILD.bazel
@@ -0,0 +1,127 @@
+# 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.
+
+load("@rules_cc//cc:cc_library.bzl", "cc_library")
+load("@rules_cc//cc:cc_test.bzl", "cc_test")
+
+# Internal extend utilities and implementation details.
+package(
+    default_visibility = [
+        "//absl/extend:__subpackages__",
+    ],
+    features = ["header_modules"],
+)
+
+cc_library(
+    name = "tuple",
+    hdrs = ["tuple.h"],
+    deps = ["//absl/base:config"],
+)
+
+cc_library(
+    name = "is_tuple_hashable",
+    hdrs = ["is_tuple_hashable.h"],
+    deps = [
+        "//absl/base:config",
+        "//absl/hash",
+    ],
+)
+
+cc_library(
+    name = "reflection",
+    srcs = ["reflection.cc"],
+    hdrs = ["reflection.h"],
+    deps = [
+        "//absl/base:config",
+        "//absl/strings",
+        "//absl/types:span",
+    ],
+)
+
+cc_library(
+    name = "aggregate",
+    hdrs = ["aggregate.h"],
+    deps = [
+        ":num_bases",
+        ":num_initializers",
+        "//absl/base:config",
+    ],
+)
+
+cc_test(
+    name = "aggregate_test",
+    srcs = ["aggregate_test.cc"],
+    deps = [
+        ":aggregate",
+        "//absl/base:config",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "num_bases",
+    hdrs = ["num_bases.h"],
+    deps = [
+        ":num_initializers",
+        "//absl/base:config",
+    ],
+)
+
+cc_test(
+    name = "num_bases_test",
+    srcs = ["num_bases_test.cc"],
+    deps = [
+        ":num_bases",
+        "//absl/base:config",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "num_initializers",
+    hdrs = ["num_initializers.h"],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+    ],
+)
+
+cc_test(
+    name = "num_initializers_test",
+    srcs = ["num_initializers_test.cc"],
+    tags = [
+        "no_test_ios_arm64",
+    ],
+    deps = [
+        ":num_initializers",
+        "//absl/base:config",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "dependencies",
+    hdrs = ["dependencies.h"],
+    deps = ["//absl/base:config"],
+)
+
+cc_test(
+    name = "dependencies_test",
+    srcs = ["dependencies_test.cc"],
+    deps = [
+        ":dependencies",
+        "//absl/base:config",
+        "@googletest//:gtest_main",
+    ],
+)
diff --git a/absl/extend/internal/aggregate.h b/absl/extend/internal/aggregate.h
new file mode 100644
index 0000000..815865c
--- /dev/null
+++ b/absl/extend/internal/aggregate.h
@@ -0,0 +1,1687 @@
+// 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.
+
+#ifndef ABSL_EXTEND_INTERNAL_AGGREGATE_H_
+#define ABSL_EXTEND_INTERNAL_AGGREGATE_H_
+
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/extend/internal/num_bases.h"
+#include "absl/extend/internal/num_initializers.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace aggregate_internal {
+
+// This collection of constants to serialize information about type qualifiers
+// in C++. Together with `ExtractQualifiers` and `ApplyQualifiers` below, this
+// allows us to apply metafunctions that change the type but preserve
+// qualifiers. For example, a meta-function that converted `T` to
+// `std::vector<T>` could use `CopyQualifiers` below to ensure that
+// `std::string` became `std::vector<std::string>`, and that
+// `const std::string&` became `const std::vector<std::string>&`.
+//
+// Note: We use a non-power-of-2 for kRef so that operator| matches reference
+// collapsing semantics. That is, `(kRefRef | kRef) == kRef` in the same way
+// that `T&& &` is `T&`.
+inline constexpr int kRefRef = 1;
+inline constexpr int kRef = 3;
+inline constexpr int kConst = 4;
+inline constexpr int kVolatile = 8;
+
+// `ExtractQualifiers` returns an integer value representing the qualifiers that
+// are applied to the template parameter `T`.
+template <typename T>
+constexpr int ExtractQualifiers() {
+  int quals = 0;
+  if constexpr (std::is_lvalue_reference_v<T>) {
+    quals |= kRef;
+  } else if constexpr (std::is_rvalue_reference_v<T>) {
+    quals |= kRefRef;
+  }
+
+  using dereffed_type = std::remove_reference_t<T>;
+  if constexpr (std::is_const_v<dereffed_type>) quals |= kConst;
+  if constexpr (std::is_volatile_v<dereffed_type>) quals |= kVolatile;
+
+  return quals;
+}
+
+// `ApplyQualifiers<T, kQuals>::type` evaluates to a type which has the same
+// underlying type as `T` but with additional qualifiers from `kQuals` applied.
+// Note that we do not remove the qualifiers from `T`. So, for example,
+// `ApplyQualifiers<const int, kRef>::type` will be `const int&` rather than
+// `int&`.
+//
+// Also note that, because `
+template <typename T, int kQuals>
+struct ApplyQualifiers {
+ private:
+  static_assert(!std::is_reference_v<T>,
+                "Apply qualifiers cannot be called on a reference type.");
+  using handle_volatile =
+      std::conditional_t<((kQuals & kVolatile) == kVolatile), volatile T, T>;
+  using handle_const =
+      std::conditional_t<((kQuals & kConst) == kConst), const handle_volatile,
+                         handle_volatile>;
+  using handle_refref = std::conditional_t<((kQuals & kRefRef) == kRefRef),
+                                           handle_const&&, handle_const>;
+  using handle_ref = std::conditional_t<((kQuals & kRef) == kRef),
+                                        handle_refref&, handle_refref>;
+
+ public:
+  using type = handle_ref;
+};
+
+// `CopyQualifiers` extracts qualifiers from `From` and overwrites the
+// qualifiers on `To`.
+template <typename From, typename To>
+using CopyQualifiers =
+    typename ApplyQualifiers<To, ExtractQualifiers<From>()>::type;
+
+// `CorrectQualifiers` is specific to the implementation of `GetFields`. In
+// particular, when constructing a tuple of references to fields of a struct, we
+// need to know which fields should be referenced and which should be forwarded.
+// `CorrectQualifiers` forwards reference-members and otherwise copies the
+// qualifiers on the struct to its members being referenced in the tuple.
+template <typename Aggregate, typename Field, typename T>
+constexpr decltype(auto) CorrectQualifiers(T& val) {
+  if constexpr (std::is_reference_v<Field>) {
+    return static_cast<Field>(val);
+  } else {
+    using type = CopyQualifiers<Aggregate&&, Field>;
+    return static_cast<type>(val);
+  }
+}
+
+// `RemoveQualifiersAndReferencesFromTuple` removes volatile and const
+// qualifiers from the underlying type of each reference type within a tuple.
+template <typename T>
+struct RemoveQualifiersAndReferencesFromTuple;
+
+template <typename... U>
+struct RemoveQualifiersAndReferencesFromTuple<std::tuple<U...>> {
+  using type =
+      std::tuple<typename std::remove_cv_t<std::remove_reference_t<U>>...>;
+};
+
+template <typename T, int kNumBases = -1>
+constexpr int NumFields() {
+  if constexpr (std::is_empty_v<T>) {
+    return 0;
+  } else if constexpr (std::is_aggregate_v<T>) {
+    if constexpr (kNumBases == -1) {
+      constexpr auto num_bases = aggregate_internal::NumBases<T>();
+      static_assert(num_bases.has_value(),
+                    "This library can only detect the number of bases when the "
+                    "type is non-empty and has exactly 0 or 1 base classes. "
+                    "However, the type has >= 2 bases.");
+      return aggregate_internal::NumInitializers<T>() - num_bases.value();
+    } else {
+      return aggregate_internal::NumInitializers<T>() - kNumBases;
+    }
+  } else {
+    return -1;
+  }
+}
+
+// Structured binding declarations are weird in that they produce the same
+// bindings whether the object is an rvalue or lvalue. Hence we add reference
+// qualifiers ourselves.
+
+struct FieldGetter {
+  struct Error {};
+  template <int kNumBases, int kFieldCount, typename T>
+  constexpr static auto Unpack(T&& t) {
+    static_assert(
+        kNumBases == -1 || kNumBases == 0 || kNumBases == 1,
+        "Unpack() only supports aggregate types that have either no "
+        "base class or 1 empty base class (absl::Extend). You can "
+        "also set the number of bases to -1 to let the library try "
+        "to detect the number of bases. All other values are invalid.");
+    if constexpr (kFieldCount == -1) {
+      constexpr int kNumFields = NumFields<std::decay_t<T>, kNumBases>();
+      if constexpr (kNumFields != -1) {
+        return Unpack<kNumBases, kNumFields>(std::forward<T>(t));
+      } else {
+        return Error{};
+      }
+    } else if constexpr (kFieldCount == 0) {
+      return std::make_tuple();
+    } else if constexpr (kFieldCount == 1) {
+      auto&& [f0] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0));
+    } else if constexpr (kFieldCount == 2) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1));
+    } else if constexpr (kFieldCount == 3) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2));
+    } else if constexpr (kFieldCount == 4) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3));
+    } else if constexpr (kFieldCount == 5) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4));
+    } else if constexpr (kFieldCount == 6) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5));
+    } else if constexpr (kFieldCount == 7) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6));
+    } else if constexpr (kFieldCount == 8) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7));
+    } else if constexpr (kFieldCount == 9) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8));
+    } else if constexpr (kFieldCount == 10) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9));
+    } else if constexpr (kFieldCount == 11) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10));
+    } else if constexpr (kFieldCount == 12) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11));
+    } else if constexpr (kFieldCount == 13) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12));
+    } else if constexpr (kFieldCount == 14) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13));
+    } else if constexpr (kFieldCount == 15) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14));
+    } else if constexpr (kFieldCount == 16) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
+              f15] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15));
+    } else if constexpr (kFieldCount == 17) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16));
+    } else if constexpr (kFieldCount == 18) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17));
+    } else if constexpr (kFieldCount == 19) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18));
+    } else if constexpr (kFieldCount == 20) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19));
+    } else if constexpr (kFieldCount == 21) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20));
+    } else if constexpr (kFieldCount == 22) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21));
+    } else if constexpr (kFieldCount == 23) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22));
+    } else if constexpr (kFieldCount == 24) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23));
+    } else if constexpr (kFieldCount == 25) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24));
+    } else if constexpr (kFieldCount == 26) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25));
+    } else if constexpr (kFieldCount == 27) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26));
+    } else if constexpr (kFieldCount == 28) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27));
+    } else if constexpr (kFieldCount == 29) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28] =
+          t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28));
+    } else if constexpr (kFieldCount == 30) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29));
+    } else if constexpr (kFieldCount == 31) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30));
+    } else if constexpr (kFieldCount == 32) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31));
+    } else if constexpr (kFieldCount == 33) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32));
+    } else if constexpr (kFieldCount == 34) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33));
+    } else if constexpr (kFieldCount == 35) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34));
+    } else if constexpr (kFieldCount == 36) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35));
+    } else if constexpr (kFieldCount == 37) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36));
+    } else if constexpr (kFieldCount == 38) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37));
+    } else if constexpr (kFieldCount == 39) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38));
+    } else if constexpr (kFieldCount == 40) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39));
+    } else if constexpr (kFieldCount == 41) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40));
+    } else if constexpr (kFieldCount == 42) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41] =
+          t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40),
+                                   CorrectQualifiers<T, decltype(f41)>(f41));
+    } else if constexpr (kFieldCount == 43) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41,
+              f42] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40),
+                                   CorrectQualifiers<T, decltype(f41)>(f41),
+                                   CorrectQualifiers<T, decltype(f42)>(f42));
+    } else if constexpr (kFieldCount == 44) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41,
+              f42, f43] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40),
+                                   CorrectQualifiers<T, decltype(f41)>(f41),
+                                   CorrectQualifiers<T, decltype(f42)>(f42),
+                                   CorrectQualifiers<T, decltype(f43)>(f43));
+    } else if constexpr (kFieldCount == 45) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41,
+              f42, f43, f44] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40),
+                                   CorrectQualifiers<T, decltype(f41)>(f41),
+                                   CorrectQualifiers<T, decltype(f42)>(f42),
+                                   CorrectQualifiers<T, decltype(f43)>(f43),
+                                   CorrectQualifiers<T, decltype(f44)>(f44));
+    } else if constexpr (kFieldCount == 46) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41,
+              f42, f43, f44, f45] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40),
+                                   CorrectQualifiers<T, decltype(f41)>(f41),
+                                   CorrectQualifiers<T, decltype(f42)>(f42),
+                                   CorrectQualifiers<T, decltype(f43)>(f43),
+                                   CorrectQualifiers<T, decltype(f44)>(f44),
+                                   CorrectQualifiers<T, decltype(f45)>(f45));
+    } else if constexpr (kFieldCount == 47) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41,
+              f42, f43, f44, f45, f46] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40),
+                                   CorrectQualifiers<T, decltype(f41)>(f41),
+                                   CorrectQualifiers<T, decltype(f42)>(f42),
+                                   CorrectQualifiers<T, decltype(f43)>(f43),
+                                   CorrectQualifiers<T, decltype(f44)>(f44),
+                                   CorrectQualifiers<T, decltype(f45)>(f45),
+                                   CorrectQualifiers<T, decltype(f46)>(f46));
+    } else if constexpr (kFieldCount == 48) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41,
+              f42, f43, f44, f45, f46, f47] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40),
+                                   CorrectQualifiers<T, decltype(f41)>(f41),
+                                   CorrectQualifiers<T, decltype(f42)>(f42),
+                                   CorrectQualifiers<T, decltype(f43)>(f43),
+                                   CorrectQualifiers<T, decltype(f44)>(f44),
+                                   CorrectQualifiers<T, decltype(f45)>(f45),
+                                   CorrectQualifiers<T, decltype(f46)>(f46),
+                                   CorrectQualifiers<T, decltype(f47)>(f47));
+    } else if constexpr (kFieldCount == 49) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41,
+              f42, f43, f44, f45, f46, f47, f48] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40),
+                                   CorrectQualifiers<T, decltype(f41)>(f41),
+                                   CorrectQualifiers<T, decltype(f42)>(f42),
+                                   CorrectQualifiers<T, decltype(f43)>(f43),
+                                   CorrectQualifiers<T, decltype(f44)>(f44),
+                                   CorrectQualifiers<T, decltype(f45)>(f45),
+                                   CorrectQualifiers<T, decltype(f46)>(f46),
+                                   CorrectQualifiers<T, decltype(f47)>(f47),
+                                   CorrectQualifiers<T, decltype(f48)>(f48));
+    } else if constexpr (kFieldCount == 50) {
+      auto&& [f0,  // Did you forget `friend absl::EnableExtensions`?
+              f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15,
+              f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, f27, f28,
+              f29, f30, f31, f32, f33, f34, f35, f36, f37, f38, f39, f40, f41,
+              f42, f43, f44, f45, f46, f47, f48, f49] = t;
+      return std::forward_as_tuple(CorrectQualifiers<T, decltype(f0)>(f0),
+                                   CorrectQualifiers<T, decltype(f1)>(f1),
+                                   CorrectQualifiers<T, decltype(f2)>(f2),
+                                   CorrectQualifiers<T, decltype(f3)>(f3),
+                                   CorrectQualifiers<T, decltype(f4)>(f4),
+                                   CorrectQualifiers<T, decltype(f5)>(f5),
+                                   CorrectQualifiers<T, decltype(f6)>(f6),
+                                   CorrectQualifiers<T, decltype(f7)>(f7),
+                                   CorrectQualifiers<T, decltype(f8)>(f8),
+                                   CorrectQualifiers<T, decltype(f9)>(f9),
+                                   CorrectQualifiers<T, decltype(f10)>(f10),
+                                   CorrectQualifiers<T, decltype(f11)>(f11),
+                                   CorrectQualifiers<T, decltype(f12)>(f12),
+                                   CorrectQualifiers<T, decltype(f13)>(f13),
+                                   CorrectQualifiers<T, decltype(f14)>(f14),
+                                   CorrectQualifiers<T, decltype(f15)>(f15),
+                                   CorrectQualifiers<T, decltype(f16)>(f16),
+                                   CorrectQualifiers<T, decltype(f17)>(f17),
+                                   CorrectQualifiers<T, decltype(f18)>(f18),
+                                   CorrectQualifiers<T, decltype(f19)>(f19),
+                                   CorrectQualifiers<T, decltype(f20)>(f20),
+                                   CorrectQualifiers<T, decltype(f21)>(f21),
+                                   CorrectQualifiers<T, decltype(f22)>(f22),
+                                   CorrectQualifiers<T, decltype(f23)>(f23),
+                                   CorrectQualifiers<T, decltype(f24)>(f24),
+                                   CorrectQualifiers<T, decltype(f25)>(f25),
+                                   CorrectQualifiers<T, decltype(f26)>(f26),
+                                   CorrectQualifiers<T, decltype(f27)>(f27),
+                                   CorrectQualifiers<T, decltype(f28)>(f28),
+                                   CorrectQualifiers<T, decltype(f29)>(f29),
+                                   CorrectQualifiers<T, decltype(f30)>(f30),
+                                   CorrectQualifiers<T, decltype(f31)>(f31),
+                                   CorrectQualifiers<T, decltype(f32)>(f32),
+                                   CorrectQualifiers<T, decltype(f33)>(f33),
+                                   CorrectQualifiers<T, decltype(f34)>(f34),
+                                   CorrectQualifiers<T, decltype(f35)>(f35),
+                                   CorrectQualifiers<T, decltype(f36)>(f36),
+                                   CorrectQualifiers<T, decltype(f37)>(f37),
+                                   CorrectQualifiers<T, decltype(f38)>(f38),
+                                   CorrectQualifiers<T, decltype(f39)>(f39),
+                                   CorrectQualifiers<T, decltype(f40)>(f40),
+                                   CorrectQualifiers<T, decltype(f41)>(f41),
+                                   CorrectQualifiers<T, decltype(f42)>(f42),
+                                   CorrectQualifiers<T, decltype(f43)>(f43),
+                                   CorrectQualifiers<T, decltype(f44)>(f44),
+                                   CorrectQualifiers<T, decltype(f45)>(f45),
+                                   CorrectQualifiers<T, decltype(f46)>(f46),
+                                   CorrectQualifiers<T, decltype(f47)>(f47),
+                                   CorrectQualifiers<T, decltype(f48)>(f48),
+                                   CorrectQualifiers<T, decltype(f49)>(f49));
+    } else {
+      static_assert(
+          kFieldCount <= 50,
+          "We are unlikely to extend support beyond 50 fields, both because of "
+          "the compile-time cost associated with doing so, and because we "
+          "believe structs this large are probably better off grouped into "
+          "well-designed smaller structs that can be nested.");
+    }
+  }
+};
+
+template <typename T,
+          typename = std::enable_if_t<!std::is_same_v<T, FieldGetter::Error>>>
+T NotAnError(T);
+
+// Given a reference to an aggregate `T`, constructs a tuple of references to
+// the fields in the aggregate. This only works for types that have either no
+// base class or 1 empty base class.
+template <typename T>
+auto Unpack(T&& t) -> decltype(NotAnError(
+    FieldGetter::Unpack<
+        0, absl::aggregate_internal::NumFields<std::decay_t<T>>(), T>(
+        std::forward<T>(t)))) {
+  return FieldGetter::Unpack<
+      0, absl::aggregate_internal::NumFields<std::decay_t<T>>(), T>(
+      std::forward<T>(t));
+}
+
+}  // namespace aggregate_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_EXTEND_INTERNAL_AGGREGATE_H_
diff --git a/absl/extend/internal/aggregate_test.cc b/absl/extend/internal/aggregate_test.cc
new file mode 100644
index 0000000..30316c9
--- /dev/null
+++ b/absl/extend/internal/aggregate_test.cc
@@ -0,0 +1,867 @@
+// 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/extend/internal/aggregate.h"
+
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace aggregate_internal {
+namespace {
+
+TEST(Qualifiers, Collapse) {
+  EXPECT_EQ(kRef | kRefRef, kRef);
+  EXPECT_NE(kConst, kVolatile);
+  EXPECT_NE(kConst, kRef);
+  EXPECT_NE(kConst, kRefRef);
+  EXPECT_NE(kVolatile, kRef);
+  EXPECT_NE(kVolatile, kRefRef);
+  EXPECT_NE(kRef, kRefRef);
+}
+
+TEST(ExtractQualifiers, Works) {
+  EXPECT_EQ(ExtractQualifiers<int>(), 0);
+  EXPECT_EQ(ExtractQualifiers<int&>(), kRef);
+  EXPECT_EQ(ExtractQualifiers<int&&>(), kRefRef);
+  EXPECT_EQ(ExtractQualifiers<const int>(), kConst);
+  EXPECT_EQ(ExtractQualifiers<const int&>(), kConst | kRef);
+  EXPECT_EQ(ExtractQualifiers<const int&&>(), kConst | kRefRef);
+  EXPECT_EQ(ExtractQualifiers<volatile int>(), kVolatile);
+  EXPECT_EQ(ExtractQualifiers<volatile int&>(), kVolatile | kRef);
+  EXPECT_EQ(ExtractQualifiers<volatile int&&>(), kVolatile | kRefRef);
+  EXPECT_EQ(ExtractQualifiers<volatile const int>(), kVolatile | kConst);
+  EXPECT_EQ(ExtractQualifiers<volatile const int&>(),
+            kVolatile | kConst | kRef);
+  EXPECT_EQ(ExtractQualifiers<volatile const int&&>(),
+            kVolatile | kConst | kRefRef);
+}
+
+TEST(ApplyQualifiers, OnBareType) {
+  EXPECT_TRUE((std::is_same_v<typename ApplyQualifiers<int, 0>::type, int>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<int, kRef>::type, int&>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<int, kRefRef>::type, int&&>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<int, kConst>::type, const int>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<int, kConst | kRef>::type,
+                      const int&>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<int, kConst | kRefRef>::type,
+                      const int&&>));
+  EXPECT_TRUE((std::is_same_v<typename ApplyQualifiers<int, kVolatile>::type,
+                              volatile int>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<int, kVolatile | kRef>::type,
+                      volatile int&>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<int, kVolatile | kRefRef>::type,
+                      volatile int&&>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<int, kVolatile | kConst>::type,
+                      volatile const int>));
+  EXPECT_TRUE((std::is_same_v<
+               typename ApplyQualifiers<int, kVolatile | kConst | kRef>::type,
+               volatile const int&>));
+  EXPECT_TRUE(
+      (std::is_same_v<
+          typename ApplyQualifiers<int, kVolatile | kConst | kRefRef>::type,
+          volatile const int&&>));
+}
+
+TEST(ApplyQualifiers, OnConstType) {
+  EXPECT_TRUE((
+      std::is_same_v<typename ApplyQualifiers<const int, 0>::type, const int>));
+  EXPECT_TRUE((std::is_same_v<typename ApplyQualifiers<const int, kRef>::type,
+                              const int&>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<const int, kRefRef>::type,
+                      const int&&>));
+  EXPECT_TRUE((std::is_same_v<typename ApplyQualifiers<const int, kConst>::type,
+                              const int>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<const int, kConst | kRef>::type,
+                      const int&>));
+  EXPECT_TRUE((std::is_same_v<
+               typename ApplyQualifiers<const int, kConst | kRefRef>::type,
+               const int&&>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<const int, kVolatile>::type,
+                      const volatile int>));
+  EXPECT_TRUE((std::is_same_v<
+               typename ApplyQualifiers<const int, kVolatile | kRef>::type,
+               const volatile int&>));
+  EXPECT_TRUE((std::is_same_v<
+               typename ApplyQualifiers<const int, kVolatile | kRefRef>::type,
+               const volatile int&&>));
+  EXPECT_TRUE((std::is_same_v<
+               typename ApplyQualifiers<const int, kVolatile | kConst>::type,
+               volatile const int>));
+  EXPECT_TRUE(
+      (std::is_same_v<
+          typename ApplyQualifiers<const int, kVolatile | kConst | kRef>::type,
+          volatile const int&>));
+  EXPECT_TRUE(
+      (std::is_same_v<typename ApplyQualifiers<const int, kVolatile | kConst |
+                                                              kRefRef>::type,
+                      volatile const int&&>));
+}
+
+TEST(CorrectQualifiers, Type) {
+  struct A {
+    int val;
+    int&& rval;
+    const int cval;
+    const int& clval;
+    const int&& crval;
+  };
+
+  A a{
+      3,                                // .val
+      static_cast<int&&>(a.val),        // .rval
+      3,                                // .cval
+      a.cval,                           // .clval
+      static_cast<const int&&>(a.cval)  // .crval
+  };
+  auto&& [v, r, c, cl, cr] = a;
+  testing::StaticAssertTypeEq<decltype(CorrectQualifiers<A, decltype(v)>(v)),
+                              int&&>();
+  testing::StaticAssertTypeEq<decltype(CorrectQualifiers<A, decltype(r)>(r)),
+                              int&&>();
+  testing::StaticAssertTypeEq<decltype(CorrectQualifiers<A, decltype(c)>(c)),
+                              const int&&>();
+  testing::StaticAssertTypeEq<decltype(CorrectQualifiers<A, decltype(cl)>(cl)),
+                              const int&>();
+
+  testing::StaticAssertTypeEq<decltype(CorrectQualifiers<A&, decltype(v)>(v)),
+                              int&>();
+  testing::StaticAssertTypeEq<decltype(CorrectQualifiers<A&, decltype(r)>(r)),
+                              int&&>();
+  testing::StaticAssertTypeEq<decltype(CorrectQualifiers<A&, decltype(c)>(c)),
+                              const int&>();
+  testing::StaticAssertTypeEq<decltype(CorrectQualifiers<A&, decltype(cl)>(cl)),
+                              const int&>();
+
+  testing::StaticAssertTypeEq<
+      decltype(CorrectQualifiers<const A&, decltype(v)>(v)), const int&>();
+  testing::StaticAssertTypeEq<
+      decltype(CorrectQualifiers<const A&, decltype(r)>(r)), int&&>();
+}
+
+TEST(RemoveQualifiersAndReferencesFromTuple, Type) {
+  EXPECT_TRUE(
+      (std::is_same_v<RemoveQualifiersAndReferencesFromTuple<std::tuple<
+                          int, int&, const int&, volatile const int&>>::type,
+                      std::tuple<int, int, int, int>>));
+}
+
+TEST(Unpack, Basic) {
+  struct A1 {
+    int a;
+  };
+  struct A2 {
+    int a;
+    int b;
+  };
+  struct A3 {
+    int a;
+    int&& b;
+  };
+
+  {
+    A1 a;
+    auto [f1] = Unpack(a);
+    EXPECT_EQ(&f1, &a.a);
+  }
+
+  {
+    A2 a;
+    auto [f1, f2] = Unpack(a);
+    EXPECT_EQ(&f1, &a.a);
+    EXPECT_EQ(&f2, &a.b);
+  }
+
+  {
+    int b = 0;
+    A3 a{0, std::move(b)};  // NOLINT(performance-move-const-arg)
+    auto [f1, f2] = Unpack(a);
+    EXPECT_EQ(&f1, &a.a);
+    EXPECT_EQ(&f2, &a.b);
+  }
+}
+
+TEST(Unpack, Types) {
+  struct A3 {
+    int field_v;
+    const int& field_l;
+    int&& field_r;
+  };
+
+  int x = 0, y = 0;
+  A3 my_struct{0, x, std::move(y)};  // NOLINT(performance-move-const-arg)
+  auto unpacked = Unpack(my_struct);
+  const auto& const_lvalue_ref = my_struct;
+  auto unpacked_const_lvalue_ref = Unpack(const_lvalue_ref);
+  auto unpacked_rvalue_ref = Unpack(std::move(my_struct));
+  testing::StaticAssertTypeEq<decltype(unpacked),
+                              std::tuple<int&, const int&, int&&>>();
+  testing::StaticAssertTypeEq<decltype(unpacked_const_lvalue_ref),
+                              std::tuple<const int&, const int&, int&&>>();
+  testing::StaticAssertTypeEq<decltype(unpacked_rvalue_ref),
+                              std::tuple<int&&, const int&, int&&>>();
+}
+
+TEST(Unpack, Const) {
+  struct A1 {
+    const int a;
+  };
+  struct A2 {
+    const int a;
+    const int b;
+  };
+  struct A3 {
+    const int a;
+    const int& b;
+    int&& c;
+  };
+
+  {
+    A1 a{};
+    auto [f1] = Unpack(a);
+    EXPECT_EQ(&f1, &a.a);
+  }
+
+  {
+    A2 a{};
+    auto [f1, f2] = Unpack(a);
+    EXPECT_EQ(&f1, &a.a);
+    EXPECT_EQ(&f2, &a.b);
+  }
+
+  {
+    int b = 0, c = 0;
+    A3 a{0, b, std::move(c)};  // NOLINT(performance-move-const-arg)
+    auto [f1, f2, f3] = Unpack(a);
+    EXPECT_EQ(&f1, &a.a);
+    EXPECT_EQ(&f2, &a.b);
+    EXPECT_EQ(&f3, &a.c);
+  }
+}
+
+TEST(Unpack, BaseClass) {
+  struct Base {};
+  struct A2 : Base {
+    int a1, a2;
+  };
+
+  A2 a;
+  auto [f1, f2] = Unpack(a);
+  EXPECT_EQ(&f1, &a.a1);
+  EXPECT_EQ(&f2, &a.a2);
+}
+
+// Not supported on older compilers due to mysterious compiler bug(s) that are
+// somewhat difficult to track down. (See b/478243383.)
+//
+// TODO(b/479561657): Enable this unconditionally.
+#if !defined(_MSC_VER) || _MSC_VER >= 1939
+TEST(Unpack, Immovable) {
+  struct Immovable {
+    Immovable() = default;
+    Immovable(Immovable&&) = delete;
+  };
+  struct A2 {
+    const Immovable& a;
+    Immovable&& b;
+  };
+
+  Immovable i1, i2;
+  A2 a{i1, std::move(i2)};
+  auto [f1, f2] = Unpack(a);
+  EXPECT_EQ(&f1, &a.a);
+  EXPECT_EQ(&f2, &a.b);
+}
+#endif  // _MSC_VER >= 1939
+
+TEST(Unpack, Empty) {
+  struct Empty {};
+  EXPECT_TRUE((std::is_same_v<std::tuple<>, decltype(Unpack(Empty{}))>));
+  Empty lvalue_empty;
+  EXPECT_TRUE((std::is_same_v<std::tuple<>, decltype(Unpack(lvalue_empty))>));
+
+  struct EmptyWithBase : Empty {};
+  EXPECT_TRUE(
+      (std::is_same_v<std::tuple<>, decltype(Unpack(EmptyWithBase{}))>));
+}
+
+TEST(Unpack, Autodetect) {
+  struct NoBases {
+    int i = 7;
+  } no_bases;
+  auto [i2] = Unpack(no_bases);
+  EXPECT_EQ(i2, 7);
+
+  struct Base {};
+  struct OneBase : Base {
+    int j = 17;
+  } one_base;
+  auto [j2] = Unpack(one_base);
+  EXPECT_EQ(j2, 17);
+
+  constexpr auto try_unpack =
+      [](auto&& v) -> decltype(NumBases(std::forward<decltype(v)>(v))) {};
+
+  struct Base2 {};
+  struct TwoBases : Base, Base2 {
+    int k;
+  };
+  EXPECT_FALSE((std::is_invocable_v<decltype(try_unpack), TwoBases>));
+}
+
+TEST(Unpack, FailsSubstitution) {
+  struct Aggregate {
+    int i;
+  };
+  struct NonAggregate {
+    explicit NonAggregate(int) {}
+    int i;
+  };
+
+  const auto unpack =
+      [](auto&& v) -> decltype(Unpack(std::forward<decltype(v)>(v))) {};
+  EXPECT_TRUE((std::is_invocable_v<decltype(unpack), Aggregate>));
+  EXPECT_FALSE((std::is_invocable_v<decltype(unpack), NonAggregate>));
+}
+
+// Not supported on older compilers due to mysterious compiler bug(s) that are
+// somewhat difficult to track down. (See b/478243383.)
+//
+// TODO(b/479561657): Enable this unconditionally.
+#if !defined(_MSC_VER) || _MSC_VER >= 1939
+template <int N, class T>
+void CheckTupleElementsEqualToIndex(const T& t) {
+  if constexpr (N > 0) {
+    EXPECT_EQ(std::get<N - 1>(t), N - 1);
+    CheckTupleElementsEqualToIndex<N - 1>(t);
+  }
+}
+
+TEST(Unpack, CorrectOrder1) {
+  struct S1 {
+    int a0 = 0;
+  };
+  CheckTupleElementsEqualToIndex<1>(Unpack(S1()));
+}
+
+TEST(Unpack, CorrectOrder2) {
+  struct S2 {
+    int a0 = 0, a1 = 1;
+  };
+  CheckTupleElementsEqualToIndex<2>(Unpack(S2()));
+}
+
+TEST(Unpack, CorrectOrder3) {
+  struct S3 {
+    int a0 = 0, a1 = 1, a2 = 2;
+  };
+  CheckTupleElementsEqualToIndex<3>(Unpack(S3()));
+}
+
+TEST(Unpack, CorrectOrder4) {
+  struct S4 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3;
+  };
+  CheckTupleElementsEqualToIndex<4>(Unpack(S4()));
+}
+
+TEST(Unpack, CorrectOrder5) {
+  struct S5 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4;
+  };
+  CheckTupleElementsEqualToIndex<5>(Unpack(S5()));
+}
+
+TEST(Unpack, CorrectOrder6) {
+  struct S6 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5;
+  };
+  CheckTupleElementsEqualToIndex<6>(Unpack(S6()));
+}
+
+TEST(Unpack, CorrectOrder7) {
+  struct S7 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6;
+  };
+  CheckTupleElementsEqualToIndex<7>(Unpack(S7()));
+}
+
+TEST(Unpack, CorrectOrder8) {
+  struct S8 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7;
+  };
+  CheckTupleElementsEqualToIndex<8>(Unpack(S8()));
+}
+
+TEST(Unpack, CorrectOrder9) {
+  struct S9 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8;
+  };
+  CheckTupleElementsEqualToIndex<9>(Unpack(S9()));
+}
+
+TEST(Unpack, CorrectOrder10) {
+  struct S10 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9;
+  };
+  CheckTupleElementsEqualToIndex<10>(Unpack(S10()));
+}
+
+TEST(Unpack, CorrectOrder11) {
+  struct S11 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10;
+  };
+  CheckTupleElementsEqualToIndex<11>(Unpack(S11()));
+}
+
+TEST(Unpack, CorrectOrder12) {
+  struct S12 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11;
+  };
+  CheckTupleElementsEqualToIndex<12>(Unpack(S12()));
+}
+
+TEST(Unpack, CorrectOrder13) {
+  struct S13 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12;
+  };
+  CheckTupleElementsEqualToIndex<13>(Unpack(S13()));
+}
+
+TEST(Unpack, CorrectOrder14) {
+  struct S14 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13;
+  };
+  CheckTupleElementsEqualToIndex<14>(Unpack(S14()));
+}
+
+TEST(Unpack, CorrectOrder15) {
+  struct S15 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14;
+  };
+  CheckTupleElementsEqualToIndex<15>(Unpack(S15()));
+}
+
+TEST(Unpack, CorrectOrder16) {
+  struct S16 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15;
+  };
+  CheckTupleElementsEqualToIndex<16>(Unpack(S16()));
+}
+
+TEST(Unpack, CorrectOrder17) {
+  struct S17 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16;
+  };
+  CheckTupleElementsEqualToIndex<17>(Unpack(S17()));
+}
+
+TEST(Unpack, CorrectOrder18) {
+  struct S18 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17;
+  };
+  CheckTupleElementsEqualToIndex<18>(Unpack(S18()));
+}
+
+TEST(Unpack, CorrectOrder19) {
+  struct S19 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18;
+  };
+  CheckTupleElementsEqualToIndex<19>(Unpack(S19()));
+}
+
+TEST(Unpack, CorrectOrder20) {
+  struct S20 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19;
+  };
+  CheckTupleElementsEqualToIndex<20>(Unpack(S20()));
+}
+
+TEST(Unpack, CorrectOrder21) {
+  struct S21 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20;
+  };
+  CheckTupleElementsEqualToIndex<21>(Unpack(S21()));
+}
+
+TEST(Unpack, CorrectOrder22) {
+  struct S22 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21;
+  };
+  CheckTupleElementsEqualToIndex<22>(Unpack(S22()));
+}
+
+TEST(Unpack, CorrectOrder23) {
+  struct S23 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22;
+  };
+  CheckTupleElementsEqualToIndex<23>(Unpack(S23()));
+}
+
+TEST(Unpack, CorrectOrder24) {
+  struct S24 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23;
+  };
+  CheckTupleElementsEqualToIndex<24>(Unpack(S24()));
+}
+
+TEST(Unpack, CorrectOrder25) {
+  struct S25 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24;
+  };
+  CheckTupleElementsEqualToIndex<25>(Unpack(S25()));
+}
+
+TEST(Unpack, CorrectOrder26) {
+  struct S26 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25;
+  };
+  CheckTupleElementsEqualToIndex<26>(Unpack(S26()));
+}
+
+TEST(Unpack, CorrectOrder27) {
+  struct S27 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26;
+  };
+  CheckTupleElementsEqualToIndex<27>(Unpack(S27()));
+}
+
+TEST(Unpack, CorrectOrder28) {
+  struct S28 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27;
+  };
+  CheckTupleElementsEqualToIndex<28>(Unpack(S28()));
+}
+
+TEST(Unpack, CorrectOrder29) {
+  struct S29 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28;
+  };
+  CheckTupleElementsEqualToIndex<29>(Unpack(S29()));
+}
+
+TEST(Unpack, CorrectOrder30) {
+  struct S30 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29;
+  };
+  CheckTupleElementsEqualToIndex<30>(Unpack(S30()));
+}
+
+TEST(Unpack, CorrectOrder31) {
+  struct S31 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30;
+  };
+  CheckTupleElementsEqualToIndex<31>(Unpack(S31()));
+}
+
+TEST(Unpack, CorrectOrder32) {
+  struct S32 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31;
+  };
+  CheckTupleElementsEqualToIndex<32>(Unpack(S32()));
+}
+
+#ifndef _MSC_VER  // MSVC constexpr evaluation hits a default limit
+TEST(Unpack, CorrectOrder33) {
+  struct S33 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32;
+  };
+  CheckTupleElementsEqualToIndex<33>(Unpack(S33()));
+}
+
+TEST(Unpack, CorrectOrder34) {
+  struct S34 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33;
+  };
+  CheckTupleElementsEqualToIndex<34>(Unpack(S34()));
+}
+
+TEST(Unpack, CorrectOrder35) {
+  struct S35 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34;
+  };
+  CheckTupleElementsEqualToIndex<35>(Unpack(S35()));
+}
+
+TEST(Unpack, CorrectOrder36) {
+  struct S36 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35;
+  };
+  CheckTupleElementsEqualToIndex<36>(Unpack(S36()));
+}
+
+TEST(Unpack, CorrectOrder37) {
+  struct S37 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36;
+  };
+  CheckTupleElementsEqualToIndex<37>(Unpack(S37()));
+}
+
+TEST(Unpack, CorrectOrder38) {
+  struct S38 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37;
+  };
+  CheckTupleElementsEqualToIndex<38>(Unpack(S38()));
+}
+
+TEST(Unpack, CorrectOrder39) {
+  struct S39 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38;
+  };
+  CheckTupleElementsEqualToIndex<39>(Unpack(S39()));
+}
+
+TEST(Unpack, CorrectOrder40) {
+  struct S40 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39;
+  };
+  CheckTupleElementsEqualToIndex<40>(Unpack(S40()));
+}
+
+TEST(Unpack, CorrectOrder41) {
+  struct S41 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40;
+  };
+  CheckTupleElementsEqualToIndex<41>(Unpack(S41()));
+}
+
+TEST(Unpack, CorrectOrder42) {
+  struct S42 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40, a41 = 41;
+  };
+  CheckTupleElementsEqualToIndex<42>(Unpack(S42()));
+}
+
+TEST(Unpack, CorrectOrder43) {
+  struct S43 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40, a41 = 41, a42 = 42;
+  };
+  CheckTupleElementsEqualToIndex<43>(Unpack(S43()));
+}
+
+TEST(Unpack, CorrectOrder44) {
+  struct S44 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40, a41 = 41, a42 = 42, a43 = 43;
+  };
+  CheckTupleElementsEqualToIndex<44>(Unpack(S44()));
+}
+
+TEST(Unpack, CorrectOrder45) {
+  struct S45 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40, a41 = 41, a42 = 42, a43 = 43,
+        a44 = 44;
+  };
+  CheckTupleElementsEqualToIndex<45>(Unpack(S45()));
+}
+
+TEST(Unpack, CorrectOrder46) {
+  struct S46 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40, a41 = 41, a42 = 42, a43 = 43,
+        a44 = 44, a45 = 45;
+  };
+  CheckTupleElementsEqualToIndex<46>(Unpack(S46()));
+}
+
+TEST(Unpack, CorrectOrder47) {
+  struct S47 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40, a41 = 41, a42 = 42, a43 = 43,
+        a44 = 44, a45 = 45, a46 = 46;
+  };
+  CheckTupleElementsEqualToIndex<47>(Unpack(S47()));
+}
+
+TEST(Unpack, CorrectOrder48) {
+  struct S48 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40, a41 = 41, a42 = 42, a43 = 43,
+        a44 = 44, a45 = 45, a46 = 46, a47 = 47;
+  };
+  CheckTupleElementsEqualToIndex<48>(Unpack(S48()));
+}
+
+TEST(Unpack, CorrectOrder49) {
+  struct S49 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40, a41 = 41, a42 = 42, a43 = 43,
+        a44 = 44, a45 = 45, a46 = 46, a47 = 47, a48 = 48;
+  };
+  CheckTupleElementsEqualToIndex<49>(Unpack(S49()));
+}
+
+TEST(Unpack, CorrectOrder50) {
+  struct S50 {
+    int a0 = 0, a1 = 1, a2 = 2, a3 = 3, a4 = 4, a5 = 5, a6 = 6, a7 = 7, a8 = 8,
+        a9 = 9, a10 = 10, a11 = 11, a12 = 12, a13 = 13, a14 = 14, a15 = 15,
+        a16 = 16, a17 = 17, a18 = 18, a19 = 19, a20 = 20, a21 = 21, a22 = 22,
+        a23 = 23, a24 = 24, a25 = 25, a26 = 26, a27 = 27, a28 = 28, a29 = 29,
+        a30 = 30, a31 = 31, a32 = 32, a33 = 33, a34 = 34, a35 = 35, a36 = 36,
+        a37 = 37, a38 = 38, a39 = 39, a40 = 40, a41 = 41, a42 = 42, a43 = 43,
+        a44 = 44, a45 = 45, a46 = 46, a47 = 47, a48 = 48, a49 = 49;
+  };
+  CheckTupleElementsEqualToIndex<50>(Unpack(S50()));
+}
+
+// When adding support for more fields, add corresponding CorrectOrderNN test(s)
+// here.
+#endif  // _MSC_VER
+#endif  // _MSC_VER >= 1939
+
+}  // namespace
+}  // namespace aggregate_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/extend/internal/dependencies.h b/absl/extend/internal/dependencies.h
new file mode 100644
index 0000000..572f7a3
--- /dev/null
+++ b/absl/extend/internal/dependencies.h
@@ -0,0 +1,83 @@
+// 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.
+
+#ifndef ABSL_EXTEND_INTERNAL_DEPENDENCIES_H_
+#define ABSL_EXTEND_INTERNAL_DEPENDENCIES_H_
+
+#include <type_traits>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace dependencies_internal {
+
+// Dependencies is a meta-function which constructs a collection which
+// recursively looks through types and either adds them to the list, or, if they
+// have a `using deps = void(...);` takes those listed dependencies as well. For
+// example, given:
+//
+// struct X {};
+// struct Y {};
+// struct A {};
+// struct B { using deps = void(A, X); };
+// struct C { using deps = void(A, Y); };
+// struct D { using deps = void(B, C); };
+//
+// Dependencies<D>() will return a function pointer returning void and accepting
+// arguments of types A, B, C, D, X, and Y in some unspecified order each
+// exactly once, and no other types.
+template <typename T>
+auto GetDependencies(T*) -> typename T::deps*;
+auto GetDependencies(void*) -> void (*)();
+
+template <typename FnPtr, typename... Ts>
+struct CombineDeps {};
+template <typename... Ps, typename... Ts>
+struct CombineDeps<void (*)(Ps...), Ts...> {
+  using type = void (*)(Ps..., Ts...);
+};
+
+template <typename... Processed>
+auto DependenciesImpl(void (*)(), void (*)(Processed...)) {
+  return static_cast<void (*)(Processed...)>(nullptr);
+}
+
+template <typename T, typename... Ts, typename... Processed>
+auto DependenciesImpl(void (*)(T, Ts...), void (*)(Processed...)) {
+  if constexpr ((std::is_same_v<T, Processed> || ...)) {
+    return DependenciesImpl(static_cast<void (*)(Ts...)>(nullptr),
+                            static_cast<void (*)(Processed...)>(nullptr));
+  } else {
+    using deps = decltype(GetDependencies(static_cast<T*>(nullptr)));
+    if constexpr (std ::is_same_v<deps, void (*)()>) {
+      return DependenciesImpl(static_cast<void (*)(Ts...)>(nullptr),
+                              static_cast<void (*)(T, Processed...)>(nullptr));
+    } else {
+      return DependenciesImpl(
+          static_cast<typename CombineDeps<deps, Ts...>::type>(nullptr),
+          static_cast<void (*)(T, Processed...)>(nullptr));
+    }
+  }
+}
+
+template <typename... Ts>
+using Dependencies = decltype(DependenciesImpl(
+    static_cast<void (*)(Ts...)>(nullptr), static_cast<void (*)()>(nullptr)));
+
+}  // namespace dependencies_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_EXTEND_INTERNAL_DEPENDENCIES_H_
diff --git a/absl/extend/internal/dependencies_test.cc b/absl/extend/internal/dependencies_test.cc
new file mode 100644
index 0000000..7fa4a13
--- /dev/null
+++ b/absl/extend/internal/dependencies_test.cc
@@ -0,0 +1,117 @@
+// 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/extend/internal/dependencies.h"
+
+#include <type_traits>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace dependencies_internal {
+namespace {
+
+struct X {};
+struct Y {};
+struct A {};
+struct B {
+  using deps = void(A, X);
+};
+struct C {
+  using deps = void(A, Y);
+};
+struct D {
+  using deps = void(B, C);
+};
+
+// We don't actually want to check equality because Dependencies doesn't
+// guarantee any ordering or repetition. Instead, we just want to check
+// containment.
+template <typename, typename>
+struct Contains : std::false_type {};
+
+template <typename Needle, typename... Haystack>
+struct Contains<void(Haystack...), Needle>
+    : std::integral_constant<bool, (std::is_same_v<Needle, Haystack> || ...)> {
+};
+
+template <typename T>
+struct Inspect;
+
+template <typename... Args>
+struct Inspect<void (*)(Args...)> {
+  template <typename T>
+  static constexpr int Count() {
+    return (std::is_same_v<T, Args> + ...);
+  }
+
+  static constexpr int Total() { return sizeof...(Args); }
+};
+
+TEST(Dependencies, Works) {
+  testing::StaticAssertTypeEq<decltype(Dependencies<X>()), void (*)(X)>();
+
+  EXPECT_EQ(Inspect<Dependencies<B>>::Count<A>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<B>>::Count<B>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<B>>::Count<C>(), 0);
+  EXPECT_EQ(Inspect<Dependencies<B>>::Count<D>(), 0);
+  EXPECT_EQ(Inspect<Dependencies<B>>::Count<X>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<B>>::Count<Y>(), 0);
+  EXPECT_EQ(Inspect<Dependencies<B>>::Total(), 3);
+
+  EXPECT_EQ(Inspect<Dependencies<D>>::Count<A>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<D>>::Count<B>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<D>>::Count<C>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<D>>::Count<D>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<D>>::Count<X>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<D>>::Count<Y>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<D>>::Total(), 6);
+}
+
+struct Recursion {
+  using deps = void(Recursion);
+};
+
+template <bool B>
+struct MutualRecursion {
+  using deps = void(MutualRecursion<!B>);
+};
+
+TEST(Dependencies, Cycles) {
+  EXPECT_EQ(Inspect<Dependencies<Recursion>>::Count<Recursion>(), 1);
+  EXPECT_EQ(Inspect<Dependencies<Recursion>>::Total(), 1);
+
+  EXPECT_EQ(Inspect<Dependencies<MutualRecursion<true>>>::Count<
+                MutualRecursion<true>>(),
+            1);
+  EXPECT_EQ(Inspect<Dependencies<MutualRecursion<true>>>::Count<
+                MutualRecursion<false>>(),
+            1);
+  EXPECT_EQ(Inspect<Dependencies<MutualRecursion<false>>>::Total(), 2);
+
+  EXPECT_EQ(Inspect<Dependencies<MutualRecursion<false>>>::Count<
+                MutualRecursion<true>>(),
+            1);
+  EXPECT_EQ(Inspect<Dependencies<MutualRecursion<false>>>::Count<
+                MutualRecursion<false>>(),
+            1);
+  EXPECT_EQ(Inspect<Dependencies<MutualRecursion<true>>>::Total(), 2);
+}
+
+}  // namespace
+}  // namespace dependencies_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/extend/internal/is_tuple_hashable.h b/absl/extend/internal/is_tuple_hashable.h
new file mode 100644
index 0000000..74495b5
--- /dev/null
+++ b/absl/extend/internal/is_tuple_hashable.h
@@ -0,0 +1,45 @@
+// 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.
+
+#ifndef ABSL_EXTEND_INTERNAL_IS_TUPLE_HASHABLE_H_
+#define ABSL_EXTEND_INTERNAL_IS_TUPLE_HASHABLE_H_
+
+#include <tuple>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/hash/hash.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace extend_internal {
+
+// Trait to check if all members of a tuple are absl::Hash-able.
+//
+template <typename T>
+struct IsTupleHashable {};
+
+// TODO(b/185498964): We wouldn't need absl::Hash if the hasher object provided
+// an "is_hashable" trait.
+template <typename... Ts>
+struct IsTupleHashable<std::tuple<Ts...>>
+    : std::integral_constant<bool,
+                             (std::is_constructible_v<absl::Hash<Ts>> && ...)> {
+};
+
+}  // namespace extend_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_EXTEND_INTERNAL_IS_TUPLE_HASHABLE_H_
diff --git a/absl/extend/internal/num_bases.h b/absl/extend/internal/num_bases.h
new file mode 100644
index 0000000..a7bcac6
--- /dev/null
+++ b/absl/extend/internal/num_bases.h
@@ -0,0 +1,87 @@
+// 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.
+
+#ifndef ABSL_EXTEND_INTERNAL_NUM_BASES_H_
+#define ABSL_EXTEND_INTERNAL_NUM_BASES_H_
+
+#include <stddef.h>
+
+#include <optional>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/extend/internal/num_initializers.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace aggregate_internal {
+
+template <typename U>
+struct OnlyBases {
+  template <typename T>
+  using IsStrictBase =
+      std::enable_if_t<std::is_base_of_v<T, U> && !std::is_same_v<T, U>, int>;
+
+  template <typename T, IsStrictBase<T> = 0>
+  operator T&&() const;  // NOLINT(google-explicit-constructor)
+  template <typename T, IsStrictBase<T> = 0>
+  operator T&() const;  // NOLINT(google-explicit-constructor)
+};
+
+template <typename T, size_t... I>
+constexpr std::optional<int> NumBasesImpl(std::index_sequence<I...>) {
+  if constexpr (BraceInitializableWith<
+                    T, OnlyBases<T>, OnlyBases<T>,
+                    decltype(  // Cast to void to avoid unintentionally invoking
+                               // comma operator or warning on unused LHS
+                        (void)I, Anything{})...>::value) {
+    // The first two initializers look like bases.
+    // The second might be a member or a base, so we give up.
+    return std::nullopt;
+  } else if constexpr (BraceInitializableWith<
+                           T, OnlyBases<T>, Anything,
+                           decltype(  // Cast to void to avoid unintentionally
+                                      // invoking comma operator or warning on
+                                      // unused LHS
+                               (void)I, Anything{})...>::value) {
+    // The first initializer is a base, but not the second. We have 1 base.
+    return 1;
+  } else {
+    // The first initializer is not a base. We have 0 bases.
+    return 0;
+  }
+}
+
+// Returns the number of base classes of the given type, with best effort:
+//
+// - If the type is empty (i.e. `std::is_empty_v<T>` is true), returns nullopt.
+// - If the type has no bases, returns 0.
+// - If the type has exactly 1 base, returns 1.
+// - Otherwise, returns nullopt.
+template <typename T>
+constexpr std::optional<int> NumBases() {
+  if constexpr (std::is_empty_v<T>) {
+    return std::nullopt;
+  } else {
+    constexpr int num_initializers = NumInitializers<T>();
+    return NumBasesImpl<T>(std::make_index_sequence<num_initializers - 1>());
+  }
+}
+
+}  // namespace aggregate_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_EXTEND_INTERNAL_NUM_BASES_H_
diff --git a/absl/extend/internal/num_bases_test.cc b/absl/extend/internal/num_bases_test.cc
new file mode 100644
index 0000000..ca6a063
--- /dev/null
+++ b/absl/extend/internal/num_bases_test.cc
@@ -0,0 +1,91 @@
+// 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/extend/internal/num_bases.h"
+
+#include <optional>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace aggregate_internal {
+namespace {
+
+using ::testing::Eq;
+using ::testing::Optional;
+
+TEST(NumBases, NoBases) {
+  struct S {
+    int i;
+  };
+  EXPECT_THAT(NumBases<S>(), Optional(0));
+
+  struct Empty {};
+  // We can't deal with empty classes right now.
+  EXPECT_THAT(NumBases<Empty>(), Eq(std::nullopt));
+}
+
+TEST(NumBases, OneBase) {
+  struct EmptyBase {};
+  struct NonEmptyBase {
+    int i;
+  };
+
+  // We can't deal with empty classes right now.
+  struct EmptyEmpty : EmptyBase {};
+  EXPECT_THAT(NumBases<EmptyEmpty>(), Eq(std::nullopt));
+
+  struct EmptyNonEmpty : NonEmptyBase {};
+  EXPECT_THAT(NumBases<EmptyNonEmpty>(), Optional(1));
+
+  struct NonEmptyEmpty : EmptyBase {
+    int i;
+  };
+  EXPECT_THAT(NumBases<NonEmptyEmpty>(), Optional(1));
+
+  struct NonEmptyNonEmpty : NonEmptyBase {
+    int j;
+  };
+  EXPECT_THAT(NumBases<NonEmptyNonEmpty>(), Optional(1));
+}
+
+TEST(NumBases, TwoBases) {
+  struct Base1 {};
+  struct Base2 {};
+  struct S : Base1, Base2 {
+    int i;
+  };
+
+  EXPECT_THAT(NumBases<S>(), Eq(std::nullopt));
+}
+
+TEST(NumBases, OneBaseAndField) {
+  // Special case for 1 base where we fail to detect it.
+  // The first member also happens to be a base.
+
+  struct Base {};
+  struct S : Base {
+    Base member;
+  };
+
+  EXPECT_THAT(NumBases<S>(), Eq(std::nullopt));
+}
+
+}  // namespace
+}  // namespace aggregate_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/extend/internal/num_initializers.h b/absl/extend/internal/num_initializers.h
new file mode 100644
index 0000000..1224e72
--- /dev/null
+++ b/absl/extend/internal/num_initializers.h
@@ -0,0 +1,113 @@
+// 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.
+
+#ifndef ABSL_EXTEND_INTERNAL_NUM_INITIALIZERS_H_
+#define ABSL_EXTEND_INTERNAL_NUM_INITIALIZERS_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace aggregate_internal {
+
+template <typename U>
+struct AnythingExcept {
+  template <typename T,
+            std::enable_if_t<!std::is_same_v<U, std::decay_t<T>>, int> = 0>
+  operator T() const {  // NOLINT(google-explicit-constructor)
+    ABSL_UNREACHABLE();
+  }
+};
+
+struct Anything {
+  template <typename T>
+  operator T() const {  // NOLINT(google-explicit-constructor)
+    ABSL_UNREACHABLE();
+  }
+};
+
+struct NotDefaultConstructible {
+  NotDefaultConstructible() = delete;
+  explicit NotDefaultConstructible(int);
+};
+
+template <typename T>
+struct Tester {
+  T t;
+  NotDefaultConstructible n;
+};
+
+template <class Void, typename T, typename... Args>
+struct BraceInitializableWithImpl : std::false_type {
+  static_assert(std::is_void_v<Void>, "First template parameter must be void");
+};
+
+template <typename T, typename... Args>
+struct BraceInitializableWithImpl<
+    std::enable_if_t<
+        !std::is_null_pointer_v<decltype(Tester<T>{std::declval<Args>()...})>>,
+    T, Args...> : std::true_type {};
+
+#ifdef __clang__
+#pragma clang diagnostic push
+// -Wmissing-braces triggers here because we are expanding arguments into the
+// first member of `Tester`. Not having the braces is necessary because we don't
+// know how many arguments are going to be used to initialize the `T` and we
+// need them to be tried greedily.
+#pragma clang diagnostic ignored "-Wmissing-braces"
+#endif
+
+template <typename T, typename... Args>
+using BraceInitializableWith = BraceInitializableWithImpl<void, T, Args...>;
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+// Count the number of initializers required for a struct of type `T`. Note that
+// we do not support C-style array members. Prefer using a std::array.
+//
+// Repeatedly tests if `T` is brace-constructible with a given number of
+// arguments. Each time it is not, one more argument is added and
+// `NumInitializers` is called recursively.
+template <typename T, typename... Args>
+constexpr int NumInitializers(Args... args) {
+  static_assert(!std::is_empty_v<T>);
+  // By attempting to brace-initialize a Tester<T> where the first member is
+  // `AnythingExcept<T>`, we force the aggregate to be expanded, meaning the
+  // first some-number of arguments are passed to `T`'s aggregate
+  // initialization. This will fail (and therefore recurse into
+  // `NumInitializers` with one more argument) if we have not found enough
+  // arguments to initialize `T`. This is because the second member of the
+  // `Tester<T>` has type `NotDefaultConstructible` which cannot be default
+  // constructed.
+  if constexpr (BraceInitializableWith<T, AnythingExcept<T>, Args...>::value) {
+    return sizeof...(Args);
+  } else {
+    static_assert(sizeof...(Args) <= sizeof(T),
+                  "Automatic field count does not support fields like l-value "
+                  "references or bit fields. Try specifying the field count.");
+    return NumInitializers<T>(args..., Anything());
+  }
+}
+
+}  // namespace aggregate_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_EXTEND_INTERNAL_NUM_INITIALIZERS_H_
diff --git a/absl/extend/internal/num_initializers_test.cc b/absl/extend/internal/num_initializers_test.cc
new file mode 100644
index 0000000..96c7b41
--- /dev/null
+++ b/absl/extend/internal/num_initializers_test.cc
@@ -0,0 +1,250 @@
+// 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/extend/internal/num_initializers.h"
+
+#include <stdint.h>
+
+#include <any>
+#include <array>
+#include <optional>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace aggregate_internal {
+namespace {
+
+TEST(NumInitializers, SimpleStructs) {
+  struct A1 {
+    int a;
+  };
+  EXPECT_EQ(NumInitializers<A1>(), 1);
+
+  struct A2 {
+    int a;
+    int b;
+  };
+  EXPECT_EQ(NumInitializers<A2>(), 2);
+
+  struct A3 {
+    int a;
+    const int& b;
+    int&& c;
+  };
+  EXPECT_EQ(NumInitializers<A3>(), 3);
+}
+
+TEST(NumInitializers, SimpleStructsWithDefaults) {
+  struct A1 {
+    int a = 1;
+  };
+  EXPECT_EQ(NumInitializers<A1>(), 1);
+
+  struct A2 {
+    int a = 1;
+    int b = 2;
+  };
+  EXPECT_EQ(NumInitializers<A2>(), 2);
+
+  struct A3 {
+    int a = 0;
+    const int& b;
+    int&& c;
+  };
+  EXPECT_EQ(NumInitializers<A3>(), 3);
+}
+
+TEST(NumInitializers, EmptyBase) {
+  struct Base {};
+
+  struct A1 : Base {
+    int a;
+  };
+  EXPECT_EQ(NumInitializers<A1>(), 2);
+
+  struct A2 : Base {
+    int a;
+    int b;
+  };
+  EXPECT_EQ(NumInitializers<A2>(), 3);
+
+  struct A3 : Base {
+    int a;
+    const int& b;
+    int&& c;
+  };
+  EXPECT_EQ(NumInitializers<A3>(), 4);
+}
+
+TEST(NumInitializers, Base) {
+  struct Base {
+    int x;
+    int y;
+  };
+
+  struct A1 : Base {
+    int a;
+  };
+  EXPECT_EQ(NumInitializers<A1>(), 2);
+
+  struct A2 : Base {
+    int a;
+    int b;
+  };
+  EXPECT_EQ(NumInitializers<A2>(), 3);
+
+  struct A3 : Base {
+    int a;
+    const int& b;
+    int&& c;
+  };
+  EXPECT_EQ(NumInitializers<A3>(), 4);
+}
+
+TEST(NumInitializers, MultipleBases) {
+  struct Base1 {
+    int x1;
+    int y1;
+  };
+  struct Base2 {
+    int x2;
+    int y2;
+  };
+
+  struct A1 : Base1, Base2 {
+    int a;
+  };
+  EXPECT_EQ(NumInitializers<A1>(), 3);
+
+  struct A2 : Base1, Base2 {
+    int a;
+    int b;
+  };
+  EXPECT_EQ(NumInitializers<A2>(), 4);
+
+  struct A3 : Base1, Base2 {
+    int a;
+    const int& b;
+    int&& c;
+  };
+  EXPECT_EQ(NumInitializers<A3>(), 5);
+}
+
+TEST(NumInitializers, StdArrayMembers) {
+  struct A {
+    std::array<int, 3> a;
+    int b;
+  };
+  EXPECT_EQ(NumInitializers<A>(), 2);
+}
+
+TEST(NumInitializers, StructMembers) {
+  struct A {
+    struct Nested {
+      int x;
+      int y;
+    } n;
+    int b;
+  };
+  EXPECT_EQ(NumInitializers<A>(), 2);
+}
+
+TEST(NumInitializers, MoveOnlyMembers) {
+  class MoveOnly {
+   public:
+    MoveOnly() = default;
+    MoveOnly(MoveOnly&&) = default;
+    MoveOnly& operator=(MoveOnly&&) = default;
+
+    MoveOnly(MoveOnly const&) = delete;
+    MoveOnly& operator=(MoveOnly const&) = delete;
+  };
+
+  struct A {
+    MoveOnly a;
+    int b;
+    MoveOnly c;
+    MoveOnly&& d;
+    // MoveOnly& e;  // does not compile, until a brave soul implements it.
+  };
+  EXPECT_EQ(NumInitializers<A>(), 4);
+}
+
+// Not supported on older compilers due to mysterious compiler bug(s) that are
+// somewhat difficult to track down. (See b/478243383.)
+//
+// TODO(b/479561657): Enable this unconditionally.
+#if !defined(_MSC_VER) || _MSC_VER >= 1939
+TEST(NumInitializers, MutableRefConstructibleMembers) {
+  class MutableRefConstructible {
+   public:
+    MutableRefConstructible() = default;
+
+    MutableRefConstructible(MutableRefConstructible&) {
+      {
+        // Dummy braces to avoid modernize-use-equals-default diagnostic.
+        // We avoid `= default` due to compiler bug on _MSC_VER < 1940.
+      }
+    }
+
+    MutableRefConstructible(const MutableRefConstructible&) = delete;
+  };
+
+  struct A {
+    MutableRefConstructible a;
+    int b;
+    MutableRefConstructible c;
+    MutableRefConstructible&& d;
+  };
+  EXPECT_EQ(NumInitializers<A>(), 4);
+}
+
+TEST(NumInitializers, ImmovableMembers) {
+  struct Immovable {
+    Immovable() = default;
+    Immovable(Immovable&&) = delete;
+  };
+
+  struct A {
+    const Immovable& a;
+    Immovable&& b;
+  };
+  EXPECT_EQ(NumInitializers<A>(), 2);
+}
+#endif  // _MSC_VER >= 1939
+
+TEST(NumInitializers, StdAnyMembers) {
+  struct A1 {
+    std::any a;  // cover `AnythingExcept`
+    int b;
+    std::any c;
+  };
+  EXPECT_EQ(NumInitializers<A1>(), 3);
+
+  struct A2 {
+    int a;
+    std::any b;  // cover `Anything`
+    const std::any& c;
+    std::any&& d;
+  };
+  EXPECT_EQ(NumInitializers<A2>(), 4);
+}
+
+}  // namespace
+}  // namespace aggregate_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/extend/internal/reflection.cc b/absl/extend/internal/reflection.cc
new file mode 100644
index 0000000..1d47998
--- /dev/null
+++ b/absl/extend/internal/reflection.cc
@@ -0,0 +1,112 @@
+// 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/extend/internal/reflection.h"
+
+#include <stddef.h>
+
+#include <cstdarg>
+
+#include "absl/base/config.h"
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace extend_internal {
+
+// `PrintfHijack` is called repeatedly with each `fmt` line and corresponding
+// arguments `va` via `__builtin_dump_struct`. While there is no guarantee about
+// the `fmt` strings provided, it is typical that lines come in 5 flavors:
+// 1. A string containing only "%s", accepting the name of the struct itself.
+// 2. A string containing only "%s%s", accepting the name of a base class.
+// 3. A string containing only whitespace and an open brace "{" indicating that
+//    we are entering a new struct.
+// 4. A string with "=" where the value passed into the format specifier which
+//    immediately precedes "=" is the name of a struct field.
+// 5. A string ending with a "}" indicating the conclusion of a struct.
+//
+// For example, for a struct
+// ```
+// struct Bacon {
+//   int repeatability;
+//   double flavor;
+//   double fattiness;
+//   struct Metadata {
+//     bool is_pork;
+//     bool is_expired;
+//   } metadata;
+// };
+// ```
+// we would expect the following values for `fmt` to be passed to `ParseLine`,
+// along with the following data in `va`:
+//     `fmt`           |    `va`
+// --------------------|-------------
+//   "%s"              | {"Bacon"}
+//   " {\n"            | {}
+//   "%s%s %s = %d\n"  | {"  ", "int", "repeatability", ???}
+//   "%s%s %s = %f\n"  | {"  ", "double", "flavor", ???}
+//   "%s%s %s = %f\n"  | {"  ", "double", "fattiness", ???}
+//   "%s%s %s ="       | {"  ", "Metadata", "metadata"}
+//   " {\n"            | {}
+//   "%s%s %s = %d\n"  | {"  ", "_Bool", "is_pork", ???}
+//   "%s%s %s = %d\n"  | {"  ", "_Bool", "is_expired", ???}
+//   "%s}\n"           | {"  "}
+//   "}\n"             | {}
+//
+// `PrintfHijack` inspects each format string and argument set, extracting field
+// names for the given struct and writes them to `fields`. If an unexpected
+// format string is encountered, `state.index` will be set to -1 indicating a
+// failure. Parsing succeeds if after every call to `PrintfHijack`,
+// `state.index == fields.size()`.
+int PrintfHijack(ParsingState& state, absl::Span<absl::string_view> fields,
+                 const char* fmt, ...) {
+  if (state.index < 0) return 0;
+
+  if (absl::EndsWith(fmt, "{\n")) {
+    ++state.brace_count;
+    return 0;
+  } else if (absl::EndsWith(fmt, "}") || absl::EndsWith(fmt, "}\n")) {
+    --state.brace_count;
+    return 0;
+  } else if (state.brace_count != 1) {
+    // Ignore everything that's not at the top-level (we only care about the
+    // names of fields in this type.
+    return 0;
+  } else if (absl::StartsWith(fmt, "%s%s %s =")) {
+    std::va_list va;
+    va_start(va, fmt);
+
+    static_cast<void>(va_arg(va, const char*));  // Indentation whitespace
+    static_cast<void>(va_arg(va, const char*));  // Field's type name
+    fields[static_cast<size_t>(state.index)] =
+        va_arg(va, const char*);  // Field name
+    ++state.index;
+
+    va_end(va);
+  } else if (fmt == absl::string_view("%s%s")) {
+    // Ignore base classes.
+    return 0;
+  } else {
+    // Unexpected case. Mark parsing as failed.
+    state.index = -1;
+  }
+
+  return 0;
+}
+
+}  // namespace extend_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/extend/internal/reflection.h b/absl/extend/internal/reflection.h
new file mode 100644
index 0000000..6751374
--- /dev/null
+++ b/absl/extend/internal/reflection.h
@@ -0,0 +1,75 @@
+// 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.
+
+#ifndef ABSL_EXTEND_INTERNAL_REFLECTION_H_
+#define ABSL_EXTEND_INTERNAL_REFLECTION_H_
+
+#include <array>
+#include <cstddef>
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+#if defined(ABSL_EXTEND_INTERNAL_TURN_OFF_FIELD_NAMES_FOR_TEST)
+#define ABSL_INTERNAL_EXTEND_PARSE_FIELD_NAMES 0
+#elif defined(TARGET_OS_OSX) || defined(__ANDROID__)
+// TODO(b/234010485): Implement field names for these.
+#define ABSL_INTERNAL_EXTEND_PARSE_FIELD_NAMES 0
+#elif ABSL_HAVE_BUILTIN(__builtin_dump_struct)
+#define ABSL_INTERNAL_EXTEND_PARSE_FIELD_NAMES 1
+#else
+#define ABSL_INTERNAL_EXTEND_PARSE_FIELD_NAMES 0
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace extend_internal {
+
+struct ParsingState {
+  // The index of the field currently being parsed.
+  int index = 0;
+  // The number of unmatched '{' characters encountered so far while parsing.
+  int brace_count = 0;
+};
+
+// Called by` __builtin_dump_struct` for each line of the struct representation.
+// Rather than printing the struct representation, we parse `fmt` to extract the
+// lines containing struct field names and store them in `T::kFieldNames`.
+// Note: `__builtin_dump_struct` provides no guarantees whatsoever on its
+// output, so our parsing is entirely best-effort.
+int PrintfHijack(ParsingState& state, absl::Span<absl::string_view> fields,
+                 const char* fmt, ...);
+
+// Forward declaration of test helper.
+template <typename T>
+struct ReflectionTestingExtension;
+
+// Not nested in ReflectionExtension to reduce template instantiations.
+template <size_t N>
+struct FieldNameInfo {
+  static constexpr size_t kFieldCount = N;
+
+#if ABSL_INTERNAL_EXTEND_PARSE_FIELD_NAMES
+  std::array<absl::string_view, kFieldCount> field_names;
+#endif
+  // Indicates whether parsing was successful.
+  bool success;
+};
+
+}  // namespace extend_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_EXTEND_INTERNAL_REFLECTION_H_
diff --git a/absl/extend/internal/tuple.h b/absl/extend/internal/tuple.h
new file mode 100644
index 0000000..747e549
--- /dev/null
+++ b/absl/extend/internal/tuple.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef ABSL_EXTEND_INTERNAL_TUPLE_H_
+#define ABSL_EXTEND_INTERNAL_TUPLE_H_
+
+#include <cstddef>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace extend_internal {
+
+template <std::size_t... N, typename F, typename... T>
+void ZippedForEachImpl(std::index_sequence<N...>, F f, T&&... t) {
+  const auto for_i = [&](auto i) { f(std::get<i>(std::forward<T>(t))...); };
+  (for_i(std::integral_constant<size_t, N>{}), ...);
+}
+
+template <typename F, typename... T>
+void ZippedForEach(F f, T&... t) {
+  using tuple_t = std::decay_t<decltype((std::declval<T>(), ...))>;
+  using seq_t = std::make_index_sequence<std::tuple_size_v<tuple_t>>;
+  (ZippedForEachImpl)(seq_t{}, f, t...);
+}
+
+template <typename F, size_t... Ns>
+auto MakeTupleFromCallable(std::index_sequence<Ns...>, F f) {
+  return std::make_tuple(f(std::integral_constant<size_t, Ns>{})...);
+}
+
+}  // namespace extend_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_EXTEND_INTERNAL_TUPLE_H_
diff --git a/absl/hash/internal/hash.cc b/absl/hash/internal/hash.cc
index 23caae9..74b6d57 100644
--- a/absl/hash/internal/hash.cc
+++ b/absl/hash/internal/hash.cc
@@ -39,6 +39,13 @@
 #include <xmmintrin.h>
 #endif  // ABSL_AES_INTERNAL_HAVE_X86_SIMD
 
+#ifdef ABSL_AES_INTERNAL_HAVE_ARM_SIMD
+#error ABSL_AES_INTERNAL_HAVE_ARM_SIMD cannot be directly set
+#elif defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(__ARM_FEATURE_CRYPTO)
+#include <arm_neon.h>
+#define ABSL_AES_INTERNAL_HAVE_ARM_SIMD
+#endif  // ABSL_INTERNAL_HAVE_ARM_NEON
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
@@ -49,39 +56,136 @@
   PrefetchToLocalCache(ptr + 5 * ABSL_CACHELINE_SIZE);
 }
 
-#ifdef ABSL_AES_INTERNAL_HAVE_X86_SIMD
-uint64_t Mix4x16Vectors(__m128i a, __m128i b, __m128i c, __m128i d) {
-  // res128 = encrypt(a + c, d) + decrypt(b - d, a)
-  auto res128 = _mm_add_epi64(_mm_aesenc_si128(_mm_add_epi64(a, c), d),
-                              _mm_aesdec_si128(_mm_sub_epi64(b, d), a));
-  auto x64 = static_cast<uint64_t>(_mm_cvtsi128_si64(res128));
-  auto y64 = static_cast<uint64_t>(_mm_extract_epi64(res128, 1));
+#if defined(ABSL_AES_INTERNAL_HAVE_X86_SIMD) || \
+    defined(ABSL_AES_INTERNAL_HAVE_ARM_SIMD)
+
+#if defined(ABSL_AES_INTERNAL_HAVE_X86_SIMD)
+using Vector128 = __m128i;
+
+inline Vector128 Load128(const uint8_t* ptr) {
+  return _mm_loadu_si128(reinterpret_cast<const Vector128*>(ptr));
+}
+
+inline Vector128 Set128(uint64_t a, uint64_t b) {
+  return _mm_set_epi64x(static_cast<int64_t>(a), static_cast<int64_t>(b));
+}
+
+inline Vector128 Add128(Vector128 a, Vector128 b) {
+  return _mm_add_epi64(a, b);
+}
+
+inline Vector128 Sub128(Vector128 a, Vector128 b) {
+  return _mm_sub_epi64(a, b);
+}
+
+inline Vector128 Encrypt128(Vector128 data, Vector128 key) {
+  return _mm_aesenc_si128(data, key);
+}
+
+inline Vector128 Decrypt128(Vector128 data, Vector128 key) {
+  return _mm_aesdec_si128(data, key);
+}
+
+inline uint64_t ExtractLow64(Vector128 v) {
+  return static_cast<uint64_t>(_mm_cvtsi128_si64(v));
+}
+
+inline uint64_t ExtractHigh64(Vector128 v) {
+  return static_cast<uint64_t>(_mm_extract_epi64(v, 1));
+}
+
+inline uint64_t Mix4x16Vectors(Vector128 a, Vector128 b, Vector128 c,
+                               Vector128 d) {
+  Vector128 res128 =
+      Add128(Encrypt128(Add128(a, c), d), Decrypt128(Sub128(b, d), a));
+  uint64_t x64 = ExtractLow64(res128);
+  uint64_t y64 = ExtractHigh64(res128);
   return x64 ^ y64;
 }
 
+#else  // ABSL_AES_INTERNAL_HAVE_ARM_SIMD
+
+using Vector128 = uint8x16_t;
+
+inline Vector128 Load128(const uint8_t* ptr) { return vld1q_u8(ptr); }
+
+inline Vector128 Set128(uint64_t a, uint64_t b) {
+  return vreinterpretq_u8_u64(vsetq_lane_u64(a, vdupq_n_u64(b), 1));
+}
+
+inline Vector128 Add128(Vector128 a, Vector128 b) {
+  return vreinterpretq_u8_u64(
+      vaddq_u64(vreinterpretq_u64_u8(a), vreinterpretq_u64_u8(b)));
+}
+
+inline Vector128 Sub128(Vector128 a, Vector128 b) {
+  return vreinterpretq_u8_u64(
+      vsubq_u64(vreinterpretq_u64_u8(a), vreinterpretq_u64_u8(b)));
+}
+
+// Encrypt128 and Decrypt128 are equivalent to x86 versions.
+// `vaeseq_u8` and `vaesdq_u8` perform `^ key` before encryption/decryption.
+// We need to perform `^ key` after encryption/decryption to improve hash
+// quality and match x86 version.
+
+inline Vector128 Encrypt128(Vector128 data, Vector128 key) {
+  return vaesmcq_u8(vaeseq_u8(data, Vector128{})) ^ key;
+}
+
+inline Vector128 Decrypt128(Vector128 data, Vector128 key) {
+  return vaesimcq_u8(vaesdq_u8(data, Vector128{})) ^ key;
+}
+
+// ArmEncrypt128 and ArmDecrypt128 are ARM specific versions that use ARM
+// instructions directly.
+// We can only use these versions in the second round of encryption/decryption
+// to have good hash quality.
+
+inline Vector128 ArmEncrypt128(Vector128 data, Vector128 key) {
+  return vaesmcq_u8(vaeseq_u8(data, key));
+}
+
+inline Vector128 ArmDecrypt128(Vector128 data, Vector128 key) {
+  return vaesimcq_u8(vaesdq_u8(data, key));
+}
+
+inline uint64_t ExtractLow64(Vector128 v) {
+  return vgetq_lane_u64(vreinterpretq_u64_u8(v), 0);
+}
+
+inline uint64_t ExtractHigh64(Vector128 v) {
+  return vgetq_lane_u64(vreinterpretq_u64_u8(v), 1);
+}
+
+uint64_t Mix4x16Vectors(Vector128 a, Vector128 b, Vector128 c, Vector128 d) {
+  Vector128 res128 = Add128(ArmEncrypt128(a, c), ArmDecrypt128(b, d));
+  uint64_t x64 = ExtractLow64(res128);
+  uint64_t y64 = ExtractHigh64(res128);
+  return x64 ^ y64;
+}
+
+#endif  // ABSL_AES_INTERNAL_HAVE_X86_SIMD
+
 uint64_t LowLevelHash33To64(uint64_t seed, const uint8_t* ptr, size_t len) {
   assert(len > 32);
   assert(len <= 64);
-  __m128i state =
-      _mm_set_epi64x(static_cast<int64_t>(seed), static_cast<int64_t>(len));
-  auto a = _mm_loadu_si128(reinterpret_cast<const __m128i*>(ptr));
-  auto b = _mm_loadu_si128(reinterpret_cast<const __m128i*>(ptr + 16));
+  Vector128 state = Set128(seed, len);
+  Vector128 a = Load128(ptr);
+  Vector128 b = Load128(ptr + 16);
   auto* last32_ptr = ptr + len - 32;
-  auto c = _mm_loadu_si128(reinterpret_cast<const __m128i*>(last32_ptr));
-  auto d = _mm_loadu_si128(reinterpret_cast<const __m128i*>(last32_ptr + 16));
+  Vector128 c = Load128(last32_ptr);
+  Vector128 d = Load128(last32_ptr + 16);
 
-  // Bits of the second argument to _mm_aesdec_si128/_mm_aesenc_si128 are
-  // XORed with the state argument after encryption.
-  // We use each value as the first argument to shuffle all the bits around.
-  // We do not add any salt to the state or loaded data, instead we vary
-  // instructions used to mix bits _mm_aesdec_si128/_mm_aesenc_si128 and
-  // _mm_add_epi64/_mm_sub_epi64.
-  // _mm_add_epi64/_mm_sub_epi64 are combined to one instruction with data
-  // loading like `vpaddq  xmm1, xmm0, xmmword ptr [rdi]`.
-  auto na = _mm_aesdec_si128(_mm_add_epi64(state, a), state);
-  auto nb = _mm_aesdec_si128(_mm_sub_epi64(state, b), state);
-  auto nc = _mm_aesenc_si128(_mm_add_epi64(state, c), state);
-  auto nd = _mm_aesenc_si128(_mm_sub_epi64(state, d), state);
+  // Bits of the second argument to Decrypt128/Encrypt128 are XORed with the
+  // state argument after encryption. We use each value as the first argument to
+  // shuffle all the bits around. We do not add any salt to the state or loaded
+  // data, instead we vary instructions used to mix bits Decrypt128/Encrypt128
+  // and Add128/Sub128. On x86 Add128/Sub128 are combined to one instruction
+  // with data loading like `vpaddq  xmm1, xmm0, xmmword ptr [rdi]`.
+  Vector128 na = Decrypt128(Add128(state, a), state);
+  Vector128 nb = Decrypt128(Sub128(state, b), state);
+  Vector128 nc = Encrypt128(Add128(state, c), state);
+  Vector128 nd = Encrypt128(Sub128(state, d), state);
 
   // We perform another round of encryption to mix bits between two halves of
   // the input.
@@ -97,11 +201,10 @@
   // If we have more than 64 bytes, we're going to handle chunks of 64
   // bytes at a time. We're going to build up four separate hash states
   // which we will then hash together. This avoids short dependency chains.
-  __m128i state0 =
-      _mm_set_epi64x(static_cast<int64_t>(seed), static_cast<int64_t>(len));
-  __m128i state1 = state0;
-  __m128i state2 = state1;
-  __m128i state3 = state2;
+  Vector128 state0 = Set128(seed, len);
+  Vector128 state1 = state0;
+  Vector128 state2 = state1;
+  Vector128 state3 = state2;
 
   // Mixing two 128-bit vectors at a time with corresponding states.
   // All variables are mixed slightly differently to avoid hash collision
@@ -111,25 +214,17 @@
   // See comments in LowLevelHash33To64 for more considerations.
   auto mix_ab = [&state0,
                  &state1](const uint8_t* p) ABSL_ATTRIBUTE_ALWAYS_INLINE {
-    // i128 a = *p;
-    // i128 b = *(p + 16);
-    // state0 = decrypt(state0 + a, state0);
-    // state1 = decrypt(state1 - b, state1);
-    auto a = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p));
-    auto b = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p + 16));
-    state0 = _mm_aesdec_si128(_mm_add_epi64(state0, a), state0);
-    state1 = _mm_aesdec_si128(_mm_sub_epi64(state1, b), state1);
+    Vector128 a = Load128(p);
+    Vector128 b = Load128(p + 16);
+    state0 = Decrypt128(Add128(state0, a), state0);
+    state1 = Decrypt128(Sub128(state1, b), state1);
   };
   auto mix_cd = [&state2,
                  &state3](const uint8_t* p) ABSL_ATTRIBUTE_ALWAYS_INLINE {
-    // i128 c = *p;
-    // i128 d = *(p + 16);
-    // state2 = encrypt(state2 + c, state2);
-    // state3 = encrypt(state3 - d, state3);
-    auto c = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p));
-    auto d = _mm_loadu_si128(reinterpret_cast<const __m128i*>(p + 16));
-    state2 = _mm_aesenc_si128(_mm_add_epi64(state2, c), state2);
-    state3 = _mm_aesenc_si128(_mm_sub_epi64(state3, d), state3);
+    Vector128 c = Load128(p);
+    Vector128 d = Load128(p + 16);
+    state2 = Encrypt128(Add128(state2, c), state2);
+    state3 = Encrypt128(Sub128(state3, d), state3);
   };
 
   do {
diff --git a/absl/hash/internal/low_level_hash_test.cc b/absl/hash/internal/low_level_hash_test.cc
index d054337..6476462 100644
--- a/absl/hash/internal/low_level_hash_test.cc
+++ b/absl/hash/internal/low_level_hash_test.cc
@@ -368,7 +368,7 @@
         << "We only maintain golden data for little endian 64 bit systems with "
            "128 bit intristics.";
   }
-#elif defined(__SSE4_2__) && defined(__AES__)
+#elif (defined(__SSE4_2__) && defined(__AES__))
   constexpr uint64_t kGolden[kNumGoldenOutputs] = {
       0xd6bdb2c9ba5e55f2, 0xffd3e23d4115a8ae, 0x2c3218ef486127de,
       0x554fa7f3a262b886, 0x06304cbf82e312d3, 0x490b3fb5af80622c,
@@ -403,6 +403,41 @@
       0x724110fb509e4376, 0xebe74b016b5cfb88, 0x3b0fe11dcf175fc9,
       0x20b737b9c0490538, 0x0db21c429b45fd17,
   };
+#elif (defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(__ARM_FEATURE_CRYPTO))
+  constexpr uint64_t kGolden[kNumGoldenOutputs] = {
+      0x248c82373f7f0d24, 0x0a4f8cbf55047086, 0x498dd0a4445ed65f,
+      0x6d418b193638ab0f, 0x4112c1ce9142980e, 0x02132db6a189f206,
+      0x36e550ca9139ee44, 0xe0a67fdbd8627314, 0x2b9528fe18f65d1d,
+      0x037d9cf48ca9fd1c, 0xa87222631332ca06, 0x31f35e09af065022,
+      0xacd6f1d29071c8e5, 0x54eb4f229a0d15a4, 0x132c27c6a747e136,
+      0x13d7cb427efe7e2f, 0x71a5d21e00f00dcd, 0xdb909cbf1b0fbb64,
+      0x4dc943ad8901fa5b, 0xacf4b3d41a46feb5, 0x12a37d19c14ffd65,
+      0xdb511011bcdd95b9, 0xd6d75af1c8b86dbd, 0xc65aefdcff941a8e,
+      0xbea311ef212c0306, 0xc49861afe7a6888b, 0x598424b541daf528,
+      0x4cc264fbb57c4640, 0x1a7376211a5e674a, 0xcb82900ad06bf89b,
+      0xd9d6201d685a4971, 0x77ed120a277ce616, 0x9bd5ad973b4d358c,
+      0x880850ff91b6b772, 0xf9d24d40448fce38, 0x870b8ee54a31707d,
+      0x613130fe647bd169, 0x04a0cc02a81989f3, 0x998adbda0ab3f8fa,
+      0x2b28729269102040, 0xbdb9be95e352a6d5, 0xd5e2a55d78bd9fb0,
+      0xef609c2b22eb93d6, 0xac23eb02494ae8e0, 0xcb8c5ab08163d2a3,
+      0x63f822fc21b42698, 0xe7e8814288c470cc, 0x143b07aae2ccd592,
+      0xc5d142f4806e13a3, 0xe695de2a1d8a344b, 0xc8ddc3ed542a5988,
+      0x60ec526cc1e5274d, 0x732a04dcf34a7ac9, 0xf1daef52096a872a,
+      0x541f04b87b3de158, 0xeb143a708b621f94, 0x0849cd39e156b25f,
+      0x36eb0746caa62c5c, 0xbfa14eb3c31f78bf, 0x256637f35dc41f20,
+      0x08293113693a58e2, 0x064202395a685840, 0x0593285ee1ed42ea,
+      0xdcbf16fd8a44f213, 0xe9f5586745f4f23d, 0x66808a2c18365ae9,
+      0xa70496836a5166e1, 0xe9ed7d0f9f572246, 0x024ba6063287d0cb,
+      0xa441f6ac287479db, 0x72502c190698ee02, 0xb79705c6ced58c29,
+      0x5c03f52968cb1fdc, 0x6f4b7c6bed6cc232, 0xed834775697438d3,
+      0x6273b075725ffb6f, 0x60df77a69e9aafb2, 0x84483bf48b989c4e,
+      0x37e42a1d35795a31, 0x280dcdb36b853ae5, 0x63309d698f2dd42c,
+      0x24e65be2c805ea5b, 0x1db08e0d041efdf9, 0xb94aea8c4648772b,
+      0x109f2b81aa4660d2, 0xcae92809feb1a390, 0x0a1cbf9628383b41,
+      0xca0bf416706fc5c8, 0x9d4751bd7e638488, 0x343b363d5d96c7c7,
+      0x6bacaedde1daf5aa, 0x721ead1618c4e405, 0xcfc19e400cb6dbc6,
+      0x7ac0dd9128ec8cc3, 0xb7dd428bb44fc744,
+  };
 #else
   constexpr uint64_t kGolden[kNumGoldenOutputs] = {
       0x669da02f8d009e0f, 0xceb19bf2255445cd, 0x0e746992d6d43a7c,
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index b68dd85..a182c65 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -68,6 +68,48 @@
 )
 
 cc_library(
+    name = "clock_interface",
+    srcs = [
+        "clock_interface.cc",
+    ],
+    hdrs = [
+        "clock_interface.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":time",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:no_destructor",
+        "//absl/base:nullability",
+        "//absl/base:raw_logging_internal",
+        "//absl/synchronization",
+    ],
+)
+
+cc_library(
+    name = "simulated_clock",
+    testonly = True,
+    srcs = [
+        "simulated_clock.cc",
+    ],
+    hdrs = [
+        "simulated_clock.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":clock_interface",
+        ":time",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:nullability",
+        "//absl/synchronization",
+    ],
+)
+
+cc_library(
     name = "test_util",
     testonly = True,
     srcs = ["internal/test_util.cc"],
@@ -111,6 +153,44 @@
 )
 
 cc_test(
+    name = "clock_interface_test",
+    srcs = [
+        "clock_interface_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":clock_interface",
+        ":time",
+        "//absl/functional:bind_front",
+        "//absl/synchronization",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "simulated_clock_test",
+    srcs = [
+        "simulated_clock_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":clock_interface",
+        ":simulated_clock",
+        ":time",
+        "//absl/base:core_headers",
+        "//absl/base:raw_logging_internal",
+        "//absl/functional:bind_front",
+        "//absl/random",
+        "//absl/synchronization",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_test(
     name = "flag_test",
     srcs = [
         "flag_test.cc",
diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt
index 34a5ad4..c3ae98c 100644
--- a/absl/time/CMakeLists.txt
+++ b/absl/time/CMakeLists.txt
@@ -131,6 +131,79 @@
     GTest::gmock_main
 )
 
+absl_cc_library(
+  NAME
+    clock_interface
+  HDRS
+    "clock_interface.h"
+  SRCS
+    "clock_interface.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::time
+    absl::config
+    absl::core_headers
+    absl::no_destructor
+    absl::nullability
+    absl::raw_logging_internal
+    absl::synchronization
+)
+
+absl_cc_test(
+  NAME
+    clock_interface_test
+  SRCS
+    "clock_interface_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::clock_interface
+    absl::time
+    absl::config
+    absl::bind_front
+    absl::synchronization
+    GTest::gmock_main
+)
+
+absl_cc_library(
+  NAME
+    simulated_clock
+  HDRS
+    "simulated_clock.h"
+  SRCS
+    "simulated_clock.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::clock_interface
+    absl::time
+    absl::config
+    absl::core_headers
+    absl::nullability
+    absl::synchronization
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    simulated_clock_test
+  SRCS
+    "simulated_clock_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::clock_interface
+    absl::simulated_clock
+    absl::time
+    absl::config
+    absl::bind_front
+    absl::random_random
+    absl::raw_logging_internal
+    absl::synchronization
+    GTest::gmock_main
+)
+
 absl_cc_test(
   NAME
     flag_test
diff --git a/absl/time/clock_interface.cc b/absl/time/clock_interface.cc
new file mode 100644
index 0000000..800d0b1
--- /dev/null
+++ b/absl/time/clock_interface.cc
@@ -0,0 +1,71 @@
+// 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/time/clock_interface.h"
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/no_destructor.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace {
+
+class RealTimeClock final : public Clock {
+ private:
+#ifdef _MSC_VER
+  // Disable MSVC warning "destructor never returns, potential memory leak"
+#pragma warning(push)
+#pragma warning(disable : 4722)
+#endif
+  ~RealTimeClock() override {
+    ABSL_RAW_LOG(FATAL, "RealTimeClock should never be destroyed");
+  }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+ public:
+  absl::Time TimeNow() override { return absl::Now(); }
+
+  void Sleep(absl::Duration d) override { absl::SleepFor(d); }
+
+  void SleepUntil(absl::Time wakeup_time) override {
+    absl::Duration d = wakeup_time - TimeNow();
+    if (d > absl::ZeroDuration()) {
+      Sleep(d);
+    }
+  }
+
+  bool AwaitWithDeadline(absl::Mutex* mu, const absl::Condition& cond,
+                         absl::Time deadline) override {
+    return mu->AwaitWithDeadline(cond, deadline);
+  }
+};
+
+}  // namespace
+
+Clock::~Clock() = default;  // go/key-method
+
+Clock& Clock::GetRealClock() {
+  static absl::NoDestructor<RealTimeClock> rtclock;
+  return *rtclock;
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/time/clock_interface.h b/absl/time/clock_interface.h
new file mode 100644
index 0000000..25ccf6e
--- /dev/null
+++ b/absl/time/clock_interface.h
@@ -0,0 +1,91 @@
+// 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: clock_interface.h
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_TIME_CLOCK_INTERFACE_H_
+#define ABSL_TIME_CLOCK_INTERFACE_H_
+
+#include "absl/base/config.h"
+#include "absl/base/macros.h"
+#include "absl/base/nullability.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// An abstract interface representing a Clock, which is an object that can
+// tell you the current time, sleep, and wait for a condition variable.
+//
+// This interface allows decoupling code that uses time from the code that
+// creates a point in time.  You can use this to your advantage by injecting
+// Clocks into interfaces rather than having implementations call absl::Now()
+// directly.
+//
+// The Clock::GetRealClock() function returns a reference to the global realtime
+// clock.
+//
+// Example:
+//
+//   bool IsWeekend(Clock& clock) {
+//     absl::Time now = clock.TimeNow();
+//     // ... code to check if 'now' is a weekend.
+//   }
+//
+//   // Production code.
+//   IsWeekend(Clock::GetRealClock());
+//
+//   // Test code:
+//   MyTestClock test_clock(SATURDAY);
+//   IsWeekend(test_clock);
+//
+class Clock {
+ public:
+  // Returns a reference to the global realtime clock.
+  // The returned clock is thread-safe.
+  static Clock& GetRealClock();
+
+  virtual ~Clock();
+
+  // Returns the current time.
+  virtual absl::Time TimeNow() = 0;
+
+  // Sleeps for the specified duration.
+  virtual void Sleep(absl::Duration d) = 0;
+
+  // Sleeps until the specified time.
+  virtual void SleepUntil(absl::Time wakeup_time) = 0;
+
+  // Returns when cond is true or the deadline has passed.  Returns true iff
+  // cond holds when returning.
+  //
+  // Requires *mu to be held at least in shared mode.  It will be held when
+  // evaluating cond, and upon return, but it may be released and reacquired
+  // in the meantime.
+  //
+  // This method is similar to mu->AwaitWithDeadline() except that the
+  // latter only works with real-time deadlines.  This call works properly
+  // with simulated time if invoked on a simulated clock.
+  virtual bool AwaitWithDeadline(absl::Mutex* absl_nonnull mu,
+                                 const absl::Condition& cond,
+                                 absl::Time deadline) = 0;
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_TIME_CLOCK_INTERFACE_H_
diff --git a/absl/time/clock_interface_test.cc b/absl/time/clock_interface_test.cc
new file mode 100644
index 0000000..6434bc0
--- /dev/null
+++ b/absl/time/clock_interface_test.cc
@@ -0,0 +1,128 @@
+// 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/time/clock_interface.h"
+
+#include <cstdint>
+#include <functional>
+#include <thread>  // NOLINT(build/c++11)
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/functional/bind_front.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/synchronization/notification.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+
+namespace {
+
+constexpr absl::Duration kLongPause = absl::Milliseconds(150);
+
+#ifdef _MSC_VER
+// As of 2026-01-29, multithreaded tests on MSVC are too flaky.
+const char* kSkipFlakyReason =
+    "Skipping this timing test because it is too flaky";
+#else
+const char* kSkipFlakyReason = nullptr;
+#endif
+
+
+void AwaitWithDeadlineAndNotify(absl::Clock* clock, absl::Mutex* mu,
+                                absl::Condition* cond, absl::Time wakeup_time,
+                                absl::Notification* note, bool* return_val) {
+  mu->lock_shared();
+  *return_val = clock->AwaitWithDeadline(mu, *cond, wakeup_time);
+  mu->unlock_shared();
+  note->Notify();
+}
+
+TEST(RealClockTest, AwaitWithVeryLargeDeadline) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::Clock& clock = absl::Clock::GetRealClock();
+  absl::Mutex mu;
+  bool f = false;
+  absl::Condition cond(&f);
+  absl::Notification note;
+  bool return_val;
+
+  std::thread thread(AwaitWithDeadlineAndNotify, &clock, &mu, &cond,
+                     absl::InfiniteFuture(), &note, &return_val);
+
+  EXPECT_FALSE(note.HasBeenNotified());
+
+  mu.lock();
+  f = true;
+  mu.unlock();
+
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  EXPECT_TRUE(return_val);
+  note.WaitForNotification();  // In case the expectation fails.
+  thread.join();
+}
+
+TEST(RealClockTest, AwaitWithPastDeadline) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::Clock& clock = absl::Clock::GetRealClock();
+  absl::Mutex mu;
+  bool f = false;
+  absl::Condition cond(&f);
+  absl::Notification note;
+  bool return_val;
+
+  std::thread thread(AwaitWithDeadlineAndNotify, &clock, &mu, &cond,
+                     clock.TimeNow() - absl::Seconds(10), &note, &return_val);
+  absl::Time start = absl::Now();
+  note.WaitForNotification();  // AwaitWithDeadline() should ping note.
+  EXPECT_GE(kLongPause, absl::Now() - start);
+  EXPECT_FALSE(return_val);
+  thread.join();
+}
+
+TEST(RealClockTest, AwaitWithSmallDeadline) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::Clock& clock = absl::Clock::GetRealClock();
+  absl::Mutex mu;
+  bool f = false;
+  absl::Condition cond(&f);
+
+  for (int i = 0; i < 5; ++i) {
+    absl::Duration wait_time = absl::Milliseconds(i);
+    absl::Duration elapsed_time;
+    {
+      absl::MutexLock lock(mu);
+      absl::Time start = clock.TimeNow();
+      absl::Time wakeup_time = start + wait_time;
+      EXPECT_FALSE(clock.AwaitWithDeadline(&mu, cond, wakeup_time));
+      elapsed_time = clock.TimeNow() - start;
+    }
+    if (elapsed_time >= absl::ZeroDuration()) {  // ignore jumps backwards
+      // 60 microseconds of slop to allow for non-monotonic clocks.
+      EXPECT_GE(elapsed_time, wait_time - absl::Microseconds(60));
+    }
+  }
+}
+
+}  // namespace
diff --git a/absl/time/simulated_clock.cc b/absl/time/simulated_clock.cc
new file mode 100644
index 0000000..6c98260
--- /dev/null
+++ b/absl/time/simulated_clock.cc
@@ -0,0 +1,225 @@
+// 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/time/simulated_clock.h"
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <optional>
+#include <utility>
+#include <vector>
+
+#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"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// There are a few tricky details in the implementation of SimulatedClock.
+//
+// The external mutex that is passed as a param of AwaitWithDeadline() is not
+// under the control of SimulatedClock; in particular, it can be destroyed any
+// time after AwaitWithDeadline() returns.  This requires the wakeup call from
+// AdvanceTime() to avoid grabbing the external mutex if AwaitWithDeadline()
+// has returned.  This is accomplished by allowing the waiter to be cancelled
+// via a bool guarded by a mutex in WakeUpInfo.
+//
+// Once AwaitWithDeadline() has released lock_, someone nefarious might call
+// the SimulatedClock destructor, so it isn't possible for AwaitWithDeadline()
+// to remove the wakeup call from waiters_ if the condition it is awaiting
+// becomes true; it cancels the waiter instead.  This means that,
+// theoretically, many obsolete entries could pile up in waiters_ if
+// AwaitWithDeadline() keeps being called but simulated time is not advanced.
+// This seems unlikely to happen in practice.
+//
+// The WakeUpInfo in waiters_ are always awoken via WakeUp() (and
+// removed) or cancelled before AwaitWithDeadline() returns.  If a
+// waiters_ value is cancelled then calling its WakeUp() method will
+// short-circuit before touching the external mutex.
+
+class SimulatedClock::WakeUpInfo {
+ public:
+  WakeUpInfo(absl::Mutex* mu, absl::Condition cond)
+      : mu_(mu),
+        cond_(cond),
+        wakeup_time_passed_(false),
+        cancelled_(false),
+        wakeup_called_(false) {}
+
+  void WakeUp() {
+    // If we are cancelled then AwaitWithDeadline may have returned, in which
+    // case we can't lock mu_.
+    {
+      absl::MutexLock lock(cancellation_mu_);
+      if (cancelled_) return;
+      wakeup_called_ = true;
+    }
+    absl::MutexLock lock(*mu_);
+    wakeup_time_passed_ = true;
+  }
+
+  void AwaitConditionOrWakeUp() {
+    mu_->Await(absl::Condition(this, &WakeUpInfo::Ready));
+  }
+
+  void CancelOrAwaitWakeUp() {
+    bool wakeup_called;
+    {
+      absl::MutexLock lock(cancellation_mu_);
+      cancelled_ = true;
+      wakeup_called = wakeup_called_;
+    }
+    if (wakeup_called && !wakeup_time_passed_) {
+      // Wait for WakeUp to complete.
+      //
+      // Note that this will unlock 'mu_'; this is actually necessary
+      // so that WakeUp() can unblock and complete.  This does allow
+      // for 'cond_' to potentially change from true to false; that is
+      // OK, since WakeUp() is being called, so the deadline must be
+      // past, and so this method is fulfilling its duties.  (Well, the
+      // destructor might be calling WakeUp(), but if you're deleting
+      // time itself while waiting for a deadline to pass, you deserve
+      // what you get.)
+      mu_->Await(absl::Condition(&wakeup_time_passed_));
+    }
+  }
+
+ private:
+  bool Ready() const { return wakeup_time_passed_ || cond_.Eval(); }
+
+  absl::Mutex* mu_;
+  absl::Condition cond_;
+  bool wakeup_time_passed_;
+  absl::Mutex cancellation_mu_;
+  bool cancelled_ ABSL_GUARDED_BY(cancellation_mu_);
+  bool wakeup_called_ ABSL_GUARDED_BY(cancellation_mu_);
+};
+
+SimulatedClock::SimulatedClock(absl::Time t) : now_(t) {}
+
+SimulatedClock::~SimulatedClock() {
+  // Wake up all existing waiters.
+  WaiterList waiters;
+  {
+    absl::MutexLock l(lock_);
+    waiters.swap(waiters_);
+  }
+  for (auto& iter : waiters) {
+    iter.second->WakeUp();
+  }
+}
+
+absl::Time SimulatedClock::TimeNow() {
+  absl::ReaderMutexLock l(lock_);
+  return now_;
+}
+
+void SimulatedClock::Sleep(absl::Duration d) { SleepUntil(TimeNow() + d); }
+
+int64_t SimulatedClock::SetTime(absl::Time t) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+  return UpdateTime([this, t]()
+                        ABSL_EXCLUSIVE_LOCKS_REQUIRED(lock_) { now_ = t; });
+}
+
+int64_t SimulatedClock::AdvanceTime(absl::Duration d)
+    ABSL_NO_THREAD_SAFETY_ANALYSIS {
+  return UpdateTime([this, d]()
+                        ABSL_EXCLUSIVE_LOCKS_REQUIRED(lock_) { now_ += d; });
+}
+
+template <class T>
+int64_t SimulatedClock::UpdateTime(const T& now_updater) {
+  // Deadlock could occur if UpdateTime() were to hold lock_ while waking up
+  // waiters, since waking up requires acquiring the external mutex, and
+  // AwaitWithDeadline() acquires the mutexes in the opposite order.  So let's
+  // first grab all the wakeup callbacks, then release lock_, then call the
+  // callbacks.
+  std::vector<WaiterList::mapped_type> wakeup_calls;
+
+  lock_.lock();
+  now_updater();  // reset now_
+  WaiterList::iterator iter;
+  while (((iter = waiters_.begin()) != waiters_.end()) &&
+         (iter->first <= now_)) {
+    wakeup_calls.push_back(std::move(iter->second));
+    waiters_.erase(iter);
+  }
+  lock_.unlock();
+
+  for (const auto& wakeup_call : wakeup_calls) {
+    wakeup_call->WakeUp();
+  }
+
+  return static_cast<int64_t>(wakeup_calls.size());
+}
+
+void SimulatedClock::SleepUntil(absl::Time wakeup_time) {
+  absl::Mutex mu;
+  absl::MutexLock lock(mu);
+  bool f = false;
+  AwaitWithDeadline(&mu, absl::Condition(&f), wakeup_time);
+}
+
+bool SimulatedClock::AwaitWithDeadline(absl::Mutex* mu,
+                                       const absl::Condition& cond,
+                                       absl::Time deadline) {
+  mu->AssertReaderHeld();
+
+  // Evaluate cond outside our own lock to minimize contention.
+  const bool ready = cond.Eval();
+
+  lock_.lock();
+  num_await_calls_++;
+
+  // Return now if the deadline is already past, or if the condition is true.
+  // This avoids creating a WakeUpInfo that won't be deleted until an
+  // appropriate UpdateTime() call.
+  if (deadline <= now_ || ready) {
+    lock_.unlock();
+    return ready;
+  }
+
+  auto wakeup_info = std::make_shared<WakeUpInfo>(mu, cond);
+  waiters_.insert(std::make_pair(deadline, wakeup_info));
+
+  lock_.unlock();
+  // SimulatedClock may be destroyed any time after this, so we can't
+  // acquire lock_ again.
+
+  // Wait until either cond.Eval() becomes true, or the deadline has passed.
+  wakeup_info->AwaitConditionOrWakeUp();
+
+  // Cancel the wakeup call, or if it's already in progress, wait for it to
+  // finish, since we must ensure no one touches 'mu' or 'cond' after we return.
+  wakeup_info->CancelOrAwaitWakeUp();
+
+  return cond.Eval();
+}
+
+std::optional<absl::Time> SimulatedClock::GetEarliestWakeupTime() const {
+  absl::ReaderMutexLock l(lock_);
+  if (waiters_.empty()) {
+    return std::nullopt;
+  }
+  return waiters_.begin()->first;
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/time/simulated_clock.h b/absl/time/simulated_clock.h
new file mode 100644
index 0000000..2225eee
--- /dev/null
+++ b/absl/time/simulated_clock.h
@@ -0,0 +1,108 @@
+// 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: simulated_clock.h
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_TIME_SIMULATED_CLOCK_H_
+#define ABSL_TIME_SIMULATED_CLOCK_H_
+
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <optional>
+
+#include "absl/base/config.h"
+#include "absl/base/nullability.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/time/clock.h"
+#include "absl/time/clock_interface.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// A simulated clock is a concrete Clock implementation that does not "tick"
+// on its own.  Time is advanced by explicit calls to the AdvanceTime() or
+// SetTime() functions.
+//
+// Example:
+//   absl::SimulatedClock sim_clock;
+//   absl::Time now = sim_clock.TimeNow();
+//   // now == absl::UnixEpoch()
+//
+//   now = sim_clock.TimeNow();
+//   // now == absl::UnixEpoch() (still)
+//
+//   sim_clock.AdvanceTime(absl::Seconds(3));
+//   now = sim_clock.TimeNow();
+//   // now == absl::UnixEpoch() + absl::Seconds(3)
+//
+// This class is thread-safe.
+class SimulatedClock : public Clock {
+ public:
+  explicit SimulatedClock(absl::Time t);
+  SimulatedClock() : SimulatedClock(absl::UnixEpoch()) {}
+
+  // The destructor should be called only if all Sleep(), etc. and
+  // AdvanceTime() calls have completed. The code does its best to let
+  // any pending calls finish gracefully, but there are no guarantees.
+  ~SimulatedClock() override;
+
+  // Returns the simulated time.
+  absl::Time TimeNow() override;
+
+  // Sleeps until the specified duration has elapsed according to this clock.
+  void Sleep(absl::Duration d) override;
+
+  // Sleeps until the specified wakeup_time.
+  void SleepUntil(absl::Time wakeup_time) override;
+
+  // Sets the simulated time to the argument.  Wakes up any threads whose
+  // sleeps have now expired. Returns the number of woken threads.
+  int64_t SetTime(absl::Time t);
+
+  // Advances the simulated time by the specified duration.  Wakes up any
+  // threads whose sleeps have now expired. Returns the number of woken threads.
+  int64_t AdvanceTime(absl::Duration d);
+
+  // Blocks until the condition is true or until the simulated clock is
+  // advanced to or beyond the wakeup time (or both).
+  bool AwaitWithDeadline(absl::Mutex* absl_nonnull mu,
+                         const absl::Condition& cond,
+                         absl::Time deadline) override
+      ABSL_SHARED_LOCKS_REQUIRED(mu);
+
+  // Returns the earliest wakeup time.
+  std::optional<absl::Time> GetEarliestWakeupTime() const;
+
+ private:
+  template <class T>
+  int64_t UpdateTime(const T& now_updater) ABSL_LOCKS_EXCLUDED(lock_);
+
+  class WakeUpInfo;
+  using WaiterList = std::multimap<absl::Time, std::shared_ptr<WakeUpInfo>>;
+
+  mutable absl::Mutex lock_;
+  absl::Time now_ ABSL_GUARDED_BY(lock_);
+  WaiterList waiters_ ABSL_GUARDED_BY(lock_);
+  int64_t num_await_calls_ ABSL_GUARDED_BY(lock_) = 0;
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_TIME_SIMULATED_CLOCK_H_
diff --git a/absl/time/simulated_clock_test.cc b/absl/time/simulated_clock_test.cc
new file mode 100644
index 0000000..4618338
--- /dev/null
+++ b/absl/time/simulated_clock_test.cc
@@ -0,0 +1,614 @@
+// 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/time/simulated_clock.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <thread>  // NOLINT(build/c++11)
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/random/random.h"
+#include "absl/synchronization/blocking_counter.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/synchronization/notification.h"
+#include "absl/time/clock.h"
+#include "absl/time/clock_interface.h"
+#include "absl/time/time.h"
+
+namespace {
+
+constexpr absl::Duration kShortPause = absl::Milliseconds(20);
+constexpr absl::Duration kLongPause = absl::Milliseconds(1000);
+
+#ifdef _MSC_VER
+// As of 2026-01-29, multithreaded tests on MSVC are too flaky.
+const char* kSkipFlakyReason =
+    "Skipping this timing test because it is too flaky";
+#else
+const char* kSkipFlakyReason = nullptr;
+#endif
+
+TEST(SimulatedClock, TimeInitializedToZero) {
+  absl::SimulatedClock simclock;
+  EXPECT_EQ(absl::UnixEpoch(), simclock.TimeNow());
+}
+
+TEST(SimulatedClock, NowSetTime) {
+  absl::SimulatedClock simclock;
+  absl::Time now = simclock.TimeNow();
+
+  now += absl::Seconds(123);
+  simclock.SetTime(now);
+  EXPECT_EQ(now, simclock.TimeNow());
+
+  now += absl::Seconds(123);
+  simclock.SetTime(now);
+  EXPECT_EQ(now, simclock.TimeNow());
+
+  now += absl::ZeroDuration();
+  simclock.SetTime(now);
+  EXPECT_EQ(now, simclock.TimeNow());
+}
+
+TEST(SimulatedClock, NowAdvanceTime) {
+  absl::SimulatedClock simclock;
+  absl::Time now = simclock.TimeNow();
+
+  simclock.AdvanceTime(absl::Seconds(123));
+  now += absl::Seconds(123);
+  EXPECT_EQ(now, simclock.TimeNow());
+
+  simclock.AdvanceTime(absl::Seconds(123));
+  now += absl::Seconds(123);
+  EXPECT_EQ(now, simclock.TimeNow());
+
+  simclock.AdvanceTime(absl::ZeroDuration());
+  now += absl::ZeroDuration();
+  EXPECT_EQ(now, simclock.TimeNow());
+}
+
+void SleepAndNotify(absl::Clock* clock, absl::Duration sleep_secs,
+                    absl::Notification* note) {
+  clock->Sleep(sleep_secs);
+  note->Notify();
+}
+
+TEST(SimulatedClock, Sleep_SetToSleepTime) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  std::thread tr(SleepAndNotify, &simclock, absl::Seconds(123), &note);
+
+  // wait for SleepAndNotify() to block
+  absl::SleepFor(kLongPause);
+  simclock.SetTime(absl::FromUnixSeconds(122));
+  // give Sleep() the opportunity to fail
+  absl::SleepFor(kShortPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  simclock.SetTime(absl::FromUnixSeconds(122 + 1));
+  // wait for Sleep() to return
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+TEST(SimulatedClock, SleepAdvanceToSleepTime) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  std::thread tr(SleepAndNotify, &simclock, absl::Seconds(123), &note);
+  // wait for SleepAndNotify() to block
+  absl::SleepFor(kLongPause);
+  simclock.AdvanceTime(absl::Seconds(122));
+  // give Sleep() the opportunity to fail
+  absl::SleepFor(kShortPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  simclock.AdvanceTime(absl::Seconds(1));
+  // wait for Sleep() to return
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+TEST(SimulatedClock, SleepSetPastSleepTime) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  std::thread tr(SleepAndNotify, &simclock, absl::Seconds(123), &note);
+  // wait for SleepAndNotify() to block
+  absl::SleepFor(kLongPause);
+  simclock.SetTime(absl::FromUnixSeconds(122));
+  // give Sleep() the opportunity to fail
+  absl::SleepFor(kShortPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  simclock.SetTime(absl::FromUnixSeconds(122 + 2));
+  // wait for Sleep() to return
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+TEST(SimulatedClock, SleepAdvancePastSleepTime) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  std::thread tr(SleepAndNotify, &simclock, absl::Seconds(123), &note);
+  // wait for SleepAndNotify() to block
+  absl::SleepFor(kLongPause);
+  simclock.AdvanceTime(absl::Seconds(122));
+  // give Sleep() the opportunity to fail
+  absl::SleepFor(kShortPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  simclock.AdvanceTime(absl::Seconds(2));
+  // wait for Sleep() to return
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+TEST(SimulatedClock, SleepZeroSleepTime) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  std::thread tr(SleepAndNotify, &simclock, absl::ZeroDuration(), &note);
+  // wait for SleepAndNotify() to ping note
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+void SleepUntilAndNotify(absl::Clock* clock, absl::Time wakeup_time,
+                         absl::Notification* note) {
+  clock->SleepUntil(wakeup_time);
+  note->Notify();
+}
+
+TEST(SimulatedClock, SleepUntilSetToSleepTime) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  simclock.SetTime(absl::FromUnixSeconds(123));
+  std::thread tr(SleepUntilAndNotify, &simclock,
+                 absl::UnixEpoch() + absl::Seconds(246), &note);
+  // wait for SleepUntilAndNotify() to block
+  absl::SleepFor(kLongPause);
+  simclock.SetTime(absl::FromUnixSeconds(123 + 122));
+  // give SleepUntil() the opportunity to fail
+  absl::SleepFor(kShortPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  simclock.SetTime(absl::FromUnixSeconds(123 + 122 + 1));
+  absl::Time start = absl::Now();
+  note.WaitForNotification();  // SleepUntilAndNotify() should ping note
+  EXPECT_GE(absl::Milliseconds(50), absl::Now() - start);
+  tr.join();
+}
+
+TEST(SimulatedClock, SleepUntilAdvanceToSleepTime) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  simclock.AdvanceTime(absl::Seconds(123));
+  std::thread tr(SleepUntilAndNotify, &simclock,
+                 absl::UnixEpoch() + absl::Seconds(246), &note);
+  // wait for SleepUntilAndNotify() to block
+  absl::SleepFor(kLongPause);
+  simclock.AdvanceTime(absl::Seconds(122));
+  // give SleepUntil() the opportunity to fail
+  absl::SleepFor(kShortPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  simclock.AdvanceTime(absl::Seconds(1));
+  absl::Time start = absl::Now();
+  note.WaitForNotification();  // SleepUntilAndNotify() should ping note
+  EXPECT_GE(absl::Milliseconds(70), absl::Now() - start);
+  tr.join();
+}
+
+TEST(SimulatedClock, SleepUntilSetPastSleepTime) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  simclock.SetTime(absl::FromUnixSeconds(123));
+  std::thread tr(SleepUntilAndNotify, &simclock,
+                 absl::UnixEpoch() + absl::Seconds(246), &note);
+  // wait for SleepUntilAndNotify() to block
+  absl::SleepFor(kLongPause);
+  simclock.SetTime(absl::FromUnixSeconds(123 + 122));
+  // give SleepUntil() the opportunity to fail
+  absl::SleepFor(kShortPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  simclock.SetTime(absl::FromUnixSeconds(123 + 122 + 2));
+  // wait for SleepUntilAndNotify() to ping note
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+TEST(SimulatedClock, SleepUntilAdvancePastSleepTime) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  simclock.AdvanceTime(absl::Seconds(123));
+  std::thread tr(SleepUntilAndNotify, &simclock,
+                 absl::UnixEpoch() + absl::Seconds(246), &note);
+  // wait for SleepUntilAndNotify() to block
+  absl::SleepFor(kLongPause);
+  simclock.AdvanceTime(absl::Seconds(122));
+  // give SleepUntil() the opportunity to fail
+  absl::SleepFor(kShortPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  simclock.AdvanceTime(absl::Seconds(2));
+  // wait for SleepUntilAndNotify() to ping note
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+TEST(SimulatedClock, SleepUntilTimeAlreadyPassed) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Notification note;
+
+  simclock.AdvanceTime(absl::Seconds(123));
+  std::thread tr(SleepUntilAndNotify, &simclock,
+                 absl::UnixEpoch() + absl::Seconds(123), &note);
+  // wait for SleepUntilAndNotify() to ping note
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+void AwaitWithDeadlineAndNotify(absl::Clock* clock, absl::Mutex* mu,
+                                absl::Condition* cond, absl::Time wakeup_time,
+                                absl::Notification* note, bool* return_val) {
+  mu->lock_shared();
+  *return_val = clock->AwaitWithDeadline(mu, *cond, wakeup_time);
+  mu->unlock_shared();
+  note->Notify();
+}
+
+TEST(SimulatedClock, AwaitWithDeadlineConditionInitiallyTrue) {
+  absl::SimulatedClock simclock;
+  absl::Mutex mu;
+  bool f = true;
+  absl::Condition cond(&f);
+  absl::MutexLock lock(mu);
+  ASSERT_TRUE(simclock.AwaitWithDeadline(&mu, cond, absl::InfiniteFuture()));
+}
+
+TEST(SimulatedClock, AwaitWithDeadlineConditionInitiallyFalse) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Mutex mu;
+  bool f = false;
+  absl::Condition cond(&f);
+  absl::Notification note;
+  bool return_val;
+
+  std::thread tr(AwaitWithDeadlineAndNotify, &simclock, &mu, &cond,
+                 absl::UnixEpoch() + absl::Seconds(123), &note, &return_val);
+  // wait for AwaitWithDeadline...() to block
+  absl::SleepFor(kShortPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  mu.lock();
+  f = true;
+  mu.unlock();
+  // wait for AwaitWithDeadline...() to ping note
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  EXPECT_TRUE(return_val);
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+TEST(SimulatedClock, AwaitWithDeadlineDeadlinePassed) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Mutex mu;
+  bool f = false;
+  absl::Condition cond(&f);
+  absl::Notification note;
+  bool return_val;
+
+  std::thread tr(AwaitWithDeadlineAndNotify, &simclock, &mu, &cond,
+                 absl::UnixEpoch() + absl::Seconds(123), &note, &return_val);
+  // wait for AwaitWithDeadline...() to block
+  absl::SleepFor(kLongPause);
+  EXPECT_FALSE(note.HasBeenNotified());
+  simclock.AdvanceTime(absl::Seconds(124));
+  // wait for AwaitWithDeadline...() to ping note
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  EXPECT_FALSE(return_val);
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+TEST(SimulatedClock, AwaitWithDeadlineDeadlineAlreadyPassed) {
+  if (kSkipFlakyReason != nullptr) {
+    GTEST_SKIP() << kSkipFlakyReason;
+  }
+
+  absl::SimulatedClock simclock;
+  absl::Mutex mu;
+  bool f = false;
+  absl::Condition cond(&f);
+  absl::Notification note;
+  bool return_val;
+
+  std::thread tr(AwaitWithDeadlineAndNotify, &simclock, &mu, &cond,
+                 absl::UnixEpoch(), &note, &return_val);
+  // wait for AwaitWithDeadline...() to ping note
+  absl::SleepFor(kLongPause);
+  EXPECT_TRUE(note.HasBeenNotified());
+  EXPECT_FALSE(return_val);
+  note.WaitForNotification();  // in case the expectation fails
+  tr.join();
+}
+
+void RacerMakesConditionTrue(absl::Notification* start_note, absl::Mutex* mu,
+                             bool* f, absl::BlockingCounter* threads_done) {
+  start_note->WaitForNotification();
+  absl::SleepFor(absl::Milliseconds(1));
+  mu->lock();
+  *f = true;
+  mu->unlock();
+  threads_done->DecrementCount();
+}
+
+void RacerAdvancesTime(absl::Notification* start_note,
+                       absl::SimulatedClock* simclock, absl::Duration d,
+                       absl::BlockingCounter* threads_done) {
+  start_note->WaitForNotification();
+  absl::SleepFor(absl::Milliseconds(1));
+  simclock->AdvanceTime(d);
+  threads_done->DecrementCount();
+}
+
+TEST(SimulatedClock, SimultaneousConditionTrueAndDeadline) {
+  absl::SimulatedClock simclock;
+  for (int iteration = 0; iteration < 100; ++iteration) {
+    auto mu = std::make_unique<absl::Mutex>();
+    bool f = false;
+    absl::Condition cond(&f);
+    absl::Notification note_start;
+    absl::BlockingCounter threads_done(2);
+    std::thread tr1(RacerMakesConditionTrue, &note_start, mu.get(), &f,
+                    &threads_done);
+    std::thread tr2(RacerAdvancesTime, &note_start, &simclock,
+                    absl::Seconds(20), &threads_done);
+    note_start.Notify();
+    mu->lock();
+    absl::Time deadline = simclock.TimeNow() + absl::Seconds(10);
+    simclock.AwaitWithDeadline(mu.get(), cond, deadline);
+    EXPECT_TRUE(f || (simclock.TimeNow() >= deadline));
+    if (f) {
+      // RacerMakesConditionTrue has unlocked mu and AwaitWithDeadline has
+      // returned, so it is safe to destruct mu. Do so while RacerAdvancesTime
+      // is possibly still running in an attempt to catch simclock holding on
+      // to a reference to mu and using it after AwaitWithDeadline returns.
+      mu->unlock();
+      mu = nullptr;
+    } else {
+      mu->unlock();
+    }
+    threads_done.Wait();
+    tr1.join();
+    tr2.join();
+  }
+}
+
+void RacerDeletesClock(absl::Mutex* mu, absl::Notification* start_note,
+                       absl::Clock* clock,
+                       absl::BlockingCounter* threads_done) {
+  start_note->WaitForNotification();
+  // mu is acquired temporarily to make sure that AwaitWithDeadline() in
+  // SimultaneousConditionTrueAndDestruction has blocked.
+  mu->lock();
+  mu->unlock();
+  absl::SleepFor(absl::Milliseconds(1));
+  delete clock;
+  threads_done->DecrementCount();
+}
+
+TEST(SimulatedClock, SimultaneousConditionTrueAndDestruction) {
+  for (int iteration = 0; iteration < 100; ++iteration) {
+    absl::Clock* clock = new absl::SimulatedClock();
+    absl::Mutex mu;
+    bool f = false;
+    absl::Condition cond(&f);
+    absl::Notification note_start;
+    absl::BlockingCounter threads_done(2);
+    std::thread tr1([&note_start, &mu, &f, &threads_done] {
+      RacerMakesConditionTrue(&note_start, &mu, &f, &threads_done);
+    });
+    std::thread tr2([&mu, &note_start, clock, &threads_done] {
+      RacerDeletesClock(&mu, &note_start, clock, &threads_done);
+    });
+    mu.lock();
+    note_start.Notify();
+    absl::Time deadline = absl::UnixEpoch() + absl::Seconds(100000);
+    clock->AwaitWithDeadline(&mu, cond, deadline);
+    mu.unlock();
+    threads_done.Wait();
+    tr1.join();
+    tr2.join();
+  }
+}
+
+class SimulatedClockTorturer {
+ public:
+  SimulatedClockTorturer(absl::SimulatedClock* simclock, int num_threads,
+                         int num_iterations)
+      : simclock_(simclock),
+        num_threads_(num_threads),
+        num_iterations_(num_iterations),
+        num_flags_(2 * num_threads),
+        mutex_and_flag_(static_cast<size_t>(num_flags_)) {}
+
+  // Implements a torture test.
+  //
+  // This method uses several groups of:
+  //   SimulatedClock
+  //   Mutex protected flag
+  // It starts several threads that call AwaitWithDeadline() and several
+  // threads that call AdvanceTime() or toggle flag values.
+  void DoTorture() {
+    // The threads calling AwaitWithDeadline() have a separate BlockingCounter
+    // than the threads calling AdvanceTime()/toggling flags, since the former
+    // would be deadlocked if all the threads that might unblock them had
+    // already finished.
+    absl::Notification go;
+    absl::BlockingCounter await_threads_done(num_threads_);
+    absl::Notification signal_threads_should_exit;
+    absl::BlockingCounter signal_threads_done(num_threads_);
+    std::vector<std::thread> trs;
+    for (int i = 0; i < num_threads_; ++i) {
+      trs.emplace_back(&SimulatedClockTorturer::AwaitRandomly, this, &go,
+                       &await_threads_done);
+    }
+    for (int i = 0; i < num_threads_; ++i) {
+      trs.emplace_back(&SimulatedClockTorturer::SignalRandomly, this, &go,
+                       &signal_threads_should_exit, &signal_threads_done);
+    }
+    go.Notify();
+    await_threads_done.Wait();
+    signal_threads_should_exit.Notify();
+    signal_threads_done.Wait();
+    for (auto& thread : trs) {
+      thread.join();
+    }
+  }
+
+ private:
+  // Randomly call AwaitWithDeadline() for num_iterations_ times.
+  void AwaitRandomly(absl::Notification* go,
+                     absl::BlockingCounter* threads_done) {
+    go->WaitForNotification();
+
+    absl::BitGen gen;
+    for (int i = 0; i < num_iterations_; ++i) {
+      auto& [mu, f] = mutex_and_flag_[absl::Uniform<size_t>(gen, size_t{0},
+                                         static_cast<size_t>(num_flags_))];
+      absl::MutexLock lock(mu);
+      absl::Time deadline = simclock_->TimeNow() + absl::Seconds(1);
+      simclock_->AwaitWithDeadline(&mu, absl::Condition(&f), deadline);
+      ABSL_RAW_CHECK(f || simclock_->TimeNow() >= deadline, "");
+    }
+
+    threads_done->DecrementCount();
+  }
+
+  // Randomly call AdvanceTime() or toggle a flag value until notified to
+  // stop.
+  void SignalRandomly(absl::Notification* go, absl::Notification* should_exit,
+                      absl::BlockingCounter* threads_done) {
+    go->WaitForNotification();
+
+    absl::BitGen gen;
+    while (!should_exit->HasBeenNotified()) {
+      int action = absl::Uniform<int>(gen, 0, num_flags_ + 1);
+      if (action < num_flags_) {
+        // Change a flag value.
+        auto& [mutex, flag] = mutex_and_flag_[static_cast<size_t>(action)];
+        absl::MutexLock lock(mutex);
+        flag = !flag;
+      } else {
+        // Advance time.
+        simclock_->AdvanceTime(absl::Seconds(1));
+      }
+    }
+
+    threads_done->DecrementCount();
+  }
+
+  absl::SimulatedClock* simclock_;
+  int num_threads_;
+  int num_iterations_;
+  int num_flags_;
+
+  struct MutexAndFlag {
+    absl::Mutex mutex;
+    bool flag ABSL_GUARDED_BY(mutex) = false;
+  };
+  std::vector<MutexAndFlag> mutex_and_flag_;
+};
+
+TEST(SimulatedClock, Torture) {
+  absl::SimulatedClock simclock;
+  constexpr int kNumThreads = 10;
+  constexpr int kNumIterations = 1000;
+  SimulatedClockTorturer torturer(&simclock, kNumThreads, kNumIterations);
+  torturer.DoTorture();
+}
+
+}  // namespace
diff --git a/ci/linux_arm_clang-latest_libcxx_bazel.sh b/ci/linux_arm_clang-latest_libcxx_bazel.sh
index 5ad9fcc..4c04c77 100755
--- a/ci/linux_arm_clang-latest_libcxx_bazel.sh
+++ b/ci/linux_arm_clang-latest_libcxx_bazel.sh
@@ -39,6 +39,11 @@
 source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
 readonly DOCKER_CONTAINER=${LINUX_ARM_CLANG_LATEST_CONTAINER}
 
+# Print information about the environment.
+docker run "${DOCKER_CONTAINER}" /usr/bin/fastfetch -c ci
+docker run "${DOCKER_CONTAINER}" /opt/llvm/bin/clang -v
+docker run "${DOCKER_CONTAINER}" cat /root/cached_bazel_versions
+
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
 if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
@@ -64,6 +69,11 @@
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
+        --env="USE_BAZEL_VERSION=9.0.0" \
+        --env="CC=/opt/llvm/bin/clang" \
+        --env="BAZEL_CXXOPTS=-std=${std}:-nostdinc++" \
+        --env="BAZEL_LINKOPTS=-L/opt/llvm/lib/aarch64-unknown-linux-gnu:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/lib/aarch64-unknown-linux-gnu" \
+        --env="CPLUS_INCLUDE_PATH=/opt/llvm/include/c++/v1:/opt/llvm/include/aarch64-unknown-linux-gnu/c++/v1/" \
         --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
         --tmpfs=/abseil-cpp \
         --workdir=/abseil-cpp \
@@ -77,17 +87,13 @@
             cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
           fi
           /usr/local/bin/bazel test ... \
-            --action_env=CC=clang-19 \
             --compilation_mode=\"${compilation_mode}\" \
             --copt=\"${exceptions_mode}\" \
             --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \
             --copt=-Werror \
-            --cxxopt=-std=${std} \
-            --cxxopt=-stdlib=libc++ \
             --define=\"absl=1\" \
             --features=external_include_paths \
             --keep_going \
-            --linkopt=-stdlib=libc++ \
             --per_file_copt=external/.*@-w \
             --show_timestamps \
             --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh
index 1200ef0..0c1ba32 100755
--- a/ci/linux_clang-latest_libcxx_asan_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh
@@ -39,6 +39,11 @@
 source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
 readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
 
+# Print information about the environment.
+docker run "${DOCKER_CONTAINER}" /usr/bin/fastfetch -c ci
+docker run "${DOCKER_CONTAINER}" /opt/llvm/bin/clang -v
+docker run "${DOCKER_CONTAINER}" cat /root/cached_bazel_versions
+
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
 if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
@@ -67,6 +72,11 @@
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
+        --env="USE_BAZEL_VERSION=9.0.0" \
+        --env="CC=/opt/llvm/bin/clang" \
+        --env="BAZEL_CXXOPTS=-std=${std}:-nostdinc++" \
+        --env="BAZEL_LINKOPTS=-L/opt/llvm/lib/x86_64-unknown-linux-gnu:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/lib/x86_64-unknown-linux-gnu" \
+        --env="CPLUS_INCLUDE_PATH=/opt/llvm/include/c++/v1:/opt/llvm/include/x86_64-unknown-linux-gnu/c++/v1/" \
         --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
@@ -75,10 +85,6 @@
         ${DOCKER_CONTAINER} \
         /bin/bash --login -c "
         /usr/local/bin/bazel test ... \
-          --action_env=\"CC=/opt/llvm/clang/bin/clang\" \
-          --action_env=\"BAZEL_CXXOPTS=-std=${std}:-nostdinc++\" \
-          --action_env=\"BAZEL_LINKOPTS=-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib\" \
-          --action_env=\"CPLUS_INCLUDE_PATH=/opt/llvm/libcxx/include/c++/v1\" \
           --compilation_mode=\"${compilation_mode}\" \
           --copt=\"${exceptions_mode}\" \
           --copt=\"-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG\" \
@@ -95,10 +101,10 @@
           --linkopt=\"-fsanitize-link-c++-runtime\" \
           --per_file_copt=external/.*@-w \
           --show_timestamps \
-          --test_env=\"ASAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer\" \
+          --test_env=\"ASAN_SYMBOLIZER_PATH=/opt/llvm/bin/llvm-symbolizer\" \
           --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
           --test_env=\"UBSAN_OPTIONS=print_stacktrace=1\" \
-          --test_env=\"UBSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer\" \
+          --test_env=\"UBSAN_SYMBOLIZER_PATH=/opt/llvm/bin/llvm-symbolizer\" \
           --test_output=errors \
           --test_tag_filters=\"-benchmark,-noasan\" \
           ${BAZEL_EXTRA_ARGS:-}"
diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh
index 74af10c..47a21ea 100755
--- a/ci/linux_clang-latest_libcxx_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_bazel.sh
@@ -39,6 +39,11 @@
 source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
 readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
 
+# Print information about the environment.
+docker run "${DOCKER_CONTAINER}" /usr/bin/fastfetch -c ci
+docker run "${DOCKER_CONTAINER}" /opt/llvm/bin/clang -v
+docker run "${DOCKER_CONTAINER}" cat /root/cached_bazel_versions
+
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
 if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
@@ -64,6 +69,11 @@
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
+        --env="USE_BAZEL_VERSION=9.0.0" \
+        --env="CC=/opt/llvm/bin/clang" \
+        --env="BAZEL_CXXOPTS=-std=${std}:-nostdinc++" \
+        --env="BAZEL_LINKOPTS=-L/opt/llvm/lib/x86_64-unknown-linux-gnu:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/lib/x86_64-unknown-linux-gnu" \
+        --env="CPLUS_INCLUDE_PATH=/opt/llvm/include/c++/v1:/opt/llvm/include/x86_64-unknown-linux-gnu/c++/v1/" \
         --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
         --tmpfs=/abseil-cpp \
         --workdir=/abseil-cpp \
@@ -77,10 +87,6 @@
             cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
           fi
           /usr/local/bin/bazel test ... \
-            --action_env=CC=/opt/llvm/clang/bin/clang \
-            --action_env=BAZEL_CXXOPTS=-std=${std}:-nostdinc++ \
-            --action_env=BAZEL_LINKOPTS=-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib \
-            --action_env=CPLUS_INCLUDE_PATH=/opt/llvm/libcxx/include/c++/v1 \
             --compilation_mode=\"${compilation_mode}\" \
             --copt=\"${exceptions_mode}\" \
             --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \
diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh
index 8634e8d..94f9c8a 100755
--- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh
@@ -39,6 +39,11 @@
 source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
 readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
 
+# Print information about the environment.
+docker run "${DOCKER_CONTAINER}" /usr/bin/fastfetch -c ci
+docker run "${DOCKER_CONTAINER}" /opt/llvm/bin/clang -v
+docker run "${DOCKER_CONTAINER}" cat /root/cached_bazel_versions
+
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
 if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
@@ -64,6 +69,11 @@
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
+        --env="USE_BAZEL_VERSION=9.0.0" \
+        --env="CC=/opt/llvm/bin/clang" \
+        --env="BAZEL_CXXOPTS=-std=${std}:-nostdinc++" \
+        --env="BAZEL_LINKOPTS=-L/opt/llvm-tsan/lib/x86_64-unknown-linux-gnu:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm-tsan/lib/x86_64-unknown-linux-gnu" \
+        --env="CPLUS_INCLUDE_PATH=/opt/llvm-tsan/include/c++/v1:/opt/llvm-tsan/include/x86_64-unknown-linux-gnu/c++/v1/" \
         --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
@@ -72,10 +82,6 @@
         ${DOCKER_CONTAINER} \
         /bin/bash --login -c "
         /usr/local/bin/bazel test ... \
-          --action_env=\"CC=/opt/llvm/clang/bin/clang\" \
-          --action_env=\"BAZEL_CXXOPTS=-std=${std}:-nostdinc++\" \
-          --action_env=\"BAZEL_LINKOPTS=-L/opt/llvm/libcxx-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib\" \
-          --action_env=\"CPLUS_INCLUDE_PATH=/opt/llvm/libcxx-tsan/include/c++/v1\" \
           --build_tag_filters=\"-notsan\" \
           --compilation_mode=\"${compilation_mode}\" \
           --copt=\"${exceptions_mode}\" \
@@ -89,7 +95,7 @@
           --linkopt=\"-fsanitize=thread\" \
           --per_file_copt=external/.*@-w \
           --show_timestamps \
-          --test_env=\"TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer\" \
+          --test_env=\"TSAN_SYMBOLIZER_PATH=/opt/llvm/bin/llvm-symbolizer\" \
           --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
           --test_output=errors \
           --test_tag_filters=\"-benchmark,-notsan\" \
diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh
index 3175e41..6b9f0b4 100755
--- a/ci/linux_clang-latest_libstdcxx_bazel.sh
+++ b/ci/linux_clang-latest_libstdcxx_bazel.sh
@@ -39,6 +39,12 @@
 source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
 readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
 
+# Print information about the environment.
+docker run "${DOCKER_CONTAINER}" /usr/bin/fastfetch -c ci
+docker run "${DOCKER_CONTAINER}" /usr/local/bin/gcc -v
+docker run "${DOCKER_CONTAINER}" /opt/llvm/bin/clang -v
+docker run "${DOCKER_CONTAINER}" cat /root/cached_bazel_versions
+
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
 if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
@@ -64,6 +70,9 @@
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
+        --env="USE_BAZEL_VERSION=9.0.0" \
+        --env="CC=/opt/llvm/bin/clang" \
+        --env="BAZEL_CXXOPTS=-std=${std}" \
         --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
@@ -72,8 +81,6 @@
         ${DOCKER_CONTAINER} \
         /bin/bash --login -c "
         /usr/local/bin/bazel test ... \
-          --action_env=\"CC=/opt/llvm/clang/bin/clang\" \
-          --action_env=\"BAZEL_CXXOPTS=-std=${std}\" \
           --compilation_mode=\"${compilation_mode}\" \
           --copt=\"--gcc-toolchain=/usr/local\" \
           --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \
diff --git a/ci/linux_docker_containers.sh b/ci/linux_docker_containers.sh
index cb0904c..8cb17f7 100644
--- a/ci/linux_docker_containers.sh
+++ b/ci/linux_docker_containers.sh
@@ -16,7 +16,7 @@
 # Test scripts should source this file to get the identifiers.
 
 readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20230612"
-readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20250527"
-readonly LINUX_ARM_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_arm_hybrid-latest:20250430"
-readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20250527"
-readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250430"
+readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20260131"
+readonly LINUX_ARM_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_arm_hybrid-latest:20260131"
+readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20260131"
+readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20260131"
diff --git a/ci/linux_gcc-floor_libstdcxx_bazel.sh b/ci/linux_gcc-floor_libstdcxx_bazel.sh
index 0ee412d..b1ca8ef 100755
--- a/ci/linux_gcc-floor_libstdcxx_bazel.sh
+++ b/ci/linux_gcc-floor_libstdcxx_bazel.sh
@@ -37,7 +37,12 @@
 fi
 
 source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
-readonly DOCKER_CONTAINER=${LINUX_GCC_FLOOR_CONTAINER}
+readonly DOCKER_CONTAINER="${LINUX_GCC_FLOOR_CONTAINER}"
+
+# Print information about the environment.
+docker run "${DOCKER_CONTAINER}" /usr/bin/fastfetch -c ci
+docker run "${DOCKER_CONTAINER}" /opt/gcc-9/bin/gcc -v
+docker run "${DOCKER_CONTAINER}" cat /root/cached_bazel_versions
 
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
@@ -64,6 +69,10 @@
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
+        --env="USE_BAZEL_VERSION=9.0.0" \
+        --env="CC=/opt/gcc-9/bin/gcc" \
+        --env="BAZEL_CXXOPTS=-std=${std}" \
+        --env="BAZEL_LINKOPTS=-L/opt/gcc-9/lib64:-Wl,-rpath=/opt/gcc-9/lib64" \
         --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
@@ -72,8 +81,6 @@
         ${DOCKER_CONTAINER} \
         /bin/bash --login -c "
         /usr/local/bin/bazel test ... \
-          --action_env=\"CC=/usr/local/bin/gcc\" \
-          --action_env=\"BAZEL_CXXOPTS=-std=${std}\" \
           --compilation_mode=\"${compilation_mode}\" \
           --copt=\"${exceptions_mode}\" \
           --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \
diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh
index 6e9b5ec..86130f5 100755
--- a/ci/linux_gcc-latest_libstdcxx_bazel.sh
+++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh
@@ -39,6 +39,11 @@
 source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
 readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
 
+# Print information about the environment.
+docker run "${DOCKER_CONTAINER}" /usr/bin/fastfetch -c ci
+docker run "${DOCKER_CONTAINER}" /usr/local/bin/gcc -v
+docker run "${DOCKER_CONTAINER}" cat /root/cached_bazel_versions
+
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
 if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
@@ -64,6 +69,9 @@
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
+        --env="USE_BAZEL_VERSION=9.0.0" \
+        --env="CC=/usr/local/bin/gcc" \
+        --env="BAZEL_CXXOPTS=-std=${std}" \
         --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
         --tmpfs=/abseil-cpp \
         --workdir=/abseil-cpp \
@@ -77,8 +85,6 @@
             cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
           fi
           /usr/local/bin/bazel test ... \
-            --action_env=CC=/usr/local/bin/gcc \
-            --action_env=BAZEL_CXXOPTS=-std=${std} \
             --compilation_mode=\"${compilation_mode}\" \
             --copt=\"${exceptions_mode}\" \
             --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \
diff --git a/ci/macos_xcode_bazel.sh b/ci/macos_xcode_bazel.sh
index a09b405..d50f979 100755
--- a/ci/macos_xcode_bazel.sh
+++ b/ci/macos_xcode_bazel.sh
@@ -19,15 +19,15 @@
 
 set -euox pipefail
 
-# Use Xcode 16.3
-sudo xcode-select -s /Applications/Xcode_16.3.app/Contents/Developer
+# Use Xcode 26.2
+sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer
 
 if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
 # If we are running on Kokoro, check for a versioned Bazel binary.
-KOKORO_GFILE_BAZEL_BIN="bazel-8.2.1-darwin-x86_64"
+KOKORO_GFILE_BAZEL_BIN="bazel-9.0.0-darwin-x86_64"
 if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
   BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
   chmod +x ${BAZEL_BIN}
diff --git a/ci/macos_xcode_cmake.sh b/ci/macos_xcode_cmake.sh
index 37be939..7a6ccd5 100755
--- a/ci/macos_xcode_cmake.sh
+++ b/ci/macos_xcode_cmake.sh
@@ -16,8 +16,8 @@
 
 set -euox pipefail
 
-# Use Xcode 16.3
-sudo xcode-select -s /Applications/Xcode_16.3.app/Contents/Developer
+# Use Xcode 26.2
+sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer
 
 brew install cmake
 
diff --git a/ci/windows_clangcl_bazel.bat b/ci/windows_clangcl_bazel.bat
index 94d27aa..ed5bc5a 100755
--- a/ci/windows_clangcl_bazel.bat
+++ b/ci/windows_clangcl_bazel.bat
@@ -47,7 +47,7 @@
 :: /google/data/rw/teams/absl/kokoro/windows.
 ::
 :: TODO(absl-team): Remove -Wno-microsoft-cast
-%KOKORO_GFILE_DIR%\bazel-8.2.1-windows-x86_64.exe ^
+%KOKORO_GFILE_DIR%\bazel-9.0.0-windows-x86_64.exe ^
   test ... ^
   --compilation_mode=%COMPILATION_MODE% ^
   --compiler=clang-cl ^
diff --git a/ci/windows_msvc_bazel.bat b/ci/windows_msvc_bazel.bat
index 6318ff1..f07bbfd 100755
--- a/ci/windows_msvc_bazel.bat
+++ b/ci/windows_msvc_bazel.bat
@@ -42,7 +42,7 @@
 :: To upgrade Bazel, first download a new binary from
 :: https://github.com/bazelbuild/bazel/releases and copy it to
 :: /google/data/rw/teams/absl/kokoro/windows.
-"%KOKORO_GFILE_DIR%\bazel-8.2.1-windows-x86_64.exe" ^
+"%KOKORO_GFILE_DIR%\bazel-9.0.0-windows-x86_64.exe" ^
   test ... ^
   --compilation_mode=%COMPILATION_MODE% ^
   --copt=/WX ^