Snap for 13871854 from 287980c4245f8f3acdb1f0975d0a5c574f23d090 to androidx-sqlite-release

Change-Id: Ia50938ed23a475a4d6b11505da0ca39d044cbc6d
diff --git a/Android.bp b/Android.bp
index db8d742..2a6bf5c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,5 +1,9 @@
+// This Android.bp file was autogenerated by external/absel-cpp/generate_bp.py
+// DO NOT EDIT
+
 package {
     default_applicable_licenses: ["libabsl_license"],
+    default_visibility: ["//visibility:private"],
 }
 
 license {
@@ -9,60 +13,13121 @@
     license_text: ["LICENSE"],
 }
 
-// Monolithic module for use on device. Currently restricted to 3P libraries
-// which require it as a dependency. See go/absl-android for more information.
-cc_library_static {
-    name: "libabsl",
+cc_defaults {
+    name: "absl_defaults",
     host_supported: true,
-    vendor_available: true,
     product_available: true,
+    ramdisk_available: true,
     recovery_available: true,
-    srcs: [
-        "absl/**/*.cc",
-    ],
-    exclude_srcs: [
-        "absl/**/*benchmark.cc",
-        "absl/**/*benchmarks.cc",
-        "absl/**/*_test.cc",
-        "absl/**/*_testing.cc",
-        "absl/base/spinlock_test_common.cc",
-        "absl/hash/internal/print_hash_of.cc",
-        "absl/log/internal/test_helpers.cc",
-        "absl/log/internal/test_matchers.cc",
-        "absl/log/scoped_mock_log.cc",
-        "absl/random/internal/gaussian_distribution_gentables.cc",
-        "absl/status/internal/status_matchers.cc",
-    ],
-    export_include_dirs: ["."],
-    shared_libs: [
-        "liblog",
-    ],
-    stl: "libc++",
-    sdk_version: "current",
+    vendor_available: true,
+    vendor_ramdisk_available: true,
+    sdk_version: "29",
     min_sdk_version: "apex_inherit",
+    stl: "libc++",
     apex_available: [
         "//apex_available:platform",
-        "com.android.adservices",
-        "com.android.extservices",
-        "com.android.ondevicepersonalization",
+        "//apex_available:anyapex",
     ],
-    visibility: [
-        "//external/federated-compute:__subpackages__",
-        "//external/grpc-grpc:__subpackages__",
-        "//external/iamf_tools:__subpackages__",
-        "//external/libtextclassifier:__subpackages__",
-        "//external/kythe:__subpackages__",
-        "//external/tensorflow:__subpackages__",
-        "//external/tflite-support:__subpackages__",
-        "//external/webrtc:__subpackages__",
-        "//frameworks/av/media/libeffects/preprocessing",
-    ],
+    target: {
+        windows: {
+            enabled: true,
+            cflags: ["-Wno-unknown-pragmas"],
+        },
+    },
 }
 
-// Globally visible host-only library.
-cc_library_host_static {
-    name: "libabsl_host",
-    whole_static_libs: ["libabsl"],
-    export_include_dirs: ["."],
+cc_defaults {
+    name: "absl_notls_defaults",
+    defaults_visibility: ["//external/protobuf:__subpackages__"],
+    host_supported: true,
+    ramdisk_available: true,
+    recovery_available: true,
+    vendor_ramdisk_available: true,
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.runtime",
+    ],
+    cflags: ["-DANDROID_DISABLE_TLS_FOR_LINKER=1"],
+}
+
+cc_defaults {
+    name: "absl_test_defaults",
+    host_supported: true,
+    product_available: true,
+    vendor_available: true,
     stl: "libc++",
 }
+
+cc_defaults {
+    name: "absl_notls_test_defaults",
+    host_supported: true,
+    stl: "libc++",
+    cflags: ["-DANDROID_DISABLE_TLS_FOR_LINKER=1"],
+}
+
+genrule {
+    name: "absl_synchronization_hdrs",
+    srcs: [
+        "absl/synchronization/barrier.h",
+        "absl/synchronization/blocking_counter.h",
+        "absl/synchronization/internal/create_thread_identity.h",
+        "absl/synchronization/internal/futex.h",
+        "absl/synchronization/internal/futex_waiter.h",
+        "absl/synchronization/internal/per_thread_sem.h",
+        "absl/synchronization/internal/pthread_waiter.h",
+        "absl/synchronization/internal/sem_waiter.h",
+        "absl/synchronization/internal/stdcpp_waiter.h",
+        "absl/synchronization/internal/waiter.h",
+        "absl/synchronization/internal/waiter_base.h",
+        "absl/synchronization/internal/win32_waiter.h",
+        "absl/synchronization/mutex.h",
+        "absl/synchronization/notification.h",
+    ],
+    out: [
+        "my_include_dir/absl/synchronization/barrier.h",
+        "my_include_dir/absl/synchronization/blocking_counter.h",
+        "my_include_dir/absl/synchronization/internal/create_thread_identity.h",
+        "my_include_dir/absl/synchronization/internal/futex.h",
+        "my_include_dir/absl/synchronization/internal/futex_waiter.h",
+        "my_include_dir/absl/synchronization/internal/per_thread_sem.h",
+        "my_include_dir/absl/synchronization/internal/pthread_waiter.h",
+        "my_include_dir/absl/synchronization/internal/sem_waiter.h",
+        "my_include_dir/absl/synchronization/internal/stdcpp_waiter.h",
+        "my_include_dir/absl/synchronization/internal/waiter.h",
+        "my_include_dir/absl/synchronization/internal/waiter_base.h",
+        "my_include_dir/absl/synchronization/internal/win32_waiter.h",
+        "my_include_dir/absl/synchronization/mutex.h",
+        "my_include_dir/absl/synchronization/notification.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_synchronization",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/synchronization/barrier.cc",
+        "absl/synchronization/blocking_counter.cc",
+        "absl/synchronization/internal/create_thread_identity.cc",
+        "absl/synchronization/internal/futex_waiter.cc",
+        "absl/synchronization/internal/per_thread_sem.cc",
+        "absl/synchronization/internal/pthread_waiter.cc",
+        "absl/synchronization/internal/sem_waiter.cc",
+        "absl/synchronization/internal/stdcpp_waiter.cc",
+        "absl/synchronization/internal/waiter_base.cc",
+        "absl/synchronization/internal/win32_waiter.cc",
+        "absl/synchronization/mutex.cc",
+        "absl/synchronization/notification.cc",
+    ],
+    generated_headers: ["absl_synchronization_hdrs"],
+    export_generated_headers: ["absl_synchronization_hdrs"],
+
+    whole_static_libs: [
+        "absl_synchronization_graphcycles_internal",
+        "absl_synchronization_kernel_timeout_internal",
+        "absl_base",
+        "absl_base_atomic_hook",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_malloc_internal",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_tracing_internal",
+        "absl_debugging_stacktrace",
+        "absl_debugging_symbolize",
+        "absl_time",
+    ],
+    export_static_lib_headers: [
+        "absl_synchronization_graphcycles_internal",
+        "absl_synchronization_kernel_timeout_internal",
+        "absl_base",
+        "absl_base_atomic_hook",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_malloc_internal",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_tracing_internal",
+        "absl_debugging_stacktrace",
+        "absl_debugging_symbolize",
+        "absl_time",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_synchronization_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/synchronization/barrier.cc",
+        "absl/synchronization/blocking_counter.cc",
+        "absl/synchronization/internal/create_thread_identity.cc",
+        "absl/synchronization/internal/futex_waiter.cc",
+        "absl/synchronization/internal/per_thread_sem.cc",
+        "absl/synchronization/internal/pthread_waiter.cc",
+        "absl/synchronization/internal/sem_waiter.cc",
+        "absl/synchronization/internal/stdcpp_waiter.cc",
+        "absl/synchronization/internal/waiter_base.cc",
+        "absl/synchronization/internal/win32_waiter.cc",
+        "absl/synchronization/mutex.cc",
+        "absl/synchronization/notification.cc",
+    ],
+    generated_headers: ["absl_synchronization_hdrs"],
+    export_generated_headers: ["absl_synchronization_hdrs"],
+
+    whole_static_libs: [
+        "absl_synchronization_graphcycles_internal_notls",
+        "absl_synchronization_kernel_timeout_internal_notls",
+        "absl_base_notls",
+        "absl_base_atomic_hook_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_malloc_internal_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_tracing_internal_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_debugging_symbolize_notls",
+        "absl_time_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_synchronization_graphcycles_internal_notls",
+        "absl_synchronization_kernel_timeout_internal_notls",
+        "absl_base_notls",
+        "absl_base_atomic_hook_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_malloc_internal_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_tracing_internal_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_debugging_symbolize_notls",
+        "absl_time_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_time_hdrs",
+    srcs: [
+        "absl/time/civil_time.h",
+        "absl/time/clock.h",
+        "absl/time/time.h",
+        "absl/time/internal/get_current_time_chrono.inc",
+        "absl/time/internal/get_current_time_posix.inc",
+    ],
+    out: [
+        "my_include_dir/absl/time/civil_time.h",
+        "my_include_dir/absl/time/clock.h",
+        "my_include_dir/absl/time/time.h",
+        "my_include_dir/absl/time/internal/get_current_time_chrono.inc",
+        "my_include_dir/absl/time/internal/get_current_time_posix.inc",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_time",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/time/civil_time.cc",
+        "absl/time/clock.cc",
+        "absl/time/duration.cc",
+        "absl/time/format.cc",
+        "absl/time/time.cc",
+    ],
+    generated_headers: ["absl_time_hdrs"],
+    export_generated_headers: ["absl_time_hdrs"],
+
+    whole_static_libs: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_numeric_int128",
+        "absl_strings",
+        "absl_strings_string_view",
+        "absl_time_internal_cctz_civil_time",
+        "absl_time_internal_cctz_time_zone",
+        "absl_types_optional",
+    ],
+    export_static_lib_headers: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_numeric_int128",
+        "absl_strings",
+        "absl_strings_string_view",
+        "absl_time_internal_cctz_civil_time",
+        "absl_time_internal_cctz_time_zone",
+        "absl_types_optional",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_time_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/time/civil_time.cc",
+        "absl/time/clock.cc",
+        "absl/time/duration.cc",
+        "absl/time/format.cc",
+        "absl/time/time.cc",
+    ],
+    generated_headers: ["absl_time_hdrs"],
+    export_generated_headers: ["absl_time_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_numeric_int128_notls",
+        "absl_strings_notls",
+        "absl_strings_string_view_notls",
+        "absl_time_internal_cctz_civil_time_notls",
+        "absl_time_internal_cctz_time_zone_notls",
+        "absl_types_optional_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_numeric_int128_notls",
+        "absl_strings_notls",
+        "absl_strings_string_view_notls",
+        "absl_time_internal_cctz_civil_time_notls",
+        "absl_time_internal_cctz_time_zone_notls",
+        "absl_types_optional_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_types_optional_hdrs",
+    srcs: [
+        "absl/types/optional.h",
+    ],
+    out: [
+        "my_include_dir/absl/types/optional.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_types_optional",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_types_optional_hdrs"],
+    export_generated_headers: ["absl_types_optional_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_types_optional_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_types_optional_hdrs"],
+    export_generated_headers: ["absl_types_optional_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_utility_hdrs",
+    srcs: [
+        "absl/utility/utility.h",
+    ],
+    out: [
+        "my_include_dir/absl/utility/utility.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_utility",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_utility_hdrs"],
+    export_generated_headers: ["absl_utility_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_utility_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_utility_hdrs"],
+    export_generated_headers: ["absl_utility_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_meta_type_traits_hdrs",
+    srcs: [
+        "absl/meta/type_traits.h",
+    ],
+    out: [
+        "my_include_dir/absl/meta/type_traits.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_meta_type_traits",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_meta_type_traits_hdrs"],
+    export_generated_headers: ["absl_meta_type_traits_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_meta_type_traits_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_meta_type_traits_hdrs"],
+    export_generated_headers: ["absl_meta_type_traits_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_core_headers_hdrs",
+    srcs: [
+        "absl/base/attributes.h",
+        "absl/base/const_init.h",
+        "absl/base/macros.h",
+        "absl/base/optimization.h",
+        "absl/base/port.h",
+        "absl/base/thread_annotations.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/attributes.h",
+        "my_include_dir/absl/base/const_init.h",
+        "my_include_dir/absl/base/macros.h",
+        "my_include_dir/absl/base/optimization.h",
+        "my_include_dir/absl/base/port.h",
+        "my_include_dir/absl/base/thread_annotations.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_core_headers",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_core_headers_hdrs"],
+    export_generated_headers: ["absl_base_core_headers_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_core_headers_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_core_headers_hdrs"],
+    export_generated_headers: ["absl_base_core_headers_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_config_hdrs",
+    srcs: [
+        "absl/base/config.h",
+        "absl/base/options.h",
+        "absl/base/policy_checks.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/config.h",
+        "my_include_dir/absl/base/options.h",
+        "my_include_dir/absl/base/policy_checks.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_config",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_config_hdrs"],
+    export_generated_headers: ["absl_base_config_hdrs"],
+
+    whole_static_libs: [
+
+    ],
+    export_static_lib_headers: [
+
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_config_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_config_hdrs"],
+    export_generated_headers: ["absl_base_config_hdrs"],
+
+    whole_static_libs: [
+
+    ],
+    export_static_lib_headers: [
+
+    ],
+
+}
+
+genrule {
+    name: "absl_time_internal_cctz_time_zone_hdrs",
+    srcs: [
+        "absl/time/internal/cctz/include/cctz/time_zone.h",
+        "absl/time/internal/cctz/include/cctz/zone_info_source.h",
+        "absl/time/internal/cctz/src/time_zone_fixed.h",
+        "absl/time/internal/cctz/src/time_zone_if.h",
+        "absl/time/internal/cctz/src/time_zone_impl.h",
+        "absl/time/internal/cctz/src/time_zone_info.h",
+        "absl/time/internal/cctz/src/time_zone_libc.h",
+        "absl/time/internal/cctz/src/time_zone_posix.h",
+        "absl/time/internal/cctz/src/tzfile.h",
+    ],
+    out: [
+        "my_include_dir/absl/time/internal/cctz/include/cctz/time_zone.h",
+        "my_include_dir/absl/time/internal/cctz/include/cctz/zone_info_source.h",
+        "my_include_dir/absl/time/internal/cctz/src/time_zone_fixed.h",
+        "my_include_dir/absl/time/internal/cctz/src/time_zone_if.h",
+        "my_include_dir/absl/time/internal/cctz/src/time_zone_impl.h",
+        "my_include_dir/absl/time/internal/cctz/src/time_zone_info.h",
+        "my_include_dir/absl/time/internal/cctz/src/time_zone_libc.h",
+        "my_include_dir/absl/time/internal/cctz/src/time_zone_posix.h",
+        "my_include_dir/absl/time/internal/cctz/src/tzfile.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_time_internal_cctz_time_zone",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/time/internal/cctz/src/time_zone_fixed.cc",
+        "absl/time/internal/cctz/src/time_zone_format.cc",
+        "absl/time/internal/cctz/src/time_zone_if.cc",
+        "absl/time/internal/cctz/src/time_zone_impl.cc",
+        "absl/time/internal/cctz/src/time_zone_info.cc",
+        "absl/time/internal/cctz/src/time_zone_libc.cc",
+        "absl/time/internal/cctz/src/time_zone_lookup.cc",
+        "absl/time/internal/cctz/src/time_zone_posix.cc",
+        "absl/time/internal/cctz/src/zone_info_source.cc",
+    ],
+    generated_headers: ["absl_time_internal_cctz_time_zone_hdrs"],
+    export_generated_headers: ["absl_time_internal_cctz_time_zone_hdrs"],
+
+    whole_static_libs: [
+        "absl_time_internal_cctz_civil_time",
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_time_internal_cctz_civil_time",
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_time_internal_cctz_time_zone_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/time/internal/cctz/src/time_zone_fixed.cc",
+        "absl/time/internal/cctz/src/time_zone_format.cc",
+        "absl/time/internal/cctz/src/time_zone_if.cc",
+        "absl/time/internal/cctz/src/time_zone_impl.cc",
+        "absl/time/internal/cctz/src/time_zone_info.cc",
+        "absl/time/internal/cctz/src/time_zone_libc.cc",
+        "absl/time/internal/cctz/src/time_zone_lookup.cc",
+        "absl/time/internal/cctz/src/time_zone_posix.cc",
+        "absl/time/internal/cctz/src/zone_info_source.cc",
+    ],
+    generated_headers: ["absl_time_internal_cctz_time_zone_hdrs"],
+    export_generated_headers: ["absl_time_internal_cctz_time_zone_hdrs"],
+
+    whole_static_libs: [
+        "absl_time_internal_cctz_civil_time_notls",
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_time_internal_cctz_civil_time_notls",
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_time_internal_cctz_civil_time_hdrs",
+    srcs: [
+        "absl/time/internal/cctz/include/cctz/civil_time.h",
+        "absl/time/internal/cctz/include/cctz/civil_time_detail.h",
+    ],
+    out: [
+        "my_include_dir/absl/time/internal/cctz/include/cctz/civil_time.h",
+        "my_include_dir/absl/time/internal/cctz/include/cctz/civil_time_detail.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_time_internal_cctz_civil_time",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/time/internal/cctz/src/civil_time_detail.cc",
+    ],
+    generated_headers: ["absl_time_internal_cctz_civil_time_hdrs"],
+    export_generated_headers: ["absl_time_internal_cctz_civil_time_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_time_internal_cctz_civil_time_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/time/internal/cctz/src/civil_time_detail.cc",
+    ],
+    generated_headers: ["absl_time_internal_cctz_civil_time_hdrs"],
+    export_generated_headers: ["absl_time_internal_cctz_civil_time_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_string_view_hdrs",
+    srcs: [
+        "absl/strings/string_view.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/string_view.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_string_view",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/strings/string_view.cc",
+    ],
+    generated_headers: ["absl_strings_string_view_hdrs"],
+    export_generated_headers: ["absl_strings_string_view_hdrs"],
+
+    whole_static_libs: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_base_throw_delegate",
+    ],
+    export_static_lib_headers: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_base_throw_delegate",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_string_view_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/strings/string_view.cc",
+    ],
+    generated_headers: ["absl_strings_string_view_hdrs"],
+    export_generated_headers: ["absl_strings_string_view_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_base_throw_delegate_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_base_throw_delegate_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_throw_delegate_hdrs",
+    srcs: [
+        "absl/base/internal/throw_delegate.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/throw_delegate.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_throw_delegate",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/base/internal/throw_delegate.cc",
+    ],
+    generated_headers: ["absl_base_throw_delegate_hdrs"],
+    export_generated_headers: ["absl_base_throw_delegate_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_raw_logging_internal",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_raw_logging_internal",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_throw_delegate_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/base/internal/throw_delegate.cc",
+    ],
+    generated_headers: ["absl_base_throw_delegate_hdrs"],
+    export_generated_headers: ["absl_base_throw_delegate_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_raw_logging_internal_hdrs",
+    srcs: [
+        "absl/base/internal/raw_logging.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/raw_logging.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_raw_logging_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/base/internal/raw_logging.cc",
+    ],
+    generated_headers: ["absl_base_raw_logging_internal_hdrs"],
+    export_generated_headers: ["absl_base_raw_logging_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_atomic_hook",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_errno_saver",
+        "absl_base_log_severity",
+    ],
+    export_static_lib_headers: [
+        "absl_base_atomic_hook",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_errno_saver",
+        "absl_base_log_severity",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_raw_logging_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/base/internal/raw_logging.cc",
+    ],
+    generated_headers: ["absl_base_raw_logging_internal_hdrs"],
+    export_generated_headers: ["absl_base_raw_logging_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_atomic_hook_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_errno_saver_notls",
+        "absl_base_log_severity_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_atomic_hook_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_errno_saver_notls",
+        "absl_base_log_severity_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_log_severity_hdrs",
+    srcs: [
+        "absl/base/log_severity.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/log_severity.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_log_severity",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/base/log_severity.cc",
+    ],
+    generated_headers: ["absl_base_log_severity_hdrs"],
+    export_generated_headers: ["absl_base_log_severity_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_log_severity_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/base/log_severity.cc",
+    ],
+    generated_headers: ["absl_base_log_severity_hdrs"],
+    export_generated_headers: ["absl_base_log_severity_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_errno_saver_hdrs",
+    srcs: [
+        "absl/base/internal/errno_saver.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/errno_saver.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_errno_saver",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_errno_saver_hdrs"],
+    export_generated_headers: ["absl_base_errno_saver_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_errno_saver_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_errno_saver_hdrs"],
+    export_generated_headers: ["absl_base_errno_saver_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_atomic_hook_hdrs",
+    srcs: [
+        "absl/base/internal/atomic_hook.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/atomic_hook.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_atomic_hook",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_atomic_hook_hdrs"],
+    export_generated_headers: ["absl_base_atomic_hook_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_atomic_hook_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_atomic_hook_hdrs"],
+    export_generated_headers: ["absl_base_atomic_hook_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_nullability_hdrs",
+    srcs: [
+        "absl/base/nullability.h",
+        "absl/base/internal/nullability_deprecated.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/nullability.h",
+        "my_include_dir/absl/base/internal/nullability_deprecated.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_nullability",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_nullability_hdrs"],
+    export_generated_headers: ["absl_base_nullability_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_nullability_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_nullability_hdrs"],
+    export_generated_headers: ["absl_base_nullability_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_hdrs",
+    srcs: [
+        "absl/base/call_once.h",
+        "absl/base/casts.h",
+        "absl/base/internal/cycleclock.h",
+        "absl/base/internal/low_level_scheduling.h",
+        "absl/base/internal/per_thread_tls.h",
+        "absl/base/internal/spinlock.h",
+        "absl/base/internal/sysinfo.h",
+        "absl/base/internal/thread_identity.h",
+        "absl/base/internal/tsan_mutex_interface.h",
+        "absl/base/internal/unscaledcycleclock.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/call_once.h",
+        "my_include_dir/absl/base/casts.h",
+        "my_include_dir/absl/base/internal/cycleclock.h",
+        "my_include_dir/absl/base/internal/low_level_scheduling.h",
+        "my_include_dir/absl/base/internal/per_thread_tls.h",
+        "my_include_dir/absl/base/internal/spinlock.h",
+        "my_include_dir/absl/base/internal/sysinfo.h",
+        "my_include_dir/absl/base/internal/thread_identity.h",
+        "my_include_dir/absl/base/internal/tsan_mutex_interface.h",
+        "my_include_dir/absl/base/internal/unscaledcycleclock.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/base/internal/cycleclock.cc",
+        "absl/base/internal/spinlock.cc",
+        "absl/base/internal/sysinfo.cc",
+        "absl/base/internal/thread_identity.cc",
+        "absl/base/internal/unscaledcycleclock.cc",
+    ],
+    generated_headers: ["absl_base_hdrs"],
+    export_generated_headers: ["absl_base_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_atomic_hook",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_cycleclock_internal",
+        "absl_base_dynamic_annotations",
+        "absl_base_log_severity",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_spinlock_wait",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_base_atomic_hook",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_cycleclock_internal",
+        "absl_base_dynamic_annotations",
+        "absl_base_log_severity",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_spinlock_wait",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/base/internal/cycleclock.cc",
+        "absl/base/internal/spinlock.cc",
+        "absl/base/internal/sysinfo.cc",
+        "absl/base/internal/thread_identity.cc",
+        "absl/base/internal/unscaledcycleclock.cc",
+    ],
+    generated_headers: ["absl_base_hdrs"],
+    export_generated_headers: ["absl_base_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_atomic_hook_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_cycleclock_internal_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_spinlock_wait_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_atomic_hook_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_cycleclock_internal_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_spinlock_wait_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_spinlock_wait_hdrs",
+    srcs: [
+        "absl/base/internal/spinlock_wait.h",
+        "absl/base/internal/spinlock_akaros.inc",
+        "absl/base/internal/spinlock_linux.inc",
+        "absl/base/internal/spinlock_posix.inc",
+        "absl/base/internal/spinlock_win32.inc",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/spinlock_wait.h",
+        "my_include_dir/absl/base/internal/spinlock_akaros.inc",
+        "my_include_dir/absl/base/internal/spinlock_linux.inc",
+        "my_include_dir/absl/base/internal/spinlock_posix.inc",
+        "my_include_dir/absl/base/internal/spinlock_win32.inc",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_spinlock_wait",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/base/internal/spinlock_wait.cc",
+    ],
+    generated_headers: ["absl_base_spinlock_wait_hdrs"],
+    export_generated_headers: ["absl_base_spinlock_wait_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_base_internal",
+        "absl_base_core_headers",
+        "absl_base_errno_saver",
+    ],
+    export_static_lib_headers: [
+        "absl_base_base_internal",
+        "absl_base_core_headers",
+        "absl_base_errno_saver",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_spinlock_wait_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/base/internal/spinlock_wait.cc",
+    ],
+    generated_headers: ["absl_base_spinlock_wait_hdrs"],
+    export_generated_headers: ["absl_base_spinlock_wait_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_base_internal_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_errno_saver_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_base_internal_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_errno_saver_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_base_internal_hdrs",
+    srcs: [
+        "absl/base/internal/hide_ptr.h",
+        "absl/base/internal/identity.h",
+        "absl/base/internal/scheduling_mode.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/hide_ptr.h",
+        "my_include_dir/absl/base/internal/identity.h",
+        "my_include_dir/absl/base/internal/scheduling_mode.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_base_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_base_internal_hdrs"],
+    export_generated_headers: ["absl_base_base_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_base_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_base_internal_hdrs"],
+    export_generated_headers: ["absl_base_base_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_dynamic_annotations_hdrs",
+    srcs: [
+        "absl/base/dynamic_annotations.h",
+        "absl/base/internal/dynamic_annotations.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/dynamic_annotations.h",
+        "my_include_dir/absl/base/internal/dynamic_annotations.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_dynamic_annotations",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_dynamic_annotations_hdrs"],
+    export_generated_headers: ["absl_base_dynamic_annotations_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_dynamic_annotations_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_dynamic_annotations_hdrs"],
+    export_generated_headers: ["absl_base_dynamic_annotations_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_cycleclock_internal_hdrs",
+    srcs: [
+        "absl/base/internal/cycleclock_config.h",
+        "absl/base/internal/unscaledcycleclock_config.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/cycleclock_config.h",
+        "my_include_dir/absl/base/internal/unscaledcycleclock_config.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_cycleclock_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_cycleclock_internal_hdrs"],
+    export_generated_headers: ["absl_base_cycleclock_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_base_internal",
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_base_internal",
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_cycleclock_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_cycleclock_internal_hdrs"],
+    export_generated_headers: ["absl_base_cycleclock_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_hdrs",
+    srcs: [
+        "absl/strings/ascii.h",
+        "absl/strings/charconv.h",
+        "absl/strings/escaping.h",
+        "absl/strings/has_absl_stringify.h",
+        "absl/strings/internal/damerau_levenshtein_distance.h",
+        "absl/strings/internal/string_constant.h",
+        "absl/strings/match.h",
+        "absl/strings/numbers.h",
+        "absl/strings/str_cat.h",
+        "absl/strings/str_join.h",
+        "absl/strings/str_replace.h",
+        "absl/strings/str_split.h",
+        "absl/strings/string_view.h",
+        "absl/strings/strip.h",
+        "absl/strings/substitute.h",
+        "absl/strings/internal/charconv_bigint.h",
+        "absl/strings/internal/charconv_parse.h",
+        "absl/strings/internal/memutil.h",
+        "absl/strings/internal/stl_type_traits.h",
+        "absl/strings/internal/str_join_internal.h",
+        "absl/strings/internal/str_split_internal.h",
+        "absl/strings/internal/stringify_sink.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/ascii.h",
+        "my_include_dir/absl/strings/charconv.h",
+        "my_include_dir/absl/strings/escaping.h",
+        "my_include_dir/absl/strings/has_absl_stringify.h",
+        "my_include_dir/absl/strings/internal/damerau_levenshtein_distance.h",
+        "my_include_dir/absl/strings/internal/string_constant.h",
+        "my_include_dir/absl/strings/match.h",
+        "my_include_dir/absl/strings/numbers.h",
+        "my_include_dir/absl/strings/str_cat.h",
+        "my_include_dir/absl/strings/str_join.h",
+        "my_include_dir/absl/strings/str_replace.h",
+        "my_include_dir/absl/strings/str_split.h",
+        "my_include_dir/absl/strings/string_view.h",
+        "my_include_dir/absl/strings/strip.h",
+        "my_include_dir/absl/strings/substitute.h",
+        "my_include_dir/absl/strings/internal/charconv_bigint.h",
+        "my_include_dir/absl/strings/internal/charconv_parse.h",
+        "my_include_dir/absl/strings/internal/memutil.h",
+        "my_include_dir/absl/strings/internal/stl_type_traits.h",
+        "my_include_dir/absl/strings/internal/str_join_internal.h",
+        "my_include_dir/absl/strings/internal/str_split_internal.h",
+        "my_include_dir/absl/strings/internal/stringify_sink.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/strings/ascii.cc",
+        "absl/strings/charconv.cc",
+        "absl/strings/escaping.cc",
+        "absl/strings/internal/charconv_bigint.cc",
+        "absl/strings/internal/charconv_parse.cc",
+        "absl/strings/internal/damerau_levenshtein_distance.cc",
+        "absl/strings/internal/memutil.cc",
+        "absl/strings/internal/stringify_sink.cc",
+        "absl/strings/match.cc",
+        "absl/strings/numbers.cc",
+        "absl/strings/str_cat.cc",
+        "absl/strings/str_replace.cc",
+        "absl/strings/str_split.cc",
+        "absl/strings/substitute.cc",
+    ],
+    generated_headers: ["absl_strings_hdrs"],
+    export_generated_headers: ["absl_strings_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_charset",
+        "absl_strings_internal",
+        "absl_strings_string_view",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_iterator_traits_internal",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_throw_delegate",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_charset",
+        "absl_strings_internal",
+        "absl_strings_string_view",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_iterator_traits_internal",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_throw_delegate",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/strings/ascii.cc",
+        "absl/strings/charconv.cc",
+        "absl/strings/escaping.cc",
+        "absl/strings/internal/charconv_bigint.cc",
+        "absl/strings/internal/charconv_parse.cc",
+        "absl/strings/internal/damerau_levenshtein_distance.cc",
+        "absl/strings/internal/memutil.cc",
+        "absl/strings/internal/stringify_sink.cc",
+        "absl/strings/match.cc",
+        "absl/strings/numbers.cc",
+        "absl/strings/str_cat.cc",
+        "absl/strings/str_replace.cc",
+        "absl/strings/str_split.cc",
+        "absl/strings/substitute.cc",
+    ],
+    generated_headers: ["absl_strings_hdrs"],
+    export_generated_headers: ["absl_strings_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_charset_notls",
+        "absl_strings_internal_notls",
+        "absl_strings_string_view_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_iterator_traits_internal_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_charset_notls",
+        "absl_strings_internal_notls",
+        "absl_strings_string_view_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_iterator_traits_internal_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_numeric_int128_hdrs",
+    srcs: [
+        "absl/numeric/int128.h",
+        "absl/numeric/int128_have_intrinsic.inc",
+        "absl/numeric/int128_no_intrinsic.inc",
+    ],
+    out: [
+        "my_include_dir/absl/numeric/int128.h",
+        "my_include_dir/absl/numeric/int128_have_intrinsic.inc",
+        "my_include_dir/absl/numeric/int128_no_intrinsic.inc",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_numeric_int128",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/numeric/int128.cc",
+    ],
+    generated_headers: ["absl_numeric_int128_hdrs"],
+    export_generated_headers: ["absl_numeric_int128_hdrs"],
+
+    whole_static_libs: [
+        "absl_numeric_bits",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_types_compare",
+    ],
+    export_static_lib_headers: [
+        "absl_numeric_bits",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_types_compare",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_numeric_int128_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/numeric/int128.cc",
+    ],
+    generated_headers: ["absl_numeric_int128_hdrs"],
+    export_generated_headers: ["absl_numeric_int128_hdrs"],
+
+    whole_static_libs: [
+        "absl_numeric_bits_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_types_compare_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_numeric_bits_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_types_compare_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_types_compare_hdrs",
+    srcs: [
+        "absl/types/compare.h",
+    ],
+    out: [
+        "my_include_dir/absl/types/compare.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_types_compare",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_types_compare_hdrs"],
+    export_generated_headers: ["absl_types_compare_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_types_compare_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_types_compare_hdrs"],
+    export_generated_headers: ["absl_types_compare_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_numeric_bits_hdrs",
+    srcs: [
+        "absl/numeric/bits.h",
+        "absl/numeric/internal/bits.h",
+    ],
+    out: [
+        "my_include_dir/absl/numeric/bits.h",
+        "my_include_dir/absl/numeric/internal/bits.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_numeric_bits",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_numeric_bits_hdrs"],
+    export_generated_headers: ["absl_numeric_bits_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_numeric_bits_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_numeric_bits_hdrs"],
+    export_generated_headers: ["absl_numeric_bits_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_endian_hdrs",
+    srcs: [
+        "absl/base/internal/endian.h",
+        "absl/base/internal/unaligned_access.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/endian.h",
+        "my_include_dir/absl/base/internal/unaligned_access.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_endian",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_endian_hdrs"],
+    export_generated_headers: ["absl_base_endian_hdrs"],
+
+    whole_static_libs: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+    ],
+    export_static_lib_headers: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_endian_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_endian_hdrs"],
+    export_generated_headers: ["absl_base_endian_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_memory_hdrs",
+    srcs: [
+        "absl/memory/memory.h",
+    ],
+    out: [
+        "my_include_dir/absl/memory/memory.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_memory",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_memory_hdrs"],
+    export_generated_headers: ["absl_memory_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_memory_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_memory_hdrs"],
+    export_generated_headers: ["absl_memory_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_iterator_traits_internal_hdrs",
+    srcs: [
+        "absl/base/internal/iterator_traits.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/iterator_traits.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_iterator_traits_internal",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_iterator_traits_internal_hdrs"],
+    export_generated_headers: ["absl_base_iterator_traits_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_iterator_traits_internal_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_iterator_traits_internal_hdrs"],
+    export_generated_headers: ["absl_base_iterator_traits_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_internal_hdrs",
+    srcs: [
+        "absl/strings/internal/escaping.h",
+        "absl/strings/internal/ostringstream.h",
+        "absl/strings/internal/resize_uninitialized.h",
+        "absl/strings/internal/utf8.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/internal/escaping.h",
+        "my_include_dir/absl/strings/internal/ostringstream.h",
+        "my_include_dir/absl/strings/internal/resize_uninitialized.h",
+        "my_include_dir/absl/strings/internal/utf8.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_internal",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/strings/internal/escaping.cc",
+        "absl/strings/internal/ostringstream.cc",
+        "absl/strings/internal/utf8.cc",
+    ],
+    generated_headers: ["absl_strings_internal_hdrs"],
+    export_generated_headers: ["absl_strings_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_raw_logging_internal",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_raw_logging_internal",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_internal_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/strings/internal/escaping.cc",
+        "absl/strings/internal/ostringstream.cc",
+        "absl/strings/internal/utf8.cc",
+    ],
+    generated_headers: ["absl_strings_internal_hdrs"],
+    export_generated_headers: ["absl_strings_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_charset_hdrs",
+    srcs: [
+        "absl/strings/charset.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/charset.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_charset",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_charset_hdrs"],
+    export_generated_headers: ["absl_strings_charset_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_string_view",
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_string_view",
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_charset_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_charset_hdrs"],
+    export_generated_headers: ["absl_strings_charset_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_string_view_notls",
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_string_view_notls",
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_symbolize_hdrs",
+    srcs: [
+        "absl/debugging/internal/symbolize.h",
+        "absl/debugging/symbolize.h",
+        "absl/debugging/symbolize_darwin.inc",
+        "absl/debugging/symbolize_elf.inc",
+        "absl/debugging/symbolize_emscripten.inc",
+        "absl/debugging/symbolize_unimplemented.inc",
+        "absl/debugging/symbolize_win32.inc",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/internal/symbolize.h",
+        "my_include_dir/absl/debugging/symbolize.h",
+        "my_include_dir/absl/debugging/symbolize_darwin.inc",
+        "my_include_dir/absl/debugging/symbolize_elf.inc",
+        "my_include_dir/absl/debugging/symbolize_emscripten.inc",
+        "my_include_dir/absl/debugging/symbolize_unimplemented.inc",
+        "my_include_dir/absl/debugging/symbolize_win32.inc",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_symbolize",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/debugging/symbolize.cc",
+    ],
+    generated_headers: ["absl_debugging_symbolize_hdrs"],
+    export_generated_headers: ["absl_debugging_symbolize_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_debugging_internal",
+        "absl_debugging_demangle_internal",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_malloc_internal",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_debugging_internal",
+        "absl_debugging_demangle_internal",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_malloc_internal",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_symbolize_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/debugging/symbolize.cc",
+    ],
+    generated_headers: ["absl_debugging_symbolize_hdrs"],
+    export_generated_headers: ["absl_debugging_symbolize_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_debugging_internal_notls",
+        "absl_debugging_demangle_internal_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_malloc_internal_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_debugging_internal_notls",
+        "absl_debugging_demangle_internal_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_malloc_internal_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_malloc_internal_hdrs",
+    srcs: [
+        "absl/base/internal/direct_mmap.h",
+        "absl/base/internal/low_level_alloc.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/direct_mmap.h",
+        "my_include_dir/absl/base/internal/low_level_alloc.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_malloc_internal",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/base/internal/low_level_alloc.cc",
+    ],
+    generated_headers: ["absl_base_malloc_internal_hdrs"],
+    export_generated_headers: ["absl_base_malloc_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_raw_logging_internal",
+    ],
+    export_static_lib_headers: [
+        "absl_base",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_raw_logging_internal",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_malloc_internal_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/base/internal/low_level_alloc.cc",
+    ],
+    generated_headers: ["absl_base_malloc_internal_hdrs"],
+    export_generated_headers: ["absl_base_malloc_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_demangle_internal_hdrs",
+    srcs: [
+        "absl/debugging/internal/demangle.h",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/internal/demangle.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_demangle_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/debugging/internal/demangle.cc",
+    ],
+    generated_headers: ["absl_debugging_demangle_internal_hdrs"],
+    export_generated_headers: ["absl_debugging_demangle_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_demangle_rust",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_numeric_bits",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_demangle_rust",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_numeric_bits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_demangle_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/debugging/internal/demangle.cc",
+    ],
+    generated_headers: ["absl_debugging_demangle_internal_hdrs"],
+    export_generated_headers: ["absl_debugging_demangle_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_demangle_rust_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_numeric_bits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_demangle_rust_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_numeric_bits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_demangle_rust_hdrs",
+    srcs: [
+        "absl/debugging/internal/demangle_rust.h",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/internal/demangle_rust.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_demangle_rust",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/debugging/internal/demangle_rust.cc",
+    ],
+    generated_headers: ["absl_debugging_demangle_rust_hdrs"],
+    export_generated_headers: ["absl_debugging_demangle_rust_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_decode_rust_punycode",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_decode_rust_punycode",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_demangle_rust_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/debugging/internal/demangle_rust.cc",
+    ],
+    generated_headers: ["absl_debugging_demangle_rust_hdrs"],
+    export_generated_headers: ["absl_debugging_demangle_rust_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_decode_rust_punycode_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_decode_rust_punycode_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_decode_rust_punycode_hdrs",
+    srcs: [
+        "absl/debugging/internal/decode_rust_punycode.h",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/internal/decode_rust_punycode.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_decode_rust_punycode",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/debugging/internal/decode_rust_punycode.cc",
+    ],
+    generated_headers: ["absl_debugging_decode_rust_punycode_hdrs"],
+    export_generated_headers: ["absl_debugging_decode_rust_punycode_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_bounded_utf8_length_sequence",
+        "absl_debugging_utf8_for_code_point",
+        "absl_base_config",
+        "absl_base_nullability",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_bounded_utf8_length_sequence",
+        "absl_debugging_utf8_for_code_point",
+        "absl_base_config",
+        "absl_base_nullability",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_decode_rust_punycode_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/debugging/internal/decode_rust_punycode.cc",
+    ],
+    generated_headers: ["absl_debugging_decode_rust_punycode_hdrs"],
+    export_generated_headers: ["absl_debugging_decode_rust_punycode_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_bounded_utf8_length_sequence_notls",
+        "absl_debugging_utf8_for_code_point_notls",
+        "absl_base_config_notls",
+        "absl_base_nullability_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_bounded_utf8_length_sequence_notls",
+        "absl_debugging_utf8_for_code_point_notls",
+        "absl_base_config_notls",
+        "absl_base_nullability_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_utf8_for_code_point_hdrs",
+    srcs: [
+        "absl/debugging/internal/utf8_for_code_point.h",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/internal/utf8_for_code_point.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_utf8_for_code_point",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/debugging/internal/utf8_for_code_point.cc",
+    ],
+    generated_headers: ["absl_debugging_utf8_for_code_point_hdrs"],
+    export_generated_headers: ["absl_debugging_utf8_for_code_point_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_utf8_for_code_point_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/debugging/internal/utf8_for_code_point.cc",
+    ],
+    generated_headers: ["absl_debugging_utf8_for_code_point_hdrs"],
+    export_generated_headers: ["absl_debugging_utf8_for_code_point_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_bounded_utf8_length_sequence_hdrs",
+    srcs: [
+        "absl/debugging/internal/bounded_utf8_length_sequence.h",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/internal/bounded_utf8_length_sequence.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_bounded_utf8_length_sequence",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_debugging_bounded_utf8_length_sequence_hdrs"],
+    export_generated_headers: ["absl_debugging_bounded_utf8_length_sequence_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_numeric_bits",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_numeric_bits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_bounded_utf8_length_sequence_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_debugging_bounded_utf8_length_sequence_hdrs"],
+    export_generated_headers: ["absl_debugging_bounded_utf8_length_sequence_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_numeric_bits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_numeric_bits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_debugging_internal_hdrs",
+    srcs: [
+        "absl/debugging/internal/address_is_readable.h",
+        "absl/debugging/internal/addresses.h",
+        "absl/debugging/internal/elf_mem_image.h",
+        "absl/debugging/internal/vdso_support.h",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/internal/address_is_readable.h",
+        "my_include_dir/absl/debugging/internal/addresses.h",
+        "my_include_dir/absl/debugging/internal/elf_mem_image.h",
+        "my_include_dir/absl/debugging/internal/vdso_support.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_debugging_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/debugging/internal/address_is_readable.cc",
+        "absl/debugging/internal/elf_mem_image.cc",
+        "absl/debugging/internal/vdso_support.cc",
+    ],
+    generated_headers: ["absl_debugging_debugging_internal_hdrs"],
+    export_generated_headers: ["absl_debugging_debugging_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_errno_saver",
+        "absl_base_raw_logging_internal",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_errno_saver",
+        "absl_base_raw_logging_internal",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_debugging_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/debugging/internal/address_is_readable.cc",
+        "absl/debugging/internal/elf_mem_image.cc",
+        "absl/debugging/internal/vdso_support.cc",
+    ],
+    generated_headers: ["absl_debugging_debugging_internal_hdrs"],
+    export_generated_headers: ["absl_debugging_debugging_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_errno_saver_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_errno_saver_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_stacktrace_hdrs",
+    srcs: [
+        "absl/debugging/stacktrace.h",
+        "absl/debugging/internal/stacktrace_aarch64-inl.inc",
+        "absl/debugging/internal/stacktrace_arm-inl.inc",
+        "absl/debugging/internal/stacktrace_config.h",
+        "absl/debugging/internal/stacktrace_emscripten-inl.inc",
+        "absl/debugging/internal/stacktrace_generic-inl.inc",
+        "absl/debugging/internal/stacktrace_powerpc-inl.inc",
+        "absl/debugging/internal/stacktrace_riscv-inl.inc",
+        "absl/debugging/internal/stacktrace_unimplemented-inl.inc",
+        "absl/debugging/internal/stacktrace_win32-inl.inc",
+        "absl/debugging/internal/stacktrace_x86-inl.inc",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/stacktrace.h",
+        "my_include_dir/absl/debugging/internal/stacktrace_aarch64-inl.inc",
+        "my_include_dir/absl/debugging/internal/stacktrace_arm-inl.inc",
+        "my_include_dir/absl/debugging/internal/stacktrace_config.h",
+        "my_include_dir/absl/debugging/internal/stacktrace_emscripten-inl.inc",
+        "my_include_dir/absl/debugging/internal/stacktrace_generic-inl.inc",
+        "my_include_dir/absl/debugging/internal/stacktrace_powerpc-inl.inc",
+        "my_include_dir/absl/debugging/internal/stacktrace_riscv-inl.inc",
+        "my_include_dir/absl/debugging/internal/stacktrace_unimplemented-inl.inc",
+        "my_include_dir/absl/debugging/internal/stacktrace_win32-inl.inc",
+        "my_include_dir/absl/debugging/internal/stacktrace_x86-inl.inc",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_stacktrace",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/debugging/stacktrace.cc",
+    ],
+    generated_headers: ["absl_debugging_stacktrace_hdrs"],
+    export_generated_headers: ["absl_debugging_stacktrace_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_debugging_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_raw_logging_internal",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_debugging_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_raw_logging_internal",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_stacktrace_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/debugging/stacktrace.cc",
+    ],
+    generated_headers: ["absl_debugging_stacktrace_hdrs"],
+    export_generated_headers: ["absl_debugging_stacktrace_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_debugging_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_debugging_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_tracing_internal_hdrs",
+    srcs: [
+        "absl/base/internal/tracing.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/tracing.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_tracing_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/base/internal/tracing.cc",
+    ],
+    generated_headers: ["absl_base_tracing_internal_hdrs"],
+    export_generated_headers: ["absl_base_tracing_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_tracing_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/base/internal/tracing.cc",
+    ],
+    generated_headers: ["absl_base_tracing_internal_hdrs"],
+    export_generated_headers: ["absl_base_tracing_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_synchronization_kernel_timeout_internal_hdrs",
+    srcs: [
+        "absl/synchronization/internal/kernel_timeout.h",
+    ],
+    out: [
+        "my_include_dir/absl/synchronization/internal/kernel_timeout.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_synchronization_kernel_timeout_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/synchronization/internal/kernel_timeout.cc",
+    ],
+    generated_headers: ["absl_synchronization_kernel_timeout_internal_hdrs"],
+    export_generated_headers: ["absl_synchronization_kernel_timeout_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_time",
+    ],
+    export_static_lib_headers: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_time",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_synchronization_kernel_timeout_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/synchronization/internal/kernel_timeout.cc",
+    ],
+    generated_headers: ["absl_synchronization_kernel_timeout_internal_hdrs"],
+    export_generated_headers: ["absl_synchronization_kernel_timeout_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_time_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_time_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_synchronization_graphcycles_internal_hdrs",
+    srcs: [
+        "absl/synchronization/internal/graphcycles.h",
+    ],
+    out: [
+        "my_include_dir/absl/synchronization/internal/graphcycles.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_synchronization_graphcycles_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/synchronization/internal/graphcycles.cc",
+    ],
+    generated_headers: ["absl_synchronization_graphcycles_internal_hdrs"],
+    export_generated_headers: ["absl_synchronization_graphcycles_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_malloc_internal",
+        "absl_base_raw_logging_internal",
+    ],
+    export_static_lib_headers: [
+        "absl_base",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_malloc_internal",
+        "absl_base_raw_logging_internal",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_synchronization_graphcycles_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/synchronization/internal/graphcycles.cc",
+    ],
+    generated_headers: ["absl_synchronization_graphcycles_internal_hdrs"],
+    export_generated_headers: ["absl_synchronization_graphcycles_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_malloc_internal_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_malloc_internal_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_status_statusor_hdrs",
+    srcs: [
+        "absl/status/statusor.h",
+        "absl/status/internal/statusor_internal.h",
+    ],
+    out: [
+        "my_include_dir/absl/status/statusor.h",
+        "my_include_dir/absl/status/internal/statusor_internal.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_status_statusor",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/status/statusor.cc",
+    ],
+    generated_headers: ["absl_status_statusor_hdrs"],
+    export_generated_headers: ["absl_status_statusor_hdrs"],
+
+    whole_static_libs: [
+        "absl_status",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_strings_has_ostream_operator",
+        "absl_strings_str_format",
+        "absl_types_variant",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_status",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_strings_has_ostream_operator",
+        "absl_strings_str_format",
+        "absl_types_variant",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_status_statusor_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/status/statusor.cc",
+    ],
+    generated_headers: ["absl_status_statusor_hdrs"],
+    export_generated_headers: ["absl_status_statusor_hdrs"],
+
+    whole_static_libs: [
+        "absl_status_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_strings_has_ostream_operator_notls",
+        "absl_strings_str_format_notls",
+        "absl_types_variant_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_status_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_strings_has_ostream_operator_notls",
+        "absl_strings_str_format_notls",
+        "absl_types_variant_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_types_variant_hdrs",
+    srcs: [
+        "absl/types/variant.h",
+    ],
+    out: [
+        "my_include_dir/absl/types/variant.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_types_variant",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_types_variant_hdrs"],
+    export_generated_headers: ["absl_types_variant_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_types_variant_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_types_variant_hdrs"],
+    export_generated_headers: ["absl_types_variant_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_str_format_hdrs",
+    srcs: [
+        "absl/strings/str_format.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/str_format.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_str_format",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_str_format_hdrs"],
+    export_generated_headers: ["absl_strings_str_format_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_str_format_internal",
+        "absl_strings_string_view",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_str_format_internal",
+        "absl_strings_string_view",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_str_format_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_str_format_hdrs"],
+    export_generated_headers: ["absl_strings_str_format_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_str_format_internal_notls",
+        "absl_strings_string_view_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_str_format_internal_notls",
+        "absl_strings_string_view_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_types_span_hdrs",
+    srcs: [
+        "absl/types/span.h",
+        "absl/types/internal/span.h",
+    ],
+    out: [
+        "my_include_dir/absl/types/span.h",
+        "my_include_dir/absl/types/internal/span.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_types_span",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_types_span_hdrs"],
+    export_generated_headers: ["absl_types_span_hdrs"],
+
+    whole_static_libs: [
+        "absl_algorithm",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_base_throw_delegate",
+        "absl_hash_weakly_mixed_integer",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_algorithm",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_base_throw_delegate",
+        "absl_hash_weakly_mixed_integer",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_types_span_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_types_span_hdrs"],
+    export_generated_headers: ["absl_types_span_hdrs"],
+
+    whole_static_libs: [
+        "absl_algorithm_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_algorithm_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_hash_weakly_mixed_integer_hdrs",
+    srcs: [
+        "absl/hash/internal/weakly_mixed_integer.h",
+    ],
+    out: [
+        "my_include_dir/absl/hash/internal/weakly_mixed_integer.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_hash_weakly_mixed_integer",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_hash_weakly_mixed_integer_hdrs"],
+    export_generated_headers: ["absl_hash_weakly_mixed_integer_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_hash_weakly_mixed_integer_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_hash_weakly_mixed_integer_hdrs"],
+    export_generated_headers: ["absl_hash_weakly_mixed_integer_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_algorithm_hdrs",
+    srcs: [
+        "absl/algorithm/algorithm.h",
+    ],
+    out: [
+        "my_include_dir/absl/algorithm/algorithm.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_algorithm",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_algorithm_hdrs"],
+    export_generated_headers: ["absl_algorithm_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_algorithm_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_algorithm_hdrs"],
+    export_generated_headers: ["absl_algorithm_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_str_format_internal_hdrs",
+    srcs: [
+        "absl/strings/internal/str_format/arg.h",
+        "absl/strings/internal/str_format/bind.h",
+        "absl/strings/internal/str_format/checker.h",
+        "absl/strings/internal/str_format/constexpr_parser.h",
+        "absl/strings/internal/str_format/extension.h",
+        "absl/strings/internal/str_format/float_conversion.h",
+        "absl/strings/internal/str_format/output.h",
+        "absl/strings/internal/str_format/parser.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/internal/str_format/arg.h",
+        "my_include_dir/absl/strings/internal/str_format/bind.h",
+        "my_include_dir/absl/strings/internal/str_format/checker.h",
+        "my_include_dir/absl/strings/internal/str_format/constexpr_parser.h",
+        "my_include_dir/absl/strings/internal/str_format/extension.h",
+        "my_include_dir/absl/strings/internal/str_format/float_conversion.h",
+        "my_include_dir/absl/strings/internal/str_format/output.h",
+        "my_include_dir/absl/strings/internal/str_format/parser.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_str_format_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/strings/internal/str_format/arg.cc",
+        "absl/strings/internal/str_format/bind.cc",
+        "absl/strings/internal/str_format/extension.cc",
+        "absl/strings/internal/str_format/float_conversion.cc",
+        "absl/strings/internal/str_format/output.cc",
+        "absl/strings/internal/str_format/parser.cc",
+    ],
+    generated_headers: ["absl_strings_str_format_internal_hdrs"],
+    export_generated_headers: ["absl_strings_str_format_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_internal",
+        "absl_strings",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_container_fixed_array",
+        "absl_container_inlined_vector",
+        "absl_functional_function_ref",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+        "absl_numeric_representation",
+        "absl_types_optional",
+        "absl_types_span",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_internal",
+        "absl_strings",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_container_fixed_array",
+        "absl_container_inlined_vector",
+        "absl_functional_function_ref",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+        "absl_numeric_representation",
+        "absl_types_optional",
+        "absl_types_span",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_str_format_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/strings/internal/str_format/arg.cc",
+        "absl/strings/internal/str_format/bind.cc",
+        "absl/strings/internal/str_format/extension.cc",
+        "absl/strings/internal/str_format/float_conversion.cc",
+        "absl/strings/internal/str_format/output.cc",
+        "absl/strings/internal/str_format/parser.cc",
+    ],
+    generated_headers: ["absl_strings_str_format_internal_hdrs"],
+    export_generated_headers: ["absl_strings_str_format_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_internal_notls",
+        "absl_strings_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_container_fixed_array_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_functional_function_ref_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+        "absl_numeric_representation_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_internal_notls",
+        "absl_strings_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_container_fixed_array_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_functional_function_ref_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+        "absl_numeric_representation_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_numeric_representation_hdrs",
+    srcs: [
+        "absl/numeric/internal/representation.h",
+    ],
+    out: [
+        "my_include_dir/absl/numeric/internal/representation.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_numeric_representation",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_numeric_representation_hdrs"],
+    export_generated_headers: ["absl_numeric_representation_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_numeric_representation_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_numeric_representation_hdrs"],
+    export_generated_headers: ["absl_numeric_representation_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_functional_function_ref_hdrs",
+    srcs: [
+        "absl/functional/function_ref.h",
+        "absl/functional/internal/function_ref.h",
+    ],
+    out: [
+        "my_include_dir/absl/functional/function_ref.h",
+        "my_include_dir/absl/functional/internal/function_ref.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_functional_function_ref",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_functional_function_ref_hdrs"],
+    export_generated_headers: ["absl_functional_function_ref_hdrs"],
+
+    whole_static_libs: [
+        "absl_functional_any_invocable",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_functional_any_invocable",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_functional_function_ref_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_functional_function_ref_hdrs"],
+    export_generated_headers: ["absl_functional_function_ref_hdrs"],
+
+    whole_static_libs: [
+        "absl_functional_any_invocable_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_functional_any_invocable_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_functional_any_invocable_hdrs",
+    srcs: [
+        "absl/functional/any_invocable.h",
+        "absl/functional/internal/any_invocable.h",
+    ],
+    out: [
+        "my_include_dir/absl/functional/any_invocable.h",
+        "my_include_dir/absl/functional/internal/any_invocable.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_functional_any_invocable",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_functional_any_invocable_hdrs"],
+    export_generated_headers: ["absl_functional_any_invocable_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_functional_any_invocable_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_functional_any_invocable_hdrs"],
+    export_generated_headers: ["absl_functional_any_invocable_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_inlined_vector_hdrs",
+    srcs: [
+        "absl/container/inlined_vector.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/inlined_vector.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_inlined_vector",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_inlined_vector_hdrs"],
+    export_generated_headers: ["absl_container_inlined_vector_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_inlined_vector_internal",
+        "absl_algorithm",
+        "absl_base_core_headers",
+        "absl_base_iterator_traits_internal",
+        "absl_base_throw_delegate",
+        "absl_hash_weakly_mixed_integer",
+        "absl_memory",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_container_inlined_vector_internal",
+        "absl_algorithm",
+        "absl_base_core_headers",
+        "absl_base_iterator_traits_internal",
+        "absl_base_throw_delegate",
+        "absl_hash_weakly_mixed_integer",
+        "absl_memory",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_inlined_vector_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_inlined_vector_hdrs"],
+    export_generated_headers: ["absl_container_inlined_vector_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_inlined_vector_internal_notls",
+        "absl_algorithm_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_iterator_traits_internal_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_inlined_vector_internal_notls",
+        "absl_algorithm_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_iterator_traits_internal_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_inlined_vector_internal_hdrs",
+    srcs: [
+        "absl/container/internal/inlined_vector.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/inlined_vector.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_inlined_vector_internal",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_inlined_vector_internal_hdrs"],
+    export_generated_headers: ["absl_container_inlined_vector_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_compressed_tuple",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_container_compressed_tuple",
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_inlined_vector_internal_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_inlined_vector_internal_hdrs"],
+    export_generated_headers: ["absl_container_inlined_vector_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_compressed_tuple_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_compressed_tuple_notls",
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_compressed_tuple_hdrs",
+    srcs: [
+        "absl/container/internal/compressed_tuple.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/compressed_tuple.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_compressed_tuple",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_compressed_tuple_hdrs"],
+    export_generated_headers: ["absl_container_compressed_tuple_hdrs"],
+
+    whole_static_libs: [
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_compressed_tuple_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_compressed_tuple_hdrs"],
+    export_generated_headers: ["absl_container_compressed_tuple_hdrs"],
+
+    whole_static_libs: [
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_fixed_array_hdrs",
+    srcs: [
+        "absl/container/fixed_array.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/fixed_array.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_fixed_array",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_fixed_array_hdrs"],
+    export_generated_headers: ["absl_container_fixed_array_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_compressed_tuple",
+        "absl_algorithm",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_iterator_traits_internal",
+        "absl_base_throw_delegate",
+        "absl_hash_weakly_mixed_integer",
+        "absl_memory",
+    ],
+    export_static_lib_headers: [
+        "absl_container_compressed_tuple",
+        "absl_algorithm",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_iterator_traits_internal",
+        "absl_base_throw_delegate",
+        "absl_hash_weakly_mixed_integer",
+        "absl_memory",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_fixed_array_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_fixed_array_hdrs"],
+    export_generated_headers: ["absl_container_fixed_array_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_compressed_tuple_notls",
+        "absl_algorithm_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_iterator_traits_internal_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_memory_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_compressed_tuple_notls",
+        "absl_algorithm_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_iterator_traits_internal_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_memory_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_has_ostream_operator_hdrs",
+    srcs: [
+        "absl/strings/has_ostream_operator.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/has_ostream_operator.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_has_ostream_operator",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_has_ostream_operator_hdrs"],
+    export_generated_headers: ["absl_strings_has_ostream_operator_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_has_ostream_operator_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_has_ostream_operator_hdrs"],
+    export_generated_headers: ["absl_strings_has_ostream_operator_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_status_hdrs",
+    srcs: [
+        "absl/status/status.h",
+        "absl/status/status_payload_printer.h",
+        "absl/status/internal/status_internal.h",
+    ],
+    out: [
+        "my_include_dir/absl/status/status.h",
+        "my_include_dir/absl/status/status_payload_printer.h",
+        "my_include_dir/absl/status/internal/status_internal.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_status",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/status/internal/status_internal.cc",
+        "absl/status/status.cc",
+        "absl/status/status_payload_printer.cc",
+    ],
+    generated_headers: ["absl_status_hdrs"],
+    export_generated_headers: ["absl_status_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_atomic_hook",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_strerror",
+        "absl_container_inlined_vector",
+        "absl_debugging_leak_check",
+        "absl_debugging_stacktrace",
+        "absl_debugging_symbolize",
+        "absl_functional_function_ref",
+        "absl_memory",
+        "absl_strings",
+        "absl_strings_cord",
+        "absl_strings_str_format",
+        "absl_types_optional",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_base_atomic_hook",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_strerror",
+        "absl_container_inlined_vector",
+        "absl_debugging_leak_check",
+        "absl_debugging_stacktrace",
+        "absl_debugging_symbolize",
+        "absl_functional_function_ref",
+        "absl_memory",
+        "absl_strings",
+        "absl_strings_cord",
+        "absl_strings_str_format",
+        "absl_types_optional",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_status_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/status/internal/status_internal.cc",
+        "absl/status/status.cc",
+        "absl/status/status_payload_printer.cc",
+    ],
+    generated_headers: ["absl_status_hdrs"],
+    export_generated_headers: ["absl_status_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_atomic_hook_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_strerror_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_debugging_leak_check_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_debugging_symbolize_notls",
+        "absl_functional_function_ref_notls",
+        "absl_memory_notls",
+        "absl_strings_notls",
+        "absl_strings_cord_notls",
+        "absl_strings_str_format_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_atomic_hook_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_strerror_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_debugging_leak_check_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_debugging_symbolize_notls",
+        "absl_functional_function_ref_notls",
+        "absl_memory_notls",
+        "absl_strings_notls",
+        "absl_strings_cord_notls",
+        "absl_strings_str_format_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_cord_hdrs",
+    srcs: [
+        "absl/strings/cord.h",
+        "absl/strings/cord_buffer.h",
+        "absl/strings/cord_analysis.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/cord.h",
+        "my_include_dir/absl/strings/cord_buffer.h",
+        "my_include_dir/absl/strings/cord_analysis.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_cord",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/strings/cord.cc",
+        "absl/strings/cord_analysis.cc",
+    ],
+    generated_headers: ["absl_strings_cord_hdrs"],
+    export_generated_headers: ["absl_strings_cord_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_cord_internal",
+        "absl_strings_cordz_info",
+        "absl_strings_cordz_update_scope",
+        "absl_strings_cordz_update_tracker",
+        "absl_strings_internal",
+        "absl_strings",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_container_inlined_vector",
+        "absl_crc_crc32c",
+        "absl_crc_crc_cord_state",
+        "absl_functional_function_ref",
+        "absl_hash_weakly_mixed_integer",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_types_compare",
+        "absl_types_optional",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_cord_internal",
+        "absl_strings_cordz_info",
+        "absl_strings_cordz_update_scope",
+        "absl_strings_cordz_update_tracker",
+        "absl_strings_internal",
+        "absl_strings",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_container_inlined_vector",
+        "absl_crc_crc32c",
+        "absl_crc_crc_cord_state",
+        "absl_functional_function_ref",
+        "absl_hash_weakly_mixed_integer",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_types_compare",
+        "absl_types_optional",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_cord_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/strings/cord.cc",
+        "absl/strings/cord_analysis.cc",
+    ],
+    generated_headers: ["absl_strings_cord_hdrs"],
+    export_generated_headers: ["absl_strings_cord_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_cord_internal_notls",
+        "absl_strings_cordz_info_notls",
+        "absl_strings_cordz_update_scope_notls",
+        "absl_strings_cordz_update_tracker_notls",
+        "absl_strings_internal_notls",
+        "absl_strings_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_crc_crc32c_notls",
+        "absl_crc_crc_cord_state_notls",
+        "absl_functional_function_ref_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_types_compare_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_cord_internal_notls",
+        "absl_strings_cordz_info_notls",
+        "absl_strings_cordz_update_scope_notls",
+        "absl_strings_cordz_update_tracker_notls",
+        "absl_strings_internal_notls",
+        "absl_strings_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_crc_crc32c_notls",
+        "absl_crc_crc_cord_state_notls",
+        "absl_functional_function_ref_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_types_compare_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_crc_crc_cord_state_hdrs",
+    srcs: [
+        "absl/crc/internal/crc_cord_state.h",
+    ],
+    out: [
+        "my_include_dir/absl/crc/internal/crc_cord_state.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_crc_crc_cord_state",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/crc/internal/crc_cord_state.cc",
+    ],
+    generated_headers: ["absl_crc_crc_cord_state_hdrs"],
+    export_generated_headers: ["absl_crc_crc_cord_state_hdrs"],
+
+    whole_static_libs: [
+        "absl_crc_crc32c",
+        "absl_base_config",
+        "absl_base_no_destructor",
+        "absl_numeric_bits",
+    ],
+    export_static_lib_headers: [
+        "absl_crc_crc32c",
+        "absl_base_config",
+        "absl_base_no_destructor",
+        "absl_numeric_bits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_crc_crc_cord_state_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/crc/internal/crc_cord_state.cc",
+    ],
+    generated_headers: ["absl_crc_crc_cord_state_hdrs"],
+    export_generated_headers: ["absl_crc_crc_cord_state_hdrs"],
+
+    whole_static_libs: [
+        "absl_crc_crc32c_notls",
+        "absl_base_config_notls",
+        "absl_base_no_destructor_notls",
+        "absl_numeric_bits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_crc_crc32c_notls",
+        "absl_base_config_notls",
+        "absl_base_no_destructor_notls",
+        "absl_numeric_bits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_no_destructor_hdrs",
+    srcs: [
+        "absl/base/no_destructor.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/no_destructor.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_no_destructor",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_no_destructor_hdrs"],
+    export_generated_headers: ["absl_base_no_destructor_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_nullability",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_nullability",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_no_destructor_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_no_destructor_hdrs"],
+    export_generated_headers: ["absl_base_no_destructor_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_nullability_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_nullability_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_crc_crc32c_hdrs",
+    srcs: [
+        "absl/crc/crc32c.h",
+        "absl/crc/internal/crc32c.h",
+        "absl/crc/internal/crc_memcpy.h",
+        "absl/crc/internal/crc32c_inline.h",
+    ],
+    out: [
+        "my_include_dir/absl/crc/crc32c.h",
+        "my_include_dir/absl/crc/internal/crc32c.h",
+        "my_include_dir/absl/crc/internal/crc_memcpy.h",
+        "my_include_dir/absl/crc/internal/crc32c_inline.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_crc_crc32c",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/crc/crc32c.cc",
+        "absl/crc/internal/crc_memcpy_fallback.cc",
+        "absl/crc/internal/crc_memcpy_x86_arm_combined.cc",
+        "absl/crc/internal/crc_non_temporal_memcpy.cc",
+    ],
+    generated_headers: ["absl_crc_crc32c_hdrs"],
+    export_generated_headers: ["absl_crc_crc32c_hdrs"],
+
+    whole_static_libs: [
+        "absl_crc_cpu_detect",
+        "absl_crc_crc_internal",
+        "absl_crc_non_temporal_memcpy",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_prefetch",
+        "absl_strings",
+        "absl_strings_str_format",
+    ],
+    export_static_lib_headers: [
+        "absl_crc_cpu_detect",
+        "absl_crc_crc_internal",
+        "absl_crc_non_temporal_memcpy",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_prefetch",
+        "absl_strings",
+        "absl_strings_str_format",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_crc_crc32c_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/crc/crc32c.cc",
+        "absl/crc/internal/crc_memcpy_fallback.cc",
+        "absl/crc/internal/crc_memcpy_x86_arm_combined.cc",
+        "absl/crc/internal/crc_non_temporal_memcpy.cc",
+    ],
+    generated_headers: ["absl_crc_crc32c_hdrs"],
+    export_generated_headers: ["absl_crc_crc32c_hdrs"],
+
+    whole_static_libs: [
+        "absl_crc_cpu_detect_notls",
+        "absl_crc_crc_internal_notls",
+        "absl_crc_non_temporal_memcpy_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_prefetch_notls",
+        "absl_strings_notls",
+        "absl_strings_str_format_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_crc_cpu_detect_notls",
+        "absl_crc_crc_internal_notls",
+        "absl_crc_non_temporal_memcpy_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_prefetch_notls",
+        "absl_strings_notls",
+        "absl_strings_str_format_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_prefetch_hdrs",
+    srcs: [
+        "absl/base/prefetch.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/prefetch.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_prefetch",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_prefetch_hdrs"],
+    export_generated_headers: ["absl_base_prefetch_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_prefetch_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_prefetch_hdrs"],
+    export_generated_headers: ["absl_base_prefetch_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_crc_non_temporal_memcpy_hdrs",
+    srcs: [
+        "absl/crc/internal/non_temporal_memcpy.h",
+    ],
+    out: [
+        "my_include_dir/absl/crc/internal/non_temporal_memcpy.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_crc_non_temporal_memcpy",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_crc_non_temporal_memcpy_hdrs"],
+    export_generated_headers: ["absl_crc_non_temporal_memcpy_hdrs"],
+
+    whole_static_libs: [
+        "absl_crc_non_temporal_arm_intrinsics",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_crc_non_temporal_arm_intrinsics",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_crc_non_temporal_memcpy_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_crc_non_temporal_memcpy_hdrs"],
+    export_generated_headers: ["absl_crc_non_temporal_memcpy_hdrs"],
+
+    whole_static_libs: [
+        "absl_crc_non_temporal_arm_intrinsics_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_crc_non_temporal_arm_intrinsics_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_crc_non_temporal_arm_intrinsics_hdrs",
+    srcs: [
+        "absl/crc/internal/non_temporal_arm_intrinsics.h",
+    ],
+    out: [
+        "my_include_dir/absl/crc/internal/non_temporal_arm_intrinsics.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_crc_non_temporal_arm_intrinsics",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_crc_non_temporal_arm_intrinsics_hdrs"],
+    export_generated_headers: ["absl_crc_non_temporal_arm_intrinsics_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_crc_non_temporal_arm_intrinsics_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_crc_non_temporal_arm_intrinsics_hdrs"],
+    export_generated_headers: ["absl_crc_non_temporal_arm_intrinsics_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_crc_crc_internal_hdrs",
+    srcs: [
+        "absl/crc/internal/crc.h",
+        "absl/crc/internal/crc32_x86_arm_combined_simd.h",
+        "absl/crc/internal/crc_internal.h",
+    ],
+    out: [
+        "my_include_dir/absl/crc/internal/crc.h",
+        "my_include_dir/absl/crc/internal/crc32_x86_arm_combined_simd.h",
+        "my_include_dir/absl/crc/internal/crc_internal.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_crc_crc_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/crc/internal/crc.cc",
+        "absl/crc/internal/crc_x86_arm_combined.cc",
+    ],
+    generated_headers: ["absl_crc_crc_internal_hdrs"],
+    export_generated_headers: ["absl_crc_crc_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_crc_cpu_detect",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_prefetch",
+        "absl_base_raw_logging_internal",
+        "absl_memory",
+        "absl_numeric_bits",
+    ],
+    export_static_lib_headers: [
+        "absl_crc_cpu_detect",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_prefetch",
+        "absl_base_raw_logging_internal",
+        "absl_memory",
+        "absl_numeric_bits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_crc_crc_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/crc/internal/crc.cc",
+        "absl/crc/internal/crc_x86_arm_combined.cc",
+    ],
+    generated_headers: ["absl_crc_crc_internal_hdrs"],
+    export_generated_headers: ["absl_crc_crc_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_crc_cpu_detect_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_prefetch_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_memory_notls",
+        "absl_numeric_bits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_crc_cpu_detect_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_prefetch_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_memory_notls",
+        "absl_numeric_bits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_crc_cpu_detect_hdrs",
+    srcs: [
+        "absl/crc/internal/cpu_detect.h",
+    ],
+    out: [
+        "my_include_dir/absl/crc/internal/cpu_detect.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_crc_cpu_detect",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/crc/internal/cpu_detect.cc",
+    ],
+    generated_headers: ["absl_crc_cpu_detect_hdrs"],
+    export_generated_headers: ["absl_crc_cpu_detect_hdrs"],
+
+    whole_static_libs: [
+        "absl_base",
+        "absl_base_config",
+        "absl_types_optional",
+    ],
+    export_static_lib_headers: [
+        "absl_base",
+        "absl_base_config",
+        "absl_types_optional",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_crc_cpu_detect_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/crc/internal/cpu_detect.cc",
+    ],
+    generated_headers: ["absl_crc_cpu_detect_hdrs"],
+    export_generated_headers: ["absl_crc_cpu_detect_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_types_optional_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_types_optional_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_cordz_update_tracker_hdrs",
+    srcs: [
+        "absl/strings/internal/cordz_update_tracker.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/internal/cordz_update_tracker.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_update_tracker",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_cordz_update_tracker_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_update_tracker_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_update_tracker_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_cordz_update_tracker_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_update_tracker_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_cordz_update_scope_hdrs",
+    srcs: [
+        "absl/strings/internal/cordz_update_scope.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/internal/cordz_update_scope.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_update_scope",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_cordz_update_scope_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_update_scope_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_cord_internal",
+        "absl_strings_cordz_info",
+        "absl_strings_cordz_update_tracker",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_cord_internal",
+        "absl_strings_cordz_info",
+        "absl_strings_cordz_update_tracker",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_update_scope_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_cordz_update_scope_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_update_scope_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_cord_internal_notls",
+        "absl_strings_cordz_info_notls",
+        "absl_strings_cordz_update_tracker_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_cord_internal_notls",
+        "absl_strings_cordz_info_notls",
+        "absl_strings_cordz_update_tracker_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_cordz_info_hdrs",
+    srcs: [
+        "absl/strings/internal/cordz_info.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/internal/cordz_info.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_info",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/strings/internal/cordz_info.cc",
+    ],
+    generated_headers: ["absl_strings_cordz_info_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_info_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_cord_internal",
+        "absl_strings_cordz_functions",
+        "absl_strings_cordz_handle",
+        "absl_strings_cordz_statistics",
+        "absl_strings_cordz_update_tracker",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_container_inlined_vector",
+        "absl_debugging_stacktrace",
+        "absl_synchronization",
+        "absl_time",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_cord_internal",
+        "absl_strings_cordz_functions",
+        "absl_strings_cordz_handle",
+        "absl_strings_cordz_statistics",
+        "absl_strings_cordz_update_tracker",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_container_inlined_vector",
+        "absl_debugging_stacktrace",
+        "absl_synchronization",
+        "absl_time",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_info_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/strings/internal/cordz_info.cc",
+    ],
+    generated_headers: ["absl_strings_cordz_info_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_info_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_cord_internal_notls",
+        "absl_strings_cordz_functions_notls",
+        "absl_strings_cordz_handle_notls",
+        "absl_strings_cordz_statistics_notls",
+        "absl_strings_cordz_update_tracker_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_synchronization_notls",
+        "absl_time_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_cord_internal_notls",
+        "absl_strings_cordz_functions_notls",
+        "absl_strings_cordz_handle_notls",
+        "absl_strings_cordz_statistics_notls",
+        "absl_strings_cordz_update_tracker_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_synchronization_notls",
+        "absl_time_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_cordz_statistics_hdrs",
+    srcs: [
+        "absl/strings/internal/cordz_statistics.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/internal/cordz_statistics.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_statistics",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_cordz_statistics_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_statistics_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_cordz_update_tracker",
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_cordz_update_tracker",
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_statistics_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_strings_cordz_statistics_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_statistics_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_cordz_update_tracker_notls",
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_cordz_update_tracker_notls",
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_cordz_handle_hdrs",
+    srcs: [
+        "absl/strings/internal/cordz_handle.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/internal/cordz_handle.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_handle",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/strings/internal/cordz_handle.cc",
+    ],
+    generated_headers: ["absl_strings_cordz_handle_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_handle_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_no_destructor",
+        "absl_base_raw_logging_internal",
+        "absl_synchronization",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_no_destructor",
+        "absl_base_raw_logging_internal",
+        "absl_synchronization",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_handle_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/strings/internal/cordz_handle.cc",
+    ],
+    generated_headers: ["absl_strings_cordz_handle_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_handle_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_synchronization_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_synchronization_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_cordz_functions_hdrs",
+    srcs: [
+        "absl/strings/internal/cordz_functions.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/internal/cordz_functions.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_functions",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/strings/internal/cordz_functions.cc",
+    ],
+    generated_headers: ["absl_strings_cordz_functions_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_functions_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_profiling_exponential_biased",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_profiling_exponential_biased",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_cordz_functions_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/strings/internal/cordz_functions.cc",
+    ],
+    generated_headers: ["absl_strings_cordz_functions_hdrs"],
+    export_generated_headers: ["absl_strings_cordz_functions_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_profiling_exponential_biased_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_profiling_exponential_biased_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_profiling_exponential_biased_hdrs",
+    srcs: [
+        "absl/profiling/internal/exponential_biased.h",
+    ],
+    out: [
+        "my_include_dir/absl/profiling/internal/exponential_biased.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_profiling_exponential_biased",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/profiling/internal/exponential_biased.cc",
+    ],
+    generated_headers: ["absl_profiling_exponential_biased_hdrs"],
+    export_generated_headers: ["absl_profiling_exponential_biased_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_profiling_exponential_biased_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/profiling/internal/exponential_biased.cc",
+    ],
+    generated_headers: ["absl_profiling_exponential_biased_hdrs"],
+    export_generated_headers: ["absl_profiling_exponential_biased_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_strings_cord_internal_hdrs",
+    srcs: [
+        "absl/strings/internal/cord_data_edge.h",
+        "absl/strings/internal/cord_internal.h",
+        "absl/strings/internal/cord_rep_btree.h",
+        "absl/strings/internal/cord_rep_btree_navigator.h",
+        "absl/strings/internal/cord_rep_btree_reader.h",
+        "absl/strings/internal/cord_rep_consume.h",
+        "absl/strings/internal/cord_rep_crc.h",
+        "absl/strings/internal/cord_rep_flat.h",
+    ],
+    out: [
+        "my_include_dir/absl/strings/internal/cord_data_edge.h",
+        "my_include_dir/absl/strings/internal/cord_internal.h",
+        "my_include_dir/absl/strings/internal/cord_rep_btree.h",
+        "my_include_dir/absl/strings/internal/cord_rep_btree_navigator.h",
+        "my_include_dir/absl/strings/internal/cord_rep_btree_reader.h",
+        "my_include_dir/absl/strings/internal/cord_rep_consume.h",
+        "my_include_dir/absl/strings/internal/cord_rep_crc.h",
+        "my_include_dir/absl/strings/internal/cord_rep_flat.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_strings_cord_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/strings/internal/cord_internal.cc",
+        "absl/strings/internal/cord_rep_btree.cc",
+        "absl/strings/internal/cord_rep_btree_navigator.cc",
+        "absl/strings/internal/cord_rep_btree_reader.cc",
+        "absl/strings/internal/cord_rep_consume.cc",
+        "absl/strings/internal/cord_rep_crc.cc",
+    ],
+    generated_headers: ["absl_strings_cord_internal_hdrs"],
+    export_generated_headers: ["absl_strings_cord_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_container_compressed_tuple",
+        "absl_container_container_memory",
+        "absl_container_inlined_vector",
+        "absl_crc_crc_cord_state",
+        "absl_functional_function_ref",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_strings",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_container_compressed_tuple",
+        "absl_container_container_memory",
+        "absl_container_inlined_vector",
+        "absl_crc_crc_cord_state",
+        "absl_functional_function_ref",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_strings_cord_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/strings/internal/cord_internal.cc",
+        "absl/strings/internal/cord_rep_btree.cc",
+        "absl/strings/internal/cord_rep_btree_navigator.cc",
+        "absl/strings/internal/cord_rep_btree_reader.cc",
+        "absl/strings/internal/cord_rep_consume.cc",
+        "absl/strings/internal/cord_rep_crc.cc",
+    ],
+    generated_headers: ["absl_strings_cord_internal_hdrs"],
+    export_generated_headers: ["absl_strings_cord_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_strings_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_container_compressed_tuple_notls",
+        "absl_container_container_memory_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_crc_crc_cord_state_notls",
+        "absl_functional_function_ref_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_strings_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_container_compressed_tuple_notls",
+        "absl_container_container_memory_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_crc_crc_cord_state_notls",
+        "absl_functional_function_ref_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_container_memory_hdrs",
+    srcs: [
+        "absl/container/internal/container_memory.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/container_memory.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_container_memory",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_container_memory_hdrs"],
+    export_generated_headers: ["absl_container_container_memory_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_container_memory_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_container_memory_hdrs"],
+    export_generated_headers: ["absl_container_container_memory_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_leak_check_hdrs",
+    srcs: [
+        "absl/debugging/leak_check.h",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/leak_check.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_leak_check",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/debugging/leak_check.cc",
+    ],
+    generated_headers: ["absl_debugging_leak_check_hdrs"],
+    export_generated_headers: ["absl_debugging_leak_check_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_leak_check_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/debugging/leak_check.cc",
+    ],
+    generated_headers: ["absl_debugging_leak_check_hdrs"],
+    export_generated_headers: ["absl_debugging_leak_check_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_strerror_hdrs",
+    srcs: [
+        "absl/base/internal/strerror.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/internal/strerror.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_strerror",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/base/internal/strerror.cc",
+    ],
+    generated_headers: ["absl_base_strerror_hdrs"],
+    export_generated_headers: ["absl_base_strerror_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_errno_saver",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_errno_saver",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_strerror_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/base/internal/strerror.cc",
+    ],
+    generated_headers: ["absl_base_strerror_hdrs"],
+    export_generated_headers: ["absl_base_strerror_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_errno_saver_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_errno_saver_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_hdrs",
+    srcs: [
+        "absl/random/random.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/random.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_hdrs"],
+    export_generated_headers: ["absl_random_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_distributions",
+        "absl_random_seed_sequences",
+        "absl_base_config",
+        "absl_random_internal_nonsecure_base",
+        "absl_random_internal_pcg_engine",
+        "absl_random_internal_randen_engine",
+    ],
+    export_static_lib_headers: [
+        "absl_random_distributions",
+        "absl_random_seed_sequences",
+        "absl_base_config",
+        "absl_random_internal_nonsecure_base",
+        "absl_random_internal_pcg_engine",
+        "absl_random_internal_randen_engine",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_hdrs"],
+    export_generated_headers: ["absl_random_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_distributions_notls",
+        "absl_random_seed_sequences_notls",
+        "absl_base_config_notls",
+        "absl_random_internal_nonsecure_base_notls",
+        "absl_random_internal_pcg_engine_notls",
+        "absl_random_internal_randen_engine_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_distributions_notls",
+        "absl_random_seed_sequences_notls",
+        "absl_base_config_notls",
+        "absl_random_internal_nonsecure_base_notls",
+        "absl_random_internal_pcg_engine_notls",
+        "absl_random_internal_randen_engine_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_randen_engine_hdrs",
+    srcs: [
+        "absl/random/internal/randen_engine.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/randen_engine.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen_engine",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_randen_engine_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_engine_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_iostream_state_saver",
+        "absl_random_internal_randen",
+        "absl_base_endian",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_iostream_state_saver",
+        "absl_random_internal_randen",
+        "absl_base_endian",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen_engine_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_randen_engine_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_engine_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_iostream_state_saver_notls",
+        "absl_random_internal_randen_notls",
+        "absl_base_endian_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_iostream_state_saver_notls",
+        "absl_random_internal_randen_notls",
+        "absl_base_endian_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_randen_hdrs",
+    srcs: [
+        "absl/random/internal/randen.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/randen.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen.cc",
+    ],
+    generated_headers: ["absl_random_internal_randen_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform",
+        "absl_random_internal_randen_hwaes",
+        "absl_random_internal_randen_slow",
+        "absl_base_raw_logging_internal",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform",
+        "absl_random_internal_randen_hwaes",
+        "absl_random_internal_randen_slow",
+        "absl_base_raw_logging_internal",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen.cc",
+    ],
+    generated_headers: ["absl_random_internal_randen_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform_notls",
+        "absl_random_internal_randen_hwaes_notls",
+        "absl_random_internal_randen_slow_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform_notls",
+        "absl_random_internal_randen_hwaes_notls",
+        "absl_random_internal_randen_slow_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_randen_slow_hdrs",
+    srcs: [
+        "absl/random/internal/randen_slow.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/randen_slow.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen_slow",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen_slow.cc",
+    ],
+    generated_headers: ["absl_random_internal_randen_slow_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_slow_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_numeric_int128",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_numeric_int128",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen_slow_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen_slow.cc",
+    ],
+    generated_headers: ["absl_random_internal_randen_slow_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_slow_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_numeric_int128_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_numeric_int128_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_platform_hdrs",
+    srcs: [
+        "absl/random/internal/platform.h",
+        "absl/random/internal/randen_traits.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/platform.h",
+        "my_include_dir/absl/random/internal/randen_traits.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_platform",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen_round_keys.cc",
+    ],
+    generated_headers: ["absl_random_internal_platform_hdrs"],
+    export_generated_headers: ["absl_random_internal_platform_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_platform_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen_round_keys.cc",
+    ],
+    generated_headers: ["absl_random_internal_platform_hdrs"],
+    export_generated_headers: ["absl_random_internal_platform_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_randen_hwaes_hdrs",
+    srcs: [
+        "absl/random/internal/randen_detect.h",
+        "absl/random/internal/randen_hwaes.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/randen_detect.h",
+        "my_include_dir/absl/random/internal/randen_hwaes.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen_hwaes",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen_detect.cc",
+    ],
+    generated_headers: ["absl_random_internal_randen_hwaes_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_hwaes_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform",
+        "absl_random_internal_randen_hwaes_impl",
+        "absl_base_config",
+        "absl_types_optional",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform",
+        "absl_random_internal_randen_hwaes_impl",
+        "absl_base_config",
+        "absl_types_optional",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen_hwaes_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen_detect.cc",
+    ],
+    generated_headers: ["absl_random_internal_randen_hwaes_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_hwaes_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform_notls",
+        "absl_random_internal_randen_hwaes_impl_notls",
+        "absl_base_config_notls",
+        "absl_types_optional_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform_notls",
+        "absl_random_internal_randen_hwaes_impl_notls",
+        "absl_base_config_notls",
+        "absl_types_optional_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_randen_hwaes_impl_hdrs",
+    srcs: [
+        "absl/random/internal/randen_hwaes.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/randen_hwaes.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen_hwaes_impl",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen_hwaes.cc",
+    ],
+    generated_headers: ["absl_random_internal_randen_hwaes_impl_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_hwaes_impl_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_numeric_int128",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_numeric_int128",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_randen_hwaes_impl_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/random/internal/randen_hwaes.cc",
+    ],
+    generated_headers: ["absl_random_internal_randen_hwaes_impl_hdrs"],
+    export_generated_headers: ["absl_random_internal_randen_hwaes_impl_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_numeric_int128_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_numeric_int128_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_iostream_state_saver_hdrs",
+    srcs: [
+        "absl/random/internal/iostream_state_saver.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/iostream_state_saver.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_iostream_state_saver",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_iostream_state_saver_hdrs"],
+    export_generated_headers: ["absl_random_internal_iostream_state_saver_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_meta_type_traits",
+        "absl_numeric_int128",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_meta_type_traits",
+        "absl_numeric_int128",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_iostream_state_saver_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_iostream_state_saver_hdrs"],
+    export_generated_headers: ["absl_random_internal_iostream_state_saver_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_int128_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_int128_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_pcg_engine_hdrs",
+    srcs: [
+        "absl/random/internal/pcg_engine.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/pcg_engine.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_pcg_engine",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_pcg_engine_hdrs"],
+    export_generated_headers: ["absl_random_internal_pcg_engine_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_fastmath",
+        "absl_random_internal_iostream_state_saver",
+        "absl_base_config",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_fastmath",
+        "absl_random_internal_iostream_state_saver",
+        "absl_base_config",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_pcg_engine_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_pcg_engine_hdrs"],
+    export_generated_headers: ["absl_random_internal_pcg_engine_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_fastmath_notls",
+        "absl_random_internal_iostream_state_saver_notls",
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_fastmath_notls",
+        "absl_random_internal_iostream_state_saver_notls",
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_fastmath_hdrs",
+    srcs: [
+        "absl/random/internal/fastmath.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/fastmath.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_fastmath",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_fastmath_hdrs"],
+    export_generated_headers: ["absl_random_internal_fastmath_hdrs"],
+
+    whole_static_libs: [
+        "absl_numeric_bits",
+    ],
+    export_static_lib_headers: [
+        "absl_numeric_bits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_fastmath_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_fastmath_hdrs"],
+    export_generated_headers: ["absl_random_internal_fastmath_hdrs"],
+
+    whole_static_libs: [
+        "absl_numeric_bits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_numeric_bits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_nonsecure_base_hdrs",
+    srcs: [
+        "absl/random/internal/nonsecure_base.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/nonsecure_base.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_nonsecure_base",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_nonsecure_base_hdrs"],
+    export_generated_headers: ["absl_random_internal_nonsecure_base_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_entropy_pool",
+        "absl_random_internal_salted_seed_seq",
+        "absl_random_internal_seed_material",
+        "absl_base_config",
+        "absl_container_inlined_vector",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_entropy_pool",
+        "absl_random_internal_salted_seed_seq",
+        "absl_random_internal_seed_material",
+        "absl_base_config",
+        "absl_container_inlined_vector",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_nonsecure_base_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_nonsecure_base_hdrs"],
+    export_generated_headers: ["absl_random_internal_nonsecure_base_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_entropy_pool_notls",
+        "absl_random_internal_salted_seed_seq_notls",
+        "absl_random_internal_seed_material_notls",
+        "absl_base_config_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_entropy_pool_notls",
+        "absl_random_internal_salted_seed_seq_notls",
+        "absl_random_internal_seed_material_notls",
+        "absl_base_config_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_seed_material_hdrs",
+    srcs: [
+        "absl/random/internal/seed_material.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/seed_material.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_seed_material",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/random/internal/seed_material.cc",
+    ],
+    generated_headers: ["absl_random_internal_seed_material_hdrs"],
+    export_generated_headers: ["absl_random_internal_seed_material_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_fast_uniform_bits",
+        "absl_base_config",
+        "absl_base_dynamic_annotations",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+        "absl_types_optional",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_fast_uniform_bits",
+        "absl_base_config",
+        "absl_base_dynamic_annotations",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+        "absl_types_optional",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_seed_material_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/random/internal/seed_material.cc",
+    ],
+    generated_headers: ["absl_random_internal_seed_material_hdrs"],
+    export_generated_headers: ["absl_random_internal_seed_material_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_fast_uniform_bits_notls",
+        "absl_base_config_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_fast_uniform_bits_notls",
+        "absl_base_config_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_fast_uniform_bits_hdrs",
+    srcs: [
+        "absl/random/internal/fast_uniform_bits.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/fast_uniform_bits.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_fast_uniform_bits",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_fast_uniform_bits_hdrs"],
+    export_generated_headers: ["absl_random_internal_fast_uniform_bits_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_traits",
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_traits",
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_fast_uniform_bits_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_fast_uniform_bits_hdrs"],
+    export_generated_headers: ["absl_random_internal_fast_uniform_bits_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_traits_notls",
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_traits_notls",
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_traits_hdrs",
+    srcs: [
+        "absl/random/internal/traits.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/traits.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_traits",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_traits_hdrs"],
+    export_generated_headers: ["absl_random_internal_traits_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_traits_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_traits_hdrs"],
+    export_generated_headers: ["absl_random_internal_traits_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_salted_seed_seq_hdrs",
+    srcs: [
+        "absl/random/internal/salted_seed_seq.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/salted_seed_seq.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_salted_seed_seq",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_salted_seed_seq_hdrs"],
+    export_generated_headers: ["absl_random_internal_salted_seed_seq_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_seed_material",
+        "absl_container_inlined_vector",
+        "absl_meta_type_traits",
+        "absl_types_optional",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_seed_material",
+        "absl_container_inlined_vector",
+        "absl_meta_type_traits",
+        "absl_types_optional",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_salted_seed_seq_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_salted_seed_seq_hdrs"],
+    export_generated_headers: ["absl_random_internal_salted_seed_seq_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_seed_material_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_meta_type_traits_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_seed_material_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_meta_type_traits_notls",
+        "absl_types_optional_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_entropy_pool_hdrs",
+    srcs: [
+        "absl/random/internal/entropy_pool.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/entropy_pool.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_entropy_pool",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/random/internal/entropy_pool.cc",
+    ],
+    generated_headers: ["absl_random_internal_entropy_pool_hdrs"],
+    export_generated_headers: ["absl_random_internal_entropy_pool_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform",
+        "absl_random_internal_randen",
+        "absl_random_internal_seed_material",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_random_seed_gen_exception",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform",
+        "absl_random_internal_randen",
+        "absl_random_internal_seed_material",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_random_seed_gen_exception",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_entropy_pool_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/random/internal/entropy_pool.cc",
+    ],
+    generated_headers: ["absl_random_internal_entropy_pool_hdrs"],
+    export_generated_headers: ["absl_random_internal_entropy_pool_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_platform_notls",
+        "absl_random_internal_randen_notls",
+        "absl_random_internal_seed_material_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_random_seed_gen_exception_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_platform_notls",
+        "absl_random_internal_randen_notls",
+        "absl_random_internal_seed_material_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_random_seed_gen_exception_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_seed_gen_exception_hdrs",
+    srcs: [
+        "absl/random/seed_gen_exception.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/seed_gen_exception.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_seed_gen_exception",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/random/seed_gen_exception.cc",
+    ],
+    generated_headers: ["absl_random_seed_gen_exception_hdrs"],
+    export_generated_headers: ["absl_random_seed_gen_exception_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_raw_logging_internal",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_raw_logging_internal",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_seed_gen_exception_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/random/seed_gen_exception.cc",
+    ],
+    generated_headers: ["absl_random_seed_gen_exception_hdrs"],
+    export_generated_headers: ["absl_random_seed_gen_exception_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_seed_sequences_hdrs",
+    srcs: [
+        "absl/random/seed_sequences.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/seed_sequences.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_seed_sequences",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/random/seed_sequences.cc",
+    ],
+    generated_headers: ["absl_random_seed_sequences_hdrs"],
+    export_generated_headers: ["absl_random_seed_sequences_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_seed_gen_exception",
+        "absl_base_config",
+        "absl_base_nullability",
+        "absl_random_internal_entropy_pool",
+        "absl_random_internal_salted_seed_seq",
+        "absl_random_internal_seed_material",
+        "absl_strings_string_view",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_random_seed_gen_exception",
+        "absl_base_config",
+        "absl_base_nullability",
+        "absl_random_internal_entropy_pool",
+        "absl_random_internal_salted_seed_seq",
+        "absl_random_internal_seed_material",
+        "absl_strings_string_view",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_seed_sequences_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/random/seed_sequences.cc",
+    ],
+    generated_headers: ["absl_random_seed_sequences_hdrs"],
+    export_generated_headers: ["absl_random_seed_sequences_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_seed_gen_exception_notls",
+        "absl_base_config_notls",
+        "absl_base_nullability_notls",
+        "absl_random_internal_entropy_pool_notls",
+        "absl_random_internal_salted_seed_seq_notls",
+        "absl_random_internal_seed_material_notls",
+        "absl_strings_string_view_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_seed_gen_exception_notls",
+        "absl_base_config_notls",
+        "absl_base_nullability_notls",
+        "absl_random_internal_entropy_pool_notls",
+        "absl_random_internal_salted_seed_seq_notls",
+        "absl_random_internal_seed_material_notls",
+        "absl_strings_string_view_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_distributions_hdrs",
+    srcs: [
+        "absl/random/bernoulli_distribution.h",
+        "absl/random/beta_distribution.h",
+        "absl/random/discrete_distribution.h",
+        "absl/random/distributions.h",
+        "absl/random/exponential_distribution.h",
+        "absl/random/gaussian_distribution.h",
+        "absl/random/log_uniform_int_distribution.h",
+        "absl/random/poisson_distribution.h",
+        "absl/random/uniform_int_distribution.h",
+        "absl/random/uniform_real_distribution.h",
+        "absl/random/zipf_distribution.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/bernoulli_distribution.h",
+        "my_include_dir/absl/random/beta_distribution.h",
+        "my_include_dir/absl/random/discrete_distribution.h",
+        "my_include_dir/absl/random/distributions.h",
+        "my_include_dir/absl/random/exponential_distribution.h",
+        "my_include_dir/absl/random/gaussian_distribution.h",
+        "my_include_dir/absl/random/log_uniform_int_distribution.h",
+        "my_include_dir/absl/random/poisson_distribution.h",
+        "my_include_dir/absl/random/uniform_int_distribution.h",
+        "my_include_dir/absl/random/uniform_real_distribution.h",
+        "my_include_dir/absl/random/zipf_distribution.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_distributions",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/random/discrete_distribution.cc",
+        "absl/random/gaussian_distribution.cc",
+    ],
+    generated_headers: ["absl_random_distributions_hdrs"],
+    export_generated_headers: ["absl_random_distributions_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+        "absl_random_internal_distribution_caller",
+        "absl_random_internal_fast_uniform_bits",
+        "absl_random_internal_fastmath",
+        "absl_random_internal_generate_real",
+        "absl_random_internal_iostream_state_saver",
+        "absl_random_internal_traits",
+        "absl_random_internal_uniform_helper",
+        "absl_random_internal_wide_multiply",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_base_base_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+        "absl_random_internal_distribution_caller",
+        "absl_random_internal_fast_uniform_bits",
+        "absl_random_internal_fastmath",
+        "absl_random_internal_generate_real",
+        "absl_random_internal_iostream_state_saver",
+        "absl_random_internal_traits",
+        "absl_random_internal_uniform_helper",
+        "absl_random_internal_wide_multiply",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_distributions_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/random/discrete_distribution.cc",
+        "absl/random/gaussian_distribution.cc",
+    ],
+    generated_headers: ["absl_random_distributions_hdrs"],
+    export_generated_headers: ["absl_random_distributions_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+        "absl_random_internal_distribution_caller_notls",
+        "absl_random_internal_fast_uniform_bits_notls",
+        "absl_random_internal_fastmath_notls",
+        "absl_random_internal_generate_real_notls",
+        "absl_random_internal_iostream_state_saver_notls",
+        "absl_random_internal_traits_notls",
+        "absl_random_internal_uniform_helper_notls",
+        "absl_random_internal_wide_multiply_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_base_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+        "absl_random_internal_distribution_caller_notls",
+        "absl_random_internal_fast_uniform_bits_notls",
+        "absl_random_internal_fastmath_notls",
+        "absl_random_internal_generate_real_notls",
+        "absl_random_internal_iostream_state_saver_notls",
+        "absl_random_internal_traits_notls",
+        "absl_random_internal_uniform_helper_notls",
+        "absl_random_internal_wide_multiply_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_wide_multiply_hdrs",
+    srcs: [
+        "absl/random/internal/wide_multiply.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/wide_multiply.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_wide_multiply",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_wide_multiply_hdrs"],
+    export_generated_headers: ["absl_random_internal_wide_multiply_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_traits",
+        "absl_base_config",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_traits",
+        "absl_base_config",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_wide_multiply_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_wide_multiply_hdrs"],
+    export_generated_headers: ["absl_random_internal_wide_multiply_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_traits_notls",
+        "absl_base_config_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_traits_notls",
+        "absl_base_config_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_uniform_helper_hdrs",
+    srcs: [
+        "absl/random/internal/uniform_helper.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/uniform_helper.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_uniform_helper",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_uniform_helper_hdrs"],
+    export_generated_headers: ["absl_random_internal_uniform_helper_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_traits",
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_traits",
+        "absl_base_config",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_uniform_helper_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_uniform_helper_hdrs"],
+    export_generated_headers: ["absl_random_internal_uniform_helper_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_traits_notls",
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_traits_notls",
+        "absl_base_config_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_generate_real_hdrs",
+    srcs: [
+        "absl/random/internal/generate_real.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/generate_real.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_generate_real",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_generate_real_hdrs"],
+    export_generated_headers: ["absl_random_internal_generate_real_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_fastmath",
+        "absl_random_internal_traits",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_fastmath",
+        "absl_random_internal_traits",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_generate_real_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_generate_real_hdrs"],
+    export_generated_headers: ["absl_random_internal_generate_real_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_internal_fastmath_notls",
+        "absl_random_internal_traits_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_internal_fastmath_notls",
+        "absl_random_internal_traits_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_internal_distribution_caller_hdrs",
+    srcs: [
+        "absl/random/internal/distribution_caller.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/internal/distribution_caller.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_internal_distribution_caller",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_distribution_caller_hdrs"],
+    export_generated_headers: ["absl_random_internal_distribution_caller_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_fast_type_id",
+        "absl_meta_type_traits",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_fast_type_id",
+        "absl_meta_type_traits",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_internal_distribution_caller_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_internal_distribution_caller_hdrs"],
+    export_generated_headers: ["absl_random_internal_distribution_caller_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_meta_type_traits_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_meta_type_traits_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_base_fast_type_id_hdrs",
+    srcs: [
+        "absl/base/fast_type_id.h",
+    ],
+    out: [
+        "my_include_dir/absl/base/fast_type_id.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_base_fast_type_id",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_fast_type_id_hdrs"],
+    export_generated_headers: ["absl_base_fast_type_id_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_base_fast_type_id_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_base_fast_type_id_hdrs"],
+    export_generated_headers: ["absl_base_fast_type_id_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_random_bit_gen_ref_hdrs",
+    srcs: [
+        "absl/random/bit_gen_ref.h",
+    ],
+    out: [
+        "my_include_dir/absl/random/bit_gen_ref.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_random_bit_gen_ref",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_bit_gen_ref_hdrs"],
+    export_generated_headers: ["absl_random_bit_gen_ref_hdrs"],
+
+    whole_static_libs: [
+        "absl_random",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_fast_type_id",
+        "absl_meta_type_traits",
+        "absl_random_internal_distribution_caller",
+        "absl_random_internal_fast_uniform_bits",
+    ],
+    export_static_lib_headers: [
+        "absl_random",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_fast_type_id",
+        "absl_meta_type_traits",
+        "absl_random_internal_distribution_caller",
+        "absl_random_internal_fast_uniform_bits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_random_bit_gen_ref_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_random_bit_gen_ref_hdrs"],
+    export_generated_headers: ["absl_random_bit_gen_ref_hdrs"],
+
+    whole_static_libs: [
+        "absl_random_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_meta_type_traits_notls",
+        "absl_random_internal_distribution_caller_notls",
+        "absl_random_internal_fast_uniform_bits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_random_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_meta_type_traits_notls",
+        "absl_random_internal_distribution_caller_notls",
+        "absl_random_internal_fast_uniform_bits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_scoped_mock_log_hdrs",
+    srcs: [
+        "absl/log/scoped_mock_log.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/scoped_mock_log.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_test_library {
+    name: "absl_log_scoped_mock_log",
+    defaults: ["absl_test_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/log/scoped_mock_log.cc",
+    ],
+    generated_headers: ["absl_log_scoped_mock_log_hdrs"],
+    export_generated_headers: ["absl_log_scoped_mock_log_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_log_entry",
+        "absl_log_log_sink",
+        "absl_log_log_sink_registry",
+        "absl_base_config",
+        "absl_base_log_severity",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_log_log_entry",
+        "absl_log_log_sink",
+        "absl_log_log_sink_registry",
+        "absl_base_config",
+        "absl_base_log_severity",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+    ],
+
+    static_libs: [
+        "libgmock",
+        "libgtest",
+    ],
+    shared: {
+        enabled: false,
+    },
+
+}
+
+cc_test_library {
+    name: "absl_log_scoped_mock_log_notls",
+    defaults: ["absl_notls_test_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/log/scoped_mock_log.cc",
+    ],
+    generated_headers: ["absl_log_scoped_mock_log_hdrs"],
+    export_generated_headers: ["absl_log_scoped_mock_log_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_log_entry_notls",
+        "absl_log_log_sink_notls",
+        "absl_log_log_sink_registry_notls",
+        "absl_base_config_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_log_entry_notls",
+        "absl_log_log_sink_notls",
+        "absl_log_log_sink_registry_notls",
+        "absl_base_config_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+    ],
+
+    static_libs: [
+        "libgmock",
+        "libgtest",
+    ],
+    shared: {
+        enabled: false,
+    },
+
+}
+
+genrule {
+    name: "absl_log_log_sink_registry_hdrs",
+    srcs: [
+        "absl/log/log_sink_registry.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/log_sink_registry.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_log_sink_registry",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_log_sink_registry_hdrs"],
+    export_generated_headers: ["absl_log_log_sink_registry_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_log_sink",
+        "absl_base_config",
+        "absl_base_nullability",
+        "absl_log_internal_log_sink_set",
+    ],
+    export_static_lib_headers: [
+        "absl_log_log_sink",
+        "absl_base_config",
+        "absl_base_nullability",
+        "absl_log_internal_log_sink_set",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_log_sink_registry_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_log_sink_registry_hdrs"],
+    export_generated_headers: ["absl_log_log_sink_registry_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_log_sink_notls",
+        "absl_base_config_notls",
+        "absl_base_nullability_notls",
+        "absl_log_internal_log_sink_set_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_log_sink_notls",
+        "absl_base_config_notls",
+        "absl_base_nullability_notls",
+        "absl_log_internal_log_sink_set_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_log_sink_set_hdrs",
+    srcs: [
+        "absl/log/internal/log_sink_set.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/log_sink_set.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_log_sink_set",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/log_sink_set.cc",
+    ],
+    generated_headers: ["absl_log_internal_log_sink_set_hdrs"],
+    export_generated_headers: ["absl_log_internal_log_sink_set_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_config",
+        "absl_log_internal_globals",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_base_no_destructor",
+        "absl_base_raw_logging_internal",
+        "absl_cleanup",
+        "absl_log_globals",
+        "absl_log_log_entry",
+        "absl_log_log_sink",
+        "absl_strings",
+        "absl_synchronization",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_config",
+        "absl_log_internal_globals",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_base_no_destructor",
+        "absl_base_raw_logging_internal",
+        "absl_cleanup",
+        "absl_log_globals",
+        "absl_log_log_entry",
+        "absl_log_log_sink",
+        "absl_strings",
+        "absl_synchronization",
+        "absl_types_span",
+    ],
+
+    target: {
+        android: {
+            shared_libs: ["liblog"],
+        },
+    },
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_log_sink_set_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/log_sink_set.cc",
+    ],
+    generated_headers: ["absl_log_internal_log_sink_set_hdrs"],
+    export_generated_headers: ["absl_log_internal_log_sink_set_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_config_notls",
+        "absl_log_internal_globals_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_cleanup_notls",
+        "absl_log_globals_notls",
+        "absl_log_log_entry_notls",
+        "absl_log_log_sink_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_config_notls",
+        "absl_log_internal_globals_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_cleanup_notls",
+        "absl_log_globals_notls",
+        "absl_log_log_entry_notls",
+        "absl_log_log_sink_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+        "absl_types_span_notls",
+    ],
+
+    target: {
+        android: {
+            shared_libs: ["liblog"],
+        },
+    },
+
+}
+
+genrule {
+    name: "absl_log_log_sink_hdrs",
+    srcs: [
+        "absl/log/log_sink.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/log_sink.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_log_sink",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/log/log_sink.cc",
+    ],
+    generated_headers: ["absl_log_log_sink_hdrs"],
+    export_generated_headers: ["absl_log_log_sink_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_log_entry",
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_log_log_entry",
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_log_sink_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/log/log_sink.cc",
+    ],
+    generated_headers: ["absl_log_log_sink_hdrs"],
+    export_generated_headers: ["absl_log_log_sink_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_log_entry_notls",
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_log_entry_notls",
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_log_entry_hdrs",
+    srcs: [
+        "absl/log/log_entry.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/log_entry.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_log_entry",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_log_entry_hdrs"],
+    export_generated_headers: ["absl_log_log_entry_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_log_internal_config",
+        "absl_strings",
+        "absl_time",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_log_internal_config",
+        "absl_strings",
+        "absl_time",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_log_entry_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_log_entry_hdrs"],
+    export_generated_headers: ["absl_log_log_entry_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_log_internal_config_notls",
+        "absl_strings_notls",
+        "absl_time_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_log_internal_config_notls",
+        "absl_strings_notls",
+        "absl_time_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_config_hdrs",
+    srcs: [
+        "absl/log/internal/config.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/config.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_config",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_config_hdrs"],
+    export_generated_headers: ["absl_log_internal_config_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_config_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_config_hdrs"],
+    export_generated_headers: ["absl_log_internal_config_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_globals_hdrs",
+    srcs: [
+        "absl/log/globals.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/globals.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_globals",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/log/globals.cc",
+    ],
+    generated_headers: ["absl_log_globals_hdrs"],
+    export_generated_headers: ["absl_log_globals_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_atomic_hook",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_base_raw_logging_internal",
+        "absl_hash",
+        "absl_log_internal_vlog_config",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_base_atomic_hook",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_base_raw_logging_internal",
+        "absl_hash",
+        "absl_log_internal_vlog_config",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_globals_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/log/globals.cc",
+    ],
+    generated_headers: ["absl_log_globals_hdrs"],
+    export_generated_headers: ["absl_log_globals_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_atomic_hook_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_hash_notls",
+        "absl_log_internal_vlog_config_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_atomic_hook_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_hash_notls",
+        "absl_log_internal_vlog_config_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_vlog_config_hdrs",
+    srcs: [
+        "absl/log/internal/vlog_config.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/vlog_config.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_vlog_config",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/vlog_config.cc",
+    ],
+    generated_headers: ["absl_log_internal_vlog_config_hdrs"],
+    export_generated_headers: ["absl_log_internal_vlog_config_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_fnmatch",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_base_nullability",
+        "absl_memory",
+        "absl_strings",
+        "absl_synchronization",
+        "absl_types_optional",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_fnmatch",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_base_nullability",
+        "absl_memory",
+        "absl_strings",
+        "absl_synchronization",
+        "absl_types_optional",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_vlog_config_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/vlog_config.cc",
+    ],
+    generated_headers: ["absl_log_internal_vlog_config_hdrs"],
+    export_generated_headers: ["absl_log_internal_vlog_config_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_fnmatch_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_nullability_notls",
+        "absl_memory_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+        "absl_types_optional_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_fnmatch_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_nullability_notls",
+        "absl_memory_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+        "absl_types_optional_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_fnmatch_hdrs",
+    srcs: [
+        "absl/log/internal/fnmatch.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/fnmatch.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_fnmatch",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/fnmatch.cc",
+    ],
+    generated_headers: ["absl_log_internal_fnmatch_hdrs"],
+    export_generated_headers: ["absl_log_internal_fnmatch_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_fnmatch_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/fnmatch.cc",
+    ],
+    generated_headers: ["absl_log_internal_fnmatch_hdrs"],
+    export_generated_headers: ["absl_log_internal_fnmatch_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_hash_hdrs",
+    srcs: [
+        "absl/hash/hash.h",
+        "absl/hash/internal/hash.h",
+    ],
+    out: [
+        "my_include_dir/absl/hash/hash.h",
+        "my_include_dir/absl/hash/internal/hash.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_hash",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/hash/internal/hash.cc",
+    ],
+    generated_headers: ["absl_hash_hdrs"],
+    export_generated_headers: ["absl_hash_hdrs"],
+
+    whole_static_libs: [
+        "absl_hash_city",
+        "absl_hash_low_level_hash",
+        "absl_hash_weakly_mixed_integer",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_container_fixed_array",
+        "absl_functional_function_ref",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+        "absl_strings",
+        "absl_types_optional",
+        "absl_types_variant",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_hash_city",
+        "absl_hash_low_level_hash",
+        "absl_hash_weakly_mixed_integer",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_container_fixed_array",
+        "absl_functional_function_ref",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_numeric_int128",
+        "absl_strings",
+        "absl_types_optional",
+        "absl_types_variant",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_hash_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/hash/internal/hash.cc",
+    ],
+    generated_headers: ["absl_hash_hdrs"],
+    export_generated_headers: ["absl_hash_hdrs"],
+
+    whole_static_libs: [
+        "absl_hash_city_notls",
+        "absl_hash_low_level_hash_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_container_fixed_array_notls",
+        "absl_functional_function_ref_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+        "absl_strings_notls",
+        "absl_types_optional_notls",
+        "absl_types_variant_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_hash_city_notls",
+        "absl_hash_low_level_hash_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_container_fixed_array_notls",
+        "absl_functional_function_ref_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_numeric_int128_notls",
+        "absl_strings_notls",
+        "absl_types_optional_notls",
+        "absl_types_variant_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_hash_low_level_hash_hdrs",
+    srcs: [
+        "absl/hash/internal/low_level_hash.h",
+    ],
+    out: [
+        "my_include_dir/absl/hash/internal/low_level_hash.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_hash_low_level_hash",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/hash/internal/low_level_hash.cc",
+    ],
+    generated_headers: ["absl_hash_low_level_hash_hdrs"],
+    export_generated_headers: ["absl_hash_low_level_hash_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_prefetch",
+        "absl_numeric_int128",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_base_prefetch",
+        "absl_numeric_int128",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_hash_low_level_hash_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/hash/internal/low_level_hash.cc",
+    ],
+    generated_headers: ["absl_hash_low_level_hash_hdrs"],
+    export_generated_headers: ["absl_hash_low_level_hash_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_prefetch_notls",
+        "absl_numeric_int128_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_base_prefetch_notls",
+        "absl_numeric_int128_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_hash_city_hdrs",
+    srcs: [
+        "absl/hash/internal/city.h",
+    ],
+    out: [
+        "my_include_dir/absl/hash/internal/city.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_hash_city",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/hash/internal/city.cc",
+    ],
+    generated_headers: ["absl_hash_city_hdrs"],
+    export_generated_headers: ["absl_hash_city_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_hash_city_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/hash/internal/city.cc",
+    ],
+    generated_headers: ["absl_hash_city_hdrs"],
+    export_generated_headers: ["absl_hash_city_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_cleanup_hdrs",
+    srcs: [
+        "absl/cleanup/cleanup.h",
+    ],
+    out: [
+        "my_include_dir/absl/cleanup/cleanup.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_cleanup",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_cleanup_hdrs"],
+    export_generated_headers: ["absl_cleanup_hdrs"],
+
+    whole_static_libs: [
+        "absl_cleanup_cleanup_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_cleanup_cleanup_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_cleanup_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_cleanup_hdrs"],
+    export_generated_headers: ["absl_cleanup_hdrs"],
+
+    whole_static_libs: [
+        "absl_cleanup_cleanup_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_cleanup_cleanup_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_cleanup_cleanup_internal_hdrs",
+    srcs: [
+        "absl/cleanup/internal/cleanup.h",
+    ],
+    out: [
+        "my_include_dir/absl/cleanup/internal/cleanup.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_cleanup_cleanup_internal",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_cleanup_cleanup_internal_hdrs"],
+    export_generated_headers: ["absl_cleanup_cleanup_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_core_headers",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_base_core_headers",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_cleanup_cleanup_internal_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_cleanup_cleanup_internal_hdrs"],
+    export_generated_headers: ["absl_cleanup_cleanup_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_core_headers_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_core_headers_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_globals_hdrs",
+    srcs: [
+        "absl/log/internal/globals.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/globals.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_globals",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/globals.cc",
+    ],
+    generated_headers: ["absl_log_internal_globals_hdrs"],
+    export_generated_headers: ["absl_log_internal_globals_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+        "absl_time",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+        "absl_time",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_globals_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/globals.cc",
+    ],
+    generated_headers: ["absl_log_internal_globals_hdrs"],
+    export_generated_headers: ["absl_log_internal_globals_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+        "absl_time_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+        "absl_time_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_hdrs",
+    srcs: [
+        "absl/log/log.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/log.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_hdrs"],
+    export_generated_headers: ["absl_log_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_vlog_is_on",
+        "absl_log_internal_log_impl",
+    ],
+    export_static_lib_headers: [
+        "absl_log_vlog_is_on",
+        "absl_log_internal_log_impl",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_hdrs"],
+    export_generated_headers: ["absl_log_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_vlog_is_on_notls",
+        "absl_log_internal_log_impl_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_vlog_is_on_notls",
+        "absl_log_internal_log_impl_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_log_impl_hdrs",
+    srcs: [
+        "absl/log/internal/log_impl.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/log_impl.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_log_impl",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_log_impl_hdrs"],
+    export_generated_headers: ["absl_log_internal_log_impl_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_conditions",
+        "absl_log_internal_log_message",
+        "absl_log_internal_strip",
+        "absl_log_absl_vlog_is_on",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_conditions",
+        "absl_log_internal_log_message",
+        "absl_log_internal_strip",
+        "absl_log_absl_vlog_is_on",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_log_impl_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_log_impl_hdrs"],
+    export_generated_headers: ["absl_log_internal_log_impl_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_conditions_notls",
+        "absl_log_internal_log_message_notls",
+        "absl_log_internal_strip_notls",
+        "absl_log_absl_vlog_is_on_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_conditions_notls",
+        "absl_log_internal_log_message_notls",
+        "absl_log_internal_strip_notls",
+        "absl_log_absl_vlog_is_on_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_absl_vlog_is_on_hdrs",
+    srcs: [
+        "absl/log/absl_vlog_is_on.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/absl_vlog_is_on.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_absl_vlog_is_on",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_absl_vlog_is_on_hdrs"],
+    export_generated_headers: ["absl_log_absl_vlog_is_on_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_log_internal_vlog_config",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_log_internal_vlog_config",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_absl_vlog_is_on_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_absl_vlog_is_on_hdrs"],
+    export_generated_headers: ["absl_log_absl_vlog_is_on_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_log_internal_vlog_config_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_log_internal_vlog_config_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_strip_hdrs",
+    srcs: [
+        "absl/log/internal/strip.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/strip.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_strip",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_strip_hdrs"],
+    export_generated_headers: ["absl_log_internal_strip_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_log_message",
+        "absl_log_internal_nullstream",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_log_message",
+        "absl_log_internal_nullstream",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_strip_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_strip_hdrs"],
+    export_generated_headers: ["absl_log_internal_strip_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_log_message_notls",
+        "absl_log_internal_nullstream_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_log_message_notls",
+        "absl_log_internal_nullstream_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_nullstream_hdrs",
+    srcs: [
+        "absl/log/internal/nullstream.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/nullstream.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_nullstream",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_nullstream_hdrs"],
+    export_generated_headers: ["absl_log_internal_nullstream_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_nullstream_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_nullstream_hdrs"],
+    export_generated_headers: ["absl_log_internal_nullstream_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_log_message_hdrs",
+    srcs: [
+        "absl/log/internal/log_message.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/log_message.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_log_message",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/log_message.cc",
+    ],
+    generated_headers: ["absl_log_internal_log_message_hdrs"],
+    export_generated_headers: ["absl_log_internal_log_message_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_append_truncated",
+        "absl_log_internal_format",
+        "absl_log_internal_globals",
+        "absl_log_internal_log_sink_set",
+        "absl_log_internal_nullguard",
+        "absl_log_internal_proto",
+        "absl_log_internal_structured_proto",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_errno_saver",
+        "absl_base_log_severity",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_strerror",
+        "absl_container_inlined_vector",
+        "absl_debugging_examine_stack",
+        "absl_log_globals",
+        "absl_log_log_entry",
+        "absl_log_log_sink",
+        "absl_log_log_sink_registry",
+        "absl_memory",
+        "absl_strings",
+        "absl_strings_internal",
+        "absl_time",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_append_truncated",
+        "absl_log_internal_format",
+        "absl_log_internal_globals",
+        "absl_log_internal_log_sink_set",
+        "absl_log_internal_nullguard",
+        "absl_log_internal_proto",
+        "absl_log_internal_structured_proto",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_errno_saver",
+        "absl_base_log_severity",
+        "absl_base_nullability",
+        "absl_base_raw_logging_internal",
+        "absl_base_strerror",
+        "absl_container_inlined_vector",
+        "absl_debugging_examine_stack",
+        "absl_log_globals",
+        "absl_log_log_entry",
+        "absl_log_log_sink",
+        "absl_log_log_sink_registry",
+        "absl_memory",
+        "absl_strings",
+        "absl_strings_internal",
+        "absl_time",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_log_message_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/log_message.cc",
+    ],
+    generated_headers: ["absl_log_internal_log_message_hdrs"],
+    export_generated_headers: ["absl_log_internal_log_message_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_append_truncated_notls",
+        "absl_log_internal_format_notls",
+        "absl_log_internal_globals_notls",
+        "absl_log_internal_log_sink_set_notls",
+        "absl_log_internal_nullguard_notls",
+        "absl_log_internal_proto_notls",
+        "absl_log_internal_structured_proto_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_errno_saver_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_strerror_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_debugging_examine_stack_notls",
+        "absl_log_globals_notls",
+        "absl_log_log_entry_notls",
+        "absl_log_log_sink_notls",
+        "absl_log_log_sink_registry_notls",
+        "absl_memory_notls",
+        "absl_strings_notls",
+        "absl_strings_internal_notls",
+        "absl_time_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_append_truncated_notls",
+        "absl_log_internal_format_notls",
+        "absl_log_internal_globals_notls",
+        "absl_log_internal_log_sink_set_notls",
+        "absl_log_internal_nullguard_notls",
+        "absl_log_internal_proto_notls",
+        "absl_log_internal_structured_proto_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_errno_saver_notls",
+        "absl_base_log_severity_notls",
+        "absl_base_nullability_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_strerror_notls",
+        "absl_container_inlined_vector_notls",
+        "absl_debugging_examine_stack_notls",
+        "absl_log_globals_notls",
+        "absl_log_log_entry_notls",
+        "absl_log_log_sink_notls",
+        "absl_log_log_sink_registry_notls",
+        "absl_memory_notls",
+        "absl_strings_notls",
+        "absl_strings_internal_notls",
+        "absl_time_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_examine_stack_hdrs",
+    srcs: [
+        "absl/debugging/internal/examine_stack.h",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/internal/examine_stack.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_examine_stack",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/debugging/internal/examine_stack.cc",
+    ],
+    generated_headers: ["absl_debugging_examine_stack_hdrs"],
+    export_generated_headers: ["absl_debugging_examine_stack_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_stacktrace",
+        "absl_debugging_symbolize",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_stacktrace",
+        "absl_debugging_symbolize",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_examine_stack_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/debugging/internal/examine_stack.cc",
+    ],
+    generated_headers: ["absl_debugging_examine_stack_hdrs"],
+    export_generated_headers: ["absl_debugging_examine_stack_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_stacktrace_notls",
+        "absl_debugging_symbolize_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_stacktrace_notls",
+        "absl_debugging_symbolize_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_structured_proto_hdrs",
+    srcs: [
+        "absl/log/internal/structured_proto.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/structured_proto.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_structured_proto",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/structured_proto.cc",
+    ],
+    generated_headers: ["absl_log_internal_structured_proto_hdrs"],
+    export_generated_headers: ["absl_log_internal_structured_proto_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_proto",
+        "absl_base_config",
+        "absl_strings",
+        "absl_types_span",
+        "absl_types_variant",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_proto",
+        "absl_base_config",
+        "absl_strings",
+        "absl_types_span",
+        "absl_types_variant",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_structured_proto_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/structured_proto.cc",
+    ],
+    generated_headers: ["absl_log_internal_structured_proto_hdrs"],
+    export_generated_headers: ["absl_log_internal_structured_proto_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_proto_notls",
+        "absl_base_config_notls",
+        "absl_strings_notls",
+        "absl_types_span_notls",
+        "absl_types_variant_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_proto_notls",
+        "absl_base_config_notls",
+        "absl_strings_notls",
+        "absl_types_span_notls",
+        "absl_types_variant_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_proto_hdrs",
+    srcs: [
+        "absl/log/internal/proto.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/proto.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_proto",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/proto.cc",
+    ],
+    generated_headers: ["absl_log_internal_proto_hdrs"],
+    export_generated_headers: ["absl_log_internal_proto_hdrs"],
+
+    whole_static_libs: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_strings",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_strings",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_proto_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/proto.cc",
+    ],
+    generated_headers: ["absl_log_internal_proto_hdrs"],
+    export_generated_headers: ["absl_log_internal_proto_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_strings_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_strings_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_nullguard_hdrs",
+    srcs: [
+        "absl/log/internal/nullguard.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/nullguard.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_nullguard",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/nullguard.cc",
+    ],
+    generated_headers: ["absl_log_internal_nullguard_hdrs"],
+    export_generated_headers: ["absl_log_internal_nullguard_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_nullguard_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/nullguard.cc",
+    ],
+    generated_headers: ["absl_log_internal_nullguard_hdrs"],
+    export_generated_headers: ["absl_log_internal_nullguard_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_format_hdrs",
+    srcs: [
+        "absl/log/internal/log_format.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/log_format.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_format",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/log_format.cc",
+    ],
+    generated_headers: ["absl_log_internal_format_hdrs"],
+    export_generated_headers: ["absl_log_internal_format_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_append_truncated",
+        "absl_log_internal_config",
+        "absl_log_internal_globals",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_strings",
+        "absl_strings_str_format",
+        "absl_time",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_append_truncated",
+        "absl_log_internal_config",
+        "absl_log_internal_globals",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_strings",
+        "absl_strings_str_format",
+        "absl_time",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_format_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/log_format.cc",
+    ],
+    generated_headers: ["absl_log_internal_format_hdrs"],
+    export_generated_headers: ["absl_log_internal_format_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_append_truncated_notls",
+        "absl_log_internal_config_notls",
+        "absl_log_internal_globals_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_strings_notls",
+        "absl_strings_str_format_notls",
+        "absl_time_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_append_truncated_notls",
+        "absl_log_internal_config_notls",
+        "absl_log_internal_globals_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_strings_notls",
+        "absl_strings_str_format_notls",
+        "absl_time_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_append_truncated_hdrs",
+    srcs: [
+        "absl/log/internal/append_truncated.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/append_truncated.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_append_truncated",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_append_truncated_hdrs"],
+    export_generated_headers: ["absl_log_internal_append_truncated_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_strings",
+        "absl_strings_internal",
+        "absl_types_span",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_strings",
+        "absl_strings_internal",
+        "absl_types_span",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_append_truncated_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_append_truncated_hdrs"],
+    export_generated_headers: ["absl_log_internal_append_truncated_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_strings_notls",
+        "absl_strings_internal_notls",
+        "absl_types_span_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_strings_notls",
+        "absl_strings_internal_notls",
+        "absl_types_span_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_conditions_hdrs",
+    srcs: [
+        "absl/log/internal/conditions.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/conditions.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_conditions",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/conditions.cc",
+    ],
+    generated_headers: ["absl_log_internal_conditions_hdrs"],
+    export_generated_headers: ["absl_log_internal_conditions_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_voidify",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_voidify",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_conditions_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/conditions.cc",
+    ],
+    generated_headers: ["absl_log_internal_conditions_hdrs"],
+    export_generated_headers: ["absl_log_internal_conditions_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_voidify_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_voidify_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_voidify_hdrs",
+    srcs: [
+        "absl/log/internal/voidify.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/voidify.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_voidify",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_voidify_hdrs"],
+    export_generated_headers: ["absl_log_internal_voidify_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_voidify_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_voidify_hdrs"],
+    export_generated_headers: ["absl_log_internal_voidify_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_vlog_is_on_hdrs",
+    srcs: [
+        "absl/log/vlog_is_on.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/vlog_is_on.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_vlog_is_on",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_vlog_is_on_hdrs"],
+    export_generated_headers: ["absl_log_vlog_is_on_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_absl_vlog_is_on",
+    ],
+    export_static_lib_headers: [
+        "absl_log_absl_vlog_is_on",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_vlog_is_on_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_vlog_is_on_hdrs"],
+    export_generated_headers: ["absl_log_vlog_is_on_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_absl_vlog_is_on_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_absl_vlog_is_on_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_initialize_hdrs",
+    srcs: [
+        "absl/log/initialize.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/initialize.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_initialize",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/log/initialize.cc",
+    ],
+    generated_headers: ["absl_log_initialize_hdrs"],
+    export_generated_headers: ["absl_log_initialize_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_globals",
+        "absl_base_config",
+        "absl_log_internal_globals",
+        "absl_time",
+    ],
+    export_static_lib_headers: [
+        "absl_log_globals",
+        "absl_base_config",
+        "absl_log_internal_globals",
+        "absl_time",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_initialize_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/log/initialize.cc",
+    ],
+    generated_headers: ["absl_log_initialize_hdrs"],
+    export_generated_headers: ["absl_log_initialize_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_globals_notls",
+        "absl_base_config_notls",
+        "absl_log_internal_globals_notls",
+        "absl_time_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_globals_notls",
+        "absl_base_config_notls",
+        "absl_log_internal_globals_notls",
+        "absl_time_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_die_if_null_hdrs",
+    srcs: [
+        "absl/log/die_if_null.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/die_if_null.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_die_if_null",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/log/die_if_null.cc",
+    ],
+    generated_headers: ["absl_log_die_if_null_hdrs"],
+    export_generated_headers: ["absl_log_die_if_null_hdrs"],
+
+    whole_static_libs: [
+        "absl_log",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_log",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_die_if_null_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/log/die_if_null.cc",
+    ],
+    generated_headers: ["absl_log_die_if_null_hdrs"],
+    export_generated_headers: ["absl_log_die_if_null_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_check_hdrs",
+    srcs: [
+        "absl/log/check.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/check.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_check",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_check_hdrs"],
+    export_generated_headers: ["absl_log_check_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_check_impl",
+        "absl_log_internal_check_op",
+        "absl_log_internal_conditions",
+        "absl_log_internal_log_message",
+        "absl_log_internal_strip",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_check_impl",
+        "absl_log_internal_check_op",
+        "absl_log_internal_conditions",
+        "absl_log_internal_log_message",
+        "absl_log_internal_strip",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_check_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_check_hdrs"],
+    export_generated_headers: ["absl_log_check_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_check_impl_notls",
+        "absl_log_internal_check_op_notls",
+        "absl_log_internal_conditions_notls",
+        "absl_log_internal_log_message_notls",
+        "absl_log_internal_strip_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_check_impl_notls",
+        "absl_log_internal_check_op_notls",
+        "absl_log_internal_conditions_notls",
+        "absl_log_internal_log_message_notls",
+        "absl_log_internal_strip_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_check_op_hdrs",
+    srcs: [
+        "absl/log/internal/check_op.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/check_op.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_check_op",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/log/internal/check_op.cc",
+    ],
+    generated_headers: ["absl_log_internal_check_op_hdrs"],
+    export_generated_headers: ["absl_log_internal_check_op_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_nullguard",
+        "absl_log_internal_nullstream",
+        "absl_log_internal_strip",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_debugging_leak_check",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_nullguard",
+        "absl_log_internal_nullstream",
+        "absl_log_internal_strip",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_debugging_leak_check",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_check_op_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/log/internal/check_op.cc",
+    ],
+    generated_headers: ["absl_log_internal_check_op_hdrs"],
+    export_generated_headers: ["absl_log_internal_check_op_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_nullguard_notls",
+        "absl_log_internal_nullstream_notls",
+        "absl_log_internal_strip_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_debugging_leak_check_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_nullguard_notls",
+        "absl_log_internal_nullstream_notls",
+        "absl_log_internal_strip_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_debugging_leak_check_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_internal_check_impl_hdrs",
+    srcs: [
+        "absl/log/internal/check_impl.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/internal/check_impl.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_internal_check_impl",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_check_impl_hdrs"],
+    export_generated_headers: ["absl_log_internal_check_impl_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_check_op",
+        "absl_log_internal_conditions",
+        "absl_log_internal_log_message",
+        "absl_log_internal_strip",
+        "absl_base_core_headers",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_check_op",
+        "absl_log_internal_conditions",
+        "absl_log_internal_log_message",
+        "absl_log_internal_strip",
+        "absl_base_core_headers",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_internal_check_impl_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_internal_check_impl_hdrs"],
+    export_generated_headers: ["absl_log_internal_check_impl_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_check_op_notls",
+        "absl_log_internal_conditions_notls",
+        "absl_log_internal_log_message_notls",
+        "absl_log_internal_strip_notls",
+        "absl_base_core_headers_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_check_op_notls",
+        "absl_log_internal_conditions_notls",
+        "absl_log_internal_log_message_notls",
+        "absl_log_internal_strip_notls",
+        "absl_base_core_headers_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_absl_log_hdrs",
+    srcs: [
+        "absl/log/absl_log.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/absl_log.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_absl_log",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_absl_log_hdrs"],
+    export_generated_headers: ["absl_log_absl_log_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_log_impl",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_log_impl",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_absl_log_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_absl_log_hdrs"],
+    export_generated_headers: ["absl_log_absl_log_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_log_impl_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_log_impl_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_log_absl_check_hdrs",
+    srcs: [
+        "absl/log/absl_check.h",
+    ],
+    out: [
+        "my_include_dir/absl/log/absl_check.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_log_absl_check",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_absl_check_hdrs"],
+    export_generated_headers: ["absl_log_absl_check_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_check_impl",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_check_impl",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_log_absl_check_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_log_absl_check_hdrs"],
+    export_generated_headers: ["absl_log_absl_check_hdrs"],
+
+    whole_static_libs: [
+        "absl_log_internal_check_impl_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_log_internal_check_impl_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_functional_bind_front_hdrs",
+    srcs: [
+        "absl/functional/bind_front.h",
+        "absl/functional/internal/front_binder.h",
+    ],
+    out: [
+        "my_include_dir/absl/functional/bind_front.h",
+        "my_include_dir/absl/functional/internal/front_binder.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_functional_bind_front",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_functional_bind_front_hdrs"],
+    export_generated_headers: ["absl_functional_bind_front_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_compressed_tuple",
+        "absl_meta_type_traits",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_container_compressed_tuple",
+        "absl_meta_type_traits",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_functional_bind_front_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_functional_bind_front_hdrs"],
+    export_generated_headers: ["absl_functional_bind_front_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_compressed_tuple_notls",
+        "absl_meta_type_traits_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_compressed_tuple_notls",
+        "absl_meta_type_traits_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_parse_hdrs",
+    srcs: [
+        "absl/flags/internal/parse.h",
+        "absl/flags/parse.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/internal/parse.h",
+        "my_include_dir/absl/flags/parse.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_parse",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/flags/parse.cc",
+    ],
+    generated_headers: ["absl_flags_parse_hdrs"],
+    export_generated_headers: ["absl_flags_parse_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag",
+        "absl_flags_commandlineflag_internal",
+        "absl_flags_config",
+        "absl_flags_flag",
+        "absl_flags_flag_internal",
+        "absl_flags_private_handle_accessor",
+        "absl_flags_program_name",
+        "absl_flags_reflection",
+        "absl_flags_usage",
+        "absl_flags_usage_internal",
+        "absl_algorithm_container",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag",
+        "absl_flags_commandlineflag_internal",
+        "absl_flags_config",
+        "absl_flags_flag",
+        "absl_flags_flag_internal",
+        "absl_flags_private_handle_accessor",
+        "absl_flags_program_name",
+        "absl_flags_reflection",
+        "absl_flags_usage",
+        "absl_flags_usage_internal",
+        "absl_algorithm_container",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_parse_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/flags/parse.cc",
+    ],
+    generated_headers: ["absl_flags_parse_hdrs"],
+    export_generated_headers: ["absl_flags_parse_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_flags_config_notls",
+        "absl_flags_flag_notls",
+        "absl_flags_flag_internal_notls",
+        "absl_flags_private_handle_accessor_notls",
+        "absl_flags_program_name_notls",
+        "absl_flags_reflection_notls",
+        "absl_flags_usage_notls",
+        "absl_flags_usage_internal_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_flags_config_notls",
+        "absl_flags_flag_notls",
+        "absl_flags_flag_internal_notls",
+        "absl_flags_private_handle_accessor_notls",
+        "absl_flags_program_name_notls",
+        "absl_flags_reflection_notls",
+        "absl_flags_usage_notls",
+        "absl_flags_usage_internal_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_algorithm_container_hdrs",
+    srcs: [
+        "absl/algorithm/container.h",
+    ],
+    out: [
+        "my_include_dir/absl/algorithm/container.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_algorithm_container",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_algorithm_container_hdrs"],
+    export_generated_headers: ["absl_algorithm_container_hdrs"],
+
+    whole_static_libs: [
+        "absl_algorithm",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_algorithm",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_algorithm_container_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_algorithm_container_hdrs"],
+    export_generated_headers: ["absl_algorithm_container_hdrs"],
+
+    whole_static_libs: [
+        "absl_algorithm_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_algorithm_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_usage_internal_hdrs",
+    srcs: [
+        "absl/flags/internal/usage.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/internal/usage.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_usage_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/flags/internal/usage.cc",
+    ],
+    generated_headers: ["absl_flags_usage_internal_hdrs"],
+    export_generated_headers: ["absl_flags_usage_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag",
+        "absl_flags_config",
+        "absl_flags_flag",
+        "absl_flags_flag_internal",
+        "absl_flags_path_util",
+        "absl_flags_private_handle_accessor",
+        "absl_flags_program_name",
+        "absl_flags_reflection",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag",
+        "absl_flags_config",
+        "absl_flags_flag",
+        "absl_flags_flag_internal",
+        "absl_flags_path_util",
+        "absl_flags_private_handle_accessor",
+        "absl_flags_program_name",
+        "absl_flags_reflection",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_usage_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/flags/internal/usage.cc",
+    ],
+    generated_headers: ["absl_flags_usage_internal_hdrs"],
+    export_generated_headers: ["absl_flags_usage_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_config_notls",
+        "absl_flags_flag_notls",
+        "absl_flags_flag_internal_notls",
+        "absl_flags_path_util_notls",
+        "absl_flags_private_handle_accessor_notls",
+        "absl_flags_program_name_notls",
+        "absl_flags_reflection_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_config_notls",
+        "absl_flags_flag_notls",
+        "absl_flags_flag_internal_notls",
+        "absl_flags_path_util_notls",
+        "absl_flags_private_handle_accessor_notls",
+        "absl_flags_program_name_notls",
+        "absl_flags_reflection_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_reflection_hdrs",
+    srcs: [
+        "absl/flags/internal/registry.h",
+        "absl/flags/reflection.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/internal/registry.h",
+        "my_include_dir/absl/flags/reflection.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_reflection",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/flags/reflection.cc",
+    ],
+    generated_headers: ["absl_flags_reflection_hdrs"],
+    export_generated_headers: ["absl_flags_reflection_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag",
+        "absl_flags_commandlineflag_internal",
+        "absl_flags_config",
+        "absl_flags_private_handle_accessor",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_fast_type_id",
+        "absl_base_no_destructor",
+        "absl_container_flat_hash_map",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag",
+        "absl_flags_commandlineflag_internal",
+        "absl_flags_config",
+        "absl_flags_private_handle_accessor",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_fast_type_id",
+        "absl_base_no_destructor",
+        "absl_container_flat_hash_map",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_reflection_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/flags/reflection.cc",
+    ],
+    generated_headers: ["absl_flags_reflection_hdrs"],
+    export_generated_headers: ["absl_flags_reflection_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_flags_config_notls",
+        "absl_flags_private_handle_accessor_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_base_no_destructor_notls",
+        "absl_container_flat_hash_map_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_flags_config_notls",
+        "absl_flags_private_handle_accessor_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_base_no_destructor_notls",
+        "absl_container_flat_hash_map_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_flat_hash_map_hdrs",
+    srcs: [
+        "absl/container/flat_hash_map.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/flat_hash_map.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_flat_hash_map",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_flat_hash_map_hdrs"],
+    export_generated_headers: ["absl_container_flat_hash_map_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_container_memory",
+        "absl_container_hash_container_defaults",
+        "absl_container_raw_hash_map",
+        "absl_algorithm_container",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_container_container_memory",
+        "absl_container_hash_container_defaults",
+        "absl_container_raw_hash_map",
+        "absl_algorithm_container",
+        "absl_base_core_headers",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_flat_hash_map_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_flat_hash_map_hdrs"],
+    export_generated_headers: ["absl_container_flat_hash_map_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_container_memory_notls",
+        "absl_container_hash_container_defaults_notls",
+        "absl_container_raw_hash_map_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_container_memory_notls",
+        "absl_container_hash_container_defaults_notls",
+        "absl_container_raw_hash_map_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_core_headers_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_raw_hash_map_hdrs",
+    srcs: [
+        "absl/container/internal/raw_hash_map.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/raw_hash_map.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_raw_hash_map",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_raw_hash_map_hdrs"],
+    export_generated_headers: ["absl_container_raw_hash_map_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common_policy_traits",
+        "absl_container_container_memory",
+        "absl_container_raw_hash_set",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_throw_delegate",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common_policy_traits",
+        "absl_container_container_memory",
+        "absl_container_raw_hash_set",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_throw_delegate",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_raw_hash_map_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_raw_hash_map_hdrs"],
+    export_generated_headers: ["absl_container_raw_hash_map_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common_policy_traits_notls",
+        "absl_container_container_memory_notls",
+        "absl_container_raw_hash_set_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common_policy_traits_notls",
+        "absl_container_container_memory_notls",
+        "absl_container_raw_hash_set_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_raw_hash_set_hdrs",
+    srcs: [
+        "absl/container/internal/raw_hash_set.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/raw_hash_set.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_raw_hash_set",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/container/internal/raw_hash_set.cc",
+    ],
+    generated_headers: ["absl_container_raw_hash_set_hdrs"],
+    export_generated_headers: ["absl_container_raw_hash_set_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common",
+        "absl_container_common_policy_traits",
+        "absl_container_compressed_tuple",
+        "absl_container_container_memory",
+        "absl_container_hash_function_defaults",
+        "absl_container_hash_policy_traits",
+        "absl_container_hashtable_control_bytes",
+        "absl_container_hashtable_debug_hooks",
+        "absl_container_hashtablez_sampler",
+        "absl_container_raw_hash_set_resize_impl",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_endian",
+        "absl_base_iterator_traits_internal",
+        "absl_base_prefetch",
+        "absl_base_raw_logging_internal",
+        "absl_functional_function_ref",
+        "absl_hash",
+        "absl_hash_weakly_mixed_integer",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common",
+        "absl_container_common_policy_traits",
+        "absl_container_compressed_tuple",
+        "absl_container_container_memory",
+        "absl_container_hash_function_defaults",
+        "absl_container_hash_policy_traits",
+        "absl_container_hashtable_control_bytes",
+        "absl_container_hashtable_debug_hooks",
+        "absl_container_hashtablez_sampler",
+        "absl_container_raw_hash_set_resize_impl",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_endian",
+        "absl_base_iterator_traits_internal",
+        "absl_base_prefetch",
+        "absl_base_raw_logging_internal",
+        "absl_functional_function_ref",
+        "absl_hash",
+        "absl_hash_weakly_mixed_integer",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_numeric_bits",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_raw_hash_set_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/container/internal/raw_hash_set.cc",
+    ],
+    generated_headers: ["absl_container_raw_hash_set_hdrs"],
+    export_generated_headers: ["absl_container_raw_hash_set_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common_notls",
+        "absl_container_common_policy_traits_notls",
+        "absl_container_compressed_tuple_notls",
+        "absl_container_container_memory_notls",
+        "absl_container_hash_function_defaults_notls",
+        "absl_container_hash_policy_traits_notls",
+        "absl_container_hashtable_control_bytes_notls",
+        "absl_container_hashtable_debug_hooks_notls",
+        "absl_container_hashtablez_sampler_notls",
+        "absl_container_raw_hash_set_resize_impl_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_endian_notls",
+        "absl_base_iterator_traits_internal_notls",
+        "absl_base_prefetch_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_functional_function_ref_notls",
+        "absl_hash_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common_notls",
+        "absl_container_common_policy_traits_notls",
+        "absl_container_compressed_tuple_notls",
+        "absl_container_container_memory_notls",
+        "absl_container_hash_function_defaults_notls",
+        "absl_container_hash_policy_traits_notls",
+        "absl_container_hashtable_control_bytes_notls",
+        "absl_container_hashtable_debug_hooks_notls",
+        "absl_container_hashtablez_sampler_notls",
+        "absl_container_raw_hash_set_resize_impl_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_endian_notls",
+        "absl_base_iterator_traits_internal_notls",
+        "absl_base_prefetch_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_functional_function_ref_notls",
+        "absl_hash_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_numeric_bits_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_raw_hash_set_resize_impl_hdrs",
+    srcs: [
+        "absl/container/internal/raw_hash_set_resize_impl.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/raw_hash_set_resize_impl.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_raw_hash_set_resize_impl",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_raw_hash_set_resize_impl_hdrs"],
+    export_generated_headers: ["absl_container_raw_hash_set_resize_impl_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_raw_hash_set_resize_impl_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_raw_hash_set_resize_impl_hdrs"],
+    export_generated_headers: ["absl_container_raw_hash_set_resize_impl_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_hashtablez_sampler_hdrs",
+    srcs: [
+        "absl/container/internal/hashtablez_sampler.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/hashtablez_sampler.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_hashtablez_sampler",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/container/internal/hashtablez_sampler.cc",
+        "absl/container/internal/hashtablez_sampler_force_weak_definition.cc",
+    ],
+    generated_headers: ["absl_container_hashtablez_sampler_hdrs"],
+    export_generated_headers: ["absl_container_hashtablez_sampler_hdrs"],
+
+    whole_static_libs: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_base_raw_logging_internal",
+        "absl_debugging_stacktrace",
+        "absl_memory",
+        "absl_profiling_exponential_biased",
+        "absl_profiling_sample_recorder",
+        "absl_synchronization",
+        "absl_time",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_base_raw_logging_internal",
+        "absl_debugging_stacktrace",
+        "absl_memory",
+        "absl_profiling_exponential_biased",
+        "absl_profiling_sample_recorder",
+        "absl_synchronization",
+        "absl_time",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_hashtablez_sampler_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/container/internal/hashtablez_sampler.cc",
+        "absl/container/internal/hashtablez_sampler_force_weak_definition.cc",
+    ],
+    generated_headers: ["absl_container_hashtablez_sampler_hdrs"],
+    export_generated_headers: ["absl_container_hashtablez_sampler_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_memory_notls",
+        "absl_profiling_exponential_biased_notls",
+        "absl_profiling_sample_recorder_notls",
+        "absl_synchronization_notls",
+        "absl_time_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_memory_notls",
+        "absl_profiling_exponential_biased_notls",
+        "absl_profiling_sample_recorder_notls",
+        "absl_synchronization_notls",
+        "absl_time_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_profiling_sample_recorder_hdrs",
+    srcs: [
+        "absl/profiling/internal/sample_recorder.h",
+    ],
+    out: [
+        "my_include_dir/absl/profiling/internal/sample_recorder.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_profiling_sample_recorder",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_profiling_sample_recorder_hdrs"],
+    export_generated_headers: ["absl_profiling_sample_recorder_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_synchronization",
+        "absl_time",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_synchronization",
+        "absl_time",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_profiling_sample_recorder_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_profiling_sample_recorder_hdrs"],
+    export_generated_headers: ["absl_profiling_sample_recorder_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_synchronization_notls",
+        "absl_time_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_synchronization_notls",
+        "absl_time_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_hashtable_debug_hooks_hdrs",
+    srcs: [
+        "absl/container/internal/hashtable_debug_hooks.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/hashtable_debug_hooks.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_hashtable_debug_hooks",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hashtable_debug_hooks_hdrs"],
+    export_generated_headers: ["absl_container_hashtable_debug_hooks_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_hashtable_debug_hooks_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hashtable_debug_hooks_hdrs"],
+    export_generated_headers: ["absl_container_hashtable_debug_hooks_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_hashtable_control_bytes_hdrs",
+    srcs: [
+        "absl/container/internal/hashtable_control_bytes.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/hashtable_control_bytes.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_hashtable_control_bytes",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hashtable_control_bytes_hdrs"],
+    export_generated_headers: ["absl_container_hashtable_control_bytes_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_numeric_bits",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_endian",
+        "absl_numeric_bits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_hashtable_control_bytes_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hashtable_control_bytes_hdrs"],
+    export_generated_headers: ["absl_container_hashtable_control_bytes_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_numeric_bits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_endian_notls",
+        "absl_numeric_bits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_hash_policy_traits_hdrs",
+    srcs: [
+        "absl/container/internal/hash_policy_traits.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/hash_policy_traits.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_hash_policy_traits",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hash_policy_traits_hdrs"],
+    export_generated_headers: ["absl_container_hash_policy_traits_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common_policy_traits",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common_policy_traits",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_hash_policy_traits_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hash_policy_traits_hdrs"],
+    export_generated_headers: ["absl_container_hash_policy_traits_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common_policy_traits_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common_policy_traits_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_common_policy_traits_hdrs",
+    srcs: [
+        "absl/container/internal/common_policy_traits.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/common_policy_traits.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_common_policy_traits",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_common_policy_traits_hdrs"],
+    export_generated_headers: ["absl_container_common_policy_traits_hdrs"],
+
+    whole_static_libs: [
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_common_policy_traits_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_common_policy_traits_hdrs"],
+    export_generated_headers: ["absl_container_common_policy_traits_hdrs"],
+
+    whole_static_libs: [
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_hash_function_defaults_hdrs",
+    srcs: [
+        "absl/container/internal/hash_function_defaults.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/hash_function_defaults.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_hash_function_defaults",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hash_function_defaults_hdrs"],
+    export_generated_headers: ["absl_container_hash_function_defaults_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common",
+        "absl_base_config",
+        "absl_hash",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_strings_cord",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common",
+        "absl_base_config",
+        "absl_hash",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_strings_cord",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_hash_function_defaults_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hash_function_defaults_hdrs"],
+    export_generated_headers: ["absl_container_hash_function_defaults_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common_notls",
+        "absl_base_config_notls",
+        "absl_hash_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_strings_cord_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common_notls",
+        "absl_base_config_notls",
+        "absl_hash_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_strings_cord_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_common_hdrs",
+    srcs: [
+        "absl/container/internal/common.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/common.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_common",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_common_hdrs"],
+    export_generated_headers: ["absl_container_common_hdrs"],
+
+    whole_static_libs: [
+        "absl_meta_type_traits",
+        "absl_types_optional",
+    ],
+    export_static_lib_headers: [
+        "absl_meta_type_traits",
+        "absl_types_optional",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_common_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_common_hdrs"],
+    export_generated_headers: ["absl_container_common_hdrs"],
+
+    whole_static_libs: [
+        "absl_meta_type_traits_notls",
+        "absl_types_optional_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_meta_type_traits_notls",
+        "absl_types_optional_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_hash_container_defaults_hdrs",
+    srcs: [
+        "absl/container/hash_container_defaults.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/hash_container_defaults.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_hash_container_defaults",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hash_container_defaults_hdrs"],
+    export_generated_headers: ["absl_container_hash_container_defaults_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_hash_function_defaults",
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_container_hash_function_defaults",
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_hash_container_defaults_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_hash_container_defaults_hdrs"],
+    export_generated_headers: ["absl_container_hash_container_defaults_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_hash_function_defaults_notls",
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_hash_function_defaults_notls",
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_private_handle_accessor_hdrs",
+    srcs: [
+        "absl/flags/internal/private_handle_accessor.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/internal/private_handle_accessor.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_private_handle_accessor",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/flags/internal/private_handle_accessor.cc",
+    ],
+    generated_headers: ["absl_flags_private_handle_accessor_hdrs"],
+    export_generated_headers: ["absl_flags_private_handle_accessor_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag",
+        "absl_flags_commandlineflag_internal",
+        "absl_base_config",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag",
+        "absl_flags_commandlineflag_internal",
+        "absl_base_config",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_private_handle_accessor_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/flags/internal/private_handle_accessor.cc",
+    ],
+    generated_headers: ["absl_flags_private_handle_accessor_hdrs"],
+    export_generated_headers: ["absl_flags_private_handle_accessor_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_base_config_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_base_config_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_commandlineflag_internal_hdrs",
+    srcs: [
+        "absl/flags/internal/commandlineflag.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/internal/commandlineflag.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_commandlineflag_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/flags/internal/commandlineflag.cc",
+    ],
+    generated_headers: ["absl_flags_commandlineflag_internal_hdrs"],
+    export_generated_headers: ["absl_flags_commandlineflag_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_fast_type_id",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_fast_type_id",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_commandlineflag_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/flags/internal/commandlineflag.cc",
+    ],
+    generated_headers: ["absl_flags_commandlineflag_internal_hdrs"],
+    export_generated_headers: ["absl_flags_commandlineflag_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_fast_type_id_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_fast_type_id_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_commandlineflag_hdrs",
+    srcs: [
+        "absl/flags/commandlineflag.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/commandlineflag.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_commandlineflag",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/flags/commandlineflag.cc",
+    ],
+    generated_headers: ["absl_flags_commandlineflag_hdrs"],
+    export_generated_headers: ["absl_flags_commandlineflag_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag_internal",
+        "absl_base_config",
+        "absl_base_fast_type_id",
+        "absl_strings",
+        "absl_types_optional",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag_internal",
+        "absl_base_config",
+        "absl_base_fast_type_id",
+        "absl_strings",
+        "absl_types_optional",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_commandlineflag_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/flags/commandlineflag.cc",
+    ],
+    generated_headers: ["absl_flags_commandlineflag_hdrs"],
+    export_generated_headers: ["absl_flags_commandlineflag_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_strings_notls",
+        "absl_types_optional_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_strings_notls",
+        "absl_types_optional_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_config_hdrs",
+    srcs: [
+        "absl/flags/config.h",
+        "absl/flags/usage_config.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/config.h",
+        "my_include_dir/absl/flags/usage_config.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_config",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/flags/usage_config.cc",
+    ],
+    generated_headers: ["absl_flags_config_hdrs"],
+    export_generated_headers: ["absl_flags_config_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_path_util",
+        "absl_flags_program_name",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_path_util",
+        "absl_flags_program_name",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_config_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/flags/usage_config.cc",
+    ],
+    generated_headers: ["absl_flags_config_hdrs"],
+    export_generated_headers: ["absl_flags_config_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_path_util_notls",
+        "absl_flags_program_name_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_path_util_notls",
+        "absl_flags_program_name_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_program_name_hdrs",
+    srcs: [
+        "absl/flags/internal/program_name.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/internal/program_name.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_program_name",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/flags/internal/program_name.cc",
+    ],
+    generated_headers: ["absl_flags_program_name_hdrs"],
+    export_generated_headers: ["absl_flags_program_name_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_path_util",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_path_util",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_no_destructor",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_program_name_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/flags/internal/program_name.cc",
+    ],
+    generated_headers: ["absl_flags_program_name_hdrs"],
+    export_generated_headers: ["absl_flags_program_name_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_path_util_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_path_util_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_no_destructor_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_path_util_hdrs",
+    srcs: [
+        "absl/flags/internal/path_util.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/internal/path_util.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_path_util",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_flags_path_util_hdrs"],
+    export_generated_headers: ["absl_flags_path_util_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_path_util_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+
+    ],
+    generated_headers: ["absl_flags_path_util_hdrs"],
+    export_generated_headers: ["absl_flags_path_util_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_flag_internal_hdrs",
+    srcs: [
+        "absl/flags/internal/flag.h",
+        "absl/flags/internal/sequence_lock.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/internal/flag.h",
+        "my_include_dir/absl/flags/internal/sequence_lock.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_flag_internal",
+    defaults: ["absl_defaults"],
+
+    srcs: [
+        "absl/flags/internal/flag.cc",
+    ],
+    generated_headers: ["absl_flags_flag_internal_hdrs"],
+    export_generated_headers: ["absl_flags_flag_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag",
+        "absl_flags_commandlineflag_internal",
+        "absl_flags_config",
+        "absl_flags_marshalling",
+        "absl_flags_reflection",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_fast_type_id",
+        "absl_base_no_destructor",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_synchronization",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag",
+        "absl_flags_commandlineflag_internal",
+        "absl_flags_config",
+        "absl_flags_marshalling",
+        "absl_flags_reflection",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_dynamic_annotations",
+        "absl_base_fast_type_id",
+        "absl_base_no_destructor",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_synchronization",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_flag_internal_notls",
+    defaults: ["absl_notls_defaults"],
+
+    srcs: [
+        "absl/flags/internal/flag.cc",
+    ],
+    generated_headers: ["absl_flags_flag_internal_hdrs"],
+    export_generated_headers: ["absl_flags_flag_internal_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_flags_config_notls",
+        "absl_flags_marshalling_notls",
+        "absl_flags_reflection_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_base_no_destructor_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_commandlineflag_internal_notls",
+        "absl_flags_config_notls",
+        "absl_flags_marshalling_notls",
+        "absl_flags_reflection_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_dynamic_annotations_notls",
+        "absl_base_fast_type_id_notls",
+        "absl_base_no_destructor_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+        "absl_utility_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_marshalling_hdrs",
+    srcs: [
+        "absl/flags/marshalling.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/marshalling.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_marshalling",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/flags/marshalling.cc",
+    ],
+    generated_headers: ["absl_flags_marshalling_hdrs"],
+    export_generated_headers: ["absl_flags_marshalling_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_numeric_int128",
+        "absl_strings",
+        "absl_strings_str_format",
+        "absl_types_optional",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_log_severity",
+        "absl_numeric_int128",
+        "absl_strings",
+        "absl_strings_str_format",
+        "absl_types_optional",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_marshalling_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/flags/marshalling.cc",
+    ],
+    generated_headers: ["absl_flags_marshalling_hdrs"],
+    export_generated_headers: ["absl_flags_marshalling_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_numeric_int128_notls",
+        "absl_strings_notls",
+        "absl_strings_str_format_notls",
+        "absl_types_optional_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_log_severity_notls",
+        "absl_numeric_int128_notls",
+        "absl_strings_notls",
+        "absl_strings_str_format_notls",
+        "absl_types_optional_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_flag_hdrs",
+    srcs: [
+        "absl/flags/declare.h",
+        "absl/flags/flag.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/declare.h",
+        "my_include_dir/absl/flags/flag.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_flag",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_flags_flag_hdrs"],
+    export_generated_headers: ["absl_flags_flag_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag",
+        "absl_flags_config",
+        "absl_flags_flag_internal",
+        "absl_flags_reflection",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_strings",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag",
+        "absl_flags_config",
+        "absl_flags_flag_internal",
+        "absl_flags_reflection",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_nullability",
+        "absl_strings",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_flag_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_flags_flag_hdrs"],
+    export_generated_headers: ["absl_flags_flag_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_config_notls",
+        "absl_flags_flag_internal_notls",
+        "absl_flags_reflection_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_strings_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_commandlineflag_notls",
+        "absl_flags_config_notls",
+        "absl_flags_flag_internal_notls",
+        "absl_flags_reflection_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_nullability_notls",
+        "absl_strings_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_flags_usage_hdrs",
+    srcs: [
+        "absl/flags/usage.h",
+    ],
+    out: [
+        "my_include_dir/absl/flags/usage.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_flags_usage",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/flags/usage.cc",
+    ],
+    generated_headers: ["absl_flags_usage_hdrs"],
+    export_generated_headers: ["absl_flags_usage_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_usage_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_usage_internal",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_strings",
+        "absl_synchronization",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_flags_usage_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/flags/usage.cc",
+    ],
+    generated_headers: ["absl_flags_usage_hdrs"],
+    export_generated_headers: ["absl_flags_usage_hdrs"],
+
+    whole_static_libs: [
+        "absl_flags_usage_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_flags_usage_internal_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_strings_notls",
+        "absl_synchronization_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_debugging_failure_signal_handler_hdrs",
+    srcs: [
+        "absl/debugging/failure_signal_handler.h",
+    ],
+    out: [
+        "my_include_dir/absl/debugging/failure_signal_handler.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_debugging_failure_signal_handler",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+        "absl/debugging/failure_signal_handler.cc",
+    ],
+    generated_headers: ["absl_debugging_failure_signal_handler_hdrs"],
+    export_generated_headers: ["absl_debugging_failure_signal_handler_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_examine_stack",
+        "absl_debugging_stacktrace",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_examine_stack",
+        "absl_debugging_stacktrace",
+        "absl_base",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_debugging_failure_signal_handler_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+        "absl/debugging/failure_signal_handler.cc",
+    ],
+    generated_headers: ["absl_debugging_failure_signal_handler_hdrs"],
+    export_generated_headers: ["absl_debugging_failure_signal_handler_hdrs"],
+
+    whole_static_libs: [
+        "absl_debugging_examine_stack_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_debugging_examine_stack_notls",
+        "absl_debugging_stacktrace_notls",
+        "absl_base_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_node_hash_set_hdrs",
+    srcs: [
+        "absl/container/node_hash_set.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/node_hash_set.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_node_hash_set",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_node_hash_set_hdrs"],
+    export_generated_headers: ["absl_container_node_hash_set_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_container_memory",
+        "absl_container_hash_container_defaults",
+        "absl_container_node_slot_policy",
+        "absl_container_raw_hash_set",
+        "absl_algorithm_container",
+        "absl_base_core_headers",
+        "absl_memory",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_container_container_memory",
+        "absl_container_hash_container_defaults",
+        "absl_container_node_slot_policy",
+        "absl_container_raw_hash_set",
+        "absl_algorithm_container",
+        "absl_base_core_headers",
+        "absl_memory",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_node_hash_set_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_node_hash_set_hdrs"],
+    export_generated_headers: ["absl_container_node_hash_set_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_container_memory_notls",
+        "absl_container_hash_container_defaults_notls",
+        "absl_container_node_slot_policy_notls",
+        "absl_container_raw_hash_set_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_core_headers_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_container_memory_notls",
+        "absl_container_hash_container_defaults_notls",
+        "absl_container_node_slot_policy_notls",
+        "absl_container_raw_hash_set_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_core_headers_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_node_slot_policy_hdrs",
+    srcs: [
+        "absl/container/internal/node_slot_policy.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/node_slot_policy.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_node_slot_policy",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_node_slot_policy_hdrs"],
+    export_generated_headers: ["absl_container_node_slot_policy_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_node_slot_policy_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_node_slot_policy_hdrs"],
+    export_generated_headers: ["absl_container_node_slot_policy_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_node_hash_map_hdrs",
+    srcs: [
+        "absl/container/node_hash_map.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/node_hash_map.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_node_hash_map",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_node_hash_map_hdrs"],
+    export_generated_headers: ["absl_container_node_hash_map_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_container_memory",
+        "absl_container_hash_container_defaults",
+        "absl_container_node_slot_policy",
+        "absl_container_raw_hash_map",
+        "absl_algorithm_container",
+        "absl_base_core_headers",
+        "absl_memory",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_container_container_memory",
+        "absl_container_hash_container_defaults",
+        "absl_container_node_slot_policy",
+        "absl_container_raw_hash_map",
+        "absl_algorithm_container",
+        "absl_base_core_headers",
+        "absl_memory",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_node_hash_map_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_node_hash_map_hdrs"],
+    export_generated_headers: ["absl_container_node_hash_map_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_container_memory_notls",
+        "absl_container_hash_container_defaults_notls",
+        "absl_container_node_slot_policy_notls",
+        "absl_container_raw_hash_map_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_core_headers_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_container_memory_notls",
+        "absl_container_hash_container_defaults_notls",
+        "absl_container_node_slot_policy_notls",
+        "absl_container_raw_hash_map_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_core_headers_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_flat_hash_set_hdrs",
+    srcs: [
+        "absl/container/flat_hash_set.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/flat_hash_set.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_flat_hash_set",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_flat_hash_set_hdrs"],
+    export_generated_headers: ["absl_container_flat_hash_set_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_container_memory",
+        "absl_container_hash_container_defaults",
+        "absl_container_raw_hash_set",
+        "absl_algorithm_container",
+        "absl_base_core_headers",
+        "absl_memory",
+        "absl_meta_type_traits",
+    ],
+    export_static_lib_headers: [
+        "absl_container_container_memory",
+        "absl_container_hash_container_defaults",
+        "absl_container_raw_hash_set",
+        "absl_algorithm_container",
+        "absl_base_core_headers",
+        "absl_memory",
+        "absl_meta_type_traits",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_flat_hash_set_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_flat_hash_set_hdrs"],
+    export_generated_headers: ["absl_container_flat_hash_set_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_container_memory_notls",
+        "absl_container_hash_container_defaults_notls",
+        "absl_container_raw_hash_set_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_core_headers_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_container_memory_notls",
+        "absl_container_hash_container_defaults_notls",
+        "absl_container_raw_hash_set_notls",
+        "absl_algorithm_container_notls",
+        "absl_base_core_headers_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_btree_hdrs",
+    srcs: [
+        "absl/container/btree_map.h",
+        "absl/container/btree_set.h",
+        "absl/container/internal/btree.h",
+        "absl/container/internal/btree_container.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/btree_map.h",
+        "my_include_dir/absl/container/btree_set.h",
+        "my_include_dir/absl/container/internal/btree.h",
+        "my_include_dir/absl/container/internal/btree_container.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_btree",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_btree_hdrs"],
+    export_generated_headers: ["absl_container_btree_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common",
+        "absl_container_common_policy_traits",
+        "absl_container_compressed_tuple",
+        "absl_container_container_memory",
+        "absl_container_layout",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_base_throw_delegate",
+        "absl_hash_weakly_mixed_integer",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_strings_cord",
+        "absl_types_compare",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common",
+        "absl_container_common_policy_traits",
+        "absl_container_compressed_tuple",
+        "absl_container_container_memory",
+        "absl_container_layout",
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_base_raw_logging_internal",
+        "absl_base_throw_delegate",
+        "absl_hash_weakly_mixed_integer",
+        "absl_memory",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_strings_cord",
+        "absl_types_compare",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_btree_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_btree_hdrs"],
+    export_generated_headers: ["absl_container_btree_hdrs"],
+
+    whole_static_libs: [
+        "absl_container_common_notls",
+        "absl_container_common_policy_traits_notls",
+        "absl_container_compressed_tuple_notls",
+        "absl_container_container_memory_notls",
+        "absl_container_layout_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_strings_cord_notls",
+        "absl_types_compare_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_container_common_notls",
+        "absl_container_common_policy_traits_notls",
+        "absl_container_compressed_tuple_notls",
+        "absl_container_container_memory_notls",
+        "absl_container_layout_notls",
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_base_raw_logging_internal_notls",
+        "absl_base_throw_delegate_notls",
+        "absl_hash_weakly_mixed_integer_notls",
+        "absl_memory_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_strings_cord_notls",
+        "absl_types_compare_notls",
+    ],
+
+}
+
+genrule {
+    name: "absl_container_layout_hdrs",
+    srcs: [
+        "absl/container/internal/layout.h",
+    ],
+    out: [
+        "my_include_dir/absl/container/internal/layout.h",
+    ],
+    export_include_dirs: ["my_include_dir"],
+    cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+        "cp --parents $(in) $(genDir)/temp && " +
+        // delete empty folders automatically created by soong
+        "rm -rf $(genDir)/my_include_dir/* && " +
+        "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+        "rm -rf $(genDir)/temp",
+}
+
+cc_library_static {
+    name: "absl_container_layout",
+    defaults: ["absl_defaults"],
+    visibility: ["//visibility:public"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_layout_hdrs"],
+    export_generated_headers: ["absl_container_layout_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_debugging_demangle_internal",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_types_span",
+        "absl_utility",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config",
+        "absl_base_core_headers",
+        "absl_debugging_demangle_internal",
+        "absl_meta_type_traits",
+        "absl_strings",
+        "absl_types_span",
+        "absl_utility",
+    ],
+
+}
+
+cc_library_static {
+    name: "absl_container_layout_notls",
+    defaults: ["absl_notls_defaults"],
+    visibility: ["//external/protobuf"],
+    srcs: [
+
+    ],
+    generated_headers: ["absl_container_layout_hdrs"],
+    export_generated_headers: ["absl_container_layout_hdrs"],
+
+    whole_static_libs: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_debugging_demangle_internal_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_types_span_notls",
+        "absl_utility_notls",
+    ],
+    export_static_lib_headers: [
+        "absl_base_config_notls",
+        "absl_base_core_headers_notls",
+        "absl_debugging_demangle_internal_notls",
+        "absl_meta_type_traits_notls",
+        "absl_strings_notls",
+        "absl_types_span_notls",
+        "absl_utility_notls",
+    ],
+
+}
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index 32cc28f..f01021b 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -10,6 +10,7 @@
   "base/config.h"
   "base/const_init.h"
   "base/dynamic_annotations.h"
+  "base/fast_type_id.h"
   "base/internal/atomic_hook.h"
   "base/internal/cycleclock.cc"
   "base/internal/cycleclock.h"
@@ -18,15 +19,13 @@
   "base/internal/dynamic_annotations.h"
   "base/internal/endian.h"
   "base/internal/errno_saver.h"
-  "base/internal/fast_type_id.h"
   "base/internal/hide_ptr.h"
   "base/internal/identity.h"
-  "base/internal/invoke.h"
-  "base/internal/inline_variable.h"
+  "base/internal/iterator_traits.h"
   "base/internal/low_level_alloc.cc"
   "base/internal/low_level_alloc.h"
   "base/internal/low_level_scheduling.h"
-  "base/internal/nullability_impl.h"
+  "base/internal/nullability_deprecated.h"
   "base/internal/per_thread_tls.h"
   "base/internal/poison.cc"
   "base/internal/poison.h"
@@ -49,6 +48,8 @@
   "base/internal/thread_identity.h"
   "base/internal/throw_delegate.cc"
   "base/internal/throw_delegate.h"
+  "base/internal/tracing.cc"
+  "base/internal/tracing.h"
   "base/internal/tsan_mutex_interface.h"
   "base/internal/unaligned_access.h"
   "base/internal/unscaledcycleclock.cc"
@@ -81,6 +82,7 @@
   "container/internal/container_memory.h"
   "container/internal/hash_function_defaults.h"
   "container/internal/hash_policy_traits.h"
+  "container/internal/hashtable_control_bytes.h"
   "container/internal/hashtable_debug.h"
   "container/internal/hashtable_debug_hooks.h"
   "container/internal/hashtablez_sampler.cc"
@@ -92,6 +94,7 @@
   "container/internal/raw_hash_map.h"
   "container/internal/raw_hash_set.cc"
   "container/internal/raw_hash_set.h"
+  "container/internal/raw_hash_set_resize_impl.h"
   "container/internal/tracked.h"
   "container/node_hash_map.h"
   "container/node_hash_set.h"
@@ -124,6 +127,7 @@
   "debugging/symbolize.h"
   "debugging/internal/address_is_readable.cc"
   "debugging/internal/address_is_readable.h"
+  "debugging/internal/addresses.h"
   "debugging/internal/bounded_utf8_length_sequence.h"
   "debugging/internal/decode_rust_punycode.cc"
   "debugging/internal/decode_rust_punycode.h"
@@ -158,6 +162,7 @@
   "hash/internal/spy_hash_state.h"
   "hash/internal/low_level_hash.h"
   "hash/internal/low_level_hash.cc"
+  "hash/internal/weakly_mixed_integer.h"
   "log/absl_check.h"
   "log/absl_log.h"
   "log/absl_vlog_is_on.h"
@@ -191,13 +196,14 @@
   "log/internal/proto.cc"
   "log/internal/strip.h"
   "log/internal/structured.h"
+  "log/internal/structured_proto.cc"
+  "log/internal/structured_proto.h"
   "log/internal/vlog_config.cc"
   "log/internal/vlog_config.h"
   "log/internal/voidify.h"
   "log/initialize.cc"
   "log/initialize.h"
   "log/log.h"
-  "log/log_entry.cc"
   "log/log_entry.h"
   "log/log_sink.cc"
   "log/log_sink.h"
@@ -234,8 +240,8 @@
   "random/internal/nonsecure_base.h"
   "random/internal/pcg_engine.h"
   "random/internal/platform.h"
-  "random/internal/pool_urbg.cc"
-  "random/internal/pool_urbg.h"
+  "random/internal/entropy_pool.cc"
+  "random/internal/entropy_pool.h"
   "random/internal/randen.cc"
   "random/internal/randen.h"
   "random/internal/randen_detect.cc"
@@ -282,7 +288,6 @@
   "strings/cord.h"
   "strings/cord_analysis.cc"
   "strings/cord_analysis.h"
-  "strings/cord_buffer.cc"
   "strings/cord_buffer.h"
   "strings/escaping.cc"
   "strings/escaping.h"
@@ -428,20 +433,11 @@
   "time/internal/cctz/src/tzfile.h"
   "time/internal/cctz/src/zone_info_source.cc"
   "types/any.h"
-  "types/bad_any_cast.cc"
-  "types/bad_any_cast.h"
-  "types/bad_optional_access.cc"
-  "types/bad_optional_access.h"
-  "types/bad_variant_access.cc"
-  "types/bad_variant_access.h"
   "types/compare.h"
-  "types/internal/variant.h"
   "types/optional.h"
-  "types/internal/optional.h"
   "types/span.h"
   "types/internal/span.h"
   "types/variant.h"
-  "utility/internal/if_constexpr.h"
   "utility/utility.h"
   "debugging/leak_check.cc"
 )
@@ -492,10 +488,6 @@
   "any"
   "any_invocable"
   "atomic_hook"
-  "bad_any_cast"
-  "bad_any_cast_impl"
-  "bad_optional_access"
-  "bad_variant_access"
   "base"
   "base_internal"
   "bind_front"
@@ -727,10 +719,8 @@
 
 if(ABSL_INTERNAL_AT_LEAST_CXX20)
   set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_20)
-elseif(ABSL_INTERNAL_AT_LEAST_CXX17)
-  set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_17)
 else()
-  set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_14)
+  set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_17)
 endif()
 
 function(absl_internal_dll_contains)
@@ -834,6 +824,7 @@
     PRIVATE
       ${_dll_libs}
       ${ABSL_DEFAULT_LINKOPTS}
+      $<$<BOOL:${ANDROID}>:-llog>
   )
   set_target_properties(${_dll} PROPERTIES
     LINKER_LANGUAGE "CXX"
@@ -894,7 +885,7 @@
   )
 
   if(ABSL_PROPAGATE_CXX_STD)
-    # Abseil libraries require C++14 as the current minimum standard. When
+    # Abseil libraries require C++17 as the current minimum standard. When
     # compiled with a higher minimum (either because it is the compiler's
     # default or explicitly requested), then Abseil requires that standard.
     target_compile_features(${_dll} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE})
diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake
index b177e59..624a3c7 100644
--- a/CMake/AbseilHelpers.cmake
+++ b/CMake/AbseilHelpers.cmake
@@ -186,16 +186,16 @@
         endif()
       endif()
     endforeach()
-    set(skip_next_cflag OFF)
     foreach(cflag ${ABSL_CC_LIB_COPTS})
-      if(skip_next_cflag)
-        set(skip_next_cflag OFF)
-      elseif(${cflag} MATCHES "^-Xarch_")
+      # Strip out the CMake-specific `SHELL:` prefix, which is used to construct
+      # a group of space-separated options.
+      # https://cmake.org/cmake/help/v3.30/command/target_compile_options.html#option-de-duplication
+      string(REGEX REPLACE "^SHELL:" "" cflag "${cflag}")
+      if(${cflag} MATCHES "^-Xarch_")
         # An -Xarch_ flag implies that its successor only applies to the
-        # specified platform. Filter both of them out before the successor
-        # reaches the "^-m" filter.
-        set(skip_next_cflag ON)
-      elseif(${cflag} MATCHES "^(-Wno|/wd)")
+        # specified platform. Such option groups are each specified in a single
+        # `SHELL:`-prefixed string in the COPTS list, which we simply ignore.
+      elseif(${cflag} MATCHES "^(-Wno-|/wd)")
         # These flags are needed to suppress warnings that might fire in our headers.
         set(PC_CFLAGS "${PC_CFLAGS} ${cflag}")
       elseif(${cflag} MATCHES "^(-W|/w[1234eo])")
@@ -301,7 +301,7 @@
     endif()
 
     if(ABSL_PROPAGATE_CXX_STD)
-      # Abseil libraries require C++14 as the current minimum standard. When
+      # Abseil libraries require C++17 as the current minimum standard. When
       # compiled with a higher standard (either because it is the compiler's
       # default or explicitly requested), then Abseil requires that standard.
       target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE})
@@ -338,7 +338,7 @@
     target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
 
     if(ABSL_PROPAGATE_CXX_STD)
-      # Abseil libraries require C++14 as the current minimum standard.
+      # Abseil libraries require C++17 as the current minimum standard.
       # Top-level application CMake projects should ensure a consistent C++
       # standard for all compiled sources by setting CMAKE_CXX_STANDARD.
       target_compile_features(${_NAME} INTERFACE ${ABSL_INTERNAL_CXX_STD_FEATURE})
@@ -450,7 +450,7 @@
   set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
 
   if(ABSL_PROPAGATE_CXX_STD)
-    # Abseil libraries require C++14 as the current minimum standard.
+    # Abseil libraries require C++17 as the current minimum standard.
     # Top-level application CMake projects should ensure a consistent C++
     # standard for all compiled sources by setting CMAKE_CXX_STANDARD.
     target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE})
diff --git a/CMake/README.md b/CMake/README.md
index 808edfe..ecaeaf0 100644
--- a/CMake/README.md
+++ b/CMake/README.md
@@ -43,8 +43,8 @@
 project(my_app_project)
 
 # Pick the C++ standard to compile with.
-# Abseil currently supports C++14, C++17, and C++20.
-set(CMAKE_CXX_STANDARD 14)
+# Abseil currently supports C++17 and C++20.
+set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 
 add_subdirectory(abseil-cpp)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7c82b3a..8d3059d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -23,8 +23,8 @@
   cmake_policy(SET CMP0141 NEW)
 endif (POLICY CMP0141)
 
-project(absl LANGUAGES CXX VERSION 20240722)
-set(ABSL_SOVERSION "2407.0.0")
+project(absl LANGUAGES CXX VERSION 20250512)
+set(ABSL_SOVERSION "2505.0.0")
 include(CTest)
 
 # Output directory is correct by default for most build setups. However, when
@@ -46,11 +46,8 @@
 set(CMAKE_BUILD_RPATH_USE_ORIGIN ON)
 
 option(ABSL_PROPAGATE_CXX_STD
-  "Use CMake C++ standard meta features (e.g. cxx_std_14) that propagate to targets that link to Abseil"
-  OFF)  # TODO: Default to ON for CMake 3.8 and greater.
-if(NOT ABSL_PROPAGATE_CXX_STD)
-  message(WARNING "A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON for CMake 3.8 and up. We recommend enabling this option to ensure your project still builds correctly.")
-endif()
+  "Use CMake C++ standard meta features (e.g. cxx_std_17) that propagate to targets that link to Abseil"
+  ON)
 
 option(ABSL_USE_SYSTEM_INCLUDES
   "Silence warnings in Abseil headers by marking them as SYSTEM includes"
@@ -204,11 +201,13 @@
     )
   endif()  # absl_VERSION
 
+  # Install the headers except for "options.h" which is installed separately.
   install(DIRECTORY absl
     DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
     FILES_MATCHING
       PATTERN "*.inc"
       PATTERN "*.h"
+      PATTERN "options.h" EXCLUDE
       PATTERN "copts" EXCLUDE
       PATTERN "testdata" EXCLUDE
     )
@@ -248,7 +247,21 @@
     ABSL_INTERNAL_OPTIONS_H_PINNED
     "${ABSL_INTERNAL_OPTIONS_H_CONTENTS}")
 
-  file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/options-pinned.h" CONTENT "${ABSL_INTERNAL_OPTIONS_H_PINNED}")
+  # If the file already exists, check if it matches the new contents.
+  # This avoids writing the file if it is already up-to-date when the CMake
+  # generation is triggered and triggering unnecessary rebuilds.
+  set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE TRUE)
+  if (EXISTS "${CMAKE_BINARY_DIR}/options-pinned.h")
+    file(READ "${CMAKE_BINARY_DIR}/options-pinned.h" ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS)
+    if ("${ABSL_INTERNAL_OPTIONS_H_PINNED}" STREQUAL "${ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS}")
+      set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE FALSE)
+    endif()
+  endif()
+
+  # If the file needs an update, generate it.
+  if (ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE)
+    file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/options-pinned.h" CONTENT "${ABSL_INTERNAL_OPTIONS_H_PINNED}")
+  endif()
 
   install(FILES "${CMAKE_BINARY_DIR}/options-pinned.h"
          DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/absl/base
diff --git a/METADATA b/METADATA
index 4f42d94..8475b65 100644
--- a/METADATA
+++ b/METADATA
@@ -1,18 +1,20 @@
-name: "extern/abseil-cpp"
-description:
-    "An open-source collection of C++ code designed to augment the C++ standard "
-    "library"
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update external/abseil-cpp
+# For more info, check https://cs.android.com/android/platform/superproject/main/+/main:tools/external_updater/README.md
 
+name: "extern/abseil-cpp"
+description: "An open-source collection of C++ code designed to augment the C++ standard library"
 third_party {
-  url {
-    type: HOMEPAGE
-    value: "https://abseil.io"
-  }
-  url {
-    type: GIT
-    value: "https://github.com/abseil/abseil-cpp"
-  }
-  version: "20240722.0"
-  last_upgrade_date { year: 2024 month: 11 day: 4 }
   license_type: NOTICE
+  last_upgrade_date {
+    year: 2025
+    month: 7
+    day: 2
+  }
+  homepage: "https://abseil.io"
+  identifier {
+    type: "Git"
+    value: "https://github.com/abseil/abseil-cpp"
+    version: "20250512.1"
+  }
 }
diff --git a/MODULE.bazel b/MODULE.bazel
index 75285b6..48a65c7 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -16,27 +16,28 @@
 
 module(
     name = "abseil-cpp",
-    version = "20240722.0",
+    version = "20250512.1",
     compatibility_level = 1,
 )
 
-cc_configure = use_extension("@bazel_tools//tools/cpp:cc_configure.bzl", "cc_configure_extension")
+cc_configure = use_extension("@rules_cc//cc:extensions.bzl",
+                             "cc_configure_extension",
+                             dev_dependency = True)
 use_repo(cc_configure, "local_config_cc")
 
-# Only direct dependencies need to be listed below.
-# Please keep the versions in sync with the versions in the WORKSPACE file.
+bazel_dep(name = "rules_cc", version = "0.1.1")
+bazel_dep(name = "bazel_skylib", version = "1.7.1")
+bazel_dep(name = "platforms", version = "0.0.11")
 
-bazel_dep(name = "bazel_skylib",
-          version = "1.5.0")
+bazel_dep(
+    name = "google_benchmark",
+    version = "1.9.2",
+    dev_dependency = True,
+)
 
-bazel_dep(name = "google_benchmark",
-          version = "1.8.3",
-          repo_name = "com_github_google_benchmark",
-          dev_dependency = True)
-
-bazel_dep(name = "googletest",
-          version = "1.15.2",
-          repo_name = "com_google_googletest")
-
-bazel_dep(name = "platforms",
-          version = "0.0.10")
+# Note: Googletest is NOT a dev_dependency. Some Abseil test utilities
+# intended to be used by Abseil users depend on GoogleTest.
+bazel_dep(
+    name = "googletest",
+    version = "1.17.0",
+)
diff --git a/README.md b/README.md
index f834fcd..c2c851e 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Abseil - C++ Common Libraries
 
 The repository contains the Abseil C++ library code. Abseil is an open-source
-collection of C++ code (compliant to C++14) designed to augment the C++
+collection of C++ code (compliant to C++17) designed to augment the C++
 standard library.
 
 ## Table of Contents
@@ -99,8 +99,8 @@
   <br /> The `memory` library contains memory management facilities that augment
   C++'s `<memory>` library.
 * [`meta`](absl/meta/)
-  <br /> The `meta` library contains compatible versions of type checks
-  available within C++14 and C++17 versions of the C++ `<type_traits>` library.
+  <br /> The `meta` library contains type checks
+  similar to those available in the C++ `<type_traits>` library.
 * [`numeric`](absl/numeric/)
   <br /> The `numeric` library contains 128-bit integer types as well as
   implementations of C++20's bitwise math functions.
@@ -108,15 +108,14 @@
   <br /> The `profiling` library contains utility code for profiling C++
   entities.  It is currently a private dependency of other Abseil libraries.
 * [`random`](absl/random/)
-  <br /> The `random` library contains functions for generating psuedorandom
+  <br /> The `random` library contains functions for generating pseudorandom
   values.
 * [`status`](absl/status/)
   <br /> The `status` library contains abstractions for error handling,
   specifically `absl::Status` and `absl::StatusOr<T>`.
 * [`strings`](absl/strings/)
   <br /> The `strings` library contains a variety of strings routines and
-  utilities, including a C++14-compatible version of the C++17
-  `std::string_view` type.
+  utilities.
 * [`synchronization`](absl/synchronization/)
   <br /> The `synchronization` library contains concurrency primitives (Abseil's
   `absl::Mutex` class, an alternative to `std::mutex`) and a variety of
@@ -126,8 +125,7 @@
   points in time, durations of time, and formatting and parsing time within
   time zones.
 * [`types`](absl/types/)
-  <br /> The `types` library contains non-container utility types, like a
-  C++14-compatible version of the C++17 `std::optional` type.
+  <br /> The `types` library contains non-container utility types.
 * [`utility`](absl/utility/)
   <br /> The `utility` library contains utility and helper code.
 
diff --git a/WORKSPACE b/WORKSPACE
deleted file mode 100644
index dee6d05..0000000
--- a/WORKSPACE
+++ /dev/null
@@ -1,63 +0,0 @@
-#
-# Copyright 2019 The Abseil Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-workspace(name = "com_google_absl")
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-
-# GoogleTest/GoogleMock framework. Used by most unit-tests.
-http_archive(
-    name = "com_google_googletest",
-    sha256 = "7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926",
-    strip_prefix = "googletest-1.15.2",
-    # Keep this URL in sync with the version in ci/cmake_common.sh and
-    # ci/windows_msvc_cmake.bat.
-    urls = ["https://github.com/google/googletest/releases/download/v1.15.2/googletest-1.15.2.tar.gz"],
-)
-
-# RE2 (the regular expression library used by GoogleTest)
-http_archive(
-    name = "com_googlesource_code_re2",
-    sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b",
-    strip_prefix = "re2-2024-07-02",
-    urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"],
-    repo_mapping = {"@abseil-cpp": "@com_google_absl"},
-)
-
-# Google benchmark.
-http_archive(
-    name = "com_github_google_benchmark",
-    sha256 = "6bc180a57d23d4d9515519f92b0c83d61b05b5bab188961f36ac7b06b0d9e9ce",
-    strip_prefix = "benchmark-1.8.3",
-    urls = ["https://github.com/google/benchmark/archive/refs/tags/v1.8.3.tar.gz"],
-)
-
-# Bazel Skylib.
-http_archive(
-    name = "bazel_skylib",
-    sha256 = "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94",
-    urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz"],
-)
-
-# Bazel platform rules.
-http_archive(
-    name = "platforms",
-    urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
-        "https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz",
-    ],
-    sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
-)
diff --git a/WORKSPACE.bzlmod b/WORKSPACE.bzlmod
deleted file mode 100644
index 83e67ba..0000000
--- a/WORKSPACE.bzlmod
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2024 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.
-
-# https://bazel.build/external/migration#workspace.bzlmod
-#
-# This file is intentionally empty. When bzlmod is enabled and this
-# file exists, the contents of WORKSPACE is ignored. This prevents
-# bzlmod builds from unintentionally depending on the WORKSPACE file.
diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel
index 253c0ae..2a25ac6 100644
--- a/absl/BUILD.bazel
+++ b/absl/BUILD.bazel
@@ -29,14 +29,6 @@
 )
 
 config_setting(
-    name = "gcc_compiler",
-    flag_values = {
-        "@bazel_tools//tools/cpp:compiler": "gcc",
-    },
-    visibility = [":__subpackages__"],
-)
-
-config_setting(
     name = "mingw_unspecified_compiler",
     flag_values = {
         "@bazel_tools//tools/cpp:compiler": "mingw",
@@ -53,91 +45,10 @@
 )
 
 config_setting(
-    name = "msvc_compiler",
-    flag_values = {
-        "@bazel_tools//tools/cpp:compiler": "msvc-cl",
-    },
-    visibility = [":__subpackages__"],
-)
-
-config_setting(
-    name = "clang-cl_compiler",
-    flag_values = {
-        "@bazel_tools//tools/cpp:compiler": "clang-cl",
-    },
-    visibility = [":__subpackages__"],
-)
-
-config_setting(
-    name = "osx",
-    constraint_values = [
-        "@platforms//os:osx",
-    ],
-)
-
-config_setting(
-    name = "ios",
-    constraint_values = [
-        "@platforms//os:ios",
-    ],
-)
-
-config_setting(
-    name = "ppc",
-    values = {
-        "cpu": "ppc",
-    },
-    visibility = [":__subpackages__"],
-)
-
-config_setting(
-    name = "cpu_wasm",
-    values = {
-        "cpu": "wasm",
-    },
-    visibility = [":__subpackages__"],
-)
-
-config_setting(
-    name = "cpu_wasm32",
-    values = {
-        "cpu": "wasm32",
-    },
-    visibility = [":__subpackages__"],
-)
-
-config_setting(
-    name = "platforms_wasm32",
-    constraint_values = [
-        "@platforms//cpu:wasm32",
-    ],
-    visibility = [":__subpackages__"],
-)
-
-config_setting(
-    name = "platforms_wasm64",
-    constraint_values = [
-        "@platforms//cpu:wasm64",
-    ],
-    visibility = [":__subpackages__"],
-)
-
-selects.config_setting_group(
-    name = "wasm",
-    match_any = [
-        ":cpu_wasm",
-        ":cpu_wasm32",
-        ":platforms_wasm32",
-        ":platforms_wasm64",
-    ],
-    visibility = [":__subpackages__"],
-)
-
-config_setting(
     name = "fuchsia",
-    values = {
-        "cpu": "fuchsia",
-    },
+    constraint_values = [
+        "@platforms//os:fuchsia",
+    ],
     visibility = [":__subpackages__"],
 )
 
diff --git a/absl/abseil.podspec.gen.py b/absl/abseil.podspec.gen.py
index cbf7cb4..e1afa21 100755
--- a/absl/abseil.podspec.gen.py
+++ b/absl/abseil.podspec.gen.py
@@ -43,10 +43,11 @@
     'USE_HEADERMAP' => 'NO',
     'ALWAYS_SEARCH_USER_PATHS' => 'NO',
   }
-  s.ios.deployment_target = '9.0'
-  s.osx.deployment_target = '10.11'
-  s.tvos.deployment_target = '9.0'
-  s.watchos.deployment_target = '2.0'
+  s.ios.deployment_target = '12.0'
+  s.osx.deployment_target = '10.13'
+  s.tvos.deployment_target = '12.0'
+  s.watchos.deployment_target = '4.0'
+  s.visionos.deployment_target = '1.0'
   s.subspec 'xcprivacy' do |ss|
     ss.resource_bundles = {
       ss.module_name => 'PrivacyInfo.xcprivacy',
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index f20e729..0ec8b92 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -51,8 +51,8 @@
     deps = [
         ":algorithm",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -83,8 +83,9 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/memory",
+        "//absl/random",
         "//absl/types:span",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt
index 252b6b2..f3dd138 100644
--- a/absl/algorithm/CMakeLists.txt
+++ b/absl/algorithm/CMakeLists.txt
@@ -68,6 +68,7 @@
     absl::config
     absl::core_headers
     absl::memory
+    absl::random_random
     absl::span
     GTest::gmock_main
 )
diff --git a/absl/algorithm/algorithm.h b/absl/algorithm/algorithm.h
index 59aeed7..48f5950 100644
--- a/absl/algorithm/algorithm.h
+++ b/absl/algorithm/algorithm.h
@@ -53,8 +53,8 @@
 // n = (`last` - `first`) comparisons. A linear search over short containers
 // may be faster than a binary search, even when the container is sorted.
 template <typename InputIterator, typename EqualityComparable>
-bool linear_search(InputIterator first, InputIterator last,
-                   const EqualityComparable& value) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search(
+    InputIterator first, InputIterator last, const EqualityComparable& value) {
   return std::find(first, last, value) != last;
 }
 
diff --git a/absl/algorithm/algorithm_test.cc b/absl/algorithm/algorithm_test.cc
index e6ee469..1c1a307 100644
--- a/absl/algorithm/algorithm_test.cc
+++ b/absl/algorithm/algorithm_test.cc
@@ -14,11 +14,9 @@
 
 #include "absl/algorithm/algorithm.h"
 
-#include <algorithm>
-#include <list>
+#include <array>
 #include <vector>
 
-#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/config.h"
 
@@ -47,4 +45,16 @@
       absl::linear_search(const_container->begin(), const_container->end(), 4));
 }
 
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+    ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+
+TEST_F(LinearSearchTest, Constexpr) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::linear_search(kArray.begin(), kArray.end(), 3));
+  static_assert(!absl::linear_search(kArray.begin(), kArray.end(), 4));
+}
+
+#endif  // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
+        //  ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+
 }  // namespace
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 6bbe3b5..6f9c193 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -44,7 +44,6 @@
 #include <cassert>
 #include <iterator>
 #include <numeric>
-#include <random>
 #include <type_traits>
 #include <unordered_map>
 #include <unordered_set>
@@ -76,8 +75,8 @@
 // An MSVC bug involving template parameter substitution requires us to use
 // decltype() here instead of just std::pair.
 template <typename C1, typename C2>
-using ContainerIterPairType =
-    decltype(std::make_pair(ContainerIter<C1>(), ContainerIter<C2>()));
+using ContainerIterPairType = decltype(std::make_pair(
+    std::declval<ContainerIter<C1>>(), std::declval<ContainerIter<C2>>()));
 
 template <typename C>
 using ContainerDifferenceType = decltype(std::distance(
@@ -131,11 +130,14 @@
 //
 // Container-based version of absl::linear_search() for performing a linear
 // search within a container.
+//
+// For a generalization that uses a predicate, see absl::c_any_of().
 template <typename C, typename EqualityComparable>
-bool c_linear_search(const C& c, EqualityComparable&& value) {
-  return linear_search(container_algorithm_internal::c_begin(c),
-                       container_algorithm_internal::c_end(c),
-                       std::forward<EqualityComparable>(value));
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search(
+    const C& c, EqualityComparable&& value) {
+  return absl::linear_search(container_algorithm_internal::c_begin(c),
+                             container_algorithm_internal::c_end(c),
+                             std::forward<EqualityComparable>(value));
 }
 
 //------------------------------------------------------------------------------
@@ -163,7 +165,7 @@
 // Container-based version of the <algorithm> `std::all_of()` function to
 // test if all elements within a container satisfy a condition.
 template <typename C, typename Pred>
-bool c_all_of(const C& c, Pred&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) {
   return std::all_of(container_algorithm_internal::c_begin(c),
                      container_algorithm_internal::c_end(c),
                      std::forward<Pred>(pred));
@@ -174,7 +176,7 @@
 // Container-based version of the <algorithm> `std::any_of()` function to
 // test if any element in a container fulfills a condition.
 template <typename C, typename Pred>
-bool c_any_of(const C& c, Pred&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) {
   return std::any_of(container_algorithm_internal::c_begin(c),
                      container_algorithm_internal::c_end(c),
                      std::forward<Pred>(pred));
@@ -185,7 +187,7 @@
 // Container-based version of the <algorithm> `std::none_of()` function to
 // test if no elements in a container fulfill a condition.
 template <typename C, typename Pred>
-bool c_none_of(const C& c, Pred&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) {
   return std::none_of(container_algorithm_internal::c_begin(c),
                       container_algorithm_internal::c_end(c),
                       std::forward<Pred>(pred));
@@ -196,7 +198,8 @@
 // Container-based version of the <algorithm> `std::for_each()` function to
 // apply a function to a container's elements.
 template <typename C, typename Function>
-decay_t<Function> c_for_each(C&& c, Function&& f) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t<Function> c_for_each(C&& c,
+                                                                 Function&& f) {
   return std::for_each(container_algorithm_internal::c_begin(c),
                        container_algorithm_internal::c_end(c),
                        std::forward<Function>(f));
@@ -207,7 +210,9 @@
 // Container-based version of the <algorithm> `std::find()` function to find
 // the first element containing the passed value within a container value.
 template <typename C, typename T>
-container_algorithm_internal::ContainerIter<C> c_find(C& c, T&& value) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<C>
+    c_find(C& c, T&& value) {
   return std::find(container_algorithm_internal::c_begin(c),
                    container_algorithm_internal::c_end(c),
                    std::forward<T>(value));
@@ -218,7 +223,8 @@
 // Container-based version of the <algorithm> `std::ranges::contains()` C++23
 // function to search a container for a value.
 template <typename Sequence, typename T>
-bool c_contains(const Sequence& sequence, T&& value) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence,
+                                                    T&& value) {
   return absl::c_find(sequence, std::forward<T>(value)) !=
          container_algorithm_internal::c_end(sequence);
 }
@@ -228,7 +234,9 @@
 // Container-based version of the <algorithm> `std::find_if()` function to find
 // the first element in a container matching the given condition.
 template <typename C, typename Pred>
-container_algorithm_internal::ContainerIter<C> c_find_if(C& c, Pred&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<C>
+    c_find_if(C& c, Pred&& pred) {
   return std::find_if(container_algorithm_internal::c_begin(c),
                       container_algorithm_internal::c_end(c),
                       std::forward<Pred>(pred));
@@ -239,8 +247,9 @@
 // Container-based version of the <algorithm> `std::find_if_not()` function to
 // find the first element in a container not matching the given condition.
 template <typename C, typename Pred>
-container_algorithm_internal::ContainerIter<C> c_find_if_not(C& c,
-                                                             Pred&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<C>
+    c_find_if_not(C& c, Pred&& pred) {
   return std::find_if_not(container_algorithm_internal::c_begin(c),
                           container_algorithm_internal::c_end(c),
                           std::forward<Pred>(pred));
@@ -251,8 +260,9 @@
 // Container-based version of the <algorithm> `std::find_end()` function to
 // find the last subsequence within a container.
 template <typename Sequence1, typename Sequence2>
-container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
-    Sequence1& sequence, Sequence2& subsequence) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<Sequence1>
+    c_find_end(Sequence1& sequence, Sequence2& subsequence) {
   return std::find_end(container_algorithm_internal::c_begin(sequence),
                        container_algorithm_internal::c_end(sequence),
                        container_algorithm_internal::c_begin(subsequence),
@@ -262,8 +272,10 @@
 // Overload of c_find_end() for using a predicate evaluation other than `==` as
 // the function's test condition.
 template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
-container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
-    Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<Sequence1>
+    c_find_end(Sequence1& sequence, Sequence2& subsequence,
+               BinaryPredicate&& pred) {
   return std::find_end(container_algorithm_internal::c_begin(sequence),
                        container_algorithm_internal::c_end(sequence),
                        container_algorithm_internal::c_begin(subsequence),
@@ -277,8 +289,9 @@
 // find the first element within the container that is also within the options
 // container.
 template <typename C1, typename C2>
-container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
-                                                                C2& options) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<C1>
+    c_find_first_of(C1& container, const C2& options) {
   return std::find_first_of(container_algorithm_internal::c_begin(container),
                             container_algorithm_internal::c_end(container),
                             container_algorithm_internal::c_begin(options),
@@ -288,8 +301,9 @@
 // Overload of c_find_first_of() for using a predicate evaluation other than
 // `==` as the function's test condition.
 template <typename C1, typename C2, typename BinaryPredicate>
-container_algorithm_internal::ContainerIter<C1> c_find_first_of(
-    C1& container, C2& options, BinaryPredicate&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<C1>
+    c_find_first_of(C1& container, const C2& options, BinaryPredicate&& pred) {
   return std::find_first_of(container_algorithm_internal::c_begin(container),
                             container_algorithm_internal::c_end(container),
                             container_algorithm_internal::c_begin(options),
@@ -302,8 +316,9 @@
 // Container-based version of the <algorithm> `std::adjacent_find()` function to
 // find equal adjacent elements within a container.
 template <typename Sequence>
-container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
-    Sequence& sequence) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<Sequence>
+    c_adjacent_find(Sequence& sequence) {
   return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
                             container_algorithm_internal::c_end(sequence));
 }
@@ -311,8 +326,9 @@
 // Overload of c_adjacent_find() for using a predicate evaluation other than
 // `==` as the function's test condition.
 template <typename Sequence, typename BinaryPredicate>
-container_algorithm_internal::ContainerIter<Sequence> c_adjacent_find(
-    Sequence& sequence, BinaryPredicate&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<Sequence>
+    c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) {
   return std::adjacent_find(container_algorithm_internal::c_begin(sequence),
                             container_algorithm_internal::c_end(sequence),
                             std::forward<BinaryPredicate>(pred));
@@ -323,8 +339,9 @@
 // Container-based version of the <algorithm> `std::count()` function to count
 // values that match within a container.
 template <typename C, typename T>
-container_algorithm_internal::ContainerDifferenceType<const C> c_count(
-    const C& c, T&& value) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerDifferenceType<const C>
+    c_count(const C& c, T&& value) {
   return std::count(container_algorithm_internal::c_begin(c),
                     container_algorithm_internal::c_end(c),
                     std::forward<T>(value));
@@ -335,8 +352,9 @@
 // Container-based version of the <algorithm> `std::count_if()` function to
 // count values matching a condition within a container.
 template <typename C, typename Pred>
-container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
-    const C& c, Pred&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerDifferenceType<const C>
+    c_count_if(const C& c, Pred&& pred) {
   return std::count_if(container_algorithm_internal::c_begin(c),
                        container_algorithm_internal::c_end(c),
                        std::forward<Pred>(pred));
@@ -348,8 +366,9 @@
 // return the first element where two ordered containers differ. Applies `==` to
 // the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
 template <typename C1, typename C2>
-container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
-                                                                       C2& c2) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIterPairType<C1, C2>
+    c_mismatch(C1& c1, C2& c2) {
   return std::mismatch(container_algorithm_internal::c_begin(c1),
                        container_algorithm_internal::c_end(c1),
                        container_algorithm_internal::c_begin(c2),
@@ -360,8 +379,9 @@
 // the function's test condition. Applies `pred`to the first N elements of `c1`
 // and `c2`, where N = min(size(c1), size(c2)).
 template <typename C1, typename C2, typename BinaryPredicate>
-container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(
-    C1& c1, C2& c2, BinaryPredicate pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIterPairType<C1, C2>
+    c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
   return std::mismatch(container_algorithm_internal::c_begin(c1),
                        container_algorithm_internal::c_end(c1),
                        container_algorithm_internal::c_begin(c2),
@@ -373,7 +393,7 @@
 // Container-based version of the <algorithm> `std::equal()` function to
 // test whether two containers are equal.
 template <typename C1, typename C2>
-bool c_equal(const C1& c1, const C2& c2) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2) {
   return std::equal(container_algorithm_internal::c_begin(c1),
                     container_algorithm_internal::c_end(c1),
                     container_algorithm_internal::c_begin(c2),
@@ -383,7 +403,8 @@
 // Overload of c_equal() for using a predicate evaluation other than `==` as
 // the function's test condition.
 template <typename C1, typename C2, typename BinaryPredicate>
-bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2,
+                                                 BinaryPredicate&& pred) {
   return std::equal(container_algorithm_internal::c_begin(c1),
                     container_algorithm_internal::c_end(c1),
                     container_algorithm_internal::c_begin(c2),
@@ -396,7 +417,8 @@
 // Container-based version of the <algorithm> `std::is_permutation()` function
 // to test whether a container is a permutation of another.
 template <typename C1, typename C2>
-bool c_is_permutation(const C1& c1, const C2& c2) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(const C1& c1,
+                                                          const C2& c2) {
   return std::is_permutation(container_algorithm_internal::c_begin(c1),
                              container_algorithm_internal::c_end(c1),
                              container_algorithm_internal::c_begin(c2),
@@ -406,7 +428,8 @@
 // Overload of c_is_permutation() for using a predicate evaluation other than
 // `==` as the function's test condition.
 template <typename C1, typename C2, typename BinaryPredicate>
-bool c_is_permutation(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(
+    const C1& c1, const C2& c2, BinaryPredicate&& pred) {
   return std::is_permutation(container_algorithm_internal::c_begin(c1),
                              container_algorithm_internal::c_end(c1),
                              container_algorithm_internal::c_begin(c2),
@@ -419,8 +442,9 @@
 // Container-based version of the <algorithm> `std::search()` function to search
 // a container for a subsequence.
 template <typename Sequence1, typename Sequence2>
-container_algorithm_internal::ContainerIter<Sequence1> c_search(
-    Sequence1& sequence, Sequence2& subsequence) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<Sequence1>
+    c_search(Sequence1& sequence, Sequence2& subsequence) {
   return std::search(container_algorithm_internal::c_begin(sequence),
                      container_algorithm_internal::c_end(sequence),
                      container_algorithm_internal::c_begin(subsequence),
@@ -430,8 +454,10 @@
 // Overload of c_search() for using a predicate evaluation other than
 // `==` as the function's test condition.
 template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
-container_algorithm_internal::ContainerIter<Sequence1> c_search(
-    Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<Sequence1>
+    c_search(Sequence1& sequence, Sequence2& subsequence,
+             BinaryPredicate&& pred) {
   return std::search(container_algorithm_internal::c_begin(sequence),
                      container_algorithm_internal::c_end(sequence),
                      container_algorithm_internal::c_begin(subsequence),
@@ -444,7 +470,8 @@
 // Container-based version of the <algorithm> `std::ranges::contains_subrange()`
 // C++23 function to search a container for a subsequence.
 template <typename Sequence1, typename Sequence2>
-bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(
+    Sequence1& sequence, Sequence2& subsequence) {
   return absl::c_search(sequence, subsequence) !=
          container_algorithm_internal::c_end(sequence);
 }
@@ -452,8 +479,8 @@
 // Overload of c_contains_subrange() for using a predicate evaluation other than
 // `==` as the function's test condition.
 template <typename Sequence1, typename Sequence2, typename BinaryPredicate>
-bool c_contains_subrange(Sequence1& sequence, Sequence2& subsequence,
-                         BinaryPredicate&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange(
+    Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) {
   return absl::c_search(sequence, subsequence,
                         std::forward<BinaryPredicate>(pred)) !=
          container_algorithm_internal::c_end(sequence);
@@ -464,8 +491,9 @@
 // Container-based version of the <algorithm> `std::search_n()` function to
 // search a container for the first sequence of N elements.
 template <typename Sequence, typename Size, typename T>
-container_algorithm_internal::ContainerIter<Sequence> c_search_n(
-    Sequence& sequence, Size count, T&& value) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<Sequence>
+    c_search_n(Sequence& sequence, Size count, T&& value) {
   return std::search_n(container_algorithm_internal::c_begin(sequence),
                        container_algorithm_internal::c_end(sequence), count,
                        std::forward<T>(value));
@@ -475,8 +503,10 @@
 // `==` as the function's test condition.
 template <typename Sequence, typename Size, typename T,
           typename BinaryPredicate>
-container_algorithm_internal::ContainerIter<Sequence> c_search_n(
-    Sequence& sequence, Size count, T&& value, BinaryPredicate&& pred) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
+    container_algorithm_internal::ContainerIter<Sequence>
+    c_search_n(Sequence& sequence, Size count, T&& value,
+               BinaryPredicate&& pred) {
   return std::search_n(container_algorithm_internal::c_begin(sequence),
                        container_algorithm_internal::c_end(sequence), count,
                        std::forward<T>(value),
@@ -816,25 +846,9 @@
           typename UniformRandomBitGenerator>
 OutputIterator c_sample(const C& c, OutputIterator result, Distance n,
                         UniformRandomBitGenerator&& gen) {
-#if defined(__cpp_lib_sample) && __cpp_lib_sample >= 201603L
   return std::sample(container_algorithm_internal::c_begin(c),
                      container_algorithm_internal::c_end(c), result, n,
                      std::forward<UniformRandomBitGenerator>(gen));
-#else
-  // Fall back to a stable selection-sampling implementation.
-  auto first = container_algorithm_internal::c_begin(c);
-  Distance unsampled_elements = c_distance(c);
-  n = (std::min)(n, unsampled_elements);
-  for (; n != 0; ++first) {
-    Distance r =
-        std::uniform_int_distribution<Distance>(0, --unsampled_elements)(gen);
-    if (r < n) {
-      *result++ = *first;
-      --n;
-    }
-  }
-  return result;
-#endif
 }
 
 //------------------------------------------------------------------------------
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 5012224..cb06335 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -16,6 +16,7 @@
 
 #include <algorithm>
 #include <array>
+#include <cstddef>
 #include <functional>
 #include <initializer_list>
 #include <iterator>
@@ -35,6 +36,7 @@
 #include "absl/base/config.h"
 #include "absl/base/macros.h"
 #include "absl/memory/memory.h"
+#include "absl/random/random.h"
 #include "absl/types/span.h"
 
 namespace {
@@ -139,11 +141,13 @@
 TEST_F(NonMutatingTest, FindFirstOf) {
   absl::c_find_first_of(container_, sequence_);
   absl::c_find_first_of(sequence_, container_);
+  absl::c_find_first_of(sequence_, std::array<int, 2>{1, 2});
 }
 
 TEST_F(NonMutatingTest, FindFirstOfWithPredicate) {
   absl::c_find_first_of(container_, sequence_, BinPredicate);
   absl::c_find_first_of(sequence_, container_, BinPredicate);
+  absl::c_find_first_of(sequence_, std::array<int, 2>{1, 2}, BinPredicate);
 }
 
 TEST_F(NonMutatingTest, AdjacentFind) { absl::c_adjacent_find(sequence_); }
@@ -984,25 +988,16 @@
   EXPECT_THAT(actual, ElementsAre(3, 4, 1, 2, 5));
 }
 
-template <typename T>
-T RandomlySeededPrng() {
-  std::random_device rdev;
-  std::seed_seq::result_type data[T::state_size];
-  std::generate_n(data, T::state_size, std::ref(rdev));
-  std::seed_seq prng_seed(data, data + T::state_size);
-  return T(prng_seed);
-}
-
 TEST(MutatingTest, Shuffle) {
   std::vector<int> actual = {1, 2, 3, 4, 5};
-  absl::c_shuffle(actual, RandomlySeededPrng<std::mt19937_64>());
+  absl::c_shuffle(actual, absl::InsecureBitGen());
   EXPECT_THAT(actual, UnorderedElementsAre(1, 2, 3, 4, 5));
 }
 
 TEST(MutatingTest, Sample) {
   std::vector<int> actual;
   absl::c_sample(std::vector<int>{1, 2, 3, 4, 5}, std::back_inserter(actual), 3,
-                 RandomlySeededPrng<std::mt19937_64>());
+                 absl::InsecureBitGen());
   EXPECT_THAT(actual, IsSubsetOf({1, 2, 3, 4, 5}));
   EXPECT_THAT(actual, SizeIs(3));
 }
@@ -1164,6 +1159,7 @@
 
 #if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
     ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+
 TEST(ConstexprTest, Distance) {
   // Works at compile time with constexpr containers.
   static_assert(absl::c_distance(std::array<int, 3>()) == 3);
@@ -1203,8 +1199,216 @@
   static_assert(*kMinMaxPair.first == 3);
   static_assert(*kMinMaxPair.second == 1);
 }
-
 #endif  // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
         //  ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
 
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+    ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+
+TEST(ConstexprTest, LinearSearch) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_linear_search(kArray, 3));
+  static_assert(!absl::c_linear_search(kArray, 4));
+}
+
+TEST(ConstexprTest, AllOf) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(!absl::c_all_of(kArray, [](int x) { return x > 1; }));
+  static_assert(absl::c_all_of(kArray, [](int x) { return x > 0; }));
+}
+
+TEST(ConstexprTest, AnyOf) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_any_of(kArray, [](int x) { return x > 2; }));
+  static_assert(!absl::c_any_of(kArray, [](int x) { return x > 5; }));
+}
+
+TEST(ConstexprTest, NoneOf) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(!absl::c_none_of(kArray, [](int x) { return x > 2; }));
+  static_assert(absl::c_none_of(kArray, [](int x) { return x > 5; }));
+}
+
+TEST(ConstexprTest, ForEach) {
+  static constexpr std::array<int, 3> kArray = [] {
+    std::array<int, 3> array = {1, 2, 3};
+    absl::c_for_each(array, [](int& x) { x += 1; });
+    return array;
+  }();
+  static_assert(kArray == std::array{2, 3, 4});
+}
+
+TEST(ConstexprTest, Find) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_find(kArray, 1) == kArray.begin());
+  static_assert(absl::c_find(kArray, 4) == kArray.end());
+}
+
+TEST(ConstexprTest, Contains) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_contains(kArray, 1));
+  static_assert(!absl::c_contains(kArray, 4));
+}
+
+TEST(ConstexprTest, FindIf) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_find_if(kArray, [](int x) { return x > 2; }) ==
+                kArray.begin() + 2);
+  static_assert(absl::c_find_if(kArray, [](int x) { return x > 5; }) ==
+                kArray.end());
+}
+
+TEST(ConstexprTest, FindIfNot) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 1; }) ==
+                kArray.begin());
+  static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 0; }) ==
+                kArray.end());
+}
+
+TEST(ConstexprTest, FindEnd) {
+  static constexpr std::array<int, 5> kHaystack = {1, 2, 3, 2, 3};
+  static constexpr std::array<int, 2> kNeedle = {2, 3};
+  static_assert(absl::c_find_end(kHaystack, kNeedle) == kHaystack.begin() + 3);
+}
+
+TEST(ConstexprTest, FindFirstOf) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_find_first_of(kArray, kArray) == kArray.begin());
+}
+
+TEST(ConstexprTest, AdjacentFind) {
+  static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
+  static_assert(absl::c_adjacent_find(kArray) == kArray.begin() + 1);
+}
+
+TEST(ConstexprTest, AdjacentFindWithPredicate) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_adjacent_find(kArray, std::less<int>()) ==
+                kArray.begin());
+}
+
+TEST(ConstexprTest, Count) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_count(kArray, 1) == 1);
+  static_assert(absl::c_count(kArray, 2) == 1);
+  static_assert(absl::c_count(kArray, 3) == 1);
+  static_assert(absl::c_count(kArray, 4) == 0);
+}
+
+TEST(ConstexprTest, CountIf) {
+  static constexpr std::array<int, 3> kArray = {1, 2, 3};
+  static_assert(absl::c_count_if(kArray, [](int x) { return x > 0; }) == 3);
+  static_assert(absl::c_count_if(kArray, [](int x) { return x > 1; }) == 2);
+}
+
+TEST(ConstexprTest, Mismatch) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(absl::c_mismatch(kArray1, kArray2) ==
+                std::pair{kArray1.end(), kArray2.end()});
+  static_assert(absl::c_mismatch(kArray1, kArray3) ==
+                std::pair{kArray1.begin(), kArray3.begin()});
+}
+
+TEST(ConstexprTest, MismatchWithPredicate) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(absl::c_mismatch(kArray1, kArray2, std::not_equal_to<int>()) ==
+                std::pair{kArray1.begin(), kArray2.begin()});
+  static_assert(absl::c_mismatch(kArray1, kArray3, std::not_equal_to<int>()) ==
+                std::pair{kArray1.end(), kArray3.end()});
+}
+
+TEST(ConstexprTest, Equal) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(absl::c_equal(kArray1, kArray2));
+  static_assert(!absl::c_equal(kArray1, kArray3));
+}
+
+TEST(ConstexprTest, EqualWithPredicate) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(!absl::c_equal(kArray1, kArray2, std::not_equal_to<int>()));
+  static_assert(absl::c_equal(kArray1, kArray3, std::not_equal_to<int>()));
+}
+
+TEST(ConstexprTest, IsPermutation) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {3, 2, 1};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(absl::c_is_permutation(kArray1, kArray2));
+  static_assert(!absl::c_is_permutation(kArray1, kArray3));
+}
+
+TEST(ConstexprTest, IsPermutationWithPredicate) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {3, 2, 1};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(absl::c_is_permutation(kArray1, kArray2, std::equal_to<int>()));
+  static_assert(
+      !absl::c_is_permutation(kArray1, kArray3, std::equal_to<int>()));
+}
+
+TEST(ConstexprTest, Search) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(absl::c_search(kArray1, kArray2) == kArray1.begin());
+  static_assert(absl::c_search(kArray1, kArray3) == kArray1.end());
+}
+
+TEST(ConstexprTest, SearchWithPredicate) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(absl::c_search(kArray1, kArray2, std::not_equal_to<int>()) ==
+                kArray1.end());
+  static_assert(absl::c_search(kArray1, kArray3, std::not_equal_to<int>()) ==
+                kArray1.begin());
+}
+
+TEST(ConstexprTest, ContainsSubrange) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(absl::c_contains_subrange(kArray1, kArray2));
+  static_assert(!absl::c_contains_subrange(kArray1, kArray3));
+}
+
+TEST(ConstexprTest, ContainsSubrangeWithPredicate) {
+  static constexpr std::array<int, 3> kArray1 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray2 = {1, 2, 3};
+  static constexpr std::array<int, 3> kArray3 = {2, 3, 4};
+  static_assert(
+      !absl::c_contains_subrange(kArray1, kArray2, std::not_equal_to<>()));
+  static_assert(
+      absl::c_contains_subrange(kArray1, kArray3, std::not_equal_to<>()));
+}
+
+TEST(ConstexprTest, SearchN) {
+  static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
+  static_assert(absl::c_search_n(kArray, 1, 1) == kArray.begin());
+  static_assert(absl::c_search_n(kArray, 2, 2) == kArray.begin() + 1);
+  static_assert(absl::c_search_n(kArray, 1, 4) == kArray.end());
+}
+
+TEST(ConstexprTest, SearchNWithPredicate) {
+  static constexpr std::array<int, 4> kArray = {1, 2, 2, 3};
+  static_assert(absl::c_search_n(kArray, 1, 1, std::not_equal_to<int>()) ==
+                kArray.begin() + 1);
+  static_assert(absl::c_search_n(kArray, 2, 2, std::not_equal_to<int>()) ==
+                kArray.end());
+  static_assert(absl::c_search_n(kArray, 1, 4, std::not_equal_to<int>()) ==
+                kArray.begin());
+}
+
+#endif  // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
+        //  ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+
 }  // namespace
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 96503c9..ef97b4e 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -82,14 +82,13 @@
 
 cc_library(
     name = "nullability",
-    srcs = ["internal/nullability_impl.h"],
+    srcs = ["internal/nullability_deprecated.h"],
     hdrs = ["nullability.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":config",
         ":core_headers",
-        "//absl/meta:type_traits",
     ],
 )
 
@@ -207,9 +206,9 @@
         "//conditions:default": [],
     }),
     linkopts = select({
-        "//absl:msvc_compiler": [],
-        "//absl:clang-cl_compiler": [],
-        "//absl:wasm": [],
+        "@rules_cc//cc/compiler:msvc-cl": [],
+        "@rules_cc//cc/compiler:clang-cl": [],
+        "@rules_cc//cc/compiler:emscripten": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     visibility = [
@@ -230,8 +229,6 @@
     hdrs = [
         "internal/hide_ptr.h",
         "internal/identity.h",
-        "internal/inline_variable.h",
-        "internal/invoke.h",
         "internal/scheduling_mode.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
@@ -268,17 +265,17 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
-        "//absl:msvc_compiler": [
+        "@rules_cc//cc/compiler:msvc-cl": [
             "-DEFAULTLIB:advapi32.lib",
         ],
-        "//absl:clang-cl_compiler": [
+        "@rules_cc//cc/compiler:clang-cl": [
             "-DEFAULTLIB:advapi32.lib",
         ],
         "//absl:mingw_compiler": [
             "-DEFAULTLIB:advapi32.lib",
             "-ladvapi32",
         ],
-        "//absl:wasm": [],
+        "@rules_cc//cc/compiler:emscripten": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
@@ -319,8 +316,8 @@
         ":atomic_hook",
         ":atomic_hook_test_helper",
         ":core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -335,8 +332,23 @@
     deps = [
         ":base",
         ":core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "attributes_test",
+    srcs = [
+        "attributes_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":core_headers",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -375,8 +387,8 @@
     deps = [
         ":config",
         ":throw_delegate",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -389,8 +401,8 @@
     deps = [
         ":errno_saver",
         ":strerror",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -405,7 +417,7 @@
     ],
     deps = [
         ":config",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -432,7 +444,7 @@
         "//absl/meta:type_traits",
         "//absl/strings",
         "//absl/utility",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -444,41 +456,8 @@
     deps = [
         ":exception_safety_testing",
         "//absl/memory",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_test(
-    name = "inline_variable_test",
-    size = "small",
-    srcs = [
-        "inline_variable_test.cc",
-        "inline_variable_test_a.cc",
-        "inline_variable_test_b.cc",
-        "internal/inline_variable_testing.h",
-    ],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":base_internal",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_test(
-    name = "invoke_test",
-    size = "small",
-    srcs = ["invoke_test.cc"],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":base_internal",
-        "//absl/memory",
-        "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -496,7 +475,7 @@
         ":config",
         ":core_headers",
         "//absl/synchronization",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
     alwayslink = 1,
 )
@@ -516,8 +495,8 @@
         ":config",
         ":core_headers",
         "//absl/synchronization",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -536,7 +515,7 @@
         ":no_destructor",
         ":raw_logging_internal",
         "//absl/synchronization",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
     alwayslink = 1,
 )
@@ -561,6 +540,9 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl:__subpackages__",
+    ],
     deps = [
         ":base",
         ":config",
@@ -576,8 +558,8 @@
     deps = [
         ":config",
         ":endian",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -589,8 +571,8 @@
     deps = [
         ":config",
         "//absl/synchronization:thread_pool",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -603,8 +585,8 @@
         ":base",
         ":core_headers",
         "//absl/synchronization",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -617,8 +599,8 @@
         ":config",
         ":no_destructor",
         ":raw_logging_internal",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -633,7 +615,7 @@
     deps = [
         ":no_destructor",
         ":raw_logging_internal",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -643,8 +625,18 @@
     deps = [
         ":core_headers",
         ":nullability",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "nullability_default_nonnull_test",
+    srcs = ["nullability_default_nonnull_test.cc"],
+    deps = [
+        ":nullability",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -656,8 +648,8 @@
     deps = [
         ":raw_logging_internal",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -670,8 +662,8 @@
     deps = [
         ":base",
         "//absl/synchronization",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -704,13 +696,14 @@
         ":base",
         ":core_headers",
         "//absl/synchronization",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "thread_identity_benchmark",
+    testonly = True,
     srcs = ["internal/thread_identity_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -719,8 +712,7 @@
     deps = [
         ":base",
         "//absl/synchronization",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -747,8 +739,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":scoped_set_env",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -763,8 +755,8 @@
         "//absl/flags:flag_internal",
         "//absl/flags:marshalling",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -793,8 +785,8 @@
     deps = [
         ":strerror",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -808,18 +800,15 @@
     visibility = ["//visibility:private"],
     deps = [
         ":strerror",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
 cc_library(
     name = "fast_type_id",
-    hdrs = ["internal/fast_type_id.h"],
+    hdrs = ["fast_type_id.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl:__subpackages__",
-    ],
     deps = [
         ":config",
     ],
@@ -828,13 +817,14 @@
 cc_test(
     name = "fast_type_id_test",
     size = "small",
-    srcs = ["internal/fast_type_id_test.cc"],
+    srcs = ["fast_type_id_test.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":core_headers",
         ":fast_type_id",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -861,8 +851,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":prefetch",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -896,8 +886,8 @@
     deps = [
         ":config",
         ":poison",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -911,8 +901,8 @@
     deps = [
         ":core_headers",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -925,7 +915,81 @@
     deps = [
         ":core_headers",
         "//absl/types:optional",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "iterator_traits_internal",
+    hdrs = ["internal/iterator_traits.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        "//absl/meta:type_traits",
+    ],
+)
+
+cc_test(
+    name = "iterator_traits_test",
+    srcs = ["internal/iterator_traits_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":iterator_traits_internal",
+        ":iterator_traits_test_helper",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "tracing_internal",
+    srcs = ["internal/tracing.cc"],
+    hdrs = ["internal/tracing.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl:__subpackages__",
+    ],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+    ],
+)
+
+cc_library(
+    name = "iterator_traits_test_helper",
+    hdrs = ["internal/iterator_traits_test_helper.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [":config"],
+)
+
+cc_test(
+    name = "tracing_internal_weak_test",
+    srcs = ["internal/tracing_weak_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":tracing_internal",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "tracing_internal_strong_test",
+    srcs = ["internal/tracing_strong_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":core_headers",
+        ":tracing_internal",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 97994fc..23942c0 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -73,11 +73,10 @@
   HDRS
     "nullability.h"
   SRCS
-    "internal/nullability_impl.h"
+    "internal/nullability_deprecated.h"
   DEPS
     absl::config
     absl::core_headers
-    absl::type_traits
   COPTS
     ${ABSL_DEFAULT_COPTS}
 )
@@ -95,6 +94,18 @@
     GTest::gtest_main
 )
 
+absl_cc_test(
+  NAME
+    nullability_default_nonnull_test
+  SRCS
+    "nullability_default_nonnull_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::nullability
+    GTest::gtest_main
+)
+
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
@@ -204,8 +215,6 @@
   HDRS
     "internal/hide_ptr.h"
     "internal/identity.h"
-    "internal/inline_variable.h"
-    "internal/invoke.h"
     "internal/scheduling_mode.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
@@ -361,6 +370,19 @@
 
 absl_cc_test(
   NAME
+    attributes_test
+  SRCS
+    "attributes_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
     bit_cast_test
   SRCS
     "bit_cast_test.cc"
@@ -400,36 +422,6 @@
     GTest::gtest_main
 )
 
-absl_cc_test(
-  NAME
-    inline_variable_test
-  SRCS
-    "internal/inline_variable_testing.h"
-    "inline_variable_test.cc"
-    "inline_variable_test_a.cc"
-    "inline_variable_test_b.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::base_internal
-    GTest::gtest_main
-)
-
-absl_cc_test(
-  NAME
-    invoke_test
-  SRCS
-    "invoke_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::base_internal
-    absl::memory
-    absl::strings
-    GTest::gmock
-    GTest::gtest_main
-)
-
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
@@ -534,6 +526,7 @@
     absl::no_destructor
     absl::config
     absl::raw_logging_internal
+    GTest::gmock
     GTest::gtest_main
 )
 
@@ -675,12 +668,11 @@
     GTest::gtest_main
 )
 
-# Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
     fast_type_id
   HDRS
-    "internal/fast_type_id.h"
+    "fast_type_id.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
@@ -693,10 +685,11 @@
   NAME
     fast_type_id_test
   SRCS
-    "internal/fast_type_id_test.cc"
+    "fast_type_id_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::core_headers
     absl::fast_type_id
     GTest::gtest_main
 )
@@ -769,3 +762,83 @@
     absl::poison
     GTest::gtest_main
 )
+
+absl_cc_library(
+  NAME
+    tracing_internal
+  HDRS
+    "internal/tracing.h"
+  SRCS
+    "internal/tracing.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+)
+
+absl_cc_test(
+  NAME
+    tracing_internal_weak_test
+  SRCS
+    "internal/tracing_weak_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::base
+    absl::tracing_internal
+    GTest::gtest_main
+)
+
+absl_cc_test(
+  NAME
+    tracing_internal_strong_test
+  SRCS
+    "internal/tracing_strong_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::base
+    absl::tracing_internal
+    GTest::gtest_main
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    iterator_traits_internal
+  HDRS
+    "internal/iterator_traits.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::type_traits
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    iterator_traits_test
+  SRCS
+    "internal/iterator_traits_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::config
+    absl::iterator_traits_internal
+    absl::iterator_traits_test_helper_internal
+    GTest::gtest_main
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    iterator_traits_test_helper_internal
+  HDRS
+    "internal/iterator_traits_test_helper.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+  PUBLIC
+)
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index 5ea5ee3..d009f6d 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -31,6 +31,8 @@
 // `__has_attribute()` first. If the check fails, we check if we are on GCC and
 // assume the attribute exists on GCC (which is verified on GCC 4.7).
 
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
 #ifndef ABSL_BASE_ATTRIBUTES_H_
 #define ABSL_BASE_ATTRIBUTES_H_
 
@@ -133,12 +135,14 @@
 // Tags a function as weak for the purposes of compilation and linking.
 // Weak attributes did not work properly in LLVM's Windows backend before
 // 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
-// for further information.
+// for further information. Weak attributes do not work across DLL boundary.
 // The MinGW compiler doesn't complain about the weak attribute until the link
 // step, presumably because Windows doesn't use ELF binaries.
-#if (ABSL_HAVE_ATTRIBUTE(weak) ||                                         \
-     (defined(__GNUC__) && !defined(__clang__))) &&                       \
-    (!defined(_WIN32) || (defined(__clang__) && __clang_major__ >= 9)) && \
+#if (ABSL_HAVE_ATTRIBUTE(weak) ||                                 \
+     (defined(__GNUC__) && !defined(__clang__))) &&               \
+    (!defined(_WIN32) ||                                          \
+     (defined(__clang__) && __clang_major__ >= 9 &&               \
+      !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL))) && \
     !defined(__MINGW32__)
 #undef ABSL_ATTRIBUTE_WEAK
 #define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
@@ -335,9 +339,9 @@
 #ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE
 #ifdef _AIX
 // __attribute__((section(#name))) on AIX is achieved by using the `.csect`
-// psudo op which includes an additional integer as part of its syntax indcating
-// alignment. If data fall under different alignments then you might get a
-// compilation error indicating a `Section type conflict`.
+// pseudo op which includes an additional integer as part of its syntax
+// indicating alignment. If data fall under different alignments then you might
+// get a compilation error indicating a `Section type conflict`.
 #define ABSL_ATTRIBUTE_SECTION_VARIABLE(name)
 #else
 #define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name)))
@@ -549,12 +553,11 @@
 //
 // Prevents the compiler from complaining about variables that appear unused.
 //
-// For code or headers that are assured to only build with C++17 and up, prefer
-// just using the standard '[[maybe_unused]]' directly over this macro.
+// Deprecated: Use the standard C++17 `[[maybe_unused]` instead.
 //
 // Due to differences in positioning requirements between the old, compiler
-// specific __attribute__ syntax and the now standard [[maybe_unused]], this
-// macro does not attempt to take advantage of '[[maybe_unused]]'.
+// specific __attribute__ syntax and the now standard `[[maybe_unused]]`, this
+// macro does not attempt to take advantage of `[[maybe_unused]]`.
 #if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))
 #undef ABSL_ATTRIBUTE_UNUSED
 #define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__))
@@ -755,6 +758,76 @@
 #define ABSL_CONST_INIT
 #endif
 
+// ABSL_REQUIRE_EXPLICIT_INIT
+//
+// ABSL_REQUIRE_EXPLICIT_INIT is placed *after* the data members of an aggregate
+// type to indicate that the annotated member must be explicitly initialized by
+// the user whenever the aggregate is constructed. For example:
+//
+//   struct Coord {
+//     int x ABSL_REQUIRE_EXPLICIT_INIT;
+//     int y ABSL_REQUIRE_EXPLICIT_INIT;
+//   };
+//   Coord coord = {1};  // warning: field 'y' is not explicitly initialized
+//
+// Note that usage on C arrays is not supported in C++.
+// Use a struct (such as std::array) to wrap the array member instead.
+//
+// Avoid applying this attribute to the members of non-aggregate types.
+// The behavior within non-aggregates is unspecified and subject to change.
+//
+// Do NOT attempt to suppress or demote the error generated by this attribute.
+// Just like with a missing function argument, it is a hard error by design.
+//
+// See the upstream documentation for more details:
+// https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization
+#ifdef __cplusplus
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_explicit_initialization)
+// clang-format off
+#define ABSL_REQUIRE_EXPLICIT_INIT \
+  [[clang::require_explicit_initialization]] = \
+    AbslInternal_YouForgotToExplicitlyInitializeAField::v
+#else
+#define ABSL_REQUIRE_EXPLICIT_INIT \
+  = AbslInternal_YouForgotToExplicitlyInitializeAField::v
+#endif
+// clang-format on
+#else
+// clang-format off
+#if ABSL_HAVE_ATTRIBUTE(require_explicit_initialization)
+#define ABSL_REQUIRE_EXPLICIT_INIT \
+  __attribute__((require_explicit_initialization))
+#else
+#define ABSL_REQUIRE_EXPLICIT_INIT \
+  /* No portable fallback for C is available */
+#endif
+// clang-format on
+#endif
+
+#ifdef __cplusplus
+struct AbslInternal_YouForgotToExplicitlyInitializeAField {
+  // A portable version of [[clang::require_explicit_initialization]] that
+  // never builds, as a last resort for all toolchains.
+  // The error messages are poor, so we don't rely on this unless we have to.
+  template <class T>
+#if !defined(SWIG)
+  constexpr
+#endif
+  operator T() const /* NOLINT */ {
+    const void *volatile deliberately_volatile_ptr = nullptr;
+    // Infinite loop to prevent constexpr compilation
+    for (;;) {
+      // This assignment ensures the 'this' pointer is not optimized away, so
+      // that linking always fails.
+      deliberately_volatile_ptr = this;  // Deliberately not constexpr
+      (void)deliberately_volatile_ptr;
+    }
+  }
+  // This is deliberately left undefined to prevent linking
+  static AbslInternal_YouForgotToExplicitlyInitializeAField v;
+};
+#endif
+
 // ABSL_ATTRIBUTE_PURE_FUNCTION
 //
 // ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure"
@@ -827,30 +900,76 @@
 #define ABSL_ATTRIBUTE_LIFETIME_BOUND
 #endif
 
-// ABSL_INTERNAL_ATTRIBUTE_VIEW indicates that a type acts like a view i.e. a
-// raw (non-owning) pointer. This enables diagnoses similar to those enabled by
-// ABSL_ATTRIBUTE_LIFETIME_BOUND.
+// Internal attribute; name and documentation TBD.
 //
-// See the following links for details:
-// https://reviews.llvm.org/D64448
-// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
-#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer)
-#define ABSL_INTERNAL_ATTRIBUTE_VIEW [[gsl::Pointer]]
+// See the upstream documentation:
+// https://clang.llvm.org/docs/AttributeReference.html#lifetime_capture_by
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetime_capture_by)
+#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) \
+  [[clang::lifetime_capture_by(Owner)]]
 #else
-#define ABSL_INTERNAL_ATTRIBUTE_VIEW
+#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner)
 #endif
 
-// ABSL_INTERNAL_ATTRIBUTE_OWNER indicates that a type acts like a smart
-// (owning) pointer. This enables diagnoses similar to those enabled by
-// ABSL_ATTRIBUTE_LIFETIME_BOUND.
+// ABSL_ATTRIBUTE_VIEW indicates that a type is solely a "view" of data that it
+// points to, similarly to a span, string_view, or other non-owning reference
+// type.
+// This enables diagnosing certain lifetime issues similar to those enabled by
+// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:
+//
+//   struct ABSL_ATTRIBUTE_VIEW StringView {
+//     template<class R>
+//     StringView(const R&);
+//   };
+//
+//   StringView f(std::string s) {
+//     return s;  // warning: address of stack memory returned
+//   }
+//
+// We disable this on Clang versions < 13 because of the following
+// false-positive:
+//
+//   absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; }
 //
 // See the following links for details:
 // https://reviews.llvm.org/D64448
 // https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
-#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner)
-#define ABSL_INTERNAL_ATTRIBUTE_OWNER [[gsl::Owner]]
+#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && \
+    (!defined(__clang_major__) || __clang_major__ >= 13)
+#define ABSL_ATTRIBUTE_VIEW [[gsl::Pointer]]
 #else
-#define ABSL_INTERNAL_ATTRIBUTE_OWNER
+#define ABSL_ATTRIBUTE_VIEW
+#endif
+
+// ABSL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or
+// similar class that owns all the data that it points to.
+// This enables diagnosing certain lifetime issues similar to those enabled by
+// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:
+//
+//   struct ABSL_ATTRIBUTE_VIEW StringView {
+//     template<class R>
+//     StringView(const R&);
+//   };
+//
+//   struct ABSL_ATTRIBUTE_OWNER String {};
+//
+//   StringView f(String s) {
+//     return s;  // warning: address of stack memory returned
+//   }
+//
+// We disable this on Clang versions < 13 because of the following
+// false-positive:
+//
+//   absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; }
+//
+// See the following links for details:
+// https://reviews.llvm.org/D64448
+// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
+#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && \
+    (!defined(__clang_major__) || __clang_major__ >= 13)
+#define ABSL_ATTRIBUTE_OWNER [[gsl::Owner]]
+#else
+#define ABSL_ATTRIBUTE_OWNER
 #endif
 
 // ABSL_ATTRIBUTE_TRIVIAL_ABI
diff --git a/absl/base/attributes_test.cc b/absl/base/attributes_test.cc
new file mode 100644
index 0000000..5d213a4
--- /dev/null
+++ b/absl/base/attributes_test.cc
@@ -0,0 +1,43 @@
+// Copyright 2025 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/base/attributes.h"
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+
+namespace {
+
+TEST(Attributes, RequireExplicitInit) {
+  struct Agg {
+    int f1;
+    int f2 ABSL_REQUIRE_EXPLICIT_INIT;
+  };
+  Agg good1 ABSL_ATTRIBUTE_UNUSED = {1, 2};
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+  Agg good2 ABSL_ATTRIBUTE_UNUSED(1, 2);
+#endif
+  Agg good3 ABSL_ATTRIBUTE_UNUSED{1, 2};
+  Agg good4 ABSL_ATTRIBUTE_UNUSED = {1, 2};
+  Agg good5 ABSL_ATTRIBUTE_UNUSED = Agg{1, 2};
+  Agg good6[1] ABSL_ATTRIBUTE_UNUSED = {{1, 2}};
+  Agg good7[1] ABSL_ATTRIBUTE_UNUSED = {Agg{1, 2}};
+  union {
+    Agg agg;
+  } good8 ABSL_ATTRIBUTE_UNUSED = {{1, 2}};
+  constexpr Agg good9 ABSL_ATTRIBUTE_UNUSED = {1, 2};
+  constexpr Agg good10 ABSL_ATTRIBUTE_UNUSED{1, 2};
+}
+
+}  // namespace
diff --git a/absl/base/call_once.h b/absl/base/call_once.h
index 7b0e69c..7bfd916 100644
--- a/absl/base/call_once.h
+++ b/absl/base/call_once.h
@@ -28,10 +28,12 @@
 #include <algorithm>
 #include <atomic>
 #include <cstdint>
+#include <functional>
 #include <type_traits>
 #include <utility>
 
-#include "absl/base/internal/invoke.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/low_level_scheduling.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/scheduling_mode.h"
@@ -47,8 +49,8 @@
 class once_flag;
 
 namespace base_internal {
-absl::Nonnull<std::atomic<uint32_t>*> ControlWord(
-    absl::Nonnull<absl::once_flag*> flag);
+std::atomic<uint32_t>* absl_nonnull ControlWord(
+    absl::once_flag* absl_nonnull flag);
 }  // namespace base_internal
 
 // call_once()
@@ -91,8 +93,8 @@
   once_flag& operator=(const once_flag&) = delete;
 
  private:
-  friend absl::Nonnull<std::atomic<uint32_t>*> base_internal::ControlWord(
-      absl::Nonnull<once_flag*> flag);
+  friend std::atomic<uint32_t>* absl_nonnull base_internal::ControlWord(
+      once_flag* absl_nonnull flag);
   std::atomic<uint32_t> control_;
 };
 
@@ -106,7 +108,7 @@
 // Like call_once, but uses KERNEL_ONLY scheduling. Intended to be used to
 // initialize entities used by the scheduler implementation.
 template <typename Callable, typename... Args>
-void LowLevelCallOnce(absl::Nonnull<absl::once_flag*> flag, Callable&& fn,
+void LowLevelCallOnce(absl::once_flag* absl_nonnull flag, Callable&& fn,
                       Args&&... args);
 
 // Disables scheduling while on stack when scheduling mode is non-cooperative.
@@ -147,10 +149,10 @@
 };
 
 template <typename Callable, typename... Args>
-ABSL_ATTRIBUTE_NOINLINE void CallOnceImpl(
-    absl::Nonnull<std::atomic<uint32_t>*> control,
-    base_internal::SchedulingMode scheduling_mode, Callable&& fn,
-    Args&&... args) {
+    void
+    CallOnceImpl(std::atomic<uint32_t>* absl_nonnull control,
+                 base_internal::SchedulingMode scheduling_mode, Callable&& fn,
+                 Args&&... args) {
 #ifndef NDEBUG
   {
     uint32_t old_control = control->load(std::memory_order_relaxed);
@@ -179,8 +181,7 @@
                                        std::memory_order_relaxed) ||
       base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,
                                   scheduling_mode) == kOnceInit) {
-    base_internal::invoke(std::forward<Callable>(fn),
-                          std::forward<Args>(args)...);
+    std::invoke(std::forward<Callable>(fn), std::forward<Args>(args)...);
     old_control =
         control->exchange(base_internal::kOnceDone, std::memory_order_release);
     if (old_control == base_internal::kOnceWaiter) {
@@ -189,13 +190,13 @@
   }  // else *control is already kOnceDone
 }
 
-inline absl::Nonnull<std::atomic<uint32_t>*> ControlWord(
-    absl::Nonnull<once_flag*> flag) {
+inline std::atomic<uint32_t>* absl_nonnull ControlWord(
+    once_flag* absl_nonnull flag) {
   return &flag->control_;
 }
 
 template <typename Callable, typename... Args>
-void LowLevelCallOnce(absl::Nonnull<absl::once_flag*> flag, Callable&& fn,
+void LowLevelCallOnce(absl::once_flag* absl_nonnull flag, Callable&& fn,
                       Args&&... args) {
   std::atomic<uint32_t>* once = base_internal::ControlWord(flag);
   uint32_t s = once->load(std::memory_order_acquire);
@@ -209,7 +210,8 @@
 }  // namespace base_internal
 
 template <typename Callable, typename... Args>
-void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
+    void
+    call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
   std::atomic<uint32_t>* once = base_internal::ControlWord(&flag);
   uint32_t s = once->load(std::memory_order_acquire);
   if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {
diff --git a/absl/base/config.h b/absl/base/config.h
index 0b22167..8e5feb5 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -117,8 +117,8 @@
 //
 // LTS releases can be obtained from
 // https://github.com/abseil/abseil-cpp/releases.
-#define ABSL_LTS_RELEASE_VERSION 20240722
-#define ABSL_LTS_RELEASE_PATCH_LEVEL 0
+#define ABSL_LTS_RELEASE_VERSION 20250512
+#define ABSL_LTS_RELEASE_PATCH_LEVEL 1
 
 // Helper macro to convert a CPP variable to a string literal.
 #define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
@@ -274,15 +274,12 @@
 #define ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE 1
 #endif
 
-
 // ABSL_HAVE_THREAD_LOCAL
 //
-// DEPRECATED - `thread_local` is available on all supported platforms.
-// Checks whether C++11's `thread_local` storage duration specifier is
-// supported.
+// Checks whether the `thread_local` storage duration specifier is supported.
 #ifdef ABSL_HAVE_THREAD_LOCAL
 #error ABSL_HAVE_THREAD_LOCAL cannot be directly set
-#else
+#elif !defined(__XTENSA__) && !defined(ANDROID_DISABLE_TLS_FOR_LINKER)
 #define ABSL_HAVE_THREAD_LOCAL 1
 #endif
 
@@ -380,7 +377,7 @@
     defined(__asmjs__) || defined(__EMSCRIPTEN__) || defined(__Fuchsia__) || \
     defined(__sun) || defined(__myriad2__) || defined(__HAIKU__) ||          \
     defined(__OpenBSD__) || defined(__NetBSD__) || defined(__QNX__) ||       \
-    defined(__VXWORKS__) || defined(__hexagon__)
+    defined(__VXWORKS__) || defined(__hexagon__) || defined(__XTENSA__)
 #define ABSL_HAVE_MMAP 1
 #endif
 
@@ -469,6 +466,9 @@
 //
 // Checks the endianness of the platform.
 //
+// Prefer using `std::endian` in C++20, or `absl::endian` from
+// absl/numeric/bits.h prior to C++20.
+//
 // Notes: uses the built in endian macros provided by GCC (since 4.6) and
 // Clang (since 3.2); see
 // https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html.
@@ -520,54 +520,22 @@
 #define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
 #endif
 
-// ABSL_HAVE_STD_ANY
-//
-// Checks whether C++17 std::any is available.
-#ifdef ABSL_HAVE_STD_ANY
-#error "ABSL_HAVE_STD_ANY cannot be directly set."
-#elif defined(__cpp_lib_any) && __cpp_lib_any >= 201606L
+// Deprecated macros for polyfill detection.
 #define ABSL_HAVE_STD_ANY 1
-#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
-    ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
-    !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
-#define ABSL_HAVE_STD_ANY 1
-#endif
-
-// ABSL_HAVE_STD_OPTIONAL
-//
-// Checks whether C++17 std::optional is available.
-#ifdef ABSL_HAVE_STD_OPTIONAL
-#error "ABSL_HAVE_STD_OPTIONAL cannot be directly set."
-#elif defined(__cpp_lib_optional) && __cpp_lib_optional >= 202106L
+#define ABSL_USES_STD_ANY 1
 #define ABSL_HAVE_STD_OPTIONAL 1
-#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
-    ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
-    !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
-#define ABSL_HAVE_STD_OPTIONAL 1
-#endif
-
-// ABSL_HAVE_STD_VARIANT
-//
-// Checks whether C++17 std::variant is available.
-#ifdef ABSL_HAVE_STD_VARIANT
-#error "ABSL_HAVE_STD_VARIANT cannot be directly set."
-#elif defined(__cpp_lib_variant) && __cpp_lib_variant >= 201606L
+#define ABSL_USES_STD_OPTIONAL 1
 #define ABSL_HAVE_STD_VARIANT 1
-#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
-    ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L && \
-    !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
-#define ABSL_HAVE_STD_VARIANT 1
-#endif
+#define ABSL_USES_STD_VARIANT 1
 
 // ABSL_HAVE_STD_STRING_VIEW
 //
-// Checks whether C++17 std::string_view is available.
+// Deprecated: always defined to 1.
+// std::string_view was added in C++17, which means all versions of C++
+// supported by Abseil have it.
 #ifdef ABSL_HAVE_STD_STRING_VIEW
 #error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set."
-#elif defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606L
-#define ABSL_HAVE_STD_STRING_VIEW 1
-#elif defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
-    ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+#else
 #define ABSL_HAVE_STD_STRING_VIEW 1
 #endif
 
@@ -587,63 +555,15 @@
 #define ABSL_HAVE_STD_ORDERING 1
 #endif
 
-// ABSL_USES_STD_ANY
-//
-// Indicates whether absl::any is an alias for std::any.
-#if !defined(ABSL_OPTION_USE_STD_ANY)
-#error options.h is misconfigured.
-#elif ABSL_OPTION_USE_STD_ANY == 0 || \
-    (ABSL_OPTION_USE_STD_ANY == 2 && !defined(ABSL_HAVE_STD_ANY))
-#undef ABSL_USES_STD_ANY
-#elif ABSL_OPTION_USE_STD_ANY == 1 || \
-    (ABSL_OPTION_USE_STD_ANY == 2 && defined(ABSL_HAVE_STD_ANY))
-#define ABSL_USES_STD_ANY 1
-#else
-#error options.h is misconfigured.
-#endif
-
-// ABSL_USES_STD_OPTIONAL
-//
-// Indicates whether absl::optional is an alias for std::optional.
-#if !defined(ABSL_OPTION_USE_STD_OPTIONAL)
-#error options.h is misconfigured.
-#elif ABSL_OPTION_USE_STD_OPTIONAL == 0 || \
-    (ABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(ABSL_HAVE_STD_OPTIONAL))
-#undef ABSL_USES_STD_OPTIONAL
-#elif ABSL_OPTION_USE_STD_OPTIONAL == 1 || \
-    (ABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(ABSL_HAVE_STD_OPTIONAL))
-#define ABSL_USES_STD_OPTIONAL 1
-#else
-#error options.h is misconfigured.
-#endif
-
-// ABSL_USES_STD_VARIANT
-//
-// Indicates whether absl::variant is an alias for std::variant.
-#if !defined(ABSL_OPTION_USE_STD_VARIANT)
-#error options.h is misconfigured.
-#elif ABSL_OPTION_USE_STD_VARIANT == 0 || \
-    (ABSL_OPTION_USE_STD_VARIANT == 2 && !defined(ABSL_HAVE_STD_VARIANT))
-#undef ABSL_USES_STD_VARIANT
-#elif ABSL_OPTION_USE_STD_VARIANT == 1 || \
-    (ABSL_OPTION_USE_STD_VARIANT == 2 && defined(ABSL_HAVE_STD_VARIANT))
-#define ABSL_USES_STD_VARIANT 1
-#else
-#error options.h is misconfigured.
-#endif
-
 // ABSL_USES_STD_STRING_VIEW
 //
 // Indicates whether absl::string_view is an alias for std::string_view.
 #if !defined(ABSL_OPTION_USE_STD_STRING_VIEW)
 #error options.h is misconfigured.
-#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 || \
-    (ABSL_OPTION_USE_STD_STRING_VIEW == 2 &&  \
-     !defined(ABSL_HAVE_STD_STRING_VIEW))
+#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0
 #undef ABSL_USES_STD_STRING_VIEW
 #elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \
-    (ABSL_OPTION_USE_STD_STRING_VIEW == 2 &&  \
-     defined(ABSL_HAVE_STD_STRING_VIEW))
+    ABSL_OPTION_USE_STD_STRING_VIEW == 2
 #define ABSL_USES_STD_STRING_VIEW 1
 #else
 #error options.h is misconfigured.
@@ -665,14 +585,6 @@
 #error options.h is misconfigured.
 #endif
 
-// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION
-// SEH exception from emplace for variant<SomeStruct> when constructing the
-// struct can throw. This defeats some of variant_test and
-// variant_exception_safety_test.
-#if defined(_MSC_VER) && _MSC_VER >= 1700 && defined(_DEBUG)
-#define ABSL_INTERNAL_MSVC_2017_DBG_MODE
-#endif
-
 // ABSL_INTERNAL_MANGLED_NS
 // ABSL_INTERNAL_MANGLED_BACKREFERENCE
 //
@@ -813,36 +725,15 @@
 
 // ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
 //
-// Class template argument deduction is a language feature added in C++17.
+// Deprecated: always defined to 1.
+// Class template argument deduction is a language feature added in C++17,
+// which means all versions of C++ supported by Abseil have it.
 #ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
 #error "ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION cannot be directly set."
-#elif defined(__cpp_deduction_guides)
+#else
 #define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1
 #endif
 
-// ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-//
-// Prior to C++17, static constexpr variables defined in classes required a
-// separate definition outside of the class body, for example:
-//
-// class Foo {
-//   static constexpr int kBar = 0;
-// };
-// constexpr int Foo::kBar;
-//
-// In C++17, these variables defined in classes are considered inline variables,
-// and the extra declaration is redundant. Since some compilers warn on the
-// extra declarations, ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL can be used
-// conditionally ignore them:
-//
-// #ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-// constexpr int Foo::kBar;
-// #endif
-#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
-    ABSL_INTERNAL_CPLUSPLUS_LANG < 201703L
-#define ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL 1
-#endif
-
 // `ABSL_INTERNAL_HAS_RTTI` determines whether abseil is being compiled with
 // RTTI support.
 #ifdef ABSL_INTERNAL_HAS_RTTI
@@ -926,7 +817,7 @@
 // https://llvm.org/docs/CompileCudaWithLLVM.html#detecting-clang-vs-nvcc-from-code
 #ifdef ABSL_INTERNAL_HAVE_ARM_NEON
 #error ABSL_INTERNAL_HAVE_ARM_NEON cannot be directly set
-#elif defined(__ARM_NEON) && !defined(__CUDA_ARCH__)
+#elif defined(__ARM_NEON) && !(defined(__NVCC__) && defined(__CUDACC__))
 #define ABSL_INTERNAL_HAVE_ARM_NEON 1
 #endif
 
diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc
index bf5aa7c..55a6fe1 100644
--- a/absl/base/exception_safety_testing_test.cc
+++ b/absl/base/exception_safety_testing_test.cc
@@ -705,10 +705,6 @@
   static constexpr int kExceptionSentinel = 9999;
 };
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr int BasicGuaranteeWithExtraContracts::kExceptionSentinel;
-#endif
-
 TEST(ExceptionCheckTest, BasicGuaranteeWithExtraContracts) {
   auto tester_with_val =
       tester.WithInitialValue(BasicGuaranteeWithExtraContracts{});
diff --git a/absl/base/internal/fast_type_id.h b/absl/base/fast_type_id.h
similarity index 67%
rename from absl/base/internal/fast_type_id.h
rename to absl/base/fast_type_id.h
index a547b3a..ff25027 100644
--- a/absl/base/internal/fast_type_id.h
+++ b/absl/base/fast_type_id.h
@@ -1,4 +1,3 @@
-//
 // Copyright 2020 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,37 +13,33 @@
 // limitations under the License.
 //
 
-#ifndef ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
-#define ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
+#ifndef ABSL_BASE_FAST_TYPE_ID_H_
+#define ABSL_BASE_FAST_TYPE_ID_H_
 
 #include "absl/base/config.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
-namespace base_internal {
 
+namespace base_internal {
 template <typename Type>
 struct FastTypeTag {
-  constexpr static char dummy_var = 0;
+  static constexpr char kDummyVar = 0;
 };
+}  // namespace base_internal
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-template <typename Type>
-constexpr char FastTypeTag<Type>::dummy_var;
-#endif
-
-// FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
-// passed-in type. These are meant to be good match for keys into maps or
-// straight up comparisons.
+// The type returned by `absl::FastTypeId<T>()`.
 using FastTypeIdType = const void*;
 
+// `absl::FastTypeId<Type>()` evaluates at compile-time to a unique id for the
+// passed-in type. These are meant to be good match for keys into maps or
+// straight up comparisons.
 template <typename Type>
-constexpr inline FastTypeIdType FastTypeId() {
-  return &FastTypeTag<Type>::dummy_var;
+constexpr FastTypeIdType FastTypeId() {
+  return &base_internal::FastTypeTag<Type>::kDummyVar;
 }
 
-}  // namespace base_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
+#endif  // ABSL_BASE_FAST_TYPE_ID_H_
diff --git a/absl/base/fast_type_id_test.cc b/absl/base/fast_type_id_test.cc
new file mode 100644
index 0000000..3068e4b
--- /dev/null
+++ b/absl/base/fast_type_id_test.cc
@@ -0,0 +1,127 @@
+// Copyright 2020 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/base/fast_type_id.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <map>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/base/macros.h"
+
+namespace {
+
+// NOLINTBEGIN(runtime/int)
+#define PRIM_TYPES(A)   \
+  A(bool)               \
+  A(short)              \
+  A(unsigned short)     \
+  A(int)                \
+  A(unsigned int)       \
+  A(long)               \
+  A(unsigned long)      \
+  A(long long)          \
+  A(unsigned long long) \
+  A(float)              \
+  A(double)             \
+  A(long double)
+// NOLINTEND(runtime/int)
+
+TEST(FastTypeIdTest, PrimitiveTypes) {
+  // clang-format off
+  constexpr absl::FastTypeIdType kTypeIds[] = {
+#define A(T) absl::FastTypeId<T>(),
+    PRIM_TYPES(A)
+#undef A
+#define A(T) absl::FastTypeId<const T>(),
+    PRIM_TYPES(A)
+#undef A
+#define A(T) absl::FastTypeId<volatile T>(),
+    PRIM_TYPES(A)
+#undef A
+#define A(T) absl::FastTypeId<const volatile T>(),
+    PRIM_TYPES(A)
+#undef A
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < ABSL_ARRAYSIZE(kTypeIds); ++i) {
+    EXPECT_EQ(kTypeIds[i], kTypeIds[i]);
+    for (size_t j = 0; j < i; ++j) {
+      EXPECT_NE(kTypeIds[i], kTypeIds[j]);
+    }
+  }
+}
+
+#define FIXED_WIDTH_TYPES(A) \
+  A(int8_t)                  \
+  A(uint8_t)                 \
+  A(int16_t)                 \
+  A(uint16_t)                \
+  A(int32_t)                 \
+  A(uint32_t)                \
+  A(int64_t)                 \
+  A(uint64_t)
+
+TEST(FastTypeIdTest, FixedWidthTypes) {
+  // clang-format off
+  constexpr absl::FastTypeIdType kTypeIds[] = {
+#define A(T) absl::FastTypeId<T>(),
+    FIXED_WIDTH_TYPES(A)
+#undef A
+#define A(T) absl::FastTypeId<const T>(),
+    FIXED_WIDTH_TYPES(A)
+#undef A
+#define A(T) absl::FastTypeId<volatile T>(),
+    FIXED_WIDTH_TYPES(A)
+#undef A
+#define A(T) absl::FastTypeId<const volatile T>(),
+    FIXED_WIDTH_TYPES(A)
+#undef A
+  };
+  // clang-format on
+
+  for (size_t i = 0; i < ABSL_ARRAYSIZE(kTypeIds); ++i) {
+    EXPECT_EQ(kTypeIds[i], kTypeIds[i]);
+    for (size_t j = 0; j < i; ++j) {
+      EXPECT_NE(kTypeIds[i], kTypeIds[j]);
+    }
+  }
+}
+
+TEST(FastTypeIdTest, AliasTypes) {
+  using int_alias = int;
+  EXPECT_EQ(absl::FastTypeId<int_alias>(), absl::FastTypeId<int>());
+}
+
+TEST(FastTypeIdTest, TemplateSpecializations) {
+  EXPECT_NE(absl::FastTypeId<std::vector<int>>(),
+            absl::FastTypeId<std::vector<long>>());  // NOLINT(runtime/int)
+
+  EXPECT_NE((absl::FastTypeId<std::map<int, float>>()),
+            (absl::FastTypeId<std::map<int, double>>()));
+}
+
+struct Base {};
+struct Derived : Base {};
+struct PDerived : private Base {};
+
+TEST(FastTypeIdTest, Inheritance) {
+  EXPECT_NE(absl::FastTypeId<Base>(), absl::FastTypeId<Derived>());
+  EXPECT_NE(absl::FastTypeId<Base>(), absl::FastTypeId<PDerived>());
+}
+
+}  // namespace
diff --git a/absl/base/inline_variable_test.cc b/absl/base/inline_variable_test.cc
deleted file mode 100644
index 37a40e1..0000000
--- a/absl/base/inline_variable_test.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2017 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 <type_traits>
-
-#include "absl/base/internal/inline_variable.h"
-#include "absl/base/internal/inline_variable_testing.h"
-
-#include "gtest/gtest.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace inline_variable_testing_internal {
-namespace {
-
-TEST(InlineVariableTest, Constexpr) {
-  static_assert(inline_variable_foo.value == 5, "");
-  static_assert(other_inline_variable_foo.value == 5, "");
-  static_assert(inline_variable_int == 5, "");
-  static_assert(other_inline_variable_int == 5, "");
-}
-
-TEST(InlineVariableTest, DefaultConstructedIdentityEquality) {
-  EXPECT_EQ(get_foo_a().value, 5);
-  EXPECT_EQ(get_foo_b().value, 5);
-  EXPECT_EQ(&get_foo_a(), &get_foo_b());
-}
-
-TEST(InlineVariableTest, DefaultConstructedIdentityInequality) {
-  EXPECT_NE(&inline_variable_foo, &other_inline_variable_foo);
-}
-
-TEST(InlineVariableTest, InitializedIdentityEquality) {
-  EXPECT_EQ(get_int_a(), 5);
-  EXPECT_EQ(get_int_b(), 5);
-  EXPECT_EQ(&get_int_a(), &get_int_b());
-}
-
-TEST(InlineVariableTest, InitializedIdentityInequality) {
-  EXPECT_NE(&inline_variable_int, &other_inline_variable_int);
-}
-
-TEST(InlineVariableTest, FunPtrType) {
-  static_assert(
-      std::is_same<void(*)(),
-                   std::decay<decltype(inline_variable_fun_ptr)>::type>::value,
-      "");
-}
-
-}  // namespace
-}  // namespace inline_variable_testing_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/base/inline_variable_test_a.cc b/absl/base/inline_variable_test_a.cc
deleted file mode 100644
index f96a58d..0000000
--- a/absl/base/inline_variable_test_a.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 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/base/internal/inline_variable_testing.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace inline_variable_testing_internal {
-
-const Foo& get_foo_a() { return inline_variable_foo; }
-
-const int& get_int_a() { return inline_variable_int; }
-
-}  // namespace inline_variable_testing_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/base/inline_variable_test_b.cc b/absl/base/inline_variable_test_b.cc
deleted file mode 100644
index 038adc3..0000000
--- a/absl/base/inline_variable_test_b.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2017 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/base/internal/inline_variable_testing.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace inline_variable_testing_internal {
-
-const Foo& get_foo_b() { return inline_variable_foo; }
-
-const int& get_int_b() { return inline_variable_int; }
-
-}  // namespace inline_variable_testing_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/base/internal/cycleclock.cc b/absl/base/internal/cycleclock.cc
index 902e3f5..9946601 100644
--- a/absl/base/internal/cycleclock.cc
+++ b/absl/base/internal/cycleclock.cc
@@ -35,11 +35,6 @@
 
 #if ABSL_USE_UNSCALED_CYCLECLOCK
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr int32_t CycleClock::kShift;
-constexpr double CycleClock::kFrequencyScale;
-#endif
-
 ABSL_CONST_INIT std::atomic<CycleClockSourceFunc>
     CycleClock::cycle_clock_source_{nullptr};
 
diff --git a/absl/base/internal/cycleclock_config.h b/absl/base/internal/cycleclock_config.h
index 191112b..50a4697 100644
--- a/absl/base/internal/cycleclock_config.h
+++ b/absl/base/internal/cycleclock_config.h
@@ -18,7 +18,6 @@
 #include <cstdint>
 
 #include "absl/base/config.h"
-#include "absl/base/internal/inline_variable.h"
 #include "absl/base/internal/unscaledcycleclock_config.h"
 
 namespace absl {
@@ -31,22 +30,23 @@
 // Not debug mode and the UnscaledCycleClock frequency is the CPU
 // frequency.  Scale the CycleClock to prevent overflow if someone
 // tries to represent the time as cycles since the Unix epoch.
-ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 1);
+inline constexpr int32_t kCycleClockShift = 1;
 #else
 // Not debug mode and the UnscaledCycleClock isn't operating at the
 // raw CPU frequency. There is no need to do any scaling, so don't
 // needlessly sacrifice precision.
-ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 0);
+inline constexpr int32_t kCycleClockShift = 0;
 #endif
 #else   // NDEBUG
 // In debug mode use a different shift to discourage depending on a
 // particular shift value.
-ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 2);
+inline constexpr int32_t kCycleClockShift = 2;
 #endif  // NDEBUG
 
-ABSL_INTERNAL_INLINE_CONSTEXPR(double, kCycleClockFrequencyScale,
-                               1.0 / (1 << kCycleClockShift));
-#endif  //  ABSL_USE_UNSCALED_CYCLECLOC
+inline constexpr double kCycleClockFrequencyScale =
+    1.0 / (1 << kCycleClockShift);
+
+#endif  // ABSL_USE_UNSCALED_CYCLECLOCK
 
 }  // namespace base_internal
 ABSL_NAMESPACE_END
diff --git a/absl/base/internal/endian.h b/absl/base/internal/endian.h
index 943f3d9..fb38f60 100644
--- a/absl/base/internal/endian.h
+++ b/absl/base/internal/endian.h
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
+// This file is for Abseil internal use only.
+// See //absl/numeric/bits.h for supported functions related to endian-ness.
 
 #ifndef ABSL_BASE_INTERNAL_ENDIAN_H_
 #define ABSL_BASE_INTERNAL_ENDIAN_H_
@@ -28,44 +30,38 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-inline uint64_t gbswap_64(uint64_t host_int) {
+constexpr uint64_t gbswap_64(uint64_t x) {
 #if ABSL_HAVE_BUILTIN(__builtin_bswap64) || defined(__GNUC__)
-  return __builtin_bswap64(host_int);
-#elif defined(_MSC_VER)
-  return _byteswap_uint64(host_int);
+  return __builtin_bswap64(x);
 #else
-  return (((host_int & uint64_t{0xFF}) << 56) |
-          ((host_int & uint64_t{0xFF00}) << 40) |
-          ((host_int & uint64_t{0xFF0000}) << 24) |
-          ((host_int & uint64_t{0xFF000000}) << 8) |
-          ((host_int & uint64_t{0xFF00000000}) >> 8) |
-          ((host_int & uint64_t{0xFF0000000000}) >> 24) |
-          ((host_int & uint64_t{0xFF000000000000}) >> 40) |
-          ((host_int & uint64_t{0xFF00000000000000}) >> 56));
+  return (((x & uint64_t{0xFF}) << 56) |
+          ((x & uint64_t{0xFF00}) << 40) |
+          ((x & uint64_t{0xFF0000}) << 24) |
+          ((x & uint64_t{0xFF000000}) << 8) |
+          ((x & uint64_t{0xFF00000000}) >> 8) |
+          ((x & uint64_t{0xFF0000000000}) >> 24) |
+          ((x & uint64_t{0xFF000000000000}) >> 40) |
+          ((x & uint64_t{0xFF00000000000000}) >> 56));
 #endif
 }
 
-inline uint32_t gbswap_32(uint32_t host_int) {
+constexpr uint32_t gbswap_32(uint32_t x) {
 #if ABSL_HAVE_BUILTIN(__builtin_bswap32) || defined(__GNUC__)
-  return __builtin_bswap32(host_int);
-#elif defined(_MSC_VER)
-  return _byteswap_ulong(host_int);
+  return __builtin_bswap32(x);
 #else
-  return (((host_int & uint32_t{0xFF}) << 24) |
-          ((host_int & uint32_t{0xFF00}) << 8) |
-          ((host_int & uint32_t{0xFF0000}) >> 8) |
-          ((host_int & uint32_t{0xFF000000}) >> 24));
+  return (((x & uint32_t{0xFF}) << 24) |
+          ((x & uint32_t{0xFF00}) << 8) |
+          ((x & uint32_t{0xFF0000}) >> 8) |
+          ((x & uint32_t{0xFF000000}) >> 24));
 #endif
 }
 
-inline uint16_t gbswap_16(uint16_t host_int) {
+constexpr uint16_t gbswap_16(uint16_t x) {
 #if ABSL_HAVE_BUILTIN(__builtin_bswap16) || defined(__GNUC__)
-  return __builtin_bswap16(host_int);
-#elif defined(_MSC_VER)
-  return _byteswap_ushort(host_int);
+  return __builtin_bswap16(x);
 #else
-  return (((host_int & uint16_t{0xFF}) << 8) |
-          ((host_int & uint16_t{0xFF00}) >> 8));
+  return (((x & uint16_t{0xFF}) << 8) |
+          ((x & uint16_t{0xFF00}) >> 8));
 #endif
 }
 
@@ -161,27 +157,27 @@
 }
 
 // Functions to do unaligned loads and stores in little-endian order.
-inline uint16_t Load16(absl::Nonnull<const void *> p) {
+inline uint16_t Load16(const void* absl_nonnull p) {
   return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
 }
 
-inline void Store16(absl::Nonnull<void *> p, uint16_t v) {
+inline void Store16(void* absl_nonnull p, uint16_t v) {
   ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
 }
 
-inline uint32_t Load32(absl::Nonnull<const void *> p) {
+inline uint32_t Load32(const void* absl_nonnull p) {
   return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
 }
 
-inline void Store32(absl::Nonnull<void *> p, uint32_t v) {
+inline void Store32(void* absl_nonnull p, uint32_t v) {
   ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
 }
 
-inline uint64_t Load64(absl::Nonnull<const void *> p) {
+inline uint64_t Load64(const void* absl_nonnull p) {
   return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
 }
 
-inline void Store64(absl::Nonnull<void *> p, uint64_t v) {
+inline void Store64(void* absl_nonnull p, uint64_t v) {
   ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
 }
 
@@ -251,27 +247,27 @@
 }
 
 // Functions to do unaligned loads and stores in big-endian order.
-inline uint16_t Load16(absl::Nonnull<const void *> p) {
+inline uint16_t Load16(const void* absl_nonnull p) {
   return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
 }
 
-inline void Store16(absl::Nonnull<void *> p, uint16_t v) {
+inline void Store16(void* absl_nonnull p, uint16_t v) {
   ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
 }
 
-inline uint32_t Load32(absl::Nonnull<const void *> p) {
+inline uint32_t Load32(const void* absl_nonnull p) {
   return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
 }
 
-inline void Store32(absl::Nonnull<void *>p, uint32_t v) {
+inline void Store32(void* absl_nonnull p, uint32_t v) {
   ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
 }
 
-inline uint64_t Load64(absl::Nonnull<const void *> p) {
+inline uint64_t Load64(const void* absl_nonnull p) {
   return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
 }
 
-inline void Store64(absl::Nonnull<void *> p, uint64_t v) {
+inline void Store64(void* absl_nonnull p, uint64_t v) {
   ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
 }
 
diff --git a/absl/base/internal/fast_type_id_test.cc b/absl/base/internal/fast_type_id_test.cc
deleted file mode 100644
index 16f3c14..0000000
--- a/absl/base/internal/fast_type_id_test.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// Copyright 2020 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/base/internal/fast_type_id.h"
-
-#include <cstdint>
-#include <map>
-#include <vector>
-
-#include "gtest/gtest.h"
-
-namespace {
-namespace bi = absl::base_internal;
-
-// NOLINTNEXTLINE
-#define PRIM_TYPES(A)   \
-  A(bool)               \
-  A(short)              \
-  A(unsigned short)     \
-  A(int)                \
-  A(unsigned int)       \
-  A(long)               \
-  A(unsigned long)      \
-  A(long long)          \
-  A(unsigned long long) \
-  A(float)              \
-  A(double)             \
-  A(long double)
-
-TEST(FastTypeIdTest, PrimitiveTypes) {
-  bi::FastTypeIdType type_ids[] = {
-#define A(T) bi::FastTypeId<T>(),
-    PRIM_TYPES(A)
-#undef A
-#define A(T) bi::FastTypeId<const T>(),
-    PRIM_TYPES(A)
-#undef A
-#define A(T) bi::FastTypeId<volatile T>(),
-    PRIM_TYPES(A)
-#undef A
-#define A(T) bi::FastTypeId<const volatile T>(),
-    PRIM_TYPES(A)
-#undef A
-  };
-  size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
-
-  for (int i = 0; i < total_type_ids; ++i) {
-    EXPECT_EQ(type_ids[i], type_ids[i]);
-    for (int j = 0; j < i; ++j) {
-      EXPECT_NE(type_ids[i], type_ids[j]);
-    }
-  }
-}
-
-#define FIXED_WIDTH_TYPES(A) \
-  A(int8_t)                  \
-  A(uint8_t)                 \
-  A(int16_t)                 \
-  A(uint16_t)                \
-  A(int32_t)                 \
-  A(uint32_t)                \
-  A(int64_t)                 \
-  A(uint64_t)
-
-TEST(FastTypeIdTest, FixedWidthTypes) {
-  bi::FastTypeIdType type_ids[] = {
-#define A(T) bi::FastTypeId<T>(),
-    FIXED_WIDTH_TYPES(A)
-#undef A
-#define A(T) bi::FastTypeId<const T>(),
-    FIXED_WIDTH_TYPES(A)
-#undef A
-#define A(T) bi::FastTypeId<volatile T>(),
-    FIXED_WIDTH_TYPES(A)
-#undef A
-#define A(T) bi::FastTypeId<const volatile T>(),
-    FIXED_WIDTH_TYPES(A)
-#undef A
-  };
-  size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
-
-  for (int i = 0; i < total_type_ids; ++i) {
-    EXPECT_EQ(type_ids[i], type_ids[i]);
-    for (int j = 0; j < i; ++j) {
-      EXPECT_NE(type_ids[i], type_ids[j]);
-    }
-  }
-}
-
-TEST(FastTypeIdTest, AliasTypes) {
-  using int_alias = int;
-  EXPECT_EQ(bi::FastTypeId<int_alias>(), bi::FastTypeId<int>());
-}
-
-TEST(FastTypeIdTest, TemplateSpecializations) {
-  EXPECT_NE(bi::FastTypeId<std::vector<int>>(),
-            bi::FastTypeId<std::vector<long>>());
-
-  EXPECT_NE((bi::FastTypeId<std::map<int, float>>()),
-            (bi::FastTypeId<std::map<int, double>>()));
-}
-
-struct Base {};
-struct Derived : Base {};
-struct PDerived : private Base {};
-
-TEST(FastTypeIdTest, Inheritance) {
-  EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<Derived>());
-  EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<PDerived>());
-}
-
-}  // namespace
diff --git a/absl/base/internal/inline_variable.h b/absl/base/internal/inline_variable.h
deleted file mode 100644
index 09daf0f..0000000
--- a/absl/base/internal/inline_variable.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2017 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_BASE_INTERNAL_INLINE_VARIABLE_H_
-#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
-
-#include <type_traits>
-
-#include "absl/base/internal/identity.h"
-
-// File:
-//   This file define a macro that allows the creation of or emulation of C++17
-//   inline variables based on whether or not the feature is supported.
-
-////////////////////////////////////////////////////////////////////////////////
-// Macro: ABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init)
-//
-// Description:
-//   Expands to the equivalent of an inline constexpr instance of the specified
-//   `type` and `name`, initialized to the value `init`. If the compiler being
-//   used is detected as supporting actual inline variables as a language
-//   feature, then the macro expands to an actual inline variable definition.
-//
-// Requires:
-//   `type` is a type that is usable in an extern variable declaration.
-//
-// Requires: `name` is a valid identifier
-//
-// Requires:
-//   `init` is an expression that can be used in the following definition:
-//     constexpr type name = init;
-//
-// Usage:
-//
-//   // Equivalent to: `inline constexpr size_t variant_npos = -1;`
-//   ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
-//
-// Differences in implementation:
-//   For a direct, language-level inline variable, decltype(name) will be the
-//   type that was specified along with const qualification, whereas for
-//   emulated inline variables, decltype(name) may be different (in practice
-//   it will likely be a reference type).
-////////////////////////////////////////////////////////////////////////////////
-
-#ifdef __cpp_inline_variables
-
-// Clang's -Wmissing-variable-declarations option erroneously warned that
-// inline constexpr objects need to be pre-declared. This has now been fixed,
-// but we will need to support this workaround for people building with older
-// versions of clang.
-//
-// Bug: https://bugs.llvm.org/show_bug.cgi?id=35862
-//
-// Note:
-//   type_identity_t is used here so that the const and name are in the
-//   appropriate place for pointer types, reference types, function pointer
-//   types, etc..
-#if defined(__clang__)
-#define ABSL_INTERNAL_EXTERN_DECL(type, name) \
-  extern const ::absl::internal::type_identity_t<type> name;
-#else  // Otherwise, just define the macro to do nothing.
-#define ABSL_INTERNAL_EXTERN_DECL(type, name)
-#endif  // defined(__clang__)
-
-// See above comment at top of file for details.
-#define ABSL_INTERNAL_INLINE_CONSTEXPR(type, name, init) \
-  ABSL_INTERNAL_EXTERN_DECL(type, name)                  \
-  inline constexpr ::absl::internal::type_identity_t<type> name = init
-
-#else
-
-// See above comment at top of file for details.
-//
-// Note:
-//   type_identity_t is used here so that the const and name are in the
-//   appropriate place for pointer types, reference types, function pointer
-//   types, etc..
-#define ABSL_INTERNAL_INLINE_CONSTEXPR(var_type, name, init)                 \
-  template <class /*AbslInternalDummy*/ = void>                              \
-  struct AbslInternalInlineVariableHolder##name {                            \
-    static constexpr ::absl::internal::type_identity_t<var_type> kInstance = \
-        init;                                                                \
-  };                                                                         \
-                                                                             \
-  template <class AbslInternalDummy>                                         \
-  constexpr ::absl::internal::type_identity_t<var_type>                      \
-      AbslInternalInlineVariableHolder##name<AbslInternalDummy>::kInstance;  \
-                                                                             \
-  static constexpr const ::absl::internal::type_identity_t<var_type>&        \
-      name = /* NOLINT */                                                    \
-      AbslInternalInlineVariableHolder##name<>::kInstance;                   \
-  static_assert(sizeof(void (*)(decltype(name))) != 0,                       \
-                "Silence unused variable warnings.")
-
-#endif  // __cpp_inline_variables
-
-#endif  // ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
diff --git a/absl/base/internal/inline_variable_testing.h b/absl/base/internal/inline_variable_testing.h
deleted file mode 100644
index f3c8145..0000000
--- a/absl/base/internal/inline_variable_testing.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017 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_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
-#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
-
-#include "absl/base/internal/inline_variable.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace inline_variable_testing_internal {
-
-struct Foo {
-  int value = 5;
-};
-
-ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, inline_variable_foo, {});
-ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, other_inline_variable_foo, {});
-
-ABSL_INTERNAL_INLINE_CONSTEXPR(int, inline_variable_int, 5);
-ABSL_INTERNAL_INLINE_CONSTEXPR(int, other_inline_variable_int, 5);
-
-ABSL_INTERNAL_INLINE_CONSTEXPR(void(*)(), inline_variable_fun_ptr, nullptr);
-
-const Foo& get_foo_a();
-const Foo& get_foo_b();
-
-const int& get_int_a();
-const int& get_int_b();
-
-}  // namespace inline_variable_testing_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
diff --git a/absl/base/internal/invoke.h b/absl/base/internal/invoke.h
deleted file mode 100644
index 643c2a4..0000000
--- a/absl/base/internal/invoke.h
+++ /dev/null
@@ -1,241 +0,0 @@
-// Copyright 2017 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::base_internal::invoke(f, args...) is an implementation of
-// INVOKE(f, args...) from section [func.require] of the C++ standard.
-// When compiled as C++17 and later versions, it is implemented as an alias of
-// std::invoke.
-//
-// [func.require]
-// Define INVOKE (f, t1, t2, ..., tN) as follows:
-// 1. (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
-//    and t1 is an object of type T or a reference to an object of type T or a
-//    reference to an object of a type derived from T;
-// 2. ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
-//    class T and t1 is not one of the types described in the previous item;
-// 3. t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
-//    an object of type T or a reference to an object of type T or a reference
-//    to an object of a type derived from T;
-// 4. (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
-//    is not one of the types described in the previous item;
-// 5. f(t1, t2, ..., tN) in all other cases.
-//
-// The implementation is SFINAE-friendly: substitution failure within invoke()
-// isn't an error.
-
-#ifndef ABSL_BASE_INTERNAL_INVOKE_H_
-#define ABSL_BASE_INTERNAL_INVOKE_H_
-
-#include "absl/base/config.h"
-
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
-
-#include <functional>
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-
-using std::invoke;
-using std::invoke_result_t;
-using std::is_invocable_r;
-
-}  // namespace base_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#else  // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
-
-#include <algorithm>
-#include <type_traits>
-#include <utility>
-
-#include "absl/meta/type_traits.h"
-
-// The following code is internal implementation detail.  See the comment at the
-// top of this file for the API documentation.
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-
-// The five classes below each implement one of the clauses from the definition
-// of INVOKE. The inner class template Accept<F, Args...> checks whether the
-// clause is applicable; static function template Invoke(f, args...) does the
-// invocation.
-//
-// By separating the clause selection logic from invocation we make sure that
-// Invoke() does exactly what the standard says.
-
-template <typename Derived>
-struct StrippedAccept {
-  template <typename... Args>
-  struct Accept : Derived::template AcceptImpl<typename std::remove_cv<
-                      typename std::remove_reference<Args>::type>::type...> {};
-};
-
-// (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T
-// and t1 is an object of type T or a reference to an object of type T or a
-// reference to an object of a type derived from T.
-struct MemFunAndRef : StrippedAccept<MemFunAndRef> {
-  template <typename... Args>
-  struct AcceptImpl : std::false_type {};
-
-  template <typename MemFunType, typename C, typename Obj, typename... Args>
-  struct AcceptImpl<MemFunType C::*, Obj, Args...>
-      : std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
-                                         absl::is_function<MemFunType>::value> {
-  };
-
-  template <typename MemFun, typename Obj, typename... Args>
-  static decltype((std::declval<Obj>().*
-                   std::declval<MemFun>())(std::declval<Args>()...))
-  Invoke(MemFun&& mem_fun, Obj&& obj, Args&&... args) {
-// Ignore bogus GCC warnings on this line.
-// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101436 for similar example.
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Warray-bounds"
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
-    return (std::forward<Obj>(obj).*
-            std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(11, 0)
-#pragma GCC diagnostic pop
-#endif
-  }
-};
-
-// ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a
-// class T and t1 is not one of the types described in the previous item.
-struct MemFunAndPtr : StrippedAccept<MemFunAndPtr> {
-  template <typename... Args>
-  struct AcceptImpl : std::false_type {};
-
-  template <typename MemFunType, typename C, typename Ptr, typename... Args>
-  struct AcceptImpl<MemFunType C::*, Ptr, Args...>
-      : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
-                                         absl::is_function<MemFunType>::value> {
-  };
-
-  template <typename MemFun, typename Ptr, typename... Args>
-  static decltype(((*std::declval<Ptr>()).*
-                   std::declval<MemFun>())(std::declval<Args>()...))
-  Invoke(MemFun&& mem_fun, Ptr&& ptr, Args&&... args) {
-    return ((*std::forward<Ptr>(ptr)).*
-            std::forward<MemFun>(mem_fun))(std::forward<Args>(args)...);
-  }
-};
-
-// t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is
-// an object of type T or a reference to an object of type T or a reference
-// to an object of a type derived from T.
-struct DataMemAndRef : StrippedAccept<DataMemAndRef> {
-  template <typename... Args>
-  struct AcceptImpl : std::false_type {};
-
-  template <typename R, typename C, typename Obj>
-  struct AcceptImpl<R C::*, Obj>
-      : std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
-                                         !absl::is_function<R>::value> {};
-
-  template <typename DataMem, typename Ref>
-  static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke(
-      DataMem&& data_mem, Ref&& ref) {
-    return std::forward<Ref>(ref).*std::forward<DataMem>(data_mem);
-  }
-};
-
-// (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1
-// is not one of the types described in the previous item.
-struct DataMemAndPtr : StrippedAccept<DataMemAndPtr> {
-  template <typename... Args>
-  struct AcceptImpl : std::false_type {};
-
-  template <typename R, typename C, typename Ptr>
-  struct AcceptImpl<R C::*, Ptr>
-      : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
-                                         !absl::is_function<R>::value> {};
-
-  template <typename DataMem, typename Ptr>
-  static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke(
-      DataMem&& data_mem, Ptr&& ptr) {
-    return (*std::forward<Ptr>(ptr)).*std::forward<DataMem>(data_mem);
-  }
-};
-
-// f(t1, t2, ..., tN) in all other cases.
-struct Callable {
-  // Callable doesn't have Accept because it's the last clause that gets picked
-  // when none of the previous clauses are applicable.
-  template <typename F, typename... Args>
-  static decltype(std::declval<F>()(std::declval<Args>()...)) Invoke(
-      F&& f, Args&&... args) {
-    return std::forward<F>(f)(std::forward<Args>(args)...);
-  }
-};
-
-// Resolves to the first matching clause.
-template <typename... Args>
-struct Invoker {
-  typedef typename std::conditional<
-      MemFunAndRef::Accept<Args...>::value, MemFunAndRef,
-      typename std::conditional<
-          MemFunAndPtr::Accept<Args...>::value, MemFunAndPtr,
-          typename std::conditional<
-              DataMemAndRef::Accept<Args...>::value, DataMemAndRef,
-              typename std::conditional<DataMemAndPtr::Accept<Args...>::value,
-                                        DataMemAndPtr, Callable>::type>::type>::
-          type>::type type;
-};
-
-// The result type of Invoke<F, Args...>.
-template <typename F, typename... Args>
-using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
-    std::declval<F>(), std::declval<Args>()...));
-
-// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
-// [func.require] of the C++ standard.
-template <typename F, typename... Args>
-invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
-  return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
-                                           std::forward<Args>(args)...);
-}
-
-template <typename AlwaysVoid, typename, typename, typename...>
-struct IsInvocableRImpl : std::false_type {};
-
-template <typename R, typename F, typename... Args>
-struct IsInvocableRImpl<
-    absl::void_t<absl::base_internal::invoke_result_t<F, Args...> >, R, F,
-    Args...>
-    : std::integral_constant<
-          bool,
-          std::is_convertible<absl::base_internal::invoke_result_t<F, Args...>,
-                              R>::value ||
-              std::is_void<R>::value> {};
-
-// Type trait whose member `value` is true if invoking `F` with `Args` is valid,
-// and either the return type is convertible to `R`, or `R` is void.
-// C++11-compatible version of `std::is_invocable_r`.
-template <typename R, typename F, typename... Args>
-using is_invocable_r = IsInvocableRImpl<void, R, F, Args...>;
-
-}  // namespace base_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
-
-#endif  // ABSL_BASE_INTERNAL_INVOKE_H_
diff --git a/absl/base/internal/iterator_traits.h b/absl/base/internal/iterator_traits.h
new file mode 100644
index 0000000..472c436
--- /dev/null
+++ b/absl/base/internal/iterator_traits.h
@@ -0,0 +1,71 @@
+// Copyright 2025 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: internal/iterator_traits.h
+// -----------------------------------------------------------------------------
+//
+// Helpers for querying traits of iterators, for implementing containers, etc.
+
+#ifndef ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_
+#define ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_
+
+#include <iterator>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+template <typename Iterator, typename = void>
+struct IteratorCategory {};
+
+template <typename Iterator>
+struct IteratorCategory<
+    Iterator,
+    absl::void_t<typename std::iterator_traits<Iterator>::iterator_category>> {
+  using type = typename std::iterator_traits<Iterator>::iterator_category;
+};
+
+template <typename Iterator, typename = void>
+struct IteratorConceptImpl : IteratorCategory<Iterator> {};
+
+template <typename Iterator>
+struct IteratorConceptImpl<
+    Iterator,
+    absl::void_t<typename std::iterator_traits<Iterator>::iterator_concept>> {
+  using type = typename std::iterator_traits<Iterator>::iterator_concept;
+};
+
+// The newer `std::iterator_traits<Iterator>::iterator_concept` if available,
+// else `std::iterator_traits<Iterator>::iterator_category`.
+template <typename Iterator>
+using IteratorConcept = typename IteratorConceptImpl<Iterator>::type;
+
+template <typename IteratorTag, typename Iterator>
+using IsAtLeastIterator =
+    std::is_convertible<IteratorConcept<Iterator>, IteratorTag>;
+
+template <typename Iterator>
+using IsAtLeastForwardIterator =
+    IsAtLeastIterator<std::forward_iterator_tag, Iterator>;
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_
diff --git a/absl/base/internal/iterator_traits_test.cc b/absl/base/internal/iterator_traits_test.cc
new file mode 100644
index 0000000..cb2044f
--- /dev/null
+++ b/absl/base/internal/iterator_traits_test.cc
@@ -0,0 +1,85 @@
+// Copyright 2025 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/base/internal/iterator_traits.h"
+
+#include <forward_list>
+#include <iterator>
+#include <list>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/iterator_traits_test_helper.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+namespace {
+
+TEST(IsAtLeastIteratorTest, IsAtLeastIterator) {
+  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag, int*>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag, int*>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::bidirectional_iterator_tag, int*>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::random_access_iterator_tag, int*>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,
+                                 std::vector<int>::iterator>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,
+                                 std::vector<int>::iterator>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::bidirectional_iterator_tag,
+                                 std::vector<int>::iterator>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::random_access_iterator_tag,
+                                 std::vector<int>::iterator>()));
+
+  EXPECT_TRUE(
+      (IsAtLeastIterator<std::input_iterator_tag, std::list<int>::iterator>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,
+                                 std::list<int>::iterator>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::bidirectional_iterator_tag,
+                                 std::list<int>::iterator>()));
+  EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,
+                                  std::list<int>::iterator>()));
+
+  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,
+                                 std::forward_list<int>::iterator>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,
+                                 std::forward_list<int>::iterator>()));
+  EXPECT_FALSE((IsAtLeastIterator<std::bidirectional_iterator_tag,
+                                  std::forward_list<int>::iterator>()));
+  EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,
+                                  std::forward_list<int>::iterator>()));
+
+  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,
+                                 std::istream_iterator<int>>()));
+  EXPECT_FALSE((IsAtLeastIterator<std::forward_iterator_tag,
+                                  std::istream_iterator<int>>()));
+  EXPECT_FALSE((IsAtLeastIterator<std::bidirectional_iterator_tag,
+                                  std::istream_iterator<int>>()));
+  EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,
+                                  std::istream_iterator<int>>()));
+
+  EXPECT_TRUE((IsAtLeastIterator<std::input_iterator_tag,
+                                 Cpp20ForwardZipIterator<int*>>()));
+  EXPECT_TRUE((IsAtLeastIterator<std::forward_iterator_tag,
+                                 Cpp20ForwardZipIterator<int*>>()));
+  EXPECT_FALSE((IsAtLeastIterator<std::bidirectional_iterator_tag,
+                                  Cpp20ForwardZipIterator<int*>>()));
+  EXPECT_FALSE((IsAtLeastIterator<std::random_access_iterator_tag,
+                                  Cpp20ForwardZipIterator<int*>>()));
+}
+
+}  // namespace
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/internal/iterator_traits_test_helper.h b/absl/base/internal/iterator_traits_test_helper.h
new file mode 100644
index 0000000..707612d
--- /dev/null
+++ b/absl/base/internal/iterator_traits_test_helper.h
@@ -0,0 +1,97 @@
+// Copyright 2025 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_BASE_INTERNAL_ITERATOR_TRAITS_TEST_HELPER_H_
+#define ABSL_BASE_INTERNAL_ITERATOR_TRAITS_TEST_HELPER_H_
+
+#include <iterator>
+#include <utility>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// This would be a forward_iterator in C++20, but it's only an input iterator
+// before that, since it has a non-reference `reference`.
+template <typename Iterator>
+class Cpp20ForwardZipIterator {
+  using IteratorReference = typename std::iterator_traits<Iterator>::reference;
+
+ public:
+  Cpp20ForwardZipIterator() = default;
+  explicit Cpp20ForwardZipIterator(Iterator left, Iterator right)
+      : left_(left), right_(right) {}
+
+  Cpp20ForwardZipIterator& operator++() {
+    ++left_;
+    ++right_;
+    return *this;
+  }
+
+  Cpp20ForwardZipIterator operator++(int) {
+    Cpp20ForwardZipIterator tmp(*this);
+    ++*this;
+    return *this;
+  }
+
+  std::pair<IteratorReference, IteratorReference> operator*() const {
+    return {*left_, *right_};
+  }
+
+  // C++17 input iterators require `operator->`, but this isn't  possible to
+  // implement. C++20 dropped the requirement.
+
+  friend bool operator==(const Cpp20ForwardZipIterator& lhs,
+                         const Cpp20ForwardZipIterator& rhs) {
+    return lhs.left_ == rhs.left_ && lhs.right_ == rhs.right_;
+  }
+
+  friend bool operator!=(const Cpp20ForwardZipIterator& lhs,
+                         const Cpp20ForwardZipIterator& rhs) {
+    return !(lhs == rhs);
+  }
+
+ private:
+  Iterator left_{};
+  Iterator right_{};
+};
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+template <typename Iterator>
+struct std::iterator_traits<
+    absl::base_internal::Cpp20ForwardZipIterator<Iterator>> {
+ private:
+  using IteratorReference = typename std::iterator_traits<Iterator>::reference;
+
+ public:
+  using iterator_category = std::input_iterator_tag;
+  using iterator_concept = std::forward_iterator_tag;
+  using value_type = std::pair<IteratorReference, IteratorReference>;
+  using difference_type =
+      typename std::iterator_traits<Iterator>::difference_type;
+  using reference = value_type;
+  using pointer = void;
+};
+
+#if defined(__cpp_lib_concepts)
+static_assert(
+    std::forward_iterator<absl::base_internal::Cpp20ForwardZipIterator<int*>>);
+#endif  // defined(__cpp_lib_concepts)
+
+#endif  // ABSL_BASE_INTERNAL_ITERATOR_TRAITS_TEST_HELPER_H_
diff --git a/absl/base/internal/low_level_alloc.cc b/absl/base/internal/low_level_alloc.cc
index a563f7b..158b609 100644
--- a/absl/base/internal/low_level_alloc.cc
+++ b/absl/base/internal/low_level_alloc.cc
@@ -330,7 +330,7 @@
   GetSystemInfo(&system_info);
   return std::max(system_info.dwPageSize, system_info.dwAllocationGranularity);
 #elif defined(__wasm__) || defined(__asmjs__) || defined(__hexagon__)
-  return getpagesize();
+  return static_cast<size_t>(getpagesize());
 #else
   return static_cast<size_t>(sysconf(_SC_PAGESIZE));
 #endif
@@ -448,8 +448,8 @@
 // that the freelist is in the correct order, that it
 // consists of regions marked "unallocated", and that no two regions
 // are adjacent in memory (they should have been coalesced).
-// L >= arena->mu
-static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena) {
+static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena)
+    ABSL_EXCLUSIVE_LOCKS_REQUIRED(arena->mu) {
   ABSL_RAW_CHECK(i < prev->levels, "too few levels in Next()");
   AllocList *next = prev->next[i];
   if (next != nullptr) {
@@ -473,6 +473,7 @@
   if (n != nullptr && reinterpret_cast<char *>(a) + a->header.size ==
                           reinterpret_cast<char *>(n)) {
     LowLevelAlloc::Arena *arena = a->header.arena;
+    arena->mu.AssertHeld();
     a->header.size += n->header.size;
     n->header.magic = 0;
     n->header.arena = nullptr;
@@ -486,8 +487,8 @@
 }
 
 // Adds block at location "v" to the free list
-// L >= arena->mu
-static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena) {
+static void AddToFreelist(void *v, LowLevelAlloc::Arena *arena)
+    ABSL_EXCLUSIVE_LOCKS_REQUIRED(arena->mu) {
   AllocList *f = reinterpret_cast<AllocList *>(reinterpret_cast<char *>(v) -
                                                sizeof(f->header));
   ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),
diff --git a/absl/base/internal/nullability_deprecated.h b/absl/base/internal/nullability_deprecated.h
new file mode 100644
index 0000000..1174a96
--- /dev/null
+++ b/absl/base/internal/nullability_deprecated.h
@@ -0,0 +1,106 @@
+// Copyright 2023 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_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
+#define ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace nullability_internal {
+
+template <typename T>
+using NullableImpl
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+    [[clang::annotate("Nullable")]]
+#endif
+// Don't add the _Nullable attribute in Objective-C compiles. Many Objective-C
+// projects enable the `-Wnullable-to-nonnull-conversion warning`, which is
+// liable to produce false positives.
+#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
+    = T _Nullable;
+#else
+    = T;
+#endif
+
+template <typename T>
+using NonnullImpl
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+    [[clang::annotate("Nonnull")]]
+#endif
+#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
+    = T _Nonnull;
+#else
+    = T;
+#endif
+
+template <typename T>
+using NullabilityUnknownImpl
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
+    [[clang::annotate("Nullability_Unspecified")]]
+#endif
+#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
+    = T _Null_unspecified;
+#else
+    = T;
+#endif
+
+}  // namespace nullability_internal
+
+// The following template aliases are deprecated forms of nullability
+// annotations. They have some limitations, for example, an incompatibility with
+// `auto*` pointers, as `auto` cannot be used in a template argument.
+//
+// It is important to note that these annotations are not distinct strong
+// *types*. They are alias templates defined to be equal to the underlying
+// pointer type. A pointer annotated `Nonnull<T*>`, for example, is simply a
+// pointer of type `T*`.
+//
+// Prefer the macro style annotations in `absl/base/nullability.h` instead.
+
+// absl::Nonnull, analogous to absl_nonnull
+//
+// Example:
+// absl::Nonnull<int*> foo;
+// Is equivalent to:
+// int* absl_nonnull foo;
+template <typename T>
+using Nonnull [[deprecated("Use `absl_nonnull`.")]] =
+    nullability_internal::NonnullImpl<T>;
+
+// absl::Nullable, analogous to absl_nullable
+//
+// Example:
+// absl::Nullable<int*> foo;
+// Is equivalent to:
+// int* absl_nullable foo;
+template <typename T>
+using Nullable [[deprecated("Use `absl_nullable`.")]] =
+    nullability_internal::NullableImpl<T>;
+
+// absl::NullabilityUnknown, analogous to absl_nullability_unknown
+//
+// Example:
+// absl::NullabilityUnknown<int*> foo;
+// Is equivalent to:
+// int* absl_nullability_unknown foo;
+template <typename T>
+using NullabilityUnknown [[deprecated("Use `absl_nullability_unknown`.")]] =
+    nullability_internal::NullabilityUnknownImpl<T>;
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
diff --git a/absl/base/internal/nullability_impl.h b/absl/base/internal/nullability_impl.h
deleted file mode 100644
index 03fa243..0000000
--- a/absl/base/internal/nullability_impl.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2023 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_BASE_INTERNAL_NULLABILITY_IMPL_H_
-#define ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
-
-#include <memory>
-#include <type_traits>
-
-#include "absl/base/attributes.h"
-#include "absl/base/config.h"
-#include "absl/meta/type_traits.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace nullability_internal {
-
-// `IsNullabilityCompatible` checks whether its first argument is a class
-// explicitly tagged as supporting nullability annotations. The tag is the type
-// declaration `absl_nullability_compatible`.
-template <typename, typename = void>
-struct IsNullabilityCompatible : std::false_type {};
-
-template <typename T>
-struct IsNullabilityCompatible<
-    T, absl::void_t<typename T::absl_nullability_compatible>> : std::true_type {
-};
-
-template <typename T>
-constexpr bool IsSupportedType = IsNullabilityCompatible<T>::value;
-
-template <typename T>
-constexpr bool IsSupportedType<T*> = true;
-
-template <typename T, typename U>
-constexpr bool IsSupportedType<T U::*> = true;
-
-template <typename T, typename... Deleter>
-constexpr bool IsSupportedType<std::unique_ptr<T, Deleter...>> = true;
-
-template <typename T>
-constexpr bool IsSupportedType<std::shared_ptr<T>> = true;
-
-template <typename T>
-struct EnableNullable {
-  static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
-                "Template argument must be a raw or supported smart pointer "
-                "type. See absl/base/nullability.h.");
-  using type = T;
-};
-
-template <typename T>
-struct EnableNonnull {
-  static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
-                "Template argument must be a raw or supported smart pointer "
-                "type. See absl/base/nullability.h.");
-  using type = T;
-};
-
-template <typename T>
-struct EnableNullabilityUnknown {
-  static_assert(nullability_internal::IsSupportedType<std::remove_cv_t<T>>,
-                "Template argument must be a raw or supported smart pointer "
-                "type. See absl/base/nullability.h.");
-  using type = T;
-};
-
-// Note: we do not apply Clang nullability attributes (e.g. _Nullable).  These
-// only support raw pointers, and conditionally enabling them only for raw
-// pointers inhibits template arg deduction.  Ideally, they would support all
-// pointer-like types.
-template <typename T, typename = typename EnableNullable<T>::type>
-using NullableImpl
-#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
-    [[clang::annotate("Nullable")]]
-#endif
-    = T;
-
-template <typename T, typename = typename EnableNonnull<T>::type>
-using NonnullImpl
-#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
-    [[clang::annotate("Nonnull")]]
-#endif
-    = T;
-
-template <typename T, typename = typename EnableNullabilityUnknown<T>::type>
-using NullabilityUnknownImpl
-#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
-    [[clang::annotate("Nullability_Unspecified")]]
-#endif
-    = T;
-
-}  // namespace nullability_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_BASE_INTERNAL_NULLABILITY_IMPL_H_
diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc
index d32b40a..35a08f0 100644
--- a/absl/base/internal/raw_logging.cc
+++ b/absl/base/internal/raw_logging.cc
@@ -175,7 +175,7 @@
     } else {
       DoRawLog(&buf, &size, "%s", kTruncated);
     }
-    AsyncSignalSafeWriteError(buffer, strlen(buffer));
+    AsyncSignalSafeWriteError(buffer, static_cast<size_t>(buf - buffer));
   }
 #else
   static_cast<void>(format);
diff --git a/absl/base/internal/spinlock.cc b/absl/base/internal/spinlock.cc
index 381b913..430f775 100644
--- a/absl/base/internal/spinlock.cc
+++ b/absl/base/internal/spinlock.cc
@@ -67,15 +67,6 @@
   submit_profile_data.Store(fn);
 }
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-// Static member variable definitions.
-constexpr uint32_t SpinLock::kSpinLockHeld;
-constexpr uint32_t SpinLock::kSpinLockCooperative;
-constexpr uint32_t SpinLock::kSpinLockDisabledScheduling;
-constexpr uint32_t SpinLock::kSpinLockSleeper;
-constexpr uint32_t SpinLock::kWaitTimeMask;
-#endif
-
 // Uncommon constructors.
 SpinLock::SpinLock(base_internal::SchedulingMode mode)
     : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {
diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h
index 1bb260f..2a10896 100644
--- a/absl/base/internal/spinlock.h
+++ b/absl/base/internal/spinlock.h
@@ -89,8 +89,7 @@
   // acquisition was successful.  If the lock was not acquired, false is
   // returned.  If this SpinLock is free at the time of the call, TryLock
   // will return true with high probability.
-  ABSL_MUST_USE_RESULT inline bool TryLock()
-      ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
+  [[nodiscard]] inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
     ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
     bool res = TryLockImpl();
     ABSL_TSAN_MUTEX_POST_LOCK(
@@ -121,7 +120,7 @@
   // Determine if the lock is held.  When the lock is held by the invoking
   // thread, true will always be returned. Intended to be used as
   // CHECK(lock.IsHeld()).
-  ABSL_MUST_USE_RESULT inline bool IsHeld() const {
+  [[nodiscard]] inline bool IsHeld() const {
     return (lockword_.load(std::memory_order_relaxed) & kSpinLockHeld) != 0;
   }
 
@@ -203,16 +202,7 @@
 
 // Corresponding locker object that arranges to acquire a spinlock for
 // the duration of a C++ scope.
-//
-// TODO(b/176172494): Use only [[nodiscard]] when baseline is raised.
-// TODO(b/6695610): Remove forward declaration when #ifdef is no longer needed.
-#if ABSL_HAVE_CPP_ATTRIBUTE(nodiscard)
-class [[nodiscard]] SpinLockHolder;
-#else
-class ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_TRIVIAL_ABI SpinLockHolder;
-#endif
-
-class ABSL_SCOPED_LOCKABLE SpinLockHolder {
+class ABSL_SCOPED_LOCKABLE [[nodiscard]] SpinLockHolder {
  public:
   inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l)
       : lock_(l) {
diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc
index 79eaba3..1937db3 100644
--- a/absl/base/internal/sysinfo.cc
+++ b/absl/base/internal/sysinfo.cc
@@ -46,6 +46,10 @@
 #include <rtems.h>
 #endif
 
+#if defined(__Fuchsia__)
+#include <zircon/process.h>
+#endif
+
 #include <string.h>
 
 #include <cassert>
@@ -461,6 +465,16 @@
   return reinterpret_cast<pid_t>(thread);
 }
 
+#elif defined(__Fuchsia__)
+
+pid_t GetTID() {
+  // Use our thread handle as the TID, which should be unique within this
+  // process (but may not be globally unique). The handle value was chosen over
+  // a kernel object ID (KOID) because zx_handle_t (32-bits) can be cast to a
+  // pid_t type without loss of precision, but a zx_koid_t (64-bits) cannot.
+  return static_cast<pid_t>(zx_thread_self());
+}
+
 #else
 
 // Fallback implementation of `GetTID` using `pthread_self`.
diff --git a/absl/base/internal/sysinfo_test.cc b/absl/base/internal/sysinfo_test.cc
index f305b6c..c2b59aa 100644
--- a/absl/base/internal/sysinfo_test.cc
+++ b/absl/base/internal/sysinfo_test.cc
@@ -41,7 +41,7 @@
   EXPECT_EQ(GetTID(), GetTID());  // Basic compile and equality test.
 #ifdef __native_client__
   // Native Client has a race condition bug that leads to memory
-  // exaustion when repeatedly creating and joining threads.
+  // exhaustion when repeatedly creating and joining threads.
   // https://bugs.chromium.org/p/nativeclient/issues/detail?id=1027
   return;
 #endif
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index b6e917c..acfc15a 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -130,7 +130,11 @@
 };
 
 // The instances of this class are allocated in NewThreadIdentity() with an
-// alignment of PerThreadSynch::kAlignment.
+// alignment of PerThreadSynch::kAlignment and never destroyed. Initialization
+// should happen in OneTimeInitThreadIdentity().
+//
+// Instances may be reused by new threads - fields should be reset in
+// ResetThreadIdentityBetweenReuse().
 //
 // NOTE: The layout of fields in this structure is critical, please do not
 //       add, remove, or modify the field placements without fully auditing the
diff --git a/absl/base/internal/thread_identity_benchmark.cc b/absl/base/internal/thread_identity_benchmark.cc
index 0ae10f2..419e82d 100644
--- a/absl/base/internal/thread_identity_benchmark.cc
+++ b/absl/base/internal/thread_identity_benchmark.cc
@@ -12,10 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "benchmark/benchmark.h"
 #include "absl/base/internal/thread_identity.h"
 #include "absl/synchronization/internal/create_thread_identity.h"
 #include "absl/synchronization/internal/per_thread_sem.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
diff --git a/absl/base/internal/tracing.cc b/absl/base/internal/tracing.cc
new file mode 100644
index 0000000..d304e6a
--- /dev/null
+++ b/absl/base/internal/tracing.cc
@@ -0,0 +1,39 @@
+// Copyright 2024 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/base/internal/tracing.h"
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+extern "C" {
+
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(
+    const void*, ObjectKind) {}
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(
+    const void*, ObjectKind) {}
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(
+    const void*, ObjectKind) {}
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(
+    const void*, ObjectKind) {}
+
+}  // extern "C"
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/internal/tracing.h b/absl/base/internal/tracing.h
new file mode 100644
index 0000000..e7ab775
--- /dev/null
+++ b/absl/base/internal/tracing.h
@@ -0,0 +1,81 @@
+// Copyright 2024 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_BASE_INTERNAL_TRACING_H_
+#define ABSL_BASE_INTERNAL_TRACING_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// Well known Abseil object types that have causality.
+enum class ObjectKind { kUnknown, kBlockingCounter, kNotification };
+
+// `TraceWait` and `TraceContinue` record the start and end of a potentially
+// blocking wait operation on `object`. `object` typically represents a higher
+// level synchronization object such as `absl::Notification`.
+void TraceWait(const void* object, ObjectKind kind);
+void TraceContinue(const void* object, ObjectKind kind);
+
+// `TraceSignal` records a signal on `object`.
+void TraceSignal(const void* object, ObjectKind kind);
+
+// `TraceObserved` records the non-blocking observation of a signaled object.
+void TraceObserved(const void* object, ObjectKind kind);
+
+// ---------------------------------------------------------------------------
+// Weak implementation detail:
+//
+// We define the weak API as extern "C": in some build configurations we pass
+// `--detect-odr-violations` to the gold linker. This causes it to flag weak
+// symbol overrides as ODR violations. Because ODR only applies to C++ and not
+// C, `--detect-odr-violations` ignores symbols not mangled with C++ names.
+// By changing our extension points to be extern "C", we dodge this check.
+// ---------------------------------------------------------------------------
+extern "C" {
+
+  void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
+                                                     ObjectKind kind);
+  void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
+                                                         ObjectKind kind);
+  void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
+                                                       ObjectKind kind);
+  void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
+                                                         ObjectKind kind);
+
+}  // extern "C"
+
+inline void TraceWait(const void* object, ObjectKind kind) {
+  ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(object, kind);
+}
+
+inline void TraceContinue(const void* object, ObjectKind kind) {
+  ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(object, kind);
+}
+
+inline void TraceSignal(const void* object, ObjectKind kind) {
+  ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(object, kind);
+}
+
+inline void TraceObserved(const void* object, ObjectKind kind) {
+  ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(object, kind);
+}
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_TRACING_H_
diff --git a/absl/base/internal/tracing_strong_test.cc b/absl/base/internal/tracing_strong_test.cc
new file mode 100644
index 0000000..979f1c5
--- /dev/null
+++ b/absl/base/internal/tracing_strong_test.cc
@@ -0,0 +1,117 @@
+// Copyright 2024 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 <tuple>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/tracing.h"
+
+#if ABSL_HAVE_ATTRIBUTE_WEAK
+
+namespace {
+
+using ::testing::ElementsAre;
+
+using ::absl::base_internal::ObjectKind;
+
+enum Function { kWait, kContinue, kSignal, kObserved };
+
+using Record = std::tuple<Function, const void*, ObjectKind>;
+
+thread_local std::vector<Record>* tls_records = nullptr;
+
+}  // namespace
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// Strong extern "C" implementation.
+extern "C" {
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
+                                                   ObjectKind kind) {
+  if (tls_records != nullptr) {
+    tls_records->push_back({kWait, object, kind});
+  }
+}
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
+                                                       ObjectKind kind) {
+  if (tls_records != nullptr) {
+    tls_records->push_back({kContinue, object, kind});
+  }
+}
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
+                                                     ObjectKind kind) {
+  if (tls_records != nullptr) {
+    tls_records->push_back({kSignal, object, kind});
+  }
+}
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
+                                                       ObjectKind kind) {
+  if (tls_records != nullptr) {
+    tls_records->push_back({kObserved, object, kind});
+  }
+}
+
+}  // extern "C"
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+namespace {
+
+TEST(TracingInternal, InvokesStrongFunctionWithNullptr) {
+  std::vector<Record> records;
+  tls_records = &records;
+  auto kind = absl::base_internal::ObjectKind::kUnknown;
+  absl::base_internal::TraceWait(nullptr, kind);
+  absl::base_internal::TraceContinue(nullptr, kind);
+  absl::base_internal::TraceSignal(nullptr, kind);
+  absl::base_internal::TraceObserved(nullptr, kind);
+  tls_records = nullptr;
+
+  EXPECT_THAT(records, ElementsAre(Record{kWait, nullptr, kind},
+                                   Record{kContinue, nullptr, kind},
+                                   Record{kSignal, nullptr, kind},
+                                   Record{kObserved, nullptr, kind}));
+}
+
+TEST(TracingInternal, InvokesStrongFunctionWithObjectAddress) {
+  int object = 0;
+  std::vector<Record> records;
+  tls_records = &records;
+  auto kind = absl::base_internal::ObjectKind::kUnknown;
+  absl::base_internal::TraceWait(&object, kind);
+  absl::base_internal::TraceContinue(&object, kind);
+  absl::base_internal::TraceSignal(&object, kind);
+  absl::base_internal::TraceObserved(&object, kind);
+  tls_records = nullptr;
+
+  EXPECT_THAT(records, ElementsAre(Record{kWait, &object, kind},
+                                   Record{kContinue, &object, kind},
+                                   Record{kSignal, &object, kind},
+                                   Record{kObserved, &object, kind}));
+}
+
+}  // namespace
+
+#endif  // ABSL_HAVE_ATTRIBUTE_WEAK
diff --git a/absl/base/internal/tracing_weak_test.cc b/absl/base/internal/tracing_weak_test.cc
new file mode 100644
index 0000000..6d7553f
--- /dev/null
+++ b/absl/base/internal/tracing_weak_test.cc
@@ -0,0 +1,34 @@
+// Copyright 2024 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 "gtest/gtest.h"
+#include "absl/base/internal/tracing.h"
+
+namespace {
+
+TEST(TracingInternal, HasDefaultImplementation) {
+  auto kind = absl::base_internal::ObjectKind::kUnknown;
+  absl::base_internal::TraceWait(nullptr, kind);
+  absl::base_internal::TraceContinue(nullptr, kind);
+  absl::base_internal::TraceSignal(nullptr, kind);
+  absl::base_internal::TraceObserved(nullptr, kind);
+
+  int object = 0;
+  absl::base_internal::TraceWait(&object, kind);
+  absl::base_internal::TraceContinue(&object, kind);
+  absl::base_internal::TraceSignal(&object, kind);
+  absl::base_internal::TraceObserved(&object, kind);
+}
+
+}  // namespace
diff --git a/absl/base/internal/unaligned_access.h b/absl/base/internal/unaligned_access.h
index 4fea457..3f5dd6f 100644
--- a/absl/base/internal/unaligned_access.h
+++ b/absl/base/internal/unaligned_access.h
@@ -36,33 +36,33 @@
 ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
-inline uint16_t UnalignedLoad16(absl::Nonnull<const void *> p) {
+inline uint16_t UnalignedLoad16(const void* absl_nonnull p) {
   uint16_t t;
   memcpy(&t, p, sizeof t);
   return t;
 }
 
-inline uint32_t UnalignedLoad32(absl::Nonnull<const void *> p) {
+inline uint32_t UnalignedLoad32(const void* absl_nonnull p) {
   uint32_t t;
   memcpy(&t, p, sizeof t);
   return t;
 }
 
-inline uint64_t UnalignedLoad64(absl::Nonnull<const void *> p) {
+inline uint64_t UnalignedLoad64(const void* absl_nonnull p) {
   uint64_t t;
   memcpy(&t, p, sizeof t);
   return t;
 }
 
-inline void UnalignedStore16(absl::Nonnull<void *> p, uint16_t v) {
+inline void UnalignedStore16(void* absl_nonnull p, uint16_t v) {
   memcpy(p, &v, sizeof v);
 }
 
-inline void UnalignedStore32(absl::Nonnull<void *> p, uint32_t v) {
+inline void UnalignedStore32(void* absl_nonnull p, uint32_t v) {
   memcpy(p, &v, sizeof v);
 }
 
-inline void UnalignedStore64(absl::Nonnull<void *> p, uint64_t v) {
+inline void UnalignedStore64(void* absl_nonnull p, uint64_t v) {
   memcpy(p, &v, sizeof v);
 }
 
diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc
index a0bf3a6..68f9273 100644
--- a/absl/base/internal/unscaledcycleclock.cc
+++ b/absl/base/internal/unscaledcycleclock.cc
@@ -105,16 +105,6 @@
 
 #elif defined(__aarch64__)
 
-// System timer of ARMv8 runs at a different frequency than the CPU's.
-// The frequency is fixed, typically in the range 1-50MHz.  It can be
-// read at CNTFRQ special register.  We assume the OS has set up
-// the virtual timer properly.
-int64_t UnscaledCycleClock::Now() {
-  int64_t virtual_timer_value;
-  asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
-  return virtual_timer_value;
-}
-
 double UnscaledCycleClock::Frequency() {
   uint64_t aarch64_timer_frequency;
   asm volatile("mrs %0, cntfrq_el0" : "=r"(aarch64_timer_frequency));
diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h
index cc1276b..bfd9887 100644
--- a/absl/base/internal/unscaledcycleclock.h
+++ b/absl/base/internal/unscaledcycleclock.h
@@ -85,6 +85,23 @@
   return static_cast<int64_t>((high << 32) | low);
 }
 
+#elif defined(__aarch64__)
+
+// System timer of ARMv8 runs at a different frequency than the CPU's.
+//
+// Frequency is fixed. From Armv8.6-A and Armv9.1-A on, the frequency is 1GHz.
+// Pre-Armv8.6-A, the frequency was a system design choice, typically in the
+// range of 1MHz to 50MHz. See also:
+// https://developer.arm.com/documentation/102379/0101/What-is-the-Generic-Timer-
+//
+// It can be read at CNTFRQ special register.  We assume the OS has set up the
+// virtual timer properly.
+inline int64_t UnscaledCycleClock::Now() {
+  int64_t virtual_timer_value;
+  asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
+  return virtual_timer_value;
+}
+
 #endif
 
 }  // namespace base_internal
diff --git a/absl/base/invoke_test.cc b/absl/base/invoke_test.cc
deleted file mode 100644
index 7be26f6..0000000
--- a/absl/base/invoke_test.cc
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2017 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/base/internal/invoke.h"
-
-#include <functional>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/memory/memory.h"
-#include "absl/strings/str_cat.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
-namespace {
-
-int Function(int a, int b) { return a - b; }
-
-void VoidFunction(int& a, int& b) {
-  a += b;
-  b = a - b;
-  a -= b;
-}
-
-int ZeroArgFunction() { return -1937; }
-
-int Sink(std::unique_ptr<int> p) {
-  return *p;
-}
-
-std::unique_ptr<int> Factory(int n) {
-  return make_unique<int>(n);
-}
-
-void NoOp() {}
-
-struct ConstFunctor {
-  int operator()(int a, int b) const { return a - b; }
-};
-
-struct MutableFunctor {
-  int operator()(int a, int b) { return a - b; }
-};
-
-struct EphemeralFunctor {
-  int operator()(int a, int b) && { return a - b; }
-};
-
-struct OverloadedFunctor {
-  template <typename... Args>
-  std::string operator()(const Args&... args) & {
-    return StrCat("&", args...);
-  }
-  template <typename... Args>
-  std::string operator()(const Args&... args) const& {
-    return StrCat("const&", args...);
-  }
-  template <typename... Args>
-  std::string operator()(const Args&... args) && {
-    return StrCat("&&", args...);
-  }
-};
-
-struct Class {
-  int Method(int a, int b) { return a - b; }
-  int ConstMethod(int a, int b) const { return a - b; }
-  int RefMethod(int a, int b) & { return a - b; }
-  int RefRefMethod(int a, int b) && { return a - b; }
-  int NoExceptMethod(int a, int b) noexcept { return a - b; }
-  int VolatileMethod(int a, int b) volatile { return a - b; }
-
-  int member;
-};
-
-struct FlipFlop {
-  int ConstMethod() const { return member; }
-  FlipFlop operator*() const { return {-member}; }
-
-  int member;
-};
-
-// CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
-// on which one is valid.
-template <typename F>
-decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
-    const F& f) {
-  return base_internal::invoke(f);
-}
-
-template <typename F>
-decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
-    const F& f) {
-  return base_internal::invoke(f, 42);
-}
-
-TEST(InvokeTest, Function) {
-  EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
-}
-
-TEST(InvokeTest, NonCopyableArgument) {
-  EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
-}
-
-TEST(InvokeTest, NonCopyableResult) {
-  EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
-}
-
-TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
-
-TEST(InvokeTest, ConstFunctor) {
-  EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
-}
-
-TEST(InvokeTest, MutableFunctor) {
-  MutableFunctor f;
-  EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
-}
-
-TEST(InvokeTest, EphemeralFunctor) {
-  EphemeralFunctor f;
-  EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
-}
-
-TEST(InvokeTest, OverloadedFunctor) {
-  OverloadedFunctor f;
-  const OverloadedFunctor& cf = f;
-
-  EXPECT_EQ("&", base_internal::invoke(f));
-  EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
-
-  EXPECT_EQ("const&", base_internal::invoke(cf));
-  EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
-
-  EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
-
-  OverloadedFunctor f2;
-  EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
-}
-
-TEST(InvokeTest, ReferenceWrapper) {
-  ConstFunctor cf;
-  MutableFunctor mf;
-  EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
-}
-
-TEST(InvokeTest, MemberFunction) {
-  std::unique_ptr<Class> p(new Class);
-  std::unique_ptr<const Class> cp(new Class);
-  std::unique_ptr<volatile Class> vp(new Class);
-
-  EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
-                                     2));  // NOLINT
-  EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));
-
-  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));
-
-  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));
-
-  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));
-
-  EXPECT_EQ(1,
-            base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
-                                     3, 2));
-  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
-                                     make_unique<const Class>(), 3, 2));
-}
-
-TEST(InvokeTest, DataMember) {
-  std::unique_ptr<Class> p(new Class{42});
-  std::unique_ptr<const Class> cp(new Class{42});
-  EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
-  EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
-  EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));
-
-  base_internal::invoke(&Class::member, p) = 42;
-  base_internal::invoke(&Class::member, p.get()) = 42;
-
-  EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
-  EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
-  EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
-}
-
-TEST(InvokeTest, FlipFlop) {
-  FlipFlop obj = {42};
-  // This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
-  // ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
-  EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
-  EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
-}
-
-TEST(InvokeTest, SfinaeFriendly) {
-  CallMaybeWithArg(NoOp);
-  EXPECT_THAT(CallMaybeWithArg(Factory), ::testing::Pointee(42));
-}
-
-TEST(IsInvocableRTest, CallableExactMatch) {
-  static_assert(
-      base_internal::is_invocable_r<int, decltype(Function), int, int>::value,
-      "Should be true for exact match of types on a free function");
-}
-
-TEST(IsInvocableRTest, CallableArgumentConversionMatch) {
-  static_assert(
-      base_internal::is_invocable_r<int, decltype(Function), char, int>::value,
-      "Should be true for convertible argument type");
-}
-
-TEST(IsInvocableRTest, CallableReturnConversionMatch) {
-  static_assert(base_internal::is_invocable_r<double, decltype(Function), int,
-                                              int>::value,
-                "Should be true for convertible return type");
-}
-
-TEST(IsInvocableRTest, CallableReturnVoid) {
-  static_assert(base_internal::is_invocable_r<void, decltype(VoidFunction),
-                                              int&, int&>::value,
-                "Should be true for void expected and actual return types");
-  static_assert(
-      base_internal::is_invocable_r<void, decltype(Function), int, int>::value,
-      "Should be true for void expected and non-void actual return types");
-}
-
-TEST(IsInvocableRTest, CallableRefQualifierMismatch) {
-  static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
-                                               int&, const int&>::value,
-                "Should be false for reference constness mismatch");
-  static_assert(!base_internal::is_invocable_r<void, decltype(VoidFunction),
-                                               int&&, int&>::value,
-                "Should be false for reference value category mismatch");
-}
-
-TEST(IsInvocableRTest, CallableArgumentTypeMismatch) {
-  static_assert(!base_internal::is_invocable_r<int, decltype(Function),
-                                               std::string, int>::value,
-                "Should be false for argument type mismatch");
-}
-
-TEST(IsInvocableRTest, CallableReturnTypeMismatch) {
-  static_assert(!base_internal::is_invocable_r<std::string, decltype(Function),
-                                               int, int>::value,
-                "Should be false for return type mismatch");
-}
-
-TEST(IsInvocableRTest, CallableTooFewArgs) {
-  static_assert(
-      !base_internal::is_invocable_r<int, decltype(Function), int>::value,
-      "Should be false for too few arguments");
-}
-
-TEST(IsInvocableRTest, CallableTooManyArgs) {
-  static_assert(!base_internal::is_invocable_r<int, decltype(Function), int,
-                                               int, int>::value,
-                "Should be false for too many arguments");
-}
-
-TEST(IsInvocableRTest, MemberFunctionAndReference) {
-  static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
-                                              Class&, int, int>::value,
-                "Should be true for exact match of types on a member function "
-                "and class reference");
-}
-
-TEST(IsInvocableRTest, MemberFunctionAndPointer) {
-  static_assert(base_internal::is_invocable_r<int, decltype(&Class::Method),
-                                              Class*, int, int>::value,
-                "Should be true for exact match of types on a member function "
-                "and class pointer");
-}
-
-TEST(IsInvocableRTest, DataMemberAndReference) {
-  static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
-                                              Class&>::value,
-                "Should be true for exact match of types on a data member and "
-                "class reference");
-}
-
-TEST(IsInvocableRTest, DataMemberAndPointer) {
-  static_assert(base_internal::is_invocable_r<int, decltype(&Class::member),
-                                              Class*>::value,
-                "Should be true for exact match of types on a data member and "
-                "class pointer");
-}
-
-TEST(IsInvocableRTest, CallableZeroArgs) {
-  static_assert(
-      base_internal::is_invocable_r<int, decltype(ZeroArgFunction)>::value,
-      "Should be true for exact match for a zero-arg free function");
-}
-
-}  // namespace
-}  // namespace base_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/base/macros.h b/absl/base/macros.h
index b318f11..ff89944 100644
--- a/absl/base/macros.h
+++ b/absl/base/macros.h
@@ -34,6 +34,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/optimization.h"
+#include "absl/base/options.h"
 #include "absl/base/port.h"
 
 // ABSL_ARRAYSIZE()
@@ -81,8 +82,9 @@
 // ABSL_ASSERT()
 //
 // In C++11, `assert` can't be used portably within constexpr functions.
+// `assert` also generates spurious unused-symbol warnings.
 // ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr
-// functions.  Example:
+// functions, and maintains references to symbols.  Example:
 //
 // constexpr double Divide(double a, double b) {
 //   return ABSL_ASSERT(b != 0), a / b;
@@ -91,8 +93,18 @@
 // This macro is inspired by
 // https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/
 #if defined(NDEBUG)
-#define ABSL_ASSERT(expr) \
-  (false ? static_cast<void>(expr) : static_cast<void>(0))
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+// We use `decltype` here to avoid generating unnecessary code that the
+// optimizer then has to optimize away.
+// This not only improves compilation performance by reducing codegen bloat
+// and optimization work, but also guarantees fast run-time performance without
+// having to rely on the optimizer.
+#define ABSL_ASSERT(expr) (decltype((expr) ? void() : void())())
+#else
+// Pre-C++20, lambdas can't be inside unevaluated operands, so we're forced to
+// rely on the optimizer.
+#define ABSL_ASSERT(expr) (false ? ((expr) ? void() : void()) : void())
+#endif
 #else
 #define ABSL_ASSERT(expr)                           \
   (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
@@ -120,7 +132,7 @@
 //
 // See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
 // hardened mode.
-#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
+#if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)
 #define ABSL_HARDENING_ASSERT(expr)                 \
   (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
                              : [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
@@ -128,6 +140,25 @@
 #define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr)
 #endif
 
+// ABSL_HARDENING_ASSERT_SLOW()
+//
+// `ABSL_HARDENING_ASSERT()` is like `ABSL_HARDENING_ASSERT()`,
+//  but specifically for assertions whose predicates are too slow
+//  to be enabled in many applications.
+//
+// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT_SLOW()` is identical to
+// `ABSL_ASSERT()`.
+//
+// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
+// hardened mode.
+#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
+#define ABSL_HARDENING_ASSERT_SLOW(expr)            \
+  (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
+                             : [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
+#else
+#define ABSL_HARDENING_ASSERT_SLOW(expr) ABSL_ASSERT(expr)
+#endif
+
 #ifdef ABSL_HAVE_EXCEPTIONS
 #define ABSL_INTERNAL_TRY try
 #define ABSL_INTERNAL_CATCH_ANY catch (...)
diff --git a/absl/base/no_destructor.h b/absl/base/no_destructor.h
index 43b3540..9d960ee 100644
--- a/absl/base/no_destructor.h
+++ b/absl/base/no_destructor.h
@@ -135,11 +135,11 @@
   // Pretend to be a smart pointer to T with deep constness.
   // Never returns a null pointer.
   T& operator*() { return *get(); }
-  absl::Nonnull<T*> operator->() { return get(); }
-  absl::Nonnull<T*> get() { return impl_.get(); }
+  T* absl_nonnull operator->() { return get(); }
+  T* absl_nonnull get() { return impl_.get(); }
   const T& operator*() const { return *get(); }
-  absl::Nonnull<const T*> operator->() const { return get(); }
-  absl::Nonnull<const T*> get() const { return impl_.get(); }
+  const T* absl_nonnull operator->() const { return get(); }
+  const T* absl_nonnull get() const { return impl_.get(); }
 
  private:
   class DirectImpl {
@@ -147,8 +147,8 @@
     template <typename... Args>
     explicit constexpr DirectImpl(Args&&... args)
         : value_(std::forward<Args>(args)...) {}
-    absl::Nonnull<const T*> get() const { return &value_; }
-    absl::Nonnull<T*> get() { return &value_; }
+    const T* absl_nonnull get() const { return &value_; }
+    T* absl_nonnull get() { return &value_; }
 
    private:
     T value_;
@@ -160,33 +160,14 @@
     explicit PlacementImpl(Args&&... args) {
       new (&space_) T(std::forward<Args>(args)...);
     }
-    absl::Nonnull<const T*> get() const {
-      return Launder(reinterpret_cast<const T*>(&space_));
+    const T* absl_nonnull get() const {
+      return std::launder(reinterpret_cast<const T*>(&space_));
     }
-    absl::Nonnull<T*> get() { return Launder(reinterpret_cast<T*>(&space_)); }
+    T* absl_nonnull get() {
+      return std::launder(reinterpret_cast<T*>(&space_));
+    }
 
    private:
-    template <typename P>
-    static absl::Nonnull<P*> Launder(absl::Nonnull<P*> p) {
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
-      return std::launder(p);
-#elif ABSL_HAVE_BUILTIN(__builtin_launder)
-      return __builtin_launder(p);
-#else
-      // When `std::launder` or equivalent are not available, we rely on
-      // undefined behavior, which works as intended on Abseil's officially
-      // supported platforms as of Q3 2023.
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
-      return p;
-#if defined(__GNUC__) && !defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-#endif
-    }
-
     alignas(T) unsigned char space_[sizeof(T)];
   };
 
@@ -199,12 +180,10 @@
       impl_;
 };
 
-#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
 // Provide 'Class Template Argument Deduction': the type of NoDestructor's T
 // will be the same type as the argument passed to NoDestructor's constructor.
 template <typename T>
 NoDestructor(T) -> NoDestructor<T>;
-#endif  // ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
 
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/no_destructor_test.cc b/absl/base/no_destructor_test.cc
index 71693c7..316b213 100644
--- a/absl/base/no_destructor_test.cc
+++ b/absl/base/no_destructor_test.cc
@@ -196,14 +196,10 @@
   EXPECT_EQ(0, Int());  // should get zero-initialized
 }
 
-#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
-// This would fail to compile if Class Template Argument Deduction was not
-// provided for absl::NoDestructor.
 TEST(NoDestructorTest, ClassTemplateArgumentDeduction) {
   absl::NoDestructor i(1);
   static_assert(std::is_same<decltype(i), absl::NoDestructor<int>>::value,
                 "Expected deduced type to be int.");
 }
-#endif
 
 }  // namespace
diff --git a/absl/base/nullability.h b/absl/base/nullability.h
index 34dc083..3a5d6e8 100644
--- a/absl/base/nullability.h
+++ b/absl/base/nullability.h
@@ -16,21 +16,21 @@
 // File: nullability.h
 // -----------------------------------------------------------------------------
 //
-// This header file defines a set of "templated annotations" for designating the
-// expected nullability of pointers. These annotations allow you to designate
-// pointers in one of three classification states:
+// This header file defines a set of annotations for designating the expected
+// nullability of pointers. These annotations allow you to designate pointers in
+// one of three classification states:
 //
-//  * "Non-null" (for pointers annotated `Nonnull<T>`), indicating that it is
+//  * "Non-null" (for pointers annotated `absl_nonnull`), indicating that it is
 //    invalid for the given pointer to ever be null.
-//  * "Nullable" (for pointers annotated `Nullable<T>`), indicating that it is
+//  * "Nullable" (for pointers annotated `absl_nullable`), indicating that it is
 //    valid for the given pointer to be null.
-//  * "Unknown" (for pointers annotated `NullabilityUnknown<T>`), indicating
-//    that the given pointer has not been yet classified as either nullable or
+//  * "Unknown" (for pointers annotated `absl_nullability_unknown`), indicating
+//    that the given pointer has not yet been classified as either nullable or
 //    non-null. This is the default state of unannotated pointers.
 //
-// NOTE: unannotated pointers implicitly bear the annotation
-// `NullabilityUnknown<T>`; you should rarely, if ever, see this annotation used
-// in the codebase explicitly.
+// NOTE: Unannotated pointers implicitly bear the annotation
+// `absl_nullability_unknown`; you should rarely, if ever, see this annotation
+// used in the codebase explicitly.
 //
 // -----------------------------------------------------------------------------
 // Nullability and Contracts
@@ -64,16 +64,49 @@
 // formalize those contracts within the codebase.
 //
 // -----------------------------------------------------------------------------
+// Annotation Syntax
+// -----------------------------------------------------------------------------
+//
+// The annotations should be positioned as a qualifier for the pointer type. For
+// example, the position of `const` when declaring a const pointer (not a
+// pointer to a const type) is the position you should also use for these
+// annotations.
+//
+// Example:
+//
+// // A const non-null pointer to an `Employee`.
+// Employee* absl_nonnull const e;
+//
+// // A non-null pointer to a const `Employee`.
+// const Employee* absl_nonnull e;
+//
+// // A non-null pointer to a const nullable pointer to an `Employee`.
+// Employee* absl_nullable const* absl_nonnull e = nullptr;
+//
+// // A non-null function pointer.
+// void (*absl_nonnull func)(int, double);
+//
+// // A non-null array of `Employee`s as a parameter.
+// void func(Employee employees[absl_nonnull]);
+//
+// // A non-null std::unique_ptr to an `Employee`.
+// // As with `const`, it is possible to place the annotation on either side of
+// // a named type not ending in `*`, but placing it before the type it
+// // describes is preferred, unless inconsistent with surrounding code.
+// absl_nonnull std::unique_ptr<Employee> employee;
+//
+// // Invalid annotation usage – this attempts to declare a pointer to a
+// // nullable `Employee`, which is meaningless.
+// absl_nullable Employee* e;
+//
+// -----------------------------------------------------------------------------
 // Using Nullability Annotations
 // -----------------------------------------------------------------------------
 //
-// It is important to note that these annotations are not distinct strong
-// *types*. They are alias templates defined to be equal to the underlying
-// pointer type. A pointer annotated `Nonnull<T*>`, for example, is simply a
-// pointer of type `T*`. Each annotation acts as a form of documentation about
-// the contract for the given pointer. Each annotation requires providers or
-// consumers of these pointers across API boundaries to take appropriate steps
-// when setting or using these pointers:
+// Each annotation acts as a form of documentation about the contract for the
+// given pointer. Each annotation requires providers or consumers of these
+// pointers across API boundaries to take appropriate steps when setting or
+// using these pointers:
 //
 // * "Non-null" pointers should never be null. It is the responsibility of the
 //   provider of this pointer to ensure that the pointer may never be set to
@@ -91,20 +124,20 @@
 // Example:
 //
 // // PaySalary() requires the passed pointer to an `Employee` to be non-null.
-// void PaySalary(absl::Nonnull<Employee *> e) {
+// void PaySalary(Employee* absl_nonnull e) {
 //   pay(e->salary);  // OK to dereference
 // }
 //
 // // CompleteTransaction() guarantees the returned pointer to an `Account` to
 // // be non-null.
-// absl::Nonnull<Account *> balance CompleteTransaction(double fee) {
+// Account* absl_nonnull balance CompleteTransaction(double fee) {
 // ...
 // }
 //
 // // Note that specifying a nullability annotation does not prevent someone
 // // from violating the contract:
 //
-// Nullable<Employee *> find(Map& employees, std::string_view name);
+// Employee* absl_nullable find(Map& employees, std::string_view name);
 //
 // void g(Map& employees) {
 //   Employee *e = find(employees, "Pat");
@@ -135,36 +168,64 @@
 //   ...
 // };
 //
-// Note: For the time being, nullability-compatible classes should additionally
-// be marked with an `absl_nullability_compatible` nested type (this will soon
-// be deprecated). The actual definition of this inner type is not relevant as
-// it is used merely as a marker. It is common to use a using declaration of
-// `absl_nullability_compatible` set to void.
-//
-// // Example:
-// struct MyPtr {
-//   using absl_nullability_compatible = void;
-//   ...
-// };
+// Note: Compilers that don't support the `nullability_on_classes` feature will
+// allow nullability annotations to be applied to any type, not just ones
+// marked with `ABSL_NULLABILITY_COMPATIBLE`.
 //
 // DISCLAIMER:
 // ===========================================================================
 // These nullability annotations are primarily a human readable signal about the
 // intended contract of the pointer. They are not *types* and do not currently
 // provide any correctness guarantees. For example, a pointer annotated as
-// `Nonnull<T*>` is *not guaranteed* to be non-null, and the compiler won't
-// alert or prevent assignment of a `Nullable<T*>` to a `Nonnull<T*>`.
+// `absl_nonnull` is *not guaranteed* to be non-null, and the compiler won't
+// alert or prevent assignment of a `T* absl_nullable` to a `T* absl_nonnull`.
 // ===========================================================================
 #ifndef ABSL_BASE_NULLABILITY_H_
 #define ABSL_BASE_NULLABILITY_H_
 
 #include "absl/base/config.h"
-#include "absl/base/internal/nullability_impl.h"
+#include "absl/base/internal/nullability_deprecated.h"
 
-namespace absl {
-ABSL_NAMESPACE_BEGIN
+// ABSL_POINTERS_DEFAULT_NONNULL
+//
+// This macro specifies that all unannotated pointer types within the given
+// file are designated as nonnull (instead of the default "unknown"). This macro
+// exists as a standalone statement and applies default nonnull behavior to all
+// subsequent pointers; as a result, place this macro as the first non-comment,
+// non-`#include` line in a file.
+//
+// Example:
+//
+//     #include "absl/base/nullability.h"
+//
+//     ABSL_POINTERS_DEFAULT_NONNULL
+//
+//     void FillMessage(Message *m);                  // implicitly non-null
+//     T* absl_nullable GetNullablePtr();           // explicitly nullable
+//     T* absl_nullability_unknown GetUnknownPtr();  // explicitly unknown
+//
+// The macro can be safely used in header files – it will not affect any files
+// that include it.
+//
+// In files with the macro, plain `T*` syntax means `T* absl_nonnull`, and the
+// exceptions (`absl_nullable` and `absl_nullability_unknown`) must be marked
+// explicitly. The same holds, correspondingly, for smart pointer types.
+//
+// For comparison, without the macro, all unannotated pointers would default to
+// unknown, and otherwise require explicit annotations to change this behavior:
+//
+//     #include "absl/base/nullability.h"
+//
+//     void FillMessage(Message* absl_nonnull m);  // explicitly non-null
+//     T* absl_nullable GetNullablePtr();          // explicitly nullable
+//     T* GetUnknownPtr();                           // implicitly unknown
+//
+// No-op except for being a human readable signal.
+#define ABSL_POINTERS_DEFAULT_NONNULL
 
-// absl::Nonnull
+#if defined(__clang__) && !defined(__OBJC__) && \
+    ABSL_HAVE_FEATURE(nullability_on_classes)
+// absl_nonnull (default with `ABSL_POINTERS_DEFAULT_NONNULL`)
 //
 // The indicated pointer is never null. It is the responsibility of the provider
 // of this pointer across an API boundary to ensure that the pointer is never
@@ -174,13 +235,12 @@
 // Example:
 //
 // // `employee` is designated as not null.
-// void PaySalary(absl::Nonnull<Employee *> employee) {
+// void PaySalary(Employee* absl_nonnull employee) {
 //   pay(*employee);  // OK to dereference
 // }
-template <typename T>
-using Nonnull = nullability_internal::NonnullImpl<T>;
+#define absl_nonnull _Nonnull
 
-// absl::Nullable
+// absl_nullable
 //
 // The indicated pointer may, by design, be either null or non-null. Consumers
 // of this pointer across an API boundary should perform a `nullptr` check
@@ -189,15 +249,14 @@
 // Example:
 //
 // // `employee` may  be null.
-// void PaySalary(absl::Nullable<Employee *> employee) {
+// void PaySalary(Employee* absl_nullable employee) {
 //   if (employee != nullptr) {
 //     Pay(*employee);  // OK to dereference
 //   }
 // }
-template <typename T>
-using Nullable = nullability_internal::NullableImpl<T>;
+#define absl_nullable _Nullable
 
-// absl::NullabilityUnknown (default)
+// absl_nullability_unknown  (default without `ABSL_POINTERS_DEFAULT_NONNULL`)
 //
 // The indicated pointer has not yet been determined to be definitively
 // "non-null" or "nullable." Providers of such pointers across API boundaries
@@ -205,17 +264,18 @@
 // Consumers of these pointers across an API boundary should treat such pointers
 // with the same caution they treat currently unannotated pointers. Most
 // existing code will have "unknown"  pointers, which should eventually be
-// migrated into one of the above two nullability states: `Nonnull<T>` or
-//  `Nullable<T>`.
+// migrated into one of the above two nullability states: `absl_nonnull` or
+//  `absl_nullable`.
 //
-// NOTE: Because this annotation is the global default state, unannotated
-// pointers are assumed to have "unknown" semantics. This assumption is designed
-// to minimize churn and reduce clutter within the codebase.
+// NOTE: For files that do not specify `ABSL_POINTERS_DEFAULT_NONNULL`,
+// because this annotation is the global default state, unannotated pointers are
+// are assumed to have "unknown" semantics. This assumption is designed to
+// minimize churn and reduce clutter within the codebase.
 //
 // Example:
 //
 // // `employee`s nullability state is unknown.
-// void PaySalary(absl::NullabilityUnknown<Employee *> employee) {
+// void PaySalary(Employee* absl_nullability_unknown employee) {
 //   Pay(*employee); // Potentially dangerous. API provider should investigate.
 // }
 //
@@ -226,11 +286,15 @@
 // void PaySalary(Employee* employee) {
 //   Pay(*employee); // Potentially dangerous. API provider should investigate.
 // }
-template <typename T>
-using NullabilityUnknown = nullability_internal::NullabilityUnknownImpl<T>;
-
-ABSL_NAMESPACE_END
-}  // namespace absl
+#define absl_nullability_unknown _Null_unspecified
+#else
+// No-op for non-Clang compilers or Objective-C.
+#define absl_nonnull
+// No-op for non-Clang compilers or Objective-C.
+#define absl_nullable
+// No-op for non-Clang compilers or Objective-C.
+#define absl_nullability_unknown
+#endif
 
 // ABSL_NULLABILITY_COMPATIBLE
 //
@@ -241,6 +305,10 @@
 // struct ABSL_NULLABILITY_COMPATIBLE MyPtr {
 //   ...
 // };
+//
+// Note: Compilers that don't support the `nullability_on_classes` feature will
+// allow nullability annotations to be applied to any type, not just ones marked
+// with `ABSL_NULLABILITY_COMPATIBLE`.
 #if ABSL_HAVE_FEATURE(nullability_on_classes)
 #define ABSL_NULLABILITY_COMPATIBLE _Nullable
 #else
diff --git a/absl/base/nullability_default_nonnull_test.cc b/absl/base/nullability_default_nonnull_test.cc
new file mode 100644
index 0000000..bd5b483
--- /dev/null
+++ b/absl/base/nullability_default_nonnull_test.cc
@@ -0,0 +1,44 @@
+// Copyright 2024 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 <cassert>
+
+#include "gtest/gtest.h"
+#include "absl/base/nullability.h"
+
+ABSL_POINTERS_DEFAULT_NONNULL
+
+namespace {
+
+void FuncWithDefaultNonnullArg(int* /*arg*/) {}
+template <typename T>
+void FuncWithDeducedDefaultNonnullArg(T* /*arg*/) {}
+
+TEST(DefaultNonnullTest, NonnullArgument) {
+  int var = 0;
+  FuncWithDefaultNonnullArg(&var);
+  FuncWithDeducedDefaultNonnullArg<int>(&var);
+}
+
+int* FuncWithDefaultNonnullReturn() {
+  static int var = 0;
+  return &var;
+}
+
+TEST(DefaultNonnullTest, NonnullReturn) {
+  auto var = FuncWithDefaultNonnullReturn();
+  (void)var;
+}
+
+}  // namespace
diff --git a/absl/base/nullability_test.cc b/absl/base/nullability_test.cc
index 028ea6c..bccc388 100644
--- a/absl/base/nullability_test.cc
+++ b/absl/base/nullability_test.cc
@@ -16,15 +16,89 @@
 
 #include <cassert>
 #include <memory>
+#include <type_traits>
 #include <utility>
 
 #include "gtest/gtest.h"
 #include "absl/base/attributes.h"
 
 namespace {
+namespace macro_annotations {
+void funcWithNonnullArg(int* absl_nonnull /*arg*/) {}
+template <typename T>
+void funcWithDeducedNonnullArg(T* absl_nonnull /*arg*/) {}
+
+TEST(NonnullTest, NonnullArgument) {
+  int var = 0;
+  funcWithNonnullArg(&var);
+  funcWithDeducedNonnullArg(&var);
+}
+
+int* absl_nonnull funcWithNonnullReturn() {
+  static int var = 0;
+  return &var;
+}
+
+TEST(NonnullTest, NonnullReturn) {
+  auto var = funcWithNonnullReturn();
+  (void)var;
+}
+
+TEST(PassThroughTest, PassesThroughRawPointerToInt) {
+  EXPECT_TRUE((std::is_same<int* absl_nonnull, int*>::value));
+  EXPECT_TRUE((std::is_same<int* absl_nullable, int*>::value));
+  EXPECT_TRUE((std::is_same<int* absl_nullability_unknown, int*>::value));
+}
+
+TEST(PassThroughTest, PassesThroughRawPointerToVoid) {
+  EXPECT_TRUE((std::is_same<void* absl_nonnull, void*>::value));
+  EXPECT_TRUE((std::is_same<void* absl_nullable, void*>::value));
+  EXPECT_TRUE((std::is_same<void* absl_nullability_unknown, void*>::value));
+}
+
+TEST(PassThroughTest, PassesThroughUniquePointerToInt) {
+  using T = std::unique_ptr<int>;
+  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughSharedPointerToInt) {
+  using T = std::shared_ptr<int>;
+  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughSharedPointerToVoid) {
+  using T = std::shared_ptr<void>;
+  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughPointerToMemberObject) {
+  using T = decltype(&std::pair<int, int>::first);
+  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
+}
+
+TEST(PassThroughTest, PassesThroughPointerToMemberFunction) {
+  using T = decltype(&std::unique_ptr<int>::reset);
+  EXPECT_TRUE((std::is_same<absl_nonnull T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullable T, T>::value));
+  EXPECT_TRUE((std::is_same<absl_nullability_unknown T, T>::value));
+}
+}  // namespace macro_annotations
+
+// Allow testing of the deprecated type alias annotations.
+ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
+
 using ::absl::Nonnull;
 using ::absl::NullabilityUnknown;
 using ::absl::Nullable;
+namespace type_alias_annotations {
 
 void funcWithNonnullArg(Nonnull<int*> /*arg*/) {}
 template <typename T>
@@ -93,6 +167,7 @@
   EXPECT_TRUE((std::is_same<NullabilityUnknown<T>, T>::value));
 }
 
+}  // namespace type_alias_annotations
 }  // namespace
 
 // Nullable ADL lookup test
@@ -126,4 +201,6 @@
   EXPECT_TRUE(DidAdlWin((util::MakeAdlWin*)nullptr));
   EXPECT_TRUE(DidAdlWin((Nullable<util::MakeAdlWin*>)nullptr));
 }
+
+ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
 }  // namespace
diff --git a/absl/base/optimization.h b/absl/base/optimization.h
index 3aa66e1..429ea9c 100644
--- a/absl/base/optimization.h
+++ b/absl/base/optimization.h
@@ -25,6 +25,8 @@
 // new code that requires C compatibility or assume C compatibility will remain
 // indefinitely.
 
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
 #ifndef ABSL_BASE_OPTIMIZATION_H_
 #define ABSL_BASE_OPTIMIZATION_H_
 
@@ -271,20 +273,14 @@
 #elif defined(_MSC_VER)
 #define ABSL_ASSUME(cond) __assume(cond)
 #elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
-#define ABSL_ASSUME(cond)            \
-  do {                               \
-    if (!(cond)) std::unreachable(); \
-  } while (false)
+#define ABSL_ASSUME(cond) ((cond) ? void() : std::unreachable())
 #elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
-#define ABSL_ASSUME(cond)                 \
-  do {                                    \
-    if (!(cond)) __builtin_unreachable(); \
-  } while (false)
+#define ABSL_ASSUME(cond) ((cond) ? void() : __builtin_unreachable())
+#elif ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+// Unimplemented. Uses the same definition as ABSL_ASSERT in the NDEBUG case.
+#define ABSL_ASSUME(expr) (decltype((expr) ? void() : void())())
 #else
-#define ABSL_ASSUME(cond)               \
-  do {                                  \
-    static_cast<void>(false && (cond)); \
-  } while (false)
+#define ABSL_ASSUME(expr) (false ? ((expr) ? void() : void()) : void())
 #endif
 
 // ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
diff --git a/absl/base/optimization_test.cc b/absl/base/optimization_test.cc
index e83369f..b47b11a 100644
--- a/absl/base/optimization_test.cc
+++ b/absl/base/optimization_test.cc
@@ -88,9 +88,9 @@
   EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
 }
 
-class ImplictlyConvertibleToBool {
+class ImplicitlyConvertibleToBool {
  public:
-  explicit ImplictlyConvertibleToBool(bool value) : value_(value) {}
+  explicit ImplicitlyConvertibleToBool(bool value) : value_(value) {}
   operator bool() const {  // NOLINT(google-explicit-constructor)
     return value_;
   }
@@ -100,17 +100,17 @@
 };
 
 TEST(PredictTest, ImplicitBoolConversion) {
-  const ImplictlyConvertibleToBool is_true(true);
-  const ImplictlyConvertibleToBool is_false(false);
+  const ImplicitlyConvertibleToBool is_true(true);
+  const ImplicitlyConvertibleToBool is_false(false);
   if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
   if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
   if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
   if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
 }
 
-class ExplictlyConvertibleToBool {
+class ExplicitlyConvertibleToBool {
  public:
-  explicit ExplictlyConvertibleToBool(bool value) : value_(value) {}
+  explicit ExplicitlyConvertibleToBool(bool value) : value_(value) {}
   explicit operator bool() const { return value_; }
 
  private:
@@ -118,12 +118,24 @@
 };
 
 TEST(PredictTest, ExplicitBoolConversion) {
-  const ExplictlyConvertibleToBool is_true(true);
-  const ExplictlyConvertibleToBool is_false(false);
+  const ExplicitlyConvertibleToBool is_true(true);
+  const ExplicitlyConvertibleToBool is_false(false);
   if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
   if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
   if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
   if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
 }
 
+// This verifies that ABSL_ASSUME compiles in a variety of contexts.
+// It does not test optimization.
+TEST(AbslAssume, Compiles) {
+  int x = 0;
+  ABSL_ASSUME(x >= 0);
+  EXPECT_EQ(x, 0);
+
+  // https://github.com/abseil/abseil-cpp/issues/1814
+  ABSL_ASSUME(x >= 0), (x >= 0) ? ++x : --x;
+  EXPECT_EQ(x, 1);
+}
+
 }  // namespace
diff --git a/absl/base/options.h b/absl/base/options.h
index 3ea6045..cba75b9 100644
--- a/absl/base/options.h
+++ b/absl/base/options.h
@@ -64,65 +64,14 @@
 // proper Abseil implementation at compile-time, which will not be sufficient
 // to guarantee ABI stability to package managers.
 
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
 #ifndef ABSL_BASE_OPTIONS_H_
 #define ABSL_BASE_OPTIONS_H_
 
 // -----------------------------------------------------------------------------
 // Type Compatibility Options
 // -----------------------------------------------------------------------------
-//
-// ABSL_OPTION_USE_STD_ANY
-//
-// This option controls whether absl::any is implemented as an alias to
-// std::any, or as an independent implementation.
-//
-// A value of 0 means to use Abseil's implementation.  This requires only C++11
-// support, and is expected to work on every toolchain we support.
-//
-// A value of 1 means to use an alias to std::any.  This requires that all code
-// using Abseil is built in C++17 mode or later.
-//
-// A value of 2 means to detect the C++ version being used to compile Abseil,
-// and use an alias only if a working std::any is available.  This option is
-// useful when you are building your entire program, including all of its
-// dependencies, from source.  It should not be used otherwise -- for example,
-// if you are distributing Abseil in a binary package manager -- since in
-// mode 2, absl::any will name a different type, with a different mangled name
-// and binary layout, depending on the compiler flags passed by the end user.
-// For more info, see https://abseil.io/about/design/dropin-types.
-//
-// User code should not inspect this macro.  To check in the preprocessor if
-// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY.
-
-#define ABSL_OPTION_USE_STD_ANY 1
-
-
-// ABSL_OPTION_USE_STD_OPTIONAL
-//
-// This option controls whether absl::optional is implemented as an alias to
-// std::optional, or as an independent implementation.
-//
-// A value of 0 means to use Abseil's implementation.  This requires only C++11
-// support, and is expected to work on every toolchain we support.
-//
-// A value of 1 means to use an alias to std::optional.  This requires that all
-// code using Abseil is built in C++17 mode or later.
-//
-// A value of 2 means to detect the C++ version being used to compile Abseil,
-// and use an alias only if a working std::optional is available.  This option
-// is useful when you are building your program from source.  It should not be
-// used otherwise -- for example, if you are distributing Abseil in a binary
-// package manager -- since in mode 2, absl::optional will name a different
-// type, with a different mangled name and binary layout, depending on the
-// compiler flags passed by the end user.  For more info, see
-// https://abseil.io/about/design/dropin-types.
-
-// User code should not inspect this macro.  To check in the preprocessor if
-// absl::optional is a typedef of std::optional, use the feature macro
-// ABSL_USES_STD_OPTIONAL.
-
-#define ABSL_OPTION_USE_STD_OPTIONAL 1
-
 
 // ABSL_OPTION_USE_STD_STRING_VIEW
 //
@@ -150,32 +99,6 @@
 
 #define ABSL_OPTION_USE_STD_STRING_VIEW 1
 
-// ABSL_OPTION_USE_STD_VARIANT
-//
-// This option controls whether absl::variant is implemented as an alias to
-// std::variant, or as an independent implementation.
-//
-// A value of 0 means to use Abseil's implementation.  This requires only C++11
-// support, and is expected to work on every toolchain we support.
-//
-// A value of 1 means to use an alias to std::variant.  This requires that all
-// code using Abseil is built in C++17 mode or later.
-//
-// A value of 2 means to detect the C++ version being used to compile Abseil,
-// and use an alias only if a working std::variant is available.  This option
-// is useful when you are building your program from source.  It should not be
-// used otherwise -- for example, if you are distributing Abseil in a binary
-// package manager -- since in mode 2, absl::variant will name a different
-// type, with a different mangled name and binary layout, depending on the
-// compiler flags passed by the end user.  For more info, see
-// https://abseil.io/about/design/dropin-types.
-//
-// User code should not inspect this macro.  To check in the preprocessor if
-// absl::variant is a typedef of std::variant, use the feature macro
-// ABSL_USES_STD_VARIANT.
-
-#define ABSL_OPTION_USE_STD_VARIANT 1
-
 // ABSL_OPTION_USE_STD_ORDERING
 //
 // This option controls whether absl::{partial,weak,strong}_ordering are
@@ -226,7 +149,11 @@
 // allowed.
 
 #define ABSL_OPTION_USE_INLINE_NAMESPACE 1
-#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20240722
+#ifdef ANDROID_DISABLE_TLS_FOR_LINKER
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20250512_notls
+#else
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20250512
+#endif
 
 // ABSL_OPTION_HARDENED
 //
@@ -235,7 +162,10 @@
 //
 // A value of 0 means that "hardened" mode is not enabled.
 //
-// A value of 1 means that "hardened" mode is enabled.
+// A value of 1 means that "hardened" mode is enabled with all checks.
+//
+// A value of 2 means that "hardened" mode is partially enabled, with
+// only a subset of checks chosen to minimize performance impact.
 //
 // Hardened builds have additional security checks enabled when `NDEBUG` is
 // defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a
diff --git a/absl/base/policy_checks.h b/absl/base/policy_checks.h
index 372e848..f84944c 100644
--- a/absl/base/policy_checks.h
+++ b/absl/base/policy_checks.h
@@ -21,6 +21,8 @@
 // reported with `#error`. This enforcement is best effort, so successfully
 // compiling this header does not guarantee a supported configuration.
 
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
 #ifndef ABSL_BASE_POLICY_CHECKS_H_
 #define ABSL_BASE_POLICY_CHECKS_H_
 
@@ -69,15 +71,15 @@
 // C++ Version Check
 // -----------------------------------------------------------------------------
 
-// Enforce C++14 as the minimum.
+// Enforce C++17 as the minimum.
 #if defined(_MSVC_LANG)
-#if _MSVC_LANG < 201402L
-#error "C++ versions less than C++14 are not supported."
-#endif  // _MSVC_LANG < 201402L
+#if _MSVC_LANG < 201703L
+#error "C++ versions less than C++17 are not supported."
+#endif  // _MSVC_LANG < 201703L
 #elif defined(__cplusplus)
-#if __cplusplus < 201402L
-#error "C++ versions less than C++14 are not supported."
-#endif  // __cplusplus < 201402L
+#if __cplusplus < 201703L
+#error "C++ versions less than C++17 are not supported."
+#endif  // __cplusplus < 201703L
 #endif
 
 // -----------------------------------------------------------------------------
diff --git a/absl/base/raw_logging_test.cc b/absl/base/raw_logging_test.cc
index 3d30bd3..f4f3445 100644
--- a/absl/base/raw_logging_test.cc
+++ b/absl/base/raw_logging_test.cc
@@ -35,16 +35,35 @@
   ABSL_RAW_LOG(ERROR, "RAW ERROR: %d", 1);
 }
 
+TEST(RawLoggingCompilationTest, LogWithNulls) {
+  ABSL_RAW_LOG(INFO, "RAW INFO: %s%c%s", "Hello", 0, "World");
+}
+
 TEST(RawLoggingCompilationTest, PassingCheck) {
   ABSL_RAW_CHECK(true, "RAW CHECK");
 }
 
+TEST(RawLoggingCompilationTest, DebugLog) {
+  ABSL_RAW_DLOG(INFO, "RAW DLOG: %d", 1);
+}
+
+TEST(RawLoggingCompilationTest, PassingDebugCheck) {
+  ABSL_RAW_DCHECK(true, "failure message");
+}
+
 // Not all platforms support output from raw log, so we don't verify any
 // particular output for RAW check failures (expecting the empty string
 // accomplishes this).  This test is primarily a compilation test, but we
 // are verifying process death when EXPECT_DEATH works for a platform.
 const char kExpectedDeathOutput[] = "";
 
+#if !defined(NDEBUG)  // if debug build
+TEST(RawLoggingDeathTest, FailingDebugCheck) {
+  EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_DCHECK(1 == 0, "explanation"),
+                            kExpectedDeathOutput);
+}
+#endif  // if debug build
+
 TEST(RawLoggingDeathTest, FailingCheck) {
   EXPECT_DEATH_IF_SUPPORTED(ABSL_RAW_CHECK(1 == 0, "explanation"),
                             kExpectedDeathOutput);
diff --git a/absl/cleanup/BUILD.bazel b/absl/cleanup/BUILD.bazel
index 984d571..d579781 100644
--- a/absl/cleanup/BUILD.bazel
+++ b/absl/cleanup/BUILD.bazel
@@ -36,7 +36,6 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        "//absl/base:base_internal",
         "//absl/base:core_headers",
         "//absl/utility",
     ],
@@ -67,7 +66,7 @@
         ":cleanup",
         "//absl/base:config",
         "//absl/utility",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/cleanup/CMakeLists.txt b/absl/cleanup/CMakeLists.txt
index f5af40b..eedf449 100644
--- a/absl/cleanup/CMakeLists.txt
+++ b/absl/cleanup/CMakeLists.txt
@@ -21,7 +21,6 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::base_internal
     absl::core_headers
     absl::utility
   PUBLIC
diff --git a/absl/cleanup/cleanup.h b/absl/cleanup/cleanup.h
index 960ccd0..311e482 100644
--- a/absl/cleanup/cleanup.h
+++ b/absl/cleanup/cleanup.h
@@ -78,7 +78,7 @@
 ABSL_NAMESPACE_BEGIN
 
 template <typename Arg, typename Callback = void()>
-class ABSL_MUST_USE_RESULT Cleanup final {
+class [[nodiscard]] Cleanup final {
   static_assert(cleanup_internal::WasDeduced<Arg>(),
                 "Explicit template parameters are not supported.");
 
@@ -115,10 +115,8 @@
 // `absl::Cleanup c = /* callback */;`
 //
 // C++17 type deduction API for creating an instance of `absl::Cleanup`
-#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
 template <typename Callback>
 Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;
-#endif  // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
 
 // `auto c = absl::MakeCleanup(/* callback */);`
 //
diff --git a/absl/cleanup/cleanup_test.cc b/absl/cleanup/cleanup_test.cc
index 72d7ff2..52774d7 100644
--- a/absl/cleanup/cleanup_test.cc
+++ b/absl/cleanup/cleanup_test.cc
@@ -116,7 +116,6 @@
   }
 }
 
-#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
 TYPED_TEST(CleanupTest, CTADProducesCorrectType) {
   {
     auto callback = TypeParam::AsCallback([] {});
@@ -186,7 +185,6 @@
         IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
   }
 }
-#endif  // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
 
 TYPED_TEST(CleanupTest, BasicUsage) {
   bool called = false;
diff --git a/absl/cleanup/internal/cleanup.h b/absl/cleanup/internal/cleanup.h
index 2783fcb..4dd6f91 100644
--- a/absl/cleanup/internal/cleanup.h
+++ b/absl/cleanup/internal/cleanup.h
@@ -19,7 +19,6 @@
 #include <type_traits>
 #include <utility>
 
-#include "absl/base/internal/invoke.h"
 #include "absl/base/macros.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/utility/utility.h"
@@ -39,7 +38,7 @@
 
 template <typename Callback>
 constexpr bool ReturnsVoid() {
-  return (std::is_same<base_internal::invoke_result_t<Callback>, void>::value);
+  return (std::is_same<std::invoke_result_t<Callback>, void>::value);
 }
 
 template <typename Callback>
@@ -70,7 +69,7 @@
 
   Storage& operator=(const Storage& other) = delete;
 
-  void* GetCallbackBuffer() { return static_cast<void*>(+callback_buffer_); }
+  void* GetCallbackBuffer() { return static_cast<void*>(callback_buffer_); }
 
   Callback& GetCallback() {
     return *reinterpret_cast<Callback*>(GetCallbackBuffer());
@@ -89,7 +88,7 @@
 
  private:
   bool is_callback_engaged_;
-  alignas(Callback) char callback_buffer_[sizeof(Callback)];
+  alignas(Callback) unsigned char callback_buffer_[sizeof(Callback)];
 };
 
 }  // namespace cleanup_internal
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index b00c30f..61e816f 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -54,8 +54,8 @@
         "//absl/types:any",
         "//absl/types:optional",
         "//absl/utility",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -70,7 +70,9 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
+        "//absl/base:iterator_traits_internal",
         "//absl/base:throw_delegate",
+        "//absl/hash:weakly_mixed_integer",
         "//absl/memory",
     ],
 )
@@ -85,10 +87,11 @@
         ":test_allocator",
         "//absl/base:config",
         "//absl/base:exception_testing",
+        "//absl/base:iterator_traits_test_helper",
         "//absl/hash:hash_testing",
         "//absl/memory",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -101,8 +104,8 @@
         ":fixed_array",
         "//absl/base:config",
         "//absl/base:exception_safety_testing",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -115,7 +118,7 @@
     tags = ["benchmark"],
     deps = [
         ":fixed_array",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -144,7 +147,9 @@
         ":inlined_vector_internal",
         "//absl/algorithm",
         "//absl/base:core_headers",
+        "//absl/base:iterator_traits_internal",
         "//absl/base:throw_delegate",
+        "//absl/hash:weakly_mixed_integer",
         "//absl/memory",
         "//absl/meta:type_traits",
     ],
@@ -171,12 +176,13 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:exception_testing",
+        "//absl/base:iterator_traits_test_helper",
         "//absl/hash:hash_testing",
         "//absl/log:check",
         "//absl/memory",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -192,7 +198,7 @@
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/strings",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -204,8 +210,8 @@
         ":inlined_vector",
         "//absl/base:config",
         "//absl/base:exception_safety_testing",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -229,8 +235,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":test_instance_tracker",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -275,8 +281,8 @@
         "//absl/log:check",
         "//absl/meta:type_traits",
         "//absl/types:any",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -305,6 +311,7 @@
     deps = [
         ":container_memory",
         ":flat_hash_set",
+        ":hash_container_defaults",
         ":hash_generator_testing",
         ":test_allocator",
         ":unordered_set_constructor_test",
@@ -312,11 +319,12 @@
         ":unordered_set_members_test",
         ":unordered_set_modifiers_test",
         "//absl/base:config",
+        "//absl/hash",
         "//absl/log:check",
         "//absl/memory",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -352,8 +360,8 @@
         ":unordered_map_members_test",
         ":unordered_map_modifiers_test",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -390,8 +398,8 @@
         ":unordered_set_modifiers_test",
         "//absl/base:config",
         "//absl/memory",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -420,8 +428,8 @@
         "//absl/base:no_destructor",
         "//absl/meta:type_traits",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -469,8 +477,8 @@
         "//absl/strings",
         "//absl/strings:cord",
         "//absl/strings:cord_test_helpers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -486,6 +494,7 @@
         "//absl/base:no_destructor",
         "//absl/memory",
         "//absl/meta:type_traits",
+        "//absl/random",
         "//absl/strings",
     ],
 )
@@ -509,8 +518,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":hash_policy_testing",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -533,8 +542,8 @@
     deps = [
         ":container_memory",
         ":hash_policy_traits",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -555,8 +564,8 @@
     deps = [
         ":common_policy_traits",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -617,11 +626,12 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/profiling:sample_recorder",
+        "//absl/random",
         "//absl/synchronization",
         "//absl/synchronization:thread_pool",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -642,8 +652,8 @@
         ":hash_policy_traits",
         ":node_slot_policy",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -653,11 +663,13 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":common_policy_traits",
         ":container_memory",
         ":raw_hash_set",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:throw_delegate",
+        "//absl/meta:type_traits",
     ],
 )
 
@@ -673,6 +685,40 @@
 )
 
 cc_library(
+    name = "hashtable_control_bytes",
+    hdrs = ["internal/hashtable_control_bytes.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:endian",
+        "//absl/numeric:bits",
+    ],
+)
+
+cc_library(
+    name = "raw_hash_set_resize_impl",
+    hdrs = ["internal/raw_hash_set_resize_impl.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = ["//absl/base:config"],
+)
+
+cc_test(
+    name = "raw_hash_set_resize_impl_test",
+    srcs = ["internal/raw_hash_set_resize_impl_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":raw_hash_set_resize_impl",
+        "//absl/base:config",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_library(
     name = "raw_hash_set",
     srcs = ["internal/raw_hash_set.cc"],
     hdrs = ["internal/raw_hash_set.h"],
@@ -680,18 +726,25 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":common",
+        ":common_policy_traits",
         ":compressed_tuple",
         ":container_memory",
+        ":hash_function_defaults",
         ":hash_policy_traits",
+        ":hashtable_control_bytes",
         ":hashtable_debug_hooks",
         ":hashtablez_sampler",
+        ":raw_hash_set_resize_impl",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
         "//absl/base:endian",
+        "//absl/base:iterator_traits_internal",
         "//absl/base:prefetch",
         "//absl/base:raw_logging_internal",
+        "//absl/functional:function_ref",
         "//absl/hash",
+        "//absl/hash:weakly_mixed_integer",
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/numeric:bits",
@@ -715,10 +768,12 @@
         ":flat_hash_set",
         ":hash_function_defaults",
         ":hash_policy_testing",
+        ":hashtable_control_bytes",
         ":hashtable_debug",
         ":hashtablez_sampler",
         ":node_hash_set",
         ":raw_hash_set",
+        ":raw_hash_set_resize_impl",
         ":test_allocator",
         ":test_instance_tracker",
         "//absl/base",
@@ -731,9 +786,12 @@
         "//absl/log:check",
         "//absl/memory",
         "//absl/meta:type_traits",
+        "//absl/numeric:int128",
+        "//absl/random",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "//absl/types:optional",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -752,7 +810,7 @@
         "//absl/base:raw_logging_internal",
         "//absl/random",
         "//absl/strings:str_format",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -791,8 +849,8 @@
         ":raw_hash_set",
         ":tracked",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -826,8 +884,8 @@
         "//absl/log:check",
         "//absl/types:span",
         "//absl/utility",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -843,7 +901,7 @@
         ":layout",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -867,7 +925,7 @@
     deps = [
         ":hash_generator_testing",
         ":hash_policy_testing",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -880,7 +938,7 @@
     deps = [
         ":hash_generator_testing",
         ":hash_policy_testing",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -893,7 +951,7 @@
     deps = [
         ":hash_generator_testing",
         ":hash_policy_testing",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -907,7 +965,7 @@
         ":hash_generator_testing",
         ":hash_policy_testing",
         "//absl/meta:type_traits",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -919,7 +977,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         "//absl/meta:type_traits",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -931,7 +989,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         "//absl/meta:type_traits",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -944,7 +1002,7 @@
     deps = [
         ":hash_generator_testing",
         ":hash_policy_testing",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -957,7 +1015,7 @@
     deps = [
         ":hash_generator_testing",
         ":hash_policy_testing",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -972,8 +1030,8 @@
         ":unordered_set_lookup_test",
         ":unordered_set_members_test",
         ":unordered_set_modifiers_test",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -988,8 +1046,8 @@
         ":unordered_map_lookup_test",
         ":unordered_map_members_test",
         ":unordered_map_modifiers_test",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1003,10 +1061,11 @@
     deps = [
         ":flat_hash_map",
         ":flat_hash_set",
+        ":hashtablez_sampler",
         ":node_hash_map",
         ":node_hash_set",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1033,6 +1092,7 @@
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/base:throw_delegate",
+        "//absl/hash:weakly_mixed_integer",
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/strings",
@@ -1087,8 +1147,8 @@
         "//absl/strings",
         "//absl/types:compare",
         "//absl/types:optional",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1117,7 +1177,6 @@
         "//absl/strings:cord",
         "//absl/strings:str_format",
         "//absl/time",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 25831d5..d8cd7d0 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -41,6 +41,7 @@
     absl::strings
     absl::throw_delegate
     absl::type_traits
+    absl::weakly_mixed_integer
 )
 
 # Internal-only target, do not depend on directly.
@@ -131,8 +132,10 @@
     absl::config
     absl::core_headers
     absl::dynamic_annotations
+    absl::iterator_traits_internal
     absl::throw_delegate
     absl::memory
+    absl::weakly_mixed_integer
   PUBLIC
 )
 
@@ -148,6 +151,7 @@
     absl::config
     absl::exception_testing
     absl::hash_testing
+    absl::iterator_traits_test_helper_internal
     absl::memory
     absl::test_allocator
     GTest::gmock_main
@@ -200,6 +204,7 @@
     absl::throw_delegate
     absl::memory
     absl::type_traits
+    absl::weakly_mixed_integer
   PUBLIC
 )
 
@@ -350,6 +355,8 @@
     absl::config
     absl::container_memory
     absl::flat_hash_set
+    absl::hash
+    absl::hash_container_defaults
     absl::hash_generator_testing
     absl::memory
     absl::strings
@@ -536,6 +543,7 @@
     absl::memory
     absl::meta
     absl::no_destructor
+    absl::random_random
     absl::strings
   TESTONLY
 )
@@ -651,6 +659,7 @@
   DEPS
     absl::config
     absl::hashtablez_sampler
+    absl::random_random
     GTest::gmock_main
 )
 
@@ -716,9 +725,11 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::config
+    absl::common_policy_traits
     absl::container_memory
     absl::core_headers
     absl::raw_hash_set
+    absl::type_traits
     absl::throw_delegate
   PUBLIC
 )
@@ -738,6 +749,21 @@
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
+    hashtable_control_bytes
+  HDRS
+    "internal/hashtable_control_bytes.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bits
+    absl::config
+    absl::core_headers
+    absl::endian
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
     raw_hash_set
   HDRS
     "internal/raw_hash_set.h"
@@ -747,6 +773,7 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::bits
+    absl::common_policy_traits
     absl::compressed_tuple
     absl::config
     absl::container_common
@@ -754,16 +781,21 @@
     absl::core_headers
     absl::dynamic_annotations
     absl::endian
+    absl::function_ref
     absl::hash
+    absl::hash_function_defaults
     absl::hash_policy_traits
+    absl::hashtable_control_bytes
     absl::hashtable_debug_hooks
     absl::hashtablez_sampler
+    absl::iterator_traits_internal
     absl::memory
     absl::meta
     absl::optional
     absl::prefetch
     absl::raw_logging_internal
     absl::utility
+    absl::weakly_mixed_integer
   PUBLIC
 )
 
@@ -788,10 +820,13 @@
     absl::hash_policy_testing
     absl::hashtable_debug
     absl::hashtablez_sampler
+    absl::int128
     absl::log
     absl::memory
     absl::node_hash_set
+    absl::optional
     absl::prefetch
+    absl::random_random
     absl::raw_hash_set
     absl::strings
     absl::test_allocator
@@ -800,6 +835,32 @@
     GTest::gmock_main
 )
 
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    raw_hash_set_resize_impl
+  HDRS
+    "internal/raw_hash_set_resize_impl.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    raw_hash_set_resize_impl_test
+  SRCS
+    "internal/raw_hash_set_resize_impl_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::config
+    absl::raw_hash_set_resize_impl
+    GTest::gmock_main
+)
+
 absl_cc_test(
   NAME
     raw_hash_set_allocator_test
@@ -1023,5 +1084,6 @@
     absl::flat_hash_set
     absl::node_hash_map
     absl::node_hash_set
+    absl::hashtablez_sampler
     GTest::gmock_main
 )
diff --git a/absl/container/btree_benchmark.cc b/absl/container/btree_benchmark.cc
index 0d26fd4..ee4efbd 100644
--- a/absl/container/btree_benchmark.cc
+++ b/absl/container/btree_benchmark.cc
@@ -26,7 +26,6 @@
 #include <unordered_set>
 #include <vector>
 
-#include "benchmark/benchmark.h"
 #include "absl/algorithm/container.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/container/btree_map.h"
@@ -42,6 +41,7 @@
 #include "absl/strings/cord.h"
 #include "absl/strings/str_format.h"
 #include "absl/time/time.h"
+#include "benchmark/benchmark.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -406,22 +406,18 @@
 template <typename T>
 void BM_FwdIter(benchmark::State& state) {
   using V = typename remove_pair_const<typename T::value_type>::type;
-  using R = typename T::value_type const*;
 
   std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
   T container(values.begin(), values.end());
 
   auto iter = container.end();
 
-  R r = nullptr;
-
   while (state.KeepRunning()) {
     if (iter == container.end()) iter = container.begin();
-    r = &(*iter);
-    ++iter;
+    auto *v = &(*iter);
+    benchmark::DoNotOptimize(v);
+    benchmark::DoNotOptimize(++iter);
   }
-
-  benchmark::DoNotOptimize(r);
 }
 
 // Benchmark random range-construction of a container.
@@ -735,7 +731,7 @@
 
 BIG_TYPE_PTR_BENCHMARKS(32);
 
-void BM_BtreeSet_IteratorSubtraction(benchmark::State& state) {
+void BM_BtreeSet_IteratorDifference(benchmark::State& state) {
   absl::InsecureBitGen bitgen;
   std::vector<int> vec;
   // Randomize the set's insertion order so the nodes aren't all full.
@@ -756,6 +752,52 @@
   }
 }
 
+BENCHMARK(BM_BtreeSet_IteratorDifference)->Range(1 << 10, 1 << 20);
+
+void BM_BtreeSet_IteratorAddition(benchmark::State& state) {
+  absl::InsecureBitGen bitgen;
+  std::vector<int> vec;
+  // Randomize the set's insertion order so the nodes aren't all full.
+  vec.reserve(static_cast<size_t>(state.range(0)));
+  for (int i = 0; i < state.range(0); ++i) vec.push_back(i);
+  absl::c_shuffle(vec, bitgen);
+
+  absl::btree_set<int> set;
+  for (int i : vec) set.insert(i);
+
+  size_t distance = absl::Uniform(bitgen, 0u, set.size());
+  while (state.KeepRunningBatch(distance)) {
+    // Let the increment go all the way to the `end` iterator.
+    const size_t begin =
+        absl::Uniform(absl::IntervalClosed, bitgen, 0u, set.size() - distance);
+    auto it = set.find(static_cast<int>(begin));
+    benchmark::DoNotOptimize(it += static_cast<int>(distance));
+    distance = absl::Uniform(bitgen, 0u, set.size());
+  }
+}
+
+BENCHMARK(BM_BtreeSet_IteratorAddition)->Range(1 << 10, 1 << 20);
+
+void BM_BtreeSet_IteratorSubtraction(benchmark::State& state) {
+  absl::InsecureBitGen bitgen;
+  std::vector<int> vec;
+  // Randomize the set's insertion order so the nodes aren't all full.
+  vec.reserve(static_cast<size_t>(state.range(0)));
+  for (int i = 0; i < state.range(0); ++i) vec.push_back(i);
+  absl::c_shuffle(vec, bitgen);
+
+  absl::btree_set<int> set;
+  for (int i : vec) set.insert(i);
+
+  size_t distance = absl::Uniform(bitgen, 0u, set.size());
+  while (state.KeepRunningBatch(distance)) {
+    size_t end = absl::Uniform(bitgen, distance, set.size());
+    auto it = set.find(static_cast<int>(end));
+    benchmark::DoNotOptimize(it -= static_cast<int>(distance));
+    distance = absl::Uniform(bitgen, 0u, set.size());
+  }
+}
+
 BENCHMARK(BM_BtreeSet_IteratorSubtraction)->Range(1 << 10, 1 << 20);
 
 }  // namespace
diff --git a/absl/container/btree_map.h b/absl/container/btree_map.h
index b959b67..32a82ef 100644
--- a/absl/container/btree_map.h
+++ b/absl/container/btree_map.h
@@ -47,8 +47,10 @@
 // iterator at the current position. Another important difference is that
 // key-types must be copy-constructible.
 //
-// Another API difference is that btree iterators can be subtracted, and this
-// is faster than using std::distance.
+// There are other API differences: first, btree iterators can be subtracted,
+// and this is faster than using `std::distance`. Additionally, btree
+// iterators can be advanced via `operator+=` and `operator-=`, which is faster
+// than using `std::advance`.
 //
 // B-tree maps are not exception-safe.
 
@@ -87,7 +89,7 @@
 //
 template <typename Key, typename Value, typename Compare = std::less<Key>,
           typename Alloc = std::allocator<std::pair<const Key, Value>>>
-class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_map
+class ABSL_ATTRIBUTE_OWNER btree_map
     : public container_internal::btree_map_container<
           container_internal::btree<container_internal::map_params<
               Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,
@@ -525,7 +527,7 @@
 //
 template <typename Key, typename Value, typename Compare = std::less<Key>,
           typename Alloc = std::allocator<std::pair<const Key, Value>>>
-class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_multimap
+class ABSL_ATTRIBUTE_OWNER btree_multimap
     : public container_internal::btree_multimap_container<
           container_internal::btree<container_internal::map_params<
               Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,
diff --git a/absl/container/btree_set.h b/absl/container/btree_set.h
index 986d27d..16181de 100644
--- a/absl/container/btree_set.h
+++ b/absl/container/btree_set.h
@@ -46,8 +46,10 @@
 // reason, `insert()`, `erase()`, and `extract_and_get_next()` return a valid
 // iterator at the current position.
 //
-// Another API difference is that btree iterators can be subtracted, and this
-// is faster than using std::distance.
+// There are other API differences: first, btree iterators can be subtracted,
+// and this is faster than using `std::distance`. Additionally, btree
+// iterators can be advanced via `operator+=` and `operator-=`, which is faster
+// than using `std::advance`.
 //
 // B-tree sets are not exception-safe.
 
@@ -89,7 +91,7 @@
 //
 template <typename Key, typename Compare = std::less<Key>,
           typename Alloc = std::allocator<Key>>
-class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_set
+class ABSL_ATTRIBUTE_OWNER btree_set
     : public container_internal::btree_set_container<
           container_internal::btree<container_internal::set_params<
               Key, Compare, Alloc, /*TargetNodeSize=*/256,
@@ -445,7 +447,7 @@
 //
 template <typename Key, typename Compare = std::less<Key>,
           typename Alloc = std::allocator<Key>>
-class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_multiset
+class ABSL_ATTRIBUTE_OWNER btree_multiset
     : public container_internal::btree_multiset_container<
           container_internal::btree<container_internal::set_params<
               Key, Compare, Alloc, /*TargetNodeSize=*/256,
diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc
index d7102fe..1d2c2a6 100644
--- a/absl/container/btree_test.cc
+++ b/absl/container/btree_test.cc
@@ -2674,8 +2674,6 @@
 }
 #endif
 
-// This test requires std::launder for mutable key access in node handles.
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
 TEST(Btree, NodeHandleMutableKeyAccess) {
   {
     absl::btree_map<std::string, std::string> map;
@@ -2701,7 +2699,6 @@
     EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
   }
 }
-#endif
 
 struct MultiKey {
   int i1;
@@ -2949,6 +2946,7 @@
 
 TEST(Btree, ConstructImplicitlyWithUnadaptedComparator) {
   absl::btree_set<MultiKey, MultiKeyComp> set = {{}, MultiKeyComp{}};
+  EXPECT_TRUE(set.empty());
 }
 
 TEST(Btree, InvalidComparatorsCaught) {
@@ -3353,7 +3351,7 @@
   set.insert(0);
 }
 
-TEST(Btree, IteratorSubtraction) {
+TEST(Btree, IteratorDifference) {
   absl::BitGen bitgen;
   std::vector<int> vec;
   // Randomize the set's insertion order so the nodes aren't all full.
@@ -3371,6 +3369,94 @@
   }
 }
 
+TEST(Btree, IteratorAddition) {
+  absl::BitGen bitgen;
+  std::vector<int> vec;
+
+  // Randomize the set's insertion order so the nodes aren't all full.
+  constexpr int kSetSize = 1000000;
+  for (int i = 0; i < kSetSize; ++i) vec.push_back(i);
+  absl::c_shuffle(vec, bitgen);
+
+  absl::btree_set<int> set;
+  for (int i : vec) set.insert(i);
+
+  for (int i = 0; i < 1000; ++i) {
+    int begin = absl::Uniform(bitgen, 0, kSetSize);
+    int end = absl::Uniform(bitgen, begin, kSetSize);
+    ASSERT_LE(begin, end);
+
+    auto it = set.find(begin);
+    it += end - begin;
+    ASSERT_EQ(it, set.find(end)) << end;
+
+    it += begin - end;
+    ASSERT_EQ(it, set.find(begin)) << begin;
+  }
+}
+
+TEST(Btree, IteratorAdditionOutOfBounds) {
+  const absl::btree_set<int> set({5});
+
+  auto it = set.find(5);
+
+  auto forward = it;
+  forward += 1;
+  EXPECT_EQ(forward, set.end());
+
+  auto backward = it;
+  EXPECT_EQ(backward, set.begin());
+
+  if (IsAssertEnabled()) {
+    EXPECT_DEATH(forward += 1, "n == 0");
+    EXPECT_DEATH(backward += -1, "position >= node->start");
+  }
+}
+
+TEST(Btree, IteratorSubtraction) {
+  absl::BitGen bitgen;
+  std::vector<int> vec;
+
+  // Randomize the set's insertion order so the nodes aren't all full.
+  constexpr int kSetSize = 1000000;
+  for (int i = 0; i < kSetSize; ++i) vec.push_back(i);
+  absl::c_shuffle(vec, bitgen);
+
+  absl::btree_set<int> set;
+  for (int i : vec) set.insert(i);
+
+  for (int i = 0; i < 1000; ++i) {
+    int begin = absl::Uniform(bitgen, 0, kSetSize);
+    int end = absl::Uniform(bitgen, begin, kSetSize);
+    ASSERT_LE(begin, end);
+
+    auto it = set.find(end);
+    it -= end - begin;
+    ASSERT_EQ(it, set.find(begin)) << begin;
+
+    it -= begin - end;
+    ASSERT_EQ(it, set.find(end)) << end;
+  }
+}
+
+TEST(Btree, IteratorSubtractionOutOfBounds) {
+  const absl::btree_set<int> set({5});
+
+  auto it = set.find(5);
+
+  auto backward = it;
+  EXPECT_EQ(backward, set.begin());
+
+  auto forward = it;
+  forward -= -1;
+  EXPECT_EQ(forward, set.end());
+
+  if (IsAssertEnabled()) {
+    EXPECT_DEATH(backward -= 1, "position >= node->start");
+    EXPECT_DEATH(forward -= -1, "n == 0");
+  }
+}
+
 TEST(Btree, DereferencingEndIterator) {
   if (!IsAssertEnabled()) GTEST_SKIP() << "Assertions not enabled.";
 
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index 9f1c813..6c238fc 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -41,13 +41,16 @@
 #include <type_traits>
 
 #include "absl/algorithm/algorithm.h"
+#include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/dynamic_annotations.h"
+#include "absl/base/internal/iterator_traits.h"
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/base/macros.h"
 #include "absl/base/optimization.h"
 #include "absl/base/port.h"
 #include "absl/container/internal/compressed_tuple.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
 #include "absl/memory/memory.h"
 
 namespace absl {
@@ -74,7 +77,7 @@
 // `std::vector`.
 template <typename T, size_t N = kFixedArrayUseDefault,
           typename A = std::allocator<T>>
-class FixedArray {
+class ABSL_ATTRIBUTE_WARN_UNUSED FixedArray {
   static_assert(!std::is_array<T>::value || std::extent<T>::value > 0,
                 "Arrays with unknown bounds cannot be used with FixedArray.");
 
@@ -84,9 +87,8 @@
   // std::iterator_traits isn't guaranteed to be SFINAE-friendly until C++17,
   // but this seems to be mostly pedantic.
   template <typename Iterator>
-  using EnableIfForwardIterator = absl::enable_if_t<std::is_convertible<
-      typename std::iterator_traits<Iterator>::iterator_category,
-      std::forward_iterator_tag>::value>;
+  using EnableIfForwardIterator = std::enable_if_t<
+      base_internal::IsAtLeastForwardIterator<Iterator>::value>;
   static constexpr bool NoexceptCopyable() {
     return std::is_nothrow_copy_constructible<StorageElement>::value &&
            absl::allocator_is_nothrow<allocator_type>::value;
@@ -391,7 +393,7 @@
   template <typename H>
   friend H AbslHashValue(H h, const FixedArray& v) {
     return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
-                      v.size());
+                      hash_internal::WeaklyMixedInteger{v.size()});
   }
 
  private:
@@ -446,7 +448,8 @@
 
    private:
     ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_);
-    alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
+    alignas(StorageElement) unsigned char buff_[sizeof(
+        StorageElement[inline_elements])];
     ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_);
   };
 
@@ -516,15 +519,6 @@
   Storage storage_;
 };
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-template <typename T, size_t N, typename A>
-constexpr size_t FixedArray<T, N, A>::kInlineBytesDefault;
-
-template <typename T, size_t N, typename A>
-constexpr typename FixedArray<T, N, A>::size_type
-    FixedArray<T, N, A>::inline_elements;
-#endif
-
 template <typename T, size_t N, typename A>
 void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateConstruct(
     typename FixedArray<T, N, A>::size_type n) {
diff --git a/absl/container/fixed_array_test.cc b/absl/container/fixed_array_test.cc
index 2421b5f..6175a7c 100644
--- a/absl/container/fixed_array_test.cc
+++ b/absl/container/fixed_array_test.cc
@@ -17,18 +17,21 @@
 #include <stdio.h>
 
 #include <cstring>
+#include <forward_list>
 #include <list>
 #include <memory>
 #include <numeric>
 #include <scoped_allocator>
 #include <stdexcept>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/exception_testing.h"
+#include "absl/base/internal/iterator_traits_test_helper.h"
 #include "absl/base/options.h"
 #include "absl/container/internal/test_allocator.h"
 #include "absl/hash/hash_testing.h"
@@ -409,6 +412,20 @@
   EXPECT_THAT(fixed, testing::ElementsAreArray(kInput));
 }
 
+TEST(IteratorConstructorTest, FromCpp20ForwardIteratorRange) {
+  std::forward_list<int> const kUnzippedInput = {2, 3, 5, 7, 11, 13, 17};
+  absl::base_internal::Cpp20ForwardZipIterator<
+      std::forward_list<int>::const_iterator> const
+      begin(std::begin(kUnzippedInput), std::begin(kUnzippedInput));
+  absl::base_internal::
+      Cpp20ForwardZipIterator<std::forward_list<int>::const_iterator> const end(
+          std::end(kUnzippedInput), std::end(kUnzippedInput));
+
+  std::forward_list<std::pair<int, int>> const items(begin, end);
+  absl::FixedArray<std::pair<int, int>> const fixed(begin, end);
+  EXPECT_THAT(fixed, testing::ElementsAreArray(items));
+}
+
 TEST(InitListConstructorTest, InitListConstruction) {
   absl::FixedArray<int> fixed = {1, 2, 3};
   EXPECT_THAT(fixed, testing::ElementsAreArray({1, 2, 3}));
@@ -419,7 +436,7 @@
   EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
 
   absl::FixedArray<int, 0> heap_array(4, 1);
-  EXPECT_THAT(stack_array, testing::ElementsAreArray({1, 1, 1, 1}));
+  EXPECT_THAT(heap_array, testing::ElementsAreArray({1, 1, 1, 1}));
 }
 
 TEST(FillConstructorTest, EmptyArray) {
@@ -518,7 +535,10 @@
   }
 };
 
-TEST(FixedArrayTest, UsesGlobalAlloc) { absl::FixedArray<PickyDelete, 0> a(5); }
+TEST(FixedArrayTest, UsesGlobalAlloc) {
+  absl::FixedArray<PickyDelete, 0> a(5);
+  EXPECT_EQ(a.size(), 5);
+}
 
 TEST(FixedArrayTest, Data) {
   static const int kInput[] = {2, 3, 5, 7, 11, 13, 17};
@@ -782,6 +802,7 @@
 
   AllocFxdArr copy = arr;
   EXPECT_EQ(allocated, len * sizeof(int) * 2);
+  EXPECT_EQ(copy, arr);
 }
 
 #ifdef ABSL_HAVE_ADDRESS_SANITIZER
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index ebd9ed6..bc86ced 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -104,6 +104,11 @@
 // If your types are not moveable or you require pointer stability for keys,
 // consider `absl::node_hash_map`.
 //
+// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:
+//  * Iteration takes O(capacity) time, not O(size).
+//  * erase() slows down begin() and ++iterator.
+//  * Capacity only shrinks on rehash() or clear() -- not on erase().
+//
 // Example:
 //
 //   // Create a flat hash map of three strings (that map to strings)
@@ -125,7 +130,7 @@
 template <class K, class V, class Hash = DefaultHashContainerHash<K>,
           class Eq = DefaultHashContainerEq<K>,
           class Allocator = std::allocator<std::pair<const K, V>>>
-class ABSL_INTERNAL_ATTRIBUTE_OWNER flat_hash_map
+class ABSL_ATTRIBUTE_OWNER flat_hash_map
     : public absl::container_internal::raw_hash_map<
           absl::container_internal::FlatHashMapPolicy<K, V>, Hash, Eq,
           Allocator> {
@@ -426,8 +431,7 @@
   // flat_hash_map::swap(flat_hash_map& other)
   //
   // Exchanges the contents of this `flat_hash_map` with those of the `other`
-  // flat hash map, avoiding invocation of any move, copy, or swap operations on
-  // individual elements.
+  // flat hash map.
   //
   // All iterators and references on the `flat_hash_map` remain valid, excepting
   // for the past-the-end iterator, which is invalidated.
@@ -574,6 +578,21 @@
   return container_internal::EraseIf(pred, &c);
 }
 
+// swap(flat_hash_map<>, flat_hash_map<>)
+//
+// Swaps the contents of two `flat_hash_map` containers.
+//
+// NOTE: we need to define this function template in order for
+// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we
+// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a
+// derived-to-base conversion, whereas `std::swap` is a function template so
+// `std::swap` will be preferred by compiler.
+template <typename K, typename V, typename H, typename E, typename A>
+void swap(flat_hash_map<K, V, H, E, A>& x,
+          flat_hash_map<K, V, H, E, A>& y) noexcept(noexcept(x.swap(y))) {
+  x.swap(y);
+}
+
 namespace container_internal {
 
 // c_for_each_fast(flat_hash_map<>, Function)
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc
index 08915e2..5c83c94 100644
--- a/absl/container/flat_hash_map_test.cc
+++ b/absl/container/flat_hash_map_test.cc
@@ -115,23 +115,29 @@
 }
 
 TEST(FlatHashMap, Relocatability) {
-  static_assert(absl::is_trivially_relocatable<int>::value, "");
+  static_assert(absl::is_trivially_relocatable<int>::value);
+#if ABSL_INTERNAL_CPLUSPLUS_LANG <= 202002L
+  // std::pair is not trivially copyable in C++23 in some standard
+  // library versions.
+  // See https://github.com/llvm/llvm-project/pull/95444 for instance.
+  // container_memory.h contains a workaround so what really matters
+  // is the transfer test below.
   static_assert(
-      absl::is_trivially_relocatable<std::pair<const int, int>>::value, "");
+      absl::is_trivially_relocatable<std::pair<const int, int>>::value);
+#endif
   static_assert(
       std::is_same<decltype(absl::container_internal::FlatHashMapPolicy<
                             int, int>::transfer<std::allocator<char>>(nullptr,
                                                                       nullptr,
                                                                       nullptr)),
-                   std::true_type>::value,
-      "");
+                   std::true_type>::value);
 
-    struct NonRelocatable {
-      NonRelocatable() = default;
-      NonRelocatable(NonRelocatable&&) {}
-      NonRelocatable& operator=(NonRelocatable&&) { return *this; }
-      void* self = nullptr;
-    };
+  struct NonRelocatable {
+    NonRelocatable() = default;
+    NonRelocatable(NonRelocatable&&) {}
+    NonRelocatable& operator=(NonRelocatable&&) { return *this; }
+    void* self = nullptr;
+  };
 
   EXPECT_FALSE(absl::is_trivially_relocatable<NonRelocatable>::value);
   EXPECT_TRUE(
@@ -360,8 +366,6 @@
   }
 }
 
-// This test requires std::launder for mutable key access in node handles.
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
 TEST(FlatHashMap, NodeHandleMutableKeyAccess) {
   flat_hash_map<std::string, std::string> map;
 
@@ -373,7 +377,6 @@
 
   EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
 }
-#endif
 
 TEST(FlatHashMap, Reserve) {
   // Verify that if we reserve(size() + n) then we can perform n insertions
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index a3e36e0..bf63eb5 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -62,7 +62,7 @@
 // Its interface is similar to that of `std::unordered_set<T>` with the
 // following notable differences:
 //
-// * Requires keys that are CopyConstructible
+// * Requires keys that are MoveConstructible
 // * Supports heterogeneous lookup, through `find()` and `insert()`, provided
 //   that the set is provided a compatible heterogeneous hashing function and
 //   equality operator. See below for details.
@@ -103,6 +103,11 @@
 // `absl::flat_hash_set<std::unique_ptr<T>>`. If your type is not moveable and
 // you require pointer stability, consider `absl::node_hash_set` instead.
 //
+// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:
+//  * Iteration takes O(capacity) time, not O(size).
+//  * erase() slows down begin() and ++iterator.
+//  * Capacity only shrinks on rehash() or clear() -- not on erase().
+//
 // Example:
 //
 //   // Create a flat hash set of three strings
@@ -122,7 +127,7 @@
 template <class T, class Hash = DefaultHashContainerHash<T>,
           class Eq = DefaultHashContainerEq<T>,
           class Allocator = std::allocator<T>>
-class ABSL_INTERNAL_ATTRIBUTE_OWNER flat_hash_set
+class ABSL_ATTRIBUTE_OWNER flat_hash_set
     : public absl::container_internal::raw_hash_set<
           absl::container_internal::FlatHashSetPolicy<T>, Hash, Eq, Allocator> {
   using Base = typename flat_hash_set::raw_hash_set;
@@ -360,8 +365,7 @@
   // flat_hash_set::swap(flat_hash_set& other)
   //
   // Exchanges the contents of this `flat_hash_set` with those of the `other`
-  // flat hash set, avoiding invocation of any move, copy, or swap operations on
-  // individual elements.
+  // flat hash set.
   //
   // All iterators and references on the `flat_hash_set` remain valid, excepting
   // for the past-the-end iterator, which is invalidated.
@@ -478,6 +482,21 @@
   return container_internal::EraseIf(pred, &c);
 }
 
+// swap(flat_hash_set<>, flat_hash_set<>)
+//
+// Swaps the contents of two `flat_hash_set` containers.
+//
+// NOTE: we need to define this function template in order for
+// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we
+// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a
+// derived-to-base conversion, whereas `std::swap` is a function template so
+// `std::swap` will be preferred by compiler.
+template <typename T, typename H, typename E, typename A>
+void swap(flat_hash_set<T, H, E, A>& x,
+          flat_hash_set<T, H, E, A>& y) noexcept(noexcept(x.swap(y))) {
+  return x.swap(y);
+}
+
 namespace container_internal {
 
 // c_for_each_fast(flat_hash_set<>, Function)
diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc
index 0dd4326..bb90efa 100644
--- a/absl/container/flat_hash_set_test.cc
+++ b/absl/container/flat_hash_set_test.cc
@@ -14,8 +14,10 @@
 
 #include "absl/container/flat_hash_set.h"
 
+#include <cstddef>
 #include <cstdint>
 #include <memory>
+#include <string>
 #include <type_traits>
 #include <utility>
 #include <vector>
@@ -23,6 +25,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/config.h"
+#include "absl/container/hash_container_defaults.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_generator_testing.h"
 #include "absl/container/internal/test_allocator.h"
@@ -30,6 +33,7 @@
 #include "absl/container/internal/unordered_set_lookup_test.h"
 #include "absl/container/internal/unordered_set_members_test.h"
 #include "absl/container/internal/unordered_set_modifiers_test.h"
+#include "absl/hash/hash.h"
 #include "absl/log/check.h"
 #include "absl/memory/memory.h"
 #include "absl/strings/string_view.h"
@@ -291,6 +295,94 @@
                          std::allocator<int>>(nullptr, nullptr))()));
 }
 
+struct HashEqInvalidOnMove {
+  HashEqInvalidOnMove() = default;
+  HashEqInvalidOnMove(const HashEqInvalidOnMove& rhs) = default;
+  HashEqInvalidOnMove(HashEqInvalidOnMove&& rhs) { rhs.moved = true; }
+  HashEqInvalidOnMove& operator=(const HashEqInvalidOnMove& rhs) = default;
+  HashEqInvalidOnMove& operator=(HashEqInvalidOnMove&& rhs) {
+    rhs.moved = true;
+    return *this;
+  }
+
+  size_t operator()(int x) const {
+    CHECK(!moved);
+    return absl::HashOf(x);
+  }
+
+  bool operator()(int x, int y) const {
+    CHECK(!moved);
+    return x == y;
+  }
+
+  bool moved = false;
+};
+
+TEST(FlatHashSet, MovedFromCleared_HashMustBeValid) {
+  flat_hash_set<int, HashEqInvalidOnMove> s1, s2;
+  // Moving the hashtable must not move the hasher because we need to support
+  // this behavior.
+  s2 = std::move(s1);
+  s1.clear();
+  s1.insert(2);
+  EXPECT_THAT(s1, UnorderedElementsAre(2));
+}
+
+TEST(FlatHashSet, MovedFromCleared_EqMustBeValid) {
+  flat_hash_set<int, DefaultHashContainerHash<int>, HashEqInvalidOnMove> s1, s2;
+  // Moving the hashtable must not move the equality functor because we need to
+  // support this behavior.
+  s2 = std::move(s1);
+  s1.clear();
+  s1.insert(2);
+  EXPECT_THAT(s1, UnorderedElementsAre(2));
+}
+
+TEST(FlatHashSet, Equality) {
+  {
+    flat_hash_set<int> s1 = {1, 2, 3};
+    flat_hash_set<int> s2 = {1, 2, 3};
+    EXPECT_EQ(s1, s2);
+  }
+  {
+    flat_hash_set<std::string> s1 = {"a", "b", "c"};
+    flat_hash_set<std::string> s2 = {"a", "b", "c"};
+    EXPECT_EQ(s1, s2);
+  }
+}
+
+class MoveOnlyInt {
+ public:
+  explicit MoveOnlyInt(int value) : value_(value) {}
+
+  MoveOnlyInt(const MoveOnlyInt& other) = delete;
+  MoveOnlyInt& operator=(const MoveOnlyInt& other) = delete;
+
+  MoveOnlyInt(MoveOnlyInt&& other) = default;
+  MoveOnlyInt& operator=(MoveOnlyInt&& other) = default;
+
+  bool operator==(const MoveOnlyInt& other) const {
+    return value_ == other.value_;
+  }
+  bool operator==(int other) const { return value_ == other; }
+
+ private:
+  template <typename H>
+  friend H AbslHashValue(H h, const MoveOnlyInt& m) {
+    return H::combine(std::move(h), m.value_);
+  }
+
+  int value_;
+};
+
+TEST(FlatHashSet, MoveOnlyKey) {
+  flat_hash_set<MoveOnlyInt> s;
+  s.insert(MoveOnlyInt(1));
+  s.insert(MoveOnlyInt(2));
+  s.insert(MoveOnlyInt(3));
+  EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3));
+}
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 974b652..f871b34 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -46,11 +46,14 @@
 #include <utility>
 
 #include "absl/algorithm/algorithm.h"
+#include "absl/base/attributes.h"
+#include "absl/base/internal/iterator_traits.h"
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/base/macros.h"
 #include "absl/base/optimization.h"
 #include "absl/base/port.h"
 #include "absl/container/internal/inlined_vector.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
 
@@ -67,7 +70,7 @@
 // as a `std::vector`. The API of the `absl::InlinedVector` within this file is
 // designed to cover the same API footprint as covered by `std::vector`.
 template <typename T, size_t N, typename A = std::allocator<T>>
-class InlinedVector {
+class ABSL_ATTRIBUTE_WARN_UNUSED InlinedVector {
   static_assert(N > 0, "`absl::InlinedVector` requires an inlined capacity.");
 
   using Storage = inlined_vector_internal::Storage<T, N, A>;
@@ -89,11 +92,11 @@
       inlined_vector_internal::DefaultValueAdapter<TheA>;
 
   template <typename Iterator>
-  using EnableIfAtLeastForwardIterator = absl::enable_if_t<
-      inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
+  using EnableIfAtLeastForwardIterator = std::enable_if_t<
+      base_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
   template <typename Iterator>
-  using DisableIfAtLeastForwardIterator = absl::enable_if_t<
-      !inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
+  using DisableIfAtLeastForwardIterator = std::enable_if_t<
+      !base_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
 
   using MemcpyPolicy = typename Storage::MemcpyPolicy;
   using ElementwiseAssignPolicy = typename Storage::ElementwiseAssignPolicy;
@@ -1006,7 +1009,8 @@
 template <typename H, typename T, size_t N, typename A>
 H AbslHashValue(H h, const absl::InlinedVector<T, N, A>& a) {
   auto size = a.size();
-  return H::combine(H::combine_contiguous(std::move(h), a.data(), size), size);
+  return H::combine(H::combine_contiguous(std::move(h), a.data(), size),
+                    hash_internal::WeaklyMixedInteger{size});
 }
 
 ABSL_NAMESPACE_END
diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc
index 6954262..ff0e77b 100644
--- a/absl/container/inlined_vector_test.cc
+++ b/absl/container/inlined_vector_test.cc
@@ -31,6 +31,7 @@
 #include "gtest/gtest.h"
 #include "absl/base/attributes.h"
 #include "absl/base/internal/exception_testing.h"
+#include "absl/base/internal/iterator_traits_test_helper.h"
 #include "absl/base/macros.h"
 #include "absl/base/options.h"
 #include "absl/container/internal/test_allocator.h"
@@ -649,6 +650,33 @@
   }
 }
 
+TEST(IntPairVec, Insert) {
+  for (size_t len = 0; len < 20; len++) {
+    for (ptrdiff_t pos = 0; pos <= static_cast<ptrdiff_t>(len); pos++) {
+      // Iterator range (C++20 forward iterator)
+      const std::forward_list<int> unzipped_input = {9999, 8888, 7777};
+      const absl::base_internal::Cpp20ForwardZipIterator<
+          std::forward_list<int>::const_iterator>
+          begin(unzipped_input.cbegin(), unzipped_input.cbegin());
+      const absl::base_internal::Cpp20ForwardZipIterator<
+          std::forward_list<int>::const_iterator>
+          end(unzipped_input.cend(), unzipped_input.cend());
+
+      std::vector<std::pair<int, int>> std_v;
+      absl::InlinedVector<std::pair<int, int>, 8> v;
+      for (size_t i = 0; i < len; ++i) {
+        std_v.emplace_back(i, i);
+        v.emplace_back(i, i);
+      }
+
+      std_v.insert(std_v.begin() + pos, begin, end);
+      auto it = v.insert(v.cbegin() + pos, begin, end);
+      EXPECT_THAT(v, ElementsAreArray(std_v));
+      EXPECT_EQ(it, v.cbegin() + pos);
+    }
+  }
+}
+
 TEST(RefCountedVec, InsertConstructorDestructor) {
   // Make sure the proper construction/destruction happen during insert
   // operations.
@@ -1190,6 +1218,7 @@
     tracker.ResetCopiesMovesSwaps();
     {  // Copy constructor should create 'len' more instances.
       InstanceVec v_copy(v);
+      EXPECT_EQ(v_copy.size(), v.size());
       EXPECT_EQ(tracker.instances(), len + len);
       EXPECT_EQ(tracker.copies(), len);
       EXPECT_EQ(tracker.moves(), 0);
@@ -1217,6 +1246,7 @@
     tracker.ResetCopiesMovesSwaps();
     {
       InstanceVec v_copy(std::move(v));
+      EXPECT_EQ(v_copy.size(), len);
       if (static_cast<size_t>(len) > inlined_capacity) {
         // Allocation is moved as a whole.
         EXPECT_EQ(tracker.instances(), len);
@@ -1747,61 +1777,80 @@
   using MyAlloc = CountingAllocator<int>;
   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
   const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
-  int64_t allocated = 0;
-  MyAlloc alloc(&allocated);
+  int64_t bytes_allocated = 0;
+  int64_t instance_count = 0;
+  MyAlloc alloc(&bytes_allocated, &instance_count);
   {
     AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + 4, alloc);
-    EXPECT_THAT(allocated, Eq(0));
+    EXPECT_THAT(bytes_allocated, Eq(0));
+    EXPECT_THAT(instance_count, Eq(4));
   }
-  EXPECT_THAT(allocated, Eq(0));
+  EXPECT_THAT(bytes_allocated, Eq(0));
+  EXPECT_THAT(instance_count, Eq(0));
   {
     AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc);
-    EXPECT_THAT(allocated, Eq(static_cast<int64_t>(v.size() * sizeof(int))));
+    EXPECT_THAT(bytes_allocated,
+                Eq(static_cast<int64_t>(v.size() * sizeof(int))));
+    EXPECT_THAT(instance_count, Eq(static_cast<int64_t>(v.size())));
   }
-  EXPECT_THAT(allocated, Eq(0));
+  EXPECT_THAT(bytes_allocated, Eq(0));
+  EXPECT_THAT(instance_count, Eq(0));
   {
     AllocVec v(4, 1, alloc);
-    EXPECT_THAT(allocated, Eq(0));
+    EXPECT_THAT(bytes_allocated, Eq(0));
+    EXPECT_THAT(instance_count, Eq(4));
 
-    int64_t allocated2 = 0;
-    MyAlloc alloc2(&allocated2);
-    AllocVec v2(v, alloc2);
-    EXPECT_THAT(allocated2, Eq(0));
+    int64_t bytes_allocated2 = 0;
+    MyAlloc alloc2(&bytes_allocated2);
+    ABSL_ATTRIBUTE_UNUSED AllocVec v2(v, alloc2);
+    EXPECT_THAT(bytes_allocated2, Eq(0));
 
-    int64_t allocated3 = 0;
-    MyAlloc alloc3(&allocated3);
-    AllocVec v3(std::move(v), alloc3);
-    EXPECT_THAT(allocated3, Eq(0));
+    int64_t bytes_allocated3 = 0;
+    MyAlloc alloc3(&bytes_allocated3);
+    ABSL_ATTRIBUTE_UNUSED AllocVec v3(std::move(v), alloc3);
+    EXPECT_THAT(bytes_allocated3, Eq(0));
   }
-  EXPECT_THAT(allocated, 0);
+  EXPECT_THAT(bytes_allocated, Eq(0));
+  EXPECT_THAT(instance_count, Eq(0));
   {
     AllocVec v(8, 2, alloc);
-    EXPECT_THAT(allocated, Eq(static_cast<int64_t>(v.size() * sizeof(int))));
+    EXPECT_THAT(bytes_allocated,
+                Eq(static_cast<int64_t>(v.size() * sizeof(int))));
+    EXPECT_THAT(instance_count, Eq(static_cast<int64_t>(v.size())));
 
-    int64_t allocated2 = 0;
-    MyAlloc alloc2(&allocated2);
+    int64_t bytes_allocated2 = 0;
+    MyAlloc alloc2(&bytes_allocated2);
     AllocVec v2(v, alloc2);
-    EXPECT_THAT(allocated2, Eq(static_cast<int64_t>(v2.size() * sizeof(int))));
+    EXPECT_THAT(bytes_allocated2,
+                Eq(static_cast<int64_t>(v2.size() * sizeof(int))));
 
-    int64_t allocated3 = 0;
-    MyAlloc alloc3(&allocated3);
+    int64_t bytes_allocated3 = 0;
+    MyAlloc alloc3(&bytes_allocated3);
     AllocVec v3(std::move(v), alloc3);
-    EXPECT_THAT(allocated3, Eq(static_cast<int64_t>(v3.size() * sizeof(int))));
+    EXPECT_THAT(bytes_allocated3,
+                Eq(static_cast<int64_t>(v3.size() * sizeof(int))));
   }
-  EXPECT_EQ(allocated, 0);
+  EXPECT_EQ(bytes_allocated, 0);
+  EXPECT_EQ(instance_count, 0);
   {
     // Test shrink_to_fit deallocations.
     AllocVec v(8, 2, alloc);
-    EXPECT_EQ(allocated, static_cast<int64_t>(8 * sizeof(int)));
+    EXPECT_EQ(bytes_allocated, static_cast<int64_t>(8 * sizeof(int)));
+    EXPECT_EQ(instance_count, 8);
     v.resize(5);
-    EXPECT_EQ(allocated, static_cast<int64_t>(8 * sizeof(int)));
+    EXPECT_EQ(bytes_allocated, static_cast<int64_t>(8 * sizeof(int)));
+    EXPECT_EQ(instance_count, 5);
     v.shrink_to_fit();
-    EXPECT_EQ(allocated, static_cast<int64_t>(5 * sizeof(int)));
+    EXPECT_EQ(bytes_allocated, static_cast<int64_t>(5 * sizeof(int)));
+    EXPECT_EQ(instance_count, 5);
     v.resize(4);
-    EXPECT_EQ(allocated, static_cast<int64_t>(5 * sizeof(int)));
+    EXPECT_EQ(bytes_allocated, static_cast<int64_t>(5 * sizeof(int)));
+    EXPECT_EQ(instance_count, 4);
     v.shrink_to_fit();
-    EXPECT_EQ(allocated, 0);
+    EXPECT_EQ(bytes_allocated, 0);
+    EXPECT_EQ(instance_count, 4);
   }
+  EXPECT_EQ(instance_count, 0);
 }
 
 TEST(AllocatorSupportTest, SwapBothAllocated) {
diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h
index 689e71a..ed541e7 100644
--- a/absl/container/internal/btree.h
+++ b/absl/container/internal/btree.h
@@ -60,6 +60,7 @@
 #include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/macros.h"
+#include "absl/base/optimization.h"
 #include "absl/container/internal/common.h"
 #include "absl/container/internal/common_policy_traits.h"
 #include "absl/container/internal/compressed_tuple.h"
@@ -224,7 +225,7 @@
 
    public:
     using Base::Base;
-    checked_compare(Compare comp) : Base(std::move(comp)) {}  // NOLINT
+    checked_compare(Compare cmp) : Base(std::move(cmp)) {}  // NOLINT
 
     // Allow converting to Compare for use in key_comp()/value_comp().
     explicit operator Compare() const { return comp(); }
@@ -708,6 +709,8 @@
   }
 
   // Getter for the parent of this node.
+  // TODO(ezb): assert that the child of the returned node at position
+  // `node_->position()` maps to the current node.
   btree_node *parent() const { return *GetField<0>(); }
   // Getter for whether the node is the root of the tree. The parent of the
   // root of the tree is the leftmost node in the tree which is guaranteed to
@@ -1175,6 +1178,26 @@
     return distance_slow(other);
   }
 
+  // Advances the iterator by `n`. Values of `n` must not result in going past
+  // the `end` iterator (for a positive `n`) or before the `begin` iterator (for
+  // a negative `n`).
+  btree_iterator &operator+=(difference_type n) {
+    assert_valid_generation(node_);
+    if (n == 0) return *this;
+    if (n < 0) return decrement_n_slow(-n);
+    return increment_n_slow(n);
+  }
+
+  // Moves the iterator by `n` positions backwards. Values of `n` must not
+  // result in going before the `begin` iterator (for a positive `n`) or past
+  // the `end` iterator (for a negative `n`).
+  btree_iterator &operator-=(difference_type n) {
+    assert_valid_generation(node_);
+    if (n == 0) return *this;
+    if (n < 0) return increment_n_slow(-n);
+    return decrement_n_slow(n);
+  }
+
   // Accessors for the key/value the iterator is pointing at.
   reference operator*() const {
     ABSL_HARDENING_ASSERT(node_ != nullptr);
@@ -1277,6 +1300,7 @@
     increment_slow();
   }
   void increment_slow();
+  btree_iterator &increment_n_slow(difference_type n);
 
   void decrement() {
     assert_valid_generation(node_);
@@ -1286,6 +1310,7 @@
     decrement_slow();
   }
   void decrement_slow();
+  btree_iterator &decrement_n_slow(difference_type n);
 
   const key_type &key() const {
     return node_->key(static_cast<size_type>(position_));
@@ -2126,50 +2151,128 @@
 
 template <typename N, typename R, typename P>
 void btree_iterator<N, R, P>::increment_slow() {
-  if (node_->is_leaf()) {
-    assert(position_ >= node_->finish());
-    btree_iterator save(*this);
-    while (position_ == node_->finish() && !node_->is_root()) {
-      assert(node_->parent()->child(node_->position()) == node_);
-      position_ = node_->position();
-      node_ = node_->parent();
+  N* node = node_;
+  int position = position_;
+  if (node->is_leaf()) {
+    assert(position >= node->finish());
+    while (position == node->finish() && !node->is_root()) {
+      assert(node->parent()->child(node->position()) == node);
+      position = node->position();
+      node = node->parent();
     }
     // TODO(ezb): assert we aren't incrementing end() instead of handling.
-    if (position_ == node_->finish()) {
-      *this = save;
+    if (position == node->finish()) {
+      return;
     }
   } else {
-    assert(position_ < node_->finish());
-    node_ = node_->child(static_cast<field_type>(position_ + 1));
-    while (node_->is_internal()) {
-      node_ = node_->start_child();
+    assert(position < node->finish());
+    node = node->child(static_cast<field_type>(position + 1));
+    while (node->is_internal()) {
+      node = node->start_child();
     }
-    position_ = node_->start();
+    position = node->start();
   }
+  *this = {node, position};
 }
 
 template <typename N, typename R, typename P>
 void btree_iterator<N, R, P>::decrement_slow() {
-  if (node_->is_leaf()) {
-    assert(position_ <= -1);
-    btree_iterator save(*this);
-    while (position_ < node_->start() && !node_->is_root()) {
-      assert(node_->parent()->child(node_->position()) == node_);
-      position_ = node_->position() - 1;
-      node_ = node_->parent();
+  N* node = node_;
+  int position = position_;
+  if (node->is_leaf()) {
+    assert(position <= -1);
+    while (position < node->start() && !node->is_root()) {
+      assert(node->parent()->child(node->position()) == node);
+      position = node->position() - 1;
+      node = node->parent();
     }
     // TODO(ezb): assert we aren't decrementing begin() instead of handling.
-    if (position_ < node_->start()) {
-      *this = save;
+    if (position < node->start()) {
+      return;
     }
   } else {
-    assert(position_ >= node_->start());
-    node_ = node_->child(static_cast<field_type>(position_));
-    while (node_->is_internal()) {
-      node_ = node_->child(node_->finish());
+    assert(position >= node->start());
+    node = node->child(static_cast<field_type>(position));
+    while (node->is_internal()) {
+      node = node->child(node->finish());
     }
-    position_ = node_->finish() - 1;
+    position = node->finish() - 1;
   }
+  *this = {node, position};
+}
+
+template <typename N, typename R, typename P>
+btree_iterator<N, R, P> &btree_iterator<N, R, P>::increment_n_slow(
+    difference_type n) {
+  N *node = node_;
+  int position = position_;
+  ABSL_ASSUME(n > 0);
+  while (n > 0) {
+    if (node->is_leaf()) {
+      if (position + n < node->finish()) {
+        position += n;
+        break;
+      } else {
+        n -= node->finish() - position;
+        position = node->finish();
+        btree_iterator save = {node, position};
+        while (position == node->finish() && !node->is_root()) {
+          position = node->position();
+          node = node->parent();
+        }
+        if (position == node->finish()) {
+          ABSL_HARDENING_ASSERT(n == 0);
+          return *this = save;
+        }
+      }
+    } else {
+      --n;
+      assert(position < node->finish());
+      node = node->child(static_cast<field_type>(position + 1));
+      while (node->is_internal()) {
+        node = node->start_child();
+      }
+      position = node->start();
+    }
+  }
+  node_ = node;
+  position_ = position;
+  return *this;
+}
+
+template <typename N, typename R, typename P>
+btree_iterator<N, R, P> &btree_iterator<N, R, P>::decrement_n_slow(
+    difference_type n) {
+  N *node = node_;
+  int position = position_;
+  ABSL_ASSUME(n > 0);
+  while (n > 0) {
+    if (node->is_leaf()) {
+      if (position - n >= node->start()) {
+        position -= n;
+        break;
+      } else {
+        n -= 1 + position - node->start();
+        position = node->start() - 1;
+        while (position < node->start() && !node->is_root()) {
+          position = node->position() - 1;
+          node = node->parent();
+        }
+        ABSL_HARDENING_ASSERT(position >= node->start());
+      }
+    } else {
+      --n;
+      assert(position >= node->start());
+      node = node->child(static_cast<field_type>(position));
+      while (node->is_internal()) {
+        node = node->child(node->finish());
+      }
+      position = node->finish() - 1;
+    }
+  }
+  node_ = node;
+  position_ = position;
+  return *this;
 }
 
 ////
diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h
index a68ce44..21f00ae 100644
--- a/absl/container/internal/btree_container.h
+++ b/absl/container/internal/btree_container.h
@@ -18,12 +18,14 @@
 #include <algorithm>
 #include <initializer_list>
 #include <iterator>
+#include <type_traits>
 #include <utility>
 
 #include "absl/base/attributes.h"
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/container/internal/btree.h"  // IWYU pragma: export
 #include "absl/container/internal/common.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
 
@@ -266,7 +268,8 @@
     for (const auto &v : b) {
       h = State::combine(std::move(h), v);
     }
-    return State::combine(std::move(h), b.size());
+    return State::combine(std::move(h),
+                          hash_internal::WeaklyMixedInteger{b.size()});
   }
 
  protected:
@@ -451,6 +454,29 @@
   template <class K>
   using key_arg = typename super_type::template key_arg<K>;
 
+  // NOTE: The mess here is to shorten the code for the (very repetitive)
+  // function overloads, and to allow the lifetime-bound overloads to dispatch
+  // to the non-lifetime-bound overloads, to ensure there is a single source of
+  // truth for each overload set.
+  //
+  // Enabled if an assignment from the given type would require the
+  // source object to remain alive for the life of the element.
+  //
+  // TODO(b/402804213): Remove these traits and simplify the overloads whenever
+  // we have a better mechanism available to handle lifetime analysis.
+  template <class K, bool Value, typename = void>
+  using LifetimeBoundK =
+      HasValue<Value, type_traits_internal::IsLifetimeBoundAssignment<
+                          typename Tree::key_type, K>>;
+  template <class M, bool Value, typename = void>
+  using LifetimeBoundV =
+      HasValue<Value, type_traits_internal::IsLifetimeBoundAssignment<
+                          typename Tree::params_type::mapped_type, M>>;
+  template <class K, bool KValue, class M, bool MValue, typename... Dummy>
+  using LifetimeBoundKV =
+      absl::conjunction<LifetimeBoundK<K, KValue, absl::void_t<Dummy...>>,
+                        LifetimeBoundV<M, MValue>>;
+
  public:
   using key_type = typename Tree::key_type;
   using mapped_type = typename params_type::mapped_type;
@@ -464,85 +490,163 @@
   using super_type::super_type;
   btree_map_container() {}
 
+  // TODO(b/402804213): Remove these macros whenever we have a better mechanism
+  // available to handle lifetime analysis.
+#define ABSL_INTERNAL_X(Func, Callee, KQual, MQual, KValue, MValue, ...)     \
+  template <                                                                 \
+      typename K = key_type, class M,                                        \
+      ABSL_INTERNAL_IF_##KValue##_NOR_##MValue(                              \
+          int = (EnableIf<LifetimeBoundKV<K, KValue, M, MValue,              \
+                                          IfRRef<int KQual>::AddPtr<K>,      \
+                                          IfRRef<int MQual>::AddPtr<M>>>()), \
+          ABSL_INTERNAL_SINGLE_ARG(                                          \
+              int &...,                                                      \
+              decltype(EnableIf<LifetimeBoundKV<K, KValue, M, MValue>>()) =  \
+                  0))>                                                       \
+  decltype(auto) Func(                                                       \
+      __VA_ARGS__ key_arg<K> KQual k ABSL_INTERNAL_IF_##KValue(              \
+          ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)),                        \
+      M MQual obj ABSL_INTERNAL_IF_##MValue(                                 \
+          ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)))                        \
+      ABSL_ATTRIBUTE_LIFETIME_BOUND {                                        \
+    return ABSL_INTERNAL_IF_##KValue##_OR_##MValue(                          \
+        (this->template Func<K, M, 0>), Callee)(                             \
+        __VA_ARGS__ std::forward<decltype(k)>(k),                            \
+        std::forward<decltype(obj)>(obj));                                   \
+  }                                                                          \
+  friend struct std::enable_if<false> /* just to force a semicolon */
   // Insertion routines.
   // Note: the nullptr template arguments and extra `const M&` overloads allow
   // for supporting bitfield arguments.
-  template <typename K = key_type, class M>
-  std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, const M &obj)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_impl(k, obj);
-  }
-  template <typename K = key_type, class M, K * = nullptr>
-  std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, const M &obj)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_impl(std::forward<K>(k), obj);
-  }
-  template <typename K = key_type, class M, M * = nullptr>
-  std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, M &&obj)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_impl(k, std::forward<M>(obj));
-  }
-  template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
-  std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, M &&obj)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_impl(std::forward<K>(k), std::forward<M>(obj));
-  }
-  template <typename K = key_type, class M>
-  iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
-                            const M &obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_hint_impl(hint, k, obj);
-  }
-  template <typename K = key_type, class M, K * = nullptr>
-  iterator insert_or_assign(const_iterator hint, key_arg<K> &&k,
-                            const M &obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_hint_impl(hint, std::forward<K>(k), obj);
-  }
-  template <typename K = key_type, class M, M * = nullptr>
-  iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
-                            M &&obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_hint_impl(hint, k, std::forward<M>(obj));
-  }
-  template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
-  iterator insert_or_assign(const_iterator hint, key_arg<K> &&k,
-                            M &&obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_hint_impl(hint, std::forward<K>(k),
-                                      std::forward<M>(obj));
-  }
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  false, false);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  false, true);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  true, false);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  true, true);
 
-  template <typename K = key_type, typename... Args,
-            typename absl::enable_if_t<
-                !std::is_convertible<K, const_iterator>::value, int> = 0>
-  std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&...args)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return try_emplace_impl(k, std::forward<Args>(args)...);
-  }
-  template <typename K = key_type, typename... Args,
-            typename absl::enable_if_t<
-                !std::is_convertible<K, const_iterator>::value, int> = 0>
-  std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&...args)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...);
-  }
-  template <typename K = key_type, typename... Args>
-  iterator try_emplace(const_iterator hint, const key_arg<K> &k,
-                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...);
-  }
-  template <typename K = key_type, typename... Args>
-  iterator try_emplace(const_iterator hint, key_arg<K> &&k,
-                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return try_emplace_hint_impl(hint, std::forward<K>(k),
-                                 std::forward<Args>(args)...);
-  }
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,
+                  false);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,
+                  true);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,
+                  false);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,
+                  true);
 
-  template <typename K = key_type>
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,
+                  false);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,
+                  true);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,
+                  false);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,
+                  true);
+
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false,
+                  false);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, true);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, false);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, true);
+
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,
+                  const &, false, false,
+                  const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,
+                  const &, false, true,
+                  const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,
+                  const &, true, false,
+                  const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,
+                  const &, true, true,
+                  const_iterator(hint) ABSL_INTERNAL_COMMA);
+
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,
+                  false, false, const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,
+                  false, true, const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,
+                  true, false, const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,
+                  true, true, const_iterator(hint) ABSL_INTERNAL_COMMA);
+
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,
+                  false, false, const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,
+                  false, true, const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,
+                  true, false, const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,
+                  true, true, const_iterator(hint) ABSL_INTERNAL_COMMA);
+
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, false,
+                  false, const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, false,
+                  true, const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, true,
+                  false, const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, true,
+                  true, const_iterator(hint) ABSL_INTERNAL_COMMA);
+#undef ABSL_INTERNAL_X
+
+#define ABSL_INTERNAL_X(Func, Callee, KQual, KValue, ...)                      \
+  template <                                                                   \
+      class K = key_type,                                                      \
+      ABSL_INTERNAL_IF_##KValue(                                               \
+          class... Args,                                                       \
+          int = (EnableIf<                                                     \
+                 LifetimeBoundK<K, KValue, IfRRef<int KQual>::AddPtr<K>>>())), \
+      ABSL_INTERNAL_IF_##KValue(                                               \
+          decltype(EnableIf<LifetimeBoundK<                                    \
+                       K, KValue, IfRRef<int KQual>::AddPtr<K>>>()) = 0,       \
+          class... Args),                                                      \
+      std::enable_if_t<!std::is_convertible<K, const_iterator>::value, int> =  \
+          0>                                                                   \
+  decltype(auto) Func(                                                         \
+      __VA_ARGS__ key_arg<K> KQual k ABSL_INTERNAL_IF_##KValue(                \
+          ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)),                          \
+      Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {                          \
+    return ABSL_INTERNAL_IF_##KValue((this->template Func<K, 0>), Callee)(     \
+        __VA_ARGS__ std::forward<decltype(k)>(k),                              \
+        std::forward<decltype(args)>(args)...);                                \
+  }                                                                            \
+  friend struct std::enable_if<false> /* just to force a semicolon */
+  ABSL_INTERNAL_X(try_emplace, try_emplace_impl, const &, false);
+  ABSL_INTERNAL_X(try_emplace, try_emplace_impl, const &, true);
+  ABSL_INTERNAL_X(try_emplace, try_emplace_impl, &&, false);
+  ABSL_INTERNAL_X(try_emplace, try_emplace_impl, &&, true);
+  ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, const &, false,
+                  const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, const &, true,
+                  const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, &&, false,
+                  const_iterator(hint) ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, &&, true,
+                  const_iterator(hint) ABSL_INTERNAL_COMMA);
+#undef ABSL_INTERNAL_X
+
+  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>()>
   mapped_type &operator[](const key_arg<K> &k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return try_emplace(k).first->second;
   }
-  template <typename K = key_type>
+  template <class K = key_type, int &..., EnableIf<LifetimeBoundK<K, true>> = 0>
+  mapped_type &operator[](
+      const key_arg<K> &k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))
+      ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template operator[]<K, 0>(k);
+  }
+  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>()>
   mapped_type &operator[](key_arg<K> &&k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return try_emplace(std::forward<K>(k)).first->second;
   }
+  template <class K = key_type, int &..., EnableIf<LifetimeBoundK<K, true>> = 0>
+  mapped_type &operator[](key_arg<K> &&k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(
+      this)) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template operator[]<K, 0>(std::forward<K>(k));
+  }
 
   template <typename K = key_type>
   mapped_type &at(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
diff --git a/absl/container/internal/common.h b/absl/container/internal/common.h
index 9239bb4..5ef6c56 100644
--- a/absl/container/internal/common.h
+++ b/absl/container/internal/common.h
@@ -21,10 +21,53 @@
 #include "absl/meta/type_traits.h"
 #include "absl/types/optional.h"
 
+// TODO(b/402804213): Clean up these macros when no longer needed.
+#define ABSL_INTERNAL_SINGLE_ARG(...) __VA_ARGS__
+
+#define ABSL_INTERNAL_IF_true(if_satisfied, ...) if_satisfied
+#define ABSL_INTERNAL_IF_false(if_satisfied, ...) __VA_ARGS__
+
+#define ABSL_INTERNAL_IF_true_AND_true ABSL_INTERNAL_IF_true
+#define ABSL_INTERNAL_IF_false_AND_false ABSL_INTERNAL_IF_false
+#define ABSL_INTERNAL_IF_true_AND_false ABSL_INTERNAL_IF_false_AND_false
+#define ABSL_INTERNAL_IF_false_AND_true ABSL_INTERNAL_IF_false_AND_false
+
+#define ABSL_INTERNAL_IF_true_OR_true ABSL_INTERNAL_IF_true
+#define ABSL_INTERNAL_IF_false_OR_false ABSL_INTERNAL_IF_false
+#define ABSL_INTERNAL_IF_true_OR_false ABSL_INTERNAL_IF_true_OR_true
+#define ABSL_INTERNAL_IF_false_OR_true ABSL_INTERNAL_IF_true_OR_true
+
+#define ABSL_INTERNAL_IF_true_NOR_true ABSL_INTERNAL_IF_false_AND_false
+#define ABSL_INTERNAL_IF_false_NOR_false ABSL_INTERNAL_IF_true_AND_true
+#define ABSL_INTERNAL_IF_true_NOR_false ABSL_INTERNAL_IF_false_AND_true
+#define ABSL_INTERNAL_IF_false_NOR_true ABSL_INTERNAL_IF_true_AND_false
+
+#define ABSL_INTERNAL_COMMA ,
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
+// TODO(b/402804213): Clean up these traits when no longer needed or
+// deduplicate them with absl::functional_internal::EnableIf.
+template <class Cond>
+using EnableIf = std::enable_if_t<Cond::value, int>;
+
+template <bool Value, class T>
+using HasValue = std::conditional_t<Value, T, absl::negation<T>>;
+
+template <class T>
+struct IfRRef {
+  template <class Other>
+  using AddPtr = Other;
+};
+
+template <class T>
+struct IfRRef<T&&> {
+  template <class Other>
+  using AddPtr = Other*;
+};
+
 template <class, class = void>
 struct IsTransparent : std::false_type {};
 template <class T>
diff --git a/absl/container/internal/common_policy_traits.h b/absl/container/internal/common_policy_traits.h
index c521f61..86e038e 100644
--- a/absl/container/internal/common_policy_traits.h
+++ b/absl/container/internal/common_policy_traits.h
@@ -28,6 +28,15 @@
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
+template <class Policy, class = void>
+struct policy_trait_element_is_owner : std::false_type {};
+
+template <class Policy>
+struct policy_trait_element_is_owner<
+    Policy,
+    std::enable_if_t<!std::is_void<typename Policy::element_is_owner>::value>>
+    : Policy::element_is_owner {};
+
 // Defines how slots are initialized/destroyed/moved.
 template <class Policy, class = void>
 struct common_policy_traits {
@@ -110,7 +119,7 @@
                                                            old_slot)) {
     return P::transfer(alloc, new_slot, old_slot);
   }
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+
   // This overload returns true_type for the trait below.
   // The conditional_t is to make the enabler type dependent.
   template <class Alloc,
@@ -126,7 +135,6 @@
         static_cast<const void*>(&element(old_slot)), sizeof(value_type));
     return {};
   }
-#endif
 
   template <class Alloc>
   static void transfer_impl(Alloc* alloc, slot_type* new_slot,
diff --git a/absl/container/internal/compressed_tuple_test.cc b/absl/container/internal/compressed_tuple_test.cc
index c3edf54..01b334e 100644
--- a/absl/container/internal/compressed_tuple_test.cc
+++ b/absl/container/internal/compressed_tuple_test.cc
@@ -386,20 +386,6 @@
 
   using Tuple = CompressedTuple<int, double, CompressedTuple<int>, Empty<0>>;
 
-  constexpr int r0 =
-      AsLValue(Tuple(1, 0.75, CompressedTuple<int>(9), {})).get<0>();
-  constexpr double r1 =
-      AsLValue(Tuple(1, 0.75, CompressedTuple<int>(9), {})).get<1>();
-  constexpr int r2 =
-      AsLValue(Tuple(1, 0.75, CompressedTuple<int>(9), {})).get<2>().get<0>();
-  constexpr CallType r3 =
-      AsLValue(Tuple(1, 0.75, CompressedTuple<int>(9), {})).get<3>().value();
-
-  EXPECT_EQ(r0, 1);
-  EXPECT_EQ(r1, 0.75);
-  EXPECT_EQ(r2, 9);
-  EXPECT_EQ(r3, CallType::kMutableRef);
-
   constexpr Tuple x(7, 1.25, CompressedTuple<int>(5), {});
   constexpr int x0 = x.get<0>();
   constexpr double x1 = x.get<1>();
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h
index ba8e08a..e7ac1db 100644
--- a/absl/container/internal/container_memory.h
+++ b/absl/container/internal/container_memory.h
@@ -17,6 +17,7 @@
 
 #include <cassert>
 #include <cstddef>
+#include <cstdint>
 #include <cstring>
 #include <memory>
 #include <new>
@@ -373,9 +374,6 @@
     return slot->value;
   }
 
-  // When C++17 is available, we can use std::launder to provide mutable
-  // access to the key for use in node handle.
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
   static K& mutable_key(slot_type* slot) {
     // Still check for kMutableKeys so that we can avoid calling std::launder
     // unless necessary because it can interfere with optimizations.
@@ -383,9 +381,6 @@
                                : *std::launder(const_cast<K*>(
                                      std::addressof(slot->value.first)));
   }
-#else  // !(defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606)
-  static const K& mutable_key(slot_type* slot) { return key(slot); }
-#endif
 
   static const K& key(const slot_type* slot) {
     return kMutableKeys::value ? slot->key : slot->value.first;
@@ -438,11 +433,17 @@
   template <class Allocator>
   static auto transfer(Allocator* alloc, slot_type* new_slot,
                        slot_type* old_slot) {
-    auto is_relocatable =
-        typename absl::is_trivially_relocatable<value_type>::type();
+    // This should really just be
+    // typename absl::is_trivially_relocatable<value_type>::type()
+    // but std::pair is not trivially copyable in C++23 in some standard
+    // library versions.
+    // See https://github.com/llvm/llvm-project/pull/95444 for instance.
+    auto is_relocatable = typename std::conjunction<
+        absl::is_trivially_relocatable<typename value_type::first_type>,
+        absl::is_trivially_relocatable<typename value_type::second_type>>::
+        type();
 
     emplace(new_slot);
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
     if (is_relocatable) {
       // TODO(b/247130232,b/251814870): remove casts after fixing warnings.
       std::memcpy(static_cast<void*>(std::launder(&new_slot->value)),
@@ -450,7 +451,6 @@
                   sizeof(value_type));
       return is_relocatable;
     }
-#endif
 
     if (kMutableKeys::value) {
       absl::allocator_traits<Allocator>::construct(
diff --git a/absl/container/internal/hash_function_defaults.h b/absl/container/internal/hash_function_defaults.h
index 0f07bcf..c2a757b 100644
--- a/absl/container/internal/hash_function_defaults.h
+++ b/absl/container/internal/hash_function_defaults.h
@@ -49,6 +49,7 @@
 #include <functional>
 #include <memory>
 #include <string>
+#include <string_view>
 #include <type_traits>
 
 #include "absl/base/config.h"
@@ -58,10 +59,6 @@
 #include "absl/strings/cord.h"
 #include "absl/strings/string_view.h"
 
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-#include <string_view>
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
@@ -113,8 +110,6 @@
 template <>
 struct HashEq<absl::Cord> : StringHashEq {};
 
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-
 template <typename TChar>
 struct BasicStringHash {
   using is_transparent = void;
@@ -153,8 +148,6 @@
 template <>
 struct HashEq<std::u32string_view> : BasicStringHashEq<char32_t> {};
 
-#endif  // ABSL_HAVE_STD_STRING_VIEW
-
 // Supports heterogeneous lookup for pointers and smart pointers.
 template <class T>
 struct HashEq<T*> {
diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc
index 912d119..9a39b07 100644
--- a/absl/container/internal/hash_function_defaults_test.cc
+++ b/absl/container/internal/hash_function_defaults_test.cc
@@ -16,6 +16,7 @@
 
 #include <cstddef>
 #include <functional>
+#include <string_view>
 #include <type_traits>
 #include <utility>
 
@@ -28,10 +29,6 @@
 #include "absl/strings/cord_test_helpers.h"
 #include "absl/strings/string_view.h"
 
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-#include <string_view>
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
@@ -118,9 +115,6 @@
 }
 
 TEST(BasicStringViewTest, WStringEqWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_eq<std::wstring> eq;
   EXPECT_TRUE(eq(L"a", L"a"));
   EXPECT_TRUE(eq(L"a", std::wstring_view(L"a")));
@@ -128,13 +122,9 @@
   EXPECT_FALSE(eq(L"a", L"b"));
   EXPECT_FALSE(eq(L"a", std::wstring_view(L"b")));
   EXPECT_FALSE(eq(L"a", std::wstring(L"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, WStringViewEqWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_eq<std::wstring_view> eq;
   EXPECT_TRUE(eq(L"a", L"a"));
   EXPECT_TRUE(eq(L"a", std::wstring_view(L"a")));
@@ -142,13 +132,9 @@
   EXPECT_FALSE(eq(L"a", L"b"));
   EXPECT_FALSE(eq(L"a", std::wstring_view(L"b")));
   EXPECT_FALSE(eq(L"a", std::wstring(L"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, U16StringEqWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_eq<std::u16string> eq;
   EXPECT_TRUE(eq(u"a", u"a"));
   EXPECT_TRUE(eq(u"a", std::u16string_view(u"a")));
@@ -156,13 +142,9 @@
   EXPECT_FALSE(eq(u"a", u"b"));
   EXPECT_FALSE(eq(u"a", std::u16string_view(u"b")));
   EXPECT_FALSE(eq(u"a", std::u16string(u"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, U16StringViewEqWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_eq<std::u16string_view> eq;
   EXPECT_TRUE(eq(u"a", u"a"));
   EXPECT_TRUE(eq(u"a", std::u16string_view(u"a")));
@@ -170,13 +152,9 @@
   EXPECT_FALSE(eq(u"a", u"b"));
   EXPECT_FALSE(eq(u"a", std::u16string_view(u"b")));
   EXPECT_FALSE(eq(u"a", std::u16string(u"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, U32StringEqWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_eq<std::u32string> eq;
   EXPECT_TRUE(eq(U"a", U"a"));
   EXPECT_TRUE(eq(U"a", std::u32string_view(U"a")));
@@ -184,13 +162,9 @@
   EXPECT_FALSE(eq(U"a", U"b"));
   EXPECT_FALSE(eq(U"a", std::u32string_view(U"b")));
   EXPECT_FALSE(eq(U"a", std::u32string(U"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, U32StringViewEqWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_eq<std::u32string_view> eq;
   EXPECT_TRUE(eq(U"a", U"a"));
   EXPECT_TRUE(eq(U"a", std::u32string_view(U"a")));
@@ -198,85 +172,60 @@
   EXPECT_FALSE(eq(U"a", U"b"));
   EXPECT_FALSE(eq(U"a", std::u32string_view(U"b")));
   EXPECT_FALSE(eq(U"a", std::u32string(U"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, WStringHashWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_hash<std::wstring> hash;
   auto h = hash(L"a");
   EXPECT_EQ(h, hash(std::wstring_view(L"a")));
   EXPECT_EQ(h, hash(std::wstring(L"a")));
   EXPECT_NE(h, hash(std::wstring_view(L"b")));
   EXPECT_NE(h, hash(std::wstring(L"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, WStringViewHashWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_hash<std::wstring_view> hash;
   auto h = hash(L"a");
   EXPECT_EQ(h, hash(std::wstring_view(L"a")));
   EXPECT_EQ(h, hash(std::wstring(L"a")));
   EXPECT_NE(h, hash(std::wstring_view(L"b")));
   EXPECT_NE(h, hash(std::wstring(L"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, U16StringHashWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_hash<std::u16string> hash;
   auto h = hash(u"a");
   EXPECT_EQ(h, hash(std::u16string_view(u"a")));
   EXPECT_EQ(h, hash(std::u16string(u"a")));
   EXPECT_NE(h, hash(std::u16string_view(u"b")));
   EXPECT_NE(h, hash(std::u16string(u"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, U16StringViewHashWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_hash<std::u16string_view> hash;
   auto h = hash(u"a");
   EXPECT_EQ(h, hash(std::u16string_view(u"a")));
   EXPECT_EQ(h, hash(std::u16string(u"a")));
   EXPECT_NE(h, hash(std::u16string_view(u"b")));
   EXPECT_NE(h, hash(std::u16string(u"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, U32StringHashWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_hash<std::u32string> hash;
   auto h = hash(U"a");
   EXPECT_EQ(h, hash(std::u32string_view(U"a")));
   EXPECT_EQ(h, hash(std::u32string(U"a")));
   EXPECT_NE(h, hash(std::u32string_view(U"b")));
   EXPECT_NE(h, hash(std::u32string(U"b")));
-#endif
 }
 
 TEST(BasicStringViewTest, U32StringViewHashWorks) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   hash_default_hash<std::u32string_view> hash;
   auto h = hash(U"a");
   EXPECT_EQ(h, hash(std::u32string_view(U"a")));
   EXPECT_EQ(h, hash(std::u32string(U"a")));
   EXPECT_NE(h, hash(std::u32string_view(U"b")));
   EXPECT_NE(h, hash(std::u32string(U"b")));
-#endif
 }
 
 struct NoDeleter {
diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc
index e89dfdb..be20e21 100644
--- a/absl/container/internal/hash_generator_testing.cc
+++ b/absl/container/internal/hash_generator_testing.cc
@@ -14,61 +14,39 @@
 
 #include "absl/container/internal/hash_generator_testing.h"
 
+#include <algorithm>
 #include <deque>
+#include <random>
+#include <string>
 
 #include "absl/base/no_destructor.h"
+#include "absl/random/random.h"
+#include "absl/strings/string_view.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace hash_internal {
-namespace {
-
-class RandomDeviceSeedSeq {
- public:
-  using result_type = typename std::random_device::result_type;
-
-  template <class Iterator>
-  void generate(Iterator start, Iterator end) {
-    while (start != end) {
-      *start = gen_();
-      ++start;
-    }
-  }
-
- private:
-  std::random_device gen_;
-};
-
-}  // namespace
-
-std::mt19937_64* GetSharedRng() {
-  static absl::NoDestructor<std::mt19937_64> rng([] {
-    RandomDeviceSeedSeq seed_seq;
-    return std::mt19937_64(seed_seq);
-  }());
-  return rng.get();
-}
 
 std::string Generator<std::string>::operator()() const {
+  absl::InsecureBitGen gen;
   // NOLINTNEXTLINE(runtime/int)
   std::uniform_int_distribution<short> chars(0x20, 0x7E);
   std::string res;
   res.resize(32);
-  std::generate(res.begin(), res.end(),
-                [&]() { return chars(*GetSharedRng()); });
+  std::generate(res.begin(), res.end(), [&]() { return chars(gen); });
   return res;
 }
 
 absl::string_view Generator<absl::string_view>::operator()() const {
   static absl::NoDestructor<std::deque<std::string>> arena;
+  absl::InsecureBitGen gen;
   // NOLINTNEXTLINE(runtime/int)
   std::uniform_int_distribution<short> chars(0x20, 0x7E);
   arena->emplace_back();
   auto& res = arena->back();
   res.resize(32);
-  std::generate(res.begin(), res.end(),
-                [&]() { return chars(*GetSharedRng()); });
+  std::generate(res.begin(), res.end(), [&]() { return chars(gen); });
   return res;
 }
 
diff --git a/absl/container/internal/hash_generator_testing.h b/absl/container/internal/hash_generator_testing.h
index f1f555a..14c878e 100644
--- a/absl/container/internal/hash_generator_testing.h
+++ b/absl/container/internal/hash_generator_testing.h
@@ -23,7 +23,9 @@
 #include <algorithm>
 #include <cassert>
 #include <iosfwd>
+#include <memory>
 #include <random>
+#include <string>
 #include <tuple>
 #include <type_traits>
 #include <utility>
@@ -32,6 +34,7 @@
 #include "absl/container/internal/hash_policy_testing.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
+#include "absl/random/random.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
@@ -48,9 +51,7 @@
 
 }  // namespace generator_internal
 
-std::mt19937_64* GetSharedRng();
-
-enum Enum {
+enum Enum : uint64_t {
   kEnumEmpty,
   kEnumDeleted,
 };
@@ -69,37 +70,27 @@
 
 template <class T>
 struct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> {
-  T operator()() const {
-    std::uniform_int_distribution<T> dist;
-    return dist(*GetSharedRng());
-  }
+  T operator()() const { return dist(gen); }
+  mutable absl::InsecureBitGen gen;
+  mutable std::uniform_int_distribution<T> dist;
 };
 
 template <>
 struct Generator<Enum> {
-  Enum operator()() const {
-    std::uniform_int_distribution<typename std::underlying_type<Enum>::type>
-        dist;
-    while (true) {
-      auto variate = dist(*GetSharedRng());
-      if (variate != kEnumEmpty && variate != kEnumDeleted)
-        return static_cast<Enum>(variate);
-    }
-  }
+  Enum operator()() const { return static_cast<Enum>(dist(gen)); }
+  mutable absl::InsecureBitGen gen;
+  mutable std::uniform_int_distribution<
+      typename std::underlying_type<Enum>::type>
+      dist;
 };
 
 template <>
 struct Generator<EnumClass> {
-  EnumClass operator()() const {
-    std::uniform_int_distribution<
-        typename std::underlying_type<EnumClass>::type>
-        dist;
-    while (true) {
-      EnumClass variate = static_cast<EnumClass>(dist(*GetSharedRng()));
-      if (variate != EnumClass::kEmpty && variate != EnumClass::kDeleted)
-        return static_cast<EnumClass>(variate);
-    }
-  }
+  EnumClass operator()() const { return static_cast<EnumClass>(dist(gen)); }
+  mutable absl::InsecureBitGen gen;
+  mutable std::uniform_int_distribution<
+      typename std::underlying_type<EnumClass>::type>
+      dist;
 };
 
 template <>
@@ -143,17 +134,17 @@
 
 template <class U>
 struct Generator<U, absl::void_t<decltype(std::declval<U&>().key()),
-                                decltype(std::declval<U&>().value())>>
+                                 decltype(std::declval<U&>().value())>>
     : Generator<std::pair<
           typename std::decay<decltype(std::declval<U&>().key())>::type,
           typename std::decay<decltype(std::declval<U&>().value())>::type>> {};
 
 template <class Container>
-using GeneratedType = decltype(
-    std::declval<const Generator<
-        typename std::conditional<generator_internal::IsMap<Container>::value,
-                                  typename Container::value_type,
-                                  typename Container::key_type>::type>&>()());
+using GeneratedType =
+    decltype(std::declval<const Generator<typename std::conditional<
+                 generator_internal::IsMap<Container>::value,
+                 typename Container::value_type,
+                 typename Container::key_type>::type>&>()());
 
 // Naive wrapper that performs a linear search of previous values.
 // Beware this is O(SQR), which is reasonable for smaller kMaxValues.
diff --git a/absl/container/internal/hash_policy_testing.h b/absl/container/internal/hash_policy_testing.h
index 66bb12e..e9f5757 100644
--- a/absl/container/internal/hash_policy_testing.h
+++ b/absl/container/internal/hash_policy_testing.h
@@ -119,7 +119,11 @@
   using propagate_on_container_swap = std::true_type;
 
   // Using old paradigm for this to ensure compatibility.
-  explicit Alloc(size_t id = 0) : id_(id) {}
+  //
+  // NOTE: As of 2025-05, this constructor cannot be explicit in order to work
+  // with the libstdc++ that ships with GCC15.
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  Alloc(size_t id = 0) : id_(id) {}
 
   Alloc(const Alloc&) = default;
   Alloc& operator=(const Alloc&) = default;
diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h
index ad835d6..cd6b42f 100644
--- a/absl/container/internal/hash_policy_traits.h
+++ b/absl/container/internal/hash_policy_traits.h
@@ -36,16 +36,12 @@
 
  private:
   struct ReturnKey {
-    // When C++17 is available, we can use std::launder to provide mutable
-    // access to the key for use in node handle.
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
     template <class Key,
               absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
     static key_type& Impl(Key&& k, int) {
       return *std::launder(
           const_cast<key_type*>(std::addressof(std::forward<Key>(k))));
     }
-#endif
 
     template <class Key>
     static Key Impl(Key&& k, char) {
diff --git a/absl/container/internal/hashtable_control_bytes.h b/absl/container/internal/hashtable_control_bytes.h
new file mode 100644
index 0000000..abaadc3
--- /dev/null
+++ b/absl/container/internal/hashtable_control_bytes.h
@@ -0,0 +1,527 @@
+// Copyright 2025 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.
+//
+// This file contains the implementation of the hashtable control bytes
+// manipulation.
+
+#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLE_CONTROL_BYTES_H_
+#define ABSL_CONTAINER_INTERNAL_HASHTABLE_CONTROL_BYTES_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+#include "absl/base/config.h"
+
+#ifdef ABSL_INTERNAL_HAVE_SSE2
+#include <emmintrin.h>
+#endif
+
+#ifdef ABSL_INTERNAL_HAVE_SSSE3
+#include <tmmintrin.h>
+#endif
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+#ifdef ABSL_INTERNAL_HAVE_ARM_NEON
+#include <arm_neon.h>
+#endif
+
+#include "absl/base/optimization.h"
+#include "absl/numeric/bits.h"
+#include "absl/base/internal/endian.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+#ifdef ABSL_SWISSTABLE_ASSERT
+#error ABSL_SWISSTABLE_ASSERT cannot be directly set
+#else
+// We use this macro for assertions that users may see when the table is in an
+// invalid state that sanitizers may help diagnose.
+#define ABSL_SWISSTABLE_ASSERT(CONDITION) \
+  assert((CONDITION) && "Try enabling sanitizers.")
+#endif
+
+
+template <typename T>
+uint32_t TrailingZeros(T x) {
+  ABSL_ASSUME(x != 0);
+  return static_cast<uint32_t>(countr_zero(x));
+}
+
+// 8 bytes bitmask with most significant bit set for every byte.
+constexpr uint64_t kMsbs8Bytes = 0x8080808080808080ULL;
+// 8 kEmpty bytes that is useful for small table initialization.
+constexpr uint64_t k8EmptyBytes = kMsbs8Bytes;
+
+// An abstract bitmask, such as that emitted by a SIMD instruction.
+//
+// Specifically, this type implements a simple bitset whose representation is
+// controlled by `SignificantBits` and `Shift`. `SignificantBits` is the number
+// of abstract bits in the bitset, while `Shift` is the log-base-two of the
+// width of an abstract bit in the representation.
+// This mask provides operations for any number of real bits set in an abstract
+// bit. To add iteration on top of that, implementation must guarantee no more
+// than the most significant real bit is set in a set abstract bit.
+template <class T, int SignificantBits, int Shift = 0>
+class NonIterableBitMask {
+ public:
+  explicit NonIterableBitMask(T mask) : mask_(mask) {}
+
+  explicit operator bool() const { return this->mask_ != 0; }
+
+  // Returns the index of the lowest *abstract* bit set in `self`.
+  uint32_t LowestBitSet() const {
+    return container_internal::TrailingZeros(mask_) >> Shift;
+  }
+
+  // Returns the index of the highest *abstract* bit set in `self`.
+  uint32_t HighestBitSet() const {
+    return static_cast<uint32_t>((bit_width(mask_) - 1) >> Shift);
+  }
+
+  // Returns the number of trailing zero *abstract* bits.
+  uint32_t TrailingZeros() const {
+    return container_internal::TrailingZeros(mask_) >> Shift;
+  }
+
+  // Returns the number of leading zero *abstract* bits.
+  uint32_t LeadingZeros() const {
+    constexpr int total_significant_bits = SignificantBits << Shift;
+    constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;
+    return static_cast<uint32_t>(
+               countl_zero(static_cast<T>(mask_ << extra_bits))) >>
+           Shift;
+  }
+
+  T mask_;
+};
+
+// Mask that can be iterable
+//
+// For example, when `SignificantBits` is 16 and `Shift` is zero, this is just
+// an ordinary 16-bit bitset occupying the low 16 bits of `mask`. When
+// `SignificantBits` is 8 and `Shift` is 3, abstract bits are represented as
+// the bytes `0x00` and `0x80`, and it occupies all 64 bits of the bitmask.
+// If NullifyBitsOnIteration is true (only allowed for Shift == 3),
+// non zero abstract bit is allowed to have additional bits
+// (e.g., `0xff`, `0x83` and `0x9c` are ok, but `0x6f` is not).
+//
+// For example:
+//   for (int i : BitMask<uint32_t, 16>(0b101)) -> yields 0, 2
+//   for (int i : BitMask<uint64_t, 8, 3>(0x0000000080800000)) -> yields 2, 3
+template <class T, int SignificantBits, int Shift = 0,
+          bool NullifyBitsOnIteration = false>
+class BitMask : public NonIterableBitMask<T, SignificantBits, Shift> {
+  using Base = NonIterableBitMask<T, SignificantBits, Shift>;
+  static_assert(std::is_unsigned<T>::value, "");
+  static_assert(Shift == 0 || Shift == 3, "");
+  static_assert(!NullifyBitsOnIteration || Shift == 3, "");
+
+ public:
+  explicit BitMask(T mask) : Base(mask) {
+    if (Shift == 3 && !NullifyBitsOnIteration) {
+      ABSL_SWISSTABLE_ASSERT(this->mask_ == (this->mask_ & kMsbs8Bytes));
+    }
+  }
+  // BitMask is an iterator over the indices of its abstract bits.
+  using value_type = int;
+  using iterator = BitMask;
+  using const_iterator = BitMask;
+
+  BitMask& operator++() {
+    if (Shift == 3 && NullifyBitsOnIteration) {
+      this->mask_ &= kMsbs8Bytes;
+    }
+    this->mask_ &= (this->mask_ - 1);
+    return *this;
+  }
+
+  uint32_t operator*() const { return Base::LowestBitSet(); }
+
+  BitMask begin() const { return *this; }
+  BitMask end() const { return BitMask(0); }
+
+ private:
+  friend bool operator==(const BitMask& a, const BitMask& b) {
+    return a.mask_ == b.mask_;
+  }
+  friend bool operator!=(const BitMask& a, const BitMask& b) {
+    return a.mask_ != b.mask_;
+  }
+};
+
+using h2_t = uint8_t;
+
+// The values here are selected for maximum performance. See the static asserts
+// below for details.
+
+// A `ctrl_t` is a single control byte, which can have one of four
+// states: empty, deleted, full (which has an associated seven-bit h2_t value)
+// and the sentinel. They have the following bit patterns:
+//
+//      empty: 1 0 0 0 0 0 0 0
+//    deleted: 1 1 1 1 1 1 1 0
+//       full: 0 h h h h h h h  // h represents the hash bits.
+//   sentinel: 1 1 1 1 1 1 1 1
+//
+// These values are specifically tuned for SSE-flavored SIMD.
+// The static_asserts below detail the source of these choices.
+//
+// We use an enum class so that when strict aliasing is enabled, the compiler
+// knows ctrl_t doesn't alias other types.
+enum class ctrl_t : int8_t {
+  kEmpty = -128,   // 0b10000000
+  kDeleted = -2,   // 0b11111110
+  kSentinel = -1,  // 0b11111111
+};
+static_assert(
+    (static_cast<int8_t>(ctrl_t::kEmpty) &
+     static_cast<int8_t>(ctrl_t::kDeleted) &
+     static_cast<int8_t>(ctrl_t::kSentinel) & 0x80) != 0,
+    "Special markers need to have the MSB to make checking for them efficient");
+static_assert(
+    ctrl_t::kEmpty < ctrl_t::kSentinel && ctrl_t::kDeleted < ctrl_t::kSentinel,
+    "ctrl_t::kEmpty and ctrl_t::kDeleted must be smaller than "
+    "ctrl_t::kSentinel to make the SIMD test of IsEmptyOrDeleted() efficient");
+static_assert(
+    ctrl_t::kSentinel == static_cast<ctrl_t>(-1),
+    "ctrl_t::kSentinel must be -1 to elide loading it from memory into SIMD "
+    "registers (pcmpeqd xmm, xmm)");
+static_assert(ctrl_t::kEmpty == static_cast<ctrl_t>(-128),
+              "ctrl_t::kEmpty must be -128 to make the SIMD check for its "
+              "existence efficient (psignb xmm, xmm)");
+static_assert(
+    (~static_cast<int8_t>(ctrl_t::kEmpty) &
+     ~static_cast<int8_t>(ctrl_t::kDeleted) &
+     static_cast<int8_t>(ctrl_t::kSentinel) & 0x7F) != 0,
+    "ctrl_t::kEmpty and ctrl_t::kDeleted must share an unset bit that is not "
+    "shared by ctrl_t::kSentinel to make the scalar test for "
+    "MaskEmptyOrDeleted() efficient");
+static_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2),
+              "ctrl_t::kDeleted must be -2 to make the implementation of "
+              "ConvertSpecialToEmptyAndFullToDeleted efficient");
+
+// Helpers for checking the state of a control byte.
+inline bool IsEmpty(ctrl_t c) { return c == ctrl_t::kEmpty; }
+inline bool IsFull(ctrl_t c) {
+  // Cast `c` to the underlying type instead of casting `0` to `ctrl_t` as `0`
+  // is not a value in the enum. Both ways are equivalent, but this way makes
+  // linters happier.
+  return static_cast<std::underlying_type_t<ctrl_t>>(c) >= 0;
+}
+inline bool IsDeleted(ctrl_t c) { return c == ctrl_t::kDeleted; }
+inline bool IsEmptyOrDeleted(ctrl_t c) { return c < ctrl_t::kSentinel; }
+
+#ifdef ABSL_INTERNAL_HAVE_SSE2
+// Quick reference guide for intrinsics used below:
+//
+// * __m128i: An XMM (128-bit) word.
+//
+// * _mm_setzero_si128: Returns a zero vector.
+// * _mm_set1_epi8:     Returns a vector with the same i8 in each lane.
+//
+// * _mm_subs_epi8:    Saturating-subtracts two i8 vectors.
+// * _mm_and_si128:    Ands two i128s together.
+// * _mm_or_si128:     Ors two i128s together.
+// * _mm_andnot_si128: And-nots two i128s together.
+//
+// * _mm_cmpeq_epi8: Component-wise compares two i8 vectors for equality,
+//                   filling each lane with 0x00 or 0xff.
+// * _mm_cmpgt_epi8: Same as above, but using > rather than ==.
+//
+// * _mm_loadu_si128:  Performs an unaligned load of an i128.
+// * _mm_storeu_si128: Performs an unaligned store of an i128.
+//
+// * _mm_sign_epi8:     Retains, negates, or zeroes each i8 lane of the first
+//                      argument if the corresponding lane of the second
+//                      argument is positive, negative, or zero, respectively.
+// * _mm_movemask_epi8: Selects the sign bit out of each i8 lane and produces a
+//                      bitmask consisting of those bits.
+// * _mm_shuffle_epi8:  Selects i8s from the first argument, using the low
+//                      four bits of each i8 lane in the second argument as
+//                      indices.
+
+// https://github.com/abseil/abseil-cpp/issues/209
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
+// _mm_cmpgt_epi8 is broken under GCC with -funsigned-char
+// Work around this by using the portable implementation of Group
+// when using -funsigned-char under GCC.
+inline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) {
+#if defined(__GNUC__) && !defined(__clang__)
+  if (std::is_unsigned<char>::value) {
+    const __m128i mask = _mm_set1_epi8(0x80);
+    const __m128i diff = _mm_subs_epi8(b, a);
+    return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask);
+  }
+#endif
+  return _mm_cmpgt_epi8(a, b);
+}
+
+struct GroupSse2Impl {
+  static constexpr size_t kWidth = 16;  // the number of slots per group
+  using BitMaskType = BitMask<uint16_t, kWidth>;
+  using NonIterableBitMaskType = NonIterableBitMask<uint16_t, kWidth>;
+
+  explicit GroupSse2Impl(const ctrl_t* pos) {
+    ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos));
+  }
+
+  // Returns a bitmask representing the positions of slots that match hash.
+  BitMaskType Match(h2_t hash) const {
+    auto match = _mm_set1_epi8(static_cast<char>(hash));
+    return BitMaskType(
+        static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
+  }
+
+  // Returns a bitmask representing the positions of empty slots.
+  NonIterableBitMaskType MaskEmpty() const {
+#ifdef ABSL_INTERNAL_HAVE_SSSE3
+    // This only works because ctrl_t::kEmpty is -128.
+    return NonIterableBitMaskType(
+        static_cast<uint16_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl))));
+#else
+    auto match = _mm_set1_epi8(static_cast<char>(ctrl_t::kEmpty));
+    return NonIterableBitMaskType(
+        static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
+#endif
+  }
+
+  // Returns a bitmask representing the positions of full slots.
+  // Note: for `is_small()` tables group may contain the "same" slot twice:
+  // original and mirrored.
+  BitMaskType MaskFull() const {
+    return BitMaskType(static_cast<uint16_t>(_mm_movemask_epi8(ctrl) ^ 0xffff));
+  }
+
+  // Returns a bitmask representing the positions of non full slots.
+  // Note: this includes: kEmpty, kDeleted, kSentinel.
+  // It is useful in contexts when kSentinel is not present.
+  auto MaskNonFull() const {
+    return BitMaskType(static_cast<uint16_t>(_mm_movemask_epi8(ctrl)));
+  }
+
+  // Returns a bitmask representing the positions of empty or deleted slots.
+  NonIterableBitMaskType MaskEmptyOrDeleted() const {
+    auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
+    return NonIterableBitMaskType(static_cast<uint16_t>(
+        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl))));
+  }
+
+  // Returns the number of trailing empty or deleted elements in the group.
+  uint32_t CountLeadingEmptyOrDeleted() const {
+    auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
+    return TrailingZeros(static_cast<uint32_t>(
+        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
+  }
+
+  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
+    auto msbs = _mm_set1_epi8(static_cast<char>(-128));
+    auto x126 = _mm_set1_epi8(126);
+#ifdef ABSL_INTERNAL_HAVE_SSSE3
+    auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
+#else
+    auto zero = _mm_setzero_si128();
+    auto special_mask = _mm_cmpgt_epi8_fixed(zero, ctrl);
+    auto res = _mm_or_si128(msbs, _mm_andnot_si128(special_mask, x126));
+#endif
+    _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res);
+  }
+
+  __m128i ctrl;
+};
+#endif  // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+
+#if defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
+struct GroupAArch64Impl {
+  static constexpr size_t kWidth = 8;
+  using BitMaskType = BitMask<uint64_t, kWidth, /*Shift=*/3,
+                              /*NullifyBitsOnIteration=*/true>;
+  using NonIterableBitMaskType =
+      NonIterableBitMask<uint64_t, kWidth, /*Shift=*/3>;
+
+  explicit GroupAArch64Impl(const ctrl_t* pos) {
+    ctrl = vld1_u8(reinterpret_cast<const uint8_t*>(pos));
+  }
+
+  auto Match(h2_t hash) const {
+    uint8x8_t dup = vdup_n_u8(hash);
+    auto mask = vceq_u8(ctrl, dup);
+    return BitMaskType(vget_lane_u64(vreinterpret_u64_u8(mask), 0));
+  }
+
+  auto MaskEmpty() const {
+    uint64_t mask =
+        vget_lane_u64(vreinterpret_u64_u8(vceq_s8(
+                          vdup_n_s8(static_cast<int8_t>(ctrl_t::kEmpty)),
+                          vreinterpret_s8_u8(ctrl))),
+                      0);
+    return NonIterableBitMaskType(mask);
+  }
+
+  // Returns a bitmask representing the positions of full slots.
+  // Note: for `is_small()` tables group may contain the "same" slot twice:
+  // original and mirrored.
+  auto MaskFull() const {
+    uint64_t mask = vget_lane_u64(
+        vreinterpret_u64_u8(vcge_s8(vreinterpret_s8_u8(ctrl),
+                                    vdup_n_s8(static_cast<int8_t>(0)))),
+        0);
+    return BitMaskType(mask);
+  }
+
+  // Returns a bitmask representing the positions of non full slots.
+  // Note: this includes: kEmpty, kDeleted, kSentinel.
+  // It is useful in contexts when kSentinel is not present.
+  auto MaskNonFull() const {
+    uint64_t mask = vget_lane_u64(
+        vreinterpret_u64_u8(vclt_s8(vreinterpret_s8_u8(ctrl),
+                                    vdup_n_s8(static_cast<int8_t>(0)))),
+        0);
+    return BitMaskType(mask);
+  }
+
+  auto MaskEmptyOrDeleted() const {
+    uint64_t mask =
+        vget_lane_u64(vreinterpret_u64_u8(vcgt_s8(
+                          vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
+                          vreinterpret_s8_u8(ctrl))),
+                      0);
+    return NonIterableBitMaskType(mask);
+  }
+
+  uint32_t CountLeadingEmptyOrDeleted() const {
+    uint64_t mask =
+        vget_lane_u64(vreinterpret_u64_u8(vcle_s8(
+                          vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
+                          vreinterpret_s8_u8(ctrl))),
+                      0);
+    // Similar to MaskEmptyorDeleted() but we invert the logic to invert the
+    // produced bitfield. We then count number of trailing zeros.
+    // Clang and GCC optimize countr_zero to rbit+clz without any check for 0,
+    // so we should be fine.
+    return static_cast<uint32_t>(countr_zero(mask)) >> 3;
+  }
+
+  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
+    uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0);
+    constexpr uint64_t slsbs = 0x0202020202020202ULL;
+    constexpr uint64_t midbs = 0x7e7e7e7e7e7e7e7eULL;
+    auto x = slsbs & (mask >> 6);
+    auto res = (x + midbs) | kMsbs8Bytes;
+    little_endian::Store64(dst, res);
+  }
+
+  uint8x8_t ctrl;
+};
+#endif  // ABSL_INTERNAL_HAVE_ARM_NEON && ABSL_IS_LITTLE_ENDIAN
+
+struct GroupPortableImpl {
+  static constexpr size_t kWidth = 8;
+  using BitMaskType = BitMask<uint64_t, kWidth, /*Shift=*/3,
+                              /*NullifyBitsOnIteration=*/false>;
+  using NonIterableBitMaskType =
+      NonIterableBitMask<uint64_t, kWidth, /*Shift=*/3>;
+
+  explicit GroupPortableImpl(const ctrl_t* pos)
+      : ctrl(little_endian::Load64(pos)) {}
+
+  BitMaskType Match(h2_t hash) const {
+    // For the technique, see:
+    // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
+    // (Determine if a word has a byte equal to n).
+    //
+    // Caveat: there are false positives but:
+    // - they only occur if there is a real match
+    // - they never occur on ctrl_t::kEmpty, ctrl_t::kDeleted, ctrl_t::kSentinel
+    // - they will be handled gracefully by subsequent checks in code
+    //
+    // Example:
+    //   v = 0x1716151413121110
+    //   hash = 0x12
+    //   retval = (v - lsbs) & ~v & msbs = 0x0000000080800000
+    constexpr uint64_t lsbs = 0x0101010101010101ULL;
+    auto x = ctrl ^ (lsbs * hash);
+    return BitMaskType((x - lsbs) & ~x & kMsbs8Bytes);
+  }
+
+  auto MaskEmpty() const {
+    return NonIterableBitMaskType((ctrl & ~(ctrl << 6)) & kMsbs8Bytes);
+  }
+
+  // Returns a bitmask representing the positions of full slots.
+  // Note: for `is_small()` tables group may contain the "same" slot twice:
+  // original and mirrored.
+  auto MaskFull() const {
+    return BitMaskType((ctrl ^ kMsbs8Bytes) & kMsbs8Bytes);
+  }
+
+  // Returns a bitmask representing the positions of non full slots.
+  // Note: this includes: kEmpty, kDeleted, kSentinel.
+  // It is useful in contexts when kSentinel is not present.
+  auto MaskNonFull() const { return BitMaskType(ctrl & kMsbs8Bytes); }
+
+  auto MaskEmptyOrDeleted() const {
+    return NonIterableBitMaskType((ctrl & ~(ctrl << 7)) & kMsbs8Bytes);
+  }
+
+  uint32_t CountLeadingEmptyOrDeleted() const {
+    // ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and
+    // kDeleted. We lower all other bits and count number of trailing zeros.
+    constexpr uint64_t bits = 0x0101010101010101ULL;
+    return static_cast<uint32_t>(countr_zero((ctrl | ~(ctrl >> 7)) & bits) >>
+                                 3);
+  }
+
+  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
+    constexpr uint64_t lsbs = 0x0101010101010101ULL;
+    auto x = ctrl & kMsbs8Bytes;
+    auto res = (~x + (x >> 7)) & ~lsbs;
+    little_endian::Store64(dst, res);
+  }
+
+  uint64_t ctrl;
+};
+
+#ifdef ABSL_INTERNAL_HAVE_SSE2
+using Group = GroupSse2Impl;
+using GroupFullEmptyOrDeleted = GroupSse2Impl;
+#elif defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
+using Group = GroupAArch64Impl;
+// For Aarch64, we use the portable implementation for counting and masking
+// full, empty or deleted group elements. This is to avoid the latency of moving
+// between data GPRs and Neon registers when it does not provide a benefit.
+// Using Neon is profitable when we call Match(), but is not when we don't,
+// which is the case when we do *EmptyOrDeleted and MaskFull operations.
+// It is difficult to make a similar approach beneficial on other architectures
+// such as x86 since they have much lower GPR <-> vector register transfer
+// latency and 16-wide Groups.
+using GroupFullEmptyOrDeleted = GroupPortableImpl;
+#else
+using Group = GroupPortableImpl;
+using GroupFullEmptyOrDeleted = GroupPortableImpl;
+#endif
+
+}  // namespace container_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#undef ABSL_SWISSTABLE_ASSERT
+
+#endif  // ABSL_CONTAINER_INTERNAL_HASHTABLE_CONTROL_BYTES_H_
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
index fd21d96..c0fce87 100644
--- a/absl/container/internal/hashtablez_sampler.cc
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -42,10 +42,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr int HashtablezInfo::kMaxStackDepth;
-#endif
-
 namespace {
 ABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{
     false
@@ -126,6 +122,26 @@
   return state == kForce;
 }
 
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+HashtablezInfoHandle ForcedTrySample(size_t inline_element_size,
+                                     size_t key_size, size_t value_size,
+                                     uint16_t soo_capacity) {
+  return HashtablezInfoHandle(SampleSlow(global_next_sample,
+                                         inline_element_size, key_size,
+                                         value_size, soo_capacity));
+}
+void TestOnlyRefreshSamplingStateForCurrentThread() {
+  global_next_sample.next_sample =
+      g_hashtablez_sample_parameter.load(std::memory_order_relaxed);
+  global_next_sample.sample_stride = global_next_sample.next_sample;
+}
+#else
+HashtablezInfoHandle ForcedTrySample(size_t, size_t, size_t, uint16_t) {
+  return HashtablezInfoHandle{nullptr};
+}
+void TestOnlyRefreshSamplingStateForCurrentThread() {}
+#endif  // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
+
 HashtablezInfo* SampleSlow(SamplingState& next_sample,
                            size_t inline_element_size, size_t key_size,
                            size_t value_size, uint16_t soo_capacity) {
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index d74acf8..305dc85 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -219,22 +219,41 @@
 extern ABSL_PER_THREAD_TLS_KEYWORD SamplingState global_next_sample;
 #endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
-// Returns a sampling handle.
-inline HashtablezInfoHandle Sample(
-    ABSL_ATTRIBUTE_UNUSED size_t inline_element_size,
-    ABSL_ATTRIBUTE_UNUSED size_t key_size,
-    ABSL_ATTRIBUTE_UNUSED size_t value_size,
-    ABSL_ATTRIBUTE_UNUSED uint16_t soo_capacity) {
+// Returns true if the next table should be sampled.
+// This function updates the global state.
+// If the function returns true, actual sampling should be done by calling
+// ForcedTrySample().
+inline bool ShouldSampleNextTable() {
 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
   if (ABSL_PREDICT_TRUE(--global_next_sample.next_sample > 0)) {
+    return false;
+  }
+  return true;
+#else
+  return false;
+#endif  // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
+}
+
+// Returns a sampling handle.
+// Must be called only if HashSetShouldBeSampled() returned true.
+// Returned handle still can be unsampled if sampling is not possible.
+HashtablezInfoHandle ForcedTrySample(size_t inline_element_size,
+                                     size_t key_size, size_t value_size,
+                                     uint16_t soo_capacity);
+
+// In case sampling needs to be disabled and re-enabled in tests, this function
+// can be used to reset the sampling state for the current thread.
+// It is useful to avoid sampling attempts and sampling delays in tests.
+void TestOnlyRefreshSamplingStateForCurrentThread();
+
+// Returns a sampling handle.
+inline HashtablezInfoHandle Sample(size_t inline_element_size, size_t key_size,
+                                   size_t value_size, uint16_t soo_capacity) {
+  if (ABSL_PREDICT_TRUE(!ShouldSampleNextTable())) {
     return HashtablezInfoHandle(nullptr);
   }
-  return HashtablezInfoHandle(SampleSlow(global_next_sample,
-                                         inline_element_size, key_size,
-                                         value_size, soo_capacity));
-#else
-  return HashtablezInfoHandle(nullptr);
-#endif  // !ABSL_PER_THREAD_TLS
+  return ForcedTrySample(inline_element_size, key_size, value_size,
+                         soo_capacity);
 }
 
 using HashtablezSampler =
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
index 24d3bc4..0de1e29 100644
--- a/absl/container/internal/hashtablez_sampler_test.cc
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -27,6 +27,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/profiling/internal/sample_recorder.h"
+#include "absl/random/random.h"
 #include "absl/synchronization/blocking_counter.h"
 #include "absl/synchronization/internal/thread_pool.h"
 #include "absl/synchronization/mutex.h"
@@ -439,8 +440,7 @@
     const size_t value_size = 13 + i % 5;
     pool.Schedule([&sampler, &stop, sampling_stride, elt_size, key_size,
                    value_size]() {
-      std::random_device rd;
-      std::mt19937 gen(rd());
+      absl::InsecureBitGen gen;
 
       std::vector<HashtablezInfo*> infoz;
       while (!stop.HasBeenNotified()) {
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
index 2f24e46..b0d3f07 100644
--- a/absl/container/internal/inlined_vector.h
+++ b/absl/container/internal/inlined_vector.h
@@ -73,18 +73,15 @@
 template <typename A>
 using MoveIterator = typename std::move_iterator<Iterator<A>>;
 
-template <typename Iterator>
-using IsAtLeastForwardIterator = std::is_convertible<
-    typename std::iterator_traits<Iterator>::iterator_category,
-    std::forward_iterator_tag>;
-
 template <typename A>
 using IsMoveAssignOk = std::is_move_assignable<ValueType<A>>;
 template <typename A>
 using IsSwapOk = absl::type_traits_internal::IsSwappable<ValueType<A>>;
 
-template <typename A, bool IsTriviallyDestructible =
-                          absl::is_trivially_destructible<ValueType<A>>::value>
+template <typename A,
+          bool IsTriviallyDestructible =
+              absl::is_trivially_destructible<ValueType<A>>::value &&
+              std::is_same<A, std::allocator<ValueType<A>>>::value>
 struct DestroyAdapter;
 
 template <typename A>
@@ -232,7 +229,7 @@
     return result.data;
   }
 
-  ABSL_MUST_USE_RESULT Allocation<A> Release() && {
+  [[nodiscard]] Allocation<A> Release() && {
     Allocation<A> result = {GetData(), GetCapacity()};
     Reset();
     return result;
@@ -546,7 +543,7 @@
       (std::max)(N, sizeof(Allocated) / sizeof(ValueType<A>));
 
   struct Inlined {
-    alignas(ValueType<A>) char inlined_data[sizeof(
+    alignas(ValueType<A>) unsigned char inlined_data[sizeof(
         ValueType<A>[kOptimalInlinedSize])];
   };
 
diff --git a/absl/container/internal/layout.h b/absl/container/internal/layout.h
index 384929a..58c8d4f 100644
--- a/absl/container/internal/layout.h
+++ b/absl/container/internal/layout.h
@@ -192,7 +192,6 @@
 #include <typeinfo>
 #include <utility>
 
-#include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/debugging/internal/demangle.h"
 #include "absl/meta/type_traits.h"
@@ -306,7 +305,7 @@
 template <class T>
 std::string TypeName() {
   std::string out;
-#if ABSL_INTERNAL_HAS_RTTI
+#ifdef ABSL_INTERNAL_HAS_RTTI
   absl::StrAppend(&out, "<",
                   absl::debugging_internal::DemangleString(typeid(T).name()),
                   ">");
@@ -316,9 +315,6 @@
 
 }  // namespace adl_barrier
 
-template <bool C>
-using EnableIf = typename std::enable_if<C, int>::type;
-
 // Can `T` be a template argument of `Layout`?
 template <class T>
 using IsLegalElementType = std::integral_constant<
@@ -418,17 +414,16 @@
   //   assert(x.Offset<1>() == 16);  // The doubles starts from 16.
   //
   // Requires: `N <= NumSizes && N < sizeof...(Ts)`.
-  template <size_t N, EnableIf<N == 0> = 0>
+  template <size_t N>
   constexpr size_t Offset() const {
-    return 0;
-  }
-
-  template <size_t N, EnableIf<N != 0> = 0>
-  constexpr size_t Offset() const {
-    static_assert(N < NumOffsets, "Index out of bounds");
-    return adl_barrier::Align(
-        Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>(),
-        ElementAlignment<N>::value);
+    if constexpr (N == 0) {
+      return 0;
+    } else {
+      static_assert(N < NumOffsets, "Index out of bounds");
+      return adl_barrier::Align(
+          Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>(),
+          ElementAlignment<N>::value);
+    }
   }
 
   // Offset in bytes of the array with the specified element type. There must
@@ -457,15 +452,14 @@
   //   assert(x.Size<1>() == 4);
   //
   // Requires: `N < NumSizes`.
-  template <size_t N, EnableIf<(N < NumStaticSizes)> = 0>
+  template <size_t N>
   constexpr size_t Size() const {
-    return kStaticSizes[N];
-  }
-
-  template <size_t N, EnableIf<(N >= NumStaticSizes)> = 0>
-  constexpr size_t Size() const {
-    static_assert(N < NumSizes, "Index out of bounds");
-    return size_[N - NumStaticSizes];
+    if constexpr (N < NumStaticSizes) {
+      return kStaticSizes[N];
+    } else {
+      static_assert(N < NumSizes, "Index out of bounds");
+      return size_[N - NumStaticSizes];
+    }
   }
 
   // The number of elements in the array with the specified element type.
@@ -596,10 +590,10 @@
   //
   // Requires: `p` is aligned to `Alignment()`.
   //
-  // Note: We mark the parameter as unused because GCC detects it is not used
-  // when `SizeSeq` is empty [-Werror=unused-but-set-parameter].
+  // Note: We mark the parameter as maybe_unused because GCC detects it is not
+  // used when `SizeSeq` is empty [-Werror=unused-but-set-parameter].
   template <class Char>
-  auto Slices(ABSL_ATTRIBUTE_UNUSED Char* p) const {
+  auto Slices([[maybe_unused]] Char* p) const {
     return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(
         Slice<SizeSeq>(p)...);
   }
@@ -624,15 +618,13 @@
   // `Char` must be `[const] [signed|unsigned] char`.
   //
   // Requires: `p` is aligned to `Alignment()`.
-  template <class Char, size_t N = NumOffsets - 1, EnableIf<N == 0> = 0>
+  template <class Char, size_t N = NumOffsets - 1>
   void PoisonPadding(const Char* p) const {
-    Pointer<0>(p);  // verify the requirements on `Char` and `p`
-  }
-
-  template <class Char, size_t N = NumOffsets - 1, EnableIf<N != 0> = 0>
-  void PoisonPadding(const Char* p) const {
-    static_assert(N < NumOffsets, "Index out of bounds");
-    (void)p;
+    if constexpr (N == 0) {
+      Pointer<0>(p);  // verify the requirements on `Char` and `p`
+    } else {
+      static_assert(N < NumOffsets, "Index out of bounds");
+      (void)p;
 #ifdef ABSL_HAVE_ADDRESS_SANITIZER
     PoisonPadding<Char, N - 1>(p);
     // The `if` is an optimization. It doesn't affect the observable behaviour.
@@ -642,6 +634,7 @@
       ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
     }
 #endif
+    }
   }
 
   // Human-readable description of the memory layout. Useful for debugging.
@@ -692,15 +685,6 @@
   size_t size_[NumRuntimeSizes > 0 ? NumRuntimeSizes : 1];
 };
 
-// Defining a constexpr static class member variable is redundant and deprecated
-// in C++17, but required in C++14.
-template <class... Elements, size_t... StaticSizeSeq, size_t... RuntimeSizeSeq,
-          size_t... SizeSeq, size_t... OffsetSeq>
-constexpr std::array<size_t, sizeof...(StaticSizeSeq)> LayoutImpl<
-    std::tuple<Elements...>, absl::index_sequence<StaticSizeSeq...>,
-    absl::index_sequence<RuntimeSizeSeq...>, absl::index_sequence<SizeSeq...>,
-    absl::index_sequence<OffsetSeq...>>::kStaticSizes;
-
 template <class StaticSizeSeq, size_t NumRuntimeSizes, class... Ts>
 using LayoutType = LayoutImpl<
     std::tuple<Ts...>, StaticSizeSeq,
diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h
index 464bf23..b42a4f2 100644
--- a/absl/container/internal/raw_hash_map.h
+++ b/absl/container/internal/raw_hash_map.h
@@ -22,8 +22,10 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/throw_delegate.h"
+#include "absl/container/internal/common_policy_traits.h"
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/raw_hash_set.h"  // IWYU pragma: export
+#include "absl/meta/type_traits.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -43,14 +45,39 @@
   using MappedConstReference = decltype(P::value(
       std::addressof(std::declval<typename raw_hash_map::const_reference>())));
 
-  using KeyArgImpl =
-      KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
+  template <class K>
+  using key_arg =
+      typename KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>::
+          template type<K, typename Policy::key_type>;
+
+  // NOTE: The mess here is to shorten the code for the (very repetitive)
+  // function overloads, and to allow the lifetime-bound overloads to dispatch
+  // to the non-lifetime-bound overloads, to ensure there is a single source of
+  // truth for each overload set.
+  //
+  // Enabled if an assignment from the given type would require the
+  // source object to remain alive for the life of the element.
+  //
+  // TODO(b/402804213): Remove these traits and simplify the overloads whenever
+  // we have a better mechanism available to handle lifetime analysis.
+  template <class K, bool Value, typename = void>
+  using LifetimeBoundK = HasValue<
+      Value, std::conditional_t<policy_trait_element_is_owner<Policy>::value,
+                                std::false_type,
+                                type_traits_internal::IsLifetimeBoundAssignment<
+                                    typename Policy::key_type, K>>>;
+  template <class V, bool Value, typename = void>
+  using LifetimeBoundV =
+      HasValue<Value, type_traits_internal::IsLifetimeBoundAssignment<
+                          typename Policy::mapped_type, V>>;
+  template <class K, bool KValue, class V, bool VValue, typename... Dummy>
+  using LifetimeBoundKV =
+      absl::conjunction<LifetimeBoundK<K, KValue, absl::void_t<Dummy...>>,
+                        LifetimeBoundV<V, VValue>>;
 
  public:
   using key_type = typename Policy::key_type;
   using mapped_type = typename Policy::mapped_type;
-  template <class K>
-  using key_arg = typename KeyArgImpl::template type<K, key_type>;
 
   static_assert(!std::is_reference<key_type>::value, "");
 
@@ -71,87 +98,175 @@
   //   union { int n : 1; };
   //   flat_hash_map<int, int> m;
   //   m.insert_or_assign(n, n);
-  template <class K = key_type, class V = mapped_type, K* = nullptr,
-            V* = nullptr>
-  std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, V&& v)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_impl(std::forward<K>(k), std::forward<V>(v));
-  }
+  //
+  // TODO(b/402804213): Remove these macros whenever we have a better mechanism
+  // available to handle lifetime analysis.
+#define ABSL_INTERNAL_X(Func, Callee, KQual, VQual, KValue, VValue, Tail, ...) \
+  template <                                                                   \
+      typename K = key_type, class V = mapped_type,                            \
+      ABSL_INTERNAL_IF_##KValue##_NOR_##VValue(                                \
+          int = (EnableIf<LifetimeBoundKV<K, KValue, V, VValue,                \
+                                          IfRRef<int KQual>::AddPtr<K>,        \
+                                          IfRRef<int VQual>::AddPtr<V>>>()),   \
+          ABSL_INTERNAL_SINGLE_ARG(                                            \
+              int &...,                                                        \
+              decltype(EnableIf<LifetimeBoundKV<K, KValue, V, VValue>>()) =    \
+                  0))>                                                         \
+  decltype(auto) Func(                                                         \
+      __VA_ARGS__ key_arg<K> KQual k ABSL_INTERNAL_IF_##KValue(                \
+          ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)),                          \
+      V VQual v ABSL_INTERNAL_IF_##VValue(ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY( \
+          this))) ABSL_ATTRIBUTE_LIFETIME_BOUND {                              \
+    return ABSL_INTERNAL_IF_##KValue##_OR_##VValue(                            \
+        (this->template Func<K, V, 0>), Callee)(                               \
+        std::forward<decltype(k)>(k), std::forward<decltype(v)>(v)) Tail;      \
+  }                                                                            \
+  static_assert(true, "This is to force a semicolon.")
 
-  template <class K = key_type, class V = mapped_type, K* = nullptr>
-  std::pair<iterator, bool> insert_or_assign(key_arg<K>&& k, const V& v)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_impl(std::forward<K>(k), v);
-  }
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  false, false, ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  false, true, ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  true, false, ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  true, true, ABSL_INTERNAL_SINGLE_ARG());
 
-  template <class K = key_type, class V = mapped_type, V* = nullptr>
-  std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, V&& v)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_impl(k, std::forward<V>(v));
-  }
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,
+                  false, ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,
+                  true, ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,
+                  false, ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,
+                  true, ABSL_INTERNAL_SINGLE_ARG());
 
-  template <class K = key_type, class V = mapped_type>
-  std::pair<iterator, bool> insert_or_assign(const key_arg<K>& k, const V& v)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign_impl(k, v);
-  }
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,
+                  false, ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,
+                  true, ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,
+                  false, ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,
+                  true, ABSL_INTERNAL_SINGLE_ARG());
 
-  template <class K = key_type, class V = mapped_type, K* = nullptr,
-            V* = nullptr>
-  iterator insert_or_assign(const_iterator, key_arg<K>&& k,
-                            V&& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign(std::forward<K>(k), std::forward<V>(v)).first;
-  }
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, false,
+                  ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, true,
+                  ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, false,
+                  ABSL_INTERNAL_SINGLE_ARG());
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, true,
+                  ABSL_INTERNAL_SINGLE_ARG());
 
-  template <class K = key_type, class V = mapped_type, K* = nullptr>
-  iterator insert_or_assign(const_iterator, key_arg<K>&& k,
-                            const V& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign(std::forward<K>(k), v).first;
-  }
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  false, false, .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  false, true, .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  true, false, .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
+                  true, true, .first, const_iterator ABSL_INTERNAL_COMMA);
 
-  template <class K = key_type, class V = mapped_type, V* = nullptr>
-  iterator insert_or_assign(const_iterator, const key_arg<K>& k,
-                            V&& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign(k, std::forward<V>(v)).first;
-  }
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,
+                  false, .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,
+                  true, .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,
+                  false, .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,
+                  true, .first, const_iterator ABSL_INTERNAL_COMMA);
 
-  template <class K = key_type, class V = mapped_type>
-  iterator insert_or_assign(const_iterator, const key_arg<K>& k,
-                            const V& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return insert_or_assign(k, v).first;
-  }
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,
+                  false, .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,
+                  true, .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,
+                  false, .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,
+                  true, .first, const_iterator ABSL_INTERNAL_COMMA);
+
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, false,
+                  .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, true,
+                  .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, false,
+                  .first, const_iterator ABSL_INTERNAL_COMMA);
+  ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, true,
+                  .first, const_iterator ABSL_INTERNAL_COMMA);
+#undef ABSL_INTERNAL_X
 
   // All `try_emplace()` overloads make the same guarantees regarding rvalue
   // arguments as `std::unordered_map::try_emplace()`, namely that these
   // functions will not move from rvalue arguments if insertions do not happen.
-  template <class K = key_type, class... Args,
+  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false, K *>>(),
+            class... Args,
             typename std::enable_if<
-                !std::is_convertible<K, const_iterator>::value, int>::type = 0,
-            K* = nullptr>
-  std::pair<iterator, bool> try_emplace(key_arg<K>&& k, Args&&... args)
+                !std::is_convertible<K, const_iterator>::value, int>::type = 0>
+  std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&...args)
       ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...);
   }
 
   template <class K = key_type, class... Args,
+            EnableIf<LifetimeBoundK<K, true, K *>> = 0,
             typename std::enable_if<
                 !std::is_convertible<K, const_iterator>::value, int>::type = 0>
-  std::pair<iterator, bool> try_emplace(const key_arg<K>& k, Args&&... args)
+  std::pair<iterator, bool> try_emplace(
+      key_arg<K> &&k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),
+      Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template try_emplace<K, 0>(std::forward<K>(k),
+                                            std::forward<Args>(args)...);
+  }
+
+  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>(),
+            class... Args,
+            typename std::enable_if<
+                !std::is_convertible<K, const_iterator>::value, int>::type = 0>
+  std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&...args)
       ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return try_emplace_impl(k, std::forward<Args>(args)...);
   }
-
-  template <class K = key_type, class... Args, K* = nullptr>
-  iterator try_emplace(const_iterator, key_arg<K>&& k,
-                       Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return try_emplace(std::forward<K>(k), std::forward<Args>(args)...).first;
+  template <class K = key_type, class... Args,
+            EnableIf<LifetimeBoundK<K, true>> = 0,
+            typename std::enable_if<
+                !std::is_convertible<K, const_iterator>::value, int>::type = 0>
+  std::pair<iterator, bool> try_emplace(
+      const key_arg<K> &k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),
+      Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template try_emplace<K, 0>(k, std::forward<Args>(args)...);
   }
 
-  template <class K = key_type, class... Args>
-  iterator try_emplace(const_iterator, const key_arg<K>& k,
-                       Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false, K *>>(),
+            class... Args>
+  iterator try_emplace(const_iterator, key_arg<K> &&k,
+                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return try_emplace(std::forward<K>(k), std::forward<Args>(args)...).first;
+  }
+  template <class K = key_type, class... Args,
+            EnableIf<LifetimeBoundK<K, true, K *>> = 0>
+  iterator try_emplace(const_iterator hint,
+                       key_arg<K> &&k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),
+                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template try_emplace<K, 0>(hint, std::forward<K>(k),
+                                            std::forward<Args>(args)...);
+  }
+
+  template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>(),
+            class... Args>
+  iterator try_emplace(const_iterator, const key_arg<K> &k,
+                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return try_emplace(k, std::forward<Args>(args)...).first;
   }
+  template <class K = key_type, class... Args,
+            EnableIf<LifetimeBoundK<K, true>> = 0>
+  iterator try_emplace(const_iterator hint,
+                       const key_arg<K> &k
+                           ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this),
+                       Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template try_emplace<K, 0>(hint, std::forward<K>(k),
+                                            std::forward<Args>(args)...);
+  }
 
   template <class K = key_type, class P = Policy>
   MappedReference<P> at(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
@@ -174,8 +289,9 @@
     return Policy::value(&*it);
   }
 
-  template <class K = key_type, class P = Policy, K* = nullptr>
-  MappedReference<P> operator[](key_arg<K>&& key)
+  template <class K = key_type, class P = Policy,
+            int = EnableIf<LifetimeBoundK<K, false, K *>>()>
+  MappedReference<P> operator[](key_arg<K> &&key)
       ABSL_ATTRIBUTE_LIFETIME_BOUND {
     // It is safe to use unchecked_deref here because try_emplace
     // will always return an iterator pointing to a valid item in the table,
@@ -183,15 +299,30 @@
     return Policy::value(
         &this->unchecked_deref(try_emplace(std::forward<K>(key)).first));
   }
+  template <class K = key_type, class P = Policy, int &...,
+            EnableIf<LifetimeBoundK<K, true, K *>> = 0>
+  MappedReference<P> operator[](
+      key_arg<K> &&key ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))
+      ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template operator[]<K, P, 0>(std::forward<K>(key));
+  }
 
-  template <class K = key_type, class P = Policy>
-  MappedReference<P> operator[](const key_arg<K>& key)
+  template <class K = key_type, class P = Policy,
+            int = EnableIf<LifetimeBoundK<K, false>>()>
+  MappedReference<P> operator[](const key_arg<K> &key)
       ABSL_ATTRIBUTE_LIFETIME_BOUND {
     // It is safe to use unchecked_deref here because try_emplace
     // will always return an iterator pointing to a valid item in the table,
     // since it inserts if nothing is found for the given key.
     return Policy::value(&this->unchecked_deref(try_emplace(key).first));
   }
+  template <class K = key_type, class P = Policy, int &...,
+            EnableIf<LifetimeBoundK<K, true>> = 0>
+  MappedReference<P> operator[](
+      const key_arg<K> &key ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))
+      ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template operator[]<K, P, 0>(key);
+  }
 
  private:
   template <class K, class V>
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index 1cae038..339e662 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -24,9 +24,13 @@
 #include "absl/base/config.h"
 #include "absl/base/dynamic_annotations.h"
 #include "absl/base/internal/endian.h"
+#include "absl/base/internal/raw_logging.h"
 #include "absl/base/optimization.h"
 #include "absl/container/internal/container_memory.h"
+#include "absl/container/internal/hashtable_control_bytes.h"
 #include "absl/container/internal/hashtablez_sampler.h"
+#include "absl/container/internal/raw_hash_set_resize_impl.h"
+#include "absl/functional/function_ref.h"
 #include "absl/hash/hash.h"
 
 namespace absl {
@@ -63,21 +67,31 @@
 static_assert(NumControlBytes(SooCapacity()) <= 17,
               "kSooControl capacity too small");
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr size_t Group::kWidth;
+namespace {
+
+#ifdef ABSL_SWISSTABLE_ASSERT
+#error ABSL_SWISSTABLE_ASSERT cannot be directly set
+#else
+// We use this macro for assertions that users may see when the table is in an
+// invalid state that sanitizers may help diagnose.
+#define ABSL_SWISSTABLE_ASSERT(CONDITION) \
+  assert((CONDITION) && "Try enabling sanitizers.")
 #endif
 
-namespace {
+[[noreturn]] ABSL_ATTRIBUTE_NOINLINE void HashTableSizeOverflow() {
+  ABSL_RAW_LOG(FATAL, "Hash table size overflow");
+}
+
+void ValidateMaxSize(size_t size, size_t slot_size) {
+  if (IsAboveValidSize(size, slot_size)) {
+    HashTableSizeOverflow();
+  }
+}
 
 // Returns "random" seed.
 inline size_t RandomSeed() {
 #ifdef ABSL_HAVE_THREAD_LOCAL
   static thread_local size_t counter = 0;
-  // On Linux kernels >= 5.4 the MSAN runtime has a false-positive when
-  // accessing thread local storage data from loaded libraries
-  // (https://github.com/google/sanitizers/issues/1265), for this reason counter
-  // needs to be annotated as initialized.
-  ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(&counter, sizeof(size_t));
   size_t value = ++counter;
 #else   // ABSL_HAVE_THREAD_LOCAL
   static std::atomic<size_t> counter(0);
@@ -86,16 +100,37 @@
   return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter));
 }
 
-bool ShouldRehashForBugDetection(const ctrl_t* ctrl, size_t capacity) {
+bool ShouldRehashForBugDetection(PerTableSeed seed, size_t capacity) {
   // Note: we can't use the abseil-random library because abseil-random
   // depends on swisstable. We want to return true with probability
   // `min(1, RehashProbabilityConstant() / capacity())`. In order to do this,
   // we probe based on a random hash and see if the offset is less than
   // RehashProbabilityConstant().
-  return probe(ctrl, capacity, absl::HashOf(RandomSeed())).offset() <
+  return probe(seed, capacity, absl::HashOf(RandomSeed())).offset() <
          RehashProbabilityConstant();
 }
 
+// Find a non-deterministic hash for single group table.
+// Last two bits are used to find a position for a newly inserted element after
+// resize.
+// This function basically using H2 last bits to save on shift operation.
+size_t SingleGroupTableH1(size_t hash, PerTableSeed seed) {
+  return hash ^ seed.seed();
+}
+
+// Returns the address of the slot `i` iterations after `slot` assuming each
+// slot has the specified size.
+inline void* NextSlot(void* slot, size_t slot_size, size_t i = 1) {
+  return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) +
+                                 slot_size * i);
+}
+
+// Returns the address of the slot just before `slot` assuming each slot has the
+// specified size.
+inline void* PrevSlot(void* slot, size_t slot_size) {
+  return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) - slot_size);
+}
+
 }  // namespace
 
 GenerationType* EmptyGeneration() {
@@ -109,42 +144,104 @@
 }
 
 bool CommonFieldsGenerationInfoEnabled::
-    should_rehash_for_bug_detection_on_insert(const ctrl_t* ctrl,
+    should_rehash_for_bug_detection_on_insert(PerTableSeed seed,
                                               size_t capacity) const {
   if (reserved_growth_ == kReservedGrowthJustRanOut) return true;
   if (reserved_growth_ > 0) return false;
-  return ShouldRehashForBugDetection(ctrl, capacity);
+  return ShouldRehashForBugDetection(seed, capacity);
 }
 
 bool CommonFieldsGenerationInfoEnabled::should_rehash_for_bug_detection_on_move(
-    const ctrl_t* ctrl, size_t capacity) const {
-  return ShouldRehashForBugDetection(ctrl, capacity);
+    PerTableSeed seed, size_t capacity) const {
+  return ShouldRehashForBugDetection(seed, capacity);
 }
 
-bool ShouldInsertBackwardsForDebug(size_t capacity, size_t hash,
-                                   const ctrl_t* ctrl) {
-  // To avoid problems with weak hashes and single bit tests, we use % 13.
-  // TODO(kfm,sbenza): revisit after we do unconditional mixing
-  return !is_small(capacity) && (H1(hash, ctrl) ^ RandomSeed()) % 13 > 6;
+namespace {
+
+FindInfo find_first_non_full_from_h1(const ctrl_t* ctrl, size_t h1,
+                                     size_t capacity) {
+  auto seq = probe(h1, capacity);
+  if (IsEmptyOrDeleted(ctrl[seq.offset()])) {
+    return {seq.offset(), /*probe_length=*/0};
+  }
+  while (true) {
+    GroupFullEmptyOrDeleted g{ctrl + seq.offset()};
+    auto mask = g.MaskEmptyOrDeleted();
+    if (mask) {
+      return {seq.offset(mask.LowestBitSet()), seq.index()};
+    }
+    seq.next();
+    ABSL_SWISSTABLE_ASSERT(seq.index() <= capacity && "full table!");
+  }
 }
 
-size_t PrepareInsertAfterSoo(size_t hash, size_t slot_size,
-                             CommonFields& common) {
-  assert(common.capacity() == NextCapacity(SooCapacity()));
-  // After resize from capacity 1 to 3, we always have exactly the slot with
-  // index 1 occupied, so we need to insert either at index 0 or index 2.
-  assert(HashSetResizeHelper::SooSlotIndex() == 1);
-  PrepareInsertCommon(common);
-  const size_t offset = H1(hash, common.control()) & 2;
-  common.growth_info().OverwriteEmptyAsFull();
-  SetCtrlInSingleGroupTable(common, offset, H2(hash), slot_size);
-  common.infoz().RecordInsert(hash, /*distance_from_desired=*/0);
-  return offset;
+// Whether a table is "small". A small table fits entirely into a probing
+// group, i.e., has a capacity < `Group::kWidth`.
+//
+// In small mode we are able to use the whole capacity. The extra control
+// bytes give us at least one "empty" control byte to stop the iteration.
+// This is important to make 1 a valid capacity.
+//
+// In small mode only the first `capacity` control bytes after the sentinel
+// are valid. The rest contain dummy ctrl_t::kEmpty values that do not
+// represent a real slot.
+constexpr bool is_small(size_t capacity) {
+  return capacity < Group::kWidth - 1;
 }
 
+template <class Fn>
+void IterateOverFullSlotsImpl(const CommonFields& c, size_t slot_size, Fn cb) {
+  const size_t cap = c.capacity();
+  const ctrl_t* ctrl = c.control();
+  void* slot = c.slot_array();
+  if (is_small(cap)) {
+    // Mirrored/cloned control bytes in small table are also located in the
+    // first group (starting from position 0). We are taking group from position
+    // `capacity` in order to avoid duplicates.
+
+    // Small tables capacity fits into portable group, where
+    // GroupPortableImpl::MaskFull is more efficient for the
+    // capacity <= GroupPortableImpl::kWidth.
+    ABSL_SWISSTABLE_ASSERT(cap <= GroupPortableImpl::kWidth &&
+                           "unexpectedly large small capacity");
+    static_assert(Group::kWidth >= GroupPortableImpl::kWidth,
+                  "unexpected group width");
+    // Group starts from kSentinel slot, so indices in the mask will
+    // be increased by 1.
+    const auto mask = GroupPortableImpl(ctrl + cap).MaskFull();
+    --ctrl;
+    slot = PrevSlot(slot, slot_size);
+    for (uint32_t i : mask) {
+      cb(ctrl + i, SlotAddress(slot, i, slot_size));
+    }
+    return;
+  }
+  size_t remaining = c.size();
+  ABSL_ATTRIBUTE_UNUSED const size_t original_size_for_assert = remaining;
+  while (remaining != 0) {
+    for (uint32_t i : GroupFullEmptyOrDeleted(ctrl).MaskFull()) {
+      ABSL_SWISSTABLE_ASSERT(IsFull(ctrl[i]) &&
+                             "hash table was modified unexpectedly");
+      cb(ctrl + i, SlotAddress(slot, i, slot_size));
+      --remaining;
+    }
+    ctrl += Group::kWidth;
+    slot = NextSlot(slot, slot_size, Group::kWidth);
+    ABSL_SWISSTABLE_ASSERT(
+        (remaining == 0 || *(ctrl - 1) != ctrl_t::kSentinel) &&
+        "hash table was modified unexpectedly");
+  }
+  // NOTE: erasure of the current element is allowed in callback for
+  // absl::erase_if specialization. So we use `>=`.
+  ABSL_SWISSTABLE_ASSERT(original_size_for_assert >= c.size() &&
+                         "hash table was modified unexpectedly");
+}
+
+}  // namespace
+
 void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity) {
-  assert(ctrl[capacity] == ctrl_t::kSentinel);
-  assert(IsValidCapacity(capacity));
+  ABSL_SWISSTABLE_ASSERT(ctrl[capacity] == ctrl_t::kSentinel);
+  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));
   for (ctrl_t* pos = ctrl; pos < ctrl + capacity; pos += Group::kWidth) {
     Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos);
   }
@@ -152,26 +249,25 @@
   std::memcpy(ctrl + capacity + 1, ctrl, NumClonedBytes());
   ctrl[capacity] = ctrl_t::kSentinel;
 }
-// Extern template instantiation for inline function.
-template FindInfo find_first_non_full(const CommonFields&, size_t);
 
-FindInfo find_first_non_full_outofline(const CommonFields& common,
-                                       size_t hash) {
-  return find_first_non_full(common, hash);
+FindInfo find_first_non_full(const CommonFields& common, size_t hash) {
+  return find_first_non_full_from_h1(common.control(), H1(hash, common.seed()),
+                                     common.capacity());
+}
+
+void IterateOverFullSlots(const CommonFields& c, size_t slot_size,
+                          absl::FunctionRef<void(const ctrl_t*, void*)> cb) {
+  IterateOverFullSlotsImpl(c, slot_size, cb);
 }
 
 namespace {
 
-// Returns the address of the slot just after slot assuming each slot has the
-// specified size.
-static inline void* NextSlot(void* slot, size_t slot_size) {
-  return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) + slot_size);
+void ResetGrowthLeft(GrowthInfo& growth_info, size_t capacity, size_t size) {
+  growth_info.InitGrowthLeftNoDeleted(CapacityToGrowth(capacity) - size);
 }
 
-// Returns the address of the slot just before slot assuming each slot has the
-// specified size.
-static inline void* PrevSlot(void* slot, size_t slot_size) {
-  return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) - slot_size);
+void ResetGrowthLeft(CommonFields& common) {
+  ResetGrowthLeft(common.growth_info(), common.capacity(), common.size());
 }
 
 // Finds guaranteed to exists empty slot from the given position.
@@ -184,17 +280,34 @@
       return i;
     }
   }
-  assert(false && "no empty slot");
-  return ~size_t{};
+  ABSL_UNREACHABLE();
 }
 
-void DropDeletesWithoutResize(CommonFields& common,
-                              const PolicyFunctions& policy) {
+// Finds guaranteed to exist full slot starting from the given position.
+// NOTE: this function is only triggered for rehash(0), when we need to
+// go back to SOO state, so we keep it simple.
+size_t FindFirstFullSlot(size_t start, size_t end, const ctrl_t* ctrl) {
+  for (size_t i = start; i < end; ++i) {
+    if (IsFull(ctrl[i])) {
+      return i;
+    }
+  }
+  ABSL_UNREACHABLE();
+}
+
+void PrepareInsertCommon(CommonFields& common) {
+  common.increment_size();
+  common.maybe_increment_generation_on_insert();
+}
+
+size_t DropDeletesWithoutResizeAndPrepareInsert(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    size_t new_hash) {
   void* set = &common;
   void* slot_array = common.slot_array();
   const size_t capacity = common.capacity();
-  assert(IsValidCapacity(capacity));
-  assert(!is_small(capacity));
+  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));
+  ABSL_SWISSTABLE_ASSERT(!is_single_group(capacity));
   // Algorithm:
   // - mark all DELETED slots as EMPTY
   // - mark all FULL slots as DELETED
@@ -215,7 +328,7 @@
   ConvertDeletedToEmptyAndFullToDeleted(ctrl, capacity);
   const void* hash_fn = policy.hash_fn(common);
   auto hasher = policy.hash_slot;
-  auto transfer = policy.transfer;
+  auto transfer_n = policy.transfer_n;
   const size_t slot_size = policy.slot_size;
 
   size_t total_probe_length = 0;
@@ -228,7 +341,7 @@
 
   for (size_t i = 0; i != capacity;
        ++i, slot_ptr = NextSlot(slot_ptr, slot_size)) {
-    assert(slot_ptr == SlotAddress(slot_array, i, slot_size));
+    ABSL_SWISSTABLE_ASSERT(slot_ptr == SlotAddress(slot_array, i, slot_size));
     if (IsEmpty(ctrl[i])) {
       tmp_space_id = i;
       continue;
@@ -243,13 +356,14 @@
     // If they do, we don't need to move the object as it falls already in the
     // best probe we can.
     const size_t probe_offset = probe(common, hash).offset();
+    const h2_t h2 = H2(hash);
     const auto probe_index = [probe_offset, capacity](size_t pos) {
       return ((pos - probe_offset) & capacity) / Group::kWidth;
     };
 
     // Element doesn't move.
     if (ABSL_PREDICT_TRUE(probe_index(new_i) == probe_index(i))) {
-      SetCtrl(common, i, H2(hash), slot_size);
+      SetCtrlInLargeTable(common, i, h2, slot_size);
       continue;
     }
 
@@ -258,14 +372,14 @@
       // Transfer element to the empty spot.
       // SetCtrl poisons/unpoisons the slots so we have to call it at the
       // right time.
-      SetCtrl(common, new_i, H2(hash), slot_size);
-      (*transfer)(set, new_slot_ptr, slot_ptr);
-      SetCtrl(common, i, ctrl_t::kEmpty, slot_size);
+      SetCtrlInLargeTable(common, new_i, h2, slot_size);
+      (*transfer_n)(set, new_slot_ptr, slot_ptr, 1);
+      SetCtrlInLargeTable(common, i, ctrl_t::kEmpty, slot_size);
       // Initialize or change empty space id.
       tmp_space_id = i;
     } else {
-      assert(IsDeleted(ctrl[new_i]));
-      SetCtrl(common, new_i, H2(hash), slot_size);
+      ABSL_SWISSTABLE_ASSERT(IsDeleted(ctrl[new_i]));
+      SetCtrlInLargeTable(common, new_i, h2, slot_size);
       // Until we are done rehashing, DELETED marks previously FULL slots.
 
       if (tmp_space_id == kUnknownId) {
@@ -275,9 +389,9 @@
       SanitizerUnpoisonMemoryRegion(tmp_space, slot_size);
 
       // Swap i and new_i elements.
-      (*transfer)(set, tmp_space, new_slot_ptr);
-      (*transfer)(set, new_slot_ptr, slot_ptr);
-      (*transfer)(set, slot_ptr, tmp_space);
+      (*transfer_n)(set, tmp_space, new_slot_ptr, 1);
+      (*transfer_n)(set, new_slot_ptr, slot_ptr, 1);
+      (*transfer_n)(set, slot_ptr, tmp_space, 1);
 
       SanitizerPoisonMemoryRegion(tmp_space, slot_size);
 
@@ -286,8 +400,14 @@
       slot_ptr = PrevSlot(slot_ptr, slot_size);
     }
   }
+  // Prepare insert for the new element.
+  PrepareInsertCommon(common);
   ResetGrowthLeft(common);
+  FindInfo find_info = find_first_non_full(common, new_hash);
+  SetCtrlInLargeTable(common, find_info.offset, H2(new_hash), slot_size);
+  common.infoz().RecordInsert(new_hash, find_info.probe_length);
   common.infoz().RecordRehash(total_probe_length);
+  return find_info.offset;
 }
 
 static bool WasNeverFull(CommonFields& c, size_t index) {
@@ -307,10 +427,126 @@
              Group::kWidth;
 }
 
+// Updates the control bytes to indicate a completely empty table such that all
+// control bytes are kEmpty except for the kSentinel byte.
+void ResetCtrl(CommonFields& common, size_t slot_size) {
+  const size_t capacity = common.capacity();
+  ctrl_t* ctrl = common.control();
+  static constexpr size_t kTwoGroupCapacity = 2 * Group::kWidth - 1;
+  if (ABSL_PREDICT_TRUE(capacity <= kTwoGroupCapacity)) {
+    std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty), Group::kWidth);
+    std::memset(ctrl + capacity, static_cast<int8_t>(ctrl_t::kEmpty),
+                Group::kWidth);
+    if (capacity == kTwoGroupCapacity) {
+      std::memset(ctrl + Group::kWidth, static_cast<int8_t>(ctrl_t::kEmpty),
+                  Group::kWidth);
+    }
+  } else {
+    std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
+                capacity + 1 + NumClonedBytes());
+  }
+  ctrl[capacity] = ctrl_t::kSentinel;
+  SanitizerPoisonMemoryRegion(common.slot_array(), slot_size * capacity);
+}
+
+// Initializes control bytes for single element table.
+// Capacity of the table must be 1.
+ABSL_ATTRIBUTE_ALWAYS_INLINE inline void InitializeSingleElementControlBytes(
+    uint64_t h2, ctrl_t* new_ctrl) {
+  static constexpr uint64_t kEmptyXorSentinel =
+      static_cast<uint8_t>(ctrl_t::kEmpty) ^
+      static_cast<uint8_t>(ctrl_t::kSentinel);
+  static constexpr uint64_t kEmpty64 = static_cast<uint8_t>(ctrl_t::kEmpty);
+  // The first 8 bytes, where present slot positions are replaced with 0.
+  static constexpr uint64_t kFirstCtrlBytesWithZeroes =
+      k8EmptyBytes ^ kEmpty64 ^ (kEmptyXorSentinel << 8) ^ (kEmpty64 << 16);
+
+  // Fill the original 0th and mirrored 2nd bytes with the hash.
+  // Result will look like:
+  // HSHEEEEE
+  // Where H = h2, E = kEmpty, S = kSentinel.
+  const uint64_t first_ctrl_bytes =
+      (h2 | kFirstCtrlBytesWithZeroes) | (h2 << 16);
+  // Fill last bytes with kEmpty.
+  std::memset(new_ctrl + 1, static_cast<int8_t>(ctrl_t::kEmpty), Group::kWidth);
+  // Overwrite the first 3 bytes with HSH. Other bytes will not be changed.
+  absl::little_endian::Store64(new_ctrl, first_ctrl_bytes);
+}
+
+// Initializes control bytes for growing after SOO to the next capacity.
+// `soo_ctrl` is placed in the position `SooSlotIndex()`.
+// `new_hash` is placed in the position `new_offset`.
+// The table must be non-empty SOO.
+ABSL_ATTRIBUTE_ALWAYS_INLINE inline void
+InitializeThreeElementsControlBytesAfterSoo(ctrl_t soo_ctrl, size_t new_hash,
+                                            size_t new_offset,
+                                            ctrl_t* new_ctrl) {
+  static constexpr size_t kNewCapacity = NextCapacity(SooCapacity());
+  static_assert(kNewCapacity == 3);
+  static_assert(is_single_group(kNewCapacity));
+  static_assert(SooSlotIndex() == 1);
+  ABSL_SWISSTABLE_ASSERT(new_offset == 0 || new_offset == 2);
+
+  static constexpr uint64_t kEmptyXorSentinel =
+      static_cast<uint8_t>(ctrl_t::kEmpty) ^
+      static_cast<uint8_t>(ctrl_t::kSentinel);
+  static constexpr uint64_t kEmpty64 = static_cast<uint8_t>(ctrl_t::kEmpty);
+  static constexpr size_t kMirroredSooSlotIndex =
+      SooSlotIndex() + kNewCapacity + 1;
+  // The first 8 bytes, where SOO slot original and mirrored positions are
+  // replaced with 0.
+  // Result will look like: E0ESE0EE
+  static constexpr uint64_t kFirstCtrlBytesWithZeroes =
+      k8EmptyBytes ^ (kEmpty64 << (8 * SooSlotIndex())) ^
+      (kEmptyXorSentinel << (8 * kNewCapacity)) ^
+      (kEmpty64 << (8 * kMirroredSooSlotIndex));
+
+  const uint64_t soo_h2 = static_cast<uint64_t>(soo_ctrl);
+  const uint64_t new_h2_xor_empty = static_cast<uint64_t>(
+      H2(new_hash) ^ static_cast<uint8_t>(ctrl_t::kEmpty));
+  // Fill the original and mirrored bytes for SOO slot.
+  // Result will look like:
+  // EHESEHEE
+  // Where H = soo_h2, E = kEmpty, S = kSentinel.
+  uint64_t first_ctrl_bytes =
+      ((soo_h2 << (8 * SooSlotIndex())) | kFirstCtrlBytesWithZeroes) |
+      (soo_h2 << (8 * kMirroredSooSlotIndex));
+  // Replace original and mirrored empty bytes for the new position.
+  // Result for new_offset 0 will look like:
+  // NHESNHEE
+  // Where H = soo_h2, N = H2(new_hash), E = kEmpty, S = kSentinel.
+  // Result for new_offset 2 will look like:
+  // EHNSEHNE
+  first_ctrl_bytes ^= (new_h2_xor_empty << (8 * new_offset));
+  size_t new_mirrored_offset = new_offset + kNewCapacity + 1;
+  first_ctrl_bytes ^= (new_h2_xor_empty << (8 * new_mirrored_offset));
+
+  // Fill last bytes with kEmpty.
+  std::memset(new_ctrl + kNewCapacity, static_cast<int8_t>(ctrl_t::kEmpty),
+              Group::kWidth);
+  // Overwrite the first 8 bytes with first_ctrl_bytes.
+  absl::little_endian::Store64(new_ctrl, first_ctrl_bytes);
+
+  // Example for group size 16:
+  // new_ctrl after 1st memset =      ???EEEEEEEEEEEEEEEE
+  // new_offset 0:
+  // new_ctrl after 2nd store  =      NHESNHEEEEEEEEEEEEE
+  // new_offset 2:
+  // new_ctrl after 2nd store  =      EHNSEHNEEEEEEEEEEEE
+
+  // Example for group size 8:
+  // new_ctrl after 1st memset =      ???EEEEEEEE
+  // new_offset 0:
+  // new_ctrl after 2nd store  =      NHESNHEEEEE
+  // new_offset 2:
+  // new_ctrl after 2nd store  =      EHNSEHNEEEE
+}
+
 }  // namespace
 
 void EraseMetaOnly(CommonFields& c, size_t index, size_t slot_size) {
-  assert(IsFull(c.control()[index]) && "erasing a dangling iterator");
+  ABSL_SWISSTABLE_ASSERT(IsFull(c.control()[index]) &&
+                         "erasing a dangling iterator");
   c.decrement_size();
   c.infoz().RecordErase();
 
@@ -321,14 +557,15 @@
   }
 
   c.growth_info().OverwriteFullAsDeleted();
-  SetCtrl(c, index, ctrl_t::kDeleted, slot_size);
+  SetCtrlInLargeTable(c, index, ctrl_t::kDeleted, slot_size);
 }
 
-void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,
+void ClearBackingArray(CommonFields& c,
+                       const PolicyFunctions& __restrict policy, void* alloc,
                        bool reuse, bool soo_enabled) {
-  c.set_size(0);
   if (reuse) {
-    assert(!soo_enabled || c.capacity() > SooCapacity());
+    c.set_size_to_zero();
+    ABSL_SWISSTABLE_ASSERT(!soo_enabled || c.capacity() > SooCapacity());
     ResetCtrl(c, policy.slot_size);
     ResetGrowthLeft(c);
     c.infoz().RecordStorageChanged(0, c.capacity());
@@ -337,192 +574,763 @@
     // infoz.
     c.infoz().RecordClearedReservation();
     c.infoz().RecordStorageChanged(0, soo_enabled ? SooCapacity() : 0);
-    (*policy.dealloc)(c, policy);
-    c = soo_enabled ? CommonFields{soo_tag_t{}} : CommonFields{};
+    c.infoz().Unregister();
+    (*policy.dealloc)(alloc, c.capacity(), c.control(), policy.slot_size,
+                      policy.slot_align, c.has_infoz());
+    c = soo_enabled ? CommonFields{soo_tag_t{}} : CommonFields{non_soo_tag_t{}};
   }
 }
 
-void HashSetResizeHelper::GrowIntoSingleGroupShuffleControlBytes(
-    ctrl_t* __restrict new_ctrl, size_t new_capacity) const {
-  assert(is_single_group(new_capacity));
+namespace {
+
+enum class ResizeNonSooMode {
+  kGuaranteedEmpty,
+  kGuaranteedAllocated,
+};
+
+// Iterates over full slots in old table, finds new positions for them and
+// transfers the slots.
+// This function is used for reserving or rehashing non-empty tables.
+// This use case is rare so the function is type erased.
+// Returns the total probe length.
+size_t FindNewPositionsAndTransferSlots(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    ctrl_t* old_ctrl, void* old_slots, size_t old_capacity) {
+  void* new_slots = common.slot_array();
+  const void* hash_fn = policy.hash_fn(common);
+  const size_t slot_size = policy.slot_size;
+
+  const auto insert_slot = [&](void* slot) {
+    size_t hash = policy.hash_slot(hash_fn, slot);
+    auto target = find_first_non_full(common, hash);
+    SetCtrl(common, target.offset, H2(hash), slot_size);
+    policy.transfer_n(&common, SlotAddress(new_slots, target.offset, slot_size),
+                      slot, 1);
+    return target.probe_length;
+  };
+  size_t total_probe_length = 0;
+  for (size_t i = 0; i < old_capacity; ++i) {
+    if (IsFull(old_ctrl[i])) {
+      total_probe_length += insert_slot(old_slots);
+    }
+    old_slots = NextSlot(old_slots, slot_size);
+  }
+  return total_probe_length;
+}
+
+template <ResizeNonSooMode kMode>
+void ResizeNonSooImpl(CommonFields& common,
+                      const PolicyFunctions& __restrict policy,
+                      size_t new_capacity, HashtablezInfoHandle infoz) {
+  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));
+  ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());
+
+  const size_t old_capacity = common.capacity();
+  [[maybe_unused]] ctrl_t* old_ctrl = common.control();
+  [[maybe_unused]] void* old_slots = common.slot_array();
+
+  const size_t slot_size = policy.slot_size;
+  const size_t slot_align = policy.slot_align;
+  const bool has_infoz = infoz.IsSampled();
+
+  common.set_capacity(new_capacity);
+  RawHashSetLayout layout(new_capacity, slot_size, slot_align, has_infoz);
+  void* alloc = policy.get_char_alloc(common);
+  char* mem = static_cast<char*>(policy.alloc(alloc, layout.alloc_size()));
+  const GenerationType old_generation = common.generation();
+  common.set_generation_ptr(
+      reinterpret_cast<GenerationType*>(mem + layout.generation_offset()));
+  common.set_generation(NextGeneration(old_generation));
+
+  ctrl_t* new_ctrl = reinterpret_cast<ctrl_t*>(mem + layout.control_offset());
+  common.set_control</*kGenerateSeed=*/true>(new_ctrl);
+  common.set_slots(mem + layout.slot_offset());
+
+  size_t total_probe_length = 0;
+  ResetCtrl(common, slot_size);
+  ABSL_SWISSTABLE_ASSERT(kMode != ResizeNonSooMode::kGuaranteedEmpty ||
+                         old_capacity == policy.soo_capacity());
+  ABSL_SWISSTABLE_ASSERT(kMode != ResizeNonSooMode::kGuaranteedAllocated ||
+                         old_capacity > 0);
+  if constexpr (kMode == ResizeNonSooMode::kGuaranteedAllocated) {
+    total_probe_length = FindNewPositionsAndTransferSlots(
+        common, policy, old_ctrl, old_slots, old_capacity);
+    (*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,
+                      has_infoz);
+    ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,
+                    common.size());
+  } else {
+    GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(
+        CapacityToGrowth(new_capacity));
+  }
+
+  if (has_infoz) {
+    common.set_has_infoz();
+    infoz.RecordStorageChanged(common.size(), new_capacity);
+    infoz.RecordRehash(total_probe_length);
+    common.set_infoz(infoz);
+  }
+}
+
+void ResizeEmptyNonAllocatedTableImpl(CommonFields& common,
+                                      const PolicyFunctions& __restrict policy,
+                                      size_t new_capacity, bool force_infoz) {
+  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));
+  ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());
+  ABSL_SWISSTABLE_ASSERT(!force_infoz || policy.soo_enabled);
+  ABSL_SWISSTABLE_ASSERT(common.capacity() <= policy.soo_capacity());
+  ABSL_SWISSTABLE_ASSERT(common.empty());
+  const size_t slot_size = policy.slot_size;
+  HashtablezInfoHandle infoz;
+  const bool should_sample =
+      policy.is_hashtablez_eligible && (force_infoz || ShouldSampleNextTable());
+  if (ABSL_PREDICT_FALSE(should_sample)) {
+    infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size,
+                            policy.soo_capacity());
+  }
+  ResizeNonSooImpl<ResizeNonSooMode::kGuaranteedEmpty>(common, policy,
+                                                       new_capacity, infoz);
+}
+
+// If the table was SOO, initializes new control bytes and transfers slot.
+// After transferring the slot, sets control and slots in CommonFields.
+// It is rare to resize an SOO table with one element to a large size.
+// Requires: `c` contains SOO data.
+void InsertOldSooSlotAndInitializeControlBytes(
+    CommonFields& c, const PolicyFunctions& __restrict policy, size_t hash,
+    ctrl_t* new_ctrl, void* new_slots) {
+  ABSL_SWISSTABLE_ASSERT(c.size() == policy.soo_capacity());
+  ABSL_SWISSTABLE_ASSERT(policy.soo_enabled);
+  size_t new_capacity = c.capacity();
+
+  c.generate_new_seed();
+  size_t offset = probe(c.seed(), new_capacity, hash).offset();
+  offset = offset == new_capacity ? 0 : offset;
+  SanitizerPoisonMemoryRegion(new_slots, policy.slot_size * new_capacity);
+  void* target_slot = SlotAddress(new_slots, offset, policy.slot_size);
+  SanitizerUnpoisonMemoryRegion(target_slot, policy.slot_size);
+  policy.transfer_n(&c, target_slot, c.soo_data(), 1);
+  c.set_control</*kGenerateSeed=*/false>(new_ctrl);
+  c.set_slots(new_slots);
+  ResetCtrl(c, policy.slot_size);
+  SetCtrl(c, offset, H2(hash), policy.slot_size);
+}
+
+enum class ResizeFullSooTableSamplingMode {
+  kNoSampling,
+  // Force sampling. If the table was still not sampled, do not resize.
+  kForceSampleNoResizeIfUnsampled,
+};
+
+void AssertSoo([[maybe_unused]] CommonFields& common,
+               [[maybe_unused]] const PolicyFunctions& policy) {
+  ABSL_SWISSTABLE_ASSERT(policy.soo_enabled);
+  ABSL_SWISSTABLE_ASSERT(common.capacity() == policy.soo_capacity());
+}
+void AssertFullSoo([[maybe_unused]] CommonFields& common,
+                   [[maybe_unused]] const PolicyFunctions& policy) {
+  AssertSoo(common, policy);
+  ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity());
+}
+
+void ResizeFullSooTable(CommonFields& common,
+                        const PolicyFunctions& __restrict policy,
+                        size_t new_capacity,
+                        ResizeFullSooTableSamplingMode sampling_mode) {
+  AssertFullSoo(common, policy);
+  const size_t slot_size = policy.slot_size;
+  const size_t slot_align = policy.slot_align;
+
+  HashtablezInfoHandle infoz;
+  if (sampling_mode ==
+      ResizeFullSooTableSamplingMode::kForceSampleNoResizeIfUnsampled) {
+    if (ABSL_PREDICT_FALSE(policy.is_hashtablez_eligible)) {
+      infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size,
+                              policy.soo_capacity());
+    }
+
+    if (!infoz.IsSampled()) {
+      return;
+    }
+  }
+
+  const bool has_infoz = infoz.IsSampled();
+
+  common.set_capacity(new_capacity);
+
+  RawHashSetLayout layout(new_capacity, slot_size, slot_align, has_infoz);
+  void* alloc = policy.get_char_alloc(common);
+  char* mem = static_cast<char*>(policy.alloc(alloc, layout.alloc_size()));
+  const GenerationType old_generation = common.generation();
+  common.set_generation_ptr(
+      reinterpret_cast<GenerationType*>(mem + layout.generation_offset()));
+  common.set_generation(NextGeneration(old_generation));
+
+  // We do not set control and slots in CommonFields yet to avoid overriding
+  // SOO data.
+  ctrl_t* new_ctrl = reinterpret_cast<ctrl_t*>(mem + layout.control_offset());
+  void* new_slots = mem + layout.slot_offset();
+
+  const size_t soo_slot_hash =
+      policy.hash_slot(policy.hash_fn(common), common.soo_data());
+
+  InsertOldSooSlotAndInitializeControlBytes(common, policy, soo_slot_hash,
+                                            new_ctrl, new_slots);
+  ResetGrowthLeft(common);
+  if (has_infoz) {
+    common.set_has_infoz();
+    common.set_infoz(infoz);
+    infoz.RecordStorageChanged(common.size(), new_capacity);
+  }
+}
+
+void GrowIntoSingleGroupShuffleControlBytes(ctrl_t* __restrict old_ctrl,
+                                            size_t old_capacity,
+                                            ctrl_t* __restrict new_ctrl,
+                                            size_t new_capacity) {
+  ABSL_SWISSTABLE_ASSERT(is_single_group(new_capacity));
   constexpr size_t kHalfWidth = Group::kWidth / 2;
-  constexpr size_t kQuarterWidth = Group::kWidth / 4;
-  assert(old_capacity_ < kHalfWidth);
-  static_assert(sizeof(uint64_t) >= kHalfWidth,
-                "Group size is too large. The ctrl bytes for half a group must "
-                "fit into a uint64_t for this implementation.");
-  static_assert(sizeof(uint64_t) <= Group::kWidth,
-                "Group size is too small. The ctrl bytes for a group must "
-                "cover a uint64_t for this implementation.");
+  ABSL_ASSUME(old_capacity < kHalfWidth);
+  ABSL_ASSUME(old_capacity > 0);
+  static_assert(Group::kWidth == 8 || Group::kWidth == 16,
+                "Group size is not supported.");
 
-  const size_t half_old_capacity = old_capacity_ / 2;
-
-  // NOTE: operations are done with compile time known size = kHalfWidth.
+  // NOTE: operations are done with compile time known size = 8.
   // Compiler optimizes that into single ASM operation.
 
-  // Load the bytes from half_old_capacity + 1. This contains the last half of
-  // old_ctrl bytes, followed by the sentinel byte, and then the first half of
-  // the cloned bytes. This effectively shuffles the control bytes.
-  uint64_t copied_bytes = 0;
-  copied_bytes =
-      absl::little_endian::Load64(old_ctrl() + half_old_capacity + 1);
+  // Load the bytes from old_capacity. This contains
+  // - the sentinel byte
+  // - all the old control bytes
+  // - the rest is filled with kEmpty bytes
+  // Example:
+  // old_ctrl =     012S012EEEEEEEEE...
+  // copied_bytes = S012EEEE
+  uint64_t copied_bytes = absl::little_endian::Load64(old_ctrl + old_capacity);
 
   // We change the sentinel byte to kEmpty before storing to both the start of
   // the new_ctrl, and past the end of the new_ctrl later for the new cloned
   // bytes. Note that this is faster than setting the sentinel byte to kEmpty
   // after the copy directly in new_ctrl because we are limited on store
   // bandwidth.
-  constexpr uint64_t kEmptyXorSentinel =
+  static constexpr uint64_t kEmptyXorSentinel =
       static_cast<uint8_t>(ctrl_t::kEmpty) ^
       static_cast<uint8_t>(ctrl_t::kSentinel);
-  const uint64_t mask_convert_old_sentinel_to_empty =
-      kEmptyXorSentinel << (half_old_capacity * 8);
-  copied_bytes ^= mask_convert_old_sentinel_to_empty;
 
-  // Copy second half of bytes to the beginning. This correctly sets the bytes
-  // [0, old_capacity]. We potentially copy more bytes in order to have compile
-  // time known size. Mirrored bytes from the old_ctrl() will also be copied. In
-  // case of old_capacity_ == 3, we will copy 1st element twice.
-  // Examples:
-  // (old capacity = 1)
-  // old_ctrl = 0S0EEEEEEE...
-  // new_ctrl = E0EEEEEE??...
-  //
-  // (old capacity = 3)
-  // old_ctrl = 012S012EEEEE...
-  // new_ctrl = 12E012EE????...
-  //
-  // (old capacity = 7)
-  // old_ctrl = 0123456S0123456EE...
-  // new_ctrl = 456E0123?????????...
-  absl::little_endian::Store64(new_ctrl, copied_bytes);
+  // Replace the first byte kSentinel with kEmpty.
+  // Resulting bytes will be shifted by one byte old control blocks.
+  // Example:
+  // old_ctrl = 012S012EEEEEEEEE...
+  // before =   S012EEEE
+  // after  =   E012EEEE
+  copied_bytes ^= kEmptyXorSentinel;
 
-  // Set the space [old_capacity + 1, new_capacity] to empty as these bytes will
-  // not be written again. This is safe because
-  // NumControlBytes = new_capacity + kWidth and new_capacity >=
-  // old_capacity+1.
-  // Examples:
-  // (old_capacity = 3, new_capacity = 15)
-  // new_ctrl  = 12E012EE?????????????...??
-  // *new_ctrl = 12E0EEEEEEEEEEEEEEEE?...??
-  // position        /          S
-  //
-  // (old_capacity = 7, new_capacity = 15)
-  // new_ctrl  = 456E0123?????????????????...??
-  // *new_ctrl = 456E0123EEEEEEEEEEEEEEEE?...??
-  // position            /      S
-  std::memset(new_ctrl + old_capacity_ + 1, static_cast<int8_t>(ctrl_t::kEmpty),
-              Group::kWidth);
+  if (Group::kWidth == 8) {
+    // With group size 8, we can grow with two write operations.
+    ABSL_SWISSTABLE_ASSERT(old_capacity < 8 &&
+                           "old_capacity is too large for group size 8");
+    absl::little_endian::Store64(new_ctrl, copied_bytes);
 
-  // Set the last kHalfWidth bytes to empty, to ensure the bytes all the way to
-  // the end are initialized.
-  // Examples:
-  // new_ctrl  = 12E0EEEEEEEEEEEEEEEE?...???????
-  // *new_ctrl = 12E0EEEEEEEEEEEEEEEE???EEEEEEEE
-  // position                   S       /
-  //
-  // new_ctrl  = 456E0123EEEEEEEEEEEEEEEE???????
-  // *new_ctrl = 456E0123EEEEEEEEEEEEEEEEEEEEEEE
-  // position                   S       /
-  std::memset(new_ctrl + NumControlBytes(new_capacity) - kHalfWidth,
+    static constexpr uint64_t kSentinal64 =
+        static_cast<uint8_t>(ctrl_t::kSentinel);
+
+    // Prepend kSentinel byte to the beginning of copied_bytes.
+    // We have maximum 3 non-empty bytes at the beginning of copied_bytes for
+    // group size 8.
+    // Example:
+    // old_ctrl = 012S012EEEE
+    // before =   E012EEEE
+    // after  =   SE012EEE
+    copied_bytes = (copied_bytes << 8) ^ kSentinal64;
+    absl::little_endian::Store64(new_ctrl + new_capacity, copied_bytes);
+    // Example for capacity 3:
+    // old_ctrl = 012S012EEEE
+    // After the first store:
+    //           >!
+    // new_ctrl = E012EEEE???????
+    // After the second store:
+    //                  >!
+    // new_ctrl = E012EEESE012EEE
+    return;
+  }
+
+  ABSL_SWISSTABLE_ASSERT(Group::kWidth == 16);
+
+  // Fill the second half of the main control bytes with kEmpty.
+  // For small capacity that may write into mirrored control bytes.
+  // It is fine as we will overwrite all the bytes later.
+  std::memset(new_ctrl + kHalfWidth, static_cast<int8_t>(ctrl_t::kEmpty),
+              kHalfWidth);
+  // Fill the second half of the mirrored control bytes with kEmpty.
+  std::memset(new_ctrl + new_capacity + kHalfWidth,
               static_cast<int8_t>(ctrl_t::kEmpty), kHalfWidth);
-
-  // Copy the first bytes to the end (starting at new_capacity +1) to set the
-  // cloned bytes. Note that we use the already copied bytes from old_ctrl here
-  // rather than copying from new_ctrl to avoid a Read-after-Write hazard, since
-  // new_ctrl was just written to. The first old_capacity-1 bytes are set
-  // correctly. Then there may be up to old_capacity bytes that need to be
-  // overwritten, and any remaining bytes will be correctly set to empty. This
-  // sets [new_capacity + 1, new_capacity +1 + old_capacity] correctly.
-  // Examples:
-  // new_ctrl  = 12E0EEEEEEEEEEEEEEEE?...???????
-  // *new_ctrl = 12E0EEEEEEEEEEEE12E012EEEEEEEEE
-  // position                   S/
-  //
-  // new_ctrl  = 456E0123EEEEEEEE?...???EEEEEEEE
-  // *new_ctrl = 456E0123EEEEEEEE456E0123EEEEEEE
-  // position                   S/
+  // Copy the first half of the non-mirrored control bytes.
+  absl::little_endian::Store64(new_ctrl, copied_bytes);
+  new_ctrl[new_capacity] = ctrl_t::kSentinel;
+  // Copy the first half of the mirrored control bytes.
   absl::little_endian::Store64(new_ctrl + new_capacity + 1, copied_bytes);
 
-  // Set The remaining bytes at the end past the cloned bytes to empty. The
-  // incorrectly set bytes are [new_capacity + old_capacity + 2,
-  // min(new_capacity + 1 + kHalfWidth, new_capacity + old_capacity + 2 +
-  // half_old_capacity)]. Taking the difference, we need to set min(kHalfWidth -
-  // (old_capacity + 1), half_old_capacity)]. Since old_capacity < kHalfWidth,
-  // half_old_capacity < kQuarterWidth, so we set kQuarterWidth beginning at
-  // new_capacity + old_capacity + 2 to kEmpty.
-  // Examples:
-  // new_ctrl  = 12E0EEEEEEEEEEEE12E012EEEEEEEEE
-  // *new_ctrl = 12E0EEEEEEEEEEEE12E0EEEEEEEEEEE
-  // position                   S    /
+  // Example for growth capacity 1->3:
+  // old_ctrl =                  0S0EEEEEEEEEEEEEE
+  // new_ctrl at the end =       E0ESE0EEEEEEEEEEEEE
+  //                                    >!
+  // new_ctrl after 1st memset = ????????EEEEEEEE???
+  //                                       >!
+  // new_ctrl after 2nd memset = ????????EEEEEEEEEEE
+  //                            >!
+  // new_ctrl after 1st store =  E0EEEEEEEEEEEEEEEEE
+  // new_ctrl after kSentinel =  E0ESEEEEEEEEEEEEEEE
+  //                                >!
+  // new_ctrl after 2nd store =  E0ESE0EEEEEEEEEEEEE
+
+  // Example for growth capacity 3->7:
+  // old_ctrl =                  012S012EEEEEEEEEEEE
+  // new_ctrl at the end =       E012EEESE012EEEEEEEEEEE
+  //                                    >!
+  // new_ctrl after 1st memset = ????????EEEEEEEE???????
+  //                                           >!
+  // new_ctrl after 2nd memset = ????????EEEEEEEEEEEEEEE
+  //                            >!
+  // new_ctrl after 1st store =  E012EEEEEEEEEEEEEEEEEEE
+  // new_ctrl after kSentinel =  E012EEESEEEEEEEEEEEEEEE
+  //                                >!
+  // new_ctrl after 2nd store =  E012EEESE012EEEEEEEEEEE
+
+  // Example for growth capacity 7->15:
+  // old_ctrl =                  0123456S0123456EEEEEEEE
+  // new_ctrl at the end =       E0123456EEEEEEESE0123456EEEEEEE
+  //                                    >!
+  // new_ctrl after 1st memset = ????????EEEEEEEE???????????????
+  //                                                   >!
+  // new_ctrl after 2nd memset = ????????EEEEEEEE???????EEEEEEEE
+  //                            >!
+  // new_ctrl after 1st store =  E0123456EEEEEEEE???????EEEEEEEE
+  // new_ctrl after kSentinel =  E0123456EEEEEEES???????EEEEEEEE
+  //                                            >!
+  // new_ctrl after 2nd store =  E0123456EEEEEEESE0123456EEEEEEE
+}
+
+// Size of the buffer we allocate on stack for storing probed elements in
+// GrowToNextCapacity algorithm.
+constexpr size_t kProbedElementsBufferSize = 512;
+
+// Decodes information about probed elements from contiguous memory.
+// Finds new position for each element and transfers it to the new slots.
+// Returns the total probe length.
+template <typename ProbedItem>
+ABSL_ATTRIBUTE_NOINLINE size_t DecodeAndInsertImpl(
+    CommonFields& c, const PolicyFunctions& __restrict policy,
+    const ProbedItem* start, const ProbedItem* end, void* old_slots) {
+  const size_t new_capacity = c.capacity();
+
+  void* new_slots = c.slot_array();
+  ctrl_t* new_ctrl = c.control();
+  size_t total_probe_length = 0;
+
+  const size_t slot_size = policy.slot_size;
+  auto transfer_n = policy.transfer_n;
+
+  for (; start < end; ++start) {
+    const FindInfo target = find_first_non_full_from_h1(
+        new_ctrl, static_cast<size_t>(start->h1), new_capacity);
+    total_probe_length += target.probe_length;
+    const size_t old_index = static_cast<size_t>(start->source_offset);
+    const size_t new_i = target.offset;
+    ABSL_SWISSTABLE_ASSERT(old_index < new_capacity / 2);
+    ABSL_SWISSTABLE_ASSERT(new_i < new_capacity);
+    ABSL_SWISSTABLE_ASSERT(IsEmpty(new_ctrl[new_i]));
+    void* src_slot = SlotAddress(old_slots, old_index, slot_size);
+    void* dst_slot = SlotAddress(new_slots, new_i, slot_size);
+    SanitizerUnpoisonMemoryRegion(dst_slot, slot_size);
+    transfer_n(&c, dst_slot, src_slot, 1);
+    SetCtrlInLargeTable(c, new_i, static_cast<h2_t>(start->h2), slot_size);
+  }
+  return total_probe_length;
+}
+
+// Sentinel value for the start of marked elements.
+// Signals that there are no marked elements.
+constexpr size_t kNoMarkedElementsSentinel = ~size_t{};
+
+// Process probed elements that did not fit into available buffers.
+// We marked them in control bytes as kSentinel.
+// Hash recomputation and full probing is done here.
+// This use case should be extremely rare.
+ABSL_ATTRIBUTE_NOINLINE size_t ProcessProbedMarkedElements(
+    CommonFields& c, const PolicyFunctions& __restrict policy, ctrl_t* old_ctrl,
+    void* old_slots, size_t start) {
+  size_t old_capacity = PreviousCapacity(c.capacity());
+  const size_t slot_size = policy.slot_size;
+  void* new_slots = c.slot_array();
+  size_t total_probe_length = 0;
+  const void* hash_fn = policy.hash_fn(c);
+  auto hash_slot = policy.hash_slot;
+  auto transfer_n = policy.transfer_n;
+  for (size_t old_index = start; old_index < old_capacity; ++old_index) {
+    if (old_ctrl[old_index] != ctrl_t::kSentinel) {
+      continue;
+    }
+    void* src_slot = SlotAddress(old_slots, old_index, slot_size);
+    const size_t hash = hash_slot(hash_fn, src_slot);
+    const FindInfo target = find_first_non_full(c, hash);
+    total_probe_length += target.probe_length;
+    const size_t new_i = target.offset;
+    void* dst_slot = SlotAddress(new_slots, new_i, slot_size);
+    SetCtrlInLargeTable(c, new_i, H2(hash), slot_size);
+    transfer_n(&c, dst_slot, src_slot, 1);
+  }
+  return total_probe_length;
+}
+
+// The largest old capacity for which it is guaranteed that all probed elements
+// fit in ProbedItemEncoder's local buffer.
+// For such tables, `encode_probed_element` is trivial.
+constexpr size_t kMaxLocalBufferOldCapacity =
+    kProbedElementsBufferSize / sizeof(ProbedItem4Bytes) - 1;
+static_assert(IsValidCapacity(kMaxLocalBufferOldCapacity));
+constexpr size_t kMaxLocalBufferNewCapacity =
+    NextCapacity(kMaxLocalBufferOldCapacity);
+static_assert(kMaxLocalBufferNewCapacity <= ProbedItem4Bytes::kMaxNewCapacity);
+static_assert(NextCapacity(kMaxLocalBufferNewCapacity) <=
+              ProbedItem4Bytes::kMaxNewCapacity);
+
+// Initializes mirrored control bytes after
+// transfer_unprobed_elements_to_next_capacity.
+void InitializeMirroredControlBytes(ctrl_t* new_ctrl, size_t new_capacity) {
+  std::memcpy(new_ctrl + new_capacity,
+              // We own GrowthInfo just before control bytes. So it is ok
+              // to read one byte from it.
+              new_ctrl - 1, Group::kWidth);
+  new_ctrl[new_capacity] = ctrl_t::kSentinel;
+}
+
+// Encodes probed elements into available memory.
+// At first, a local (on stack) buffer is used. The size of the buffer is
+// kProbedElementsBufferSize bytes.
+// When the local buffer is full, we switch to `control_` buffer. We are allowed
+// to overwrite `control_` buffer till the `source_offset` byte. In case we have
+// no space in `control_` buffer, we fallback to a naive algorithm for all the
+// rest of the probed elements. We mark elements as kSentinel in control bytes
+// and later process them fully. See ProcessMarkedElements for details. It
+// should be extremely rare.
+template <typename ProbedItemType,
+          // If true, we only use the local buffer and never switch to the
+          // control buffer.
+          bool kGuaranteedFitToBuffer = false>
+class ProbedItemEncoder {
+ public:
+  using ProbedItem = ProbedItemType;
+  explicit ProbedItemEncoder(ctrl_t* control) : control_(control) {}
+
+  // Encode item into the best available location.
+  void EncodeItem(ProbedItem item) {
+    if (ABSL_PREDICT_FALSE(!kGuaranteedFitToBuffer && pos_ >= end_)) {
+      return ProcessEncodeWithOverflow(item);
+    }
+    ABSL_SWISSTABLE_ASSERT(pos_ < end_);
+    *pos_ = item;
+    ++pos_;
+  }
+
+  // Decodes information about probed elements from all available sources.
+  // Finds new position for each element and transfers it to the new slots.
+  // Returns the total probe length.
+  size_t DecodeAndInsertToTable(CommonFields& common,
+                                const PolicyFunctions& __restrict policy,
+                                void* old_slots) const {
+    if (pos_ == buffer_) {
+      return 0;
+    }
+    if constexpr (kGuaranteedFitToBuffer) {
+      return DecodeAndInsertImpl(common, policy, buffer_, pos_, old_slots);
+    }
+    size_t total_probe_length = DecodeAndInsertImpl(
+        common, policy, buffer_,
+        local_buffer_full_ ? buffer_ + kBufferSize : pos_, old_slots);
+    if (!local_buffer_full_) {
+      return total_probe_length;
+    }
+    total_probe_length +=
+        DecodeAndInsertToTableOverflow(common, policy, old_slots);
+    return total_probe_length;
+  }
+
+ private:
+  static ProbedItem* AlignToNextItem(void* ptr) {
+    return reinterpret_cast<ProbedItem*>(AlignUpTo(
+        reinterpret_cast<uintptr_t>(ptr), alignof(ProbedItem)));
+  }
+
+  ProbedItem* OverflowBufferStart() const {
+    // We reuse GrowthInfo memory as well.
+    return AlignToNextItem(control_ - ControlOffset(/*has_infoz=*/false));
+  }
+
+  // Encodes item when previously allocated buffer is full.
+  // At first that happens when local buffer is full.
+  // We switch from the local buffer to the control buffer.
+  // Every time this function is called, the available buffer is extended till
+  // `item.source_offset` byte in the control buffer.
+  // After the buffer is extended, this function wouldn't be called till the
+  // buffer is exhausted.
   //
-  // new_ctrl  = 456E0123EEEEEEEE456E0123EEEEEEE
-  // *new_ctrl = 456E0123EEEEEEEE456E0123EEEEEEE (no change)
-  // position                   S        /
-  std::memset(new_ctrl + new_capacity + old_capacity_ + 2,
-              static_cast<int8_t>(ctrl_t::kEmpty), kQuarterWidth);
+  // If there's no space in the control buffer, we fallback to naive algorithm
+  // and mark probed elements as kSentinel in the control buffer. In this case,
+  // we will call this function for every subsequent probed element.
+  ABSL_ATTRIBUTE_NOINLINE void ProcessEncodeWithOverflow(ProbedItem item) {
+    if (!local_buffer_full_) {
+      local_buffer_full_ = true;
+      pos_ = OverflowBufferStart();
+    }
+    const size_t source_offset = static_cast<size_t>(item.source_offset);
+    // We are in fallback mode so we can't reuse control buffer anymore.
+    // Probed elements are marked as kSentinel in the control buffer.
+    if (ABSL_PREDICT_FALSE(marked_elements_starting_position_ !=
+                           kNoMarkedElementsSentinel)) {
+      control_[source_offset] = ctrl_t::kSentinel;
+      return;
+    }
+    // Refresh the end pointer to the new available position.
+    // Invariant: if pos < end, then we have at least sizeof(ProbedItem) bytes
+    // to write.
+    end_ = control_ + source_offset + 1 - sizeof(ProbedItem);
+    if (ABSL_PREDICT_TRUE(pos_ < end_)) {
+      *pos_ = item;
+      ++pos_;
+      return;
+    }
+    control_[source_offset] = ctrl_t::kSentinel;
+    marked_elements_starting_position_ = source_offset;
+    // Now we will always fall down to `ProcessEncodeWithOverflow`.
+    ABSL_SWISSTABLE_ASSERT(pos_ >= end_);
+  }
 
-  // Finally, we set the new sentinel byte.
-  new_ctrl[new_capacity] = ctrl_t::kSentinel;
+  // Decodes information about probed elements from control buffer and processes
+  // marked elements.
+  // Finds new position for each element and transfers it to the new slots.
+  // Returns the total probe length.
+  ABSL_ATTRIBUTE_NOINLINE size_t DecodeAndInsertToTableOverflow(
+      CommonFields& common, const PolicyFunctions& __restrict policy,
+      void* old_slots) const {
+    ABSL_SWISSTABLE_ASSERT(local_buffer_full_ &&
+                           "must not be called when local buffer is not full");
+    size_t total_probe_length = DecodeAndInsertImpl(
+        common, policy, OverflowBufferStart(), pos_, old_slots);
+    if (ABSL_PREDICT_TRUE(marked_elements_starting_position_ ==
+                          kNoMarkedElementsSentinel)) {
+      return total_probe_length;
+    }
+    total_probe_length +=
+        ProcessProbedMarkedElements(common, policy, control_, old_slots,
+                                    marked_elements_starting_position_);
+    return total_probe_length;
+  }
+
+  static constexpr size_t kBufferSize =
+      kProbedElementsBufferSize / sizeof(ProbedItem);
+  ProbedItem buffer_[kBufferSize];
+  // If local_buffer_full_ is false, then pos_/end_ are in the local buffer,
+  // otherwise, they're in the overflow buffer.
+  ProbedItem* pos_ = buffer_;
+  const void* end_ = buffer_ + kBufferSize;
+  ctrl_t* const control_;
+  size_t marked_elements_starting_position_ = kNoMarkedElementsSentinel;
+  bool local_buffer_full_ = false;
+};
+
+// Grows to next capacity with specified encoder type.
+// Encoder is used to store probed elements that are processed later.
+// Different encoder is used depending on the capacity of the table.
+// Returns total probe length.
+template <typename Encoder>
+size_t GrowToNextCapacity(CommonFields& common,
+                          const PolicyFunctions& __restrict policy,
+                          ctrl_t* old_ctrl, void* old_slots) {
+  using ProbedItem = typename Encoder::ProbedItem;
+  ABSL_SWISSTABLE_ASSERT(common.capacity() <= ProbedItem::kMaxNewCapacity);
+  Encoder encoder(old_ctrl);
+  policy.transfer_unprobed_elements_to_next_capacity(
+      common, old_ctrl, old_slots, &encoder,
+      [](void* probed_storage, h2_t h2, size_t source_offset, size_t h1) {
+        auto encoder_ptr = static_cast<Encoder*>(probed_storage);
+        encoder_ptr->EncodeItem(ProbedItem(h2, source_offset, h1));
+      });
+  InitializeMirroredControlBytes(common.control(), common.capacity());
+  return encoder.DecodeAndInsertToTable(common, policy, old_slots);
 }
 
-void HashSetResizeHelper::InitControlBytesAfterSoo(ctrl_t* new_ctrl, ctrl_t h2,
-                                                   size_t new_capacity) {
-  assert(is_single_group(new_capacity));
-  std::memset(new_ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
-              NumControlBytes(new_capacity));
-  assert(HashSetResizeHelper::SooSlotIndex() == 1);
-  // This allows us to avoid branching on had_soo_slot_.
-  assert(had_soo_slot_ || h2 == ctrl_t::kEmpty);
-  new_ctrl[1] = new_ctrl[new_capacity + 2] = h2;
-  new_ctrl[new_capacity] = ctrl_t::kSentinel;
+// Grows to next capacity for relatively small tables so that even if all
+// elements are probed, we don't need to overflow the local buffer.
+// Returns total probe length.
+size_t GrowToNextCapacityThatFitsInLocalBuffer(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    ctrl_t* old_ctrl, void* old_slots) {
+  ABSL_SWISSTABLE_ASSERT(common.capacity() <= kMaxLocalBufferNewCapacity);
+  return GrowToNextCapacity<
+      ProbedItemEncoder<ProbedItem4Bytes, /*kGuaranteedFitToBuffer=*/true>>(
+      common, policy, old_ctrl, old_slots);
 }
 
-void HashSetResizeHelper::GrowIntoSingleGroupShuffleTransferableSlots(
-    void* new_slots, size_t slot_size) const {
-  assert(old_capacity_ > 0);
-  const size_t half_old_capacity = old_capacity_ / 2;
-
-  SanitizerUnpoisonMemoryRegion(old_slots(), slot_size * old_capacity_);
-  std::memcpy(new_slots,
-              SlotAddress(old_slots(), half_old_capacity + 1, slot_size),
-              slot_size * half_old_capacity);
-  std::memcpy(SlotAddress(new_slots, half_old_capacity + 1, slot_size),
-              old_slots(), slot_size * (half_old_capacity + 1));
+// Grows to next capacity with different encodings. Returns total probe length.
+// These functions are useful to simplify profile analysis.
+size_t GrowToNextCapacity4BytesEncoder(CommonFields& common,
+                                       const PolicyFunctions& __restrict policy,
+                                       ctrl_t* old_ctrl, void* old_slots) {
+  return GrowToNextCapacity<ProbedItemEncoder<ProbedItem4Bytes>>(
+      common, policy, old_ctrl, old_slots);
+}
+size_t GrowToNextCapacity8BytesEncoder(CommonFields& common,
+                                       const PolicyFunctions& __restrict policy,
+                                       ctrl_t* old_ctrl, void* old_slots) {
+  return GrowToNextCapacity<ProbedItemEncoder<ProbedItem8Bytes>>(
+      common, policy, old_ctrl, old_slots);
+}
+size_t GrowToNextCapacity16BytesEncoder(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    ctrl_t* old_ctrl, void* old_slots) {
+  return GrowToNextCapacity<ProbedItemEncoder<ProbedItem16Bytes>>(
+      common, policy, old_ctrl, old_slots);
 }
 
-void HashSetResizeHelper::GrowSizeIntoSingleGroupTransferable(
-    CommonFields& c, size_t slot_size) {
-  assert(old_capacity_ < Group::kWidth / 2);
-  assert(is_single_group(c.capacity()));
-  assert(IsGrowingIntoSingleGroupApplicable(old_capacity_, c.capacity()));
-
-  GrowIntoSingleGroupShuffleControlBytes(c.control(), c.capacity());
-  GrowIntoSingleGroupShuffleTransferableSlots(c.slot_array(), slot_size);
-
-  // We poison since GrowIntoSingleGroupShuffleTransferableSlots
-  // may leave empty slots unpoisoned.
-  PoisonSingleGroupEmptySlots(c, slot_size);
+// Grows to next capacity for tables with relatively large capacity so that we
+// can't guarantee that all probed elements fit in the local buffer. Returns
+// total probe length.
+size_t GrowToNextCapacityOverflowLocalBuffer(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    ctrl_t* old_ctrl, void* old_slots) {
+  const size_t new_capacity = common.capacity();
+  if (ABSL_PREDICT_TRUE(new_capacity <= ProbedItem4Bytes::kMaxNewCapacity)) {
+    return GrowToNextCapacity4BytesEncoder(common, policy, old_ctrl, old_slots);
+  }
+  if (ABSL_PREDICT_TRUE(new_capacity <= ProbedItem8Bytes::kMaxNewCapacity)) {
+    return GrowToNextCapacity8BytesEncoder(common, policy, old_ctrl, old_slots);
+  }
+  // 16 bytes encoding supports the maximum swisstable capacity.
+  return GrowToNextCapacity16BytesEncoder(common, policy, old_ctrl, old_slots);
 }
 
-void HashSetResizeHelper::TransferSlotAfterSoo(CommonFields& c,
-                                               size_t slot_size) {
-  assert(was_soo_);
-  assert(had_soo_slot_);
-  assert(is_single_group(c.capacity()));
-  std::memcpy(SlotAddress(c.slot_array(), SooSlotIndex(), slot_size),
-              old_soo_data(), slot_size);
-  PoisonSingleGroupEmptySlots(c, slot_size);
+// Dispatches to the appropriate `GrowToNextCapacity*` function based on the
+// capacity of the table. Returns total probe length.
+ABSL_ATTRIBUTE_NOINLINE
+size_t GrowToNextCapacityDispatch(CommonFields& common,
+                                  const PolicyFunctions& __restrict policy,
+                                  ctrl_t* old_ctrl, void* old_slots) {
+  const size_t new_capacity = common.capacity();
+  if (ABSL_PREDICT_TRUE(new_capacity <= kMaxLocalBufferNewCapacity)) {
+    return GrowToNextCapacityThatFitsInLocalBuffer(common, policy, old_ctrl,
+                                                   old_slots);
+  } else {
+    return GrowToNextCapacityOverflowLocalBuffer(common, policy, old_ctrl,
+                                                 old_slots);
+  }
 }
 
-namespace {
+// Grows to next capacity and prepares insert for the given new_hash.
+// Returns the offset of the new element.
+size_t GrowToNextCapacityAndPrepareInsert(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    size_t new_hash) {
+  ABSL_SWISSTABLE_ASSERT(common.growth_left() == 0);
+  const size_t old_capacity = common.capacity();
+  ABSL_SWISSTABLE_ASSERT(old_capacity == 0 ||
+                         old_capacity > policy.soo_capacity());
+
+  const size_t new_capacity = NextCapacity(old_capacity);
+  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));
+  ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());
+
+  ctrl_t* old_ctrl = common.control();
+  void* old_slots = common.slot_array();
+
+  common.set_capacity(new_capacity);
+  const size_t slot_size = policy.slot_size;
+  const size_t slot_align = policy.slot_align;
+  HashtablezInfoHandle infoz;
+  if (old_capacity > 0) {
+    infoz = common.infoz();
+  } else {
+    const bool should_sample =
+        policy.is_hashtablez_eligible && ShouldSampleNextTable();
+    if (ABSL_PREDICT_FALSE(should_sample)) {
+      infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size,
+                              policy.soo_capacity());
+    }
+  }
+  const bool has_infoz = infoz.IsSampled();
+
+  RawHashSetLayout layout(new_capacity, slot_size, slot_align, has_infoz);
+  void* alloc = policy.get_char_alloc(common);
+  char* mem = static_cast<char*>(policy.alloc(alloc, layout.alloc_size()));
+  const GenerationType old_generation = common.generation();
+  common.set_generation_ptr(
+      reinterpret_cast<GenerationType*>(mem + layout.generation_offset()));
+  common.set_generation(NextGeneration(old_generation));
+
+  ctrl_t* new_ctrl = reinterpret_cast<ctrl_t*>(mem + layout.control_offset());
+  void* new_slots = mem + layout.slot_offset();
+  common.set_control</*kGenerateSeed=*/false>(new_ctrl);
+  common.set_slots(new_slots);
+  SanitizerPoisonMemoryRegion(new_slots, new_capacity * slot_size);
+
+  h2_t new_h2 = H2(new_hash);
+  size_t total_probe_length = 0;
+  FindInfo find_info;
+  if (old_capacity == 0) {
+    static_assert(NextCapacity(0) == 1);
+    InitializeSingleElementControlBytes(new_h2, new_ctrl);
+    common.generate_new_seed();
+    find_info = FindInfo{0, 0};
+    SanitizerUnpoisonMemoryRegion(new_slots, slot_size);
+  } else {
+    if (ABSL_PREDICT_TRUE(is_single_group(new_capacity))) {
+      GrowIntoSingleGroupShuffleControlBytes(old_ctrl, old_capacity, new_ctrl,
+                                             new_capacity);
+      // Single group tables have all slots full on resize. So we can transfer
+      // all slots without checking the control bytes.
+      ABSL_SWISSTABLE_ASSERT(common.size() == old_capacity);
+      auto* target = NextSlot(new_slots, slot_size);
+      SanitizerUnpoisonMemoryRegion(target, old_capacity * slot_size);
+      policy.transfer_n(&common, target, old_slots, old_capacity);
+      // We put the new element either at the beginning or at the end of the
+      // table with approximately equal probability.
+      size_t offset = SingleGroupTableH1(new_hash, common.seed()) & 1
+                          ? 0
+                          : new_capacity - 1;
+
+      ABSL_SWISSTABLE_ASSERT(IsEmpty(new_ctrl[offset]));
+      SetCtrlInSingleGroupTable(common, offset, new_h2, policy.slot_size);
+      find_info = FindInfo{offset, 0};
+    } else {
+      total_probe_length =
+          GrowToNextCapacityDispatch(common, policy, old_ctrl, old_slots);
+      find_info = find_first_non_full(common, new_hash);
+      SetCtrlInLargeTable(common, find_info.offset, new_h2, policy.slot_size);
+    }
+    ABSL_SWISSTABLE_ASSERT(old_capacity > policy.soo_capacity());
+    (*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,
+                      has_infoz);
+  }
+  PrepareInsertCommon(common);
+  ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,
+                  common.size());
+
+  if (ABSL_PREDICT_FALSE(has_infoz)) {
+    common.set_has_infoz();
+    infoz.RecordStorageChanged(common.size() - 1, new_capacity);
+    infoz.RecordRehash(total_probe_length);
+    infoz.RecordInsert(new_hash, find_info.probe_length);
+    common.set_infoz(infoz);
+  }
+  return find_info.offset;
+}
 
 // Called whenever the table needs to vacate empty slots either by removing
-// tombstones via rehash or growth.
+// tombstones via rehash or growth to next capacity.
 ABSL_ATTRIBUTE_NOINLINE
-FindInfo FindInsertPositionWithGrowthOrRehash(CommonFields& common, size_t hash,
-                                              const PolicyFunctions& policy) {
+size_t RehashOrGrowToNextCapacityAndPrepareInsert(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    size_t new_hash) {
   const size_t cap = common.capacity();
+  ABSL_ASSUME(cap > 0);
   if (cap > Group::kWidth &&
       // Do these calculations in 64-bit to avoid overflow.
       common.size() * uint64_t{32} <= cap * uint64_t{25}) {
@@ -567,77 +1375,468 @@
     //  762 | 149836       0.37        13 | 148559       0.74       190
     //  807 | 149736       0.39        14 | 151107       0.39        14
     //  852 | 150204       0.42        15 | 151019       0.42        15
-    DropDeletesWithoutResize(common, policy);
+    return DropDeletesWithoutResizeAndPrepareInsert(common, policy, new_hash);
   } else {
     // Otherwise grow the container.
-    policy.resize(common, NextCapacity(cap), HashtablezInfoHandle{});
+    return GrowToNextCapacityAndPrepareInsert(common, policy, new_hash);
   }
-  // This function is typically called with tables containing deleted slots.
-  // The table will be big and `FindFirstNonFullAfterResize` will always
-  // fallback to `find_first_non_full`. So using `find_first_non_full` directly.
-  return find_first_non_full(common, hash);
+}
+
+// Slow path for PrepareInsertNonSoo that is called when the table has deleted
+// slots or need to be resized or rehashed.
+size_t PrepareInsertNonSooSlow(CommonFields& common,
+                               const PolicyFunctions& __restrict policy,
+                               size_t hash) {
+  const GrowthInfo growth_info = common.growth_info();
+  ABSL_SWISSTABLE_ASSERT(!growth_info.HasNoDeletedAndGrowthLeft());
+  if (ABSL_PREDICT_TRUE(growth_info.HasNoGrowthLeftAndNoDeleted())) {
+    // Table without deleted slots (>95% cases) that needs to be resized.
+    ABSL_SWISSTABLE_ASSERT(growth_info.HasNoDeleted() &&
+                           growth_info.GetGrowthLeft() == 0);
+    return GrowToNextCapacityAndPrepareInsert(common, policy, hash);
+  }
+  if (ABSL_PREDICT_FALSE(growth_info.HasNoGrowthLeftAssumingMayHaveDeleted())) {
+    // Table with deleted slots that needs to be rehashed or resized.
+    return RehashOrGrowToNextCapacityAndPrepareInsert(common, policy, hash);
+  }
+  // Table with deleted slots that has space for the inserting element.
+  FindInfo target = find_first_non_full(common, hash);
+  PrepareInsertCommon(common);
+  common.growth_info().OverwriteControlAsFull(common.control()[target.offset]);
+  SetCtrlInLargeTable(common, target.offset, H2(hash), policy.slot_size);
+  common.infoz().RecordInsert(hash, target.probe_length);
+  return target.offset;
+}
+
+// Resizes empty non-allocated SOO table to NextCapacity(SooCapacity()),
+// forces the table to be sampled and prepares the insert.
+// SOO tables need to switch from SOO to heap in order to store the infoz.
+// Requires:
+//   1. `c.capacity() == SooCapacity()`.
+//   2. `c.empty()`.
+ABSL_ATTRIBUTE_NOINLINE size_t
+GrowEmptySooTableToNextCapacityForceSamplingAndPrepareInsert(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    size_t new_hash) {
+  ResizeEmptyNonAllocatedTableImpl(common, policy, NextCapacity(SooCapacity()),
+                                   /*force_infoz=*/true);
+  PrepareInsertCommon(common);
+  common.growth_info().OverwriteEmptyAsFull();
+  SetCtrlInSingleGroupTable(common, SooSlotIndex(), H2(new_hash),
+                            policy.slot_size);
+  common.infoz().RecordInsert(new_hash, /*distance_from_desired=*/0);
+  return SooSlotIndex();
+}
+
+// Resizes empty non-allocated table to the capacity to fit new_size elements.
+// Requires:
+//   1. `c.capacity() == policy.soo_capacity()`.
+//   2. `c.empty()`.
+//   3. `new_size > policy.soo_capacity()`.
+// The table will be attempted to be sampled.
+void ReserveEmptyNonAllocatedTableToFitNewSize(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    size_t new_size) {
+  ValidateMaxSize(new_size, policy.slot_size);
+  ABSL_ASSUME(new_size > 0);
+  ResizeEmptyNonAllocatedTableImpl(common, policy, SizeToCapacity(new_size),
+                                   /*force_infoz=*/false);
+  // This is after resize, to ensure that we have completed the allocation
+  // and have potentially sampled the hashtable.
+  common.infoz().RecordReservation(new_size);
+}
+
+// Type erased version of raw_hash_set::reserve for tables that have an
+// allocated backing array.
+//
+// Requires:
+//   1. `c.capacity() > policy.soo_capacity()` OR `!c.empty()`.
+// Reserving already allocated tables is considered to be a rare case.
+ABSL_ATTRIBUTE_NOINLINE void ReserveAllocatedTable(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    size_t new_size) {
+  const size_t cap = common.capacity();
+  ValidateMaxSize(new_size, policy.slot_size);
+  ABSL_ASSUME(new_size > 0);
+  const size_t new_capacity = SizeToCapacity(new_size);
+  if (cap == policy.soo_capacity()) {
+    ABSL_SWISSTABLE_ASSERT(!common.empty());
+    ResizeFullSooTable(common, policy, new_capacity,
+                       ResizeFullSooTableSamplingMode::kNoSampling);
+  } else {
+    ABSL_SWISSTABLE_ASSERT(cap > policy.soo_capacity());
+    // TODO(b/382423690): consider using GrowToNextCapacity, when applicable.
+    ResizeAllocatedTableWithSeedChange(common, policy, new_capacity);
+  }
+  common.infoz().RecordReservation(new_size);
 }
 
 }  // namespace
 
-const void* GetHashRefForEmptyHasher(const CommonFields& common) {
+void* GetRefForEmptyClass(CommonFields& common) {
   // Empty base optimization typically make the empty base class address to be
   // the same as the first address of the derived class object.
-  // But we generally assume that for empty hasher we can return any valid
+  // But we generally assume that for empty classes we can return any valid
   // pointer.
   return &common;
 }
 
-size_t PrepareInsertNonSoo(CommonFields& common, size_t hash, FindInfo target,
-                           const PolicyFunctions& policy) {
+void ResizeAllocatedTableWithSeedChange(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    size_t new_capacity) {
+  ResizeNonSooImpl<ResizeNonSooMode::kGuaranteedAllocated>(
+      common, policy, new_capacity, common.infoz());
+}
+
+void ReserveEmptyNonAllocatedTableToFitBucketCount(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    size_t bucket_count) {
+  size_t new_capacity = NormalizeCapacity(bucket_count);
+  ValidateMaxSize(CapacityToGrowth(new_capacity), policy.slot_size);
+  ResizeEmptyNonAllocatedTableImpl(common, policy, new_capacity,
+                                   /*force_infoz=*/false);
+}
+
+// Resizes a full SOO table to the NextCapacity(SooCapacity()).
+template <size_t SooSlotMemcpySize, bool TransferUsesMemcpy>
+size_t GrowSooTableToNextCapacityAndPrepareInsert(
+    CommonFields& common, const PolicyFunctions& __restrict policy,
+    size_t new_hash, ctrl_t soo_slot_ctrl) {
+  AssertSoo(common, policy);
+  if (ABSL_PREDICT_FALSE(soo_slot_ctrl == ctrl_t::kEmpty)) {
+    // The table is empty, it is only used for forced sampling of SOO tables.
+    return GrowEmptySooTableToNextCapacityForceSamplingAndPrepareInsert(
+        common, policy, new_hash);
+  }
+  ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity());
+  static constexpr size_t kNewCapacity = NextCapacity(SooCapacity());
+  const size_t slot_size = policy.slot_size;
+  const size_t slot_align = policy.slot_align;
+  common.set_capacity(kNewCapacity);
+
+  // Since the table is not empty, it will not be sampled.
+  // The decision to sample was already made during the first insertion.
+  RawHashSetLayout layout(kNewCapacity, slot_size, slot_align,
+                          /*has_infoz=*/false);
+  void* alloc = policy.get_char_alloc(common);
+  char* mem = static_cast<char*>(policy.alloc(alloc, layout.alloc_size()));
+  const GenerationType old_generation = common.generation();
+  common.set_generation_ptr(
+      reinterpret_cast<GenerationType*>(mem + layout.generation_offset()));
+  common.set_generation(NextGeneration(old_generation));
+
+  // We do not set control and slots in CommonFields yet to avoid overriding
+  // SOO data.
+  ctrl_t* new_ctrl = reinterpret_cast<ctrl_t*>(mem + layout.control_offset());
+  void* new_slots = mem + layout.slot_offset();
+
+  PrepareInsertCommon(common);
+  ABSL_SWISSTABLE_ASSERT(common.size() == 2);
+  GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(kNewCapacity - 2);
+  common.generate_new_seed();
+
+  // After resize from capacity 1 to 3, we always have exactly the slot with
+  // index 1 occupied, so we need to insert either at index 0 or index 2.
+  static_assert(SooSlotIndex() == 1);
+  const size_t offset = SingleGroupTableH1(new_hash, common.seed()) & 2;
+  InitializeThreeElementsControlBytesAfterSoo(soo_slot_ctrl, new_hash, offset,
+                                              new_ctrl);
+
+  SanitizerPoisonMemoryRegion(new_slots, slot_size * kNewCapacity);
+  void* target_slot = SlotAddress(new_slots, SooSlotIndex(), slot_size);
+  SanitizerUnpoisonMemoryRegion(target_slot, slot_size);
+  if constexpr (TransferUsesMemcpy) {
+    // Target slot is placed at index 1, but capacity is at
+    // minimum 3. So we are allowed to copy at least twice as much
+    // memory.
+    static_assert(SooSlotIndex() == 1);
+    static_assert(SooSlotMemcpySize > 0);
+    static_assert(SooSlotMemcpySize <= MaxSooSlotSize());
+    ABSL_SWISSTABLE_ASSERT(SooSlotMemcpySize <= 2 * slot_size);
+    ABSL_SWISSTABLE_ASSERT(SooSlotMemcpySize >= slot_size);
+    void* next_slot = SlotAddress(target_slot, 1, slot_size);
+    SanitizerUnpoisonMemoryRegion(next_slot, SooSlotMemcpySize - slot_size);
+    std::memcpy(target_slot, common.soo_data(), SooSlotMemcpySize);
+    SanitizerPoisonMemoryRegion(next_slot, SooSlotMemcpySize - slot_size);
+  } else {
+    static_assert(SooSlotMemcpySize == 0);
+    policy.transfer_n(&common, target_slot, common.soo_data(), 1);
+  }
+  // Seed was already generated above.
+  common.set_control</*kGenerateSeed=*/false>(new_ctrl);
+  common.set_slots(new_slots);
+
+  common.infoz().RecordInsert(new_hash, /*distance_from_desired=*/0);
+  SanitizerUnpoisonMemoryRegion(SlotAddress(new_slots, offset, slot_size),
+                                slot_size);
+  return offset;
+}
+
+void GrowFullSooTableToNextCapacityForceSampling(
+    CommonFields& common, const PolicyFunctions& __restrict policy) {
+  AssertFullSoo(common, policy);
+  ResizeFullSooTable(
+      common, policy, NextCapacity(SooCapacity()),
+      ResizeFullSooTableSamplingMode::kForceSampleNoResizeIfUnsampled);
+}
+
+void Rehash(CommonFields& common, const PolicyFunctions& __restrict policy,
+            size_t n) {
+  const size_t cap = common.capacity();
+
+  auto clear_backing_array = [&]() {
+    ClearBackingArray(common, policy, policy.get_char_alloc(common),
+                      /*reuse=*/false, policy.soo_enabled);
+  };
+
+  const size_t slot_size = policy.slot_size;
+
+  if (n == 0) {
+    if (cap <= policy.soo_capacity()) return;
+    if (common.empty()) {
+      clear_backing_array();
+      return;
+    }
+    if (common.size() <= policy.soo_capacity()) {
+      // When the table is already sampled, we keep it sampled.
+      if (common.infoz().IsSampled()) {
+        static constexpr size_t kInitialSampledCapacity =
+            NextCapacity(SooCapacity());
+        if (cap > kInitialSampledCapacity) {
+          ResizeAllocatedTableWithSeedChange(common, policy,
+                                             kInitialSampledCapacity);
+        }
+        // This asserts that we didn't lose sampling coverage in `resize`.
+        ABSL_SWISSTABLE_ASSERT(common.infoz().IsSampled());
+        return;
+      }
+      ABSL_SWISSTABLE_ASSERT(slot_size <= sizeof(HeapOrSoo));
+      ABSL_SWISSTABLE_ASSERT(policy.slot_align <= alignof(HeapOrSoo));
+      HeapOrSoo tmp_slot(uninitialized_tag_t{});
+      size_t begin_offset = FindFirstFullSlot(0, cap, common.control());
+      policy.transfer_n(
+          &common, &tmp_slot,
+          SlotAddress(common.slot_array(), begin_offset, slot_size), 1);
+      clear_backing_array();
+      policy.transfer_n(&common, common.soo_data(), &tmp_slot, 1);
+      common.set_full_soo();
+      return;
+    }
+  }
+
+  ValidateMaxSize(n, policy.slot_size);
+  // bitor is a faster way of doing `max` here. We will round up to the next
+  // power-of-2-minus-1, so bitor is good enough.
+  const size_t new_capacity =
+      NormalizeCapacity(n | SizeToCapacity(common.size()));
+  // n == 0 unconditionally rehashes as per the standard.
+  if (n == 0 || new_capacity > cap) {
+    if (cap == policy.soo_capacity()) {
+      if (common.empty()) {
+        ResizeEmptyNonAllocatedTableImpl(common, policy, new_capacity,
+                                         /*force_infoz=*/false);
+      } else {
+        ResizeFullSooTable(common, policy, new_capacity,
+                           ResizeFullSooTableSamplingMode::kNoSampling);
+      }
+    } else {
+      ResizeAllocatedTableWithSeedChange(common, policy, new_capacity);
+    }
+    // This is after resize, to ensure that we have completed the allocation
+    // and have potentially sampled the hashtable.
+    common.infoz().RecordReservation(n);
+  }
+}
+
+void Copy(CommonFields& common, const PolicyFunctions& __restrict policy,
+          const CommonFields& other,
+          absl::FunctionRef<void(void*, const void*)> copy_fn) {
+  const size_t size = other.size();
+  ABSL_SWISSTABLE_ASSERT(size > 0);
+  const size_t soo_capacity = policy.soo_capacity();
+  const size_t slot_size = policy.slot_size;
+  if (size <= soo_capacity) {
+    ABSL_SWISSTABLE_ASSERT(size == 1);
+    common.set_full_soo();
+    const void* other_slot =
+        other.capacity() <= soo_capacity
+            ? other.soo_data()
+            : SlotAddress(
+                  other.slot_array(),
+                  FindFirstFullSlot(0, other.capacity(), other.control()),
+                  slot_size);
+    copy_fn(common.soo_data(), other_slot);
+
+    if (policy.is_hashtablez_eligible && ShouldSampleNextTable()) {
+      GrowFullSooTableToNextCapacityForceSampling(common, policy);
+    }
+    return;
+  }
+
+  ReserveTableToFitNewSize(common, policy, size);
+  auto infoz = common.infoz();
+  ABSL_SWISSTABLE_ASSERT(other.capacity() > soo_capacity);
+  const size_t cap = common.capacity();
+  ABSL_SWISSTABLE_ASSERT(cap > soo_capacity);
+  // Note about single group tables:
+  // 1. It is correct to have any order of elements.
+  // 2. Order has to be non deterministic.
+  // 3. We are assigning elements with arbitrary `shift` starting from
+  //    `capacity + shift` position.
+  // 4. `shift` must be coprime with `capacity + 1` in order to be able to use
+  //     modular arithmetic to traverse all positions, instead of cycling
+  //     through a subset of positions. Odd numbers are coprime with any
+  //     `capacity + 1` (2^N).
+  size_t offset = cap;
+  const size_t shift = is_single_group(cap) ? (common.seed().seed() | 1) : 0;
+  const void* hash_fn = policy.hash_fn(common);
+  auto hasher = policy.hash_slot;
+  IterateOverFullSlotsImpl(
+      other, slot_size, [&](const ctrl_t* that_ctrl, void* that_slot) {
+        if (shift == 0) {
+          // Big tables case. Position must be searched via probing.
+          // The table is guaranteed to be empty, so we can do faster than
+          // a full `insert`.
+          const size_t hash = (*hasher)(hash_fn, that_slot);
+          FindInfo target = find_first_non_full(common, hash);
+          infoz.RecordInsert(hash, target.probe_length);
+          offset = target.offset;
+        } else {
+          // Small tables case. Next position is computed via shift.
+          offset = (offset + shift) & cap;
+        }
+        const h2_t h2 = static_cast<h2_t>(*that_ctrl);
+        // We rely on the hash not changing for small tables.
+        ABSL_SWISSTABLE_ASSERT(
+            H2((*hasher)(hash_fn, that_slot)) == h2 &&
+            "hash function value changed unexpectedly during the copy");
+        SetCtrl(common, offset, h2, slot_size);
+        copy_fn(SlotAddress(common.slot_array(), offset, slot_size), that_slot);
+        common.maybe_increment_generation_on_insert();
+      });
+  if (shift != 0) {
+    // On small table copy we do not record individual inserts.
+    // RecordInsert requires hash, but it is unknown for small tables.
+    infoz.RecordStorageChanged(size, cap);
+  }
+  common.increment_size(size);
+  common.growth_info().OverwriteManyEmptyAsFull(size);
+}
+
+void ReserveTableToFitNewSize(CommonFields& common,
+                              const PolicyFunctions& __restrict policy,
+                              size_t new_size) {
+  common.reset_reserved_growth(new_size);
+  common.set_reservation_size(new_size);
+  ABSL_SWISSTABLE_ASSERT(new_size > policy.soo_capacity());
+  const size_t cap = common.capacity();
+  if (ABSL_PREDICT_TRUE(common.empty() && cap <= policy.soo_capacity())) {
+    return ReserveEmptyNonAllocatedTableToFitNewSize(common, policy, new_size);
+  }
+
+  ABSL_SWISSTABLE_ASSERT(!common.empty() || cap > policy.soo_capacity());
+  ABSL_SWISSTABLE_ASSERT(cap > 0);
+  const size_t max_size_before_growth =
+      cap <= policy.soo_capacity() ? policy.soo_capacity()
+                                   : common.size() + common.growth_left();
+  if (new_size <= max_size_before_growth) {
+    return;
+  }
+  ReserveAllocatedTable(common, policy, new_size);
+}
+
+size_t PrepareInsertNonSoo(CommonFields& common,
+                           const PolicyFunctions& __restrict policy,
+                           size_t hash, FindInfo target) {
+  const bool rehash_for_bug_detection =
+      common.should_rehash_for_bug_detection_on_insert() &&
+      // Required to allow use of ResizeAllocatedTable.
+      common.capacity() > 0;
+  if (rehash_for_bug_detection) {
+    // Move to a different heap allocation in order to detect bugs.
+    const size_t cap = common.capacity();
+    ResizeAllocatedTableWithSeedChange(
+        common, policy, common.growth_left() > 0 ? cap : NextCapacity(cap));
+    target = find_first_non_full(common, hash);
+  }
+
+  const GrowthInfo growth_info = common.growth_info();
   // When there are no deleted slots in the table
   // and growth_left is positive, we can insert at the first
   // empty slot in the probe sequence (target).
-  const bool use_target_hint =
-      // Optimization is disabled when generations are enabled.
-      // We have to rehash even sparse tables randomly in such mode.
-      !SwisstableGenerationsEnabled() &&
-      common.growth_info().HasNoDeletedAndGrowthLeft();
-  if (ABSL_PREDICT_FALSE(!use_target_hint)) {
-    // Notes about optimized mode when generations are disabled:
-    // We do not enter this branch if table has no deleted slots
-    // and growth_left is positive.
-    // We enter this branch in the following cases listed in decreasing
-    // frequency:
-    // 1. Table without deleted slots (>95% cases) that needs to be resized.
-    // 2. Table with deleted slots that has space for the inserting element.
-    // 3. Table with deleted slots that needs to be rehashed or resized.
-    if (ABSL_PREDICT_TRUE(common.growth_info().HasNoGrowthLeftAndNoDeleted())) {
-      const size_t old_capacity = common.capacity();
-      policy.resize(common, NextCapacity(old_capacity), HashtablezInfoHandle{});
-      target = HashSetResizeHelper::FindFirstNonFullAfterResize(
-          common, old_capacity, hash);
-    } else {
-      // Note: the table may have no deleted slots here when generations
-      // are enabled.
-      const bool rehash_for_bug_detection =
-          common.should_rehash_for_bug_detection_on_insert();
-      if (rehash_for_bug_detection) {
-        // Move to a different heap allocation in order to detect bugs.
-        const size_t cap = common.capacity();
-        policy.resize(common,
-                      common.growth_left() > 0 ? cap : NextCapacity(cap),
-                      HashtablezInfoHandle{});
-      }
-      if (ABSL_PREDICT_TRUE(common.growth_left() > 0)) {
-        target = find_first_non_full(common, hash);
-      } else {
-        target = FindInsertPositionWithGrowthOrRehash(common, hash, policy);
-      }
-    }
+  if (ABSL_PREDICT_FALSE(!growth_info.HasNoDeletedAndGrowthLeft())) {
+    return PrepareInsertNonSooSlow(common, policy, hash);
   }
   PrepareInsertCommon(common);
-  common.growth_info().OverwriteControlAsFull(common.control()[target.offset]);
+  common.growth_info().OverwriteEmptyAsFull();
   SetCtrl(common, target.offset, H2(hash), policy.slot_size);
   common.infoz().RecordInsert(hash, target.probe_length);
   return target.offset;
 }
 
+namespace {
+// Returns true if the following is true
+// 1. OptimalMemcpySizeForSooSlotTransfer(left) >
+//    OptimalMemcpySizeForSooSlotTransfer(left - 1)
+// 2. OptimalMemcpySizeForSooSlotTransfer(left) are equal for all i in [left,
+// right].
+// This function is used to verify that we have all the possible template
+// instantiations for GrowFullSooTableToNextCapacity.
+// With this verification the problem may be detected at compile time instead of
+// link time.
+constexpr bool VerifyOptimalMemcpySizeForSooSlotTransferRange(size_t left,
+                                                              size_t right) {
+  size_t optimal_size_for_range = OptimalMemcpySizeForSooSlotTransfer(left);
+  if (optimal_size_for_range <= OptimalMemcpySizeForSooSlotTransfer(left - 1)) {
+    return false;
+  }
+  for (size_t i = left + 1; i <= right; ++i) {
+    if (OptimalMemcpySizeForSooSlotTransfer(i) != optimal_size_for_range) {
+      return false;
+    }
+  }
+  return true;
+}
+}  // namespace
+
+// Extern template instantiation for inline function.
+template size_t TryFindNewIndexWithoutProbing(size_t h1, size_t old_index,
+                                              size_t old_capacity,
+                                              ctrl_t* new_ctrl,
+                                              size_t new_capacity);
+
+// We need to instantiate ALL possible template combinations because we define
+// the function in the cc file.
+template size_t GrowSooTableToNextCapacityAndPrepareInsert<0, false>(
+    CommonFields&, const PolicyFunctions&, size_t, ctrl_t);
+template size_t GrowSooTableToNextCapacityAndPrepareInsert<
+    OptimalMemcpySizeForSooSlotTransfer(1), true>(CommonFields&,
+                                                  const PolicyFunctions&,
+                                                  size_t, ctrl_t);
+
+static_assert(VerifyOptimalMemcpySizeForSooSlotTransferRange(2, 3));
+template size_t GrowSooTableToNextCapacityAndPrepareInsert<
+    OptimalMemcpySizeForSooSlotTransfer(3), true>(CommonFields&,
+                                                  const PolicyFunctions&,
+                                                  size_t, ctrl_t);
+
+static_assert(VerifyOptimalMemcpySizeForSooSlotTransferRange(4, 8));
+template size_t GrowSooTableToNextCapacityAndPrepareInsert<
+    OptimalMemcpySizeForSooSlotTransfer(8), true>(CommonFields&,
+                                                  const PolicyFunctions&,
+                                                  size_t, ctrl_t);
+
+#if UINTPTR_MAX == UINT32_MAX
+static_assert(MaxSooSlotSize() == 8);
+#else
+static_assert(VerifyOptimalMemcpySizeForSooSlotTransferRange(9, 16));
+template size_t GrowSooTableToNextCapacityAndPrepareInsert<
+    OptimalMemcpySizeForSooSlotTransfer(16), true>(CommonFields&,
+                                                   const PolicyFunctions&,
+                                                   size_t, ctrl_t);
+static_assert(MaxSooSlotSize() == 16);
+#endif
+
 }  // namespace container_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index d4fe8f5..f5e3fdf 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -41,12 +41,6 @@
 // When heterogeneous lookup is disabled, only the explicit `key_type` overloads
 // exist.
 //
-// find() also supports passing the hash explicitly:
-//
-//   iterator find(const key_type& key, size_t hash);
-//   template <class U>
-//   iterator find(const U& key, size_t hash);
-//
 // In addition the pointer to element and iterator stability guarantees are
 // weaker: all iterators and pointers are invalidated after a new element is
 // inserted.
@@ -190,6 +184,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
+#include <functional>
 #include <initializer_list>
 #include <iterator>
 #include <limits>
@@ -201,6 +196,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/endian.h"
+#include "absl/base/internal/iterator_traits.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/macros.h"
 #include "absl/base/optimization.h"
@@ -208,32 +204,22 @@
 #include "absl/base/port.h"
 #include "absl/base/prefetch.h"
 #include "absl/container/internal/common.h"  // IWYU pragma: export // for node_handle
+#include "absl/container/internal/common_policy_traits.h"
 #include "absl/container/internal/compressed_tuple.h"
 #include "absl/container/internal/container_memory.h"
+#include "absl/container/internal/hash_function_defaults.h"
 #include "absl/container/internal/hash_policy_traits.h"
+#include "absl/container/internal/hashtable_control_bytes.h"
 #include "absl/container/internal/hashtable_debug_hooks.h"
 #include "absl/container/internal/hashtablez_sampler.h"
+#include "absl/functional/function_ref.h"
+#include "absl/hash/hash.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
 #include "absl/numeric/bits.h"
 #include "absl/utility/utility.h"
 
-#ifdef ABSL_INTERNAL_HAVE_SSE2
-#include <emmintrin.h>
-#endif
-
-#ifdef ABSL_INTERNAL_HAVE_SSSE3
-#include <tmmintrin.h>
-#endif
-
-#ifdef _MSC_VER
-#include <intrin.h>
-#endif
-
-#ifdef ABSL_INTERNAL_HAVE_ARM_NEON
-#include <arm_neon.h>
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
@@ -252,6 +238,15 @@
 #define ABSL_SWISSTABLE_ENABLE_GENERATIONS
 #endif
 
+#ifdef ABSL_SWISSTABLE_ASSERT
+#error ABSL_SWISSTABLE_ASSERT cannot be directly set
+#else
+// We use this macro for assertions that users may see when the table is in an
+// invalid state that sanitizers may help diagnose.
+#define ABSL_SWISSTABLE_ASSERT(CONDITION) \
+  assert((CONDITION) && "Try enabling sanitizers.")
+#endif
+
 // We use uint8_t so we don't need to worry about padding.
 using GenerationType = uint8_t;
 
@@ -271,6 +266,15 @@
 constexpr size_t NumGenerationBytes() { return 0; }
 #endif
 
+// Returns true if we should assert that the table is not accessed after it has
+// been destroyed or during the destruction of the table.
+constexpr bool SwisstableAssertAccessToDestroyedTable() {
+#ifndef NDEBUG
+  return true;
+#endif
+  return SwisstableGenerationsEnabled();
+}
+
 template <typename AllocType>
 void SwapAlloc(AllocType& lhs, AllocType& rhs,
                std::true_type /* propagate_on_container_swap */) {
@@ -322,7 +326,7 @@
   // sequence and `mask` (usually the capacity of the table) as the mask to
   // apply to each value in the progression.
   probe_seq(size_t hash, size_t mask) {
-    assert(((mask + 1) & mask) == 0 && "not a mask");
+    ABSL_SWISSTABLE_ASSERT(((mask + 1) & mask) == 0 && "not a mask");
     mask_ = mask;
     offset_ = hash & mask_;
   }
@@ -376,166 +380,21 @@
   return false;
 }
 
-template <typename T>
-uint32_t TrailingZeros(T x) {
-  ABSL_ASSUME(x != 0);
-  return static_cast<uint32_t>(countr_zero(x));
-}
-
-// 8 bytes bitmask with most significant bit set for every byte.
-constexpr uint64_t kMsbs8Bytes = 0x8080808080808080ULL;
-
-// An abstract bitmask, such as that emitted by a SIMD instruction.
-//
-// Specifically, this type implements a simple bitset whose representation is
-// controlled by `SignificantBits` and `Shift`. `SignificantBits` is the number
-// of abstract bits in the bitset, while `Shift` is the log-base-two of the
-// width of an abstract bit in the representation.
-// This mask provides operations for any number of real bits set in an abstract
-// bit. To add iteration on top of that, implementation must guarantee no more
-// than the most significant real bit is set in a set abstract bit.
-template <class T, int SignificantBits, int Shift = 0>
-class NonIterableBitMask {
- public:
-  explicit NonIterableBitMask(T mask) : mask_(mask) {}
-
-  explicit operator bool() const { return this->mask_ != 0; }
-
-  // Returns the index of the lowest *abstract* bit set in `self`.
-  uint32_t LowestBitSet() const {
-    return container_internal::TrailingZeros(mask_) >> Shift;
-  }
-
-  // Returns the index of the highest *abstract* bit set in `self`.
-  uint32_t HighestBitSet() const {
-    return static_cast<uint32_t>((bit_width(mask_) - 1) >> Shift);
-  }
-
-  // Returns the number of trailing zero *abstract* bits.
-  uint32_t TrailingZeros() const {
-    return container_internal::TrailingZeros(mask_) >> Shift;
-  }
-
-  // Returns the number of leading zero *abstract* bits.
-  uint32_t LeadingZeros() const {
-    constexpr int total_significant_bits = SignificantBits << Shift;
-    constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;
-    return static_cast<uint32_t>(
-               countl_zero(static_cast<T>(mask_ << extra_bits))) >>
-           Shift;
-  }
-
-  T mask_;
-};
-
-// Mask that can be iterable
-//
-// For example, when `SignificantBits` is 16 and `Shift` is zero, this is just
-// an ordinary 16-bit bitset occupying the low 16 bits of `mask`. When
-// `SignificantBits` is 8 and `Shift` is 3, abstract bits are represented as
-// the bytes `0x00` and `0x80`, and it occupies all 64 bits of the bitmask.
-// If NullifyBitsOnIteration is true (only allowed for Shift == 3),
-// non zero abstract bit is allowed to have additional bits
-// (e.g., `0xff`, `0x83` and `0x9c` are ok, but `0x6f` is not).
-//
-// For example:
-//   for (int i : BitMask<uint32_t, 16>(0b101)) -> yields 0, 2
-//   for (int i : BitMask<uint64_t, 8, 3>(0x0000000080800000)) -> yields 2, 3
-template <class T, int SignificantBits, int Shift = 0,
-          bool NullifyBitsOnIteration = false>
-class BitMask : public NonIterableBitMask<T, SignificantBits, Shift> {
-  using Base = NonIterableBitMask<T, SignificantBits, Shift>;
-  static_assert(std::is_unsigned<T>::value, "");
-  static_assert(Shift == 0 || Shift == 3, "");
-  static_assert(!NullifyBitsOnIteration || Shift == 3, "");
-
- public:
-  explicit BitMask(T mask) : Base(mask) {
-    if (Shift == 3 && !NullifyBitsOnIteration) {
-      assert(this->mask_ == (this->mask_ & kMsbs8Bytes));
-    }
-  }
-  // BitMask is an iterator over the indices of its abstract bits.
-  using value_type = int;
-  using iterator = BitMask;
-  using const_iterator = BitMask;
-
-  BitMask& operator++() {
-    if (Shift == 3 && NullifyBitsOnIteration) {
-      this->mask_ &= kMsbs8Bytes;
-    }
-    this->mask_ &= (this->mask_ - 1);
-    return *this;
-  }
-
-  uint32_t operator*() const { return Base::LowestBitSet(); }
-
-  BitMask begin() const { return *this; }
-  BitMask end() const { return BitMask(0); }
-
- private:
-  friend bool operator==(const BitMask& a, const BitMask& b) {
-    return a.mask_ == b.mask_;
-  }
-  friend bool operator!=(const BitMask& a, const BitMask& b) {
-    return a.mask_ != b.mask_;
-  }
-};
-
-using h2_t = uint8_t;
-
-// The values here are selected for maximum performance. See the static asserts
-// below for details.
-
-// A `ctrl_t` is a single control byte, which can have one of four
-// states: empty, deleted, full (which has an associated seven-bit h2_t value)
-// and the sentinel. They have the following bit patterns:
-//
-//      empty: 1 0 0 0 0 0 0 0
-//    deleted: 1 1 1 1 1 1 1 0
-//       full: 0 h h h h h h h  // h represents the hash bits.
-//   sentinel: 1 1 1 1 1 1 1 1
-//
-// These values are specifically tuned for SSE-flavored SIMD.
-// The static_asserts below detail the source of these choices.
-//
-// We use an enum class so that when strict aliasing is enabled, the compiler
-// knows ctrl_t doesn't alias other types.
-enum class ctrl_t : int8_t {
-  kEmpty = -128,   // 0b10000000
-  kDeleted = -2,   // 0b11111110
-  kSentinel = -1,  // 0b11111111
-};
-static_assert(
-    (static_cast<int8_t>(ctrl_t::kEmpty) &
-     static_cast<int8_t>(ctrl_t::kDeleted) &
-     static_cast<int8_t>(ctrl_t::kSentinel) & 0x80) != 0,
-    "Special markers need to have the MSB to make checking for them efficient");
-static_assert(
-    ctrl_t::kEmpty < ctrl_t::kSentinel && ctrl_t::kDeleted < ctrl_t::kSentinel,
-    "ctrl_t::kEmpty and ctrl_t::kDeleted must be smaller than "
-    "ctrl_t::kSentinel to make the SIMD test of IsEmptyOrDeleted() efficient");
-static_assert(
-    ctrl_t::kSentinel == static_cast<ctrl_t>(-1),
-    "ctrl_t::kSentinel must be -1 to elide loading it from memory into SIMD "
-    "registers (pcmpeqd xmm, xmm)");
-static_assert(ctrl_t::kEmpty == static_cast<ctrl_t>(-128),
-              "ctrl_t::kEmpty must be -128 to make the SIMD check for its "
-              "existence efficient (psignb xmm, xmm)");
-static_assert(
-    (~static_cast<int8_t>(ctrl_t::kEmpty) &
-     ~static_cast<int8_t>(ctrl_t::kDeleted) &
-     static_cast<int8_t>(ctrl_t::kSentinel) & 0x7F) != 0,
-    "ctrl_t::kEmpty and ctrl_t::kDeleted must share an unset bit that is not "
-    "shared by ctrl_t::kSentinel to make the scalar test for "
-    "MaskEmptyOrDeleted() efficient");
-static_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2),
-              "ctrl_t::kDeleted must be -2 to make the implementation of "
-              "ConvertSpecialToEmptyAndFullToDeleted efficient");
-
 // See definition comment for why this is size 32.
 ABSL_DLL extern const ctrl_t kEmptyGroup[32];
 
+// We use these sentinel capacity values in debug mode to indicate different
+// classes of bugs.
+enum InvalidCapacity : size_t {
+  kAboveMaxValidCapacity = ~size_t{} - 100,
+  kReentrance,
+  kDestroyed,
+
+  // These two must be last because we use `>= kMovedFrom` to mean moved-from.
+  kMovedFrom,
+  kSelfMovedFrom,
+};
+
 // Returns a pointer to a control byte group that can be used by empty tables.
 inline ctrl_t* EmptyGroup() {
   // Const must be cast away here; no uses of this function will actually write
@@ -566,54 +425,111 @@
   return *generation == SentinelEmptyGeneration();
 }
 
-// Mixes a randomly generated per-process seed with `hash` and `ctrl` to
-// randomize insertion order within groups.
-bool ShouldInsertBackwardsForDebug(size_t capacity, size_t hash,
-                                   const ctrl_t* ctrl);
+// We only allow a maximum of 1 SOO element, which makes the implementation
+// much simpler. Complications with multiple SOO elements include:
+// - Satisfying the guarantee that erasing one element doesn't invalidate
+//   iterators to other elements means we would probably need actual SOO
+//   control bytes.
+// - In order to prevent user code from depending on iteration order for small
+//   tables, we would need to randomize the iteration order somehow.
+constexpr size_t SooCapacity() { return 1; }
+// Sentinel type to indicate SOO CommonFields construction.
+struct soo_tag_t {};
+// Sentinel type to indicate SOO CommonFields construction with full size.
+struct full_soo_tag_t {};
+// Sentinel type to indicate non-SOO CommonFields construction.
+struct non_soo_tag_t {};
+// Sentinel value to indicate an uninitialized value explicitly.
+struct uninitialized_tag_t {};
+// Sentinel value to indicate creation of an empty table without a seed.
+struct no_seed_empty_tag_t {};
 
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline bool ShouldInsertBackwards(
-    ABSL_ATTRIBUTE_UNUSED size_t capacity, ABSL_ATTRIBUTE_UNUSED size_t hash,
-    ABSL_ATTRIBUTE_UNUSED const ctrl_t* ctrl) {
-#if defined(NDEBUG)
-  return false;
-#else
-  return ShouldInsertBackwardsForDebug(capacity, hash, ctrl);
-#endif
+// Per table hash salt. This gets mixed into H1 to randomize iteration order
+// per-table.
+// The seed is needed to ensure non-determinism of iteration order.
+class PerTableSeed {
+ public:
+  // The number of bits in the seed.
+  // It is big enough to ensure non-determinism of iteration order.
+  // We store the seed inside a uint64_t together with size and other metadata.
+  // Using 16 bits allows us to save one `and` instruction in H1 (we use movzwl
+  // instead of movq+and).
+  static constexpr size_t kBitCount = 16;
+
+  // Returns the seed for the table. Only the lowest kBitCount are non zero.
+  size_t seed() const { return seed_; }
+
+ private:
+  friend class HashtableSize;
+  explicit PerTableSeed(size_t seed) : seed_(seed) {}
+
+  const size_t seed_;
+};
+
+// Returns next per-table seed.
+inline uint16_t NextSeed() {
+  static_assert(PerTableSeed::kBitCount == 16);
+  thread_local uint16_t seed =
+      static_cast<uint16_t>(reinterpret_cast<uintptr_t>(&seed));
+  seed += uint16_t{0xad53};
+  return seed;
 }
 
-// Returns insert position for the given mask.
-// We want to add entropy even when ASLR is not enabled.
-// In debug build we will randomly insert in either the front or back of
-// the group.
-// TODO(kfm,sbenza): revisit after we do unconditional mixing
-template <class Mask>
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline auto GetInsertionOffset(
-    Mask mask, ABSL_ATTRIBUTE_UNUSED size_t capacity,
-    ABSL_ATTRIBUTE_UNUSED size_t hash,
-    ABSL_ATTRIBUTE_UNUSED const ctrl_t* ctrl) {
-#if defined(NDEBUG)
-  return mask.LowestBitSet();
-#else
-  return ShouldInsertBackwardsForDebug(capacity, hash, ctrl)
-             ? mask.HighestBitSet()
-             : mask.LowestBitSet();
-#endif
-}
+// The size and also has additionally
+// 1) one bit that stores whether we have infoz.
+// 2) PerTableSeed::kBitCount bits for the seed.
+class HashtableSize {
+ public:
+  static constexpr size_t kSizeBitCount = 64 - PerTableSeed::kBitCount - 1;
 
-// Returns a per-table, hash salt, which changes on resize. This gets mixed into
-// H1 to randomize iteration order per-table.
-//
-// The seed consists of the ctrl_ pointer, which adds enough entropy to ensure
-// non-determinism of iteration order in most cases.
-inline size_t PerTableSalt(const ctrl_t* ctrl) {
-  // The low bits of the pointer have little or no entropy because of
-  // alignment. We shift the pointer to try to use higher entropy bits. A
-  // good number seems to be 12 bits, because that aligns with page size.
-  return reinterpret_cast<uintptr_t>(ctrl) >> 12;
-}
-// Extracts the H1 portion of a hash: 57 bits mixed with a per-table salt.
-inline size_t H1(size_t hash, const ctrl_t* ctrl) {
-  return (hash >> 7) ^ PerTableSalt(ctrl);
+  explicit HashtableSize(uninitialized_tag_t) {}
+  explicit HashtableSize(no_seed_empty_tag_t) : data_(0) {}
+  explicit HashtableSize(full_soo_tag_t) : data_(kSizeOneNoMetadata) {}
+
+  // Returns actual size of the table.
+  size_t size() const { return static_cast<size_t>(data_ >> kSizeShift); }
+  void increment_size() { data_ += kSizeOneNoMetadata; }
+  void increment_size(size_t size) {
+    data_ += static_cast<uint64_t>(size) * kSizeOneNoMetadata;
+  }
+  void decrement_size() { data_ -= kSizeOneNoMetadata; }
+  // Returns true if the table is empty.
+  bool empty() const { return data_ < kSizeOneNoMetadata; }
+  // Sets the size to zero, but keeps all the metadata bits.
+  void set_size_to_zero_keep_metadata() { data_ = data_ & kMetadataMask; }
+
+  PerTableSeed seed() const {
+    return PerTableSeed(static_cast<size_t>(data_) & kSeedMask);
+  }
+
+  void generate_new_seed() {
+    data_ = (data_ & ~kSeedMask) ^ uint64_t{NextSeed()};
+  }
+
+  // Returns true if the table has infoz.
+  bool has_infoz() const {
+    return ABSL_PREDICT_FALSE((data_ & kHasInfozMask) != 0);
+  }
+
+  // Sets the has_infoz bit.
+  void set_has_infoz() { data_ |= kHasInfozMask; }
+
+  void set_no_seed_for_testing() { data_ &= ~kSeedMask; }
+
+ private:
+  static constexpr size_t kSizeShift = 64 - kSizeBitCount;
+  static constexpr uint64_t kSizeOneNoMetadata = uint64_t{1} << kSizeShift;
+  static constexpr uint64_t kMetadataMask = kSizeOneNoMetadata - 1;
+  static constexpr uint64_t kSeedMask =
+      (uint64_t{1} << PerTableSeed::kBitCount) - 1;
+  // The next bit after the seed.
+  static constexpr uint64_t kHasInfozMask = kSeedMask + 1;
+  uint64_t data_;
+};
+
+// Extracts the H1 portion of a hash: 57 bits mixed with a per-table seed.
+inline size_t H1(size_t hash, PerTableSeed seed) {
+  return (hash >> 7) ^ seed.seed();
 }
 
 // Extracts the H2 portion of a hash: the 7 bits not used for H1.
@@ -621,308 +537,6 @@
 // These are used as an occupied control byte.
 inline h2_t H2(size_t hash) { return hash & 0x7F; }
 
-// Helpers for checking the state of a control byte.
-inline bool IsEmpty(ctrl_t c) { return c == ctrl_t::kEmpty; }
-inline bool IsFull(ctrl_t c) {
-  // Cast `c` to the underlying type instead of casting `0` to `ctrl_t` as `0`
-  // is not a value in the enum. Both ways are equivalent, but this way makes
-  // linters happier.
-  return static_cast<std::underlying_type_t<ctrl_t>>(c) >= 0;
-}
-inline bool IsDeleted(ctrl_t c) { return c == ctrl_t::kDeleted; }
-inline bool IsEmptyOrDeleted(ctrl_t c) { return c < ctrl_t::kSentinel; }
-
-#ifdef ABSL_INTERNAL_HAVE_SSE2
-// Quick reference guide for intrinsics used below:
-//
-// * __m128i: An XMM (128-bit) word.
-//
-// * _mm_setzero_si128: Returns a zero vector.
-// * _mm_set1_epi8:     Returns a vector with the same i8 in each lane.
-//
-// * _mm_subs_epi8:    Saturating-subtracts two i8 vectors.
-// * _mm_and_si128:    Ands two i128s together.
-// * _mm_or_si128:     Ors two i128s together.
-// * _mm_andnot_si128: And-nots two i128s together.
-//
-// * _mm_cmpeq_epi8: Component-wise compares two i8 vectors for equality,
-//                   filling each lane with 0x00 or 0xff.
-// * _mm_cmpgt_epi8: Same as above, but using > rather than ==.
-//
-// * _mm_loadu_si128:  Performs an unaligned load of an i128.
-// * _mm_storeu_si128: Performs an unaligned store of an i128.
-//
-// * _mm_sign_epi8:     Retains, negates, or zeroes each i8 lane of the first
-//                      argument if the corresponding lane of the second
-//                      argument is positive, negative, or zero, respectively.
-// * _mm_movemask_epi8: Selects the sign bit out of each i8 lane and produces a
-//                      bitmask consisting of those bits.
-// * _mm_shuffle_epi8:  Selects i8s from the first argument, using the low
-//                      four bits of each i8 lane in the second argument as
-//                      indices.
-
-// https://github.com/abseil/abseil-cpp/issues/209
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
-// _mm_cmpgt_epi8 is broken under GCC with -funsigned-char
-// Work around this by using the portable implementation of Group
-// when using -funsigned-char under GCC.
-inline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) {
-#if defined(__GNUC__) && !defined(__clang__)
-  if (std::is_unsigned<char>::value) {
-    const __m128i mask = _mm_set1_epi8(0x80);
-    const __m128i diff = _mm_subs_epi8(b, a);
-    return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask);
-  }
-#endif
-  return _mm_cmpgt_epi8(a, b);
-}
-
-struct GroupSse2Impl {
-  static constexpr size_t kWidth = 16;  // the number of slots per group
-
-  explicit GroupSse2Impl(const ctrl_t* pos) {
-    ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos));
-  }
-
-  // Returns a bitmask representing the positions of slots that match hash.
-  BitMask<uint16_t, kWidth> Match(h2_t hash) const {
-    auto match = _mm_set1_epi8(static_cast<char>(hash));
-    BitMask<uint16_t, kWidth> result = BitMask<uint16_t, kWidth>(0);
-    result = BitMask<uint16_t, kWidth>(
-        static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
-    return result;
-  }
-
-  // Returns a bitmask representing the positions of empty slots.
-  NonIterableBitMask<uint16_t, kWidth> MaskEmpty() const {
-#ifdef ABSL_INTERNAL_HAVE_SSSE3
-    // This only works because ctrl_t::kEmpty is -128.
-    return NonIterableBitMask<uint16_t, kWidth>(
-        static_cast<uint16_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl))));
-#else
-    auto match = _mm_set1_epi8(static_cast<char>(ctrl_t::kEmpty));
-    return NonIterableBitMask<uint16_t, kWidth>(
-        static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
-#endif
-  }
-
-  // Returns a bitmask representing the positions of full slots.
-  // Note: for `is_small()` tables group may contain the "same" slot twice:
-  // original and mirrored.
-  BitMask<uint16_t, kWidth> MaskFull() const {
-    return BitMask<uint16_t, kWidth>(
-        static_cast<uint16_t>(_mm_movemask_epi8(ctrl) ^ 0xffff));
-  }
-
-  // Returns a bitmask representing the positions of non full slots.
-  // Note: this includes: kEmpty, kDeleted, kSentinel.
-  // It is useful in contexts when kSentinel is not present.
-  auto MaskNonFull() const {
-    return BitMask<uint16_t, kWidth>(
-        static_cast<uint16_t>(_mm_movemask_epi8(ctrl)));
-  }
-
-  // Returns a bitmask representing the positions of empty or deleted slots.
-  NonIterableBitMask<uint16_t, kWidth> MaskEmptyOrDeleted() const {
-    auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
-    return NonIterableBitMask<uint16_t, kWidth>(static_cast<uint16_t>(
-        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl))));
-  }
-
-  // Returns the number of trailing empty or deleted elements in the group.
-  uint32_t CountLeadingEmptyOrDeleted() const {
-    auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
-    return TrailingZeros(static_cast<uint32_t>(
-        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
-  }
-
-  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
-    auto msbs = _mm_set1_epi8(static_cast<char>(-128));
-    auto x126 = _mm_set1_epi8(126);
-#ifdef ABSL_INTERNAL_HAVE_SSSE3
-    auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
-#else
-    auto zero = _mm_setzero_si128();
-    auto special_mask = _mm_cmpgt_epi8_fixed(zero, ctrl);
-    auto res = _mm_or_si128(msbs, _mm_andnot_si128(special_mask, x126));
-#endif
-    _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res);
-  }
-
-  __m128i ctrl;
-};
-#endif  // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
-
-#if defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
-struct GroupAArch64Impl {
-  static constexpr size_t kWidth = 8;
-
-  explicit GroupAArch64Impl(const ctrl_t* pos) {
-    ctrl = vld1_u8(reinterpret_cast<const uint8_t*>(pos));
-  }
-
-  auto Match(h2_t hash) const {
-    uint8x8_t dup = vdup_n_u8(hash);
-    auto mask = vceq_u8(ctrl, dup);
-    return BitMask<uint64_t, kWidth, /*Shift=*/3,
-                   /*NullifyBitsOnIteration=*/true>(
-        vget_lane_u64(vreinterpret_u64_u8(mask), 0));
-  }
-
-  NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
-    uint64_t mask =
-        vget_lane_u64(vreinterpret_u64_u8(vceq_s8(
-                          vdup_n_s8(static_cast<int8_t>(ctrl_t::kEmpty)),
-                          vreinterpret_s8_u8(ctrl))),
-                      0);
-    return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
-  }
-
-  // Returns a bitmask representing the positions of full slots.
-  // Note: for `is_small()` tables group may contain the "same" slot twice:
-  // original and mirrored.
-  auto MaskFull() const {
-    uint64_t mask = vget_lane_u64(
-        vreinterpret_u64_u8(vcge_s8(vreinterpret_s8_u8(ctrl),
-                                    vdup_n_s8(static_cast<int8_t>(0)))),
-        0);
-    return BitMask<uint64_t, kWidth, /*Shift=*/3,
-                   /*NullifyBitsOnIteration=*/true>(mask);
-  }
-
-  // Returns a bitmask representing the positions of non full slots.
-  // Note: this includes: kEmpty, kDeleted, kSentinel.
-  // It is useful in contexts when kSentinel is not present.
-  auto MaskNonFull() const {
-    uint64_t mask = vget_lane_u64(
-        vreinterpret_u64_u8(vclt_s8(vreinterpret_s8_u8(ctrl),
-                                    vdup_n_s8(static_cast<int8_t>(0)))),
-        0);
-    return BitMask<uint64_t, kWidth, /*Shift=*/3,
-                   /*NullifyBitsOnIteration=*/true>(mask);
-  }
-
-  NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const {
-    uint64_t mask =
-        vget_lane_u64(vreinterpret_u64_u8(vcgt_s8(
-                          vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
-                          vreinterpret_s8_u8(ctrl))),
-                      0);
-    return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
-  }
-
-  uint32_t CountLeadingEmptyOrDeleted() const {
-    uint64_t mask =
-        vget_lane_u64(vreinterpret_u64_u8(vcle_s8(
-                          vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
-                          vreinterpret_s8_u8(ctrl))),
-                      0);
-    // Similar to MaskEmptyorDeleted() but we invert the logic to invert the
-    // produced bitfield. We then count number of trailing zeros.
-    // Clang and GCC optimize countr_zero to rbit+clz without any check for 0,
-    // so we should be fine.
-    return static_cast<uint32_t>(countr_zero(mask)) >> 3;
-  }
-
-  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
-    uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0);
-    constexpr uint64_t slsbs = 0x0202020202020202ULL;
-    constexpr uint64_t midbs = 0x7e7e7e7e7e7e7e7eULL;
-    auto x = slsbs & (mask >> 6);
-    auto res = (x + midbs) | kMsbs8Bytes;
-    little_endian::Store64(dst, res);
-  }
-
-  uint8x8_t ctrl;
-};
-#endif  // ABSL_INTERNAL_HAVE_ARM_NEON && ABSL_IS_LITTLE_ENDIAN
-
-struct GroupPortableImpl {
-  static constexpr size_t kWidth = 8;
-
-  explicit GroupPortableImpl(const ctrl_t* pos)
-      : ctrl(little_endian::Load64(pos)) {}
-
-  BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const {
-    // For the technique, see:
-    // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
-    // (Determine if a word has a byte equal to n).
-    //
-    // Caveat: there are false positives but:
-    // - they only occur if there is a real match
-    // - they never occur on ctrl_t::kEmpty, ctrl_t::kDeleted, ctrl_t::kSentinel
-    // - they will be handled gracefully by subsequent checks in code
-    //
-    // Example:
-    //   v = 0x1716151413121110
-    //   hash = 0x12
-    //   retval = (v - lsbs) & ~v & msbs = 0x0000000080800000
-    constexpr uint64_t lsbs = 0x0101010101010101ULL;
-    auto x = ctrl ^ (lsbs * hash);
-    return BitMask<uint64_t, kWidth, 3>((x - lsbs) & ~x & kMsbs8Bytes);
-  }
-
-  NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
-    return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & ~(ctrl << 6)) &
-                                                   kMsbs8Bytes);
-  }
-
-  // Returns a bitmask representing the positions of full slots.
-  // Note: for `is_small()` tables group may contain the "same" slot twice:
-  // original and mirrored.
-  BitMask<uint64_t, kWidth, 3> MaskFull() const {
-    return BitMask<uint64_t, kWidth, 3>((ctrl ^ kMsbs8Bytes) & kMsbs8Bytes);
-  }
-
-  // Returns a bitmask representing the positions of non full slots.
-  // Note: this includes: kEmpty, kDeleted, kSentinel.
-  // It is useful in contexts when kSentinel is not present.
-  auto MaskNonFull() const {
-    return BitMask<uint64_t, kWidth, 3>(ctrl & kMsbs8Bytes);
-  }
-
-  NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const {
-    return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & ~(ctrl << 7)) &
-                                                   kMsbs8Bytes);
-  }
-
-  uint32_t CountLeadingEmptyOrDeleted() const {
-    // ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and
-    // kDeleted. We lower all other bits and count number of trailing zeros.
-    constexpr uint64_t bits = 0x0101010101010101ULL;
-    return static_cast<uint32_t>(countr_zero((ctrl | ~(ctrl >> 7)) & bits) >>
-                                 3);
-  }
-
-  void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
-    constexpr uint64_t lsbs = 0x0101010101010101ULL;
-    auto x = ctrl & kMsbs8Bytes;
-    auto res = (~x + (x >> 7)) & ~lsbs;
-    little_endian::Store64(dst, res);
-  }
-
-  uint64_t ctrl;
-};
-
-#ifdef ABSL_INTERNAL_HAVE_SSE2
-using Group = GroupSse2Impl;
-using GroupFullEmptyOrDeleted = GroupSse2Impl;
-#elif defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
-using Group = GroupAArch64Impl;
-// For Aarch64, we use the portable implementation for counting and masking
-// full, empty or deleted group elements. This is to avoid the latency of moving
-// between data GPRs and Neon registers when it does not provide a benefit.
-// Using Neon is profitable when we call Match(), but is not when we don't,
-// which is the case when we do *EmptyOrDeleted and MaskFull operations.
-// It is difficult to make a similar approach beneficial on other architectures
-// such as x86 since they have much lower GPR <-> vector register transfer
-// latency and 16-wide Groups.
-using GroupFullEmptyOrDeleted = GroupPortableImpl;
-#else
-using Group = GroupPortableImpl;
-using GroupFullEmptyOrDeleted = GroupPortableImpl;
-#endif
-
 // When there is an insertion with no reserved growth, we rehash with
 // probability `min(1, RehashProbabilityConstant() / capacity())`. Using a
 // constant divided by capacity ensures that inserting N elements is still O(N)
@@ -957,10 +571,10 @@
   // references. We rehash on the first insertion after reserved_growth_ reaches
   // 0 after a call to reserve. We also do a rehash with low probability
   // whenever reserved_growth_ is zero.
-  bool should_rehash_for_bug_detection_on_insert(const ctrl_t* ctrl,
+  bool should_rehash_for_bug_detection_on_insert(PerTableSeed seed,
                                                  size_t capacity) const;
   // Similar to above, except that we don't depend on reserved_growth_.
-  bool should_rehash_for_bug_detection_on_move(const ctrl_t* ctrl,
+  bool should_rehash_for_bug_detection_on_move(PerTableSeed seed,
                                                size_t capacity) const;
   void maybe_increment_generation_on_insert() {
     if (reserved_growth_ == kReservedGrowthJustRanOut) reserved_growth_ = 0;
@@ -1014,10 +628,10 @@
   CommonFieldsGenerationInfoDisabled& operator=(
       CommonFieldsGenerationInfoDisabled&&) = default;
 
-  bool should_rehash_for_bug_detection_on_insert(const ctrl_t*, size_t) const {
+  bool should_rehash_for_bug_detection_on_insert(PerTableSeed, size_t) const {
     return false;
   }
-  bool should_rehash_for_bug_detection_on_move(const ctrl_t*, size_t) const {
+  bool should_rehash_for_bug_detection_on_move(PerTableSeed, size_t) const {
     return false;
   }
   void maybe_increment_generation_on_insert() {}
@@ -1105,19 +719,20 @@
 
   // Overwrites single empty slot with a full slot.
   void OverwriteEmptyAsFull() {
-    assert(GetGrowthLeft() > 0);
+    ABSL_SWISSTABLE_ASSERT(GetGrowthLeft() > 0);
     --growth_left_info_;
   }
 
   // Overwrites several empty slots with full slots.
-  void OverwriteManyEmptyAsFull(size_t cnt) {
-    assert(GetGrowthLeft() >= cnt);
-    growth_left_info_ -= cnt;
+  void OverwriteManyEmptyAsFull(size_t count) {
+    ABSL_SWISSTABLE_ASSERT(GetGrowthLeft() >= count);
+    growth_left_info_ -= count;
   }
 
   // Overwrites specified control element with full slot.
   void OverwriteControlAsFull(ctrl_t ctrl) {
-    assert(GetGrowthLeft() >= static_cast<size_t>(IsEmpty(ctrl)));
+    ABSL_SWISSTABLE_ASSERT(GetGrowthLeft() >=
+                           static_cast<size_t>(IsEmpty(ctrl)));
     growth_left_info_ -= static_cast<size_t>(IsEmpty(ctrl));
   }
 
@@ -1136,7 +751,14 @@
   // 2. There is no growth left.
   bool HasNoGrowthLeftAndNoDeleted() const { return growth_left_info_ == 0; }
 
-  // Returns true if table guaranteed to have no k
+  // Returns true if GetGrowthLeft() == 0, but must be called only if
+  // HasNoDeleted() is false. It is slightly more efficient.
+  bool HasNoGrowthLeftAssumingMayHaveDeleted() const {
+    ABSL_SWISSTABLE_ASSERT(!HasNoDeleted());
+    return growth_left_info_ == kDeletedBit;
+  }
+
+  // Returns true if table guaranteed to have no kDeleted slots.
   bool HasNoDeleted() const {
     return static_cast<std::make_signed_t<size_t>>(growth_left_info_) >= 0;
   }
@@ -1157,7 +779,7 @@
 // Returns whether `n` is a valid capacity (i.e., number of slots).
 //
 // A valid capacity is a non-zero integer `2^m - 1`.
-inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
+constexpr bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
 
 // Returns the number of "cloned control bytes".
 //
@@ -1173,26 +795,32 @@
 
 // Computes the offset from the start of the backing allocation of control.
 // infoz and growth_info are stored at the beginning of the backing array.
-inline static size_t ControlOffset(bool has_infoz) {
+constexpr size_t ControlOffset(bool has_infoz) {
   return (has_infoz ? sizeof(HashtablezInfoHandle) : 0) + sizeof(GrowthInfo);
 }
 
+// Returns the offset of the next item after `offset` that is aligned to `align`
+// bytes. `align` must be a power of two.
+constexpr size_t AlignUpTo(size_t offset, size_t align) {
+  return (offset + align - 1) & (~align + 1);
+}
+
 // Helper class for computing offsets and allocation size of hash set fields.
 class RawHashSetLayout {
  public:
-  explicit RawHashSetLayout(size_t capacity, size_t slot_align, bool has_infoz)
-      : capacity_(capacity),
-        control_offset_(ControlOffset(has_infoz)),
+  explicit RawHashSetLayout(size_t capacity, size_t slot_size,
+                            size_t slot_align, bool has_infoz)
+      : control_offset_(ControlOffset(has_infoz)),
         generation_offset_(control_offset_ + NumControlBytes(capacity)),
         slot_offset_(
-            (generation_offset_ + NumGenerationBytes() + slot_align - 1) &
-            (~slot_align + 1)) {
-    assert(IsValidCapacity(capacity));
+            AlignUpTo(generation_offset_ + NumGenerationBytes(), slot_align)),
+        alloc_size_(slot_offset_ + capacity * slot_size) {
+    ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));
+    ABSL_SWISSTABLE_ASSERT(
+        slot_size <=
+        ((std::numeric_limits<size_t>::max)() - slot_offset_) / capacity);
   }
 
-  // Returns the capacity of a table.
-  size_t capacity() const { return capacity_; }
-
   // Returns precomputed offset from the start of the backing allocation of
   // control.
   size_t control_offset() const { return control_offset_; }
@@ -1207,32 +835,17 @@
 
   // Given the capacity of a table, computes the total size of the backing
   // array.
-  size_t alloc_size(size_t slot_size) const {
-    return slot_offset_ + capacity_ * slot_size;
-  }
+  size_t alloc_size() const { return alloc_size_; }
 
  private:
-  size_t capacity_;
   size_t control_offset_;
   size_t generation_offset_;
   size_t slot_offset_;
+  size_t alloc_size_;
 };
 
 struct HashtableFreeFunctionsAccess;
 
-// We only allow a maximum of 1 SOO element, which makes the implementation
-// much simpler. Complications with multiple SOO elements include:
-// - Satisfying the guarantee that erasing one element doesn't invalidate
-//   iterators to other elements means we would probably need actual SOO
-//   control bytes.
-// - In order to prevent user code from depending on iteration order for small
-//   tables, we would need to randomize the iteration order somehow.
-constexpr size_t SooCapacity() { return 1; }
-// Sentinel type to indicate SOO CommonFields construction.
-struct soo_tag_t {};
-// Sentinel type to indicate SOO CommonFields construction with full size.
-struct full_soo_tag_t {};
-
 // Suppress erroneous uninitialized memory errors on GCC. For example, GCC
 // thinks that the call to slot_array() in find_or_prepare_insert() is reading
 // uninitialized memory, but slot_array is only called there when the table is
@@ -1260,7 +873,7 @@
 };
 
 struct HeapPtrs {
-  HeapPtrs() = default;
+  explicit HeapPtrs(uninitialized_tag_t) {}
   explicit HeapPtrs(ctrl_t* c) : control(c) {}
 
   // The control bytes (and, also, a pointer near to the base of the backing
@@ -1279,10 +892,13 @@
   MaybeInitializedPtr slot_array;
 };
 
+// Returns the maximum size of the SOO slot.
+constexpr size_t MaxSooSlotSize() { return sizeof(HeapPtrs); }
+
 // Manages the backing array pointers or the SOO slot. When raw_hash_set::is_soo
 // is true, the SOO slot is stored in `soo_data`. Otherwise, we use `heap`.
 union HeapOrSoo {
-  HeapOrSoo() = default;
+  explicit HeapOrSoo(uninitialized_tag_t) : heap(uninitialized_tag_t{}) {}
   explicit HeapOrSoo(ctrl_t* c) : heap(c) {}
 
   ctrl_t*& control() {
@@ -1305,44 +921,83 @@
   }
 
   HeapPtrs heap;
-  unsigned char soo_data[sizeof(HeapPtrs)];
+  unsigned char soo_data[MaxSooSlotSize()];
 };
 
+// Returns a reference to the GrowthInfo object stored immediately before
+// `control`.
+inline GrowthInfo& GetGrowthInfoFromControl(ctrl_t* control) {
+  auto* gl_ptr = reinterpret_cast<GrowthInfo*>(control) - 1;
+  ABSL_SWISSTABLE_ASSERT(
+      reinterpret_cast<uintptr_t>(gl_ptr) % alignof(GrowthInfo) == 0);
+  return *gl_ptr;
+}
+
 // CommonFields hold the fields in raw_hash_set that do not depend
 // on template parameters. This allows us to conveniently pass all
 // of this state to helper functions as a single argument.
 class CommonFields : public CommonFieldsGenerationInfo {
  public:
-  CommonFields() : capacity_(0), size_(0), heap_or_soo_(EmptyGroup()) {}
-  explicit CommonFields(soo_tag_t) : capacity_(SooCapacity()), size_(0) {}
+  explicit CommonFields(soo_tag_t)
+      : capacity_(SooCapacity()),
+        size_(no_seed_empty_tag_t{}),
+        heap_or_soo_(uninitialized_tag_t{}) {}
   explicit CommonFields(full_soo_tag_t)
-      : capacity_(SooCapacity()), size_(size_t{1} << HasInfozShift()) {}
+      : capacity_(SooCapacity()),
+        size_(full_soo_tag_t{}),
+        heap_or_soo_(uninitialized_tag_t{}) {}
+  explicit CommonFields(non_soo_tag_t)
+      : capacity_(0),
+        size_(no_seed_empty_tag_t{}),
+        heap_or_soo_(EmptyGroup()) {}
+  // For use in swapping.
+  explicit CommonFields(uninitialized_tag_t)
+      : size_(uninitialized_tag_t{}), heap_or_soo_(uninitialized_tag_t{}) {}
 
   // Not copyable
   CommonFields(const CommonFields&) = delete;
   CommonFields& operator=(const CommonFields&) = delete;
 
+  // Copy with guarantee that it is not SOO.
+  CommonFields(non_soo_tag_t, const CommonFields& that)
+      : capacity_(that.capacity_),
+        size_(that.size_),
+        heap_or_soo_(that.heap_or_soo_) {
+  }
+
   // Movable
   CommonFields(CommonFields&& that) = default;
   CommonFields& operator=(CommonFields&&) = default;
 
   template <bool kSooEnabled>
   static CommonFields CreateDefault() {
-    return kSooEnabled ? CommonFields{soo_tag_t{}} : CommonFields{};
+    return kSooEnabled ? CommonFields{soo_tag_t{}}
+                       : CommonFields{non_soo_tag_t{}};
   }
 
   // The inline data for SOO is written on top of control_/slots_.
   const void* soo_data() const { return heap_or_soo_.get_soo_data(); }
   void* soo_data() { return heap_or_soo_.get_soo_data(); }
 
-  HeapOrSoo heap_or_soo() const { return heap_or_soo_; }
-  const HeapOrSoo& heap_or_soo_ref() const { return heap_or_soo_; }
-
   ctrl_t* control() const { return heap_or_soo_.control(); }
-  void set_control(ctrl_t* c) { heap_or_soo_.control() = c; }
+
+  // When we set the control bytes, we also often want to generate a new seed.
+  // So we bundle these two operations together to make sure we don't forget to
+  // generate a new seed.
+  // The table will be invalidated if
+  // `kGenerateSeed && !empty() && !is_single_group(capacity())` because H1 is
+  // being changed. In such cases, we will need to rehash the table.
+  template <bool kGenerateSeed>
+  void set_control(ctrl_t* c) {
+    heap_or_soo_.control() = c;
+    if constexpr (kGenerateSeed) {
+      generate_new_seed();
+    }
+  }
   void* backing_array_start() const {
     // growth_info (and maybe infoz) is stored before control bytes.
-    assert(reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0);
+    ABSL_SWISSTABLE_ASSERT(
+        reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0);
     return control() - ControlOffset(has_infoz());
   }
 
@@ -1352,31 +1007,46 @@
   void set_slots(void* s) { heap_or_soo_.slot_array().set(s); }
 
   // The number of filled slots.
-  size_t size() const { return size_ >> HasInfozShift(); }
-  void set_size(size_t s) {
-    size_ = (s << HasInfozShift()) | (size_ & HasInfozMask());
-  }
+  size_t size() const { return size_.size(); }
+  // Sets the size to zero, but keeps hashinfoz bit and seed.
+  void set_size_to_zero() { size_.set_size_to_zero_keep_metadata(); }
   void set_empty_soo() {
     AssertInSooMode();
-    size_ = 0;
+    size_ = HashtableSize(no_seed_empty_tag_t{});
   }
   void set_full_soo() {
     AssertInSooMode();
-    size_ = size_t{1} << HasInfozShift();
+    size_ = HashtableSize(full_soo_tag_t{});
   }
   void increment_size() {
-    assert(size() < capacity());
-    size_ += size_t{1} << HasInfozShift();
+    ABSL_SWISSTABLE_ASSERT(size() < capacity());
+    size_.increment_size();
+  }
+  void increment_size(size_t n) {
+    ABSL_SWISSTABLE_ASSERT(size() + n <= capacity());
+    size_.increment_size(n);
   }
   void decrement_size() {
-    assert(size() > 0);
-    size_ -= size_t{1} << HasInfozShift();
+    ABSL_SWISSTABLE_ASSERT(!empty());
+    size_.decrement_size();
   }
+  bool empty() const { return size_.empty(); }
+
+  // The seed used for the H1 part of the hash function.
+  PerTableSeed seed() const { return size_.seed(); }
+  // Generates a new seed for the H1 part of the hash function.
+  // The table will be invalidated if
+  // `kGenerateSeed && !empty() && !is_single_group(capacity())` because H1 is
+  // being changed. In such cases, we will need to rehash the table.
+  void generate_new_seed() { size_.generate_new_seed(); }
+  void set_no_seed_for_testing() { size_.set_no_seed_for_testing(); }
 
   // The total number of available slots.
   size_t capacity() const { return capacity_; }
   void set_capacity(size_t c) {
-    assert(c == 0 || IsValidCapacity(c));
+    // We allow setting above the max valid capacity for debugging purposes.
+    ABSL_SWISSTABLE_ASSERT(c == 0 || IsValidCapacity(c) ||
+                           c > kAboveMaxValidCapacity);
     capacity_ = c;
   }
 
@@ -1387,20 +1057,14 @@
   size_t growth_left() const { return growth_info().GetGrowthLeft(); }
 
   GrowthInfo& growth_info() {
-    auto* gl_ptr = reinterpret_cast<GrowthInfo*>(control()) - 1;
-    assert(reinterpret_cast<uintptr_t>(gl_ptr) % alignof(GrowthInfo) == 0);
-    return *gl_ptr;
+    return GetGrowthInfoFromControl(control());
   }
   GrowthInfo growth_info() const {
     return const_cast<CommonFields*>(this)->growth_info();
   }
 
-  bool has_infoz() const {
-    return ABSL_PREDICT_FALSE((size_ & HasInfozMask()) != 0);
-  }
-  void set_has_infoz(bool has_infoz) {
-    size_ = (size() << HasInfozShift()) | static_cast<size_t>(has_infoz);
-  }
+  bool has_infoz() const { return size_.has_infoz(); }
+  void set_has_infoz() { size_.set_has_infoz(); }
 
   HashtablezInfoHandle infoz() {
     return has_infoz()
@@ -1408,17 +1072,23 @@
                : HashtablezInfoHandle();
   }
   void set_infoz(HashtablezInfoHandle infoz) {
-    assert(has_infoz());
+    ABSL_SWISSTABLE_ASSERT(has_infoz());
     *reinterpret_cast<HashtablezInfoHandle*>(backing_array_start()) = infoz;
   }
 
   bool should_rehash_for_bug_detection_on_insert() const {
+    if constexpr (!SwisstableGenerationsEnabled()) {
+      return false;
+    }
+    // As an optimization, we avoid calling ShouldRehashForBugDetection if we
+    // will end up rehashing anyways.
+    if (growth_left() == 0) return false;
     return CommonFieldsGenerationInfo::
-        should_rehash_for_bug_detection_on_insert(control(), capacity());
+        should_rehash_for_bug_detection_on_insert(seed(), capacity());
   }
   bool should_rehash_for_bug_detection_on_move() const {
     return CommonFieldsGenerationInfo::should_rehash_for_bug_detection_on_move(
-        control(), capacity());
+        seed(), capacity());
   }
   void reset_reserved_growth(size_t reservation) {
     CommonFieldsGenerationInfo::reset_reserved_growth(reservation, size());
@@ -1426,8 +1096,8 @@
 
   // The size of the backing array allocation.
   size_t alloc_size(size_t slot_size, size_t slot_align) const {
-    return RawHashSetLayout(capacity(), slot_align, has_infoz())
-        .alloc_size(slot_size);
+    return RawHashSetLayout(capacity(), slot_size, slot_align, has_infoz())
+        .alloc_size();
   }
 
   // Move fields other than heap_or_soo_.
@@ -1444,6 +1114,20 @@
         std::count(control(), control() + capacity(), ctrl_t::kDeleted));
   }
 
+  // Helper to enable sanitizer mode validation to protect against reentrant
+  // calls during element constructor/destructor.
+  template <typename F>
+  void RunWithReentrancyGuard(F f) {
+#ifdef NDEBUG
+    f();
+    return;
+#endif
+    const size_t cap = capacity();
+    set_capacity(InvalidCapacity::kReentrance);
+    f();
+    set_capacity(cap);
+  }
+
  private:
   // We store the has_infoz bit in the lowest bit of size_.
   static constexpr size_t HasInfozShift() { return 1; }
@@ -1454,8 +1138,8 @@
   // We can't assert that SOO is enabled because we don't have SooEnabled(), but
   // we assert what we can.
   void AssertInSooMode() const {
-    assert(capacity() == SooCapacity());
-    assert(!has_infoz());
+    ABSL_SWISSTABLE_ASSERT(capacity() == SooCapacity());
+    ABSL_SWISSTABLE_ASSERT(!has_infoz());
   }
 
   // The number of slots in the backing array. This is always 2^N-1 for an
@@ -1466,11 +1150,10 @@
   // regressions, presumably because we need capacity to do find operations.
   size_t capacity_;
 
-  // The size and also has one bit that stores whether we have infoz.
   // TODO(b/289225379): we could put size_ into HeapOrSoo and make capacity_
   // encode the size in SOO case. We would be making size()/capacity() more
   // expensive in order to have more SOO space.
-  size_t size_;
+  HashtableSize size_;
 
   // Either the control/slots pointers or the SOO slot.
   HeapOrSoo heap_or_soo_;
@@ -1480,11 +1163,17 @@
 class raw_hash_set;
 
 // Returns the next valid capacity after `n`.
-inline size_t NextCapacity(size_t n) {
-  assert(IsValidCapacity(n) || n == 0);
+constexpr size_t NextCapacity(size_t n) {
+  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(n) || n == 0);
   return n * 2 + 1;
 }
 
+// Returns the previous valid capacity before `n`.
+constexpr size_t PreviousCapacity(size_t n) {
+  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(n));
+  return n / 2;
+}
+
 // Applies the following mapping to every byte in the control array:
 //   * kDeleted -> kEmpty
 //   * kEmpty -> kEmpty
@@ -1496,7 +1185,7 @@
 void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity);
 
 // Converts `n` into the next valid capacity, per `IsValidCapacity`.
-inline size_t NormalizeCapacity(size_t n) {
+constexpr size_t NormalizeCapacity(size_t n) {
   return n ? ~size_t{} >> countl_zero(n) : 1;
 }
 
@@ -1510,8 +1199,8 @@
 
 // Given `capacity`, applies the load factor; i.e., it returns the maximum
 // number of values we should put into the table before a resizing rehash.
-inline size_t CapacityToGrowth(size_t capacity) {
-  assert(IsValidCapacity(capacity));
+constexpr size_t CapacityToGrowth(size_t capacity) {
+  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));
   // `capacity*7/8`
   if (Group::kWidth == 8 && capacity == 7) {
     // x-x/8 does not work when x==7.
@@ -1520,18 +1209,28 @@
   return capacity - capacity / 8;
 }
 
-// Given `growth`, "unapplies" the load factor to find how large the capacity
+// Given `size`, "unapplies" the load factor to find how large the capacity
 // should be to stay within the load factor.
 //
-// This might not be a valid capacity and `NormalizeCapacity()` should be
-// called on this.
-inline size_t GrowthToLowerboundCapacity(size_t growth) {
-  // `growth*8/7`
-  if (Group::kWidth == 8 && growth == 7) {
-    // x+(x-1)/7 does not work when x==7.
-    return 8;
+// For size == 0, returns 0.
+// For other values, returns the same as `NormalizeCapacity(size*8/7)`.
+constexpr size_t SizeToCapacity(size_t size) {
+  if (size == 0) {
+    return 0;
   }
-  return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
+  // The minimum possible capacity is NormalizeCapacity(size).
+  // Shifting right `~size_t{}` by `leading_zeros` yields
+  // NormalizeCapacity(size).
+  int leading_zeros = absl::countl_zero(size);
+  constexpr size_t kLast3Bits = size_t{7} << (sizeof(size_t) * 8 - 3);
+  size_t max_size_for_next_capacity = kLast3Bits >> leading_zeros;
+  // Decrease shift if size is too big for the minimum capacity.
+  leading_zeros -= static_cast<int>(size > max_size_for_next_capacity);
+  if constexpr (Group::kWidth == 8) {
+    // Formula doesn't work when size==7 for 8-wide groups.
+    leading_zeros -= (size == 7);
+  }
+  return (~size_t{}) >> leading_zeros;
 }
 
 template <class InputIter>
@@ -1540,12 +1239,9 @@
   if (bucket_count != 0) {
     return bucket_count;
   }
-  using InputIterCategory =
-      typename std::iterator_traits<InputIter>::iterator_category;
-  if (std::is_base_of<std::random_access_iterator_tag,
-                      InputIterCategory>::value) {
-    return GrowthToLowerboundCapacity(
-        static_cast<size_t>(std::distance(first, last)));
+  if (base_internal::IsAtLeastIterator<std::random_access_iterator_tag,
+                                       InputIter>()) {
+    return SizeToCapacity(static_cast<size_t>(std::distance(first, last)));
   }
   return 0;
 }
@@ -1618,7 +1314,7 @@
           FATAL, "Invalid iterator comparison. The element was likely erased.");
     }
   } else {
-    ABSL_HARDENING_ASSERT(
+    ABSL_HARDENING_ASSERT_SLOW(
         ctrl_is_valid_for_comparison &&
         "Invalid iterator comparison. The element might have been erased or "
         "the table might have rehashed. Consider running with --config=asan to "
@@ -1703,7 +1399,7 @@
             "hashtable.");
     fail_if(true, "Comparing non-end() iterators from different hashtables.");
   } else {
-    ABSL_HARDENING_ASSERT(
+    ABSL_HARDENING_ASSERT_SLOW(
         AreItersFromSameContainer(ctrl_a, ctrl_b, slot_a, slot_b) &&
         "Invalid iterator comparison. The iterators may be from different "
         "containers or the container might have rehashed or moved. Consider "
@@ -1716,33 +1412,22 @@
   size_t probe_length;
 };
 
-// Whether a table is "small". A small table fits entirely into a probing
-// group, i.e., has a capacity < `Group::kWidth`.
-//
-// In small mode we are able to use the whole capacity. The extra control
-// bytes give us at least one "empty" control byte to stop the iteration.
-// This is important to make 1 a valid capacity.
-//
-// In small mode only the first `capacity` control bytes after the sentinel
-// are valid. The rest contain dummy ctrl_t::kEmpty values that do not
-// represent a real slot. This is important to take into account on
-// `find_first_non_full()`, where we never try
-// `ShouldInsertBackwards()` for small tables.
-inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; }
-
 // Whether a table fits entirely into a probing group.
 // Arbitrary order of elements in such tables is correct.
-inline bool is_single_group(size_t capacity) {
+constexpr bool is_single_group(size_t capacity) {
   return capacity <= Group::kWidth;
 }
 
 // Begins a probing operation on `common.control`, using `hash`.
-inline probe_seq<Group::kWidth> probe(const ctrl_t* ctrl, const size_t capacity,
+inline probe_seq<Group::kWidth> probe(size_t h1, size_t capacity) {
+  return probe_seq<Group::kWidth>(h1, capacity);
+}
+inline probe_seq<Group::kWidth> probe(PerTableSeed seed, size_t capacity,
                                       size_t hash) {
-  return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity);
+  return probe(H1(hash, seed), capacity);
 }
 inline probe_seq<Group::kWidth> probe(const CommonFields& common, size_t hash) {
-  return probe(common.control(), common.capacity(), hash);
+  return probe(common.seed(), common.capacity(), hash);
 }
 
 // Probes an array of control bits using a probe sequence derived from `hash`,
@@ -1752,56 +1437,75 @@
 //
 // NOTE: this function must work with tables having both empty and deleted
 // slots in the same group. Such tables appear during `erase()`.
+FindInfo find_first_non_full(const CommonFields& common, size_t hash);
+
+constexpr size_t kProbedElementIndexSentinel = ~size_t{};
+
+// Implementation detail of transfer_unprobed_elements_to_next_capacity_fn.
+// Tries to find the new index for an element whose hash corresponds to
+// `h1` for growth to the next capacity.
+// Returns kProbedElementIndexSentinel if full probing is required.
+//
+// If element is located in the first probing group in the table before growth,
+// returns one of two positions: `old_index` or `old_index + old_capacity + 1`.
+//
+// Otherwise, we will try to insert it into the first probe group of the new
+// table. We only attempt to do so if the first probe group is already
+// initialized.
 template <typename = void>
-inline FindInfo find_first_non_full(const CommonFields& common, size_t hash) {
-  auto seq = probe(common, hash);
-  const ctrl_t* ctrl = common.control();
-  if (IsEmptyOrDeleted(ctrl[seq.offset()]) &&
-      !ShouldInsertBackwards(common.capacity(), hash, ctrl)) {
-    return {seq.offset(), /*probe_length=*/0};
+inline size_t TryFindNewIndexWithoutProbing(size_t h1, size_t old_index,
+                                            size_t old_capacity,
+                                            ctrl_t* new_ctrl,
+                                            size_t new_capacity) {
+  size_t index_diff = old_index - h1;
+  // The first probe group starts with h1 & capacity.
+  // All following groups start at (h1 + Group::kWidth * K) & capacity.
+  // We can find an index within the floating group as index_diff modulo
+  // Group::kWidth.
+  // Both old and new capacity are larger than Group::kWidth so we can avoid
+  // computing `& capacity`.
+  size_t in_floating_group_index = index_diff & (Group::kWidth - 1);
+  // By subtracting we will get the difference between the first probe group
+  // and the probe group corresponding to old_index.
+  index_diff -= in_floating_group_index;
+  if (ABSL_PREDICT_TRUE((index_diff & old_capacity) == 0)) {
+    size_t new_index = (h1 + in_floating_group_index) & new_capacity;
+    ABSL_ASSUME(new_index != kProbedElementIndexSentinel);
+    return new_index;
   }
-  while (true) {
-    GroupFullEmptyOrDeleted g{ctrl + seq.offset()};
-    auto mask = g.MaskEmptyOrDeleted();
-    if (mask) {
-      return {
-          seq.offset(GetInsertionOffset(mask, common.capacity(), hash, ctrl)),
-          seq.index()};
-    }
-    seq.next();
-    assert(seq.index() <= common.capacity() && "full table!");
+  ABSL_SWISSTABLE_ASSERT(((old_index - h1) & old_capacity) >= Group::kWidth);
+  // Try to insert element into the first probe group.
+  // new_ctrl is not yet fully initialized so we can't use regular search via
+  // find_first_non_full.
+
+  // We can search in the first probe group only if it is located in already
+  // initialized part of the table.
+  if (ABSL_PREDICT_FALSE((h1 & old_capacity) >= old_index)) {
+    return kProbedElementIndexSentinel;
   }
+  size_t offset = h1 & new_capacity;
+  Group new_g(new_ctrl + offset);
+  if (auto mask = new_g.MaskNonFull(); ABSL_PREDICT_TRUE(mask)) {
+    size_t result = offset + mask.LowestBitSet();
+    ABSL_ASSUME(result != kProbedElementIndexSentinel);
+    return result;
+  }
+  return kProbedElementIndexSentinel;
 }
 
-// Extern template for inline function keep possibility of inlining.
+// Extern template for inline function keeps possibility of inlining.
 // When compiler decided to not inline, no symbols will be added to the
 // corresponding translation unit.
-extern template FindInfo find_first_non_full(const CommonFields&, size_t);
-
-// Non-inlined version of find_first_non_full for use in less
-// performance critical routines.
-FindInfo find_first_non_full_outofline(const CommonFields&, size_t);
-
-inline void ResetGrowthLeft(CommonFields& common) {
-  common.growth_info().InitGrowthLeftNoDeleted(
-      CapacityToGrowth(common.capacity()) - common.size());
-}
-
-// Sets `ctrl` to `{kEmpty, kSentinel, ..., kEmpty}`, marking the entire
-// array as marked as empty.
-inline void ResetCtrl(CommonFields& common, size_t slot_size) {
-  const size_t capacity = common.capacity();
-  ctrl_t* ctrl = common.control();
-  std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
-              capacity + 1 + NumClonedBytes());
-  ctrl[capacity] = ctrl_t::kSentinel;
-  SanitizerPoisonMemoryRegion(common.slot_array(), slot_size * capacity);
-}
+extern template size_t TryFindNewIndexWithoutProbing(size_t h1,
+                                                     size_t old_index,
+                                                     size_t old_capacity,
+                                                     ctrl_t* new_ctrl,
+                                                     size_t new_capacity);
 
 // Sets sanitizer poisoning for slot corresponding to control byte being set.
 inline void DoSanitizeOnSetCtrl(const CommonFields& c, size_t i, ctrl_t h,
                                 size_t slot_size) {
-  assert(i < c.capacity());
+  ABSL_SWISSTABLE_ASSERT(i < c.capacity());
   auto* slot_i = static_cast<const char*>(c.slot_array()) + i * slot_size;
   if (IsFull(h)) {
     SanitizerUnpoisonMemoryRegion(slot_i, slot_size);
@@ -1831,7 +1535,7 @@
 // setting the cloned control byte.
 inline void SetCtrlInSingleGroupTable(const CommonFields& c, size_t i, ctrl_t h,
                                       size_t slot_size) {
-  assert(is_single_group(c.capacity()));
+  ABSL_SWISSTABLE_ASSERT(is_single_group(c.capacity()));
   DoSanitizeOnSetCtrl(c, i, h, slot_size);
   ctrl_t* ctrl = c.control();
   ctrl[i] = h;
@@ -1843,6 +1547,22 @@
   SetCtrlInSingleGroupTable(c, i, static_cast<ctrl_t>(h), slot_size);
 }
 
+// Like SetCtrl, but in a table with capacity >= Group::kWidth - 1,
+// we can save some operations when setting the cloned control byte.
+inline void SetCtrlInLargeTable(const CommonFields& c, size_t i, ctrl_t h,
+                                size_t slot_size) {
+  ABSL_SWISSTABLE_ASSERT(c.capacity() >= Group::kWidth - 1);
+  DoSanitizeOnSetCtrl(c, i, h, slot_size);
+  ctrl_t* ctrl = c.control();
+  ctrl[i] = h;
+  ctrl[((i - NumClonedBytes()) & c.capacity()) + NumClonedBytes()] = h;
+}
+// Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
+inline void SetCtrlInLargeTable(const CommonFields& c, size_t i, h2_t h,
+                                size_t slot_size) {
+  SetCtrlInLargeTable(c, i, static_cast<ctrl_t>(h), slot_size);
+}
+
 // growth_info (which is a size_t) is stored with the backing array.
 constexpr size_t BackingArrayAlignment(size_t align_of_slot) {
   return (std::max)(align_of_slot, alignof(GrowthInfo));
@@ -1855,442 +1575,283 @@
                             (slot * slot_size));
 }
 
-// Iterates over all full slots and calls `cb(const ctrl_t*, SlotType*)`.
-// No insertion to the table allowed during Callback call.
+// Iterates over all full slots and calls `cb(const ctrl_t*, void*)`.
+// No insertion to the table is allowed during `cb` call.
 // Erasure is allowed only for the element passed to the callback.
-template <class SlotType, class Callback>
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline void IterateOverFullSlots(
-    const CommonFields& c, SlotType* slot, Callback cb) {
-  const size_t cap = c.capacity();
-  const ctrl_t* ctrl = c.control();
-  if (is_small(cap)) {
-    // Mirrored/cloned control bytes in small table are also located in the
-    // first group (starting from position 0). We are taking group from position
-    // `capacity` in order to avoid duplicates.
-
-    // Small tables capacity fits into portable group, where
-    // GroupPortableImpl::MaskFull is more efficient for the
-    // capacity <= GroupPortableImpl::kWidth.
-    assert(cap <= GroupPortableImpl::kWidth &&
-           "unexpectedly large small capacity");
-    static_assert(Group::kWidth >= GroupPortableImpl::kWidth,
-                  "unexpected group width");
-    // Group starts from kSentinel slot, so indices in the mask will
-    // be increased by 1.
-    const auto mask = GroupPortableImpl(ctrl + cap).MaskFull();
-    --ctrl;
-    --slot;
-    for (uint32_t i : mask) {
-      cb(ctrl + i, slot + i);
-    }
-    return;
-  }
-  size_t remaining = c.size();
-  ABSL_ATTRIBUTE_UNUSED const size_t original_size_for_assert = remaining;
-  while (remaining != 0) {
-    for (uint32_t i : GroupFullEmptyOrDeleted(ctrl).MaskFull()) {
-      assert(IsFull(ctrl[i]) && "hash table was modified unexpectedly");
-      cb(ctrl + i, slot + i);
-      --remaining;
-    }
-    ctrl += Group::kWidth;
-    slot += Group::kWidth;
-    assert((remaining == 0 || *(ctrl - 1) != ctrl_t::kSentinel) &&
-           "hash table was modified unexpectedly");
-  }
-  // NOTE: erasure of the current element is allowed in callback for
-  // absl::erase_if specialization. So we use `>=`.
-  assert(original_size_for_assert >= c.size() &&
-         "hash table was modified unexpectedly");
-}
+// The table must not be in SOO mode.
+void IterateOverFullSlots(const CommonFields& c, size_t slot_size,
+                          absl::FunctionRef<void(const ctrl_t*, void*)> cb);
 
 template <typename CharAlloc>
-constexpr bool ShouldSampleHashtablezInfo() {
+constexpr bool ShouldSampleHashtablezInfoForAlloc() {
   // Folks with custom allocators often make unwarranted assumptions about the
   // behavior of their classes vis-a-vis trivial destructability and what
   // calls they will or won't make.  Avoid sampling for people with custom
   // allocators to get us out of this mess.  This is not a hard guarantee but
   // a workaround while we plan the exact guarantee we want to provide.
-  return std::is_same<CharAlloc, std::allocator<char>>::value;
+  return std::is_same_v<CharAlloc, std::allocator<char>>;
 }
 
 template <bool kSooEnabled>
-HashtablezInfoHandle SampleHashtablezInfo(size_t sizeof_slot, size_t sizeof_key,
-                                          size_t sizeof_value,
-                                          size_t old_capacity, bool was_soo,
-                                          HashtablezInfoHandle forced_infoz,
-                                          CommonFields& c) {
-  if (forced_infoz.IsSampled()) return forced_infoz;
+bool ShouldSampleHashtablezInfoOnResize(bool force_sampling,
+                                        bool is_hashtablez_eligible,
+                                        size_t old_capacity, CommonFields& c) {
+  if (!is_hashtablez_eligible) return false;
+  // Force sampling is only allowed for SOO tables.
+  ABSL_SWISSTABLE_ASSERT(kSooEnabled || !force_sampling);
+  if (kSooEnabled && force_sampling) {
+    return true;
+  }
   // In SOO, we sample on the first insertion so if this is an empty SOO case
   // (e.g. when reserve is called), then we still need to sample.
-  if (kSooEnabled && was_soo && c.size() == 0) {
-    return Sample(sizeof_slot, sizeof_key, sizeof_value, SooCapacity());
+  if (kSooEnabled && old_capacity == SooCapacity() && c.empty()) {
+    return ShouldSampleNextTable();
   }
-  // For non-SOO cases, we sample whenever the capacity is increasing from zero
-  // to non-zero.
   if (!kSooEnabled && old_capacity == 0) {
-    return Sample(sizeof_slot, sizeof_key, sizeof_value, 0);
+    return ShouldSampleNextTable();
   }
-  return c.infoz();
+  return false;
 }
 
-// Helper class to perform resize of the hash set.
-//
-// It contains special optimizations for small group resizes.
-// See GrowIntoSingleGroupShuffleControlBytes for details.
-class HashSetResizeHelper {
- public:
-  explicit HashSetResizeHelper(CommonFields& c, bool was_soo, bool had_soo_slot,
-                               HashtablezInfoHandle forced_infoz)
-      : old_capacity_(c.capacity()),
-        had_infoz_(c.has_infoz()),
-        was_soo_(was_soo),
-        had_soo_slot_(had_soo_slot),
-        forced_infoz_(forced_infoz) {}
-
-  // Optimized for small groups version of `find_first_non_full`.
-  // Beneficial only right after calling `raw_hash_set::resize`.
-  // It is safe to call in case capacity is big or was not changed, but there
-  // will be no performance benefit.
-  // It has implicit assumption that `resize` will call
-  // `GrowSizeIntoSingleGroup*` in case `IsGrowingIntoSingleGroupApplicable`.
-  // Falls back to `find_first_non_full` in case of big groups.
-  static FindInfo FindFirstNonFullAfterResize(const CommonFields& c,
-                                              size_t old_capacity,
-                                              size_t hash) {
-    if (!IsGrowingIntoSingleGroupApplicable(old_capacity, c.capacity())) {
-      return find_first_non_full(c, hash);
-    }
-    // Find a location for the new element non-deterministically.
-    // Note that any position is correct.
-    // It will located at `half_old_capacity` or one of the other
-    // empty slots with approximately 50% probability each.
-    size_t offset = probe(c, hash).offset();
-
-    // Note that we intentionally use unsigned int underflow.
-    if (offset - (old_capacity + 1) >= old_capacity) {
-      // Offset fall on kSentinel or into the mostly occupied first half.
-      offset = old_capacity / 2;
-    }
-    assert(IsEmpty(c.control()[offset]));
-    return FindInfo{offset, 0};
-  }
-
-  HeapOrSoo& old_heap_or_soo() { return old_heap_or_soo_; }
-  void* old_soo_data() { return old_heap_or_soo_.get_soo_data(); }
-  ctrl_t* old_ctrl() const {
-    assert(!was_soo_);
-    return old_heap_or_soo_.control();
-  }
-  void* old_slots() const {
-    assert(!was_soo_);
-    return old_heap_or_soo_.slot_array().get();
-  }
-  size_t old_capacity() const { return old_capacity_; }
-
-  // Returns the index of the SOO slot when growing from SOO to non-SOO in a
-  // single group. See also InitControlBytesAfterSoo(). It's important to use
-  // index 1 so that when resizing from capacity 1 to 3, we can still have
-  // random iteration order between the first two inserted elements.
-  // I.e. it allows inserting the second element at either index 0 or 2.
-  static size_t SooSlotIndex() { return 1; }
-
-  // Allocates a backing array for the hashtable.
-  // Reads `capacity` and updates all other fields based on the result of
-  // the allocation.
-  //
-  // It also may do the following actions:
-  // 1. initialize control bytes
-  // 2. initialize slots
-  // 3. deallocate old slots.
-  //
-  // We are bundling a lot of functionality
-  // in one ABSL_ATTRIBUTE_NOINLINE function in order to minimize binary code
-  // duplication in raw_hash_set<>::resize.
-  //
-  // `c.capacity()` must be nonzero.
-  // POSTCONDITIONS:
-  //  1. CommonFields is initialized.
-  //
-  //  if IsGrowingIntoSingleGroupApplicable && TransferUsesMemcpy
-  //    Both control bytes and slots are fully initialized.
-  //    old_slots are deallocated.
-  //    infoz.RecordRehash is called.
-  //
-  //  if IsGrowingIntoSingleGroupApplicable && !TransferUsesMemcpy
-  //    Control bytes are fully initialized.
-  //    infoz.RecordRehash is called.
-  //    GrowSizeIntoSingleGroup must be called to finish slots initialization.
-  //
-  //  if !IsGrowingIntoSingleGroupApplicable
-  //    Control bytes are initialized to empty table via ResetCtrl.
-  //    raw_hash_set<>::resize must insert elements regularly.
-  //    infoz.RecordRehash is called if old_capacity == 0.
-  //
-  //  Returns IsGrowingIntoSingleGroupApplicable result to avoid recomputation.
-  template <typename Alloc, size_t SizeOfSlot, bool TransferUsesMemcpy,
-            bool SooEnabled, size_t AlignOfSlot>
-  ABSL_ATTRIBUTE_NOINLINE bool InitializeSlots(CommonFields& c, Alloc alloc,
-                                               ctrl_t soo_slot_h2,
-                                               size_t key_size,
-                                               size_t value_size) {
-    assert(c.capacity());
-    HashtablezInfoHandle infoz =
-        ShouldSampleHashtablezInfo<Alloc>()
-            ? SampleHashtablezInfo<SooEnabled>(SizeOfSlot, key_size, value_size,
-                                               old_capacity_, was_soo_,
-                                               forced_infoz_, c)
-            : HashtablezInfoHandle{};
-
-    const bool has_infoz = infoz.IsSampled();
-    RawHashSetLayout layout(c.capacity(), AlignOfSlot, has_infoz);
-    char* mem = static_cast<char*>(Allocate<BackingArrayAlignment(AlignOfSlot)>(
-        &alloc, layout.alloc_size(SizeOfSlot)));
-    const GenerationType old_generation = c.generation();
-    c.set_generation_ptr(
-        reinterpret_cast<GenerationType*>(mem + layout.generation_offset()));
-    c.set_generation(NextGeneration(old_generation));
-    c.set_control(reinterpret_cast<ctrl_t*>(mem + layout.control_offset()));
-    c.set_slots(mem + layout.slot_offset());
-    ResetGrowthLeft(c);
-
-    const bool grow_single_group =
-        IsGrowingIntoSingleGroupApplicable(old_capacity_, layout.capacity());
-    if (SooEnabled && was_soo_ && grow_single_group) {
-      InitControlBytesAfterSoo(c.control(), soo_slot_h2, layout.capacity());
-      if (TransferUsesMemcpy && had_soo_slot_) {
-        TransferSlotAfterSoo(c, SizeOfSlot);
-      }
-      // SooEnabled implies that old_capacity_ != 0.
-    } else if ((SooEnabled || old_capacity_ != 0) && grow_single_group) {
-      if (TransferUsesMemcpy) {
-        GrowSizeIntoSingleGroupTransferable(c, SizeOfSlot);
-        DeallocateOld<AlignOfSlot>(alloc, SizeOfSlot);
-      } else {
-        GrowIntoSingleGroupShuffleControlBytes(c.control(), layout.capacity());
-      }
-    } else {
-      ResetCtrl(c, SizeOfSlot);
-    }
-
-    c.set_has_infoz(has_infoz);
-    if (has_infoz) {
-      infoz.RecordStorageChanged(c.size(), layout.capacity());
-      if ((SooEnabled && was_soo_) || grow_single_group || old_capacity_ == 0) {
-        infoz.RecordRehash(0);
-      }
-      c.set_infoz(infoz);
-    }
-    return grow_single_group;
-  }
-
-  // Relocates slots into new single group consistent with
-  // GrowIntoSingleGroupShuffleControlBytes.
-  //
-  // PRECONDITIONS:
-  // 1. GrowIntoSingleGroupShuffleControlBytes was already called.
-  template <class PolicyTraits, class Alloc>
-  void GrowSizeIntoSingleGroup(CommonFields& c, Alloc& alloc_ref) {
-    assert(old_capacity_ < Group::kWidth / 2);
-    assert(IsGrowingIntoSingleGroupApplicable(old_capacity_, c.capacity()));
-    using slot_type = typename PolicyTraits::slot_type;
-    assert(is_single_group(c.capacity()));
-
-    auto* new_slots = static_cast<slot_type*>(c.slot_array());
-    auto* old_slots_ptr = static_cast<slot_type*>(old_slots());
-
-    size_t shuffle_bit = old_capacity_ / 2 + 1;
-    for (size_t i = 0; i < old_capacity_; ++i) {
-      if (IsFull(old_ctrl()[i])) {
-        size_t new_i = i ^ shuffle_bit;
-        SanitizerUnpoisonMemoryRegion(new_slots + new_i, sizeof(slot_type));
-        PolicyTraits::transfer(&alloc_ref, new_slots + new_i,
-                               old_slots_ptr + i);
-      }
-    }
-    PoisonSingleGroupEmptySlots(c, sizeof(slot_type));
-  }
-
-  // Deallocates old backing array.
-  template <size_t AlignOfSlot, class CharAlloc>
-  void DeallocateOld(CharAlloc alloc_ref, size_t slot_size) {
-    SanitizerUnpoisonMemoryRegion(old_slots(), slot_size * old_capacity_);
-    auto layout = RawHashSetLayout(old_capacity_, AlignOfSlot, had_infoz_);
-    Deallocate<BackingArrayAlignment(AlignOfSlot)>(
-        &alloc_ref, old_ctrl() - layout.control_offset(),
-        layout.alloc_size(slot_size));
-  }
-
- private:
-  // Returns true if `GrowSizeIntoSingleGroup` can be used for resizing.
-  static bool IsGrowingIntoSingleGroupApplicable(size_t old_capacity,
-                                                 size_t new_capacity) {
-    // NOTE that `old_capacity < new_capacity` in order to have
-    // `old_capacity < Group::kWidth / 2` to make faster copies of 8 bytes.
-    return is_single_group(new_capacity) && old_capacity < new_capacity;
-  }
-
-  // Relocates control bytes and slots into new single group for
-  // transferable objects.
-  // Must be called only if IsGrowingIntoSingleGroupApplicable returned true.
-  void GrowSizeIntoSingleGroupTransferable(CommonFields& c, size_t slot_size);
-
-  // If there was an SOO slot and slots are transferable, transfers the SOO slot
-  // into the new heap allocation. Must be called only if
-  // IsGrowingIntoSingleGroupApplicable returned true.
-  void TransferSlotAfterSoo(CommonFields& c, size_t slot_size);
-
-  // Shuffle control bits deterministically to the next capacity.
-  // Returns offset for newly added element with given hash.
-  //
-  // PRECONDITIONs:
-  // 1. new_ctrl is allocated for new_capacity,
-  //    but not initialized.
-  // 2. new_capacity is a single group.
-  //
-  // All elements are transferred into the first `old_capacity + 1` positions
-  // of the new_ctrl. Elements are rotated by `old_capacity_ / 2 + 1` positions
-  // in order to change an order and keep it non deterministic.
-  // Although rotation itself deterministic, position of the new added element
-  // will be based on `H1` and is not deterministic.
-  //
-  // Examples:
-  // S = kSentinel, E = kEmpty
-  //
-  // old_ctrl = SEEEEEEEE...
-  // new_ctrl = ESEEEEEEE...
-  //
-  // old_ctrl = 0SEEEEEEE...
-  // new_ctrl = E0ESE0EEE...
-  //
-  // old_ctrl = 012S012EEEEEEEEE...
-  // new_ctrl = 2E01EEES2E01EEE...
-  //
-  // old_ctrl = 0123456S0123456EEEEEEEEEEE...
-  // new_ctrl = 456E0123EEEEEES456E0123EEE...
-  void GrowIntoSingleGroupShuffleControlBytes(ctrl_t* new_ctrl,
-                                              size_t new_capacity) const;
-
-  // If the table was SOO, initializes new control bytes. `h2` is the control
-  // byte corresponding to the full slot. Must be called only if
-  // IsGrowingIntoSingleGroupApplicable returned true.
-  // Requires: `had_soo_slot_ || h2 == ctrl_t::kEmpty`.
-  void InitControlBytesAfterSoo(ctrl_t* new_ctrl, ctrl_t h2,
-                                size_t new_capacity);
-
-  // Shuffle trivially transferable slots in the way consistent with
-  // GrowIntoSingleGroupShuffleControlBytes.
-  //
-  // PRECONDITIONs:
-  // 1. old_capacity must be non-zero.
-  // 2. new_ctrl is fully initialized using
-  //    GrowIntoSingleGroupShuffleControlBytes.
-  // 3. new_slots is allocated and *not* poisoned.
-  //
-  // POSTCONDITIONS:
-  // 1. new_slots are transferred from old_slots_ consistent with
-  //    GrowIntoSingleGroupShuffleControlBytes.
-  // 2. Empty new_slots are *not* poisoned.
-  void GrowIntoSingleGroupShuffleTransferableSlots(void* new_slots,
-                                                   size_t slot_size) const;
-
-  // Poison empty slots that were transferred using the deterministic algorithm
-  // described above.
-  // PRECONDITIONs:
-  // 1. new_ctrl is fully initialized using
-  //    GrowIntoSingleGroupShuffleControlBytes.
-  // 2. new_slots is fully initialized consistent with
-  //    GrowIntoSingleGroupShuffleControlBytes.
-  void PoisonSingleGroupEmptySlots(CommonFields& c, size_t slot_size) const {
-    // poison non full items
-    for (size_t i = 0; i < c.capacity(); ++i) {
-      if (!IsFull(c.control()[i])) {
-        SanitizerPoisonMemoryRegion(SlotAddress(c.slot_array(), i, slot_size),
-                                    slot_size);
-      }
-    }
-  }
-
-  HeapOrSoo old_heap_or_soo_;
-  size_t old_capacity_;
-  bool had_infoz_;
-  bool was_soo_;
-  bool had_soo_slot_;
-  // Either null infoz or a pre-sampled forced infoz for SOO tables.
-  HashtablezInfoHandle forced_infoz_;
-};
-
-inline void PrepareInsertCommon(CommonFields& common) {
-  common.increment_size();
-  common.maybe_increment_generation_on_insert();
+// Allocates `n` bytes for a backing array.
+template <size_t AlignOfBackingArray, typename Alloc>
+ABSL_ATTRIBUTE_NOINLINE void* AllocateBackingArray(void* alloc, size_t n) {
+  return Allocate<AlignOfBackingArray>(static_cast<Alloc*>(alloc), n);
 }
 
-// Like prepare_insert, but for the case of inserting into a full SOO table.
-size_t PrepareInsertAfterSoo(size_t hash, size_t slot_size,
-                             CommonFields& common);
+template <size_t AlignOfBackingArray, typename Alloc>
+ABSL_ATTRIBUTE_NOINLINE void DeallocateBackingArray(
+    void* alloc, size_t capacity, ctrl_t* ctrl, size_t slot_size,
+    size_t slot_align, bool had_infoz) {
+  RawHashSetLayout layout(capacity, slot_size, slot_align, had_infoz);
+  void* backing_array = ctrl - layout.control_offset();
+  // Unpoison before returning the memory to the allocator.
+  SanitizerUnpoisonMemoryRegion(backing_array, layout.alloc_size());
+  Deallocate<AlignOfBackingArray>(static_cast<Alloc*>(alloc), backing_array,
+                                  layout.alloc_size());
+}
 
 // PolicyFunctions bundles together some information for a particular
 // raw_hash_set<T, ...> instantiation. This information is passed to
 // type-erased functions that want to do small amounts of type-specific
 // work.
 struct PolicyFunctions {
-  size_t slot_size;
+  uint32_t key_size;
+  uint32_t value_size;
+  uint32_t slot_size;
+  uint16_t slot_align;
+  bool soo_enabled;
+  bool is_hashtablez_eligible;
 
   // Returns the pointer to the hash function stored in the set.
-  const void* (*hash_fn)(const CommonFields& common);
+  void* (*hash_fn)(CommonFields& common);
 
   // Returns the hash of the pointed-to slot.
   size_t (*hash_slot)(const void* hash_fn, void* slot);
 
-  // Transfers the contents of src_slot to dst_slot.
-  void (*transfer)(void* set, void* dst_slot, void* src_slot);
+  // Transfers the contents of `count` slots from src_slot to dst_slot.
+  // We use ability to transfer several slots in single group table growth.
+  void (*transfer_n)(void* set, void* dst_slot, void* src_slot, size_t count);
+
+  // Returns the pointer to the CharAlloc stored in the set.
+  void* (*get_char_alloc)(CommonFields& common);
+
+  // Allocates n bytes for the backing store for common.
+  void* (*alloc)(void* alloc, size_t n);
 
   // Deallocates the backing store from common.
-  void (*dealloc)(CommonFields& common, const PolicyFunctions& policy);
+  void (*dealloc)(void* alloc, size_t capacity, ctrl_t* ctrl, size_t slot_size,
+                  size_t slot_align, bool had_infoz);
 
-  // Resizes set to the new capacity.
-  // Arguments are used as in raw_hash_set::resize_impl.
-  void (*resize)(CommonFields& common, size_t new_capacity,
-                 HashtablezInfoHandle forced_infoz);
+  // Implementation detail of GrowToNextCapacity.
+  // Iterates over all full slots and transfers unprobed elements.
+  // Initializes the new control bytes except mirrored bytes and kSentinel.
+  // Caller must finish the initialization.
+  // All slots corresponding to the full control bytes are transferred.
+  // Probed elements are reported by `encode_probed_element` callback.
+  // encode_probed_element may overwrite old_ctrl buffer till source_offset.
+  // Different encoding is used depending on the capacity of the table.
+  // See ProbedItem*Bytes classes for details.
+  void (*transfer_unprobed_elements_to_next_capacity)(
+      CommonFields& common, const ctrl_t* old_ctrl, void* old_slots,
+      // TODO(b/382423690): Try to use absl::FunctionRef here.
+      void* probed_storage,
+      void (*encode_probed_element)(void* probed_storage, h2_t h2,
+                                    size_t source_offset, size_t h1));
+
+  uint8_t soo_capacity() const {
+    return static_cast<uint8_t>(soo_enabled ? SooCapacity() : 0);
+  }
 };
 
+// Returns the maximum valid size for a table with 1-byte slots.
+// This function is an utility shared by MaxValidSize and IsAboveValidSize.
+// Template parameter is only used to enable testing.
+template <size_t kSizeOfSizeT = sizeof(size_t)>
+constexpr size_t MaxValidSizeFor1ByteSlot() {
+  if constexpr (kSizeOfSizeT == 8) {
+    return CapacityToGrowth(
+        static_cast<size_t>(uint64_t{1} << HashtableSize::kSizeBitCount) - 1);
+  } else {
+    static_assert(kSizeOfSizeT == 4);
+    return CapacityToGrowth((size_t{1} << (kSizeOfSizeT * 8 - 2)) - 1);
+  }
+}
+
+// Returns the maximum valid size for a table with provided slot size.
+// Template parameter is only used to enable testing.
+template <size_t kSizeOfSizeT = sizeof(size_t)>
+constexpr size_t MaxValidSize(size_t slot_size) {
+  if constexpr (kSizeOfSizeT == 8) {
+    // For small slot sizes we are limited by HashtableSize::kSizeBitCount.
+    if (slot_size < size_t{1} << (64 - HashtableSize::kSizeBitCount)) {
+      return MaxValidSizeFor1ByteSlot<kSizeOfSizeT>();
+    }
+    return (size_t{1} << (kSizeOfSizeT * 8 - 2)) / slot_size;
+  } else {
+    return MaxValidSizeFor1ByteSlot<kSizeOfSizeT>() / slot_size;
+  }
+}
+
+// Returns true if size is larger than the maximum valid size.
+// It is an optimization to avoid the division operation in the common case.
+// Template parameter is only used to enable testing.
+template <size_t kSizeOfSizeT = sizeof(size_t)>
+constexpr bool IsAboveValidSize(size_t size, size_t slot_size) {
+  if constexpr (kSizeOfSizeT == 8) {
+    // For small slot sizes we are limited by HashtableSize::kSizeBitCount.
+    if (ABSL_PREDICT_TRUE(slot_size <
+                          (size_t{1} << (64 - HashtableSize::kSizeBitCount)))) {
+      return size > MaxValidSizeFor1ByteSlot<kSizeOfSizeT>();
+    }
+    return size > MaxValidSize<kSizeOfSizeT>(slot_size);
+  } else {
+    return uint64_t{size} * slot_size >
+           MaxValidSizeFor1ByteSlot<kSizeOfSizeT>();
+  }
+}
+
+// Returns the index of the SOO slot when growing from SOO to non-SOO in a
+// single group. See also InitializeSmallControlBytesAfterSoo(). It's important
+// to use index 1 so that when resizing from capacity 1 to 3, we can still have
+// random iteration order between the first two inserted elements.
+// I.e. it allows inserting the second element at either index 0 or 2.
+constexpr size_t SooSlotIndex() { return 1; }
+
+// Maximum capacity for the algorithm for small table after SOO.
+// Note that typical size after SOO is 3, but we allow up to 7.
+// Allowing till 16 would require additional store that can be avoided.
+constexpr size_t MaxSmallAfterSooCapacity() { return 7; }
+
+// Type erased version of raw_hash_set::reserve.
+// Requires: `new_size > policy.soo_capacity`.
+void ReserveTableToFitNewSize(CommonFields& common,
+                              const PolicyFunctions& policy, size_t new_size);
+
+// Resizes empty non-allocated table to the next valid capacity after
+// `bucket_count`. Requires:
+//   1. `c.capacity() == policy.soo_capacity`.
+//   2. `c.empty()`.
+//   3. `new_size > policy.soo_capacity`.
+// The table will be attempted to be sampled.
+void ReserveEmptyNonAllocatedTableToFitBucketCount(
+    CommonFields& common, const PolicyFunctions& policy, size_t bucket_count);
+
+// Type erased version of raw_hash_set::rehash.
+void Rehash(CommonFields& common, const PolicyFunctions& policy, size_t n);
+
+// Type erased version of copy constructor.
+void Copy(CommonFields& common, const PolicyFunctions& policy,
+          const CommonFields& other,
+          absl::FunctionRef<void(void*, const void*)> copy_fn);
+
+// Returns the optimal size for memcpy when transferring SOO slot.
+// Otherwise, returns the optimal size for memcpy SOO slot transfer
+// to SooSlotIndex().
+// At the destination we are allowed to copy upto twice more bytes,
+// because there is at least one more slot after SooSlotIndex().
+// The result must not exceed MaxSooSlotSize().
+// Some of the cases are merged to minimize the number of function
+// instantiations.
+constexpr size_t OptimalMemcpySizeForSooSlotTransfer(
+    size_t slot_size, size_t max_soo_slot_size = MaxSooSlotSize()) {
+  static_assert(MaxSooSlotSize() >= 8, "unexpectedly small SOO slot size");
+  if (slot_size == 1) {
+    return 1;
+  }
+  if (slot_size <= 3) {
+    return 4;
+  }
+  // We are merging 4 and 8 into one case because we expect them to be the
+  // hottest cases. Copying 8 bytes is as fast on common architectures.
+  if (slot_size <= 8) {
+    return 8;
+  }
+  if (max_soo_slot_size <= 16) {
+    return max_soo_slot_size;
+  }
+  if (slot_size <= 16) {
+    return 16;
+  }
+  if (max_soo_slot_size <= 24) {
+    return max_soo_slot_size;
+  }
+  static_assert(MaxSooSlotSize() <= 24, "unexpectedly large SOO slot size");
+  return 24;
+}
+
+// Resizes SOO table to the NextCapacity(SooCapacity()) and prepares insert for
+// the given new_hash. Returns the offset of the new element.
+// `soo_slot_ctrl` is the control byte of the SOO slot.
+// If soo_slot_ctrl is kEmpty
+//   1. The table must be empty.
+//   2. Table will be forced to be sampled.
+// All possible template combinations are defined in cc file to improve
+// compilation time.
+template <size_t SooSlotMemcpySize, bool TransferUsesMemcpy>
+size_t GrowSooTableToNextCapacityAndPrepareInsert(CommonFields& common,
+                                                  const PolicyFunctions& policy,
+                                                  size_t new_hash,
+                                                  ctrl_t soo_slot_ctrl);
+
+// As `ResizeFullSooTableToNextCapacity`, except that we also force the SOO
+// table to be sampled. SOO tables need to switch from SOO to heap in order to
+// store the infoz. No-op if sampling is disabled or not possible.
+void GrowFullSooTableToNextCapacityForceSampling(CommonFields& common,
+                                                 const PolicyFunctions& policy);
+
+// Resizes table with allocated slots and change the table seed.
+// Tables with SOO enabled must have capacity > policy.soo_capacity.
+// No sampling will be performed since table is already allocated.
+void ResizeAllocatedTableWithSeedChange(CommonFields& common,
+                                        const PolicyFunctions& policy,
+                                        size_t new_capacity);
+
 // ClearBackingArray clears the backing array, either modifying it in place,
 // or creating a new one based on the value of "reuse".
 // REQUIRES: c.capacity > 0
 void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,
-                       bool reuse, bool soo_enabled);
+                       void* alloc, bool reuse, bool soo_enabled);
 
 // Type-erased version of raw_hash_set::erase_meta_only.
 void EraseMetaOnly(CommonFields& c, size_t index, size_t slot_size);
 
-// Function to place in PolicyFunctions::dealloc for raw_hash_sets
-// that are using std::allocator. This allows us to share the same
-// function body for raw_hash_set instantiations that have the
-// same slot alignment.
-template <size_t AlignOfSlot>
-ABSL_ATTRIBUTE_NOINLINE void DeallocateStandard(CommonFields& common,
-                                                const PolicyFunctions& policy) {
-  // Unpoison before returning the memory to the allocator.
-  SanitizerUnpoisonMemoryRegion(common.slot_array(),
-                                policy.slot_size * common.capacity());
-
-  std::allocator<char> alloc;
-  common.infoz().Unregister();
-  Deallocate<BackingArrayAlignment(AlignOfSlot)>(
-      &alloc, common.backing_array_start(),
-      common.alloc_size(policy.slot_size, AlignOfSlot));
-}
-
 // For trivially relocatable types we use memcpy directly. This allows us to
 // share the same function body for raw_hash_set instantiations that have the
 // same slot size as long as they are relocatable.
+// Separate function for relocating single slot cause significant binary bloat.
 template <size_t SizeOfSlot>
-ABSL_ATTRIBUTE_NOINLINE void TransferRelocatable(void*, void* dst, void* src) {
-  memcpy(dst, src, SizeOfSlot);
+ABSL_ATTRIBUTE_NOINLINE void TransferNRelocatable(void*, void* dst, void* src,
+                                                  size_t count) {
+  // TODO(b/382423690): Experiment with making specialization for power of 2 and
+  // non power of 2. This would require passing the size of the slot.
+  memcpy(dst, src, SizeOfSlot * count);
 }
 
-// Type erased raw_hash_set::get_hash_ref_fn for the empty hash function case.
-const void* GetHashRefForEmptyHasher(const CommonFields& common);
+// Returns a pointer to `common`. This is used to implement type erased
+// raw_hash_set::get_hash_ref_fn and raw_hash_set::get_alloc_ref_fn for the
+// empty class cases.
+void* GetRefForEmptyClass(CommonFields& common);
 
 // Given the hash of a value not currently in the table and the first empty
 // slot in the probe sequence, finds a viable slot index to insert it at.
@@ -2307,8 +1868,8 @@
 // REQUIRES: Table is not SOO.
 // REQUIRES: At least one non-full slot available.
 // REQUIRES: `target` is a valid empty position to insert.
-size_t PrepareInsertNonSoo(CommonFields& common, size_t hash, FindInfo target,
-                           const PolicyFunctions& policy);
+size_t PrepareInsertNonSoo(CommonFields& common, const PolicyFunctions& policy,
+                           size_t hash, FindInfo target);
 
 // A SwissTable.
 //
@@ -2339,9 +1900,6 @@
  public:
   using init_type = typename PolicyTraits::init_type;
   using key_type = typename PolicyTraits::key_type;
-  // TODO(sbenza): Hide slot_type as it is an implementation detail. Needs user
-  // code fixes!
-  using slot_type = typename PolicyTraits::slot_type;
   using allocator_type = Alloc;
   using size_type = size_t;
   using difference_type = ptrdiff_t;
@@ -2356,6 +1914,7 @@
   using const_pointer = typename absl::allocator_traits<
       allocator_type>::template rebind_traits<value_type>::const_pointer;
 
+ private:
   // Alias used for heterogeneous lookup functions.
   // `key_arg<K>` evaluates to `K` when the functors are transparent and to
   // `key_type` otherwise. It permits template argument deduction on `K` for the
@@ -2363,7 +1922,8 @@
   template <class K>
   using key_arg = typename KeyArgImpl::template type<K, key_type>;
 
- private:
+  using slot_type = typename PolicyTraits::slot_type;
+
   // TODO(b/289225379): we could add extra SOO space inside raw_hash_set
   // after CommonFields to allow inlining larger slot_types (e.g. std::string),
   // but it's a bit complicated if we want to support incomplete mapped_type in
@@ -2376,6 +1936,10 @@
            alignof(slot_type) <= alignof(HeapOrSoo);
   }
 
+  constexpr static size_t DefaultCapacity() {
+    return SooEnabled() ? SooCapacity() : 0;
+  }
+
   // Whether `size` fits in the SOO capacity of this table.
   bool fits_in_soo(size_t size) const {
     return SooEnabled() && size <= SooCapacity();
@@ -2402,23 +1966,14 @@
   static_assert(std::is_lvalue_reference<reference>::value,
                 "Policy::element() must return a reference");
 
-  template <typename T>
-  struct SameAsElementReference
-      : std::is_same<typename std::remove_cv<
-                         typename std::remove_reference<reference>::type>::type,
-                     typename std::remove_cv<
-                         typename std::remove_reference<T>::type>::type> {};
-
   // An enabler for insert(T&&): T must be convertible to init_type or be the
   // same as [cv] value_type [ref].
-  // Note: we separate SameAsElementReference into its own type to avoid using
-  // reference unless we need to. MSVC doesn't seem to like it in some
-  // cases.
   template <class T>
-  using RequiresInsertable = typename std::enable_if<
-      absl::disjunction<std::is_convertible<T, init_type>,
-                        SameAsElementReference<T>>::value,
-      int>::type;
+  using Insertable = absl::disjunction<
+      std::is_same<absl::remove_cvref_t<reference>, absl::remove_cvref_t<T>>,
+      std::is_convertible<T, init_type>>;
+  template <class T>
+  using IsNotBitField = std::is_pointer<T*>;
 
   // RequiresNotInit is a workaround for gcc prior to 7.1.
   // See https://godbolt.org/g/Y4xsUh.
@@ -2429,6 +1984,17 @@
   template <class... Ts>
   using IsDecomposable = IsDecomposable<void, PolicyTraits, Hash, Eq, Ts...>;
 
+  template <class T>
+  using IsDecomposableAndInsertable =
+      IsDecomposable<std::enable_if_t<Insertable<T>::value, T>>;
+
+  // Evaluates to true if an assignment from the given type would require the
+  // source object to remain alive for the life of the element.
+  template <class U>
+  using IsLifetimeBoundAssignmentFrom = std::conditional_t<
+      policy_trait_element_is_owner<Policy>::value, std::false_type,
+      type_traits_internal::IsLifetimeBoundAssignment<init_type, U>>;
+
  public:
   static_assert(std::is_same<pointer, value_type*>::value,
                 "Allocators with custom pointer types are not supported");
@@ -2607,14 +2173,15 @@
       std::is_nothrow_default_constructible<key_equal>::value &&
       std::is_nothrow_default_constructible<allocator_type>::value) {}
 
-  ABSL_ATTRIBUTE_NOINLINE explicit raw_hash_set(
+  explicit raw_hash_set(
       size_t bucket_count, const hasher& hash = hasher(),
       const key_equal& eq = key_equal(),
       const allocator_type& alloc = allocator_type())
       : settings_(CommonFields::CreateDefault<SooEnabled()>(), hash, eq,
                   alloc) {
-    if (bucket_count > (SooEnabled() ? SooCapacity() : 0)) {
-      resize(NormalizeCapacity(bucket_count));
+    if (bucket_count > DefaultCapacity()) {
+      ReserveEmptyNonAllocatedTableToFitBucketCount(
+          common(), GetPolicyFunctions(), bucket_count);
     }
   }
 
@@ -2672,7 +2239,8 @@
   //   absl::flat_hash_set<int> a, b{a};
   //
   // RequiresNotInit<T> is a workaround for gcc prior to 7.1.
-  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
+  template <class T, RequiresNotInit<T> = 0,
+            std::enable_if_t<Insertable<T>::value, int> = 0>
   raw_hash_set(std::initializer_list<T> init, size_t bucket_count = 0,
                const hasher& hash = hasher(), const key_equal& eq = key_equal(),
                const allocator_type& alloc = allocator_type())
@@ -2683,7 +2251,8 @@
                const allocator_type& alloc = allocator_type())
       : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}
 
-  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
+  template <class T, RequiresNotInit<T> = 0,
+            std::enable_if_t<Insertable<T>::value, int> = 0>
   raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
                const hasher& hash, const allocator_type& alloc)
       : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
@@ -2692,7 +2261,8 @@
                const hasher& hash, const allocator_type& alloc)
       : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
 
-  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
+  template <class T, RequiresNotInit<T> = 0,
+            std::enable_if_t<Insertable<T>::value, int> = 0>
   raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
                const allocator_type& alloc)
       : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
@@ -2701,7 +2271,8 @@
                const allocator_type& alloc)
       : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
 
-  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
+  template <class T, RequiresNotInit<T> = 0,
+            std::enable_if_t<Insertable<T>::value, int> = 0>
   raw_hash_set(std::initializer_list<T> init, const allocator_type& alloc)
       : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}
 
@@ -2711,72 +2282,20 @@
 
   raw_hash_set(const raw_hash_set& that)
       : raw_hash_set(that, AllocTraits::select_on_container_copy_construction(
-                               that.alloc_ref())) {}
+                               allocator_type(that.char_alloc_ref()))) {}
 
   raw_hash_set(const raw_hash_set& that, const allocator_type& a)
-      : raw_hash_set(GrowthToLowerboundCapacity(that.size()), that.hash_ref(),
-                     that.eq_ref(), a) {
-    const size_t size = that.size();
-    if (size == 0) {
-      return;
-    }
-    // We don't use `that.is_soo()` here because `that` can have non-SOO
-    // capacity but have a size that fits into SOO capacity.
-    if (fits_in_soo(size)) {
-      assert(size == 1);
-      common().set_full_soo();
-      emplace_at(soo_iterator(), *that.begin());
-      const HashtablezInfoHandle infoz = try_sample_soo();
-      if (infoz.IsSampled()) resize_with_soo_infoz(infoz);
-      return;
-    }
-    assert(!that.is_soo());
-    const size_t cap = capacity();
-    // Note about single group tables:
-    // 1. It is correct to have any order of elements.
-    // 2. Order has to be non deterministic.
-    // 3. We are assigning elements with arbitrary `shift` starting from
-    //    `capacity + shift` position.
-    // 4. `shift` must be coprime with `capacity + 1` in order to be able to use
-    //     modular arithmetic to traverse all positions, instead if cycling
-    //     through a subset of positions. Odd numbers are coprime with any
-    //     `capacity + 1` (2^N).
-    size_t offset = cap;
-    const size_t shift =
-        is_single_group(cap) ? (PerTableSalt(control()) | 1) : 0;
-    IterateOverFullSlots(
-        that.common(), that.slot_array(),
-        [&](const ctrl_t* that_ctrl,
-            slot_type* that_slot) ABSL_ATTRIBUTE_ALWAYS_INLINE {
-          if (shift == 0) {
-            // Big tables case. Position must be searched via probing.
-            // The table is guaranteed to be empty, so we can do faster than
-            // a full `insert`.
-            const size_t hash = PolicyTraits::apply(
-                HashElement{hash_ref()}, PolicyTraits::element(that_slot));
-            FindInfo target = find_first_non_full_outofline(common(), hash);
-            infoz().RecordInsert(hash, target.probe_length);
-            offset = target.offset;
-          } else {
-            // Small tables case. Next position is computed via shift.
-            offset = (offset + shift) & cap;
-          }
-          const h2_t h2 = static_cast<h2_t>(*that_ctrl);
-          assert(  // We rely that hash is not changed for small tables.
-              H2(PolicyTraits::apply(HashElement{hash_ref()},
-                                     PolicyTraits::element(that_slot))) == h2 &&
-              "hash function value changed unexpectedly during the copy");
-          SetCtrl(common(), offset, h2, sizeof(slot_type));
-          emplace_at(iterator_at(offset), PolicyTraits::element(that_slot));
-          common().maybe_increment_generation_on_insert();
-        });
-    if (shift != 0) {
-      // On small table copy we do not record individual inserts.
-      // RecordInsert requires hash, but it is unknown for small tables.
-      infoz().RecordStorageChanged(size, cap);
-    }
-    common().set_size(size);
-    growth_info().OverwriteManyEmptyAsFull(size);
+      : raw_hash_set(0, that.hash_ref(), that.eq_ref(), a) {
+    that.AssertNotDebugCapacity();
+    if (that.empty()) return;
+    Copy(common(), GetPolicyFunctions(), that.common(),
+         [this](void* dst, const void* src) {
+           // TODO(b/413598253): type erase for trivially copyable types via
+           // PolicyTraits.
+           construct(to_slot(dst),
+                     PolicyTraits::element(
+                         static_cast<slot_type*>(const_cast<void*>(src))));
+         });
   }
 
   ABSL_ATTRIBUTE_NOINLINE raw_hash_set(raw_hash_set&& that) noexcept(
@@ -2786,31 +2305,31 @@
       :  // Hash, equality and allocator are copied instead of moved because
          // `that` must be left valid. If Hash is std::function<Key>, moving it
          // would create a nullptr functor that cannot be called.
-         // TODO(b/296061262): move instead of copying hash/eq/alloc.
          // Note: we avoid using exchange for better generated code.
         settings_(PolicyTraits::transfer_uses_memcpy() || !that.is_full_soo()
                       ? std::move(that.common())
                       : CommonFields{full_soo_tag_t{}},
-                  that.hash_ref(), that.eq_ref(), that.alloc_ref()) {
+                  that.hash_ref(), that.eq_ref(), that.char_alloc_ref()) {
     if (!PolicyTraits::transfer_uses_memcpy() && that.is_full_soo()) {
       transfer(soo_slot(), that.soo_slot());
     }
     that.common() = CommonFields::CreateDefault<SooEnabled()>();
-    maybe_increment_generation_or_rehash_on_move();
+    annotate_for_bug_detection_on_move(that);
   }
 
   raw_hash_set(raw_hash_set&& that, const allocator_type& a)
       : settings_(CommonFields::CreateDefault<SooEnabled()>(), that.hash_ref(),
                   that.eq_ref(), a) {
-    if (a == that.alloc_ref()) {
+    if (CharAlloc(a) == that.char_alloc_ref()) {
       swap_common(that);
-      maybe_increment_generation_or_rehash_on_move();
+      annotate_for_bug_detection_on_move(that);
     } else {
       move_elements_allocs_unequal(std::move(that));
     }
   }
 
   raw_hash_set& operator=(const raw_hash_set& that) {
+    that.AssertNotDebugCapacity();
     if (ABSL_PREDICT_FALSE(this == &that)) return *this;
     constexpr bool propagate_alloc =
         AllocTraits::propagate_on_container_copy_assignment::value;
@@ -2818,7 +2337,9 @@
     // is an exact match for that.size(). If this->capacity() is too big, then
     // it would make iteration very slow to reuse the allocation. Maybe we can
     // do the same heuristic as clear() and reuse if it's small enough.
-    raw_hash_set tmp(that, propagate_alloc ? that.alloc_ref() : alloc_ref());
+    allocator_type alloc(propagate_alloc ? that.char_alloc_ref()
+                                         : char_alloc_ref());
+    raw_hash_set tmp(that, alloc);
     // NOLINTNEXTLINE: not returning *this for performance.
     return assign_impl<propagate_alloc>(std::move(tmp));
   }
@@ -2835,18 +2356,24 @@
         typename AllocTraits::propagate_on_container_move_assignment());
   }
 
-  ~raw_hash_set() { destructor_impl(); }
+  ~raw_hash_set() {
+    destructor_impl();
+    if constexpr (SwisstableAssertAccessToDestroyedTable()) {
+      common().set_capacity(InvalidCapacity::kDestroyed);
+    }
+  }
 
   iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
     if (ABSL_PREDICT_FALSE(empty())) return end();
-    if (is_soo()) return soo_iterator();
+    if (capacity() == 1) return single_iterator();
     iterator it = {control(), common().slots_union(),
                    common().generation_ptr()};
     it.skip_empty_or_deleted();
-    assert(IsFull(*it.control()));
+    ABSL_SWISSTABLE_ASSERT(IsFull(*it.control()));
     return it;
   }
   iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    AssertNotDebugCapacity();
     return iterator(common().generation_ptr());
   }
 
@@ -2854,7 +2381,7 @@
     return const_cast<raw_hash_set*>(this)->begin();
   }
   const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return iterator(common().generation_ptr());
+    return const_cast<raw_hash_set*>(this)->end();
   }
   const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return begin();
@@ -2862,18 +2389,26 @@
   const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }
 
   bool empty() const { return !size(); }
-  size_t size() const { return common().size(); }
+  size_t size() const {
+    AssertNotDebugCapacity();
+    return common().size();
+  }
   size_t capacity() const {
     const size_t cap = common().capacity();
-    // Compiler complains when using functions in assume so use local variables.
-    ABSL_ATTRIBUTE_UNUSED static constexpr bool kEnabled = SooEnabled();
-    ABSL_ATTRIBUTE_UNUSED static constexpr size_t kCapacity = SooCapacity();
-    ABSL_ASSUME(!kEnabled || cap >= kCapacity);
+    // Compiler complains when using functions in ASSUME so use local variable.
+    [[maybe_unused]] static constexpr size_t kDefaultCapacity =
+        DefaultCapacity();
+    ABSL_ASSUME(cap >= kDefaultCapacity);
     return cap;
   }
-  size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
+  size_t max_size() const { return MaxValidSize(sizeof(slot_type)); }
 
   ABSL_ATTRIBUTE_REINITIALIZES void clear() {
+    if (SwisstableGenerationsEnabled() &&
+        capacity() >= InvalidCapacity::kMovedFrom) {
+      common().set_capacity(DefaultCapacity());
+    }
+    AssertNotDebugCapacity();
     // Iterating over this container is O(bucket_count()). When bucket_count()
     // is much greater than size(), iteration becomes prohibitively expensive.
     // For clear() it is more important to reuse the allocated array when the
@@ -2889,8 +2424,7 @@
       common().set_empty_soo();
     } else {
       destroy_slots();
-      ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/cap < 128,
-                        SooEnabled());
+      clear_backing_array(/*reuse=*/cap < 128);
     }
     common().set_reserved_growth(0);
     common().set_reservation_size(0);
@@ -2901,15 +2435,26 @@
   //
   //   flat_hash_map<std::string, int> m;
   //   m.insert(std::make_pair("abc", 42));
-  // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
-  // bug.
-  template <class T, RequiresInsertable<T> = 0, class T2 = T,
-            typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
-            T* = nullptr>
+  template <class T,
+            int = std::enable_if_t<IsDecomposableAndInsertable<T>::value &&
+                                       IsNotBitField<T>::value &&
+                                       !IsLifetimeBoundAssignmentFrom<T>::value,
+                                   int>()>
   std::pair<iterator, bool> insert(T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return emplace(std::forward<T>(value));
   }
 
+  template <class T, int&...,
+            std::enable_if_t<IsDecomposableAndInsertable<T>::value &&
+                                 IsNotBitField<T>::value &&
+                                 IsLifetimeBoundAssignmentFrom<T>::value,
+                             int> = 0>
+  std::pair<iterator, bool> insert(
+      T&& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))
+      ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template insert<T, 0>(std::forward<T>(value));
+  }
+
   // This overload kicks in when the argument is a bitfield or an lvalue of
   // insertable and decomposable type.
   //
@@ -2921,13 +2466,23 @@
   //   const char* p = "hello";
   //   s.insert(p);
   //
-  template <
-      class T, RequiresInsertable<const T&> = 0,
-      typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
+  template <class T, int = std::enable_if_t<
+                         IsDecomposableAndInsertable<const T&>::value &&
+                             !IsLifetimeBoundAssignmentFrom<const T&>::value,
+                         int>()>
   std::pair<iterator, bool> insert(const T& value)
       ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return emplace(value);
   }
+  template <class T, int&...,
+            std::enable_if_t<IsDecomposableAndInsertable<const T&>::value &&
+                                 IsLifetimeBoundAssignmentFrom<const T&>::value,
+                             int> = 0>
+  std::pair<iterator, bool> insert(
+      const T& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))
+      ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template insert<T, 0>(value);
+  }
 
   // This overload kicks in when the argument is an rvalue of init_type. Its
   // purpose is to handle brace-init-list arguments.
@@ -2935,22 +2490,44 @@
   //   flat_hash_map<std::string, int> s;
   //   s.insert({"abc", 42});
   std::pair<iterator, bool> insert(init_type&& value)
-      ABSL_ATTRIBUTE_LIFETIME_BOUND {
+      ABSL_ATTRIBUTE_LIFETIME_BOUND
+#if __cplusplus >= 202002L
+    requires(!IsLifetimeBoundAssignmentFrom<init_type>::value)
+#endif
+  {
     return emplace(std::move(value));
   }
+#if __cplusplus >= 202002L
+  std::pair<iterator, bool> insert(
+      init_type&& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))
+      ABSL_ATTRIBUTE_LIFETIME_BOUND
+    requires(IsLifetimeBoundAssignmentFrom<init_type>::value)
+  {
+    return emplace(std::move(value));
+  }
+#endif
 
-  // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
-  // bug.
-  template <class T, RequiresInsertable<T> = 0, class T2 = T,
-            typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
-            T* = nullptr>
+  template <class T,
+            int = std::enable_if_t<IsDecomposableAndInsertable<T>::value &&
+                                       IsNotBitField<T>::value &&
+                                       !IsLifetimeBoundAssignmentFrom<T>::value,
+                                   int>()>
   iterator insert(const_iterator, T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return insert(std::forward<T>(value)).first;
   }
+  template <class T, int&...,
+            std::enable_if_t<IsDecomposableAndInsertable<T>::value &&
+                                 IsNotBitField<T>::value &&
+                                 IsLifetimeBoundAssignmentFrom<T>::value,
+                             int> = 0>
+  iterator insert(const_iterator hint,
+                  T&& value ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))
+      ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return this->template insert<T, 0>(hint, std::forward<T>(value));
+  }
 
-  template <
-      class T, RequiresInsertable<const T&> = 0,
-      typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
+  template <class T, std::enable_if_t<
+                         IsDecomposableAndInsertable<const T&>::value, int> = 0>
   iterator insert(const_iterator,
                   const T& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return insert(value).first;
@@ -2966,7 +2543,8 @@
     for (; first != last; ++first) emplace(*first);
   }
 
-  template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0>
+  template <class T, RequiresNotInit<T> = 0,
+            std::enable_if_t<Insertable<const T&>::value, int> = 0>
   void insert(std::initializer_list<T> ilist) {
     insert(ilist.begin(), ilist.end());
   }
@@ -3005,8 +2583,8 @@
   //   flat_hash_map<std::string, std::string> m = {{"abc", "def"}};
   //   // Creates no std::string copies and makes no heap allocations.
   //   m.emplace("abc", "xyz");
-  template <class... Args, typename std::enable_if<
-                               IsDecomposable<Args...>::value, int>::type = 0>
+  template <class... Args,
+            std::enable_if_t<IsDecomposable<Args...>::value, int> = 0>
   std::pair<iterator, bool> emplace(Args&&... args)
       ABSL_ATTRIBUTE_LIFETIME_BOUND {
     return PolicyTraits::apply(EmplaceDecomposable{*this},
@@ -3016,8 +2594,8 @@
   // This overload kicks in if we cannot deduce the key from args. It constructs
   // value_type unconditionally and then either moves it into the table or
   // destroys.
-  template <class... Args, typename std::enable_if<
-                               !IsDecomposable<Args...>::value, int>::type = 0>
+  template <class... Args,
+            std::enable_if_t<!IsDecomposable<Args...>::value, int> = 0>
   std::pair<iterator, bool> emplace(Args&&... args)
       ABSL_ATTRIBUTE_LIFETIME_BOUND {
     alignas(slot_type) unsigned char raw[sizeof(slot_type)];
@@ -3068,7 +2646,7 @@
    public:
     template <class... Args>
     void operator()(Args&&... args) const {
-      assert(*slot_);
+      ABSL_SWISSTABLE_ASSERT(*slot_);
       PolicyTraits::construct(alloc_, *slot_, std::forward<Args>(args)...);
       *slot_ = nullptr;
     }
@@ -3086,8 +2664,9 @@
     auto res = find_or_prepare_insert(key);
     if (res.second) {
       slot_type* slot = res.first.slot();
-      std::forward<F>(f)(constructor(&alloc_ref(), &slot));
-      assert(!slot);
+      allocator_type alloc(char_alloc_ref());
+      std::forward<F>(f)(constructor(&alloc, &slot));
+      ABSL_SWISSTABLE_ASSERT(!slot);
     }
     return res.first;
   }
@@ -3109,24 +2688,16 @@
     return 1;
   }
 
-  // Erases the element pointed to by `it`.  Unlike `std::unordered_set::erase`,
-  // this method returns void to reduce algorithmic complexity to O(1).  The
-  // iterator is invalidated, so any increment should be done before calling
-  // erase.  In order to erase while iterating across a map, use the following
-  // idiom (which also works for some standard containers):
-  //
-  // for (auto it = m.begin(), end = m.end(); it != end;) {
-  //   // `erase()` will invalidate `it`, so advance `it` first.
-  //   auto copy_it = it++;
-  //   if (<pred>) {
-  //     m.erase(copy_it);
-  //   }
-  // }
+  // Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`,
+  // this method returns void to reduce algorithmic complexity to O(1). The
+  // iterator is invalidated so any increment should be done before calling
+  // erase (e.g. `erase(it++)`).
   void erase(const_iterator cit) { erase(cit.inner_); }
 
   // This overload is necessary because otherwise erase<K>(const K&) would be
   // a better match if non-const iterator is passed as an argument.
   void erase(iterator it) {
+    AssertNotDebugCapacity();
     AssertIsFull(it.control(), it.generation(), it.generation_ptr(), "erase()");
     destroy(it.slot());
     if (is_soo()) {
@@ -3138,7 +2709,8 @@
 
   iterator erase(const_iterator first,
                  const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    // We check for empty first because ClearBackingArray requires that
+    AssertNotDebugCapacity();
+    // We check for empty first because clear_backing_array requires that
     // capacity() > 0 as a precondition.
     if (empty()) return end();
     if (first == last) return last.inner_;
@@ -3149,11 +2721,10 @@
     }
     if (first == begin() && last == end()) {
       // TODO(ezb): we access control bytes in destroy_slots so it could make
-      // sense to combine destroy_slots and ClearBackingArray to avoid cache
+      // sense to combine destroy_slots and clear_backing_array to avoid cache
       // misses when the table is large. Note that we also do this in clear().
       destroy_slots();
-      ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/true,
-                        SooEnabled());
+      clear_backing_array(/*reuse=*/true);
       common().set_reserved_growth(common().reservation_size());
       return end();
     }
@@ -3167,6 +2738,8 @@
   // If the element already exists in `this`, it is left unmodified in `src`.
   template <typename H, typename E>
   void merge(raw_hash_set<Policy, H, E, Alloc>& src) {  // NOLINT
+    AssertNotDebugCapacity();
+    src.AssertNotDebugCapacity();
     assert(this != &src);
     // Returns whether insertion took place.
     const auto insert_slot = [this](slot_type* src_slot) {
@@ -3193,9 +2766,11 @@
   }
 
   node_type extract(const_iterator position) {
+    AssertNotDebugCapacity();
     AssertIsFull(position.control(), position.inner_.generation(),
                  position.inner_.generation_ptr(), "extract()");
-    auto node = CommonAccess::Transfer<node_type>(alloc_ref(), position.slot());
+    allocator_type alloc(char_alloc_ref());
+    auto node = CommonAccess::Transfer<node_type>(alloc, position.slot());
     if (is_soo()) {
       common().set_empty_soo();
     } else {
@@ -3204,9 +2779,8 @@
     return node;
   }
 
-  template <
-      class K = key_type,
-      typename std::enable_if<!std::is_same<K, iterator>::value, int>::type = 0>
+  template <class K = key_type,
+            std::enable_if_t<!std::is_same<K, iterator>::value, int> = 0>
   node_type extract(const key_arg<K>& key) {
     auto it = find(key);
     return it == end() ? node_type() : extract(const_iterator{it});
@@ -3216,71 +2790,22 @@
       IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
       IsNoThrowSwappable<allocator_type>(
           typename AllocTraits::propagate_on_container_swap{})) {
+    AssertNotDebugCapacity();
+    that.AssertNotDebugCapacity();
     using std::swap;
     swap_common(that);
     swap(hash_ref(), that.hash_ref());
     swap(eq_ref(), that.eq_ref());
-    SwapAlloc(alloc_ref(), that.alloc_ref(),
+    SwapAlloc(char_alloc_ref(), that.char_alloc_ref(),
               typename AllocTraits::propagate_on_container_swap{});
   }
 
-  void rehash(size_t n) {
-    const size_t cap = capacity();
-    if (n == 0) {
-      if (cap == 0 || is_soo()) return;
-      if (empty()) {
-        ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/false,
-                          SooEnabled());
-        return;
-      }
-      if (fits_in_soo(size())) {
-        // When the table is already sampled, we keep it sampled.
-        if (infoz().IsSampled()) {
-          const size_t kInitialSampledCapacity = NextCapacity(SooCapacity());
-          if (capacity() > kInitialSampledCapacity) {
-            resize(kInitialSampledCapacity);
-          }
-          // This asserts that we didn't lose sampling coverage in `resize`.
-          assert(infoz().IsSampled());
-          return;
-        }
-        alignas(slot_type) unsigned char slot_space[sizeof(slot_type)];
-        slot_type* tmp_slot = to_slot(slot_space);
-        transfer(tmp_slot, begin().slot());
-        ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/false,
-                          SooEnabled());
-        transfer(soo_slot(), tmp_slot);
-        common().set_full_soo();
-        return;
-      }
-    }
-
-    // bitor is a faster way of doing `max` here. We will round up to the next
-    // power-of-2-minus-1, so bitor is good enough.
-    auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
-    // n == 0 unconditionally rehashes as per the standard.
-    if (n == 0 || m > cap) {
-      resize(m);
-
-      // This is after resize, to ensure that we have completed the allocation
-      // and have potentially sampled the hashtable.
-      infoz().RecordReservation(n);
-    }
-  }
+  void rehash(size_t n) { Rehash(common(), GetPolicyFunctions(), n); }
 
   void reserve(size_t n) {
-    const size_t max_size_before_growth =
-        is_soo() ? SooCapacity() : size() + growth_left();
-    if (n > max_size_before_growth) {
-      size_t m = GrowthToLowerboundCapacity(n);
-      resize(NormalizeCapacity(m));
-
-      // This is after resize, to ensure that we have completed the allocation
-      // and have potentially sampled the hashtable.
-      infoz().RecordReservation(n);
+    if (ABSL_PREDICT_TRUE(n > DefaultCapacity())) {
+      ReserveTableToFitNewSize(common(), GetPolicyFunctions(), n);
     }
-    common().reset_reserved_growth(n);
-    common().set_reservation_size(n);
   }
 
   // Extension API: support for heterogeneous keys.
@@ -3304,43 +2829,38 @@
   // specific benchmarks indicating its importance.
   template <class K = key_type>
   void prefetch(const key_arg<K>& key) const {
-    if (SooEnabled() ? is_soo() : capacity() == 0) return;
+    if (capacity() == DefaultCapacity()) return;
     (void)key;
     // Avoid probing if we won't be able to prefetch the addresses received.
 #ifdef ABSL_HAVE_PREFETCH
     prefetch_heap_block();
-    auto seq = probe(common(), hash_ref()(key));
+    auto seq = probe(common(), hash_of(key));
     PrefetchToLocalCache(control() + seq.offset());
     PrefetchToLocalCache(slot_array() + seq.offset());
 #endif  // ABSL_HAVE_PREFETCH
   }
 
-  // The API of find() has two extensions.
-  //
-  // 1. The hash can be passed by the user. It must be equal to the hash of the
-  // key.
-  //
-  // 2. The type of the key argument doesn't have to be key_type. This is so
-  // called heterogeneous key support.
   template <class K = key_type>
+  ABSL_DEPRECATE_AND_INLINE()
   iterator find(const key_arg<K>& key,
-                size_t hash) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    AssertHashEqConsistent(key);
-    if (is_soo()) return find_soo(key);
-    return find_non_soo(key, hash);
+                size_t) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return find(key);
   }
+  // The API of find() has one extension: the type of the key argument doesn't
+  // have to be key_type. This is so called heterogeneous key support.
   template <class K = key_type>
   iterator find(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    AssertHashEqConsistent(key);
-    if (is_soo()) return find_soo(key);
+    AssertOnFind(key);
+    if (capacity() <= 1) return find_small(key);
     prefetch_heap_block();
-    return find_non_soo(key, hash_ref()(key));
+    return find_large(key, hash_of(key));
   }
 
   template <class K = key_type>
+  ABSL_DEPRECATE_AND_INLINE()
   const_iterator find(const key_arg<K>& key,
-                      size_t hash) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return const_cast<raw_hash_set*>(this)->find(key, hash);
+                      size_t) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return find(key);
   }
   template <class K = key_type>
   const_iterator find(const key_arg<K>& key) const
@@ -3383,7 +2903,9 @@
 
   hasher hash_function() const { return hash_ref(); }
   key_equal key_eq() const { return eq_ref(); }
-  allocator_type get_allocator() const { return alloc_ref(); }
+  allocator_type get_allocator() const {
+    return allocator_type(char_alloc_ref());
+  }
 
   friend bool operator==(const raw_hash_set& a, const raw_hash_set& b) {
     if (a.size() != b.size()) return false;
@@ -3392,7 +2914,16 @@
     if (outer->capacity() > inner->capacity()) std::swap(outer, inner);
     for (const value_type& elem : *outer) {
       auto it = PolicyTraits::apply(FindElement{*inner}, elem);
-      if (it == inner->end() || !(*it == elem)) return false;
+      if (it == inner->end()) return false;
+      // Note: we used key_equal to check for key equality in FindElement, but
+      // we may need to do an additional comparison using
+      // value_type::operator==. E.g. the keys could be equal and the
+      // mapped_types could be unequal in a map or even in a set, key_equal
+      // could ignore some fields that aren't ignored by operator==.
+      static constexpr bool kKeyEqIsValueEq =
+          std::is_same<key_type, value_type>::value &&
+          std::is_same<key_equal, hash_default_eq<key_type>>::value;
+      if (!kKeyEqIsValueEq && !(*it == elem)) return false;
     }
     return true;
   }
@@ -3406,7 +2937,7 @@
                                  H>::type
   AbslHashValue(H h, const raw_hash_set& s) {
     return H::combine(H::combine_unordered(std::move(h), s.begin(), s.end()),
-                      s.size());
+                      hash_internal::WeaklyMixedInteger{s.size()});
   }
 
   friend void swap(raw_hash_set& a,
@@ -3441,7 +2972,7 @@
   struct EqualElement {
     template <class K2, class... Args>
     bool operator()(const K2& lhs, Args&&...) const {
-      return eq(lhs, rhs);
+      ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(eq(lhs, rhs));
     }
     const K1& rhs;
     const key_equal& eq;
@@ -3476,37 +3007,51 @@
     slot_type&& slot;
   };
 
-  // TODO(b/303305702): re-enable reentrant validation.
   template <typename... Args>
   inline void construct(slot_type* slot, Args&&... args) {
-    PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
+    common().RunWithReentrancyGuard([&] {
+      allocator_type alloc(char_alloc_ref());
+      PolicyTraits::construct(&alloc, slot, std::forward<Args>(args)...);
+    });
   }
   inline void destroy(slot_type* slot) {
-    PolicyTraits::destroy(&alloc_ref(), slot);
+    common().RunWithReentrancyGuard([&] {
+      allocator_type alloc(char_alloc_ref());
+      PolicyTraits::destroy(&alloc, slot);
+    });
   }
   inline void transfer(slot_type* to, slot_type* from) {
-    PolicyTraits::transfer(&alloc_ref(), to, from);
+    common().RunWithReentrancyGuard([&] {
+      allocator_type alloc(char_alloc_ref());
+      PolicyTraits::transfer(&alloc, to, from);
+    });
   }
 
   // TODO(b/289225379): consider having a helper class that has the impls for
   // SOO functionality.
   template <class K = key_type>
-  iterator find_soo(const key_arg<K>& key) {
-    assert(is_soo());
-    return empty() || !PolicyTraits::apply(EqualElement<K>{key, eq_ref()},
-                                           PolicyTraits::element(soo_slot()))
+  iterator find_small(const key_arg<K>& key) {
+    ABSL_SWISSTABLE_ASSERT(capacity() <= 1);
+    return empty() || !PolicyTraits::apply(
+                          EqualElement<K>{key, eq_ref()},
+                          PolicyTraits::element(single_slot()))
                ? end()
-               : soo_iterator();
+               : single_iterator();
   }
 
   template <class K = key_type>
-  iterator find_non_soo(const key_arg<K>& key, size_t hash) {
-    assert(!is_soo());
+  iterator find_large(const key_arg<K>& key, size_t hash) {
+    ABSL_SWISSTABLE_ASSERT(capacity() > 1);
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     auto seq = probe(common(), hash);
+    const h2_t h2 = H2(hash);
     const ctrl_t* ctrl = control();
     while (true) {
+#ifndef ABSL_HAVE_MEMORY_SANITIZER
+      absl::PrefetchToLocalCache(slot_array() + seq.offset());
+#endif
       Group g{ctrl + seq.offset()};
-      for (uint32_t i : g.Match(H2(hash))) {
+      for (uint32_t i : g.Match(h2)) {
         if (ABSL_PREDICT_TRUE(PolicyTraits::apply(
                 EqualElement<K>{key, eq_ref()},
                 PolicyTraits::element(slot_array() + seq.offset(i)))))
@@ -3514,40 +3059,57 @@
       }
       if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return end();
       seq.next();
-      assert(seq.index() <= capacity() && "full table!");
+      ABSL_SWISSTABLE_ASSERT(seq.index() <= capacity() && "full table!");
     }
   }
 
-  // Conditionally samples hashtablez for SOO tables. This should be called on
-  // insertion into an empty SOO table and in copy construction when the size
-  // can fit in SOO capacity.
-  inline HashtablezInfoHandle try_sample_soo() {
-    assert(is_soo());
-    if (!ShouldSampleHashtablezInfo<CharAlloc>()) return HashtablezInfoHandle{};
-    return Sample(sizeof(slot_type), sizeof(key_type), sizeof(value_type),
-                  SooCapacity());
+  // Returns true if the table needs to be sampled.
+  // This should be called on insertion into an empty SOO table and in copy
+  // construction when the size can fit in SOO capacity.
+  bool should_sample_soo() const {
+    ABSL_SWISSTABLE_ASSERT(is_soo());
+    if (!ShouldSampleHashtablezInfoForAlloc<CharAlloc>()) return false;
+    return ABSL_PREDICT_FALSE(ShouldSampleNextTable());
   }
 
-  inline void destroy_slots() {
-    assert(!is_soo());
+  void clear_backing_array(bool reuse) {
+    ABSL_SWISSTABLE_ASSERT(capacity() > DefaultCapacity());
+    ClearBackingArray(common(), GetPolicyFunctions(), &char_alloc_ref(), reuse,
+                      SooEnabled());
+  }
+
+  void destroy_slots() {
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     if (PolicyTraits::template destroy_is_trivial<Alloc>()) return;
-    IterateOverFullSlots(
-        common(), slot_array(),
-        [&](const ctrl_t*, slot_type* slot)
-            ABSL_ATTRIBUTE_ALWAYS_INLINE { this->destroy(slot); });
+    auto destroy_slot = [&](const ctrl_t*, void* slot) {
+      this->destroy(static_cast<slot_type*>(slot));
+    };
+    if constexpr (SwisstableAssertAccessToDestroyedTable()) {
+      CommonFields common_copy(non_soo_tag_t{}, this->common());
+      common().set_capacity(InvalidCapacity::kDestroyed);
+      IterateOverFullSlots(common_copy, sizeof(slot_type), destroy_slot);
+      common().set_capacity(common_copy.capacity());
+    } else {
+      IterateOverFullSlots(common(), sizeof(slot_type), destroy_slot);
+    }
   }
 
-  inline void dealloc() {
-    assert(capacity() != 0);
+  void dealloc() {
+    ABSL_SWISSTABLE_ASSERT(capacity() > DefaultCapacity());
     // Unpoison before returning the memory to the allocator.
     SanitizerUnpoisonMemoryRegion(slot_array(), sizeof(slot_type) * capacity());
     infoz().Unregister();
-    Deallocate<BackingArrayAlignment(alignof(slot_type))>(
-        &alloc_ref(), common().backing_array_start(),
-        common().alloc_size(sizeof(slot_type), alignof(slot_type)));
+    DeallocateBackingArray<BackingArrayAlignment(alignof(slot_type)),
+                           CharAlloc>(&char_alloc_ref(), capacity(), control(),
+                                      sizeof(slot_type), alignof(slot_type),
+                                      common().has_infoz());
   }
 
-  inline void destructor_impl() {
+  void destructor_impl() {
+    if (SwisstableGenerationsEnabled() &&
+        capacity() >= InvalidCapacity::kMovedFrom) {
+      return;
+    }
     if (capacity() == 0) return;
     if (is_soo()) {
       if (!empty()) {
@@ -3564,141 +3126,37 @@
   // This merely updates the pertinent control byte. This can be used in
   // conjunction with Policy::transfer to move the object to another place.
   void erase_meta_only(const_iterator it) {
-    assert(!is_soo());
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     EraseMetaOnly(common(), static_cast<size_t>(it.control() - control()),
                   sizeof(slot_type));
   }
 
+  template <class K>
+  size_t hash_of(const K& key) const {
+    return hash_ref()(key);
+  }
   size_t hash_of(slot_type* slot) const {
     return PolicyTraits::apply(HashElement{hash_ref()},
                                PolicyTraits::element(slot));
   }
 
-  // Resizes table to the new capacity and move all elements to the new
-  // positions accordingly.
-  //
-  // Note that for better performance instead of
-  // find_first_non_full(common(), hash),
-  // HashSetResizeHelper::FindFirstNonFullAfterResize(
-  //    common(), old_capacity, hash)
-  // can be called right after `resize`.
-  void resize(size_t new_capacity) {
-    raw_hash_set::resize_impl(common(), new_capacity, HashtablezInfoHandle{});
-  }
-
-  // As above, except that we also accept a pre-sampled, forced infoz for
-  // SOO tables, since they need to switch from SOO to heap in order to
-  // store the infoz.
-  void resize_with_soo_infoz(HashtablezInfoHandle forced_infoz) {
-    assert(forced_infoz.IsSampled());
-    raw_hash_set::resize_impl(common(), NextCapacity(SooCapacity()),
-                              forced_infoz);
-  }
-
-  // Resizes set to the new capacity.
-  // It is a static function in order to use its pointer in GetPolicyFunctions.
-  ABSL_ATTRIBUTE_NOINLINE static void resize_impl(
-      CommonFields& common, size_t new_capacity,
-      HashtablezInfoHandle forced_infoz) {
-    raw_hash_set* set = reinterpret_cast<raw_hash_set*>(&common);
-    assert(IsValidCapacity(new_capacity));
-    assert(!set->fits_in_soo(new_capacity));
-    const bool was_soo = set->is_soo();
-    const bool had_soo_slot = was_soo && !set->empty();
-    const ctrl_t soo_slot_h2 =
-        had_soo_slot ? static_cast<ctrl_t>(H2(set->hash_of(set->soo_slot())))
-                     : ctrl_t::kEmpty;
-    HashSetResizeHelper resize_helper(common, was_soo, had_soo_slot,
-                                      forced_infoz);
-    // Initialize HashSetResizeHelper::old_heap_or_soo_. We can't do this in
-    // HashSetResizeHelper constructor because it can't transfer slots when
-    // transfer_uses_memcpy is false.
-    // TODO(b/289225379): try to handle more of the SOO cases inside
-    // InitializeSlots. See comment on cl/555990034 snapshot #63.
-    if (PolicyTraits::transfer_uses_memcpy() || !had_soo_slot) {
-      resize_helper.old_heap_or_soo() = common.heap_or_soo();
-    } else {
-      set->transfer(set->to_slot(resize_helper.old_soo_data()),
-                    set->soo_slot());
-    }
-    common.set_capacity(new_capacity);
-    // Note that `InitializeSlots` does different number initialization steps
-    // depending on the values of `transfer_uses_memcpy` and capacities.
-    // Refer to the comment in `InitializeSlots` for more details.
-    const bool grow_single_group =
-        resize_helper.InitializeSlots<CharAlloc, sizeof(slot_type),
-                                      PolicyTraits::transfer_uses_memcpy(),
-                                      SooEnabled(), alignof(slot_type)>(
-            common, CharAlloc(set->alloc_ref()), soo_slot_h2, sizeof(key_type),
-            sizeof(value_type));
-
-    // In the SooEnabled() case, capacity is never 0 so we don't check.
-    if (!SooEnabled() && resize_helper.old_capacity() == 0) {
-      // InitializeSlots did all the work including infoz().RecordRehash().
-      return;
-    }
-    assert(resize_helper.old_capacity() > 0);
-    // Nothing more to do in this case.
-    if (was_soo && !had_soo_slot) return;
-
-    slot_type* new_slots = set->slot_array();
-    if (grow_single_group) {
-      if (PolicyTraits::transfer_uses_memcpy()) {
-        // InitializeSlots did all the work.
-        return;
-      }
-      if (was_soo) {
-        set->transfer(new_slots + resize_helper.SooSlotIndex(),
-                      to_slot(resize_helper.old_soo_data()));
-        return;
-      } else {
-        // We want GrowSizeIntoSingleGroup to be called here in order to make
-        // InitializeSlots not depend on PolicyTraits.
-        resize_helper.GrowSizeIntoSingleGroup<PolicyTraits>(common,
-                                                            set->alloc_ref());
-      }
-    } else {
-      // InitializeSlots prepares control bytes to correspond to empty table.
-      const auto insert_slot = [&](slot_type* slot) {
-        size_t hash = PolicyTraits::apply(HashElement{set->hash_ref()},
-                                          PolicyTraits::element(slot));
-        auto target = find_first_non_full(common, hash);
-        SetCtrl(common, target.offset, H2(hash), sizeof(slot_type));
-        set->transfer(new_slots + target.offset, slot);
-        return target.probe_length;
-      };
-      if (was_soo) {
-        insert_slot(to_slot(resize_helper.old_soo_data()));
-        return;
-      } else {
-        auto* old_slots = static_cast<slot_type*>(resize_helper.old_slots());
-        size_t total_probe_length = 0;
-        for (size_t i = 0; i != resize_helper.old_capacity(); ++i) {
-          if (IsFull(resize_helper.old_ctrl()[i])) {
-            total_probe_length += insert_slot(old_slots + i);
-          }
-        }
-        common.infoz().RecordRehash(total_probe_length);
-      }
-    }
-    resize_helper.DeallocateOld<alignof(slot_type)>(CharAlloc(set->alloc_ref()),
-                                                    sizeof(slot_type));
-  }
-
   // Casting directly from e.g. char* to slot_type* can cause compilation errors
   // on objective-C. This function converts to void* first, avoiding the issue.
   static slot_type* to_slot(void* buf) { return static_cast<slot_type*>(buf); }
 
   // Requires that lhs does not have a full SOO slot.
-  static void move_common(bool that_is_full_soo, allocator_type& rhs_alloc,
+  static void move_common(bool rhs_is_full_soo, CharAlloc& rhs_alloc,
                           CommonFields& lhs, CommonFields&& rhs) {
-    if (PolicyTraits::transfer_uses_memcpy() || !that_is_full_soo) {
+    if (PolicyTraits::transfer_uses_memcpy() || !rhs_is_full_soo) {
       lhs = std::move(rhs);
     } else {
       lhs.move_non_heap_or_soo_fields(rhs);
-      // TODO(b/303305702): add reentrancy guard.
-      PolicyTraits::transfer(&rhs_alloc, to_slot(lhs.soo_data()),
-                             to_slot(rhs.soo_data()));
+      rhs.RunWithReentrancyGuard([&] {
+        lhs.RunWithReentrancyGuard([&] {
+          PolicyTraits::transfer(&rhs_alloc, to_slot(lhs.soo_data()),
+                                 to_slot(rhs.soo_data()));
+        });
+      });
     }
   }
 
@@ -3710,21 +3168,33 @@
       swap(common(), that.common());
       return;
     }
-    CommonFields tmp = CommonFields::CreateDefault<SooEnabled()>();
+    CommonFields tmp = CommonFields(uninitialized_tag_t{});
     const bool that_is_full_soo = that.is_full_soo();
-    move_common(that_is_full_soo, that.alloc_ref(), tmp,
+    move_common(that_is_full_soo, that.char_alloc_ref(), tmp,
                 std::move(that.common()));
-    move_common(is_full_soo(), alloc_ref(), that.common(), std::move(common()));
-    move_common(that_is_full_soo, that.alloc_ref(), common(), std::move(tmp));
+    move_common(is_full_soo(), char_alloc_ref(), that.common(),
+                std::move(common()));
+    move_common(that_is_full_soo, that.char_alloc_ref(), common(),
+                std::move(tmp));
   }
 
-  void maybe_increment_generation_or_rehash_on_move() {
-    if (!SwisstableGenerationsEnabled() || capacity() == 0 || is_soo()) {
+  void annotate_for_bug_detection_on_move(
+      [[maybe_unused]] raw_hash_set& that) {
+    // We only enable moved-from validation when generations are enabled (rather
+    // than using NDEBUG) to avoid issues in which NDEBUG is enabled in some
+    // translation units but not in others.
+    if (SwisstableGenerationsEnabled()) {
+      that.common().set_capacity(this == &that ? InvalidCapacity::kSelfMovedFrom
+                                               : InvalidCapacity::kMovedFrom);
+    }
+    if (!SwisstableGenerationsEnabled() || capacity() == DefaultCapacity() ||
+        capacity() > kAboveMaxValidCapacity) {
       return;
     }
     common().increment_generation();
     if (!empty() && common().should_rehash_for_bug_detection_on_move()) {
-      resize(capacity());
+      ResizeAllocatedTableWithSeedChange(common(), GetPolicyFunctions(),
+                                         capacity());
     }
   }
 
@@ -3733,15 +3203,14 @@
     // We don't bother checking for this/that aliasing. We just need to avoid
     // breaking the invariants in that case.
     destructor_impl();
-    move_common(that.is_full_soo(), that.alloc_ref(), common(),
+    move_common(that.is_full_soo(), that.char_alloc_ref(), common(),
                 std::move(that.common()));
-    // TODO(b/296061262): move instead of copying hash/eq/alloc.
     hash_ref() = that.hash_ref();
     eq_ref() = that.eq_ref();
-    CopyAlloc(alloc_ref(), that.alloc_ref(),
+    CopyAlloc(char_alloc_ref(), that.char_alloc_ref(),
               std::integral_constant<bool, propagate_alloc>());
     that.common() = CommonFields::CreateDefault<SooEnabled()>();
-    maybe_increment_generation_or_rehash_on_move();
+    annotate_for_bug_detection_on_move(that);
     return *this;
   }
 
@@ -3755,7 +3224,7 @@
     }
     if (!that.is_soo()) that.dealloc();
     that.common() = CommonFields::CreateDefault<SooEnabled()>();
-    maybe_increment_generation_or_rehash_on_move();
+    annotate_for_bug_detection_on_move(that);
     return *this;
   }
 
@@ -3765,7 +3234,7 @@
   }
   raw_hash_set& move_assign(raw_hash_set&& that,
                             std::false_type /*propagate_alloc*/) {
-    if (alloc_ref() == that.alloc_ref()) {
+    if (char_alloc_ref() == that.char_alloc_ref()) {
       return assign_impl<false>(std::move(that));
     }
     // Aliasing can't happen here because allocs would compare equal above.
@@ -3774,7 +3243,6 @@
     // We can't take over that's memory so we need to move each element.
     // While moving elements, this should have that's hash/eq so copy hash/eq
     // before moving elements.
-    // TODO(b/296061262): move instead of copying hash/eq.
     hash_ref() = that.hash_ref();
     eq_ref() = that.eq_ref();
     return move_elements_allocs_unequal(std::move(that));
@@ -3782,35 +3250,42 @@
 
   template <class K>
   std::pair<iterator, bool> find_or_prepare_insert_soo(const K& key) {
+    ctrl_t soo_slot_ctrl;
     if (empty()) {
-      const HashtablezInfoHandle infoz = try_sample_soo();
-      if (infoz.IsSampled()) {
-        resize_with_soo_infoz(infoz);
-      } else {
+      if (!should_sample_soo()) {
         common().set_full_soo();
         return {soo_iterator(), true};
       }
+      soo_slot_ctrl = ctrl_t::kEmpty;
     } else if (PolicyTraits::apply(EqualElement<K>{key, eq_ref()},
                                    PolicyTraits::element(soo_slot()))) {
       return {soo_iterator(), false};
     } else {
-      resize(NextCapacity(SooCapacity()));
+      soo_slot_ctrl = static_cast<ctrl_t>(H2(hash_of(soo_slot())));
     }
-    const size_t index =
-        PrepareInsertAfterSoo(hash_ref()(key), sizeof(slot_type), common());
+    constexpr bool kUseMemcpy =
+        PolicyTraits::transfer_uses_memcpy() && SooEnabled();
+    size_t index = GrowSooTableToNextCapacityAndPrepareInsert<
+        kUseMemcpy ? OptimalMemcpySizeForSooSlotTransfer(sizeof(slot_type)) : 0,
+        kUseMemcpy>(common(), GetPolicyFunctions(), hash_of(key),
+                    soo_slot_ctrl);
     return {iterator_at(index), true};
   }
 
   template <class K>
   std::pair<iterator, bool> find_or_prepare_insert_non_soo(const K& key) {
-    assert(!is_soo());
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     prefetch_heap_block();
-    auto hash = hash_ref()(key);
+    const size_t hash = hash_of(key);
     auto seq = probe(common(), hash);
+    const h2_t h2 = H2(hash);
     const ctrl_t* ctrl = control();
     while (true) {
+#ifndef ABSL_HAVE_MEMORY_SANITIZER
+      absl::PrefetchToLocalCache(slot_array() + seq.offset());
+#endif
       Group g{ctrl + seq.offset()};
-      for (uint32_t i : g.Match(H2(hash))) {
+      for (uint32_t i : g.Match(h2)) {
         if (ABSL_PREDICT_TRUE(PolicyTraits::apply(
                 EqualElement<K>{key, eq_ref()},
                 PolicyTraits::element(slot_array() + seq.offset(i)))))
@@ -3818,50 +3293,86 @@
       }
       auto mask_empty = g.MaskEmpty();
       if (ABSL_PREDICT_TRUE(mask_empty)) {
-        size_t target = seq.offset(
-            GetInsertionOffset(mask_empty, capacity(), hash, control()));
-        return {iterator_at(PrepareInsertNonSoo(common(), hash,
-                                                FindInfo{target, seq.index()},
-                                                GetPolicyFunctions())),
+        size_t target = seq.offset(mask_empty.LowestBitSet());
+        return {iterator_at(PrepareInsertNonSoo(common(), GetPolicyFunctions(),
+                                                hash,
+                                                FindInfo{target, seq.index()})),
                 true};
       }
       seq.next();
-      assert(seq.index() <= capacity() && "full table!");
+      ABSL_SWISSTABLE_ASSERT(seq.index() <= capacity() && "full table!");
     }
   }
 
  protected:
+  // Asserts for correctness that we run on find/find_or_prepare_insert.
+  template <class K>
+  void AssertOnFind([[maybe_unused]] const K& key) {
+    AssertHashEqConsistent(key);
+    AssertNotDebugCapacity();
+  }
+
+  // Asserts that the capacity is not a sentinel invalid value.
+  void AssertNotDebugCapacity() const {
+#ifdef NDEBUG
+    if (!SwisstableGenerationsEnabled()) {
+      return;
+    }
+#endif
+    if (ABSL_PREDICT_TRUE(capacity() <
+                          InvalidCapacity::kAboveMaxValidCapacity)) {
+      return;
+    }
+    assert(capacity() != InvalidCapacity::kReentrance &&
+           "Reentrant container access during element construction/destruction "
+           "is not allowed.");
+    if constexpr (SwisstableAssertAccessToDestroyedTable()) {
+      if (capacity() == InvalidCapacity::kDestroyed) {
+        ABSL_RAW_LOG(FATAL, "Use of destroyed hash table.");
+      }
+    }
+    if (SwisstableGenerationsEnabled() &&
+        ABSL_PREDICT_FALSE(capacity() >= InvalidCapacity::kMovedFrom)) {
+      if (capacity() == InvalidCapacity::kSelfMovedFrom) {
+        // If this log triggers, then a hash table was move-assigned to itself
+        // and then used again later without being reinitialized.
+        ABSL_RAW_LOG(FATAL, "Use of self-move-assigned hash table.");
+      }
+      ABSL_RAW_LOG(FATAL, "Use of moved-from hash table.");
+    }
+  }
+
   // Asserts that hash and equal functors provided by the user are consistent,
   // meaning that `eq(k1, k2)` implies `hash(k1)==hash(k2)`.
   template <class K>
-  void AssertHashEqConsistent(ABSL_ATTRIBUTE_UNUSED const K& key) {
-#ifndef NDEBUG
+  void AssertHashEqConsistent(const K& key) {
+#ifdef NDEBUG
+    return;
+#endif
+    // If the hash/eq functors are known to be consistent, then skip validation.
+    if (std::is_same<hasher, absl::container_internal::StringHash>::value &&
+        std::is_same<key_equal, absl::container_internal::StringEq>::value) {
+      return;
+    }
+    if (std::is_scalar<key_type>::value &&
+        std::is_same<hasher, absl::Hash<key_type>>::value &&
+        std::is_same<key_equal, std::equal_to<key_type>>::value) {
+      return;
+    }
     if (empty()) return;
 
-    const size_t hash_of_arg = hash_ref()(key);
-    const auto assert_consistent = [&](const ctrl_t*, slot_type* slot) {
-      const value_type& element = PolicyTraits::element(slot);
+    const size_t hash_of_arg = hash_of(key);
+    const auto assert_consistent = [&](const ctrl_t*, void* slot) {
+      const value_type& element =
+          PolicyTraits::element(static_cast<slot_type*>(slot));
       const bool is_key_equal =
           PolicyTraits::apply(EqualElement<K>{key, eq_ref()}, element);
       if (!is_key_equal) return;
 
       const size_t hash_of_slot =
           PolicyTraits::apply(HashElement{hash_ref()}, element);
-      const bool is_hash_equal = hash_of_arg == hash_of_slot;
-      if (!is_hash_equal) {
-        // In this case, we're going to crash. Do a couple of other checks for
-        // idempotence issues. Recalculating hash/eq here is also convenient for
-        // debugging with gdb/lldb.
-        const size_t once_more_hash_arg = hash_ref()(key);
-        assert(hash_of_arg == once_more_hash_arg && "hash is not idempotent.");
-        const size_t once_more_hash_slot =
-            PolicyTraits::apply(HashElement{hash_ref()}, element);
-        assert(hash_of_slot == once_more_hash_slot &&
-               "hash is not idempotent.");
-        const bool once_more_eq =
-            PolicyTraits::apply(EqualElement<K>{key, eq_ref()}, element);
-        assert(is_key_equal == once_more_eq && "equality is not idempotent.");
-      }
+      [[maybe_unused]] const bool is_hash_equal =
+          hash_of_arg == hash_of_slot;
       assert((!is_key_equal || is_hash_equal) &&
              "eq(k1, k2) must imply that hash(k1) == hash(k2). "
              "hash/eq functors are inconsistent.");
@@ -3873,8 +3384,7 @@
     }
     // We only do validation for small tables so that it's constant time.
     if (capacity() > 16) return;
-    IterateOverFullSlots(common(), slot_array(), assert_consistent);
-#endif
+    IterateOverFullSlots(common(), sizeof(slot_type), assert_consistent);
   }
 
   // Attempts to find `key` in the table; if it isn't found, returns an iterator
@@ -3882,7 +3392,7 @@
   // `key`'s H2. Returns a bool indicating whether an insertion can take place.
   template <class K>
   std::pair<iterator, bool> find_or_prepare_insert(const K& key) {
-    AssertHashEqConsistent(key);
+    AssertOnFind(key);
     if (is_soo()) return find_or_prepare_insert_soo(key);
     return find_or_prepare_insert_non_soo(key);
   }
@@ -3899,7 +3409,10 @@
   void emplace_at(iterator iter, Args&&... args) {
     construct(iter.slot(), std::forward<Args>(args)...);
 
-    assert(PolicyTraits::apply(FindElement{*this}, *iter) == iter &&
+    // When capacity is 1, find calls find_small and if size is 0, then it will
+    // return an end iterator. This can happen in the raw_hash_set copy ctor.
+    assert((capacity() == 1 ||
+            PolicyTraits::apply(FindElement{*this}, *iter) == iter) &&
            "constructed value does not match the lookup key");
   }
 
@@ -3926,16 +3439,16 @@
   //
   // See `CapacityToGrowth()`.
   size_t growth_left() const {
-    assert(!is_soo());
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     return common().growth_left();
   }
 
   GrowthInfo& growth_info() {
-    assert(!is_soo());
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     return common().growth_info();
   }
   GrowthInfo growth_info() const {
-    assert(!is_soo());
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     return common().growth_info();
   }
 
@@ -3943,7 +3456,7 @@
   // cache misses. This is intended to overlap with execution of calculating the
   // hash for a key.
   void prefetch_heap_block() const {
-    assert(!is_soo());
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
 #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
     __builtin_prefetch(control(), 0, 1);
 #endif
@@ -3953,19 +3466,21 @@
   const CommonFields& common() const { return settings_.template get<0>(); }
 
   ctrl_t* control() const {
-    assert(!is_soo());
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     return common().control();
   }
   slot_type* slot_array() const {
-    assert(!is_soo());
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     return static_cast<slot_type*>(common().slot_array());
   }
   slot_type* soo_slot() {
-    assert(is_soo());
-    return static_cast<slot_type*>(common().soo_data());
+    ABSL_SWISSTABLE_ASSERT(is_soo());
+    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(
+        static_cast<slot_type*>(common().soo_data()));
   }
   const slot_type* soo_slot() const {
-    return const_cast<raw_hash_set*>(this)->soo_slot();
+    ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(
+        const_cast<raw_hash_set*>(this)->soo_slot());
   }
   iterator soo_iterator() {
     return {SooControl(), soo_slot(), common().generation_ptr()};
@@ -3973,8 +3488,22 @@
   const_iterator soo_iterator() const {
     return const_cast<raw_hash_set*>(this)->soo_iterator();
   }
+  slot_type* single_slot() {
+    ABSL_SWISSTABLE_ASSERT(capacity() <= 1);
+    return SooEnabled() ? soo_slot() : slot_array();
+  }
+  const slot_type* single_slot() const {
+    return const_cast<raw_hash_set*>(this)->single_slot();
+  }
+  iterator single_iterator() {
+    return {SooEnabled() ? SooControl() : control(), single_slot(),
+            common().generation_ptr()};
+  }
+  const_iterator single_iterator() const {
+    return const_cast<raw_hash_set*>(this)->single_iterator();
+  }
   HashtablezInfoHandle infoz() {
-    assert(!is_soo());
+    ABSL_SWISSTABLE_ASSERT(!is_soo());
     return common().infoz();
   }
 
@@ -3982,49 +3511,118 @@
   const hasher& hash_ref() const { return settings_.template get<1>(); }
   key_equal& eq_ref() { return settings_.template get<2>(); }
   const key_equal& eq_ref() const { return settings_.template get<2>(); }
-  allocator_type& alloc_ref() { return settings_.template get<3>(); }
-  const allocator_type& alloc_ref() const {
+  CharAlloc& char_alloc_ref() { return settings_.template get<3>(); }
+  const CharAlloc& char_alloc_ref() const {
     return settings_.template get<3>();
   }
 
-  static const void* get_hash_ref_fn(const CommonFields& common) {
-    auto* h = reinterpret_cast<const raw_hash_set*>(&common);
-    return &h->hash_ref();
+  static void* get_char_alloc_ref_fn(CommonFields& common) {
+    auto* h = reinterpret_cast<raw_hash_set*>(&common);
+    return &h->char_alloc_ref();
   }
-  static void transfer_slot_fn(void* set, void* dst, void* src) {
+  static void* get_hash_ref_fn(CommonFields& common) {
+    auto* h = reinterpret_cast<raw_hash_set*>(&common);
+    // TODO(b/397453582): Remove support for const hasher.
+    return const_cast<std::remove_const_t<hasher>*>(&h->hash_ref());
+  }
+  static void transfer_n_slots_fn(void* set, void* dst, void* src,
+                                  size_t count) {
+    auto* src_slot = to_slot(src);
+    auto* dst_slot = to_slot(dst);
+
     auto* h = static_cast<raw_hash_set*>(set);
-    h->transfer(static_cast<slot_type*>(dst), static_cast<slot_type*>(src));
+    for (; count > 0; --count, ++src_slot, ++dst_slot) {
+      h->transfer(dst_slot, src_slot);
+    }
   }
-  // Note: dealloc_fn will only be used if we have a non-standard allocator.
-  static void dealloc_fn(CommonFields& common, const PolicyFunctions&) {
+
+  // TODO(b/382423690): Try to type erase entire function or at least type erase
+  // by GetKey + Hash for memcpyable types.
+  // TODO(b/382423690): Try to type erase for big slots: sizeof(slot_type) > 16.
+  static void transfer_unprobed_elements_to_next_capacity_fn(
+      CommonFields& common, const ctrl_t* old_ctrl, void* old_slots,
+      void* probed_storage,
+      void (*encode_probed_element)(void* probed_storage, h2_t h2,
+                                    size_t source_offset, size_t h1)) {
+    const size_t new_capacity = common.capacity();
+    const size_t old_capacity = PreviousCapacity(new_capacity);
+    ABSL_ASSUME(old_capacity + 1 >= Group::kWidth);
+    ABSL_ASSUME((old_capacity + 1) % Group::kWidth == 0);
+
     auto* set = reinterpret_cast<raw_hash_set*>(&common);
+    slot_type* old_slots_ptr = to_slot(old_slots);
+    ctrl_t* new_ctrl = common.control();
+    slot_type* new_slots = set->slot_array();
 
-    // Unpoison before returning the memory to the allocator.
-    SanitizerUnpoisonMemoryRegion(common.slot_array(),
-                                  sizeof(slot_type) * common.capacity());
+    const PerTableSeed seed = common.seed();
 
-    common.infoz().Unregister();
-    Deallocate<BackingArrayAlignment(alignof(slot_type))>(
-        &set->alloc_ref(), common.backing_array_start(),
-        common.alloc_size(sizeof(slot_type), alignof(slot_type)));
+    for (size_t group_index = 0; group_index < old_capacity;
+         group_index += Group::kWidth) {
+      GroupFullEmptyOrDeleted old_g(old_ctrl + group_index);
+      std::memset(new_ctrl + group_index, static_cast<int8_t>(ctrl_t::kEmpty),
+                  Group::kWidth);
+      std::memset(new_ctrl + group_index + old_capacity + 1,
+                  static_cast<int8_t>(ctrl_t::kEmpty), Group::kWidth);
+      // TODO(b/382423690): try to type erase everything outside of the loop.
+      // We will share a lot of code in expense of one function call per group.
+      for (auto in_fixed_group_index : old_g.MaskFull()) {
+        size_t old_index = group_index + in_fixed_group_index;
+        slot_type* old_slot = old_slots_ptr + old_index;
+        // TODO(b/382423690): try to avoid entire hash calculation since we need
+        // only one new bit of h1.
+        size_t hash = set->hash_of(old_slot);
+        size_t h1 = H1(hash, seed);
+        h2_t h2 = H2(hash);
+        size_t new_index = TryFindNewIndexWithoutProbing(
+            h1, old_index, old_capacity, new_ctrl, new_capacity);
+        // Note that encode_probed_element is allowed to use old_ctrl buffer
+        // till and included the old_index.
+        if (ABSL_PREDICT_FALSE(new_index == kProbedElementIndexSentinel)) {
+          encode_probed_element(probed_storage, h2, old_index, h1);
+          continue;
+        }
+        ABSL_SWISSTABLE_ASSERT((new_index & old_capacity) <= old_index);
+        ABSL_SWISSTABLE_ASSERT(IsEmpty(new_ctrl[new_index]));
+        new_ctrl[new_index] = static_cast<ctrl_t>(h2);
+        auto* new_slot = new_slots + new_index;
+        SanitizerUnpoisonMemoryRegion(new_slot, sizeof(slot_type));
+        set->transfer(new_slot, old_slot);
+        SanitizerPoisonMemoryRegion(old_slot, sizeof(slot_type));
+      }
+    }
   }
 
   static const PolicyFunctions& GetPolicyFunctions() {
+    static_assert(sizeof(slot_type) <= (std::numeric_limits<uint32_t>::max)(),
+                  "Slot size is too large. Use std::unique_ptr for value type "
+                  "or use absl::node_hash_{map,set}.");
+    static_assert(alignof(slot_type) <=
+                  size_t{(std::numeric_limits<uint16_t>::max)()});
+    static_assert(sizeof(key_type) <=
+                  size_t{(std::numeric_limits<uint32_t>::max)()});
+    static_assert(sizeof(value_type) <=
+                  size_t{(std::numeric_limits<uint32_t>::max)()});
+    static constexpr size_t kBackingArrayAlignment =
+        BackingArrayAlignment(alignof(slot_type));
     static constexpr PolicyFunctions value = {
-        sizeof(slot_type),
+        static_cast<uint32_t>(sizeof(key_type)),
+        static_cast<uint32_t>(sizeof(value_type)),
+        static_cast<uint32_t>(sizeof(slot_type)),
+        static_cast<uint16_t>(alignof(slot_type)), SooEnabled(),
+        ShouldSampleHashtablezInfoForAlloc<CharAlloc>(),
         // TODO(b/328722020): try to type erase
         // for standard layout and alignof(Hash) <= alignof(CommonFields).
-        std::is_empty<hasher>::value ? &GetHashRefForEmptyHasher
-                                     : &raw_hash_set::get_hash_ref_fn,
+        std::is_empty_v<hasher> ? &GetRefForEmptyClass
+                                : &raw_hash_set::get_hash_ref_fn,
         PolicyTraits::template get_hash_slot_fn<hasher>(),
         PolicyTraits::transfer_uses_memcpy()
-            ? TransferRelocatable<sizeof(slot_type)>
-            : &raw_hash_set::transfer_slot_fn,
-        (std::is_same<SlotAlloc, std::allocator<slot_type>>::value
-             ? &DeallocateStandard<alignof(slot_type)>
-             : &raw_hash_set::dealloc_fn),
-        &raw_hash_set::resize_impl,
-    };
+            ? TransferNRelocatable<sizeof(slot_type)>
+            : &raw_hash_set::transfer_n_slots_fn,
+        std::is_empty_v<Alloc> ? &GetRefForEmptyClass
+                               : &raw_hash_set::get_char_alloc_ref_fn,
+        &AllocateBackingArray<kBackingArrayAlignment, CharAlloc>,
+        &DeallocateBackingArray<kBackingArrayAlignment, CharAlloc>,
+        &raw_hash_set::transfer_unprobed_elements_to_next_capacity_fn};
     return value;
   }
 
@@ -4032,9 +3630,9 @@
   // CompressedTuple will ensure that sizeof is not affected by any of the empty
   // fields that occur after CommonFields.
   absl::container_internal::CompressedTuple<CommonFields, hasher, key_equal,
-                                            allocator_type>
+                                            CharAlloc>
       settings_{CommonFields::CreateDefault<SooEnabled()>(), hasher{},
-                key_equal{}, allocator_type{}};
+                key_equal{}, CharAlloc{}};
 };
 
 // Friend access for free functions in raw_hash_set.h.
@@ -4047,17 +3645,21 @@
     if (c->is_soo()) {
       auto it = c->soo_iterator();
       if (!pred(*it)) {
-        assert(c->size() == 1 && "hash table was modified unexpectedly");
+        ABSL_SWISSTABLE_ASSERT(c->size() == 1 &&
+                               "hash table was modified unexpectedly");
         return 0;
       }
       c->destroy(it.slot());
       c->common().set_empty_soo();
       return 1;
     }
-    ABSL_ATTRIBUTE_UNUSED const size_t original_size_for_assert = c->size();
+    [[maybe_unused]] const size_t original_size_for_assert = c->size();
     size_t num_deleted = 0;
+    using SlotType = typename Set::slot_type;
     IterateOverFullSlots(
-        c->common(), c->slot_array(), [&](const ctrl_t* ctrl, auto* slot) {
+        c->common(), sizeof(SlotType),
+        [&](const ctrl_t* ctrl, void* slot_void) {
+          auto* slot = static_cast<SlotType*>(slot_void);
           if (pred(Set::PolicyTraits::element(slot))) {
             c->destroy(slot);
             EraseMetaOnly(c->common(), static_cast<size_t>(ctrl - c->control()),
@@ -4067,8 +3669,9 @@
         });
     // NOTE: IterateOverFullSlots allow removal of the current element, so we
     // verify the size additionally here.
-    assert(original_size_for_assert - num_deleted == c->size() &&
-           "hash table was modified unexpectedly");
+    ABSL_SWISSTABLE_ASSERT(original_size_for_assert - num_deleted ==
+                               c->size() &&
+                           "hash table was modified unexpectedly");
     return num_deleted;
   }
 
@@ -4081,10 +3684,12 @@
       cb(*c->soo_iterator());
       return;
     }
+    using SlotType = typename Set::slot_type;
     using ElementTypeWithConstness = decltype(*c->begin());
     IterateOverFullSlots(
-        c->common(), c->slot_array(), [&cb](const ctrl_t*, auto* slot) {
-          ElementTypeWithConstness& element = Set::PolicyTraits::element(slot);
+        c->common(), sizeof(SlotType), [&cb](const ctrl_t*, void* slot) {
+          ElementTypeWithConstness& element =
+              Set::PolicyTraits::element(static_cast<SlotType*>(slot));
           cb(element);
         });
   }
@@ -4117,12 +3722,13 @@
                              const typename Set::key_type& key) {
     if (set.is_soo()) return 0;
     size_t num_probes = 0;
-    size_t hash = set.hash_ref()(key);
+    const size_t hash = set.hash_of(key);
     auto seq = probe(set.common(), hash);
+    const h2_t h2 = H2(hash);
     const ctrl_t* ctrl = set.control();
     while (true) {
       container_internal::Group g{ctrl + seq.offset()};
-      for (uint32_t i : g.Match(container_internal::H2(hash))) {
+      for (uint32_t i : g.Match(h2)) {
         if (Traits::apply(
                 typename Set::template EqualElement<typename Set::key_type>{
                     key, set.eq_ref()},
@@ -4155,6 +3761,22 @@
 };
 
 }  // namespace hashtable_debug_internal
+
+// Extern template instantiations reduce binary size and linker input size.
+// Function definition is in raw_hash_set.cc.
+extern template size_t GrowSooTableToNextCapacityAndPrepareInsert<0, false>(
+    CommonFields&, const PolicyFunctions&, size_t, ctrl_t);
+extern template size_t GrowSooTableToNextCapacityAndPrepareInsert<1, true>(
+    CommonFields&, const PolicyFunctions&, size_t, ctrl_t);
+extern template size_t GrowSooTableToNextCapacityAndPrepareInsert<4, true>(
+    CommonFields&, const PolicyFunctions&, size_t, ctrl_t);
+extern template size_t GrowSooTableToNextCapacityAndPrepareInsert<8, true>(
+    CommonFields&, const PolicyFunctions&, size_t, ctrl_t);
+#if UINTPTR_MAX == UINT64_MAX
+extern template size_t GrowSooTableToNextCapacityAndPrepareInsert<16, true>(
+    CommonFields&, const PolicyFunctions&, size_t, ctrl_t);
+#endif
+
 }  // namespace container_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
@@ -4162,5 +3784,6 @@
 #undef ABSL_SWISSTABLE_ENABLE_GENERATIONS
 #undef ABSL_SWISSTABLE_IGNORE_UNINITIALIZED
 #undef ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN
+#undef ABSL_SWISSTABLE_ASSERT
 
 #endif  // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
diff --git a/absl/container/internal/raw_hash_set_benchmark.cc b/absl/container/internal/raw_hash_set_benchmark.cc
index 424b72c..ac94877 100644
--- a/absl/container/internal/raw_hash_set_benchmark.cc
+++ b/absl/container/internal/raw_hash_set_benchmark.cc
@@ -172,8 +172,7 @@
 //
 // On a table of size N, keep deleting the LRU entry and add a random one.
 void BM_CacheInSteadyState(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   string_generator gen{12};
   StringTable t;
   std::deque<std::string> keys;
@@ -250,8 +249,7 @@
 BENCHMARK(BM_EndComparison);
 
 void BM_Iteration(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   string_generator gen{12};
   StringTable t;
 
@@ -293,8 +291,7 @@
     ->ArgPair(1000, 10);
 
 void BM_CopyCtorSparseInt(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   IntTable t;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
 
@@ -312,8 +309,7 @@
 BENCHMARK(BM_CopyCtorSparseInt)->Range(1, 4096);
 
 void BM_CopyCtorInt(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   IntTable t;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
 
@@ -330,8 +326,7 @@
 BENCHMARK(BM_CopyCtorInt)->Range(0, 4096);
 
 void BM_CopyCtorString(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   StringTable t;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
 
@@ -348,8 +343,7 @@
 BENCHMARK(BM_CopyCtorString)->Range(0, 4096);
 
 void BM_CopyAssign(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   IntTable t;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
   while (t.size() < state.range(0)) {
@@ -365,8 +359,7 @@
 BENCHMARK(BM_CopyAssign)->Range(128, 4096);
 
 void BM_RangeCtor(benchmark::State& state) {
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
   std::vector<int> values;
   const size_t desired_size = state.range(0);
@@ -418,7 +411,17 @@
     }
   }
 }
-BENCHMARK(BM_ReserveIntTable)->Range(1, 64);
+BENCHMARK(BM_ReserveIntTable)
+    ->Arg(1)
+    ->Arg(2)
+    ->Arg(4)
+    ->Arg(8)
+    ->Arg(16)
+    ->Arg(32)
+    ->Arg(64)
+    ->Arg(128)
+    ->Arg(256)
+    ->Arg(512);
 
 void BM_ReserveStringTable(benchmark::State& state) {
   constexpr size_t kBatchSize = 1024;
@@ -437,7 +440,17 @@
     }
   }
 }
-BENCHMARK(BM_ReserveStringTable)->Range(1, 64);
+BENCHMARK(BM_ReserveStringTable)
+    ->Arg(1)
+    ->Arg(2)
+    ->Arg(4)
+    ->Arg(8)
+    ->Arg(16)
+    ->Arg(32)
+    ->Arg(64)
+    ->Arg(128)
+    ->Arg(256)
+    ->Arg(512);
 
 // Like std::iota, except that ctrl_t doesn't support operator++.
 template <typename CtrlIter>
diff --git a/absl/container/internal/raw_hash_set_probe_benchmark.cc b/absl/container/internal/raw_hash_set_probe_benchmark.cc
index 8f36305..e56648f 100644
--- a/absl/container/internal/raw_hash_set_probe_benchmark.cc
+++ b/absl/container/internal/raw_hash_set_probe_benchmark.cc
@@ -245,13 +245,28 @@
   }
 };
 
-constexpr char kStringFormat[] = "/path/to/file/name-%07d-of-9999999.txt";
+enum class StringSize { kSmall, kMedium, kLarge, kExtraLarge };
+constexpr char kStringFormat[] = "%s/name-%07d-of-9999999.txt";
 
-template <bool small>
+template <StringSize size>
 struct String {
   std::string value;
   static std::string Make(uint32_t v) {
-    return {small ? absl::StrCat(v) : absl::StrFormat(kStringFormat, v)};
+    switch (size) {
+      case StringSize::kSmall:
+        return absl::StrCat(v);
+      case StringSize::kMedium:  // < 32 bytes
+        return absl::StrFormat(kStringFormat, "/path", v);
+      case StringSize::kLarge:  // 33-64 bytes
+        return absl::StrFormat(kStringFormat, "/path/to/file", v);
+      case StringSize::kExtraLarge:  // > 64 bytes
+        return absl::StrFormat(kStringFormat,
+                               "/path/to/a/very/long/file/name/so/that/total/"
+                               "length/is/larger/than/64/bytes",
+                               v);
+      default:
+        return "";
+    }
   }
 };
 
@@ -285,10 +300,9 @@
   mutable uintptr_t current = PointerForAlignment<Align>();
 };
 
-
-template <bool small>
-struct Sequential<String<small>> {
-  std::string operator()() const { return String<small>::Make(current++); }
+template <StringSize size>
+struct Sequential<String<size>> {
+  std::string operator()() const { return String<size>::Make(current++); }
   mutable uint32_t current = 0;
 };
 
@@ -389,10 +403,10 @@
   }
 };
 
-template <class Dist, bool small>
-struct Random<String<small>, Dist> {
+template <class Dist, StringSize size>
+struct Random<String<size>, Dist> {
   std::string operator()() const {
-    return String<small>::Make(Random<uint32_t, Dist>{}());
+    return String<size>::Make(Random<uint32_t, Dist>{}());
   }
 };
 
@@ -421,9 +435,20 @@
   return absl::StrCat("PtrIdentity", Align);
 }
 
-template <bool small>
-std::string Name(String<small>*) {
-  return small ? "StrS" : "StrL";
+template <StringSize size>
+std::string Name(String<size>*) {
+  switch (size) {
+    case StringSize::kSmall:
+      return "StrS";
+    case StringSize::kMedium:
+      return "StrM";
+    case StringSize::kLarge:
+      return "StrL";
+    case StringSize::kExtraLarge:
+      return "StrXL";
+    default:
+      return "";
+  }
 }
 
 template <class T, class U>
@@ -543,12 +568,18 @@
   RunForType<PtrIdentity<32>>(results);
   RunForType<PtrIdentity<64>>(results);
   RunForType<std::pair<uint32_t, uint32_t>>(results);
-  RunForType<String<true>>(results);
-  RunForType<String<false>>(results);
-  RunForType<std::pair<uint64_t, String<true>>>(results);
-  RunForType<std::pair<String<true>, uint64_t>>(results);
-  RunForType<std::pair<uint64_t, String<false>>>(results);
-  RunForType<std::pair<String<false>, uint64_t>>(results);
+  RunForType<String<StringSize::kSmall>>(results);
+  RunForType<String<StringSize::kMedium>>(results);
+  RunForType<String<StringSize::kLarge>>(results);
+  RunForType<String<StringSize::kExtraLarge>>(results);
+  RunForType<std::pair<uint64_t, String<StringSize::kSmall>>>(results);
+  RunForType<std::pair<String<StringSize::kSmall>, uint64_t>>(results);
+  RunForType<std::pair<uint64_t, String<StringSize::kMedium>>>(results);
+  RunForType<std::pair<String<StringSize::kMedium>, uint64_t>>(results);
+  RunForType<std::pair<uint64_t, String<StringSize::kLarge>>>(results);
+  RunForType<std::pair<String<StringSize::kLarge>, uint64_t>>(results);
+  RunForType<std::pair<uint64_t, String<StringSize::kExtraLarge>>>(results);
+  RunForType<std::pair<String<StringSize::kExtraLarge>, uint64_t>>(results);
 
   switch (output()) {
     case OutputStyle::kRegular:
diff --git a/absl/container/internal/raw_hash_set_resize_impl.h b/absl/container/internal/raw_hash_set_resize_impl.h
new file mode 100644
index 0000000..149d9e8
--- /dev/null
+++ b/absl/container/internal/raw_hash_set_resize_impl.h
@@ -0,0 +1,80 @@
+// Copyright 2025 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.
+//
+// This is a private implementation detail of resize algorithm of
+// raw_hash_set. It is exposed in a separate file for testing purposes.
+
+#ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_RESIZE_IMPL_H_
+#define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_RESIZE_IMPL_H_
+
+#include <cstddef>
+#include <cstdint>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// Encoding for probed elements used for smaller tables.
+// Data is encoded into single integer.
+// Storage format for 4 bytes:
+// - 7 bits for h2
+// - 12 bits for source_offset
+// - 13 bits for h1
+// Storage format for 8 bytes:
+// - 7 bits for h2
+// - 28 bits for source_offset
+// - 29 bits for h1
+// Storage format for 16 bytes:
+// - 7 bits for h2
+// - 57 bits for source_offset
+// - 58 bits for h1
+template <typename IntType, size_t kTotalBits>
+struct ProbedItemImpl {
+  static constexpr IntType kH2Bits = 7;
+
+  static constexpr IntType kMaxOldBits = (kTotalBits - kH2Bits) / 2;
+  static constexpr IntType kMaxOldCapacity = (IntType{1} << kMaxOldBits) - 1;
+
+  // We always have one bit more for h1.
+  static constexpr IntType kMaxNewBits = kMaxOldBits + 1;
+  static constexpr IntType kMaxNewCapacity = (IntType{1} << kMaxNewBits) - 1;
+
+  static constexpr IntType kH2Shift = (kTotalBits - kH2Bits);
+  static_assert(kMaxNewBits + kMaxOldBits + kH2Bits == kTotalBits);
+
+  ProbedItemImpl() = default;
+  ProbedItemImpl(uint8_t h2_arg, size_t source_offset_arg, size_t h1_arg)
+      : h2(h2_arg),
+        source_offset(static_cast<IntType>(source_offset_arg)),
+        h1(static_cast<IntType>(h1_arg)) {}
+
+  IntType h2 : kH2Bits;
+  IntType source_offset : kMaxOldBits;
+  IntType h1 : kMaxNewBits;
+};
+
+using ProbedItem4Bytes = ProbedItemImpl<uint32_t, 32>;
+static_assert(sizeof(ProbedItem4Bytes) == 4);
+using ProbedItem8Bytes = ProbedItemImpl<uint64_t, 64>;
+static_assert(sizeof(ProbedItem8Bytes) == 8);
+using ProbedItem16Bytes = ProbedItemImpl<uint64_t, 7 + 57 + 58>;
+static_assert(sizeof(ProbedItem16Bytes) == 16);
+
+}  // namespace container_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_RESIZE_IMPL_H_
diff --git a/absl/container/internal/raw_hash_set_resize_impl_test.cc b/absl/container/internal/raw_hash_set_resize_impl_test.cc
new file mode 100644
index 0000000..5020fca
--- /dev/null
+++ b/absl/container/internal/raw_hash_set_resize_impl_test.cc
@@ -0,0 +1,66 @@
+// Copyright 2025 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/container/internal/raw_hash_set_resize_impl.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+namespace {
+
+constexpr size_t kSmallSourceOffset = 17;
+constexpr size_t kSmallH1 = 25;
+
+template <class Encoder>
+class EncoderTest : public testing::Test {};
+
+using ProbedItemTypes =
+    ::testing::Types<ProbedItem4Bytes, ProbedItem8Bytes, ProbedItem16Bytes>;
+TYPED_TEST_SUITE(EncoderTest, ProbedItemTypes);
+
+TYPED_TEST(EncoderTest, EncodeDecodeSmall) {
+  using ProbedItem = TypeParam;
+  for (uint8_t h2 = 0; h2 < 128; ++h2) {
+    ProbedItem item(h2, kSmallSourceOffset, kSmallH1);
+    EXPECT_EQ(item.h2, h2);
+    EXPECT_EQ(item.source_offset, kSmallSourceOffset);
+    EXPECT_EQ(item.h1 & ProbedItem::kMaxNewCapacity, kSmallH1);
+  }
+}
+
+TYPED_TEST(EncoderTest, EncodeDecodeMax) {
+  using ProbedItem = TypeParam;
+  for (uint8_t h2 = 0; h2 < 128; ++h2) {
+    size_t source_offset = static_cast<size_t>(std::min<uint64_t>(
+        ProbedItem::kMaxOldCapacity, (std::numeric_limits<size_t>::max)()));
+    size_t h1 = static_cast<size_t>(std::min<uint64_t>(
+        ProbedItem::kMaxNewCapacity, (std::numeric_limits<size_t>::max)()));
+    ProbedItem item(h2, source_offset, h1);
+    EXPECT_EQ(item.h2, h2);
+    EXPECT_EQ(item.source_offset, source_offset);
+    EXPECT_EQ(item.h1 & ProbedItem::kMaxNewCapacity, h1);
+  }
+}
+
+}  // namespace
+}  // namespace container_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index f1257d4..9a323c4 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -17,19 +17,23 @@
 #include <algorithm>
 #include <array>
 #include <atomic>
+#include <bitset>
 #include <cmath>
 #include <cstddef>
 #include <cstdint>
+#include <cstring>
 #include <deque>
 #include <functional>
 #include <iostream>
 #include <iterator>
+#include <limits>
 #include <list>
 #include <map>
 #include <memory>
 #include <numeric>
 #include <ostream>
 #include <random>
+#include <set>
 #include <string>
 #include <tuple>
 #include <type_traits>
@@ -49,8 +53,13 @@
 #include "absl/container/internal/container_memory.h"
 #include "absl/container/internal/hash_function_defaults.h"
 #include "absl/container/internal/hash_policy_testing.h"
+#include "absl/random/random.h"
+// TODO(b/382423690): Separate tests that depend only on
+// hashtable_control_bytes.
+#include "absl/container/internal/hashtable_control_bytes.h"
 #include "absl/container/internal/hashtable_debug.h"
 #include "absl/container/internal/hashtablez_sampler.h"
+#include "absl/container/internal/raw_hash_set_resize_impl.h"
 #include "absl/container/internal/test_allocator.h"
 #include "absl/container/internal/test_instance_tracker.h"
 #include "absl/container/node_hash_set.h"
@@ -60,8 +69,10 @@
 #include "absl/log/log.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
+#include "absl/numeric/int128.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -69,8 +80,8 @@
 
 struct RawHashSetTestOnlyAccess {
   template <typename C>
-  static auto GetCommon(const C& c) -> decltype(c.common()) {
-    return c.common();
+  static auto GetCommon(C&& c) -> decltype(std::forward<C>(c).common()) {
+    return std::forward<C>(c).common();
   }
   template <typename C>
   static auto GetSlots(const C& c) -> decltype(c.slot_array()) {
@@ -91,10 +102,28 @@
 using ::testing::Lt;
 using ::testing::Pair;
 using ::testing::UnorderedElementsAre;
+using ::testing::UnorderedElementsAreArray;
 
 // Convenience function to static cast to ctrl_t.
 ctrl_t CtrlT(int i) { return static_cast<ctrl_t>(i); }
 
+// Enables sampling with 1 percent sampling rate and
+// resets the rate counter for the current thread.
+void SetSamplingRateTo1Percent() {
+  SetHashtablezEnabled(true);
+  SetHashtablezSampleParameter(100);  // Sample ~1% of tables.
+  // Reset rate counter for the current thread.
+  TestOnlyRefreshSamplingStateForCurrentThread();
+}
+
+// Disables sampling and resets the rate counter for the current thread.
+void DisableSampling() {
+  SetHashtablezEnabled(false);
+  SetHashtablezSampleParameter(1 << 16);
+  // Reset rate counter for the current thread.
+  TestOnlyRefreshSamplingStateForCurrentThread();
+}
+
 TEST(GrowthInfoTest, GetGrowthLeft) {
   GrowthInfo gi;
   gi.InitGrowthLeftNoDeleted(5);
@@ -183,6 +212,60 @@
   EXPECT_FALSE(gi.HasNoDeleted());
 }
 
+TEST(GrowthInfoTest, HasNoGrowthLeftAssumingMayHaveDeleted) {
+  GrowthInfo gi;
+  gi.InitGrowthLeftNoDeleted(1);
+  gi.OverwriteFullAsDeleted();
+  EXPECT_EQ(gi.GetGrowthLeft(), 1);
+  EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
+  gi.OverwriteControlAsFull(ctrl_t::kDeleted);
+  EXPECT_EQ(gi.GetGrowthLeft(), 1);
+  EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
+  gi.OverwriteFullAsEmpty();
+  EXPECT_EQ(gi.GetGrowthLeft(), 2);
+  EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
+  gi.OverwriteEmptyAsFull();
+  EXPECT_EQ(gi.GetGrowthLeft(), 1);
+  EXPECT_FALSE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
+  gi.OverwriteEmptyAsFull();
+  EXPECT_EQ(gi.GetGrowthLeft(), 0);
+  EXPECT_TRUE(gi.HasNoGrowthLeftAssumingMayHaveDeleted());
+}
+
+TEST(Util, OptimalMemcpySizeForSooSlotTransfer) {
+  EXPECT_EQ(1, OptimalMemcpySizeForSooSlotTransfer(1));
+  ASSERT_EQ(4, OptimalMemcpySizeForSooSlotTransfer(2));
+  ASSERT_EQ(4, OptimalMemcpySizeForSooSlotTransfer(3));
+  for (size_t slot_size = 4; slot_size <= 8; ++slot_size) {
+    ASSERT_EQ(8, OptimalMemcpySizeForSooSlotTransfer(slot_size));
+  }
+  // If maximum amount of memory is 16, then we can copy up to 16 bytes.
+  for (size_t slot_size = 9; slot_size <= 16; ++slot_size) {
+    ASSERT_EQ(16,
+              OptimalMemcpySizeForSooSlotTransfer(slot_size,
+                                                  /*max_soo_slot_size=*/16));
+    ASSERT_EQ(16,
+              OptimalMemcpySizeForSooSlotTransfer(slot_size,
+                                                  /*max_soo_slot_size=*/24));
+  }
+  // But we shouldn't try to copy more than maximum amount of memory.
+  for (size_t slot_size = 9; slot_size <= 12; ++slot_size) {
+    ASSERT_EQ(12, OptimalMemcpySizeForSooSlotTransfer(
+                      slot_size, /*max_soo_slot_size=*/12));
+  }
+  for (size_t slot_size = 17; slot_size <= 24; ++slot_size) {
+    ASSERT_EQ(24,
+              OptimalMemcpySizeForSooSlotTransfer(slot_size,
+                                                  /*max_soo_slot_size=*/24));
+  }
+  // We shouldn't copy more than maximum.
+  for (size_t slot_size = 17; slot_size <= 20; ++slot_size) {
+    ASSERT_EQ(20,
+              OptimalMemcpySizeForSooSlotTransfer(slot_size,
+                                                  /*max_soo_slot_size=*/20));
+  }
+}
+
 TEST(Util, NormalizeCapacity) {
   EXPECT_EQ(1, NormalizeCapacity(0));
   EXPECT_EQ(1, NormalizeCapacity(1));
@@ -199,9 +282,14 @@
 TEST(Util, GrowthAndCapacity) {
   // Verify that GrowthToCapacity gives the minimum capacity that has enough
   // growth.
-  for (size_t growth = 0; growth < 10000; ++growth) {
+  EXPECT_EQ(SizeToCapacity(0), 0);
+  EXPECT_EQ(SizeToCapacity(1), 1);
+  EXPECT_EQ(SizeToCapacity(2), 3);
+  EXPECT_EQ(SizeToCapacity(3), 3);
+  for (size_t growth = 1; growth < 10000; ++growth) {
     SCOPED_TRACE(growth);
-    size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth));
+    size_t capacity = SizeToCapacity(growth);
+    ASSERT_TRUE(IsValidCapacity(capacity));
     // The capacity is large enough for `growth`.
     EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth));
     // For (capacity+1) < kWidth, growth should equal capacity.
@@ -221,8 +309,8 @@
     SCOPED_TRACE(capacity);
     size_t growth = CapacityToGrowth(capacity);
     EXPECT_THAT(growth, Lt(capacity));
-    EXPECT_LE(GrowthToLowerboundCapacity(growth), capacity);
-    EXPECT_EQ(NormalizeCapacity(GrowthToLowerboundCapacity(growth)), capacity);
+    EXPECT_EQ(SizeToCapacity(growth), capacity);
+    EXPECT_EQ(NormalizeCapacity(SizeToCapacity(growth)), capacity);
   }
 }
 
@@ -533,8 +621,6 @@
 using IntPolicy = ValuePolicy<int64_t>;
 using Uint8Policy = ValuePolicy<uint8_t>;
 
-using TranferableIntPolicy = ValuePolicy<int64_t, /*kTransferable=*/true>;
-
 // For testing SOO.
 template <int N>
 class SizedValue {
@@ -573,6 +659,48 @@
 using SizedValuePolicy =
     ValuePolicy<SizedValue<N>, /*kTransferable=*/true, kSoo>;
 
+// Value is aligned as type T and contains N copies of it.
+template <typename T, int N>
+class AlignedValue {
+ public:
+  AlignedValue(int64_t v) {  // NOLINT
+    for (int i = 0; i < N; ++i) {
+      vals_[i] = v;
+      if (sizeof(T) < sizeof(int64_t)) {
+        v >>= (8 * sizeof(T));
+      } else {
+        v = 0;
+      }
+    }
+  }
+  AlignedValue() : AlignedValue(0) {}
+  AlignedValue(const AlignedValue&) = default;
+  AlignedValue& operator=(const AlignedValue&) = default;
+
+  int64_t operator*() const {
+    if (sizeof(T) == sizeof(int64_t)) {
+      return vals_[0];
+    }
+    int64_t result = 0;
+    for (int i = N - 1; i >= 0; --i) {
+      result <<= (8 * sizeof(T));
+      result += vals_[i];
+    }
+    return result;
+  }
+  explicit operator int() const { return **this; }
+  explicit operator int64_t() const { return **this; }
+
+  template <typename H>
+  friend H AbslHashValue(H h, AlignedValue sv) {
+    return H::combine(std::move(h), *sv);
+  }
+  bool operator==(const AlignedValue& rhs) const { return **this == *rhs; }
+
+ private:
+  T vals_[N];
+};
+
 class StringPolicy {
   template <class F, class K, class V,
             class = typename std::enable_if<
@@ -650,10 +778,11 @@
   using Base::Base;
 };
 
-template <typename T, bool kTransferable = false, bool kSoo = false>
+template <typename T, bool kTransferable = false, bool kSoo = false,
+          class Alloc = std::allocator<T>>
 struct ValueTable
     : raw_hash_set<ValuePolicy<T, kTransferable, kSoo>, hash_default_hash<T>,
-                   std::equal_to<T>, std::allocator<T>> {
+                   std::equal_to<T>, Alloc> {
   using Base = typename ValueTable::raw_hash_set;
   using Base::Base;
 };
@@ -663,11 +792,6 @@
 
 using TransferableIntTable = ValueTable<int64_t, /*kTransferable=*/true>;
 
-constexpr size_t kNonSooSize = sizeof(HeapOrSoo) + 8;
-static_assert(sizeof(SizedValue<kNonSooSize>) >= kNonSooSize, "too small");
-using NonSooIntTable = ValueTable<SizedValue<kNonSooSize>>;
-using SooIntTable = ValueTable<int64_t, /*kTransferable=*/true, /*kSoo=*/true>;
-
 template <typename T>
 struct CustomAlloc : std::allocator<T> {
   CustomAlloc() = default;
@@ -688,6 +812,50 @@
   using Base::Base;
 };
 
+template <typename T>
+struct ChangingSizeAndTrackingTypeAlloc : std::allocator<T> {
+  ChangingSizeAndTrackingTypeAlloc() = default;
+
+  template <typename U>
+  explicit ChangingSizeAndTrackingTypeAlloc(
+      const ChangingSizeAndTrackingTypeAlloc<U>& other) {
+    EXPECT_EQ(other.type_id,
+              ChangingSizeAndTrackingTypeAlloc<U>::ComputeTypeId());
+  }
+
+  template <class U>
+  struct rebind {
+    using other = ChangingSizeAndTrackingTypeAlloc<U>;
+  };
+
+  T* allocate(size_t n) {
+    EXPECT_EQ(type_id, ComputeTypeId());
+    return std::allocator<T>::allocate(n);
+  }
+
+  void deallocate(T* p, std::size_t n) {
+    EXPECT_EQ(type_id, ComputeTypeId());
+    return std::allocator<T>::deallocate(p, n);
+  }
+
+  static size_t ComputeTypeId() { return absl::HashOf(typeid(T).name()); }
+
+  // We add extra data to make the allocator size being changed.
+  // This also make type_id positioned differently, so that assertions in the
+  // allocator can catch bugs more likely.
+  char data_before[sizeof(T) * 3] = {0};
+  size_t type_id = ComputeTypeId();
+  char data_after[sizeof(T) * 5] = {0};
+};
+
+struct ChangingSizeAllocIntTable
+    : raw_hash_set<IntPolicy, hash_default_hash<int64_t>,
+                   std::equal_to<int64_t>,
+                   ChangingSizeAndTrackingTypeAlloc<int64_t>> {
+  using Base = typename ChangingSizeAllocIntTable::raw_hash_set;
+  using Base::Base;
+};
+
 struct MinimumAlignmentUint8Table
     : raw_hash_set<Uint8Policy, hash_default_hash<uint8_t>,
                    std::equal_to<uint8_t>, MinimumAlignmentAlloc<uint8_t>> {
@@ -741,28 +909,44 @@
   using Base::Base;
 };
 
-struct BadTable : raw_hash_set<IntPolicy, BadFastHash, std::equal_to<int>,
+struct BadTable : raw_hash_set<IntPolicy, BadFastHash, std::equal_to<int64_t>,
                                std::allocator<int>> {
   using Base = typename BadTable::raw_hash_set;
   BadTable() = default;
   using Base::Base;
 };
 
+constexpr size_t kNonSooSize = sizeof(HeapOrSoo) + 8;
+using NonSooIntTableSlotType = SizedValue<kNonSooSize>;
+static_assert(sizeof(NonSooIntTableSlotType) >= kNonSooSize, "too small");
+using NonSooIntTable = ValueTable<NonSooIntTableSlotType>;
+using SooInt32Table =
+    ValueTable<int32_t, /*kTransferable=*/true, /*kSoo=*/true>;
+using SooIntTable = ValueTable<int64_t, /*kTransferable=*/true, /*kSoo=*/true>;
+using NonMemcpyableSooIntTable =
+    ValueTable<int64_t, /*kTransferable=*/false, /*kSoo=*/true>;
+using MemcpyableSooIntCustomAllocTable =
+    ValueTable<int64_t, /*kTransferable=*/true, /*kSoo=*/true,
+               ChangingSizeAndTrackingTypeAlloc<int64_t>>;
+using NonMemcpyableSooIntCustomAllocTable =
+    ValueTable<int64_t, /*kTransferable=*/false, /*kSoo=*/true,
+               ChangingSizeAndTrackingTypeAlloc<int64_t>>;
+
 TEST(Table, EmptyFunctorOptimization) {
   static_assert(std::is_empty<std::equal_to<absl::string_view>>::value, "");
   static_assert(std::is_empty<std::allocator<int>>::value, "");
 
   struct MockTable {
+    size_t capacity;
+    uint64_t size;
     void* ctrl;
     void* slots;
-    size_t size;
-    size_t capacity;
   };
   struct StatelessHash {
     size_t operator()(absl::string_view) const { return 0; }
   };
   struct StatefulHash : StatelessHash {
-    size_t dummy;
+    uint64_t dummy;
   };
 
   struct GenerationData {
@@ -800,7 +984,10 @@
 template <class TableType>
 class SooTest : public testing::Test {};
 
-using SooTableTypes = ::testing::Types<SooIntTable, NonSooIntTable>;
+using SooTableTypes =
+    ::testing::Types<SooIntTable, NonSooIntTable, NonMemcpyableSooIntTable,
+                     MemcpyableSooIntCustomAllocTable,
+                     NonMemcpyableSooIntCustomAllocTable>;
 TYPED_TEST_SUITE(SooTest, SooTableTypes);
 
 TYPED_TEST(SooTest, Empty) {
@@ -809,6 +996,21 @@
   EXPECT_TRUE(t.empty());
 }
 
+TEST(Table, Prefetch) {
+  IntTable t;
+  t.emplace(1);
+  // Works for both present and absent keys.
+  t.prefetch(1);
+  t.prefetch(2);
+
+  static constexpr int size = 10;
+  for (int i = 0; i < size; ++i) t.insert(i);
+  for (int i = 0; i < size; ++i) {
+    t.prefetch(i);
+    ASSERT_TRUE(t.find(i) != t.end()) << i;
+  }
+}
+
 TYPED_TEST(SooTest, LookupEmpty) {
   TypeParam t;
   auto it = t.find(0);
@@ -939,8 +1141,41 @@
 template <class TableType>
 class SmallTableResizeTest : public testing::Test {};
 
-using SmallTableTypes =
-    ::testing::Types<IntTable, TransferableIntTable, SooIntTable>;
+using SmallTableTypes = ::testing::Types<
+    IntTable, TransferableIntTable, SooIntTable,
+    // int8
+    ValueTable<int8_t, /*kTransferable=*/true, /*kSoo=*/true>,
+    ValueTable<int8_t, /*kTransferable=*/false, /*kSoo=*/true>,
+    // int16
+    ValueTable<int16_t, /*kTransferable=*/true, /*kSoo=*/true>,
+    ValueTable<int16_t, /*kTransferable=*/false, /*kSoo=*/true>,
+    // int128
+    ValueTable<SizedValue<16>, /*kTransferable=*/true, /*kSoo=*/true>,
+    ValueTable<SizedValue<16>, /*kTransferable=*/false, /*kSoo=*/true>,
+    // int192
+    ValueTable<SizedValue<24>, /*kTransferable=*/true, /*kSoo=*/true>,
+    ValueTable<SizedValue<24>, /*kTransferable=*/false, /*kSoo=*/true>,
+    // Special tables.
+    MinimumAlignmentUint8Table, CustomAllocIntTable, ChangingSizeAllocIntTable,
+    BadTable,
+    // alignment 1, size 2.
+    ValueTable<AlignedValue<uint8_t, 2>, /*kTransferable=*/true, /*kSoo=*/true>,
+    ValueTable<AlignedValue<uint8_t, 2>, /*kTransferable=*/false,
+               /*kSoo=*/true>,
+    // alignment 1, size 7.
+    ValueTable<AlignedValue<uint8_t, 7>, /*kTransferable=*/true, /*kSoo=*/true>,
+    ValueTable<AlignedValue<uint8_t, 7>, /*kTransferable=*/false,
+               /*kSoo=*/true>,
+    // alignment 2, size 6.
+    ValueTable<AlignedValue<uint16_t, 3>, /*kTransferable=*/true,
+               /*kSoo=*/true>,
+    ValueTable<AlignedValue<uint16_t, 3>, /*kTransferable=*/false,
+               /*kSoo=*/true>,
+    // alignment 2, size 10.
+    ValueTable<AlignedValue<uint16_t, 5>, /*kTransferable=*/true,
+               /*kSoo=*/true>,
+    ValueTable<AlignedValue<uint16_t, 5>, /*kTransferable=*/false,
+               /*kSoo=*/true>>;
 TYPED_TEST_SUITE(SmallTableResizeTest, SmallTableTypes);
 
 TYPED_TEST(SmallTableResizeTest, InsertIntoSmallTable) {
@@ -959,6 +1194,9 @@
   for (size_t source_size = 0; source_size < 32; ++source_size) {
     for (size_t target_size = source_size; target_size < 32; ++target_size) {
       for (bool rehash : {false, true}) {
+        SCOPED_TRACE(absl::StrCat("source_size: ", source_size,
+                                  ", target_size: ", target_size,
+                                  ", rehash: ", rehash));
         TypeParam t;
         for (size_t i = 0; i < source_size; ++i) {
           t.insert(static_cast<int>(i));
@@ -978,6 +1216,7 @@
 }
 
 TYPED_TEST(SmallTableResizeTest, ResizeReduceSmallTables) {
+  DisableSampling();
   for (size_t source_size = 0; source_size < 32; ++source_size) {
     for (size_t target_size = 0; target_size <= source_size; ++target_size) {
       TypeParam t;
@@ -1281,7 +1520,7 @@
 };
 
 struct Modulo1000HashTable
-    : public raw_hash_set<IntPolicy, Modulo1000Hash, std::equal_to<int>,
+    : public raw_hash_set<IntPolicy, Modulo1000Hash, std::equal_to<int64_t>,
                           std::allocator<int>> {};
 
 // Test that rehash with no resize happen in case of many deleted slots.
@@ -1335,18 +1574,18 @@
 
 TYPED_TEST(SooTest, InsertEraseStressTest) {
   TypeParam t;
-  const size_t kMinElementCount = 250;
+  const size_t kMinElementCount = 50;
   std::deque<int> keys;
   size_t i = 0;
   for (; i < MaxDensitySize(kMinElementCount); ++i) {
-    t.emplace(i);
+    t.emplace(static_cast<int64_t>(i));
     keys.push_back(i);
   }
-  const size_t kNumIterations = 1000000;
+  const size_t kNumIterations = 20000;
   for (; i < kNumIterations; ++i) {
     ASSERT_EQ(1, t.erase(keys.front()));
     keys.pop_front();
-    t.emplace(i);
+    t.emplace(static_cast<int64_t>(i));
     keys.push_back(i);
   }
 }
@@ -1364,8 +1603,11 @@
 
 TYPED_TEST(SooTest, LargeTable) {
   TypeParam t;
-  for (int64_t i = 0; i != 100000; ++i) t.emplace(i << 40);
-  for (int64_t i = 0; i != 100000; ++i)
+  for (int64_t i = 0; i != 10000; ++i) {
+    t.emplace(i << 40);
+    ASSERT_EQ(t.size(), i + 1);
+  }
+  for (int64_t i = 0; i != 10000; ++i)
     ASSERT_EQ(i << 40, static_cast<int64_t>(*t.find(i << 40)));
 }
 
@@ -1696,8 +1938,7 @@
     const std::vector<int64_t>& keys, size_t num_iters) {
   ProbeStats stats;
 
-  std::random_device rd;
-  std::mt19937 rng(rd());
+  absl::InsecureBitGen rng;
   auto linear_transform = [](size_t x, size_t y) { return x * 17 + y * 13; };
   std::uniform_int_distribution<size_t> dist(0, keys.size() - 1);
   while (num_iters--) {
@@ -1963,6 +2204,43 @@
   }
 }
 
+TYPED_TEST(SooTest, CopyAssignment) {
+  std::vector<size_t> sizes = {0, 1, 7, 25};
+  for (size_t source_size : sizes) {
+    for (size_t target_size : sizes) {
+      SCOPED_TRACE(absl::StrCat("source_size: ", source_size,
+                                " target_size: ", target_size));
+      TypeParam source;
+      std::vector<int> source_elements;
+      for (size_t i = 0; i < source_size; ++i) {
+        source.emplace(static_cast<int>(i) * 2);
+        source_elements.push_back(static_cast<int>(i) * 2);
+      }
+      TypeParam target;
+      for (size_t i = 0; i < target_size; ++i) {
+        target.emplace(static_cast<int>(i) * 3);
+      }
+      target = source;
+      ASSERT_EQ(target.size(), source_size);
+      ASSERT_THAT(target, UnorderedElementsAreArray(source_elements));
+    }
+  }
+}
+
+TYPED_TEST(SooTest, CopyConstructWithSampling) {
+  SetSamplingRateTo1Percent();
+  for (int i = 0; i < 10000; ++i) {
+    TypeParam t;
+    t.emplace(0);
+    EXPECT_EQ(1, t.size());
+    {
+      TypeParam u(t);
+      EXPECT_EQ(1, u.size());
+      EXPECT_THAT(*u.find(0), 0);
+    }
+  }
+}
+
 TYPED_TEST(SooTest, CopyDifferentSizes) {
   TypeParam t;
 
@@ -2090,6 +2368,10 @@
   t.emplace("a", "b");
   EXPECT_EQ(1, t.size());
   t = std::move(*&t);
+  if (SwisstableGenerationsEnabled()) {
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    EXPECT_DEATH_IF_SUPPORTED(t.contains("a"), "self-move-assigned");
+  }
   // As long as we don't crash, it's fine.
 }
 
@@ -2146,7 +2428,7 @@
 
 TYPED_TEST(SooTest, ReplacingDeletedSlotDoesNotRehash) {
   // We need to disable hashtablez to avoid issues related to SOO and sampling.
-  SetHashtablezEnabled(false);
+  DisableSampling();
 
   size_t n;
   {
@@ -2429,8 +2711,9 @@
 }
 
 template <typename T>
-T MakeSimpleTable(size_t size) {
+T MakeSimpleTable(size_t size, bool do_reserve) {
   T t;
+  if (do_reserve) t.reserve(size);
   while (t.size() < size) t.insert(t.size());
   return t;
 }
@@ -2442,58 +2725,78 @@
   return res;
 }
 
-// These IterationOrderChanges tests depend on non-deterministic behavior.
-// We are injecting non-determinism from the pointer of the table, but do so in
-// a way that only the page matters. We have to retry enough times to make sure
-// we are touching different memory pages to cause the ordering to change.
-// We also need to keep the old tables around to avoid getting the same memory
-// blocks over and over.
-TYPED_TEST(SooTest, IterationOrderChangesByInstance) {
-  for (size_t size : {2, 6, 12, 20}) {
-    const auto reference_table = MakeSimpleTable<TypeParam>(size);
-    const auto reference = OrderOfIteration(reference_table);
+// Generate irrelevant seeds to avoid being stuck in the same last bit
+// in seed.
+void GenerateIrrelevantSeeds(int cnt) {
+  for (int i = cnt % 17; i > 0; --i) {
+    NextSeed();
+  }
+}
 
-    std::vector<TypeParam> tables;
-    bool found_difference = false;
-    for (int i = 0; !found_difference && i < 5000; ++i) {
-      tables.push_back(MakeSimpleTable<TypeParam>(size));
-      found_difference = OrderOfIteration(tables.back()) != reference;
-    }
-    if (!found_difference) {
-      FAIL()
-          << "Iteration order remained the same across many attempts with size "
-          << size;
+// These IterationOrderChanges tests depend on non-deterministic behavior.
+// We are injecting non-determinism to the table.
+// We have to retry enough times to make sure that the seed changes in bits that
+// matter for the iteration order.
+TYPED_TEST(SooTest, IterationOrderChangesByInstance) {
+  DisableSampling();  // We do not want test to pass only because of sampling.
+  for (bool do_reserve : {false, true}) {
+    for (size_t size : {2u, 6u, 12u, 20u}) {
+      SCOPED_TRACE(absl::StrCat("size: ", size, " do_reserve: ", do_reserve));
+      const auto reference_table = MakeSimpleTable<TypeParam>(size, do_reserve);
+      const auto reference = OrderOfIteration(reference_table);
+
+      bool found_difference = false;
+      for (int i = 0; !found_difference && i < 500; ++i) {
+        auto new_table = MakeSimpleTable<TypeParam>(size, do_reserve);
+        found_difference = OrderOfIteration(new_table) != reference;
+        GenerateIrrelevantSeeds(i);
+      }
+      if (!found_difference) {
+        FAIL() << "Iteration order remained the same across many attempts.";
+      }
     }
   }
 }
 
 TYPED_TEST(SooTest, IterationOrderChangesOnRehash) {
+  DisableSampling();  // We do not want test to pass only because of sampling.
+
   // We test different sizes with many small numbers, because small table
   // resize has a different codepath.
   // Note: iteration order for size() <= 1 is always the same.
-  for (size_t size : std::vector<size_t>{2, 3, 6, 7, 12, 15, 20, 50}) {
-    for (size_t rehash_size : {
-             size_t{0},  // Force rehash is guaranteed.
-             size * 10   // Rehash to the larger capacity is guaranteed.
-         }) {
-      std::vector<TypeParam> garbage;
-      bool ok = false;
-      for (int i = 0; i < 5000; ++i) {
-        auto t = MakeSimpleTable<TypeParam>(size);
-        const auto reference = OrderOfIteration(t);
-        // Force rehash.
-        t.rehash(rehash_size);
-        auto trial = OrderOfIteration(t);
-        if (trial != reference) {
-          // We are done.
-          ok = true;
-          break;
+  for (bool do_reserve : {false, true}) {
+    for (size_t size : {2u, 3u, 6u, 7u, 12u, 15u, 20u, 50u}) {
+      for (size_t rehash_size : {
+               size_t{0},        // Force rehash is guaranteed.
+               size * 10  // Rehash to the larger capacity is guaranteed.
+           }) {
+        SCOPED_TRACE(absl::StrCat("size: ", size, " rehash_size: ", rehash_size,
+                                  " do_reserve: ", do_reserve));
+        bool ok = false;
+        auto t = MakeSimpleTable<TypeParam>(size, do_reserve);
+        const size_t original_capacity = t.capacity();
+        auto reference = OrderOfIteration(t);
+        for (int i = 0; i < 500; ++i) {
+          if (i > 0 && rehash_size != 0) {
+            // Rehash back to original size.
+            t.rehash(0);
+            ASSERT_EQ(t.capacity(), original_capacity);
+            reference = OrderOfIteration(t);
+          }
+          // Force rehash.
+          t.rehash(rehash_size);
+          auto trial = OrderOfIteration(t);
+          if (trial != reference) {
+            // We are done.
+            ok = true;
+            break;
+          }
+          GenerateIrrelevantSeeds(i);
         }
-        garbage.push_back(std::move(t));
+        EXPECT_TRUE(ok)
+            << "Iteration order remained the same across many attempts " << size
+            << "->" << rehash_size << ".";
       }
-      EXPECT_TRUE(ok)
-          << "Iteration order remained the same across many attempts " << size
-          << "->" << rehash_size << ".";
     }
   }
 }
@@ -2502,7 +2805,7 @@
 // This prevents dependency on pointer stability on small tables.
 TYPED_TEST(SooTest, UnstablePointers) {
   // We need to disable hashtablez to avoid issues related to SOO and sampling.
-  SetHashtablezEnabled(false);
+  DisableSampling();
 
   TypeParam table;
 
@@ -2634,18 +2937,29 @@
 template <typename T>
 class RawHashSamplerTest : public testing::Test {};
 
-using RawHashSamplerTestTypes = ::testing::Types<SooIntTable, NonSooIntTable>;
+using RawHashSamplerTestTypes = ::testing::Types<
+    // 32 bits to make sure that table is Soo for 32 bits platform as well.
+    // 64 bits table is not SOO due to alignment.
+    SooInt32Table,
+    NonSooIntTable>;
 TYPED_TEST_SUITE(RawHashSamplerTest, RawHashSamplerTestTypes);
 
 TYPED_TEST(RawHashSamplerTest, Sample) {
-  constexpr bool soo_enabled = std::is_same<SooIntTable, TypeParam>::value;
+  constexpr bool soo_enabled = std::is_same<SooInt32Table, TypeParam>::value;
   // Enable the feature even if the prod default is off.
-  SetHashtablezEnabled(true);
-  SetHashtablezSampleParameter(100);  // Sample ~1% of tables.
+  SetSamplingRateTo1Percent();
+
+  ASSERT_EQ(TypeParam().capacity(), soo_enabled ? SooCapacity() : 0);
 
   auto& sampler = GlobalHashtablezSampler();
   size_t start_size = 0;
-  absl::flat_hash_set<const HashtablezInfo*> preexisting_info;
+
+  // Reserve these utility tables, so that if they sampled, they'll be
+  // preexisting.
+  absl::flat_hash_set<const HashtablezInfo*> preexisting_info(10);
+  absl::flat_hash_map<size_t, int> observed_checksums(10);
+  absl::flat_hash_map<ssize_t, int> reservations(10);
+
   start_size += sampler.Iterate([&](const HashtablezInfo& info) {
     preexisting_info.insert(&info);
     ++start_size;
@@ -2672,8 +2986,6 @@
     }
   }
   size_t end_size = 0;
-  absl::flat_hash_map<size_t, int> observed_checksums;
-  absl::flat_hash_map<ssize_t, int> reservations;
   end_size += sampler.Iterate([&](const HashtablezInfo& info) {
     ++end_size;
     if (preexisting_info.contains(&info)) return;
@@ -2710,25 +3022,25 @@
 }
 
 std::vector<const HashtablezInfo*> SampleSooMutation(
-    absl::FunctionRef<void(SooIntTable&)> mutate_table) {
+    absl::FunctionRef<void(SooInt32Table&)> mutate_table) {
   // Enable the feature even if the prod default is off.
-  SetHashtablezEnabled(true);
-  SetHashtablezSampleParameter(100);  // Sample ~1% of tables.
+  SetSamplingRateTo1Percent();
 
   auto& sampler = GlobalHashtablezSampler();
-  size_t start_size = 0;
-  absl::flat_hash_set<const HashtablezInfo*> preexisting_info;
+  int64_t start_size = 0;
+  // Reserve the table, so that if it sampled, it'll be preexisting.
+  absl::flat_hash_set<const HashtablezInfo*> preexisting_info(10);
   start_size += sampler.Iterate([&](const HashtablezInfo& info) {
     preexisting_info.insert(&info);
     ++start_size;
   });
 
-  std::vector<SooIntTable> tables;
+  std::vector<SooInt32Table> tables;
   for (int i = 0; i < 1000000; ++i) {
     tables.emplace_back();
     mutate_table(tables.back());
   }
-  size_t end_size = 0;
+  int64_t end_size = 0;
   std::vector<const HashtablezInfo*> infos;
   end_size += sampler.Iterate([&](const HashtablezInfo& info) {
     ++end_size;
@@ -2743,16 +3055,16 @@
 }
 
 TEST(RawHashSamplerTest, SooTableInsertToEmpty) {
-  if (SooIntTable().capacity() != SooCapacity()) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
     CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
     GTEST_SKIP() << "not SOO on this platform";
   }
   std::vector<const HashtablezInfo*> infos =
-      SampleSooMutation([](SooIntTable& t) { t.insert(1); });
+      SampleSooMutation([](SooInt32Table& t) { t.insert(1); });
 
   for (const HashtablezInfo* info : infos) {
     ASSERT_EQ(info->inline_element_size,
-              sizeof(typename SooIntTable::value_type));
+              sizeof(typename SooInt32Table::value_type));
     ASSERT_EQ(info->soo_capacity, SooCapacity());
     ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));
     ASSERT_EQ(info->size, 1);
@@ -2764,16 +3076,16 @@
 }
 
 TEST(RawHashSamplerTest, SooTableReserveToEmpty) {
-  if (SooIntTable().capacity() != SooCapacity()) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
     CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
     GTEST_SKIP() << "not SOO on this platform";
   }
   std::vector<const HashtablezInfo*> infos =
-      SampleSooMutation([](SooIntTable& t) { t.reserve(100); });
+      SampleSooMutation([](SooInt32Table& t) { t.reserve(100); });
 
   for (const HashtablezInfo* info : infos) {
     ASSERT_EQ(info->inline_element_size,
-              sizeof(typename SooIntTable::value_type));
+              sizeof(typename SooInt32Table::value_type));
     ASSERT_EQ(info->soo_capacity, SooCapacity());
     ASSERT_GE(info->capacity, 100);
     ASSERT_EQ(info->size, 0);
@@ -2787,19 +3099,19 @@
 // This tests that reserve on a full SOO table doesn't incorrectly result in new
 // (over-)sampling.
 TEST(RawHashSamplerTest, SooTableReserveToFullSoo) {
-  if (SooIntTable().capacity() != SooCapacity()) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
     CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
     GTEST_SKIP() << "not SOO on this platform";
   }
   std::vector<const HashtablezInfo*> infos =
-      SampleSooMutation([](SooIntTable& t) {
+      SampleSooMutation([](SooInt32Table& t) {
         t.insert(1);
         t.reserve(100);
       });
 
   for (const HashtablezInfo* info : infos) {
     ASSERT_EQ(info->inline_element_size,
-              sizeof(typename SooIntTable::value_type));
+              sizeof(typename SooInt32Table::value_type));
     ASSERT_EQ(info->soo_capacity, SooCapacity());
     ASSERT_GE(info->capacity, 100);
     ASSERT_EQ(info->size, 1);
@@ -2810,15 +3122,38 @@
   }
 }
 
+TEST(RawHashSamplerTest, SooTableSampleOnCopy) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
+    CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
+    GTEST_SKIP() << "not SOO on this platform";
+  }
+
+  SooInt32Table t_orig;
+  t_orig.insert(1);
+
+  std::vector<const HashtablezInfo*> infos =
+      SampleSooMutation([&t_orig](SooInt32Table& t) {
+        t = t_orig;
+      });
+
+  for (const HashtablezInfo* info : infos) {
+    ASSERT_EQ(info->inline_element_size,
+              sizeof(typename SooInt32Table::value_type));
+    ASSERT_EQ(info->soo_capacity, SooCapacity());
+    ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));
+    ASSERT_EQ(info->size, 1);
+  }
+}
+
 // This tests that rehash(0) on a sampled table with size that fits in SOO
 // doesn't incorrectly result in losing sampling.
 TEST(RawHashSamplerTest, SooTableRehashShrinkWhenSizeFitsInSoo) {
-  if (SooIntTable().capacity() != SooCapacity()) {
+  if (SooInt32Table().capacity() != SooCapacity()) {
     CHECK_LT(sizeof(void*), 8) << "missing SOO coverage";
     GTEST_SKIP() << "not SOO on this platform";
   }
   std::vector<const HashtablezInfo*> infos =
-      SampleSooMutation([](SooIntTable& t) {
+      SampleSooMutation([](SooInt32Table& t) {
         t.reserve(100);
         t.insert(1);
         EXPECT_GE(t.capacity(), 100);
@@ -2827,7 +3162,7 @@
 
   for (const HashtablezInfo* info : infos) {
     ASSERT_EQ(info->inline_element_size,
-              sizeof(typename SooIntTable::value_type));
+              sizeof(typename SooInt32Table::value_type));
     ASSERT_EQ(info->soo_capacity, SooCapacity());
     ASSERT_EQ(info->capacity, NextCapacity(SooCapacity()));
     ASSERT_EQ(info->size, 1);
@@ -2841,19 +3176,19 @@
 
 TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
   // Enable the feature even if the prod default is off.
-  SetHashtablezEnabled(true);
-  SetHashtablezSampleParameter(100);  // Sample ~1% of tables.
+  SetSamplingRateTo1Percent();
 
   auto& sampler = GlobalHashtablezSampler();
-  size_t start_size = 0;
+  int64_t start_size = 0;
   start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });
 
   std::vector<CustomAllocIntTable> tables;
-  for (int i = 0; i < 1000000; ++i) {
+  for (int i = 0; i < 100000; ++i) {
     tables.emplace_back();
     tables.back().insert(1);
+    tables.push_back(tables.back());  // Copies the table.
   }
-  size_t end_size = 0;
+  int64_t end_size = 0;
   end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; });
 
   EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
@@ -2885,6 +3220,20 @@
   }
 }
 
+TYPED_TEST(SanitizerTest, PoisoningUnusedOnGrowth) {
+  TypeParam t;
+  for (int64_t i = 0; i < 100; ++i) {
+    t.insert(i);
+
+    int64_t* slots = RawHashSetTestOnlyAccess::GetSlots(t);
+    int poisoned = 0;
+    for (size_t i = 0; i < t.capacity(); ++i) {
+      poisoned += static_cast<int>(__asan_address_is_poisoned(slots + i));
+    }
+    ASSERT_EQ(poisoned, t.capacity() - t.size());
+  }
+}
+
 // TODO(b/289225379): poison inline space when empty SOO.
 TEST(Sanitizer, PoisoningOnErase) {
   NonSooIntTable t;
@@ -2907,28 +3256,27 @@
   // first slot when alignof(value_type) is 1. We test repeated
   // insertions/erases and verify that the behavior is correct.
   TypeParam t;
-  std::unordered_set<uint8_t> verifier;  // NOLINT
+  std::bitset<256> verifier;
 
   // Do repeated insertions/erases from the table.
-  for (int64_t i = 0; i < 100000; ++i) {
+  for (int64_t i = 0; i < 10000; ++i) {
     SCOPED_TRACE(i);
     const uint8_t u = (i * -i) & 0xFF;
     auto it = t.find(u);
-    auto verifier_it = verifier.find(u);
     if (it == t.end()) {
-      ASSERT_EQ(verifier_it, verifier.end());
+      ASSERT_FALSE(verifier.test(u));
       t.insert(u);
-      verifier.insert(u);
+      verifier.set(u);
     } else {
-      ASSERT_NE(verifier_it, verifier.end());
+      ASSERT_TRUE(verifier.test(u));
       t.erase(it);
-      verifier.erase(verifier_it);
+      verifier.reset(u);
     }
   }
 
-  EXPECT_EQ(t.size(), verifier.size());
+  EXPECT_EQ(t.size(), verifier.count());
   for (uint8_t u : t) {
-    EXPECT_EQ(verifier.count(u), 1);
+    ASSERT_TRUE(verifier.test(u));
   }
 }
 
@@ -3351,16 +3699,16 @@
     t.insert(1);
     EXPECT_EQ(HashCount(t), 1);
     t.erase(1);
-    EXPECT_EQ(HashCount(t), 2);
+    EXPECT_LE(HashCount(t), 2);
   }
   {
     Table t;
     t.insert(3);
     EXPECT_EQ(HashCount(t), 1);
     auto node = t.extract(3);
-    EXPECT_EQ(HashCount(t), 2);
+    EXPECT_LE(HashCount(t), 2);
     t.insert(std::move(node));
-    EXPECT_EQ(HashCount(t), 3);
+    EXPECT_LE(HashCount(t), 3);
   }
   {
     Table t;
@@ -3379,22 +3727,22 @@
 // IterateOverFullSlots doesn't support SOO.
 TEST(Table, IterateOverFullSlotsEmpty) {
   NonSooIntTable t;
-  auto fail_if_any = [](const ctrl_t*, auto* i) {
-    FAIL() << "expected no slots " << **i;
+  using SlotType = NonSooIntTableSlotType;
+  auto fail_if_any = [](const ctrl_t*, void* i) {
+    FAIL() << "expected no slots " << **static_cast<SlotType*>(i);
   };
   container_internal::IterateOverFullSlots(
-      RawHashSetTestOnlyAccess::GetCommon(t),
-      RawHashSetTestOnlyAccess::GetSlots(t), fail_if_any);
+      RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType), fail_if_any);
   for (size_t i = 0; i < 256; ++i) {
     t.reserve(i);
     container_internal::IterateOverFullSlots(
-        RawHashSetTestOnlyAccess::GetCommon(t),
-        RawHashSetTestOnlyAccess::GetSlots(t), fail_if_any);
+        RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType), fail_if_any);
   }
 }
 
 TEST(Table, IterateOverFullSlotsFull) {
   NonSooIntTable t;
+  using SlotType = NonSooIntTableSlotType;
 
   std::vector<int64_t> expected_slots;
   for (int64_t idx = 0; idx < 128; ++idx) {
@@ -3403,9 +3751,9 @@
 
     std::vector<int64_t> slots;
     container_internal::IterateOverFullSlots(
-        RawHashSetTestOnlyAccess::GetCommon(t),
-        RawHashSetTestOnlyAccess::GetSlots(t),
-        [&t, &slots](const ctrl_t* ctrl, auto* i) {
+        RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType),
+        [&t, &slots](const ctrl_t* ctrl, void* slot) {
+          SlotType* i = static_cast<SlotType*>(slot);
           ptrdiff_t ctrl_offset =
               ctrl - RawHashSetTestOnlyAccess::GetCommon(t).control();
           ptrdiff_t slot_offset = i - RawHashSetTestOnlyAccess::GetSlots(t);
@@ -3424,16 +3772,16 @@
     if (reserve_size == -1) reserve_size = size;
     for (int64_t idx = 0; idx < size; ++idx) {
       NonSooIntTable t;
+      using SlotType = NonSooIntTableSlotType;
       t.reserve(static_cast<size_t>(reserve_size));
       for (int val = 0; val <= idx; ++val) {
         t.insert(val);
       }
 
       container_internal::IterateOverFullSlots(
-          RawHashSetTestOnlyAccess::GetCommon(t),
-          RawHashSetTestOnlyAccess::GetSlots(t),
-          [&t](const ctrl_t*, auto* i) {
-            int64_t value = **i;
+          RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType),
+          [&t](const ctrl_t*, void* slot) {
+            int64_t value = **static_cast<SlotType*>(slot);
             // Erase the other element from 2*k and 2*k+1 pair.
             t.erase(value ^ 1);
           });
@@ -3459,16 +3807,16 @@
     int64_t size = reserve_size / size_divisor;
     for (int64_t idx = 1; idx <= size; ++idx) {
       NonSooIntTable t;
+      using SlotType = NonSooIntTableSlotType;
       t.reserve(static_cast<size_t>(reserve_size));
       for (int val = 1; val <= idx; ++val) {
         t.insert(val);
       }
 
       container_internal::IterateOverFullSlots(
-          RawHashSetTestOnlyAccess::GetCommon(t),
-          RawHashSetTestOnlyAccess::GetSlots(t),
-          [&t](const ctrl_t*, auto* i) {
-            int64_t value = **i;
+          RawHashSetTestOnlyAccess::GetCommon(t), sizeof(SlotType),
+          [&t](const ctrl_t*, void* slot) {
+            int64_t value = **static_cast<SlotType*>(slot);
             t.insert(-value);
           });
     }
@@ -3531,7 +3879,7 @@
 
   // We disable hashtablez sampling for this test to ensure that the table isn't
   // sampled. When the table is sampled, it won't rehash down to SOO.
-  SetHashtablezEnabled(false);
+  DisableSampling();
 
   t.reserve(100);
   t.insert(0);
@@ -3547,7 +3895,7 @@
 }
 
 TEST(Table, ReserveToNonSoo) {
-  for (int reserve_capacity : {8, 100000}) {
+  for (size_t reserve_capacity : {2u, 8u, 100000u}) {
     SooIntTable t;
     t.insert(0);
 
@@ -3594,6 +3942,328 @@
                             "hash/eq functors are inconsistent.");
 }
 
+struct ConstructCaller {
+  explicit ConstructCaller(int v) : val(v) {}
+  ConstructCaller(int v, absl::FunctionRef<void()> func) : val(v) { func(); }
+  template <typename H>
+  friend H AbslHashValue(H h, const ConstructCaller& d) {
+    return H::combine(std::move(h), d.val);
+  }
+  bool operator==(const ConstructCaller& c) const { return val == c.val; }
+
+  int val;
+};
+
+struct DestroyCaller {
+  explicit DestroyCaller(int v) : val(v) {}
+  DestroyCaller(int v, absl::FunctionRef<void()> func)
+      : val(v), destroy_func(func) {}
+  DestroyCaller(DestroyCaller&& that)
+      : val(that.val), destroy_func(std::move(that.destroy_func)) {
+    that.Deactivate();
+  }
+  ~DestroyCaller() {
+    if (destroy_func) (*destroy_func)();
+  }
+  void Deactivate() { destroy_func = absl::nullopt; }
+
+  template <typename H>
+  friend H AbslHashValue(H h, const DestroyCaller& d) {
+    return H::combine(std::move(h), d.val);
+  }
+  bool operator==(const DestroyCaller& d) const { return val == d.val; }
+
+  int val;
+  absl::optional<absl::FunctionRef<void()>> destroy_func;
+};
+
+TEST(Table, ReentrantCallsFail) {
+#ifdef NDEBUG
+  GTEST_SKIP() << "Reentrant checks only enabled in debug mode.";
+#else
+  {
+    ValueTable<ConstructCaller> t;
+    t.insert(ConstructCaller{0});
+    auto erase_begin = [&] { t.erase(t.begin()); };
+    EXPECT_DEATH_IF_SUPPORTED(t.emplace(1, erase_begin), "");
+  }
+  {
+    ValueTable<DestroyCaller> t;
+    t.insert(DestroyCaller{0});
+    auto find_0 = [&] { t.find(DestroyCaller{0}); };
+    t.insert(DestroyCaller{1, find_0});
+    for (int i = 10; i < 20; ++i) t.insert(DestroyCaller{i});
+    EXPECT_DEATH_IF_SUPPORTED(t.clear(), "");
+    for (auto& elem : t) elem.Deactivate();
+  }
+  {
+    ValueTable<DestroyCaller> t;
+    t.insert(DestroyCaller{0});
+    auto insert_1 = [&] { t.insert(DestroyCaller{1}); };
+    t.insert(DestroyCaller{1, insert_1});
+    for (int i = 10; i < 20; ++i) t.insert(DestroyCaller{i});
+    EXPECT_DEATH_IF_SUPPORTED(t.clear(), "");
+    for (auto& elem : t) elem.Deactivate();
+  }
+#endif
+}
+
+// TODO(b/328794765): this check is very useful to run with ASAN in opt mode.
+TEST(Table, DestroyedCallsFail) {
+#ifdef NDEBUG
+  ASSERT_EQ(SwisstableAssertAccessToDestroyedTable(),
+            SwisstableGenerationsEnabled());
+#else
+  ASSERT_TRUE(SwisstableAssertAccessToDestroyedTable());
+#endif
+  if (!SwisstableAssertAccessToDestroyedTable()) {
+    GTEST_SKIP() << "Validation not enabled.";
+  }
+#if !defined(__clang__) && defined(__GNUC__)
+  GTEST_SKIP() << "Flaky on GCC.";
+#endif
+  absl::optional<IntTable> t;
+  t.emplace({1});
+  IntTable* t_ptr = &*t;
+  EXPECT_TRUE(t_ptr->contains(1));
+  t.reset();
+  std::string expected_death_message =
+#if defined(ABSL_HAVE_MEMORY_SANITIZER)
+      "use-of-uninitialized-value";
+#else
+      "destroyed hash table";
+#endif
+  EXPECT_DEATH_IF_SUPPORTED(t_ptr->contains(1), expected_death_message);
+}
+
+TEST(Table, DestroyedCallsFailDuringDestruction) {
+  if (!SwisstableAssertAccessToDestroyedTable()) {
+    GTEST_SKIP() << "Validation not enabled.";
+  }
+#if !defined(__clang__) && defined(__GNUC__)
+  GTEST_SKIP() << "Flaky on GCC.";
+#endif
+  // When EXPECT_DEATH_IF_SUPPORTED is not executed, the code after it is not
+  // executed as well.
+  // We need to destruct the table correctly in such a case.
+  // Must be defined before the table for correct destruction order.
+  bool do_lookup = false;
+
+  using Table = absl::flat_hash_map<int, std::shared_ptr<int>>;
+  absl::optional<Table> t = Table();
+  Table* t_ptr = &*t;
+  auto destroy = [&](int* ptr) {
+    if (do_lookup) {
+      ASSERT_TRUE(t_ptr->contains(*ptr));
+    }
+    delete ptr;
+  };
+  t->insert({0, std::shared_ptr<int>(new int(0), destroy)});
+  auto destroy_with_lookup = [&] {
+    do_lookup = true;
+    t.reset();
+  };
+  std::string expected_death_message =
+#ifdef NDEBUG
+      "destroyed hash table";
+#else
+      "Reentrant container access";
+#endif
+  EXPECT_DEATH_IF_SUPPORTED(destroy_with_lookup(), expected_death_message);
+}
+
+TEST(Table, MovedFromCallsFail) {
+  if (!SwisstableGenerationsEnabled()) {
+    GTEST_SKIP() << "Moved-from checks only enabled in sanitizer mode.";
+    return;
+  }
+
+  {
+    ABSL_ATTRIBUTE_UNUSED IntTable t1, t2, t3;
+    t1.insert(1);
+    t2 = std::move(t1);
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    EXPECT_DEATH_IF_SUPPORTED(t1.contains(1), "moved-from");
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    EXPECT_DEATH_IF_SUPPORTED(t1.swap(t3), "moved-from");
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    EXPECT_DEATH_IF_SUPPORTED(t1.merge(t3), "moved-from");
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    EXPECT_DEATH_IF_SUPPORTED(IntTable{t1}, "moved-from");
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    EXPECT_DEATH_IF_SUPPORTED(t1.begin(), "moved-from");
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    EXPECT_DEATH_IF_SUPPORTED(t1.end(), "moved-from");
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    EXPECT_DEATH_IF_SUPPORTED(t1.size(), "moved-from");
+  }
+  {
+    ABSL_ATTRIBUTE_UNUSED IntTable t1;
+    t1.insert(1);
+    ABSL_ATTRIBUTE_UNUSED IntTable t2(std::move(t1));
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    EXPECT_DEATH_IF_SUPPORTED(t1.contains(1), "moved-from");
+    t1.clear();  // Clearing a moved-from table is allowed.
+  }
+  {
+    // Test that using a table (t3) that was moved-to from a moved-from table
+    // (t1) fails.
+    ABSL_ATTRIBUTE_UNUSED IntTable t1, t2, t3;
+    t1.insert(1);
+    t2 = std::move(t1);
+    // NOLINTNEXTLINE(bugprone-use-after-move)
+    t3 = std::move(t1);
+    EXPECT_DEATH_IF_SUPPORTED(t3.contains(1), "moved-from");
+  }
+}
+
+TEST(HashtableSize, GenerateNewSeedDoesntChangeSize) {
+  size_t size = 1;
+  do {
+    HashtableSize hs(no_seed_empty_tag_t{});
+    hs.increment_size(size);
+    EXPECT_EQ(hs.size(), size);
+    hs.generate_new_seed();
+    EXPECT_EQ(hs.size(), size);
+    size = size * 2 + 1;
+  } while (size < MaxValidSizeFor1ByteSlot());
+}
+
+TEST(Table, MaxValidSize) {
+  IntTable t;
+  EXPECT_EQ(MaxValidSize(sizeof(IntTable::value_type)), t.max_size());
+  if constexpr (sizeof(size_t) == 8) {
+    for (size_t i = 0; i < 35; ++i) {
+      SCOPED_TRACE(i);
+      size_t slot_size = size_t{1} << i;
+      size_t max_size = MaxValidSize(slot_size);
+      ASSERT_FALSE(IsAboveValidSize(max_size, slot_size));
+      ASSERT_TRUE(IsAboveValidSize(max_size + 1, slot_size));
+      ASSERT_LT(max_size, uint64_t{1} << 60);
+      // For non gigantic slot sizes we expect max size to be at least 2^40.
+      if (i <= 22) {
+        ASSERT_FALSE(IsAboveValidSize(size_t{1} << 40, slot_size));
+        ASSERT_GE(max_size, uint64_t{1} << 40);
+      }
+      ASSERT_LT(SizeToCapacity(max_size),
+                uint64_t{1} << HashtableSize::kSizeBitCount);
+      ASSERT_LT(absl::uint128(max_size) * slot_size, uint64_t{1} << 63);
+    }
+  }
+  EXPECT_LT(MaxValidSize</*kSizeOfSizeT=*/4>(1), 1 << 30);
+  EXPECT_LT(MaxValidSize</*kSizeOfSizeT=*/4>(2), 1 << 29);
+  for (size_t i = 0; i < 29; ++i) {
+    size_t slot_size = size_t{1} << i;
+    size_t max_size = MaxValidSize</*kSizeOfSizeT=*/4>(slot_size);
+    ASSERT_FALSE(IsAboveValidSize</*kSizeOfSizeT=*/4>(max_size, slot_size));
+    ASSERT_TRUE(IsAboveValidSize</*kSizeOfSizeT=*/4>(max_size + 1, slot_size));
+    ASSERT_LT(max_size, 1 << 30);
+    size_t max_capacity = SizeToCapacity(max_size);
+    ASSERT_LT(max_capacity, (size_t{1} << 31) / slot_size);
+    ASSERT_GT(max_capacity, (1 << 29) / slot_size);
+    ASSERT_LT(max_capacity * slot_size, size_t{1} << 31);
+  }
+}
+
+TEST(Table, MaxSizeOverflow) {
+  size_t overflow = (std::numeric_limits<size_t>::max)();
+  EXPECT_DEATH_IF_SUPPORTED(IntTable t(overflow), "Hash table size overflow");
+  IntTable t;
+  EXPECT_DEATH_IF_SUPPORTED(t.reserve(overflow), "Hash table size overflow");
+  EXPECT_DEATH_IF_SUPPORTED(t.rehash(overflow), "Hash table size overflow");
+  size_t slightly_overflow = MaxValidSize(sizeof(IntTable::value_type)) + 1;
+  size_t slightly_overflow_capacity =
+      NextCapacity(NormalizeCapacity(slightly_overflow));
+  EXPECT_DEATH_IF_SUPPORTED(IntTable t2(slightly_overflow_capacity - 10),
+                            "Hash table size overflow");
+  EXPECT_DEATH_IF_SUPPORTED(t.reserve(slightly_overflow),
+                            "Hash table size overflow");
+  EXPECT_DEATH_IF_SUPPORTED(t.rehash(slightly_overflow),
+                            "Hash table size overflow");
+  IntTable non_empty_table;
+  non_empty_table.insert(0);
+  EXPECT_DEATH_IF_SUPPORTED(non_empty_table.reserve(slightly_overflow),
+                            "Hash table size overflow");
+}
+
+// TODO(b/397453582): Remove support for const hasher and remove this test.
+TEST(Table, ConstLambdaHash) {
+  int64_t multiplier = 17;
+  // Make sure that code compiles and work OK with non-empty hasher with const
+  // qualifier.
+  const auto hash = [multiplier](SizedValue<64> value) -> size_t {
+    return static_cast<size_t>(static_cast<int64_t>(value) * multiplier);
+  };
+  static_assert(!std::is_empty_v<decltype(hash)>);
+  absl::flat_hash_set<SizedValue<64>, decltype(hash)> t(0, hash);
+  t.insert(1);
+  EXPECT_EQ(t.size(), 1);
+  EXPECT_EQ(t.find(1), t.begin());
+  EXPECT_EQ(t.find(2), t.end());
+  t.insert(2);
+  EXPECT_EQ(t.size(), 2);
+  EXPECT_NE(t.find(1), t.end());
+  EXPECT_NE(t.find(2), t.end());
+  EXPECT_EQ(t.find(3), t.end());
+}
+
+struct ConstUint8Hash {
+  size_t operator()(uint8_t) const { return *value; }
+  size_t* value;
+};
+
+// This test is imitating growth of a very big table and triggers all buffer
+// overflows.
+// We try to insert all elements into the first probe group.
+// So the resize codepath in test does the following:
+// 1. Insert 16 elements into the first probe group. No other elements will be
+//    inserted into the first probe group.
+// 2. There will be enough elements to fill up the local buffer even for
+//    encoding with 4 bytes.
+// 3. After local buffer is full, we will fill up the control buffer till
+//    some point.
+// 4. Then a few times we will extend control buffer end.
+// 5. Finally we will catch up and go to overflow codepath.
+TEST(Table, GrowExtremelyLargeTable) {
+  constexpr size_t kTargetCapacity =
+#if defined(__wasm__) || defined(__asmjs__)
+      NextCapacity(ProbedItem4Bytes::kMaxNewCapacity);  // OOMs on WASM.
+#else
+      NextCapacity(ProbedItem8Bytes::kMaxNewCapacity);
+#endif
+
+  size_t hash = 0;
+  // In order to save memory we use 1 byte slot.
+  // There are not enough different values to achieve big capacity, so we
+  // artificially update growth info to force resize.
+  absl::flat_hash_set<uint8_t, ConstUint8Hash> t(63, ConstUint8Hash{&hash});
+  CommonFields& common = RawHashSetTestOnlyAccess::GetCommon(t);
+  // Set 0 seed so that H1 is always 0.
+  common.set_no_seed_for_testing();
+  ASSERT_EQ(H1(t.hash_function()(75), common.seed()), 0);
+  uint8_t inserted_till = 210;
+  for (uint8_t i = 0; i < inserted_till; ++i) {
+    t.insert(i);
+  }
+  for (uint8_t i = 0; i < inserted_till; ++i) {
+    ASSERT_TRUE(t.contains(i));
+  }
+
+  for (size_t cap = t.capacity(); cap < kTargetCapacity;
+       cap = NextCapacity(cap)) {
+    ASSERT_EQ(t.capacity(), cap);
+    // Update growth info to force resize on the next insert.
+    common.growth_info().OverwriteManyEmptyAsFull(CapacityToGrowth(cap) -
+                                                  t.size());
+    t.insert(inserted_till++);
+    ASSERT_EQ(t.capacity(), NextCapacity(cap));
+    for (uint8_t i = 0; i < inserted_till; ++i) {
+      ASSERT_TRUE(t.contains(i));
+    }
+  }
+  EXPECT_EQ(t.capacity(), kTargetCapacity);
+}
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index 5615e49..8aed18b 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -99,6 +99,11 @@
 // In most cases `T` needs only to provide the `absl_container_hash`. In this
 // case `std::equal_to<void>` will be used instead of `eq` part.
 //
+// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:
+//  * Iteration takes O(capacity) time, not O(size).
+//  * erase() slows down begin() and ++iterator.
+//  * Capacity only shrinks on rehash() or clear() -- not on erase().
+//
 // Example:
 //
 //   // Create a node hash map of three strings (that map to strings)
@@ -120,7 +125,7 @@
 template <class Key, class Value, class Hash = DefaultHashContainerHash<Key>,
           class Eq = DefaultHashContainerEq<Key>,
           class Alloc = std::allocator<std::pair<const Key, Value>>>
-class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_map
+class ABSL_ATTRIBUTE_OWNER node_hash_map
     : public absl::container_internal::raw_hash_map<
           absl::container_internal::NodeHashMapPolicy<Key, Value>, Hash, Eq,
           Alloc> {
@@ -236,8 +241,13 @@
   //   Erases the element at `position` of the `node_hash_map`, returning
   //   `void`.
   //
-  //   NOTE: this return behavior is different than that of STL containers in
-  //   general and `std::unordered_map` in particular.
+  //   NOTE: Returning `void` in this case is different than that of STL
+  //   containers in general and `std::unordered_map` in particular (which
+  //   return an iterator to the element following the erased element). If that
+  //   iterator is needed, simply post increment the iterator:
+  //
+  //     map.erase(it++);
+  //
   //
   // iterator erase(const_iterator first, const_iterator last):
   //
@@ -417,8 +427,7 @@
   // node_hash_map::swap(node_hash_map& other)
   //
   // Exchanges the contents of this `node_hash_map` with those of the `other`
-  // node hash map, avoiding invocation of any move, copy, or swap operations on
-  // individual elements.
+  // node hash map.
   //
   // All iterators and references on the `node_hash_map` remain valid, excepting
   // for the past-the-end iterator, which is invalidated.
@@ -558,6 +567,21 @@
   return container_internal::EraseIf(pred, &c);
 }
 
+// swap(node_hash_map<>, node_hash_map<>)
+//
+// Swaps the contents of two `node_hash_map` containers.
+//
+// NOTE: we need to define this function template in order for
+// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we
+// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a
+// derived-to-base conversion, whereas `std::swap` is a function template so
+// `std::swap` will be preferred by compiler.
+template <typename K, typename V, typename H, typename E, typename A>
+void swap(node_hash_map<K, V, H, E, A>& x,
+          node_hash_map<K, V, H, E, A>& y) noexcept(noexcept(x.swap(y))) {
+  return x.swap(y);
+}
+
 namespace container_internal {
 
 // c_for_each_fast(node_hash_map<>, Function)
diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc
index 4ad5d0d..c67d81f 100644
--- a/absl/container/node_hash_map_test.cc
+++ b/absl/container/node_hash_map_test.cc
@@ -322,8 +322,6 @@
   }
 }
 
-// This test requires std::launder for mutable key access in node handles.
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
 TEST(NodeHashMap, NodeHandleMutableKeyAccess) {
   node_hash_map<std::string, std::string> map;
 
@@ -335,7 +333,6 @@
 
   EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
 }
-#endif
 
 TEST(NodeHashMap, RecursiveTypeCompiles) {
   struct RecursiveType {
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index 53435ae..6240e2d 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -97,6 +97,11 @@
 // In most cases `T` needs only to provide the `absl_container_hash`. In this
 // case `std::equal_to<void>` will be used instead of `eq` part.
 //
+// PERFORMANCE WARNING: Erasure & sparsity can negatively affect performance:
+//  * Iteration takes O(capacity) time, not O(size).
+//  * erase() slows down begin() and ++iterator.
+//  * Capacity only shrinks on rehash() or clear() -- not on erase().
+//
 // Example:
 //
 //   // Create a node hash set of three strings
@@ -115,7 +120,7 @@
 //  }
 template <class T, class Hash = DefaultHashContainerHash<T>,
           class Eq = DefaultHashContainerEq<T>, class Alloc = std::allocator<T>>
-class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_set
+class ABSL_ATTRIBUTE_OWNER node_hash_set
     : public absl::container_internal::raw_hash_set<
           absl::container_internal::NodeHashSetPolicy<T>, Hash, Eq, Alloc> {
   using Base = typename node_hash_set::raw_hash_set;
@@ -230,8 +235,13 @@
   //   Erases the element at `position` of the `node_hash_set`, returning
   //   `void`.
   //
-  //   NOTE: this return behavior is different than that of STL containers in
-  //   general and `std::unordered_set` in particular.
+  //   NOTE: Returning `void` in this case is different than that of STL
+  //   containers in general and `std::unordered_map` in particular (which
+  //   return an iterator to the element following the erased element). If that
+  //   iterator is needed, simply post increment the iterator:
+  //
+  //     map.erase(it++);
+  //
   //
   // iterator erase(const_iterator first, const_iterator last):
   //
@@ -349,8 +359,7 @@
   // node_hash_set::swap(node_hash_set& other)
   //
   // Exchanges the contents of this `node_hash_set` with those of the `other`
-  // node hash set, avoiding invocation of any move, copy, or swap operations on
-  // individual elements.
+  // node hash set.
   //
   // All iterators and references on the `node_hash_set` remain valid, excepting
   // for the past-the-end iterator, which is invalidated.
@@ -467,6 +476,21 @@
   return container_internal::EraseIf(pred, &c);
 }
 
+// swap(node_hash_set<>, node_hash_set<>)
+//
+// Swaps the contents of two `node_hash_set` containers.
+//
+// NOTE: we need to define this function template in order for
+// `flat_hash_set::swap` to be called instead of `std::swap`. Even though we
+// have `swap(raw_hash_set&, raw_hash_set&)` defined, that function requires a
+// derived-to-base conversion, whereas `std::swap` is a function template so
+// `std::swap` will be preferred by compiler.
+template <typename T, typename H, typename E, typename A>
+void swap(node_hash_set<T, H, E, A>& x,
+          node_hash_set<T, H, E, A>& y) noexcept(noexcept(x.swap(y))) {
+  return x.swap(y);
+}
+
 namespace container_internal {
 
 // c_for_each_fast(node_hash_set<>, Function)
diff --git a/absl/container/sample_element_size_test.cc b/absl/container/sample_element_size_test.cc
index 22470b4..ccc616f 100644
--- a/absl/container/sample_element_size_test.cc
+++ b/absl/container/sample_element_size_test.cc
@@ -21,6 +21,7 @@
 #include "gtest/gtest.h"
 #include "absl/container/flat_hash_map.h"
 #include "absl/container/flat_hash_set.h"
+#include "absl/container/internal/hashtablez_sampler.h"
 #include "absl/container/node_hash_map.h"
 #include "absl/container/node_hash_set.h"
 
@@ -46,6 +47,7 @@
     std::vector<Table>& tables,
     const std::vector<typename Table::value_type>& values,
     size_t expected_element_size) {
+  EXPECT_GT(values.size(), 0);
   for (int i = 0; i < 10; ++i) {
     // We create a new table and must store it somewhere so that when we store
     // a pointer to the resulting `HashtablezInfo` into `preexisting_info`
@@ -82,6 +84,7 @@
   // Enable sampling even if the prod default is off.
   SetHashtablezEnabled(true);
   SetHashtablezSampleParameter(1);
+  TestOnlyRefreshSamplingStateForCurrentThread();
 
   auto& sampler = GlobalHashtablezSampler();
   std::vector<flat_hash_map<int, bigstruct>> flat_map_tables;
@@ -92,14 +95,6 @@
   std::vector<std::pair<const int, bigstruct>> map_values = {{0, bigstruct{}},
                                                              {1, bigstruct{}}};
 
-  // It takes thousands of new tables after changing the sampling parameters
-  // before you actually get some instrumentation.  And if you must actually
-  // put something into those tables.
-  for (int i = 0; i < 10000; ++i) {
-    flat_map_tables.emplace_back();
-    flat_map_tables.back()[i] = bigstruct{};
-  }
-
   // clang-tidy gives a false positive on this declaration.  This unordered set
   // cannot be a flat_hash_set, however, since that would introduce a mutex
   // deadlock.
diff --git a/absl/copts/AbseilConfigureCopts.cmake b/absl/copts/AbseilConfigureCopts.cmake
index a618199..f1d8b26 100644
--- a/absl/copts/AbseilConfigureCopts.cmake
+++ b/absl/copts/AbseilConfigureCopts.cmake
@@ -71,7 +71,7 @@
 endif()
 
 
-if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "QCC")
   set(ABSL_DEFAULT_COPTS "${ABSL_GCC_FLAGS}")
   set(ABSL_TEST_COPTS "${ABSL_GCC_TEST_FLAGS}")
 elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")  # MATCHES so we get both Clang and AppleClang
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake
index da2282f..7d8af92 100644
--- a/absl/copts/GENERATED_AbseilCopts.cmake
+++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -23,6 +23,7 @@
     "-Wno-implicit-int-conversion"
     "-Wno-missing-prototypes"
     "-Wno-missing-variable-declarations"
+    "-Wno-nullability-completeness"
     "-Wno-shadow"
     "-Wno-shorten-64-to-32"
     "-Wno-sign-compare"
@@ -97,6 +98,7 @@
     "-Winvalid-constexpr"
     "-Wliteral-conversion"
     "-Wmissing-declarations"
+    "-Wnullability-completeness"
     "-Woverlength-strings"
     "-Wpointer-arith"
     "-Wself-assign"
@@ -106,6 +108,7 @@
     "-Wstring-conversion"
     "-Wtautological-overlap-compare"
     "-Wtautological-unsigned-zero-compare"
+    "-Wthread-safety"
     "-Wundef"
     "-Wuninitialized"
     "-Wunreachable-code"
@@ -144,6 +147,7 @@
     "-Wstring-conversion"
     "-Wtautological-overlap-compare"
     "-Wtautological-unsigned-zero-compare"
+    "-Wthread-safety"
     "-Wundef"
     "-Wuninitialized"
     "-Wunreachable-code"
@@ -161,6 +165,7 @@
     "-Wno-implicit-int-conversion"
     "-Wno-missing-prototypes"
     "-Wno-missing-variable-declarations"
+    "-Wno-nullability-completeness"
     "-Wno-shadow"
     "-Wno-shorten-64-to-32"
     "-Wno-sign-compare"
@@ -181,8 +186,6 @@
     "/wd4005"
     "/wd4068"
     "/wd4180"
-    "/wd4244"
-    "/wd4267"
     "/wd4503"
     "/wd4800"
     "/DNOMINMAX"
@@ -202,8 +205,6 @@
     "/wd4005"
     "/wd4068"
     "/wd4180"
-    "/wd4244"
-    "/wd4267"
     "/wd4503"
     "/wd4800"
     "/DNOMINMAX"
@@ -213,23 +214,9 @@
     "/D_ENABLE_EXTENDED_ALIGNED_STORAGE"
     "/wd4018"
     "/wd4101"
+    "/wd4244"
+    "/wd4267"
     "/wd4503"
     "/wd4996"
     "/DNOMINMAX"
 )
-
-list(APPEND ABSL_RANDOM_HWAES_ARM32_FLAGS
-    "-mfpu=neon"
-)
-
-list(APPEND ABSL_RANDOM_HWAES_ARM64_FLAGS
-    "-march=armv8-a+crypto"
-)
-
-list(APPEND ABSL_RANDOM_HWAES_MSVC_X64_FLAGS
-)
-
-list(APPEND ABSL_RANDOM_HWAES_X64_FLAGS
-    "-maes"
-    "-msse4.1"
-)
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl
index b9e0071..23896e9 100644
--- a/absl/copts/GENERATED_copts.bzl
+++ b/absl/copts/GENERATED_copts.bzl
@@ -24,6 +24,7 @@
     "-Wno-implicit-int-conversion",
     "-Wno-missing-prototypes",
     "-Wno-missing-variable-declarations",
+    "-Wno-nullability-completeness",
     "-Wno-shadow",
     "-Wno-shorten-64-to-32",
     "-Wno-sign-compare",
@@ -98,6 +99,7 @@
     "-Winvalid-constexpr",
     "-Wliteral-conversion",
     "-Wmissing-declarations",
+    "-Wnullability-completeness",
     "-Woverlength-strings",
     "-Wpointer-arith",
     "-Wself-assign",
@@ -107,6 +109,7 @@
     "-Wstring-conversion",
     "-Wtautological-overlap-compare",
     "-Wtautological-unsigned-zero-compare",
+    "-Wthread-safety",
     "-Wundef",
     "-Wuninitialized",
     "-Wunreachable-code",
@@ -145,6 +148,7 @@
     "-Wstring-conversion",
     "-Wtautological-overlap-compare",
     "-Wtautological-unsigned-zero-compare",
+    "-Wthread-safety",
     "-Wundef",
     "-Wuninitialized",
     "-Wunreachable-code",
@@ -162,6 +166,7 @@
     "-Wno-implicit-int-conversion",
     "-Wno-missing-prototypes",
     "-Wno-missing-variable-declarations",
+    "-Wno-nullability-completeness",
     "-Wno-shadow",
     "-Wno-shorten-64-to-32",
     "-Wno-sign-compare",
@@ -182,8 +187,6 @@
     "/wd4005",
     "/wd4068",
     "/wd4180",
-    "/wd4244",
-    "/wd4267",
     "/wd4503",
     "/wd4800",
     "/DNOMINMAX",
@@ -203,8 +206,6 @@
     "/wd4005",
     "/wd4068",
     "/wd4180",
-    "/wd4244",
-    "/wd4267",
     "/wd4503",
     "/wd4800",
     "/DNOMINMAX",
@@ -214,23 +215,9 @@
     "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
     "/wd4018",
     "/wd4101",
+    "/wd4244",
+    "/wd4267",
     "/wd4503",
     "/wd4996",
     "/DNOMINMAX",
 ]
-
-ABSL_RANDOM_HWAES_ARM32_FLAGS = [
-    "-mfpu=neon",
-]
-
-ABSL_RANDOM_HWAES_ARM64_FLAGS = [
-    "-march=armv8-a+crypto",
-]
-
-ABSL_RANDOM_HWAES_MSVC_X64_FLAGS = [
-]
-
-ABSL_RANDOM_HWAES_X64_FLAGS = [
-    "-maes",
-    "-msse4.1",
-]
diff --git a/absl/copts/configure_copts.bzl b/absl/copts/configure_copts.bzl
index ca5f26d..9e0be28 100644
--- a/absl/copts/configure_copts.bzl
+++ b/absl/copts/configure_copts.bzl
@@ -15,68 +15,25 @@
     "ABSL_MSVC_FLAGS",
     "ABSL_MSVC_LINKOPTS",
     "ABSL_MSVC_TEST_FLAGS",
-    "ABSL_RANDOM_HWAES_ARM32_FLAGS",
-    "ABSL_RANDOM_HWAES_ARM64_FLAGS",
-    "ABSL_RANDOM_HWAES_MSVC_X64_FLAGS",
-    "ABSL_RANDOM_HWAES_X64_FLAGS",
 )
 
 ABSL_DEFAULT_COPTS = select({
-    "//absl:msvc_compiler": ABSL_MSVC_FLAGS,
-    "//absl:clang-cl_compiler": ABSL_CLANG_CL_FLAGS,
-    "//absl:clang_compiler": ABSL_LLVM_FLAGS,
-    "//absl:gcc_compiler": ABSL_GCC_FLAGS,
-    "//conditions:default": ABSL_GCC_FLAGS,
+    "@rules_cc//cc/compiler:msvc-cl": ABSL_MSVC_FLAGS,
+    "@rules_cc//cc/compiler:clang-cl": ABSL_CLANG_CL_FLAGS,
+    "@rules_cc//cc/compiler:clang": ABSL_LLVM_FLAGS,
+    "@rules_cc//cc/compiler:gcc": ABSL_GCC_FLAGS,
+    "//conditions:default": [],
 })
 
 ABSL_TEST_COPTS = select({
-    "//absl:msvc_compiler": ABSL_MSVC_TEST_FLAGS,
-    "//absl:clang-cl_compiler": ABSL_CLANG_CL_TEST_FLAGS,
-    "//absl:clang_compiler": ABSL_LLVM_TEST_FLAGS,
-    "//absl:gcc_compiler": ABSL_GCC_TEST_FLAGS,
-    "//conditions:default": ABSL_GCC_TEST_FLAGS,
+    "@rules_cc//cc/compiler:msvc-cl": ABSL_MSVC_TEST_FLAGS,
+    "@rules_cc//cc/compiler:clang-cl": ABSL_CLANG_CL_TEST_FLAGS,
+    "@rules_cc//cc/compiler:clang": ABSL_LLVM_TEST_FLAGS,
+    "@rules_cc//cc/compiler:gcc": ABSL_GCC_TEST_FLAGS,
+    "//conditions:default": [],
 })
 
 ABSL_DEFAULT_LINKOPTS = select({
-    "//absl:msvc_compiler": ABSL_MSVC_LINKOPTS,
+    "@rules_cc//cc/compiler:msvc-cl": ABSL_MSVC_LINKOPTS,
     "//conditions:default": [],
 })
-
-# ABSL_RANDOM_RANDEN_COPTS blaze copts flags which are required by each
-# environment to build an accelerated RandenHwAes library.
-ABSL_RANDOM_RANDEN_COPTS = select({
-    # APPLE
-    ":cpu_darwin_x86_64": ABSL_RANDOM_HWAES_X64_FLAGS,
-    ":cpu_darwin": ABSL_RANDOM_HWAES_X64_FLAGS,
-    ":cpu_x64_windows_msvc": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS,
-    ":cpu_x64_windows": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS,
-    ":cpu_k8": ABSL_RANDOM_HWAES_X64_FLAGS,
-    ":cpu_ppc": ["-mcrypto"],
-    ":cpu_aarch64": ABSL_RANDOM_HWAES_ARM64_FLAGS,
-
-    # Supported by default or unsupported.
-    "//conditions:default": [],
-})
-
-# absl_random_randen_copts_init:
-#  Initialize the config targets based on cpu, os, etc. used to select
-#  the required values for ABSL_RANDOM_RANDEN_COPTS
-def absl_random_randen_copts_init():
-    """Initialize the config_settings used by ABSL_RANDOM_RANDEN_COPTS."""
-
-    # CPU configs.
-    # These configs have consistent flags to enable HWAES intsructions.
-    cpu_configs = [
-        "ppc",
-        "k8",
-        "darwin_x86_64",
-        "darwin",
-        "x64_windows_msvc",
-        "x64_windows",
-        "aarch64",
-    ]
-    for cpu in cpu_configs:
-        native.config_setting(
-            name = "cpu_%s" % cpu,
-            values = {"cpu": cpu},
-        )
diff --git a/absl/copts/copts.py b/absl/copts/copts.py
index 2d85ac7..8cf8f31 100644
--- a/absl/copts/copts.py
+++ b/absl/copts/copts.py
@@ -57,6 +57,7 @@
     "-Winvalid-constexpr",
     "-Wliteral-conversion",
     "-Wmissing-declarations",
+    "-Wnullability-completeness",
     "-Woverlength-strings",
     "-Wpointer-arith",
     "-Wself-assign",
@@ -66,6 +67,7 @@
     "-Wstring-conversion",
     "-Wtautological-overlap-compare",
     "-Wtautological-unsigned-zero-compare",
+    "-Wthread-safety",
     "-Wundef",
     "-Wuninitialized",
     "-Wunreachable-code",
@@ -91,6 +93,7 @@
     "-Wno-implicit-int-conversion",
     "-Wno-missing-prototypes",
     "-Wno-missing-variable-declarations",
+    "-Wno-nullability-completeness",
     "-Wno-shadow",
     "-Wno-shorten-64-to-32",
     "-Wno-sign-compare",
@@ -118,10 +121,6 @@
     "/wd4068",  # unknown pragma
     # qualifier applied to function type has no meaning; ignored
     "/wd4180",
-    # conversion from 'type1' to 'type2', possible loss of data
-    "/wd4244",
-    # conversion from 'size_t' to 'type', possible loss of data
-    "/wd4267",
     # The decorated name was longer than the compiler limit
     "/wd4503",
     # forcing value to bool 'true' or 'false' (performance warning)
@@ -158,37 +157,35 @@
 COPT_VARS = {
     "ABSL_GCC_FLAGS": ABSL_GCC_FLAGS,
     "ABSL_GCC_TEST_FLAGS": GccStyleFilterAndCombine(
-        ABSL_GCC_FLAGS, ABSL_GCC_TEST_ADDITIONAL_FLAGS),
+        ABSL_GCC_FLAGS, ABSL_GCC_TEST_ADDITIONAL_FLAGS
+    ),
     "ABSL_LLVM_FLAGS": ABSL_LLVM_FLAGS,
     "ABSL_LLVM_TEST_FLAGS": GccStyleFilterAndCombine(
-        ABSL_LLVM_FLAGS, ABSL_LLVM_TEST_ADDITIONAL_FLAGS),
-    "ABSL_CLANG_CL_FLAGS":
-        MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES,
-    "ABSL_CLANG_CL_TEST_FLAGS":
-        MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES + ABSL_LLVM_TEST_ADDITIONAL_FLAGS,
-    "ABSL_MSVC_FLAGS":
-        MSVC_BIG_WARNING_FLAGS + MSVC_WARNING_FLAGS + MSVC_DEFINES,
-    "ABSL_MSVC_TEST_FLAGS":
-        MSVC_BIG_WARNING_FLAGS + MSVC_WARNING_FLAGS + MSVC_DEFINES + [
+        ABSL_LLVM_FLAGS, ABSL_LLVM_TEST_ADDITIONAL_FLAGS
+    ),
+    "ABSL_CLANG_CL_FLAGS": MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES,
+    "ABSL_CLANG_CL_TEST_FLAGS": (
+        MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES + ABSL_LLVM_TEST_ADDITIONAL_FLAGS
+    ),
+    "ABSL_MSVC_FLAGS": (
+        MSVC_BIG_WARNING_FLAGS + MSVC_WARNING_FLAGS + MSVC_DEFINES
+    ),
+    "ABSL_MSVC_TEST_FLAGS": (
+        MSVC_BIG_WARNING_FLAGS
+        + MSVC_WARNING_FLAGS
+        + MSVC_DEFINES
+        + [
             "/wd4018",  # signed/unsigned mismatch
             "/wd4101",  # unreferenced local variable
+            "/wd4244",  # shortening conversion
+            "/wd4267",  # shortening conversion
             "/wd4503",  # decorated name length exceeded, name was truncated
             "/wd4996",  # use of deprecated symbol
             "/DNOMINMAX",  # disable the min() and max() macros from <windows.h>
-        ],
+        ]
+    ),
     "ABSL_MSVC_LINKOPTS": [
         # Object file doesn't export any previously undefined symbols
         "-ignore:4221",
     ],
-    # "HWAES" is an abbreviation for "hardware AES" (AES - Advanced Encryption
-    # Standard). These flags are used for detecting whether or not the target
-    # architecture has hardware support for AES instructions which can be used
-    # to improve performance of some random bit generators.
-    "ABSL_RANDOM_HWAES_ARM64_FLAGS": ["-march=armv8-a+crypto"],
-    "ABSL_RANDOM_HWAES_ARM32_FLAGS": ["-mfpu=neon"],
-    "ABSL_RANDOM_HWAES_X64_FLAGS": [
-        "-maes",
-        "-msse4.1",
-    ],
-    "ABSL_RANDOM_HWAES_MSVC_X64_FLAGS": [],
 }
diff --git a/absl/crc/BUILD.bazel b/absl/crc/BUILD.bazel
index 890d637..b659a7e 100644
--- a/absl/crc/BUILD.bazel
+++ b/absl/crc/BUILD.bazel
@@ -42,6 +42,7 @@
     deps = [
         "//absl/base",
         "//absl/base:config",
+        "//absl/types:optional",
     ],
 )
 
@@ -111,8 +112,8 @@
         ":crc32c",
         "//absl/strings",
         "//absl/strings:str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -158,8 +159,8 @@
         "//absl/random",
         "//absl/random:distributions",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -171,8 +172,8 @@
     visibility = ["//visibility:private"],
     deps = [
         ":non_temporal_memcpy",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -200,8 +201,8 @@
     deps = [
         ":crc32c",
         ":crc_cord_state",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -219,6 +220,6 @@
         ":crc32c",
         "//absl/memory",
         "//absl/strings",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/crc/CMakeLists.txt b/absl/crc/CMakeLists.txt
index d52a1bc..f068e54 100644
--- a/absl/crc/CMakeLists.txt
+++ b/absl/crc/CMakeLists.txt
@@ -25,6 +25,7 @@
   DEPS
     absl::base
     absl::config
+    absl::optional
 )
 
 # Internal-only target, do not depend on directly.
diff --git a/absl/crc/crc32c.cc b/absl/crc/crc32c.cc
index 468c1b3..9b1ef7e 100644
--- a/absl/crc/crc32c.cc
+++ b/absl/crc/crc32c.cc
@@ -54,10 +54,6 @@
 
 }  // namespace crc_internal
 
-crc32c_t ComputeCrc32c(absl::string_view buf) {
-  return ExtendCrc32c(crc32c_t{0}, buf);
-}
-
 crc32c_t ExtendCrc32cByZeroes(crc32c_t initial_crc, size_t length) {
   uint32_t crc = static_cast<uint32_t>(initial_crc) ^ kCRC32Xor;
   CrcEngine()->ExtendByZeroes(&crc, length);
diff --git a/absl/crc/crc32c.h b/absl/crc/crc32c.h
index 362861e..5ecc6b3 100644
--- a/absl/crc/crc32c.h
+++ b/absl/crc/crc32c.h
@@ -83,11 +83,6 @@
 // CRC32C Computation Functions
 // -----------------------------------------------------------------------------
 
-// ComputeCrc32c()
-//
-// Returns the CRC32C value of the provided string.
-crc32c_t ComputeCrc32c(absl::string_view buf);
-
 // ExtendCrc32c()
 //
 // Computes a CRC32C value from an `initial_crc` CRC32C value including the
@@ -112,6 +107,13 @@
   return crc_internal::ExtendCrc32cInternal(initial_crc, buf_to_add);
 }
 
+// ComputeCrc32c()
+//
+// Returns the CRC32C value of the provided string.
+inline crc32c_t ComputeCrc32c(absl::string_view buf) {
+  return ExtendCrc32c(crc32c_t{0}, buf);
+}
+
 // ExtendCrc32cByZeroes()
 //
 // Computes a CRC32C value for a buffer with an `initial_crc` CRC32C value,
diff --git a/absl/crc/crc32c_benchmark.cc b/absl/crc/crc32c_benchmark.cc
index 3b46ef3..d7cecc3 100644
--- a/absl/crc/crc32c_benchmark.cc
+++ b/absl/crc/crc32c_benchmark.cc
@@ -40,7 +40,13 @@
     benchmark::DoNotOptimize(crc);
   }
 }
-BENCHMARK(BM_Calculate)->Arg(0)->Arg(1)->Arg(100)->Arg(10000)->Arg(500000);
+BENCHMARK(BM_Calculate)
+    ->Arg(0)
+    ->Arg(1)
+    ->Arg(100)
+    ->Arg(2048)
+    ->Arg(10000)
+    ->Arg(500000);
 
 void BM_Extend(benchmark::State& state) {
   int len = state.range(0);
@@ -53,8 +59,14 @@
     benchmark::DoNotOptimize(crc);
   }
 }
-BENCHMARK(BM_Extend)->Arg(0)->Arg(1)->Arg(100)->Arg(10000)->Arg(500000)->Arg(
-    100 * 1000 * 1000);
+BENCHMARK(BM_Extend)
+    ->Arg(0)
+    ->Arg(1)
+    ->Arg(100)
+    ->Arg(2048)
+    ->Arg(10000)
+    ->Arg(500000)
+    ->Arg(100 * 1000 * 1000);
 
 // Make working set >> CPU cache size to benchmark prefetches better
 void BM_ExtendCacheMiss(benchmark::State& state) {
@@ -147,7 +159,8 @@
   state.SetBytesProcessed(static_cast<int64_t>(state.iterations()) *
                           state.range(0));
 }
-BENCHMARK(BM_Memcpy)->Arg(0)->Arg(1)->Arg(100)->Arg(10000)->Arg(500000);
+BENCHMARK(BM_Memcpy)->Arg(0)->Arg(1)->Arg(100)->Arg(2048)->Arg(10000)->Arg(
+    500000);
 
 void BM_RemoveSuffix(benchmark::State& state) {
   int full_string_len = state.range(0);
diff --git a/absl/crc/internal/cpu_detect.cc b/absl/crc/internal/cpu_detect.cc
index d7eedd1..c59f773 100644
--- a/absl/crc/internal/cpu_detect.cc
+++ b/absl/crc/internal/cpu_detect.cc
@@ -18,12 +18,21 @@
 #include <string>
 
 #include "absl/base/config.h"
+#include "absl/types/optional.h"  // IWYU pragma: keep
 
 #if defined(__aarch64__) && defined(__linux__)
 #include <asm/hwcap.h>
 #include <sys/auxv.h>
 #endif
 
+#if defined(__aarch64__) && defined(__APPLE__)
+#if defined(__has_include) && __has_include(<arm/cpu_capabilities_public.h>)
+#include <arm/cpu_capabilities_public.h>
+#endif
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#endif
+
 #if defined(_WIN32) || defined(_WIN64)
 #include <intrin.h>
 #endif
@@ -269,8 +278,55 @@
 }
 
 bool SupportsArmCRC32PMULL() {
+#if defined(HWCAP_CRC32) && defined(HWCAP_PMULL)
   uint64_t hwcaps = getauxval(AT_HWCAP);
   return (hwcaps & HWCAP_CRC32) && (hwcaps & HWCAP_PMULL);
+#else
+  return false;
+#endif
+}
+
+#elif defined(__aarch64__) && defined(__APPLE__)
+
+CpuType GetCpuType() { return CpuType::kUnknown; }
+
+template <typename T>
+static absl::optional<T> ReadSysctlByName(const char* name) {
+  T val;
+  size_t val_size = sizeof(T);
+  int ret = sysctlbyname(name, &val, &val_size, nullptr, 0);
+  if (ret == -1) {
+    return absl::nullopt;
+  }
+  return val;
+}
+
+bool SupportsArmCRC32PMULL() {
+  // Newer XNU kernels support querying all capabilities in a single
+  // sysctlbyname.
+#if defined(CAP_BIT_CRC32) && defined(CAP_BIT_FEAT_PMULL)
+  static const absl::optional<uint64_t> caps =
+      ReadSysctlByName<uint64_t>("hw.optional.arm.caps");
+  if (caps.has_value()) {
+    constexpr uint64_t kCrc32AndPmullCaps =
+        (uint64_t{1} << CAP_BIT_CRC32) | (uint64_t{1} << CAP_BIT_FEAT_PMULL);
+    return (*caps & kCrc32AndPmullCaps) == kCrc32AndPmullCaps;
+  }
+#endif
+
+  // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3915619
+  static const absl::optional<int> armv8_crc32 =
+      ReadSysctlByName<int>("hw.optional.armv8_crc32");
+  if (armv8_crc32.value_or(0) == 0) {
+    return false;
+  }
+  // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855
+  static const absl::optional<int> feat_pmull =
+      ReadSysctlByName<int>("hw.optional.arm.FEAT_PMULL");
+  if (feat_pmull.value_or(0) == 0) {
+    return false;
+  }
+  return true;
 }
 
 #else
diff --git a/absl/crc/internal/crc32_x86_arm_combined_simd.h b/absl/crc/internal/crc32_x86_arm_combined_simd.h
index 0f6e347..5a9b61a 100644
--- a/absl/crc/internal/crc32_x86_arm_combined_simd.h
+++ b/absl/crc/internal/crc32_x86_arm_combined_simd.h
@@ -99,19 +99,12 @@
 // Produces a XOR operation of |l| and |r|.
 V128 V128_Xor(const V128 l, const V128 r);
 
-// Produces an AND operation of |l| and |r|.
-V128 V128_And(const V128 l, const V128 r);
-
 // Sets the lower half of a 128 bit register to the given 64-bit value and
 // zeroes the upper half.
 // dst[63:0] := |r|
 // dst[127:64] := |0|
 V128 V128_From64WithZeroFill(const uint64_t r);
 
-// Shift |l| right by |imm| bytes while shifting in zeros.
-template <int imm>
-V128 V128_ShiftRight(const V128 l);
-
 // Extracts a 32-bit integer from |l|, selected with |imm|.
 template <int imm>
 int V128_Extract32(const V128 l);
@@ -170,18 +163,11 @@
 
 inline V128 V128_Xor(const V128 l, const V128 r) { return _mm_xor_si128(l, r); }
 
-inline V128 V128_And(const V128 l, const V128 r) { return _mm_and_si128(l, r); }
-
 inline V128 V128_From64WithZeroFill(const uint64_t r) {
   return _mm_set_epi64x(static_cast<int64_t>(0), static_cast<int64_t>(r));
 }
 
 template <int imm>
-inline V128 V128_ShiftRight(const V128 l) {
-  return _mm_srli_si128(l, imm);
-}
-
-template <int imm>
 inline int V128_Extract32(const V128 l) {
   return _mm_extract_epi32(l, imm);
 }
@@ -261,8 +247,6 @@
 
 inline V128 V128_Xor(const V128 l, const V128 r) { return veorq_u64(l, r); }
 
-inline V128 V128_And(const V128 l, const V128 r) { return vandq_u64(l, r); }
-
 inline V128 V128_From64WithZeroFill(const uint64_t r){
   constexpr uint64x2_t kZero = {0, 0};
   return vsetq_lane_u64(r, kZero, 0);
@@ -270,12 +254,6 @@
 
 
 template <int imm>
-inline V128 V128_ShiftRight(const V128 l) {
-  return vreinterpretq_u64_s8(
-      vextq_s8(vreinterpretq_s8_u64(l), vdupq_n_s8(0), imm));
-}
-
-template <int imm>
 inline int V128_Extract32(const V128 l) {
   return vgetq_lane_s32(vreinterpretq_s32_u64(l), imm);
 }
diff --git a/absl/crc/internal/crc_x86_arm_combined.cc b/absl/crc/internal/crc_x86_arm_combined.cc
index 79dace3..3194bec 100644
--- a/absl/crc/internal/crc_x86_arm_combined.cc
+++ b/absl/crc/internal/crc_x86_arm_combined.cc
@@ -64,27 +64,27 @@
 constexpr size_t kSmallCutoff = 256;
 constexpr size_t kMediumCutoff = 2048;
 
-#define ABSL_INTERNAL_STEP1(crc)                      \
+#define ABSL_INTERNAL_STEP1(crc, p)                   \
   do {                                                \
     crc = CRC32_u8(static_cast<uint32_t>(crc), *p++); \
   } while (0)
-#define ABSL_INTERNAL_STEP2(crc)                                               \
+#define ABSL_INTERNAL_STEP2(crc, p)                                            \
   do {                                                                         \
     crc =                                                                      \
         CRC32_u16(static_cast<uint32_t>(crc), absl::little_endian::Load16(p)); \
     p += 2;                                                                    \
   } while (0)
-#define ABSL_INTERNAL_STEP4(crc)                                               \
+#define ABSL_INTERNAL_STEP4(crc, p)                                            \
   do {                                                                         \
     crc =                                                                      \
         CRC32_u32(static_cast<uint32_t>(crc), absl::little_endian::Load32(p)); \
     p += 4;                                                                    \
   } while (0)
-#define ABSL_INTERNAL_STEP8(crc, data)                  \
-  do {                                                  \
-    crc = CRC32_u64(static_cast<uint32_t>(crc),         \
-                    absl::little_endian::Load64(data)); \
-    data += 8;                                          \
+#define ABSL_INTERNAL_STEP8(crc, p)                                            \
+  do {                                                                         \
+    crc =                                                                      \
+        CRC32_u64(static_cast<uint32_t>(crc), absl::little_endian::Load64(p)); \
+    p += 8;                                                                    \
   } while (0)
 #define ABSL_INTERNAL_STEP8BY2(crc0, crc1, p0, p1) \
   do {                                             \
@@ -221,7 +221,8 @@
   // We are applying it to CRC32C polynomial.
   ABSL_ATTRIBUTE_ALWAYS_INLINE void Process64BytesPclmul(
       const uint8_t* p, V128* partialCRC) const {
-    V128 loopMultiplicands = V128_Load(reinterpret_cast<const V128*>(k1k2));
+    V128 loopMultiplicands =
+        V128_Load(reinterpret_cast<const V128*>(kFoldAcross512Bits));
 
     V128 partialCRC1 = partialCRC[0];
     V128 partialCRC2 = partialCRC[1];
@@ -265,53 +266,33 @@
 
     // Combine 4 vectors of partial crc into a single vector.
     V128 reductionMultiplicands =
-        V128_Load(reinterpret_cast<const V128*>(k5k6));
+        V128_Load(reinterpret_cast<const V128*>(kFoldAcross256Bits));
 
     V128 low = V128_PMulLow(reductionMultiplicands, partialCRC1);
     V128 high = V128_PMulHi(reductionMultiplicands, partialCRC1);
 
     partialCRC1 = V128_Xor(low, high);
-    partialCRC1 = V128_Xor(partialCRC1, partialCRC2);
+    partialCRC1 = V128_Xor(partialCRC1, partialCRC3);
 
-    low = V128_PMulLow(reductionMultiplicands, partialCRC3);
-    high = V128_PMulHi(reductionMultiplicands, partialCRC3);
+    low = V128_PMulLow(reductionMultiplicands, partialCRC2);
+    high = V128_PMulHi(reductionMultiplicands, partialCRC2);
 
-    partialCRC3 = V128_Xor(low, high);
-    partialCRC3 = V128_Xor(partialCRC3, partialCRC4);
+    partialCRC2 = V128_Xor(low, high);
+    partialCRC2 = V128_Xor(partialCRC2, partialCRC4);
 
-    reductionMultiplicands = V128_Load(reinterpret_cast<const V128*>(k3k4));
+    reductionMultiplicands =
+        V128_Load(reinterpret_cast<const V128*>(kFoldAcross128Bits));
 
     low = V128_PMulLow(reductionMultiplicands, partialCRC1);
     high = V128_PMulHi(reductionMultiplicands, partialCRC1);
     V128 fullCRC = V128_Xor(low, high);
-    fullCRC = V128_Xor(fullCRC, partialCRC3);
+    fullCRC = V128_Xor(fullCRC, partialCRC2);
 
     // Reduce fullCRC into scalar value.
-    reductionMultiplicands = V128_Load(reinterpret_cast<const V128*>(k5k6));
-
-    V128 mask = V128_Load(reinterpret_cast<const V128*>(kMask));
-
-    V128 tmp = V128_PMul01(reductionMultiplicands, fullCRC);
-    fullCRC = V128_ShiftRight<8>(fullCRC);
-    fullCRC = V128_Xor(fullCRC, tmp);
-
-    reductionMultiplicands = V128_Load(reinterpret_cast<const V128*>(k7k0));
-
-    tmp = V128_ShiftRight<4>(fullCRC);
-    fullCRC = V128_And(fullCRC, mask);
-    fullCRC = V128_PMulLow(reductionMultiplicands, fullCRC);
-    fullCRC = V128_Xor(tmp, fullCRC);
-
-    reductionMultiplicands = V128_Load(reinterpret_cast<const V128*>(kPoly));
-
-    tmp = V128_And(fullCRC, mask);
-    tmp = V128_PMul01(reductionMultiplicands, tmp);
-    tmp = V128_And(tmp, mask);
-    tmp = V128_PMulLow(reductionMultiplicands, tmp);
-
-    fullCRC = V128_Xor(tmp, fullCRC);
-
-    return static_cast<uint64_t>(V128_Extract32<1>(fullCRC));
+    uint32_t crc = 0;
+    crc = CRC32_u64(crc, V128_Extract64<0>(fullCRC));
+    crc = CRC32_u64(crc, V128_Extract64<1>(fullCRC));
+    return crc;
   }
 
   // Update crc with 64 bytes of data from p.
@@ -325,15 +306,23 @@
     return crc;
   }
 
-  // Generated by crc32c_x86_test --crc32c_generate_constants=true
-  // and verified against constants in linux kernel for S390:
-  // https://github.com/torvalds/linux/blob/master/arch/s390/crypto/crc32le-vx.S
-  alignas(16) static constexpr uint64_t k1k2[2] = {0x0740eef02, 0x09e4addf8};
-  alignas(16) static constexpr uint64_t k3k4[2] = {0x1384aa63a, 0x0ba4fc28e};
-  alignas(16) static constexpr uint64_t k5k6[2] = {0x0f20c0dfe, 0x14cd00bd6};
-  alignas(16) static constexpr uint64_t k7k0[2] = {0x0dd45aab8, 0x000000000};
-  alignas(16) static constexpr uint64_t kPoly[2] = {0x105ec76f0, 0x0dea713f1};
-  alignas(16) static constexpr uint32_t kMask[4] = {~0u, 0u, ~0u, 0u};
+  // Constants generated by './scripts/gen-crc-consts.py x86_pclmul
+  // crc32_lsb_0x82f63b78' from the Linux kernel.
+  alignas(16) static constexpr uint64_t kFoldAcross512Bits[2] = {
+      // (x^543 mod G) * x^32
+      0x00000000740eef02,
+      // (x^479 mod G) * x^32
+      0x000000009e4addf8};
+  alignas(16) static constexpr uint64_t kFoldAcross256Bits[2] = {
+      // (x^287 mod G) * x^32
+      0x000000003da6d0cb,
+      // (x^223 mod G) * x^32
+      0x00000000ba4fc28e};
+  alignas(16) static constexpr uint64_t kFoldAcross128Bits[2] = {
+      // (x^159 mod G) * x^32
+      0x00000000f20c0dfe,
+      // (x^95 mod G) * x^32
+      0x00000000493c7d27};
 
   // Medium runs of bytes are broken into groups of kGroupsSmall blocks of same
   // size. Each group is CRCed in parallel then combined at the end of the
@@ -345,24 +334,6 @@
   static constexpr size_t kMaxStreams = 3;
 };
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-alignas(16) constexpr uint64_t
-    CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::k1k2[2];
-alignas(16) constexpr uint64_t
-    CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::k3k4[2];
-alignas(16) constexpr uint64_t
-    CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::k5k6[2];
-alignas(16) constexpr uint64_t
-    CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::k7k0[2];
-alignas(16) constexpr uint64_t
-    CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::kPoly[2];
-alignas(16) constexpr uint32_t
-    CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::kMask[4];
-constexpr size_t
-    CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::kGroupsSmall;
-constexpr size_t CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::kMaxStreams;
-#endif  // ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-
 template <size_t num_crc_streams, size_t num_pclmul_streams,
           CutoffStrategy strategy>
 class CRC32AcceleratedX86ARMCombinedMultipleStreams
@@ -384,15 +355,15 @@
       length &= ~size_t{8};
     }
     if (length & 4) {
-      ABSL_INTERNAL_STEP4(l);
+      ABSL_INTERNAL_STEP4(l, p);
       length &= ~size_t{4};
     }
     if (length & 2) {
-      ABSL_INTERNAL_STEP2(l);
+      ABSL_INTERNAL_STEP2(l, p);
       length &= ~size_t{2};
     }
     if (length & 1) {
-      ABSL_INTERNAL_STEP1(l);
+      ABSL_INTERNAL_STEP1(l, p);
       length &= ~size_t{1};
     }
     if (length == 0) {
@@ -478,7 +449,7 @@
       const uint8_t* x = RoundUp<8>(p);
       // Process bytes until p is 8-byte aligned, if that isn't past the end.
       while (p != x) {
-        ABSL_INTERNAL_STEP1(l);
+        ABSL_INTERNAL_STEP1(l, p);
       }
 
       size_t bs = static_cast<size_t>(e - p) /
@@ -597,7 +568,7 @@
     }
     // Process the last few bytes
     while (p != e) {
-      ABSL_INTERNAL_STEP1(l);
+      ABSL_INTERNAL_STEP1(l, p);
     }
 
 #undef ABSL_INTERNAL_STEP8BY3
diff --git a/absl/crc/internal/non_temporal_memcpy.h b/absl/crc/internal/non_temporal_memcpy.h
index 7ae83bd..5d3e4e3 100644
--- a/absl/crc/internal/non_temporal_memcpy.h
+++ b/absl/crc/internal/non_temporal_memcpy.h
@@ -111,20 +111,31 @@
 #endif  // __SSE3__ || __aarch64__ || (_MSC_VER && __AVX__)
 }
 
+// We try to force non_temporal_store_memcpy_avx to use AVX instructions
+// so that we can select it at runtime when AVX is available.
+// Clang on Windows has gnu::target but does not make AVX types like __m256i
+// available when trying to force specific functions to use AVX compiles.
+#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::target) && !defined(_MSC_VER) && \
+    (defined(__x86_64__) || defined(__i386__))
+#define ABSL_INTERNAL_CAN_FORCE_AVX 1
+#endif
+
 // If the objects overlap, the behavior is undefined. Uses regular memcpy
 // instead of non-temporal memcpy if the required CPU intrinsics are unavailable
 // at compile time.
-#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::target) && \
-    (defined(__x86_64__) || defined(__i386__))
+#ifdef ABSL_INTERNAL_CAN_FORCE_AVX
 [[gnu::target("avx")]]
 #endif
 inline void *non_temporal_store_memcpy_avx(void *__restrict dst,
                                            const void *__restrict src,
                                            size_t len) {
-  // This function requires AVX. For clang and gcc we compile it with AVX even
-  // if the translation unit isn't built with AVX support. This works because we
-  // only select this implementation at runtime if the CPU supports AVX.
-#if defined(__SSE3__) || (defined(_MSC_VER) && defined(__AVX__))
+  // This function requires AVX. If possible we compile it with AVX even if the
+  // translation unit isn't built with AVX support. This works because we only
+  // select this implementation at runtime if the CPU supports AVX.
+  // MSVC AVX support implies SSE3 support.
+#if ((defined(__AVX__) || defined(ABSL_INTERNAL_CAN_FORCE_AVX)) && \
+     defined(__SSE3__)) ||                                         \
+    (defined(_MSC_VER) && defined(__AVX__))
   uint8_t *d = reinterpret_cast<uint8_t *>(dst);
   const uint8_t *s = reinterpret_cast<const uint8_t *>(src);
 
@@ -170,10 +181,13 @@
   }
   return dst;
 #else
+  // Fallback to regular memcpy so that this function compiles.
   return memcpy(dst, src, len);
-#endif  // __SSE3__ || (_MSC_VER && __AVX__)
+#endif
 }
 
+#undef ABSL_INTERNAL_CAN_FORCE_AVX
+
 }  // namespace crc_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/crc/internal/non_temporal_memcpy_test.cc b/absl/crc/internal/non_temporal_memcpy_test.cc
index eb07a55..b2b19d3 100644
--- a/absl/crc/internal/non_temporal_memcpy_test.cc
+++ b/absl/crc/internal/non_temporal_memcpy_test.cc
@@ -57,6 +57,7 @@
   }
 }
 
+#ifdef __AVX__
 TEST_P(NonTemporalMemcpyTest, AVXEquality) {
   uint8_t* src = a_.data() + GetParam().src_offset;
   uint8_t* dst = b_.data() + GetParam().dst_offset;
@@ -67,6 +68,7 @@
     EXPECT_EQ(src[i], dst[i]);
   }
 }
+#endif
 
 // 63B is smaller than one cacheline operation thus the non-temporal routine
 // will not be called.
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index 52b407c..cd0f1de 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -66,9 +66,11 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":stacktrace",
+        "//absl/base:config",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "//absl/types:span",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -88,8 +90,8 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS + select({
-        "//absl:msvc_compiler": ["-DEFAULTLIB:dbghelp.lib"],
-        "//absl:clang-cl_compiler": ["-DEFAULTLIB:dbghelp.lib"],
+        "@rules_cc//cc/compiler:msvc-cl": ["-DEFAULTLIB:dbghelp.lib"],
+        "@rules_cc//cc/compiler:clang-cl": ["-DEFAULTLIB:dbghelp.lib"],
         "//absl:mingw_compiler": [
             "-DEFAULTLIB:dbghelp.lib",
             "-ldbghelp",
@@ -113,13 +115,13 @@
     name = "symbolize_test",
     srcs = ["symbolize_test.cc"],
     copts = ABSL_TEST_COPTS + select({
-        "//absl:msvc_compiler": ["/Z7"],
-        "//absl:clang-cl_compiler": ["/Z7"],
+        "@rules_cc//cc/compiler:msvc-cl": ["/Z7"],
+        "@rules_cc//cc/compiler:clang-cl": ["/Z7"],
         "//conditions:default": [],
     }),
     linkopts = ABSL_DEFAULT_LINKOPTS + select({
-        "//absl:msvc_compiler": ["/DEBUG"],
-        "//absl:clang-cl_compiler": ["/DEBUG"],
+        "@rules_cc//cc/compiler:msvc-cl": ["/DEBUG"],
+        "@rules_cc//cc/compiler:clang-cl": ["/DEBUG"],
         "//conditions:default": [],
     }),
     deps = [
@@ -132,7 +134,7 @@
         "//absl/log:check",
         "//absl/memory",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -177,9 +179,9 @@
     srcs = ["failure_signal_handler_test.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = select({
-        "//absl:msvc_compiler": [],
-        "//absl:clang-cl_compiler": [],
-        "//absl:wasm": [],
+        "@rules_cc//cc/compiler:msvc-cl": [],
+        "@rules_cc//cc/compiler:clang-cl": [],
+        "@rules_cc//cc/compiler:emscripten": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
@@ -189,7 +191,7 @@
         "//absl/base:raw_logging_internal",
         "//absl/log:check",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -202,6 +204,7 @@
     ],
     hdrs = [
         "internal/address_is_readable.h",
+        "internal/addresses.h",
         "internal/elf_mem_image.h",
         "internal/vdso_support.h",
     ],
@@ -249,8 +252,8 @@
         "//absl/base:core_headers",
         "//absl/log",
         "//absl/memory",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -273,8 +276,8 @@
     deps = [
         ":bounded_utf8_length_sequence",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -300,8 +303,8 @@
     deps = [
         ":decode_rust_punycode",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -327,8 +330,8 @@
         ":demangle_rust",
         "//absl/base:config",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -349,8 +352,8 @@
     deps = [
         ":utf8_for_code_point",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -376,8 +379,8 @@
         ":leak_check",
         "//absl/base:config",
         "//absl/log",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -394,8 +397,8 @@
     deps = [
         ":leak_check",
         "//absl/log",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -424,8 +427,8 @@
         ":stack_consumption",
         "//absl/base:core_headers",
         "//absl/log",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -440,6 +443,6 @@
         ":stacktrace",
         "//absl/base:config",
         "//absl/base:core_headers",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt
index a96b4f3..60b138a 100644
--- a/absl/debugging/CMakeLists.txt
+++ b/absl/debugging/CMakeLists.txt
@@ -55,7 +55,9 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::stacktrace
+    absl::config
     absl::core_headers
+    absl::span
     GTest::gmock_main
 )
 
@@ -174,6 +176,7 @@
     debugging_internal
   HDRS
     "internal/address_is_readable.h"
+    "internal/addresses.h"
     "internal/elf_mem_image.h"
     "internal/vdso_support.h"
   SRCS
diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc
index 570d1e5..d31f5a1 100644
--- a/absl/debugging/failure_signal_handler.cc
+++ b/absl/debugging/failure_signal_handler.cc
@@ -21,6 +21,7 @@
 #ifdef _WIN32
 #include <windows.h>
 #else
+#include <pthread.h>
 #include <sched.h>
 #include <unistd.h>
 #endif
@@ -65,6 +66,23 @@
 #endif
 #endif
 
+// ABSL_HAVE_PTHREAD_CPU_NUMBER_NP
+//
+// Checks whether pthread_cpu_number_np is available.
+#ifdef ABSL_HAVE_PTHREAD_CPU_NUMBER_NP
+#error ABSL_HAVE_PTHREAD_CPU_NUMBER_NP cannot be directly set
+#elif defined(__APPLE__) && defined(__has_include) &&              \
+    ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) &&    \
+      __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 110000) ||  \
+     (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) &&   \
+      __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 140200) || \
+     (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) &&    \
+      __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ >= 70100) ||   \
+     (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) &&       \
+      __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ >= 140200))
+#define ABSL_HAVE_PTHREAD_CPU_NUMBER_NP 1
+#endif
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
@@ -330,6 +348,20 @@
 using GetTidType = decltype(absl::base_internal::GetTID());
 ABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0);
 
+static int GetCpuNumber() {
+#ifdef ABSL_HAVE_SCHED_GETCPU
+  return sched_getcpu();
+#elif defined(ABSL_HAVE_PTHREAD_CPU_NUMBER_NP)
+  size_t cpu_num;
+  if (pthread_cpu_number_np(&cpu_num) == 0) {
+    return static_cast<int>(cpu_num);
+  }
+  return -1;
+#else
+  return -1;
+#endif
+}
+
 #ifndef ABSL_HAVE_SIGACTION
 static void AbslFailureSignalHandler(int signo) {
   void* ucontext = nullptr;
@@ -360,10 +392,7 @@
   // Increase the chance that the CPU we report was the same CPU on which the
   // signal was received by doing this as early as possible, i.e. after
   // verifying that this is not a recursive signal handler invocation.
-  int my_cpu = -1;
-#ifdef ABSL_HAVE_SCHED_GETCPU
-  my_cpu = sched_getcpu();
-#endif
+  int my_cpu = GetCpuNumber();
 
 #ifdef ABSL_HAVE_ALARM
   // Set an alarm to abort the program in case this code hangs or deadlocks.
diff --git a/absl/debugging/internal/addresses.h b/absl/debugging/internal/addresses.h
new file mode 100644
index 0000000..504fd6f
--- /dev/null
+++ b/absl/debugging/internal/addresses.h
@@ -0,0 +1,57 @@
+// Copyright 2025 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_DEBUGGING_INTERNAL_ADDRESSES_H_
+#define ABSL_DEBUGGING_INTERNAL_ADDRESSES_H_
+
+#include <stdint.h>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace debugging_internal {
+
+// Removes any metadata (tag bits) from the given pointer, converting it into a
+// user-readable address.
+inline uintptr_t StripPointerMetadata(uintptr_t ptr) {
+#if defined(__aarch64__)
+  // When PAC-RET (-mbranch-protection=pac-ret) is enabled, return addresses
+  // stored on the stack will be signed, which means that pointer bits outside
+  // of the virtual address range are potentially set. Since the stacktrace code
+  // is expected to return normal code pointers, this function clears those
+  // bits.
+  register uintptr_t x30 __asm__("x30") = ptr;
+  // The normal instruction for clearing PAC bits is XPACI, but for
+  // compatibility with ARM platforms that do not support pointer
+  // authentication, we use the hint space instruction XPACLRI instead. Hint
+  // space instructions behave as NOPs on unsupported platforms.
+#define ABSL_XPACLRI_HINT "hint #0x7;"
+  asm(ABSL_XPACLRI_HINT : "+r"(x30));  // asm("xpaclri" : "+r"(x30));
+#undef ABSL_XPACLRI_HINT
+  return x30;
+#else
+  return ptr;
+#endif
+}
+
+inline uintptr_t StripPointerMetadata(void* ptr) {
+  return StripPointerMetadata(reinterpret_cast<uintptr_t>(ptr));
+}
+
+}  // namespace debugging_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_DEBUGGING_INTERNAL_ADDRESSES_H_
diff --git a/absl/debugging/internal/decode_rust_punycode.cc b/absl/debugging/internal/decode_rust_punycode.cc
index 43b46bf..6652dc2 100644
--- a/absl/debugging/internal/decode_rust_punycode.cc
+++ b/absl/debugging/internal/decode_rust_punycode.cc
@@ -172,7 +172,7 @@
 
 }  // namespace
 
-absl::Nullable<char*> DecodeRustPunycode(DecodeRustPunycodeOptions options) {
+char* absl_nullable DecodeRustPunycode(DecodeRustPunycodeOptions options) {
   const char* punycode_begin = options.punycode_begin;
   const char* const punycode_end = options.punycode_end;
   char* const out_begin = options.out_begin;
diff --git a/absl/debugging/internal/decode_rust_punycode.h b/absl/debugging/internal/decode_rust_punycode.h
index 0ae53ff..44aad8a 100644
--- a/absl/debugging/internal/decode_rust_punycode.h
+++ b/absl/debugging/internal/decode_rust_punycode.h
@@ -23,10 +23,10 @@
 namespace debugging_internal {
 
 struct DecodeRustPunycodeOptions {
-  const char* punycode_begin;
-  const char* punycode_end;
-  char* out_begin;
-  char* out_end;
+  const char* absl_nonnull punycode_begin;
+  const char* absl_nonnull punycode_end;
+  char* absl_nonnull out_begin;
+  char* absl_nonnull out_end;
 };
 
 // Given Rust Punycode in `punycode_begin .. punycode_end`, writes the
@@ -46,7 +46,7 @@
 // DecodeRustPunycode is async-signal-safe with bounded runtime and a small
 // stack footprint, making it suitable for use in demangling Rust symbol names
 // from a signal handler.
-absl::Nullable<char*> DecodeRustPunycode(DecodeRustPunycodeOptions options);
+char* absl_nullable DecodeRustPunycode(DecodeRustPunycodeOptions options);
 
 }  // namespace debugging_internal
 ABSL_NAMESPACE_END
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index caac763..5f62ebb 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -484,36 +484,6 @@
 
 static bool IsDigit(char c) { return c >= '0' && c <= '9'; }
 
-// Returns true if "str" is a function clone suffix.  These suffixes are used
-// by GCC 4.5.x and later versions (and our locally-modified version of GCC
-// 4.4.x) to indicate functions which have been cloned during optimization.
-// We treat any sequence (.<alpha>+.<digit>+)+ as a function clone suffix.
-// Additionally, '_' is allowed along with the alphanumeric sequence.
-static bool IsFunctionCloneSuffix(const char *str) {
-  size_t i = 0;
-  while (str[i] != '\0') {
-    bool parsed = false;
-    // Consume a single [.<alpha> | _]*[.<digit>]* sequence.
-    if (str[i] == '.' && (IsAlpha(str[i + 1]) || str[i + 1] == '_')) {
-      parsed = true;
-      i += 2;
-      while (IsAlpha(str[i]) || str[i] == '_') {
-        ++i;
-      }
-    }
-    if (str[i] == '.' && IsDigit(str[i + 1])) {
-      parsed = true;
-      i += 2;
-      while (IsDigit(str[i])) {
-        ++i;
-      }
-    }
-    if (!parsed)
-      return false;
-  }
-  return true;  // Consumed everything in "str".
-}
-
 static bool EndsWith(State *state, const char chr) {
   return state->parse_state.out_cur_idx > 0 &&
          state->parse_state.out_cur_idx < state->out_end_idx &&
@@ -1039,7 +1009,8 @@
     number = ~number + 1;
   }
   if (p != RemainingInput(state)) {  // Conversion succeeded.
-    state->parse_state.mangled_idx += p - RemainingInput(state);
+    state->parse_state.mangled_idx +=
+        static_cast<int>(p - RemainingInput(state));
     UpdateHighWaterMark(state);
     if (number_out != nullptr) {
       // Note: possibly truncate "number".
@@ -1062,7 +1033,8 @@
     }
   }
   if (p != RemainingInput(state)) {  // Conversion succeeded.
-    state->parse_state.mangled_idx += p - RemainingInput(state);
+    state->parse_state.mangled_idx +=
+        static_cast<int>(p - RemainingInput(state));
     UpdateHighWaterMark(state);
     return true;
   }
@@ -1081,7 +1053,8 @@
     }
   }
   if (p != RemainingInput(state)) {  // Conversion succeeded.
-    state->parse_state.mangled_idx += p - RemainingInput(state);
+    state->parse_state.mangled_idx +=
+        static_cast<int>(p - RemainingInput(state));
     UpdateHighWaterMark(state);
     return true;
   }
@@ -1100,7 +1073,7 @@
   } else {
     MaybeAppendWithLength(state, RemainingInput(state), length);
   }
-  state->parse_state.mangled_idx += length;
+  state->parse_state.mangled_idx += static_cast<int>(length);
   UpdateHighWaterMark(state);
   return true;
 }
@@ -2816,7 +2789,8 @@
     // On late parse failure, roll back not only the input but also the output,
     // whose trailing NUL was overwritten.
     state->parse_state = copy;
-    if (state->parse_state.append) {
+    if (state->parse_state.append &&
+        state->parse_state.out_cur_idx < state->out_end_idx) {
       state->out[state->parse_state.out_cur_idx] = '\0';
     }
     return false;
@@ -2829,7 +2803,8 @@
     return true;
   }
   state->parse_state = copy;
-  if (state->parse_state.append) {
+  if (state->parse_state.append &&
+      state->parse_state.out_cur_idx < state->out_end_idx) {
     state->out[state->parse_state.out_cur_idx] = '\0';
   }
 
@@ -2927,7 +2902,7 @@
   if (ParseMangledName(state)) {
     if (RemainingInput(state)[0] != '\0') {
       // Drop trailing function clone suffix, if any.
-      if (IsFunctionCloneSuffix(RemainingInput(state))) {
+      if (RemainingInput(state)[0] == '.') {
         return true;
       }
       // Append trailing version suffix if any.
diff --git a/absl/debugging/internal/demangle_rust.cc b/absl/debugging/internal/demangle_rust.cc
index 4309bd8..f7f6713 100644
--- a/absl/debugging/internal/demangle_rust.cc
+++ b/absl/debugging/internal/demangle_rust.cc
@@ -84,7 +84,7 @@
   // structure was not recognized or exceeded implementation limits, such as by
   // nesting structures too deep.  In either case *this should not be used
   // again.
-  ABSL_MUST_USE_RESULT bool Parse() && {
+  [[nodiscard]] bool Parse() && {
     // Recursively parses the grammar production named by callee, then resumes
     // execution at the next statement.
     //
@@ -564,7 +564,7 @@
 
   // If the next input character is the given character, consumes it and returns
   // true; otherwise returns false without consuming a character.
-  ABSL_MUST_USE_RESULT bool Eat(char want) {
+  [[nodiscard]] bool Eat(char want) {
     if (encoding_[pos_] != want) return false;
     ++pos_;
     return true;
@@ -573,7 +573,7 @@
   // Provided there is enough remaining output space, appends c to the output,
   // writing a fresh NUL terminator afterward, and returns true.  Returns false
   // if the output buffer had less than two bytes free.
-  ABSL_MUST_USE_RESULT bool EmitChar(char c) {
+  [[nodiscard]] bool EmitChar(char c) {
     if (silence_depth_ > 0) return true;
     if (out_end_ - out_ < 2) return false;
     *out_++ = c;
@@ -584,7 +584,7 @@
   // Provided there is enough remaining output space, appends the C string token
   // to the output, followed by a NUL character, and returns true.  Returns
   // false if not everything fit into the output buffer.
-  ABSL_MUST_USE_RESULT bool Emit(const char* token) {
+  [[nodiscard]] bool Emit(const char* token) {
     if (silence_depth_ > 0) return true;
     const size_t token_length = std::strlen(token);
     const size_t bytes_to_copy = token_length + 1;  // token and final NUL
@@ -598,7 +598,7 @@
   // of disambiguator (if it's nonnegative) or "?" (if it's negative) to the
   // output, followed by a NUL character, and returns true.  Returns false if
   // not everything fit into the output buffer.
-  ABSL_MUST_USE_RESULT bool EmitDisambiguator(int disambiguator) {
+  [[nodiscard]] bool EmitDisambiguator(int disambiguator) {
     if (disambiguator < 0) return EmitChar('?');  // parsed but too large
     if (disambiguator == 0) return EmitChar('0');
     // Convert disambiguator to decimal text.  Three digits per byte is enough
@@ -618,7 +618,7 @@
   // On success returns true and fills value with the encoded value if it was
   // not too big, otherwise with -1.  If the optional disambiguator was omitted,
   // value is 0.  On parse failure returns false and sets value to -1.
-  ABSL_MUST_USE_RESULT bool ParseDisambiguator(int& value) {
+  [[nodiscard]] bool ParseDisambiguator(int& value) {
     value = -1;
 
     // disambiguator = s base-62-number
@@ -639,7 +639,7 @@
   // On success returns true and fills value with the encoded value if it was
   // not too big, otherwise with -1.  On parse failure returns false and sets
   // value to -1.
-  ABSL_MUST_USE_RESULT bool ParseBase62Number(int& value) {
+  [[nodiscard]] bool ParseBase62Number(int& value) {
     value = -1;
 
     // base-62-number = (digit | lower | upper)* _
@@ -686,7 +686,7 @@
   // A nonzero uppercase_namespace specifies the character after the N in a
   // nested-identifier, e.g., 'C' for a closure, allowing ParseIdentifier to
   // write out the name with the conventional decoration for that namespace.
-  ABSL_MUST_USE_RESULT bool ParseIdentifier(char uppercase_namespace = '\0') {
+  [[nodiscard]] bool ParseIdentifier(char uppercase_namespace = '\0') {
     // identifier -> disambiguator? undisambiguated-identifier
     int disambiguator = 0;
     if (!ParseDisambiguator(disambiguator)) return false;
@@ -703,7 +703,7 @@
   //
   // At other appearances of undisambiguated-identifier in the grammar, this
   // treatment is not applicable, and the call site omits both arguments.
-  ABSL_MUST_USE_RESULT bool ParseUndisambiguatedIdentifier(
+  [[nodiscard]] bool ParseUndisambiguatedIdentifier(
       char uppercase_namespace = '\0', int disambiguator = 0) {
     // undisambiguated-identifier -> u? decimal-number _? bytes
     const bool is_punycoded = Eat('u');
@@ -766,7 +766,7 @@
   // Consumes a decimal number like 0 or 123 from the input.  On success returns
   // true and fills value with the encoded value.  If the encoded value is too
   // large or otherwise unparsable, returns false and sets value to -1.
-  ABSL_MUST_USE_RESULT bool ParseDecimalNumber(int& value) {
+  [[nodiscard]] bool ParseDecimalNumber(int& value) {
     value = -1;
     if (!IsDigit(Peek())) return false;
     int encoded_number = Take() - '0';
@@ -788,7 +788,7 @@
   // Consumes a binder of higher-ranked lifetimes if one is present.  On success
   // returns true and discards the encoded lifetime count.  On parse failure
   // returns false.
-  ABSL_MUST_USE_RESULT bool ParseOptionalBinder() {
+  [[nodiscard]] bool ParseOptionalBinder() {
     // binder -> G base-62-number
     if (!Eat('G')) return true;
     int ignored_binding_count;
@@ -802,7 +802,7 @@
   // things we omit from output, such as the entire contents of generic-args.
   //
   // On parse failure returns false.
-  ABSL_MUST_USE_RESULT bool ParseOptionalLifetime() {
+  [[nodiscard]] bool ParseOptionalLifetime() {
     // lifetime -> L base-62-number
     if (!Eat('L')) return true;
     int ignored_de_bruijn_index;
@@ -811,14 +811,14 @@
 
   // Consumes a lifetime just like ParseOptionalLifetime, but returns false if
   // there is no lifetime here.
-  ABSL_MUST_USE_RESULT bool ParseRequiredLifetime() {
+  [[nodiscard]] bool ParseRequiredLifetime() {
     if (Peek() != 'L') return false;
     return ParseOptionalLifetime();
   }
 
   // Pushes ns onto the namespace stack and returns true if the stack is not
   // full, else returns false.
-  ABSL_MUST_USE_RESULT bool PushNamespace(char ns) {
+  [[nodiscard]] bool PushNamespace(char ns) {
     if (namespace_depth_ == kNamespaceStackSize) return false;
     namespace_stack_[namespace_depth_++] = ns;
     return true;
@@ -830,7 +830,7 @@
 
   // Pushes position onto the position stack and returns true if the stack is
   // not full, else returns false.
-  ABSL_MUST_USE_RESULT bool PushPosition(int position) {
+  [[nodiscard]] bool PushPosition(int position) {
     if (position_depth_ == kPositionStackSize) return false;
     position_stack_[position_depth_++] = position;
     return true;
@@ -845,7 +845,7 @@
   // beginning of the backref target.  Returns true on success.  Returns false
   // if parsing failed, the stack is exhausted, or the backref target position
   // is out of range.
-  ABSL_MUST_USE_RESULT bool BeginBackref() {
+  [[nodiscard]] bool BeginBackref() {
     // backref = B base-62-number (B already consumed)
     //
     // Reject backrefs that don't parse, overflow int, or don't point backward.
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index 5579221..2012184 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -556,14 +556,15 @@
   EXPECT_TRUE(Demangle("_ZL3Foov.part.9.165493.constprop.775.31805", tmp,
                        sizeof(tmp)));
   EXPECT_STREQ("Foo()", tmp);
-  // Invalid (. without anything else), should not demangle.
-  EXPECT_FALSE(Demangle("_ZL3Foov.", tmp, sizeof(tmp)));
-  // Invalid (. with mix of alpha and digits), should not demangle.
-  EXPECT_FALSE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp)));
-  // Invalid (.clone. not followed by number), should not demangle.
-  EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
-  // Invalid (.constprop. not followed by number), should not demangle.
-  EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
+  // Other suffixes should demangle too.
+  EXPECT_TRUE(Demangle("_ZL3Foov.", tmp, sizeof(tmp)));
+  EXPECT_STREQ("Foo()", tmp);
+  EXPECT_TRUE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp)));
+  EXPECT_STREQ("Foo()", tmp);
+  EXPECT_TRUE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
+  EXPECT_STREQ("Foo()", tmp);
+  EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
+  EXPECT_STREQ("Foo()", tmp);
 }
 
 TEST(Demangle, Discriminators) {
@@ -2017,6 +2018,13 @@
   TestOnInput(data.c_str());
 }
 
+TEST(DemangleRegression, ShortOutputBuffer) {
+  // This should not crash.
+  char buffer[1];
+  EXPECT_FALSE(
+      absl::debugging_internal::Demangle("_ZZ2wwE", buffer, sizeof(buffer)));
+}
+
 struct Base {
   virtual ~Base() = default;
 };
diff --git a/absl/debugging/internal/elf_mem_image.h b/absl/debugging/internal/elf_mem_image.h
index 19c4952..1fac29c 100644
--- a/absl/debugging/internal/elf_mem_image.h
+++ b/absl/debugging/internal/elf_mem_image.h
@@ -35,7 +35,7 @@
 #if defined(__ELF__) && !defined(__OpenBSD__) && !defined(__QNX__) && \
     !defined(__native_client__) && !defined(__asmjs__) &&             \
     !defined(__wasm__) && !defined(__HAIKU__) && !defined(__sun) &&   \
-    !defined(__VXWORKS__) && !defined(__hexagon__)
+    !defined(__VXWORKS__) && !defined(__hexagon__) && !defined(__XTENSA__)
 #define ABSL_HAVE_ELF_MEM_IMAGE 1
 #endif
 
diff --git a/absl/debugging/internal/stack_consumption.h b/absl/debugging/internal/stack_consumption.h
index f41b64c..f5ba557 100644
--- a/absl/debugging/internal/stack_consumption.h
+++ b/absl/debugging/internal/stack_consumption.h
@@ -24,7 +24,7 @@
 // Use this feature test macro to detect its availability.
 #ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
 #error ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION cannot be set directly
-#elif !defined(__APPLE__) && !defined(_WIN32) &&                     \
+#elif !defined(__APPLE__) && !defined(_WIN32) && !defined(__Fuchsia__) && \
     (defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
      defined(__aarch64__) || defined(__riscv))
 #define ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 1
diff --git a/absl/debugging/internal/stacktrace_aarch64-inl.inc b/absl/debugging/internal/stacktrace_aarch64-inl.inc
index b123479..1746b5d 100644
--- a/absl/debugging/internal/stacktrace_aarch64-inl.inc
+++ b/absl/debugging/internal/stacktrace_aarch64-inl.inc
@@ -18,6 +18,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/debugging/internal/address_is_readable.h"
+#include "absl/debugging/internal/addresses.h"
 #include "absl/debugging/internal/vdso_support.h"  // a no-op on non-elf or non-glibc systems
 #include "absl/debugging/stacktrace.h"
 
@@ -101,7 +102,8 @@
 // "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
 template<bool STRICT_UNWINDING, bool WITH_CONTEXT>
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
-ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY  // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.
 static void **NextStackFrame(void **old_frame_pointer, const void *uc,
                              const StackInfo *stack_info) {
   void **new_frame_pointer = reinterpret_cast<void**>(*old_frame_pointer);
@@ -124,6 +126,7 @@
       if (pre_signal_frame_pointer >= old_frame_pointer) {
         new_frame_pointer = pre_signal_frame_pointer;
       }
+    }
   }
 #endif
 
@@ -131,17 +134,13 @@
   if ((reinterpret_cast<uintptr_t>(new_frame_pointer) & 7) != 0)
     return nullptr;
 
-  // Check that alleged frame pointer is actually readable. This is to
-  // prevent "double fault" in case we hit the first fault due to e.g.
-  // stack corruption.
-  if (!absl::debugging_internal::AddressIsReadable(
-          new_frame_pointer))
-    return nullptr;
-  }
-
+  uintptr_t new_fp_comparable = reinterpret_cast<uintptr_t>(new_frame_pointer);
   // Only check the size if both frames are in the same stack.
-  if (InsideSignalStack(new_frame_pointer, stack_info) ==
-      InsideSignalStack(old_frame_pointer, stack_info)) {
+  const bool old_inside_signal_stack =
+      InsideSignalStack(old_frame_pointer, stack_info);
+  const bool new_inside_signal_stack =
+      InsideSignalStack(new_frame_pointer, stack_info);
+  if (new_inside_signal_stack == old_inside_signal_stack) {
     // Check frame size.  In strict mode, we assume frames to be under
     // 100,000 bytes.  In non-strict mode, we relax the limit to 1MB.
     const size_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
@@ -155,16 +154,15 @@
     if (frame_size > max_size) {
       size_t stack_low = stack_info->stack_low;
       size_t stack_high = stack_info->stack_high;
-      if (InsideSignalStack(new_frame_pointer, stack_info)) {
+      if (new_inside_signal_stack) {
         stack_low = stack_info->sig_stack_low;
         stack_high = stack_info->sig_stack_high;
       }
       if (stack_high < kUnknownStackEnd &&
           static_cast<size_t>(getpagesize()) < stack_low) {
-        const uintptr_t new_fp_u =
-            reinterpret_cast<uintptr_t>(new_frame_pointer);
         // Stack bounds are known.
-        if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {
+        if (!(stack_low < new_fp_comparable &&
+              new_fp_comparable <= stack_high)) {
           // new_frame_pointer is not within a known stack.
           return nullptr;
         }
@@ -174,8 +172,19 @@
       }
     }
   }
+  // New frame pointer is valid if it is inside either known stack or readable.
+  // This assumes that everything within either known stack is readable. Outside
+  // either known stack but readable is unexpected, and possibly corrupt, but
+  // for now assume it is valid. If it isn't actually valid, the next frame will
+  // be corrupt and we will detect that next iteration.
+  if (new_inside_signal_stack ||
+      (new_fp_comparable >= stack_info->stack_low &&
+       new_fp_comparable < stack_info->stack_high) ||
+      absl::debugging_internal::AddressIsReadable(new_frame_pointer)) {
+    return new_frame_pointer;
+  }
 
-  return new_frame_pointer;
+  return nullptr;
 }
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
@@ -184,8 +193,10 @@
 ABSL_ATTRIBUTE_NOINLINE
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
 ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
-static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
-                      const void *ucp, int *min_dropped_frames) {
+ABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.
+static int UnwindImpl(void **result, uintptr_t *frames, int *sizes,
+                      int max_depth, int skip_count, const void *ucp,
+                      int *min_dropped_frames) {
 #ifdef __GNUC__
   void **frame_pointer = reinterpret_cast<void**>(__builtin_frame_address(0));
 #else
@@ -219,10 +230,18 @@
     if (skip_count > 0) {
       skip_count--;
     } else {
-      result[n] = prev_return_address;
+      result[n] = reinterpret_cast<void *>(
+          absl::debugging_internal::StripPointerMetadata(prev_return_address));
       if (IS_STACK_FRAMES) {
-        sizes[n] = static_cast<int>(
-            ComputeStackFrameSize(prev_frame_pointer, frame_pointer));
+        if (frames != nullptr) {
+          frames[n] = absl::debugging_internal::StripPointerMetadata(
+                          prev_frame_pointer) +
+                      2 * sizeof(void *) /* go past the return address */;
+        }
+        if (sizes != nullptr) {
+          sizes[n] = static_cast<int>(
+              ComputeStackFrameSize(prev_frame_pointer, frame_pointer));
+        }
       }
       n++;
     }
diff --git a/absl/debugging/internal/stacktrace_arm-inl.inc b/absl/debugging/internal/stacktrace_arm-inl.inc
index 102a2a1..3feb521 100644
--- a/absl/debugging/internal/stacktrace_arm-inl.inc
+++ b/absl/debugging/internal/stacktrace_arm-inl.inc
@@ -19,6 +19,7 @@
 
 #include <cstdint>
 
+#include "absl/debugging/internal/addresses.h"
 #include "absl/debugging/stacktrace.h"
 
 // WARNING:
@@ -67,8 +68,9 @@
 #endif
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
-static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
-                      const void * /* ucp */, int *min_dropped_frames) {
+static int UnwindImpl(void **result, uintptr_t *frames, int *sizes,
+                      int max_depth, int skip_count, const void * /* ucp */,
+                      int *min_dropped_frames) {
 #ifdef __GNUC__
   void **sp = reinterpret_cast<void**>(__builtin_frame_address(0));
 #else
@@ -97,11 +99,18 @@
       result[n] = *sp;
 
       if (IS_STACK_FRAMES) {
-        if (next_sp > sp) {
-          sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp;
-        } else {
-          // A frame-size of 0 is used to indicate unknown frame size.
-          sizes[n] = 0;
+        if (frames != nullptr) {
+          frames[n] = absl::debugging_internal::StripPointerMetadata(sp) +
+                      1 * sizeof(void *) /* go past the return address */;
+        }
+        if (sizes != nullptr) {
+          if (next_sp > sp) {
+            sizes[n] = absl::debugging_internal::StripPointerMetadata(next_sp) -
+                       absl::debugging_internal::StripPointerMetadata(sp);
+          } else {
+            // A frame-size of 0 is used to indicate unknown frame size.
+            sizes[n] = 0;
+          }
         }
       }
       n++;
diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h
index 3929b1b..8f84a87 100644
--- a/absl/debugging/internal/stacktrace_config.h
+++ b/absl/debugging/internal/stacktrace_config.h
@@ -42,6 +42,12 @@
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_emscripten-inl.inc"
 
+#elif defined(__ANDROID__)
+#if defined(ABSL_HAVE_THREAD_LOCAL)
+#define ABSL_STACKTRACE_INL_HEADER \
+  "absl/debugging/internal/stacktrace_generic-inl.inc"
+#endif
+
 #elif defined(__linux__) && !defined(__ANDROID__)
 
 #if defined(NO_FRAME_POINTER) && \
@@ -52,11 +58,11 @@
   "absl/debugging/internal/stacktrace_libunwind-inl.inc"
 #define STACKTRACE_USES_LIBUNWIND 1
 #elif defined(NO_FRAME_POINTER) && defined(__has_include)
-#if __has_include(<execinfo.h>)
+#if __has_include(<execinfo.h>) && defined(ABSL_HAVE_THREAD_LOCAL)
 // Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_generic-inl.inc"
-#endif  // __has_include(<execinfo.h>)
+#endif  // __has_include(<execinfo.h>) && defined(ABSL_HAVE_THREAD_LOCAL)
 #elif defined(__i386__) || defined(__x86_64__)
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_x86-inl.inc"
@@ -70,11 +76,11 @@
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_riscv-inl.inc"
 #elif defined(__has_include)
-#if __has_include(<execinfo.h>)
+#if __has_include(<execinfo.h>) && defined(ABSL_HAVE_THREAD_LOCAL)
 // Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_generic-inl.inc"
-#endif  // __has_include(<execinfo.h>)
+#endif  // __has_include(<execinfo.h>) && defined(ABSL_HAVE_THREAD_LOCAL)
 #endif  // defined(__has_include)
 
 #endif  // defined(__linux__) && !defined(__ANDROID__)
diff --git a/absl/debugging/internal/stacktrace_emscripten-inl.inc b/absl/debugging/internal/stacktrace_emscripten-inl.inc
index 0f44451..2f39c70 100644
--- a/absl/debugging/internal/stacktrace_emscripten-inl.inc
+++ b/absl/debugging/internal/stacktrace_emscripten-inl.inc
@@ -21,8 +21,10 @@
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_EMSCRIPTEN_INL_H_
 
 #include <emscripten.h>
+#include <stdint.h>
 
 #include <atomic>
+#include <cstddef>
 #include <cstring>
 
 #include "absl/base/attributes.h"
@@ -62,8 +64,9 @@
 }();
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
-static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
-                      const void *ucp, int *min_dropped_frames) {
+static int UnwindImpl(void **result, uintptr_t *frames, int *sizes,
+                      int max_depth, int skip_count, const void *ucp,
+                      int *min_dropped_frames) {
   if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) {
     return 0;
   }
@@ -75,7 +78,8 @@
 
   int size;
   uintptr_t pc = emscripten_stack_snapshot();
-  size = emscripten_stack_unwind_buffer(pc, stack, kStackLength);
+  size =
+      static_cast<int>(emscripten_stack_unwind_buffer(pc, stack, kStackLength));
 
   int result_count = size - skip_count;
   if (result_count < 0) result_count = 0;
@@ -83,8 +87,13 @@
   for (int i = 0; i < result_count; i++) result[i] = stack[i + skip_count];
 
   if (IS_STACK_FRAMES) {
-    // No implementation for finding out the stack frame sizes yet.
-    memset(sizes, 0, sizeof(*sizes) * result_count);
+    // No implementation for finding out the stack frames yet.
+    if (frames != nullptr) {
+      memset(frames, 0, sizeof(*frames) * static_cast<size_t>(result_count));
+    }
+    if (sizes != nullptr) {
+      memset(sizes, 0, sizeof(*sizes) * static_cast<size_t>(result_count));
+    }
   }
   if (min_dropped_frames != nullptr) {
     if (size - skip_count - max_depth > 0) {
diff --git a/absl/debugging/internal/stacktrace_generic-inl.inc b/absl/debugging/internal/stacktrace_generic-inl.inc
index 5fa169a..4d5ba37 100644
--- a/absl/debugging/internal/stacktrace_generic-inl.inc
+++ b/absl/debugging/internal/stacktrace_generic-inl.inc
@@ -20,13 +20,26 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
 
+#ifndef __ANDROID__
 #include <execinfo.h>
+#endif
+
 #include <atomic>
+#include <cstdint>
 #include <cstring>
 
 #include "absl/debugging/stacktrace.h"
 #include "absl/base/attributes.h"
 
+// Android local modification: locally declare backtrace() as a weak symbol.
+// Normally we would use NDK's weak symbol mode, but for an unclear reason it
+// causes backtrace() to be strongly linked into some tests even when we set
+// sdk_version to 29, which breaks Mainline backwards compatibility tests.
+// TODO: b/432562276 - investigate root cause and remove this workaround.
+#ifdef __ANDROID__
+int backtrace(void** buffer, int size) ABSL_ATTRIBUTE_WEAK;
+#endif
+
 // Sometimes, we can try to get a stack trace from within a stack
 // trace, because we don't block signals inside this code (which would be too
 // expensive: the two extra system calls per stack trace do matter here).
@@ -46,6 +59,11 @@
 // Waiting until static initializers run seems to be late enough.
 // This file is included into stacktrace.cc so this will only run once.
 ABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() {
+#ifdef __ANDROID__
+  if (&backtrace == nullptr) {
+    return 0;
+  }
+#endif
   void* unused_stack[1];
   // Force the first backtrace to happen early to get the one-time shared lib
   // loading (allocation) out of the way. After the first call it is much safer
@@ -56,8 +74,9 @@
 }();
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
-static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
-                      const void *ucp, int *min_dropped_frames) {
+static int UnwindImpl(void** result, uintptr_t* frames, int* sizes,
+                      int max_depth, int skip_count, const void* ucp,
+                      int* min_dropped_frames) {
   if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) {
     return 0;
   }
@@ -79,8 +98,13 @@
     result[i] = stack[i + skip_count];
 
   if (IS_STACK_FRAMES) {
-    // No implementation for finding out the stack frame sizes yet.
-    memset(sizes, 0, sizeof(*sizes) * static_cast<size_t>(result_count));
+    // No implementation for finding out the stack frames yet.
+    if (frames != nullptr) {
+      memset(frames, 0, sizeof(*frames) * static_cast<size_t>(result_count));
+    }
+    if (sizes != nullptr) {
+      memset(sizes, 0, sizeof(*sizes) * static_cast<size_t>(result_count));
+    }
   }
   if (min_dropped_frames != nullptr) {
     if (size - skip_count - max_depth > 0) {
diff --git a/absl/debugging/internal/stacktrace_powerpc-inl.inc b/absl/debugging/internal/stacktrace_powerpc-inl.inc
index a49ed2f..f82ca8f 100644
--- a/absl/debugging/internal/stacktrace_powerpc-inl.inc
+++ b/absl/debugging/internal/stacktrace_powerpc-inl.inc
@@ -21,6 +21,7 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_
 
+#include "absl/debugging/internal/addresses.h"
 #if defined(__linux__)
 #include <asm/ptrace.h>   // for PT_NIP.
 #include <ucontext.h>     // for ucontext_t
@@ -40,22 +41,22 @@
 
 // Given a stack pointer, return the saved link register value.
 // Note that this is the link register for a callee.
-static inline void *StacktracePowerPCGetLR(void **sp) {
+static inline void **StacktracePowerPCGetLRPtr(void **sp) {
   // PowerPC has 3 main ABIs, which say where in the stack the
   // Link Register is.  For DARWIN and AIX (used by apple and
   // linux ppc64), it's in sp[2].  For SYSV (used by linux ppc),
   // it's in sp[1].
 #if defined(_CALL_AIX) || defined(_CALL_DARWIN)
-  return *(sp+2);
+  return (sp + 2);
 #elif defined(_CALL_SYSV)
-  return *(sp+1);
+  return (sp + 1);
 #elif defined(__APPLE__) || defined(__FreeBSD__) || \
     (defined(__linux__) && defined(__PPC64__))
   // This check is in case the compiler doesn't define _CALL_AIX/etc.
-  return *(sp+2);
+  return (sp + 2);
 #elif defined(__linux)
   // This check is in case the compiler doesn't define _CALL_SYSV.
-  return *(sp+1);
+  return (sp + 1);
 #else
 #error Need to specify the PPC ABI for your architecture.
 #endif
@@ -68,6 +69,7 @@
 template<bool STRICT_UNWINDING, bool IS_WITH_CONTEXT>
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
 ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.
 static void **NextStackFrame(void **old_sp, const void *uc) {
   void **new_sp = (void **) *old_sp;
   enum { kStackAlignment = 16 };
@@ -125,9 +127,8 @@
       }
     }
 
-    if (new_sp != nullptr &&
-        kernel_symbol_status == kAddressValid &&
-        StacktracePowerPCGetLR(new_sp) == kernel_sigtramp_rt64_address) {
+    if (new_sp != nullptr && kernel_symbol_status == kAddressValid &&
+        *StacktracePowerPCGetLRPtr(new_sp) == kernel_sigtramp_rt64_address) {
       const ucontext_t* signal_context =
           reinterpret_cast<const ucontext_t*>(uc);
       void **const sp_before_signal =
@@ -164,8 +165,10 @@
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
 ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
-static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
-                      const void *ucp, int *min_dropped_frames) {
+ABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.
+static int UnwindImpl(void **result, uintptr_t *frames, int *sizes,
+                      int max_depth, int skip_count, const void *ucp,
+                      int *min_dropped_frames) {
   void **sp;
   // Apple macOS uses an old version of gnu as -- both Darwin 7.9.0 (Panther)
   // and Darwin 8.8.1 (Tiger) use as 1.38.  This means we have to use a
@@ -211,13 +214,21 @@
     if (skip_count > 0) {
       skip_count--;
     } else {
-      result[n] = StacktracePowerPCGetLR(sp);
+      void **lr = StacktracePowerPCGetLRPtr(sp);
+      result[n] = *lr;
       if (IS_STACK_FRAMES) {
-        if (next_sp > sp) {
-          sizes[n] = (uintptr_t)next_sp - (uintptr_t)sp;
-        } else {
-          // A frame-size of 0 is used to indicate unknown frame size.
-          sizes[n] = 0;
+        if (frames != nullptr) {
+          frames[n] = absl::debugging_internal::StripPointerMetadata(lr) +
+                      1 * sizeof(void *) /* go past the return address */;
+        }
+        if (sizes != nullptr) {
+          if (next_sp > sp) {
+            sizes[n] = absl::debugging_internal::StripPointerMetadata(next_sp) -
+                       absl::debugging_internal::StripPointerMetadata(sp);
+          } else {
+            // A frame-size of 0 is used to indicate unknown frame size.
+            sizes[n] = 0;
+          }
         }
       }
       n++;
diff --git a/absl/debugging/internal/stacktrace_riscv-inl.inc b/absl/debugging/internal/stacktrace_riscv-inl.inc
index 20183fa..f9919c6 100644
--- a/absl/debugging/internal/stacktrace_riscv-inl.inc
+++ b/absl/debugging/internal/stacktrace_riscv-inl.inc
@@ -20,6 +20,7 @@
 #include <sys/ucontext.h>
 
 #include "absl/base/config.h"
+#include "absl/debugging/internal/addresses.h"
 #if defined(__linux__)
 #include <sys/mman.h>
 #include <ucontext.h>
@@ -36,15 +37,16 @@
 #include "absl/base/attributes.h"
 #include "absl/debugging/stacktrace.h"
 
-static const uintptr_t kUnknownFrameSize = 0;
+static constexpr ptrdiff_t kUnknownFrameSize = 0;
 
 // Compute the size of a stack frame in [low..high).  We assume that low < high.
 // Return size of kUnknownFrameSize.
 template <typename T>
-static inline uintptr_t ComputeStackFrameSize(const T *low, const T *high) {
+static inline ptrdiff_t ComputeStackFrameSize(const T *low, const T *high) {
   const char *low_char_ptr = reinterpret_cast<const char *>(low);
   const char *high_char_ptr = reinterpret_cast<const char *>(high);
-  return low < high ? high_char_ptr - low_char_ptr : kUnknownFrameSize;
+  return low < high ? static_cast<ptrdiff_t>(high_char_ptr - low_char_ptr)
+                    : kUnknownFrameSize;
 }
 
 // Given a pointer to a stack frame, locate and return the calling stackframe,
@@ -54,6 +56,7 @@
 template <bool STRICT_UNWINDING, bool WITH_CONTEXT>
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
 ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.
 static void ** NextStackFrame(void **old_frame_pointer, const void *uc,
                               const std::pair<size_t, size_t> range) {
   //               .
@@ -93,8 +96,8 @@
 
   // Check frame size.  In strict mode, we assume frames to be under 100,000
   // bytes.  In non-strict mode, we relax the limit to 1MB.
-  const uintptr_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
-  const uintptr_t frame_size =
+  const ptrdiff_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
+  const ptrdiff_t frame_size =
       ComputeStackFrameSize(old_frame_pointer, new_frame_pointer);
   if (frame_size == kUnknownFrameSize) {
     if (STRICT_UNWINDING)
@@ -116,8 +119,10 @@
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
 ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
-static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
-                      const void *ucp, int *min_dropped_frames) {
+ABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.
+static int UnwindImpl(void **result, uintptr_t *frames, int *sizes,
+                      int max_depth, int skip_count, const void *ucp,
+                      int *min_dropped_frames) {
   // The `frame_pointer` that is computed here points to the top of the frame.
   // The two words preceding the address are the return address and the previous
   // frame pointer.
@@ -151,7 +156,14 @@
     } else {
       result[n] = return_address;
       if (IS_STACK_FRAMES) {
-        sizes[n] = ComputeStackFrameSize(frame_pointer, next_frame_pointer);
+        // NextStackFrame() has already checked that frame size fits to int
+        if (frames != nullptr) {
+          frames[n] =
+              absl::debugging_internal::StripPointerMetadata(frame_pointer);
+        }
+        if (sizes != nullptr) {
+          sizes[n] = ComputeStackFrameSize(frame_pointer, next_frame_pointer);
+        }
       }
       n++;
     }
diff --git a/absl/debugging/internal/stacktrace_unimplemented-inl.inc b/absl/debugging/internal/stacktrace_unimplemented-inl.inc
index 5b8fb19..ec63940 100644
--- a/absl/debugging/internal/stacktrace_unimplemented-inl.inc
+++ b/absl/debugging/internal/stacktrace_unimplemented-inl.inc
@@ -2,9 +2,10 @@
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
-static int UnwindImpl(void** /* result */, int* /* sizes */,
-                      int /* max_depth */, int /* skip_count */,
-                      const void* /* ucp */, int *min_dropped_frames) {
+static int UnwindImpl(void** /* result */, uintptr_t* /* frames */,
+                      int* /* sizes */, int /* max_depth */,
+                      int /* skip_count */, const void* /* ucp */,
+                      int* min_dropped_frames) {
   if (min_dropped_frames != nullptr) {
     *min_dropped_frames = 0;
   }
diff --git a/absl/debugging/internal/stacktrace_win32-inl.inc b/absl/debugging/internal/stacktrace_win32-inl.inc
index ef2b973..f57c187 100644
--- a/absl/debugging/internal/stacktrace_win32-inl.inc
+++ b/absl/debugging/internal/stacktrace_win32-inl.inc
@@ -37,42 +37,29 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
 
-#include <windows.h>    // for GetProcAddress and GetModuleHandle
+#include <windows.h>  // CaptureStackBackTrace
+
 #include <cassert>
 
-typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
-    IN ULONG frames_to_skip,
-    IN ULONG frames_to_capture,
-    OUT PVOID *backtrace,
-    OUT PULONG backtrace_hash);
-
-// It is not possible to load RtlCaptureStackBackTrace at static init time in
-// UWP. CaptureStackBackTrace is the public version of RtlCaptureStackBackTrace
-#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
-    !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
-static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
-    &::CaptureStackBackTrace;
-#else
-// Load the function we need at static init time, where we don't have
-// to worry about someone else holding the loader's lock.
-static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
-    (RtlCaptureStackBackTrace_Function*)GetProcAddress(
-        GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
-#endif  // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
-
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
-static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
-                      const void*, int* min_dropped_frames) {
+static int UnwindImpl(void** result, uintptr_t* frames, int* sizes,
+                      int max_depth, int skip_count, const void*,
+                      int* min_dropped_frames) {
   USHORT n = 0;
-  if (!RtlCaptureStackBackTrace_fn || skip_count < 0 || max_depth < 0) {
+  if (skip_count < 0 || max_depth < 0) {
     // can't get a stacktrace with no function/invalid args
   } else {
-    n = RtlCaptureStackBackTrace_fn(static_cast<ULONG>(skip_count) + 2,
-                                    static_cast<ULONG>(max_depth), result, 0);
+    n = CaptureStackBackTrace(static_cast<ULONG>(skip_count) + 2,
+                              static_cast<ULONG>(max_depth), result, 0);
   }
   if (IS_STACK_FRAMES) {
-    // No implementation for finding out the stack frame sizes yet.
-    memset(sizes, 0, sizeof(*sizes) * n);
+    // No implementation for finding out the stack frames yet.
+    if (frames != nullptr) {
+      memset(frames, 0, sizeof(*frames) * n);
+    }
+    if (sizes != nullptr) {
+      memset(sizes, 0, sizeof(*sizes) * n);
+    }
   }
   if (min_dropped_frames != nullptr) {
     // Not implemented.
diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc
index 1975ba7..96b128e 100644
--- a/absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/absl/debugging/internal/stacktrace_x86-inl.inc
@@ -33,6 +33,7 @@
 #include "absl/base/macros.h"
 #include "absl/base/port.h"
 #include "absl/debugging/internal/address_is_readable.h"
+#include "absl/debugging/internal/addresses.h"
 #include "absl/debugging/internal/vdso_support.h"  // a no-op on non-elf or non-glibc systems
 #include "absl/debugging/stacktrace.h"
 
@@ -163,6 +164,7 @@
 template <bool STRICT_UNWINDING, bool WITH_CONTEXT>
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
 ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.
 static void **NextStackFrame(void **old_fp, const void *uc,
                              size_t stack_low, size_t stack_high) {
   void **new_fp = (void **)*old_fp;
@@ -326,9 +328,11 @@
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
 ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_THREAD   // May read random elements from stack.
 ABSL_ATTRIBUTE_NOINLINE
-static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
-                      const void *ucp, int *min_dropped_frames) {
+static int UnwindImpl(void **result, uintptr_t *frames, int *sizes,
+                      int max_depth, int skip_count, const void *ucp,
+                      int *min_dropped_frames) {
   int n = 0;
   void **fp = reinterpret_cast<void **>(__builtin_frame_address(0));
 
@@ -349,13 +353,19 @@
     } else {
       result[n] = *(fp + 1);
       if (IS_STACK_FRAMES) {
-        if (next_fp > fp) {
-          sizes[n] = static_cast<int>(
-              reinterpret_cast<uintptr_t>(next_fp) -
-              reinterpret_cast<uintptr_t>(fp));
-        } else {
-          // A frame-size of 0 is used to indicate unknown frame size.
-          sizes[n] = 0;
+        if (frames) {
+          frames[n] = absl::debugging_internal::StripPointerMetadata(fp) +
+                      2 * sizeof(void *) /* go past the return address */;
+        }
+        if (sizes) {
+          if (next_fp > fp) {
+            sizes[n] = static_cast<int>(
+                absl::debugging_internal::StripPointerMetadata(next_fp) -
+                absl::debugging_internal::StripPointerMetadata(fp));
+          } else {
+            // A frame-size of 0 is used to indicate unknown frame size.
+            sizes[n] = 0;
+          }
         }
       }
       n++;
diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc
index fdb8798..1370bcc 100644
--- a/absl/debugging/leak_check.cc
+++ b/absl/debugging/leak_check.cc
@@ -28,7 +28,7 @@
 #include <sanitizer/lsan_interface.h>
 
 #if ABSL_HAVE_ATTRIBUTE_WEAK
-extern "C" ABSL_ATTRIBUTE_WEAK int __lsan_is_turned_off();
+extern "C" ABSL_ATTRIBUTE_WEAK int __lsan_is_turned_off() { return 0; }
 #endif
 
 namespace absl {
@@ -37,13 +37,13 @@
 
 #if ABSL_HAVE_ATTRIBUTE_WEAK
 bool LeakCheckerIsActive() {
-  return !(&__lsan_is_turned_off && __lsan_is_turned_off());
+  return __lsan_is_turned_off() == 0;
 }
 #else
 bool LeakCheckerIsActive() { return true; }
 #endif
 
-bool FindAndReportLeaks() { return __lsan_do_recoverable_leak_check(); }
+bool FindAndReportLeaks() { return __lsan_do_recoverable_leak_check() != 0; }
 void DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); }
 void RegisterLivePointers(const void* ptr, size_t size) {
   __lsan_register_root_region(ptr, size);
diff --git a/absl/debugging/stacktrace.cc b/absl/debugging/stacktrace.cc
index ff8069f..f71e80c 100644
--- a/absl/debugging/stacktrace.cc
+++ b/absl/debugging/stacktrace.cc
@@ -36,12 +36,42 @@
 
 #include "absl/debugging/stacktrace.h"
 
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
 #include <atomic>
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
 #include "absl/base/port.h"
 #include "absl/debugging/internal/stacktrace_config.h"
 
+#ifdef ABSL_INTERNAL_HAVE_ALLOCA
+#error ABSL_INTERNAL_HAVE_ALLOCA cannot be directly set
+#endif
+
+#ifdef _WIN32
+#include <malloc.h>
+#define ABSL_INTERNAL_HAVE_ALLOCA 1
+#else
+#ifdef __has_include
+#if __has_include(<alloca.h>)
+#include <alloca.h>
+#define ABSL_INTERNAL_HAVE_ALLOCA 1
+#elif !defined(alloca)
+static void* alloca(size_t) noexcept { return nullptr; }
+#endif
+#endif
+#endif
+
+#ifdef ABSL_INTERNAL_HAVE_ALLOCA
+static constexpr bool kHaveAlloca = true;
+#else
+static constexpr bool kHaveAlloca = false;
+#endif
+
 #if defined(ABSL_STACKTRACE_INL_HEADER)
 #include ABSL_STACKTRACE_INL_HEADER
 #else
@@ -66,59 +96,111 @@
 std::atomic<Unwinder> custom;
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, int* sizes,
-                                               int max_depth, int skip_count,
-                                               const void* uc,
+ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, uintptr_t* frames,
+                                               int* sizes, int max_depth,
+                                               int skip_count, const void* uc,
                                                int* min_dropped_frames) {
-  Unwinder f = &UnwindImpl<IS_STACK_FRAMES, IS_WITH_CONTEXT>;
   Unwinder g = custom.load(std::memory_order_acquire);
-  if (g != nullptr) f = g;
-
+  int size;
   // Add 1 to skip count for the unwinder function itself
-  int size = (*f)(result, sizes, max_depth, skip_count + 1, uc,
-                  min_dropped_frames);
-  // To disable tail call to (*f)(...)
+  ++skip_count;
+  if (g != nullptr) {
+    size = (*g)(result, sizes, max_depth, skip_count, uc, min_dropped_frames);
+    // Frame pointers aren't returned by existing hooks, so clear them.
+    if (frames != nullptr) {
+      std::fill(frames, frames + size, uintptr_t());
+    }
+  } else {
+    size = UnwindImpl<IS_STACK_FRAMES, IS_WITH_CONTEXT>(
+        result, frames, sizes, max_depth, skip_count, uc, min_dropped_frames);
+  }
   ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
   return size;
 }
 
 }  // anonymous namespace
 
-ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackFrames(
-    void** result, int* sizes, int max_depth, int skip_count) {
-  return Unwind<true, false>(result, sizes, max_depth, skip_count, nullptr,
-                             nullptr);
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
+internal_stacktrace::GetStackFrames(void** result, uintptr_t* frames,
+                                    int* sizes, int max_depth, int skip_count) {
+  if (internal_stacktrace::ShouldFixUpStack()) {
+    size_t depth = static_cast<size_t>(Unwind<true, true>(
+        result, frames, sizes, max_depth, skip_count, nullptr, nullptr));
+    internal_stacktrace::FixUpStack(result, frames, sizes,
+                                    static_cast<size_t>(max_depth), depth);
+    return static_cast<int>(depth);
+  }
+
+  return Unwind<true, false>(result, frames, sizes, max_depth, skip_count,
+                             nullptr, nullptr);
 }
 
 ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
-GetStackFramesWithContext(void** result, int* sizes, int max_depth,
-                          int skip_count, const void* uc,
-                          int* min_dropped_frames) {
-  return Unwind<true, true>(result, sizes, max_depth, skip_count, uc,
+internal_stacktrace::GetStackFramesWithContext(void** result, uintptr_t* frames,
+                                               int* sizes, int max_depth,
+                                               int skip_count, const void* uc,
+                                               int* min_dropped_frames) {
+  if (internal_stacktrace::ShouldFixUpStack()) {
+    size_t depth = static_cast<size_t>(Unwind<true, true>(
+        result, frames, sizes, max_depth, skip_count, uc, min_dropped_frames));
+    internal_stacktrace::FixUpStack(result, frames, sizes,
+                                    static_cast<size_t>(max_depth), depth);
+    return static_cast<int>(depth);
+  }
+
+  return Unwind<true, true>(result, frames, sizes, max_depth, skip_count, uc,
                             min_dropped_frames);
 }
 
 ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace(
     void** result, int max_depth, int skip_count) {
-  return Unwind<false, false>(result, nullptr, max_depth, skip_count, nullptr,
-                              nullptr);
+  if (internal_stacktrace::ShouldFixUpStack()) {
+    if constexpr (kHaveAlloca) {
+      const size_t nmax = static_cast<size_t>(max_depth);
+      uintptr_t* frames =
+          static_cast<uintptr_t*>(alloca(nmax * sizeof(*frames)));
+      int* sizes = static_cast<int*>(alloca(nmax * sizeof(*sizes)));
+      size_t depth = static_cast<size_t>(Unwind<true, false>(
+          result, frames, sizes, max_depth, skip_count, nullptr, nullptr));
+      internal_stacktrace::FixUpStack(result, frames, sizes, nmax, depth);
+      return static_cast<int>(depth);
+    }
+  }
+
+  return Unwind<false, false>(result, nullptr, nullptr, max_depth, skip_count,
+                              nullptr, nullptr);
 }
 
 ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
 GetStackTraceWithContext(void** result, int max_depth, int skip_count,
                          const void* uc, int* min_dropped_frames) {
-  return Unwind<false, true>(result, nullptr, max_depth, skip_count, uc,
-                             min_dropped_frames);
+  if (internal_stacktrace::ShouldFixUpStack()) {
+    if constexpr (kHaveAlloca) {
+      const size_t nmax = static_cast<size_t>(max_depth);
+      uintptr_t* frames =
+          static_cast<uintptr_t*>(alloca(nmax * sizeof(*frames)));
+      int* sizes = static_cast<int*>(alloca(nmax * sizeof(*sizes)));
+      size_t depth = static_cast<size_t>(
+          Unwind<true, true>(result, frames, sizes, max_depth, skip_count, uc,
+                             min_dropped_frames));
+      internal_stacktrace::FixUpStack(result, frames, sizes, nmax, depth);
+      return static_cast<int>(depth);
+    }
+  }
+
+  return Unwind<false, true>(result, nullptr, nullptr, max_depth, skip_count,
+                             uc, min_dropped_frames);
 }
 
 void SetStackUnwinder(Unwinder w) {
   custom.store(w, std::memory_order_release);
 }
 
-int DefaultStackUnwinder(void** pcs, int* sizes, int depth, int skip,
-                         const void* uc, int* min_dropped_frames) {
+ABSL_ATTRIBUTE_ALWAYS_INLINE static inline int DefaultStackUnwinderImpl(
+    void** pcs, uintptr_t* frames, int* sizes, int depth, int skip,
+    const void* uc, int* min_dropped_frames) {
   skip++;  // For this function
-  Unwinder f = nullptr;
+  decltype(&UnwindImpl<false, false>) f;
   if (sizes == nullptr) {
     if (uc == nullptr) {
       f = &UnwindImpl<false, false>;
@@ -132,11 +214,46 @@
       f = &UnwindImpl<true, true>;
     }
   }
-  volatile int x = 0;
-  int n = (*f)(pcs, sizes, depth, skip, uc, min_dropped_frames);
-  x = 1; (void) x;  // To disable tail call to (*f)(...)
+  return (*f)(pcs, frames, sizes, depth, skip, uc, min_dropped_frames);
+}
+
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
+internal_stacktrace::DefaultStackUnwinder(void** pcs, uintptr_t* frames,
+                                          int* sizes, int depth, int skip,
+                                          const void* uc,
+                                          int* min_dropped_frames) {
+  int n = DefaultStackUnwinderImpl(pcs, frames, sizes, depth, skip, uc,
+                                   min_dropped_frames);
+  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
   return n;
 }
 
+ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int DefaultStackUnwinder(
+    void** pcs, int* sizes, int depth, int skip, const void* uc,
+    int* min_dropped_frames) {
+  int n = DefaultStackUnwinderImpl(pcs, nullptr, sizes, depth, skip, uc,
+                                   min_dropped_frames);
+  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
+  return n;
+}
+
+ABSL_ATTRIBUTE_WEAK bool internal_stacktrace::ShouldFixUpStack() {
+  return false;
+}
+
+// Fixes up the stack trace of the current thread, in the first `depth` frames
+// of each buffer. The buffers need to be larger than `depth`, to accommodate
+// any newly inserted elements. `depth` is updated to reflect the new number of
+// elements valid across all the buffers. (It is therefore recommended that all
+// buffer sizes be equal.)
+//
+// The `frames` and `sizes` parameters denote the bounds of the stack frame
+// corresponding to each instruction pointer in the `pcs`.
+// Any elements inside these buffers may be zero or null, in which case that
+// information is assumed to be absent/unavailable.
+ABSL_ATTRIBUTE_WEAK void internal_stacktrace::FixUpStack(void**, uintptr_t*,
+                                                         int*, size_t,
+                                                         size_t&) {}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/debugging/stacktrace.h b/absl/debugging/stacktrace.h
index 0ec0ffd..8777172 100644
--- a/absl/debugging/stacktrace.h
+++ b/absl/debugging/stacktrace.h
@@ -31,11 +31,53 @@
 #ifndef ABSL_DEBUGGING_STACKTRACE_H_
 #define ABSL_DEBUGGING_STACKTRACE_H_
 
+#include <stddef.h>
+#include <stdint.h>
+
+#include "absl/base/attributes.h"
 #include "absl/base/config.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
+namespace internal_stacktrace {
+
+// Same as `absl::GetStackFrames`, but with an optional `frames` parameter to
+// allow callers to receive the raw stack frame addresses.
+// This is internal for now; use `absl::GetStackFrames()` instead.
+extern int GetStackFrames(void** result, uintptr_t* frames, int* sizes,
+                          int max_depth, int skip_count);
+
+// Same as `absl::GetStackFramesWithContext`, but with an optional `frames`
+// parameter to allow callers to receive a start address for each stack frame.
+// The address may be zero in cases where it cannot be computed.
+//
+// DO NOT use this function without consulting the owners of absl/debuggging.
+// There is NO GUARANTEE on the precise frame addresses returned on any given
+// platform. It is only intended to provide sufficient non-overlapping bounds on
+// the local variables of a stack frame when used in conjunction with the
+// returned frame sizes. The actual pointers may be ABI-dependent, may vary at
+// run time, and are subject to breakage without notice.
+//
+// Implementation note:
+// Currently, we *attempt* to return the Canonical Frame Address (CFA) in DWARF
+// on most platforms. This is the value of the stack pointer just before the
+// 'call' instruction is executed in the caller.
+// Not all platforms and toolchains support this exact address, so this should
+// not be relied on for correctness.
+extern int GetStackFramesWithContext(void** result, uintptr_t* frames,
+                                     int* sizes, int max_depth, int skip_count,
+                                     const void* uc, int* min_dropped_frames);
+
+// Same as `absl::DefaultStackUnwinder`, but with an optional `frames` parameter
+// to allow callers to receive the raw stack frame addresses.
+// This is internal for now; do not depend on this externally.
+extern int DefaultStackUnwinder(void** pcs, uintptr_t* frames, int* sizes,
+                                int max_depth, int skip_count, const void* uc,
+                                int* min_dropped_frames);
+
+}  // namespace internal_stacktrace
+
 // GetStackFrames()
 //
 // Records program counter values for up to `max_depth` frames, skipping the
@@ -78,8 +120,13 @@
 //
 // This routine may return fewer stack frame entries than are
 // available. Also note that `result` and `sizes` must both be non-null.
-extern int GetStackFrames(void** result, int* sizes, int max_depth,
-                          int skip_count);
+ABSL_ATTRIBUTE_ALWAYS_INLINE inline int GetStackFrames(void** result,
+                                                       int* sizes,
+                                                       int max_depth,
+                                                       int skip_count) {
+  return internal_stacktrace::GetStackFrames(result, nullptr, sizes, max_depth,
+                                             skip_count);
+}
 
 // GetStackFramesWithContext()
 //
@@ -102,9 +149,12 @@
 // or other reasons. (This value will be set to `0` if no frames were dropped.)
 // The number of total stack frames is guaranteed to be >= skip_count +
 // max_depth + *min_dropped_frames.
-extern int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
-                                     int skip_count, const void* uc,
-                                     int* min_dropped_frames);
+ABSL_ATTRIBUTE_ALWAYS_INLINE inline int GetStackFramesWithContext(
+    void** result, int* sizes, int max_depth, int skip_count, const void* uc,
+    int* min_dropped_frames) {
+  return internal_stacktrace::GetStackFramesWithContext(
+      result, nullptr, sizes, max_depth, skip_count, uc, min_dropped_frames);
+}
 
 // GetStackTrace()
 //
@@ -225,6 +275,24 @@
 // working.
 extern bool StackTraceWorksForTest();
 }  // namespace debugging_internal
+
+namespace internal_stacktrace {
+extern bool ShouldFixUpStack();
+
+// Fixes up the stack trace of the current thread, in the first `depth` frames
+// of each buffer. The buffers need to be larger than `depth`, to accommodate
+// any newly inserted elements. `depth` is updated to reflect the new number of
+// elements valid across all the buffers. (It is therefore recommended that all
+// buffer sizes be equal.)
+//
+// The `frames` and `sizes` parameters denote the bounds of the stack frame
+// corresponding to each instruction pointer in the `pcs`.
+// Any elements inside these buffers may be zero or null, in which case that
+// information is assumed to be absent/unavailable.
+extern void FixUpStack(void** pcs, uintptr_t* frames, int* sizes,
+                       size_t capacity, size_t& depth);
+}  // namespace internal_stacktrace
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/debugging/stacktrace_test.cc b/absl/debugging/stacktrace_test.cc
index 31f7723..4477d84 100644
--- a/absl/debugging/stacktrace_test.cc
+++ b/absl/debugging/stacktrace_test.cc
@@ -14,12 +14,48 @@
 
 #include "absl/debugging/stacktrace.h"
 
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
-#include "absl/base/macros.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/optimization.h"
+#include "absl/types/span.h"
+
+static int g_should_fixup_calls = 0;
+static int g_fixup_calls = 0;
+static bool g_enable_fixup = false;
+
+#if ABSL_HAVE_ATTRIBUTE_WEAK
+bool absl::internal_stacktrace::ShouldFixUpStack() {
+  ++g_should_fixup_calls;
+  return g_enable_fixup;
+}
+
+void absl::internal_stacktrace::FixUpStack(void**, uintptr_t*, int*, size_t,
+                                           size_t&) {
+  ++g_fixup_calls;
+}
+#endif
 
 namespace {
 
+using ::testing::ContainerEq;
+using ::testing::Contains;
+using ::testing::internal::Cleanup;
+
+struct StackTrace {
+  static constexpr int kStackCount = 64;
+  int depth;
+  void* result[kStackCount];
+  uintptr_t frames[kStackCount];
+  int sizes[kStackCount];
+};
+
 // This test is currently only known to pass on Linux x86_64/aarch64.
 #if defined(__linux__) && (defined(__x86_64__) || defined(__aarch64__))
 ABSL_ATTRIBUTE_NOINLINE void Unwind(void* p) {
@@ -44,4 +80,219 @@
 }
 #endif
 
+// This is a separate function to avoid inlining.
+ABSL_ATTRIBUTE_NOINLINE static void FixupNoFixupEquivalenceNoInline() {
+#if defined(__riscv)
+  GTEST_SKIP() << "Skipping test on RISC-V due to pre-existing failure";
+#endif
+
+#if ABSL_HAVE_ATTRIBUTE_WEAK
+  // This test is known not to pass on MSVC (due to weak symbols)
+
+  const Cleanup restore_state([enable_fixup = g_enable_fixup,
+                               fixup_calls = g_fixup_calls,
+                               should_fixup_calls = g_should_fixup_calls]() {
+    g_enable_fixup = enable_fixup;
+    g_fixup_calls = fixup_calls;
+    g_should_fixup_calls = should_fixup_calls;
+  });
+
+  constexpr int kSkip = 1;  // Skip our own frame, whose return PCs won't match
+  constexpr auto kStackCount = 1;
+
+  StackTrace a;
+  StackTrace b;
+
+  // ==========================================================================
+
+  g_fixup_calls = 0;
+  g_should_fixup_calls = 0;
+  a.depth = absl::GetStackTrace(a.result, kStackCount, kSkip);
+  g_enable_fixup = !g_enable_fixup;
+  b.depth = absl::GetStackTrace(b.result, kStackCount, kSkip);
+  EXPECT_THAT(
+      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));
+  EXPECT_GT(g_should_fixup_calls, 0);
+  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);
+
+  // ==========================================================================
+
+  g_fixup_calls = 0;
+  g_should_fixup_calls = 0;
+  a.depth = absl::GetStackFrames(a.result, a.sizes, kStackCount, kSkip);
+  g_enable_fixup = !g_enable_fixup;
+  b.depth = absl::GetStackFrames(b.result, b.sizes, kStackCount, kSkip);
+  EXPECT_THAT(
+      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));
+  EXPECT_THAT(
+      absl::MakeSpan(a.sizes, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.sizes, static_cast<size_t>(b.depth))));
+  EXPECT_GT(g_should_fixup_calls, 0);
+  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);
+
+  // ==========================================================================
+
+  g_fixup_calls = 0;
+  g_should_fixup_calls = 0;
+  a.depth = absl::GetStackTraceWithContext(a.result, kStackCount, kSkip,
+                                           nullptr, nullptr);
+  g_enable_fixup = !g_enable_fixup;
+  b.depth = absl::GetStackTraceWithContext(b.result, kStackCount, kSkip,
+                                           nullptr, nullptr);
+  EXPECT_THAT(
+      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));
+  EXPECT_GT(g_should_fixup_calls, 0);
+  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);
+
+  // ==========================================================================
+
+  g_fixup_calls = 0;
+  g_should_fixup_calls = 0;
+  a.depth = absl::GetStackFramesWithContext(a.result, a.sizes, kStackCount,
+                                            kSkip, nullptr, nullptr);
+  g_enable_fixup = !g_enable_fixup;
+  b.depth = absl::GetStackFramesWithContext(b.result, b.sizes, kStackCount,
+                                            kSkip, nullptr, nullptr);
+  EXPECT_THAT(
+      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));
+  EXPECT_THAT(
+      absl::MakeSpan(a.sizes, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.sizes, static_cast<size_t>(b.depth))));
+  EXPECT_GT(g_should_fixup_calls, 0);
+  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);
+
+  // ==========================================================================
+
+  g_fixup_calls = 0;
+  g_should_fixup_calls = 0;
+  a.depth = absl::internal_stacktrace::GetStackFrames(
+      a.result, a.frames, a.sizes, kStackCount, kSkip);
+  g_enable_fixup = !g_enable_fixup;
+  b.depth = absl::internal_stacktrace::GetStackFrames(
+      b.result, b.frames, b.sizes, kStackCount, kSkip);
+  EXPECT_THAT(
+      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));
+  EXPECT_THAT(
+      absl::MakeSpan(a.sizes, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.sizes, static_cast<size_t>(b.depth))));
+  EXPECT_THAT(
+      absl::MakeSpan(a.frames, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.frames, static_cast<size_t>(b.depth))));
+  EXPECT_GT(g_should_fixup_calls, 0);
+  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);
+
+  // ==========================================================================
+
+  g_fixup_calls = 0;
+  g_should_fixup_calls = 0;
+  a.depth = absl::internal_stacktrace::GetStackFramesWithContext(
+      a.result, a.frames, a.sizes, kStackCount, kSkip, nullptr, nullptr);
+  g_enable_fixup = !g_enable_fixup;
+  b.depth = absl::internal_stacktrace::GetStackFramesWithContext(
+      b.result, b.frames, b.sizes, kStackCount, kSkip, nullptr, nullptr);
+  EXPECT_THAT(
+      absl::MakeSpan(a.result, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.result, static_cast<size_t>(b.depth))));
+  EXPECT_THAT(
+      absl::MakeSpan(a.sizes, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.sizes, static_cast<size_t>(b.depth))));
+  EXPECT_THAT(
+      absl::MakeSpan(a.frames, static_cast<size_t>(a.depth)),
+      ContainerEq(absl::MakeSpan(b.frames, static_cast<size_t>(b.depth))));
+  EXPECT_GT(g_should_fixup_calls, 0);
+  EXPECT_GE(g_should_fixup_calls, g_fixup_calls);
+
+  // ==========================================================================
+#else
+  GTEST_SKIP() << "Need weak symbol support";
+#endif
+}
+
+TEST(StackTrace, FixupNoFixupEquivalence) { FixupNoFixupEquivalenceNoInline(); }
+
+#if ABSL_HAVE_BUILTIN(__builtin_frame_address)
+struct FrameInfo {
+  const void* return_address;
+  uintptr_t frame_address;
+};
+
+// Returns the canonical frame address and return address for the current stack
+// frame, while capturing the stack trace at the same time.
+// This performs any platform-specific adjustments necessary to convert from the
+// compiler built-ins to the expected API outputs.
+ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS     // May read random elements from stack.
+    ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY  // May read random elements from stack.
+        ABSL_ATTRIBUTE_NOINLINE static FrameInfo
+        CaptureBacktraceNoInline(StackTrace& backtrace) {
+  FrameInfo result;
+  result.return_address = __builtin_return_address(0);
+  // Large enough to cover all realistic slots the return address could be in
+  const int kMaxReturnAddressIndex = 5;
+  void* const* bfa = static_cast<void* const*>(__builtin_frame_address(0));
+  backtrace.depth = absl::internal_stacktrace::GetStackFramesWithContext(
+      backtrace.result, backtrace.frames, backtrace.sizes,
+      StackTrace::kStackCount, /*skip_count=*/0,
+      /*uc=*/nullptr, /*min_dropped_frames=*/nullptr);
+  // Make sure the return address is at a reasonable location in the frame
+  ptrdiff_t i;
+  for (i = 0; i < kMaxReturnAddressIndex; ++i) {
+    // Avoid std::find() here, since it lacks no-sanitize attributes.
+    if (bfa[i] == result.return_address) {
+      break;
+    }
+  }
+  result.frame_address =
+      i < kMaxReturnAddressIndex
+          ? reinterpret_cast<uintptr_t>(
+                bfa + i + 1 /* get the Canonical Frame Address (CFA) */)
+          : 0;
+  return result;
+}
+
+TEST(StackTrace, CanonicalFrameAddresses) {
+  // Now capture a stack trace and verify that the return addresses and frame
+  // addresses line up for one frame.
+  StackTrace backtrace;
+  const auto [return_address, frame_address] =
+      CaptureBacktraceNoInline(backtrace);
+  auto return_addresses = absl::MakeSpan(backtrace.result)
+                              .subspan(0, static_cast<size_t>(backtrace.depth));
+  auto frame_addresses = absl::MakeSpan(backtrace.frames)
+                             .subspan(0, static_cast<size_t>(backtrace.depth));
+
+  // Many platforms don't support this by default.
+  bool support_is_expected = false;
+
+  if (support_is_expected) {
+    // If all zeros were returned, that is valid per the function's contract.
+    // It just means we don't support returning frame addresses on this
+    // platform.
+    bool supported = static_cast<size_t>(std::count(frame_addresses.begin(),
+                                                    frame_addresses.end(), 0)) <
+                     frame_addresses.size();
+    EXPECT_TRUE(supported);
+    if (supported) {
+      ASSERT_TRUE(frame_address)
+          << "unable to obtain frame address corresponding to return address";
+      EXPECT_THAT(return_addresses, Contains(return_address).Times(1));
+      EXPECT_THAT(frame_addresses, Contains(frame_address).Times(1));
+      ptrdiff_t ifound = std::find(return_addresses.begin(),
+                                   return_addresses.end(), return_address) -
+                         return_addresses.begin();
+      // Make sure we found the frame in the first place.
+      ASSERT_LT(ifound, backtrace.depth);
+      // Make sure the frame address actually corresponds to the return
+      // address.
+      EXPECT_EQ(frame_addresses[static_cast<size_t>(ifound)], frame_address);
+      // Make sure the addresses only appear once.
+    }
+  }
+}
+#endif
+
 }  // namespace
diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc
index 638d395..344436f 100644
--- a/absl/debugging/symbolize.cc
+++ b/absl/debugging/symbolize.cc
@@ -12,12 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
 #include "absl/debugging/symbolize.h"
 
 #ifdef _WIN32
 #include <winapifamily.h>
-#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \
-    WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
 // UWP doesn't have access to win32 APIs.
 #define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32
 #endif
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index ae75cd4..9836c93 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -52,6 +52,7 @@
 #include <elf.h>
 #include <fcntl.h>
 #include <link.h>  // For ElfW() macro.
+#include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -124,12 +125,20 @@
 // Some platforms use a special .opd section to store function pointers.
 const char kOpdSectionName[] = ".opd";
 
-#if (defined(__powerpc__) && !(_CALL_ELF > 1)) || defined(__ia64)
+#if defined(__powerpc64__) && defined(_CALL_ELF)
+#if _CALL_ELF <= 1
+#define ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI 1
+#endif
+#endif
+#if defined(ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI) || defined(__ia64)
 // Use opd section for function descriptors on these platforms, the function
 // address is the first word of the descriptor.
-enum { kPlatformUsesOPDSections = 1 };
-#else  // not PPC or IA64
-enum { kPlatformUsesOPDSections = 0 };
+//
+// https://maskray.me/blog/2023-02-26-linker-notes-on-power-isa notes that
+// opd sections are used on 64-bit PowerPC with the ELFv1 ABI.
+inline constexpr bool kPlatformUsesOPDSections = true;
+#else
+inline constexpr bool kPlatformUsesOPDSections = false;
 #endif
 
 // This works for PowerPC & IA64 only.  A function descriptor consist of two
@@ -376,6 +385,46 @@
   SymbolCacheLine symbol_cache_[SYMBOL_CACHE_LINES];
 };
 
+// Protect against client code closing low-valued file descriptors it doesn't
+// actually own.
+int OpenReadOnlyWithHighFD(const char *fname) {
+  static int high_fd = [] {
+    struct rlimit rlim{};
+    const int rc = getrlimit(RLIMIT_NOFILE, &rlim);
+    if (rc == 0 && rlim.rlim_cur >= 2000) {
+      const int max_fd = static_cast<int>(rlim.rlim_cur);
+
+      // This will return 2000 on reasonably-configured systems.
+      return std::min<int>(2000, max_fd - 1000);
+    }
+    ABSL_RAW_LOG(WARNING, "Unable to get high fd: rc=%d, limit=%ld",  //
+                 rc, static_cast<long>(rlim.rlim_cur));
+    return -1;
+  }();
+  constexpr int kOpenFlags = O_RDONLY | O_CLOEXEC;
+  if (high_fd >= 1000) {
+    const int fd = open(fname, kOpenFlags);
+    if (fd != -1 && fd < high_fd) {
+      // Try to relocate fd to high range.
+      static_assert(kOpenFlags & O_CLOEXEC,
+                    "F_DUPFD_CLOEXEC assumes O_CLOEXEC");
+      const int fd2 = fcntl(fd, F_DUPFD_CLOEXEC, high_fd);
+      if (fd2 != -1) {
+        // Successfully obtained high fd. Use it.
+        close(fd);
+        return fd2;
+      } else {
+        ABSL_RAW_LOG(WARNING, "Unable to dup fd=%d above %d, errno=%d", fd,
+                     high_fd, errno);
+      }
+    }
+    // Either open failed and fd==-1, or fd is already above high_fd, or fcntl
+    // failed and fd is valid (but low).
+    return fd;
+  }
+  return open(fname, kOpenFlags);
+}
+
 static std::atomic<Symbolizer *> g_cached_symbolizer;
 
 }  // namespace
@@ -541,11 +590,9 @@
         (buf_bytes > num_bytes_left) ? num_bytes_left : buf_bytes;
     const off_t offset = sh_offset + static_cast<off_t>(i * sizeof(buf[0]));
     const ssize_t len = file->ReadFromOffset(buf, num_bytes_to_read, offset);
-    if (len < 0) {
-      ABSL_RAW_LOG(
-          WARNING,
-          "Reading %zu bytes from offset %ju returned %zd which is negative.",
-          num_bytes_to_read, static_cast<intmax_t>(offset), len);
+    if (len <= 0) {
+      ABSL_RAW_LOG(WARNING, "Reading %zu bytes from offset %ju returned %zd.",
+                   num_bytes_to_read, static_cast<intmax_t>(offset), len);
       return false;
     }
     if (static_cast<size_t>(len) % sizeof(buf[0]) != 0) {
@@ -1066,7 +1113,7 @@
   snprintf(maps_path, sizeof(maps_path), "/proc/self/task/%d/maps", getpid());
 
   int maps_fd;
-  NO_INTR(maps_fd = open(maps_path, O_RDONLY));
+  NO_INTR(maps_fd = OpenReadOnlyWithHighFD(maps_path));
   FileDescriptor wrapped_maps_fd(maps_fd);
   if (wrapped_maps_fd.get() < 0) {
     ABSL_RAW_LOG(WARNING, "%s: errno=%d", maps_path, errno);
@@ -1340,7 +1387,7 @@
   if (memcmp(obj->start_addr, ELFMAG, SELFMAG) != 0) {
     return;
   }
-  int fd = open("/proc/self/exe", O_RDONLY);
+  int fd = OpenReadOnlyWithHighFD("/proc/self/exe");
   if (fd == -1) {
     return;
   }
@@ -1364,7 +1411,7 @@
 
 static bool MaybeInitializeObjFile(ObjFile *obj) {
   if (obj->fd < 0) {
-    obj->fd = open(obj->filename, O_RDONLY);
+    obj->fd = OpenReadOnlyWithHighFD(obj->filename);
 
     if (obj->fd < 0) {
       // Getting /proc/self/exe here means that we were hinted.
@@ -1372,7 +1419,7 @@
         // /proc/self/exe may be inaccessible (due to setuid, etc.), so try
         // accessing the binary via argv0.
         if (argv0_value != nullptr) {
-          obj->fd = open(argv0_value, O_RDONLY);
+          obj->fd = OpenReadOnlyWithHighFD(argv0_value);
         }
       } else {
         MaybeOpenFdFromSelfExe(obj);
@@ -1412,11 +1459,11 @@
       }
       phoff += phentsize;
 
-#if defined(__powerpc__) && !(_CALL_ELF > 1)
-      // On the PowerPC ELF v1 ABI, function pointers actually point to function
-      // descriptors. These descriptors are stored in an .opd section, which is
-      // mapped read-only. We thus need to look at all readable segments, not
-      // just the executable ones.
+#ifdef ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI
+      // On the PowerPC 64-bit ELFv1 ABI, function pointers actually point to
+      // function descriptors. These descriptors are stored in an .opd section,
+      // which is mapped read-only. We thus need to look at all readable
+      // segments, not just the executable ones.
       constexpr int interesting = PF_R;
 #else
       constexpr int interesting = PF_X | PF_R;
@@ -1723,3 +1770,5 @@
   return absl::debugging_internal::GetFileMappingHint(start, end, offset,
                                                       filename);
 }
+
+#undef ABSL_INTERNAL_HAVE_PPC64_ELFV1_ABI
diff --git a/absl/debugging/symbolize_emscripten.inc b/absl/debugging/symbolize_emscripten.inc
index a0f344d..f6da0ac 100644
--- a/absl/debugging/symbolize_emscripten.inc
+++ b/absl/debugging/symbolize_emscripten.inc
@@ -58,12 +58,13 @@
     return false;
   }
 
-  strncpy(out, func_name, out_size);
+  strncpy(out, func_name, static_cast<size_t>(out_size));
 
   if (out[out_size - 1] != '\0') {
     // strncpy() does not '\0' terminate when it truncates.
     static constexpr char kEllipsis[] = "...";
-    int ellipsis_size = std::min<int>(sizeof(kEllipsis) - 1, out_size - 1);
+    size_t ellipsis_size =
+        std::min(sizeof(kEllipsis) - 1, static_cast<size_t>(out_size) - 1);
     memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);
     out[out_size - 1] = '\0';
   }
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc
index d0feab2..69b0a26 100644
--- a/absl/debugging/symbolize_test.cc
+++ b/absl/debugging/symbolize_test.cc
@@ -167,9 +167,8 @@
 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
   void *return_address = __builtin_return_address(0);
   const char *symbol = TrySymbolize(return_address);
-  CHECK_NE(symbol, nullptr) << "TestWithReturnAddress failed";
-  CHECK_STREQ(symbol, "main") << "TestWithReturnAddress failed";
-  std::cout << "TestWithReturnAddress passed" << std::endl;
+  ASSERT_NE(symbol, nullptr) << "TestWithReturnAddress failed";
+  EXPECT_STREQ(symbol, "main") << "TestWithReturnAddress failed";
 #endif
 }
 
@@ -490,10 +489,9 @@
     (defined(__i386__) || defined(__x86_64__))
   void *pc = non_inline_func();
   const char *symbol = TrySymbolize(pc);
-  CHECK_NE(symbol, nullptr) << "TestWithPCInsideNonInlineFunction failed";
-  CHECK_STREQ(symbol, "non_inline_func")
+  ASSERT_NE(symbol, nullptr) << "TestWithPCInsideNonInlineFunction failed";
+  EXPECT_STREQ(symbol, "non_inline_func")
       << "TestWithPCInsideNonInlineFunction failed";
-  std::cout << "TestWithPCInsideNonInlineFunction passed" << std::endl;
 #endif
 }
 
@@ -502,9 +500,8 @@
     (defined(__i386__) || defined(__x86_64__))
   void *pc = inline_func();  // Must be inlined.
   const char *symbol = TrySymbolize(pc);
-  CHECK_NE(symbol, nullptr) << "TestWithPCInsideInlineFunction failed";
-  CHECK_STREQ(symbol, __FUNCTION__) << "TestWithPCInsideInlineFunction failed";
-  std::cout << "TestWithPCInsideInlineFunction passed" << std::endl;
+  ASSERT_NE(symbol, nullptr) << "TestWithPCInsideInlineFunction failed";
+  EXPECT_STREQ(symbol, __FUNCTION__) << "TestWithPCInsideInlineFunction failed";
 #endif
 }
 }
@@ -545,9 +542,8 @@
 void ABSL_ATTRIBUTE_NOINLINE TestArmThumbOverlap() {
 #if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
   const char *symbol = TrySymbolize((void *)&ArmThumbOverlapArm);
-  CHECK_NE(symbol, nullptr) << "TestArmThumbOverlap failed";
-  CHECK_STREQ("ArmThumbOverlapArm()", symbol) << "TestArmThumbOverlap failed";
-  std::cout << "TestArmThumbOverlap passed" << std::endl;
+  ASSERT_NE(symbol, nullptr) << "TestArmThumbOverlap failed";
+  EXPECT_STREQ("ArmThumbOverlapArm()", symbol) << "TestArmThumbOverlap failed";
 #endif
 }
 
diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc
index 53a099a..589890f 100644
--- a/absl/debugging/symbolize_win32.inc
+++ b/absl/debugging/symbolize_win32.inc
@@ -15,7 +15,9 @@
 // See "Retrieving Symbol Information by Address":
 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx
 
+#include <ntstatus.h>
 #include <windows.h>
+#include <winternl.h>
 
 // MSVC header dbghelp.h has a warning for an ignored typedef.
 #pragma warning(push)
@@ -45,13 +47,30 @@
   // symbols be loaded. This is the fastest, most efficient way to use
   // the symbol handler.
   SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME);
-  if (!SymInitialize(process, nullptr, true)) {
-    // GetLastError() returns a Win32 DWORD, but we assign to
-    // unsigned long long to simplify the ABSL_RAW_LOG case below.  The uniform
-    // initialization guarantees this is not a narrowing conversion.
-    const unsigned long long error{GetLastError()};  // NOLINT(runtime/int)
-    ABSL_RAW_LOG(FATAL, "SymInitialize() failed: %llu", error);
+  DWORD syminitialize_error;
+  constexpr int kSymInitializeRetries = 5;
+  for (int i = 0; i < kSymInitializeRetries; ++i) {
+    if (SymInitialize(process, nullptr, true)) {
+      return;
+    }
+
+    // SymInitialize can fail sometimes with a STATUS_INFO_LENGTH_MISMATCH
+    // NTSTATUS (0xC0000004), which can happen when a module load occurs during
+    // the SymInitialize call. In this case, we should try calling SymInitialize
+    // again.
+    syminitialize_error = GetLastError();
+    // Both NTSTATUS and DWORD are 32-bit numbers, which makes the cast safe.
+    if (syminitialize_error !=
+        static_cast<DWORD>(STATUS_INFO_LENGTH_MISMATCH)) {
+      break;
+    }
   }
+
+  // GetLastError() returns a Win32 DWORD, but we assign to
+  // unsigned long long to simplify the ABSL_RAW_LOG case below.  The uniform
+  // initialization guarantees this is not a narrowing conversion.
+  const unsigned long long error{syminitialize_error};
+  ABSL_RAW_LOG(FATAL, "SymInitialize() failed: %llu", error);
 }
 
 bool Symbolize(const void* pc, char* out, int out_size) {
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 7a8ec7e..620af2b 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -66,6 +66,7 @@
         ":path_util",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:no_destructor",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -87,6 +88,7 @@
         ":program_name",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:no_destructor",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -190,6 +192,7 @@
         ":private_handle_accessor",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:fast_type_id",
         "//absl/base:no_destructor",
         "//absl/container:flat_hash_map",
         "//absl/strings",
@@ -219,6 +222,8 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
+        "//absl/base:fast_type_id",
+        "//absl/base:no_destructor",
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/strings",
@@ -242,6 +247,7 @@
         ":reflection",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:nullability",
         "//absl/strings",
     ],
 )
@@ -270,6 +276,7 @@
         ":reflection",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:no_destructor",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -318,6 +325,7 @@
         "//absl/algorithm:container",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:no_destructor",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -349,8 +357,8 @@
         ":reflection",
         "//absl/memory",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -364,8 +372,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -399,8 +407,8 @@
         "//absl/strings",
         "//absl/time",
         "//absl/types:optional",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -425,7 +433,7 @@
         "//absl/strings",
         "//absl/time",
         "//absl/types:optional",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -439,8 +447,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":marshalling",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -470,8 +478,8 @@
         "//absl/log",
         "//absl/strings",
         "//absl/types:span",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -485,8 +493,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":path_util",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -498,12 +506,15 @@
     ],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    tags = ["no_test_wasm"],
+    tags = [
+        "no_test_fuchsia_x64",
+        "no_test_wasm",
+    ],
     deps = [
         ":program_name",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -528,8 +539,8 @@
         ":reflection",
         "//absl/memory",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -549,8 +560,8 @@
         "//absl/base",
         "//absl/container:fixed_array",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -567,8 +578,8 @@
         ":path_util",
         ":program_name",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -597,6 +608,6 @@
         ":usage",
         ":usage_internal",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index 7376d11..d0ea452 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -45,6 +45,7 @@
   DEPS
     absl::config
     absl::core_headers
+    absl::no_destructor
     absl::flags_path_util
     absl::strings
     absl::synchronization
@@ -68,6 +69,7 @@
     absl::flags_path_util
     absl::flags_program_name
     absl::core_headers
+    absl::no_destructor
     absl::strings
     absl::synchronization
 )
@@ -163,6 +165,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::config
+    absl::fast_type_id
     absl::flags_commandlineflag
     absl::flags_private_handle_accessor
     absl::flags_config
@@ -188,10 +191,12 @@
   DEPS
     absl::base
     absl::config
+    absl::fast_type_id
     absl::flags_commandlineflag
     absl::flags_commandlineflag_internal
     absl::flags_config
     absl::flags_marshalling
+    absl::no_destructor
     absl::synchronization
     absl::meta
     absl::utility
@@ -215,6 +220,7 @@
     absl::flags_internal
     absl::flags_reflection
     absl::core_headers
+    absl::nullability
     absl::strings
 )
 
@@ -259,6 +265,7 @@
     absl::config
     absl::core_headers
     absl::flags_usage_internal
+    absl::no_destructor
     absl::raw_logging_internal
     absl::strings
     absl::synchronization
@@ -289,6 +296,7 @@
     absl::flags_program_name
     absl::flags_reflection
     absl::flags_usage
+    absl::no_destructor
     absl::strings
     absl::synchronization
 )
diff --git a/absl/flags/commandlineflag.cc b/absl/flags/commandlineflag.cc
index 9f3b4a5..4140230 100644
--- a/absl/flags/commandlineflag.cc
+++ b/absl/flags/commandlineflag.cc
@@ -24,6 +24,7 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
+absl::string_view CommandLineFlag::TypeName() const { return ""; }
 bool CommandLineFlag::IsRetired() const { return false; }
 bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {
   return ParseFrom(value, flags_internal::SET_FLAGS_VALUE,
diff --git a/absl/flags/commandlineflag.h b/absl/flags/commandlineflag.h
index 26ec0e7..9098b4c 100644
--- a/absl/flags/commandlineflag.h
+++ b/absl/flags/commandlineflag.h
@@ -30,7 +30,7 @@
 #include <string>
 
 #include "absl/base/config.h"
-#include "absl/base/internal/fast_type_id.h"
+#include "absl/base/fast_type_id.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
@@ -80,7 +80,7 @@
   // Return true iff flag has type T.
   template <typename T>
   inline bool IsOfType() const {
-    return TypeId() == base_internal::FastTypeId<T>();
+    return TypeId() == FastTypeId<T>();
   }
 
   // absl::CommandLineFlag::TryGet()
@@ -200,6 +200,13 @@
   // Checks that flags default value can be converted to string and back to the
   // flag's value type.
   virtual void CheckDefaultValueParsingRoundtrip() const = 0;
+
+  // absl::CommandLineFlag::TypeName()
+  //
+  // Returns string representation of the type of this flag
+  // (the way it is spelled in the ABSL_FLAG macro).
+  // The default implementation returns the empty string.
+  virtual absl::string_view TypeName() const;
 };
 #if defined(__GNUC__) && !defined(__clang__)
 #pragma GCC diagnostic pop
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index a8e0e93..e052d5f 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -35,6 +35,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
+#include "absl/base/nullability.h"
 #include "absl/base/optimization.h"
 #include "absl/flags/commandlineflag.h"
 #include "absl/flags/config.h"
@@ -94,7 +95,7 @@
 //   // FLAGS_firstname is a Flag of type `std::string`
 //   std::string first_name = absl::GetFlag(FLAGS_firstname);
 template <typename T>
-ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
+[[nodiscard]] T GetFlag(const absl::Flag<T>& flag) {
   return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
 }
 
@@ -106,7 +107,7 @@
 // thread-safe, but is potentially expensive. Avoid setting flags in general,
 // but especially within performance-critical code.
 template <typename T>
-void SetFlag(absl::Flag<T>* flag, const T& v) {
+void SetFlag(absl::Flag<T>* absl_nonnull flag, const T& v) {
   flags_internal::FlagImplPeer::InvokeSet(*flag, v);
 }
 
@@ -114,7 +115,7 @@
 // convertible to `T`. E.g., use this overload to pass a "const char*" when `T`
 // is `std::string`.
 template <typename T, typename V>
-void SetFlag(absl::Flag<T>* flag, const V& v) {
+void SetFlag(absl::Flag<T>* absl_nonnull flag, const V& v) {
   T value(v);
   flags_internal::FlagImplPeer::InvokeSet(*flag, value);
 }
@@ -204,12 +205,14 @@
 
 #if ABSL_FLAGS_STRIP_NAMES
 #define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
+#define ABSL_FLAG_IMPL_TYPENAME(txt) ""
 #define ABSL_FLAG_IMPL_FILENAME() ""
 #define ABSL_FLAG_IMPL_REGISTRAR(T, flag)                                      \
   absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \
                                                 nullptr)
 #else
 #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
+#define ABSL_FLAG_IMPL_TYPENAME(txt) txt
 #define ABSL_FLAG_IMPL_FILENAME() __FILE__
 #define ABSL_FLAG_IMPL_REGISTRAR(T, flag)                                     \
   absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \
@@ -261,16 +264,17 @@
 // Note: Name of registrar object is not arbitrary. It is used to "grab"
 // global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
 // of defining two flags with names foo and nofoo.
-#define ABSL_FLAG_IMPL(Type, name, default_value, help)                       \
-  extern ::absl::Flag<Type> FLAGS_##name;                                     \
-  namespace absl /* block flags in namespaces */ {}                           \
-  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)           \
-  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                             \
-  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                              \
-      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),              \
-      ABSL_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \
-  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;             \
-  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                   \
+#define ABSL_FLAG_IMPL(Type, name, default_value, help)               \
+  extern ::absl::Flag<Type> FLAGS_##name;                             \
+  namespace absl /* block flags in namespaces */ {}                   \
+  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)   \
+  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                     \
+  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                      \
+      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_TYPENAME(#Type), \
+      ABSL_FLAG_IMPL_FILENAME(), ABSL_FLAG_IMPL_HELP_ARG(name),       \
+      ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)};                        \
+  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;     \
+  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =           \
       ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
 
 // ABSL_RETIRED_FLAG
@@ -290,8 +294,7 @@
 // arguments unchanged (unless of course you actually want to retire the flag
 // type at this time as well).
 //
-// `default_value` is only used as a double check on the type. `explanation` is
-// unused.
+// `default_value` and `explanation` are unused.
 // TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of
 // retired flags are cleaned up.
 #define ABSL_RETIRED_FLAG(type, name, default_value, explanation)      \
diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc
index 8af5bf7..e3ab24c 100644
--- a/absl/flags/flag_test.cc
+++ b/absl/flags/flag_test.cc
@@ -149,9 +149,9 @@
 #define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind)                        \
   constexpr flags::FlagDefaultArg f1default##T{                            \
       flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind};     \
-  constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T};     \
+  constexpr absl::Flag<T> f1##T{"f1", #T, "file", help_arg, f1default##T}; \
   ABSL_CONST_INIT absl::Flag<T> f2##T {                                    \
-    "f2", "file",                                                          \
+    "f2", #T, "file",                                                      \
         {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
         flags::FlagDefaultArg {                                            \
       flags::FlagDefaultSrc(&TestMakeDflt<T>),                             \
diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h
index ebfe81b..daef4e3 100644
--- a/absl/flags/internal/commandlineflag.h
+++ b/absl/flags/internal/commandlineflag.h
@@ -17,7 +17,7 @@
 #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 
 #include "absl/base/config.h"
-#include "absl/base/internal/fast_type_id.h"
+#include "absl/base/fast_type_id.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -28,7 +28,7 @@
 // cases this id is enough to uniquely identify the flag's value type. In a few
 // cases we'll have to resort to using actual RTTI implementation if it is
 // available.
-using FlagFastTypeId = absl::base_internal::FastTypeIdType;
+using FlagFastTypeId = absl::FastTypeIdType;
 
 // Options that control SetCommandLineOptionWithMode.
 enum FlagSettingMode {
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc
index 981f19f..37f6ef1 100644
--- a/absl/flags/internal/flag.cc
+++ b/absl/flags/internal/flag.cc
@@ -34,7 +34,10 @@
 #include "absl/base/config.h"
 #include "absl/base/const_init.h"
 #include "absl/base/dynamic_annotations.h"
+#include "absl/base/fast_type_id.h"
+#include "absl/base/no_destructor.h"
 #include "absl/base/optimization.h"
+#include "absl/base/thread_annotations.h"
 #include "absl/flags/config.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/usage_config.h"
@@ -57,7 +60,7 @@
 // Currently we only validate flag values for user-defined flag types.
 bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
 #define DONT_VALIDATE(T, _) \
-  if (flag_type_id == base_internal::FastTypeId<T>()) return false;
+  if (flag_type_id == absl::FastTypeId<T>()) return false;
   ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE)
 #undef DONT_VALIDATE
 
@@ -85,11 +88,15 @@
 // we move the memory to the freelist where it lives indefinitely, so it can
 // still be safely accessed. This also prevents leak checkers from complaining
 // about the leaked memory that can no longer be accessed through any pointer.
-ABSL_CONST_INIT absl::Mutex s_freelist_guard(absl::kConstInit);
-ABSL_CONST_INIT std::vector<void*>* s_freelist = nullptr;
+absl::Mutex* FreelistMutex() {
+  static absl::NoDestructor<absl::Mutex> mutex;
+  return mutex.get();
+}
+ABSL_CONST_INIT std::vector<void*>* s_freelist ABSL_GUARDED_BY(FreelistMutex())
+    ABSL_PT_GUARDED_BY(FreelistMutex()) = nullptr;
 
 void AddToFreelist(void* p) {
-  absl::MutexLock l(&s_freelist_guard);
+  absl::MutexLock l(FreelistMutex());
   if (!s_freelist) {
     s_freelist = new std::vector<void*>;
   }
@@ -101,7 +108,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 uint64_t NumLeakedFlagValues() {
-  absl::MutexLock l(&s_freelist_guard);
+  absl::MutexLock l(FreelistMutex());
   return s_freelist == nullptr ? 0u : s_freelist->size();
 }
 
@@ -336,6 +343,8 @@
 
 absl::string_view FlagImpl::Name() const { return name_; }
 
+absl::string_view FlagImpl::TypeName() const { return type_name_; }
+
 std::string FlagImpl::Filename() const {
   return flags_internal::GetUsageConfig().normalize_filename(filename_);
 }
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index a0be31d..b61a247 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -57,7 +57,7 @@
 using Flag = flags_internal::Flag<T>;
 
 template <typename T>
-ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
+[[nodiscard]] T GetFlag(const absl::Flag<T>& flag);
 
 template <typename T>
 void SetFlag(absl::Flag<T>* flag, const T& v);
@@ -373,9 +373,13 @@
 
   static constexpr int RequiredAlignment() { return 4; }
 
+  constexpr MaskedPointer() : ptr_(nullptr) {}
   constexpr explicit MaskedPointer(ptr_t rhs) : ptr_(rhs) {}
   MaskedPointer(ptr_t rhs, bool is_candidate);
 
+  MaskedPointer(const MaskedPointer& rhs) = default;
+  MaskedPointer& operator=(const MaskedPointer& rhs) = default;
+
   void* Ptr() const {
     return reinterpret_cast<void*>(reinterpret_cast<mask_t>(ptr_) &
                                    kPtrValueMask);
@@ -578,10 +582,12 @@
 #endif
 class FlagImpl final : public CommandLineFlag {
  public:
-  constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
-                     FlagHelpArg help, FlagValueStorageKind value_kind,
+  constexpr FlagImpl(const char* name, const char* type_name,
+                     const char* filename, FlagOpFn op, FlagHelpArg help,
+                     FlagValueStorageKind value_kind,
                      FlagDefaultArg default_arg)
       : name_(name),
+        type_name_(type_name),
         filename_(filename),
         op_(op),
         help_(help.source),
@@ -694,6 +700,7 @@
 
   // CommandLineFlag interface implementation
   absl::string_view Name() const override;
+  absl::string_view TypeName() const override;
   std::string Filename() const override;
   std::string Help() const override;
   FlagFastTypeId TypeId() const override;
@@ -727,6 +734,10 @@
 
   // Flags name passed to ABSL_FLAG as second arg.
   const char* const name_;
+
+  // Flags type passed to ABSL_FLAG as first arg.
+  const char* const type_name_;
+
   // The file name where ABSL_FLAG resides.
   const char* const filename_;
   // Type-specific operations vtable.
@@ -772,7 +783,7 @@
   // heap allocation during initialization, which is both slows program startup
   // and can fail. Using reserved space + placement new allows us to avoid both
   // problems.
-  alignas(absl::Mutex) mutable char data_guard_[sizeof(absl::Mutex)];
+  alignas(absl::Mutex) mutable unsigned char data_guard_[sizeof(absl::Mutex)];
 };
 #if defined(__GNUC__) && !defined(__clang__)
 #pragma GCC diagnostic pop
@@ -785,9 +796,9 @@
 template <typename T>
 class Flag {
  public:
-  constexpr Flag(const char* name, const char* filename, FlagHelpArg help,
-                 const FlagDefaultArg default_arg)
-      : impl_(name, filename, &FlagOps<T>, help,
+  constexpr Flag(const char* name, const char* type_name, const char* filename,
+                 FlagHelpArg help, const FlagDefaultArg default_arg)
+      : impl_(name, type_name, filename, &FlagOps<T>, help,
               flags_internal::StorageKind<T>(), default_arg),
         value_() {}
 
@@ -817,7 +828,7 @@
     U u;
 
 #if !defined(NDEBUG)
-    impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+    impl_.AssertValidType(absl::FastTypeId<T>(), &GenRuntimeTypeId<T>);
 #endif
 
     if (ABSL_PREDICT_FALSE(!value_.Get(impl_.seq_lock_, u.value))) {
@@ -826,7 +837,7 @@
     return std::move(u.value);
   }
   void Set(const T& v) {
-    impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+    impl_.AssertValidType(absl::FastTypeId<T>(), &GenRuntimeTypeId<T>);
     impl_.Write(&v);
   }
 
@@ -865,7 +876,8 @@
 template <typename T>
 void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
   struct AlignedSpace {
-    alignas(MaskedPointer::RequiredAlignment()) alignas(T) char buf[sizeof(T)];
+    alignas(MaskedPointer::RequiredAlignment()) alignas(
+        T) unsigned char buf[sizeof(T)];
   };
   using Allocator = std::allocator<AlignedSpace>;
   switch (op) {
@@ -890,7 +902,7 @@
     case FlagOp::kSizeof:
       return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T)));
     case FlagOp::kFastTypeId:
-      return const_cast<void*>(base_internal::FastTypeId<T>());
+      return const_cast<void*>(absl::FastTypeId<T>());
     case FlagOp::kRuntimeTypeId:
       return const_cast<std::type_info*>(GenRuntimeTypeId<T>());
     case FlagOp::kParse: {
diff --git a/absl/flags/internal/private_handle_accessor.cc b/absl/flags/internal/private_handle_accessor.cc
index a7eb58b..610d1ff 100644
--- a/absl/flags/internal/private_handle_accessor.cc
+++ b/absl/flags/internal/private_handle_accessor.cc
@@ -59,6 +59,10 @@
   return flag.ParseFrom(value, set_mode, source, error);
 }
 
+absl::string_view PrivateHandleAccessor::TypeName(const CommandLineFlag& flag) {
+  return flag.TypeName();
+}
+
 }  // namespace flags_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/private_handle_accessor.h b/absl/flags/internal/private_handle_accessor.h
index c64435c..bf4154c 100644
--- a/absl/flags/internal/private_handle_accessor.h
+++ b/absl/flags/internal/private_handle_accessor.h
@@ -52,6 +52,9 @@
   static bool ParseFrom(CommandLineFlag& flag, absl::string_view value,
                         flags_internal::FlagSettingMode set_mode,
                         flags_internal::ValueSource source, std::string& error);
+
+  // Access to CommandLineFlag::TypeName.
+  static absl::string_view TypeName(const CommandLineFlag& flag);
 };
 
 }  // namespace flags_internal
diff --git a/absl/flags/internal/program_name.cc b/absl/flags/internal/program_name.cc
index 51d698d..fb06643 100644
--- a/absl/flags/internal/program_name.cc
+++ b/absl/flags/internal/program_name.cc
@@ -19,7 +19,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
-#include "absl/base/const_init.h"
+#include "absl/base/no_destructor.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/flags/internal/path_util.h"
 #include "absl/strings/string_view.h"
@@ -29,30 +29,31 @@
 ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit);
-ABSL_CONST_INIT static std::string* program_name
-    ABSL_GUARDED_BY(program_name_guard) = nullptr;
+static absl::Mutex* ProgramNameMutex() {
+  static absl::NoDestructor<absl::Mutex> mutex;
+  return mutex.get();
+}
+ABSL_CONST_INIT static std::string* program_name ABSL_GUARDED_BY(
+    ProgramNameMutex()) ABSL_PT_GUARDED_BY(ProgramNameMutex()) = nullptr;
 
 std::string ProgramInvocationName() {
-  absl::MutexLock l(&program_name_guard);
-
+  absl::MutexLock l(ProgramNameMutex());
   return program_name ? *program_name : "UNKNOWN";
 }
 
 std::string ShortProgramInvocationName() {
-  absl::MutexLock l(&program_name_guard);
-
+  absl::MutexLock l(ProgramNameMutex());
   return program_name ? std::string(flags_internal::Basename(*program_name))
                       : "UNKNOWN";
 }
 
 void SetProgramInvocationName(absl::string_view prog_name_str) {
-  absl::MutexLock l(&program_name_guard);
-
-  if (!program_name)
+  absl::MutexLock l(ProgramNameMutex());
+  if (!program_name) {
     program_name = new std::string(prog_name_str);
-  else
+  } else {
     program_name->assign(prog_name_str.data(), prog_name_str.size());
+  }
 }
 
 }  // namespace flags_internal
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
index 4b68c85..be9aacc 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -19,6 +19,7 @@
 #include <functional>
 
 #include "absl/base/config.h"
+#include "absl/base/fast_type_id.h"
 #include "absl/flags/commandlineflag.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/strings/string_view.h"
@@ -73,7 +74,7 @@
 //
 
 // Retire flag with name "name" and type indicated by ops.
-void Retire(const char* name, FlagFastTypeId type_id, char* buf);
+void Retire(const char* name, FlagFastTypeId type_id, unsigned char* buf);
 
 constexpr size_t kRetiredFlagObjSize = 3 * sizeof(void*);
 constexpr size_t kRetiredFlagObjAlignment = alignof(void*);
@@ -83,11 +84,11 @@
 class RetiredFlag {
  public:
   void Retire(const char* flag_name) {
-    flags_internal::Retire(flag_name, base_internal::FastTypeId<T>(), buf_);
+    flags_internal::Retire(flag_name, absl::FastTypeId<T>(), buf_);
   }
 
  private:
-  alignas(kRetiredFlagObjAlignment) char buf_[kRetiredFlagObjSize];
+  alignas(kRetiredFlagObjAlignment) unsigned char buf_[kRetiredFlagObjSize];
 };
 
 }  // namespace flags_internal
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index 8b169bc..fc68b03 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -29,7 +29,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
-#include "absl/base/const_init.h"
+#include "absl/base/no_destructor.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/flags/commandlineflag.h"
 #include "absl/flags/flag.h"
@@ -434,45 +434,48 @@
 
 namespace {
 
-ABSL_CONST_INIT absl::Mutex help_attributes_guard(absl::kConstInit);
-ABSL_CONST_INIT std::string* match_substr
-    ABSL_GUARDED_BY(help_attributes_guard) = nullptr;
-ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(help_attributes_guard) =
+absl::Mutex* HelpAttributesMutex() {
+  static absl::NoDestructor<absl::Mutex> mutex;
+  return mutex.get();
+}
+ABSL_CONST_INIT std::string* match_substr ABSL_GUARDED_BY(HelpAttributesMutex())
+    ABSL_PT_GUARDED_BY(HelpAttributesMutex()) = nullptr;
+ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(HelpAttributesMutex()) =
     HelpMode::kNone;
-ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(help_attributes_guard) =
+ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(HelpAttributesMutex()) =
     HelpFormat::kHumanReadable;
 
 }  // namespace
 
 std::string GetFlagsHelpMatchSubstr() {
-  absl::MutexLock l(&help_attributes_guard);
+  absl::MutexLock l(HelpAttributesMutex());
   if (match_substr == nullptr) return "";
   return *match_substr;
 }
 
 void SetFlagsHelpMatchSubstr(absl::string_view substr) {
-  absl::MutexLock l(&help_attributes_guard);
+  absl::MutexLock l(HelpAttributesMutex());
   if (match_substr == nullptr) match_substr = new std::string;
   match_substr->assign(substr.data(), substr.size());
 }
 
 HelpMode GetFlagsHelpMode() {
-  absl::MutexLock l(&help_attributes_guard);
+  absl::MutexLock l(HelpAttributesMutex());
   return help_mode;
 }
 
 void SetFlagsHelpMode(HelpMode mode) {
-  absl::MutexLock l(&help_attributes_guard);
+  absl::MutexLock l(HelpAttributesMutex());
   help_mode = mode;
 }
 
 HelpFormat GetFlagsHelpFormat() {
-  absl::MutexLock l(&help_attributes_guard);
+  absl::MutexLock l(HelpAttributesMutex());
   return help_format;
 }
 
 void SetFlagsHelpFormat(HelpFormat format) {
-  absl::MutexLock l(&help_attributes_guard);
+  absl::MutexLock l(HelpAttributesMutex());
   help_format = format;
 }
 
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index 526b61d..c87cacd 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -35,7 +35,7 @@
 #include "absl/algorithm/container.h"
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
-#include "absl/base/const_init.h"
+#include "absl/base/no_destructor.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/flags/commandlineflag.h"
 #include "absl/flags/config.h"
@@ -64,18 +64,25 @@
 namespace flags_internal {
 namespace {
 
-ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit);
+absl::Mutex* ProcessingChecksMutex() {
+  static absl::NoDestructor<absl::Mutex> mutex;
+  return mutex.get();
+}
 
 ABSL_CONST_INIT bool flagfile_needs_processing
-    ABSL_GUARDED_BY(processing_checks_guard) = false;
+    ABSL_GUARDED_BY(ProcessingChecksMutex()) = false;
 ABSL_CONST_INIT bool fromenv_needs_processing
-    ABSL_GUARDED_BY(processing_checks_guard) = false;
+    ABSL_GUARDED_BY(ProcessingChecksMutex()) = false;
 ABSL_CONST_INIT bool tryfromenv_needs_processing
-    ABSL_GUARDED_BY(processing_checks_guard) = false;
+    ABSL_GUARDED_BY(ProcessingChecksMutex()) = false;
 
-ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit);
+absl::Mutex* SpecifiedFlagsMutex() {
+  static absl::NoDestructor<absl::Mutex> mutex;
+  return mutex.get();
+}
+
 ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags
-    ABSL_GUARDED_BY(specified_flags_guard) = nullptr;
+    ABSL_GUARDED_BY(SpecifiedFlagsMutex()) = nullptr;
 
 // Suggesting at most kMaxHints flags in case of misspellings.
 ABSL_CONST_INIT const size_t kMaxHints = 100;
@@ -106,7 +113,7 @@
     .OnUpdate([]() {
       if (absl::GetFlag(FLAGS_flagfile).empty()) return;
 
-      absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
+      absl::MutexLock l(absl::flags_internal::ProcessingChecksMutex());
 
       // Setting this flag twice before it is handled most likely an internal
       // error and should be reviewed by developers.
@@ -122,7 +129,7 @@
     .OnUpdate([]() {
       if (absl::GetFlag(FLAGS_fromenv).empty()) return;
 
-      absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
+      absl::MutexLock l(absl::flags_internal::ProcessingChecksMutex());
 
       // Setting this flag twice before it is handled most likely an internal
       // error and should be reviewed by developers.
@@ -138,7 +145,7 @@
     .OnUpdate([]() {
       if (absl::GetFlag(FLAGS_tryfromenv).empty()) return;
 
-      absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
+      absl::MutexLock l(absl::flags_internal::ProcessingChecksMutex());
 
       // Setting this flag twice before it is handled most likely an internal
       // error and should be reviewed by developers.
@@ -415,7 +422,7 @@
                           std::vector<std::string>& flagfile_value) {
   bool success = true;
 
-  absl::MutexLock l(&flags_internal::processing_checks_guard);
+  absl::MutexLock l(flags_internal::ProcessingChecksMutex());
 
   // flagfile could have been set either on a command line or
   // programmatically before invoking ParseCommandLine. Note that we do not
@@ -478,7 +485,7 @@
   // going to be {"f1", "f2"}
   if (!flagfile_value.empty()) {
     absl::SetFlag(&FLAGS_flagfile, flagfile_value);
-    absl::MutexLock l(&flags_internal::processing_checks_guard);
+    absl::MutexLock l(flags_internal::ProcessingChecksMutex());
     flags_internal::flagfile_needs_processing = false;
   }
 
@@ -490,7 +497,7 @@
     absl::SetFlag(&FLAGS_tryfromenv, {});
   }
 
-  absl::MutexLock l(&flags_internal::processing_checks_guard);
+  absl::MutexLock l(flags_internal::ProcessingChecksMutex());
   flags_internal::fromenv_needs_processing = false;
   flags_internal::tryfromenv_needs_processing = false;
 }
@@ -637,7 +644,7 @@
 // --------------------------------------------------------------------
 
 bool WasPresentOnCommandLine(absl::string_view flag_name) {
-  absl::ReaderMutexLock l(&specified_flags_guard);
+  absl::ReaderMutexLock l(SpecifiedFlagsMutex());
   ABSL_INTERNAL_CHECK(specified_flags != nullptr,
                       "ParseCommandLine is not invoked yet");
 
@@ -764,7 +771,7 @@
   }
   positional_args.push_back(argv[0]);
 
-  absl::MutexLock l(&flags_internal::specified_flags_guard);
+  absl::MutexLock l(flags_internal::SpecifiedFlagsMutex());
   if (specified_flags == nullptr) {
     specified_flags = new std::vector<const CommandLineFlag*>;
   } else {
diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc
index ea856ff..b8b4a2e 100644
--- a/absl/flags/reflection.cc
+++ b/absl/flags/reflection.cc
@@ -289,11 +289,10 @@
 
 }  // namespace
 
-void Retire(const char* name, FlagFastTypeId type_id, char* buf) {
+void Retire(const char* name, FlagFastTypeId type_id, unsigned char* buf) {
   static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, "");
   static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, "");
-  auto* flag = ::new (static_cast<void*>(buf))
-      flags_internal::RetiredFlagObj(name, type_id);
+  auto* flag = ::new (buf) flags_internal::RetiredFlagObj(name, type_id);
   FlagRegistry::GlobalRegistry().RegisterFlag(*flag, nullptr);
 }
 
diff --git a/absl/flags/usage_config.cc b/absl/flags/usage_config.cc
index 5d7426d..5922c5e 100644
--- a/absl/flags/usage_config.cc
+++ b/absl/flags/usage_config.cc
@@ -22,6 +22,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/const_init.h"
+#include "absl/base/no_destructor.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/flags/internal/path_util.h"
 #include "absl/flags/internal/program_name.h"
@@ -104,14 +105,18 @@
 
 // --------------------------------------------------------------------
 
-ABSL_CONST_INIT absl::Mutex custom_usage_config_guard(absl::kConstInit);
+absl::Mutex* CustomUsageConfigMutex() {
+  static absl::NoDestructor<absl::Mutex> mutex;
+  return mutex.get();
+}
 ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config
-    ABSL_GUARDED_BY(custom_usage_config_guard) = nullptr;
+    ABSL_GUARDED_BY(CustomUsageConfigMutex())
+        ABSL_PT_GUARDED_BY(CustomUsageConfigMutex()) = nullptr;
 
 }  // namespace
 
 FlagsUsageConfig GetUsageConfig() {
-  absl::MutexLock l(&custom_usage_config_guard);
+  absl::MutexLock l(CustomUsageConfigMutex());
 
   if (custom_usage_config) return *custom_usage_config;
 
@@ -136,7 +141,7 @@
 }  // namespace flags_internal
 
 void SetFlagsUsageConfig(FlagsUsageConfig usage_config) {
-  absl::MutexLock l(&flags_internal::custom_usage_config_guard);
+  absl::MutexLock l(flags_internal::CustomUsageConfigMutex());
 
   if (!usage_config.contains_helpshort_flags)
     usage_config.contains_helpshort_flags =
diff --git a/absl/functional/BUILD.bazel b/absl/functional/BUILD.bazel
index 1a18af2..aeed3b6 100644
--- a/absl/functional/BUILD.bazel
+++ b/absl/functional/BUILD.bazel
@@ -39,7 +39,6 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        "//absl/base:base_internal",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
@@ -57,13 +56,12 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":any_invocable",
-        "//absl/base:base_internal",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
         "//absl/utility",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -74,7 +72,6 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        "//absl/base:base_internal",
         "//absl/container:compressed_tuple",
         "//absl/meta:type_traits",
         "//absl/utility",
@@ -89,8 +86,8 @@
     deps = [
         ":bind_front",
         "//absl/memory",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -102,7 +99,6 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":any_invocable",
-        "//absl/base:base_internal",
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
     ],
@@ -118,8 +114,8 @@
         ":function_ref",
         "//absl/container:test_instance_tracker",
         "//absl/memory",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -145,13 +141,14 @@
         "//absl/strings",
         "//absl/strings:string_view",
         "//absl/types:variant",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "function_type_benchmark",
+    testonly = True,
     srcs = [
         "function_type_benchmark.cc",
     ],
@@ -162,7 +159,6 @@
         ":any_invocable",
         ":function_ref",
         "//absl/base:core_headers",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/functional/CMakeLists.txt b/absl/functional/CMakeLists.txt
index 38fea8b..91939db 100644
--- a/absl/functional/CMakeLists.txt
+++ b/absl/functional/CMakeLists.txt
@@ -24,7 +24,6 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::base_internal
     absl::config
     absl::core_headers
     absl::type_traits
@@ -42,7 +41,6 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::any_invocable
-    absl::base_internal
     absl::config
     absl::core_headers
     absl::type_traits
@@ -60,7 +58,6 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::base_internal
     absl::compressed_tuple
   PUBLIC
 )
@@ -88,7 +85,6 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::base_internal
     absl::core_headers
     absl::any_invocable
     absl::meta
diff --git a/absl/functional/any_invocable.h b/absl/functional/any_invocable.h
index 3acb9fd..43ea9af 100644
--- a/absl/functional/any_invocable.h
+++ b/absl/functional/any_invocable.h
@@ -25,7 +25,7 @@
 //
 // NOTE: `absl::AnyInvocable` is similar to the C++23 `std::move_only_function`
 // abstraction, but has a slightly different API and is not designed to be a
-// drop-in replacement or C++11-compatible backfill of that type.
+// drop-in replacement or backfill of that type.
 //
 // Credits to Matt Calabrese (https://github.com/mattcalabrese) for the original
 // implementation.
@@ -97,11 +97,10 @@
 // my_func(std::move(func6));
 //
 // `AnyInvocable` also properly respects `const` qualifiers, reference
-// qualifiers, and the `noexcept` specification (only in C++ 17 and beyond) as
-// part of the user-specified function type (e.g.
-// `AnyInvocable<void() const && noexcept>`). These qualifiers will be applied
-// to the `AnyInvocable` object's `operator()`, and the underlying invocable
-// must be compatible with those qualifiers.
+// qualifiers, and the `noexcept` specification  as part of the user-specified
+// function type (e.g. `AnyInvocable<void() const && noexcept>`). These
+// qualifiers will be applied to the `AnyInvocable` object's `operator()`, and
+// the underlying invocable must be compatible with those qualifiers.
 //
 // Comparison of const and non-const function types:
 //
@@ -280,11 +279,10 @@
   //
   // WARNING: An `AnyInvocable` that wraps an empty `std::function` is not
   // itself empty. This behavior is consistent with the standard equivalent
-  // `std::move_only_function`.
-  //
-  // In other words:
+  // `std::move_only_function`. In the following example, `a()` will actually
+  // invoke `f()`, leading to an `std::bad_function_call` exception:
   //   std::function<void()> f;  // empty
-  //   absl::AnyInvocable<void()> a = std::move(f);  // not empty
+  //   absl::AnyInvocable<void()> a = f;  // not empty
   //
   // Invoking an empty `AnyInvocable` results in undefined behavior.
   explicit operator bool() const noexcept { return this->HasValue(); }
diff --git a/absl/functional/any_invocable_test.cc b/absl/functional/any_invocable_test.cc
index a740faa..6ad6323 100644
--- a/absl/functional/any_invocable_test.cc
+++ b/absl/functional/any_invocable_test.cc
@@ -31,15 +31,6 @@
 
 namespace {
 
-// Helper macro used to avoid spelling `noexcept` in language versions older
-// than C++17, where it is not part of the type system, in order to avoid
-// compilation failures and internal compiler errors.
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
-#define ABSL_INTERNAL_NOEXCEPT_SPEC(noex) noexcept(noex)
-#else
-#define ABSL_INTERNAL_NOEXCEPT_SPEC(noex)
-#endif
-
 // A dummy type we use when passing qualifiers to metafunctions
 struct _ {};
 
@@ -104,9 +95,6 @@
       absl::conditional_t<std::is_const<T>::value, R(P...) const&&, R(P...) &&>;
 };
 
-// If noexcept is a part of the type system, then provide the noexcept forms.
-#if defined(__cpp_noexcept_function_type)
-
 template <class T, class R, class... P>
 struct GiveQualifiersToFunImpl<T, R(P...) noexcept> {
   using type = absl::conditional_t<std::is_const<T>::value,
@@ -127,8 +115,6 @@
                           R(P...) && noexcept>;
 };
 
-#endif  // defined(__cpp_noexcept_function_type)
-
 template <class T, class Fun>
 using GiveQualifiersToFun = typename GiveQualifiersToFunImpl<T, Fun>::type;
 
@@ -200,7 +186,7 @@
                 tail) {}                                                      \
     add(add&& other) = default; /*NOLINT*/                                    \
     Int operator()(int a, int b, int c) qual                                  \
-        ABSL_INTERNAL_NOEXCEPT_SPEC(CallExceptionSpec == NothrowCall::yes) {  \
+        noexcept(CallExceptionSpec == NothrowCall::yes) {                     \
       return state + a + b + c;                                               \
     }                                                                         \
     int state;                                                                \
@@ -218,7 +204,7 @@
     ~add() noexcept {}                                                        \
     add(add&& other) = default; /*NOLINT*/                                    \
     Int operator()(int a, int b, int c) qual                                  \
-        ABSL_INTERNAL_NOEXCEPT_SPEC(CallExceptionSpec == NothrowCall::yes) {  \
+        noexcept(CallExceptionSpec == NothrowCall::yes) {                     \
       return state + a + b + c;                                               \
     }                                                                         \
     int state;                                                                \
@@ -322,8 +308,8 @@
   static constexpr ObjAlign kAlignment = Alignment;
 
   // These types are used when testing with member object pointer Invocables
-  using UnqualifiedUnaryFunType = int(Int const&&)
-      ABSL_INTERNAL_NOEXCEPT_SPEC(CallExceptionSpec == NothrowCall::yes);
+  using UnqualifiedUnaryFunType = int(Int const&&) noexcept(CallExceptionSpec ==
+                                                            NothrowCall::yes);
   using UnaryFunType = GiveQualifiersToFun<Qualifiers, UnqualifiedUnaryFunType>;
   using MemObjPtrType = int(Int::*);
   using UnaryAnyInvType = AnyInvocable<UnaryFunType>;
@@ -1233,9 +1219,6 @@
 TYPED_TEST_SUITE_P(AnyInvTestNoexceptTrue);
 
 TYPED_TEST_P(AnyInvTestNoexceptTrue, ConversionConstructionConstraints) {
-#if ABSL_INTERNAL_CPLUSPLUS_LANG < 201703L
-  GTEST_SKIP() << "Noexcept was not part of the type system before C++17.";
-#else
   using AnyInvType = typename TypeParam::AnyInvType;
 
   EXPECT_FALSE((std::is_constructible<
@@ -1244,13 +1227,9 @@
   EXPECT_FALSE((
       std::is_constructible<AnyInvType,
                             typename TypeParam::IncompatibleInvocable>::value));
-#endif
 }
 
 TYPED_TEST_P(AnyInvTestNoexceptTrue, ConversionAssignConstraints) {
-#if ABSL_INTERNAL_CPLUSPLUS_LANG < 201703L
-  GTEST_SKIP() << "Noexcept was not part of the type system before C++17.";
-#else
   using AnyInvType = typename TypeParam::AnyInvType;
 
   EXPECT_FALSE((std::is_assignable<
@@ -1259,7 +1238,6 @@
   EXPECT_FALSE(
       (std::is_assignable<AnyInvType&,
                           typename TypeParam::IncompatibleInvocable>::value));
-#endif
 }
 
 template <class T>
@@ -1283,9 +1261,6 @@
 }
 
 TYPED_TEST_P(AnyInvTestNonRvalue, NonMoveableResultType) {
-#if ABSL_INTERNAL_CPLUSPLUS_LANG < 201703L
-  GTEST_SKIP() << "Copy/move elision was not standard before C++17";
-#else
   // Define a result type that cannot be copy- or move-constructed.
   struct Result {
     int x;
@@ -1312,7 +1287,6 @@
 
   AnyInvocable<Fun> any_inv(return_17);
   EXPECT_EQ(17, any_inv().x);
-#endif
 }
 
 TYPED_TEST_P(AnyInvTestNonRvalue, ConversionAssignReferenceWrapperEmptyLhs) {
@@ -1367,9 +1341,6 @@
 }
 
 TYPED_TEST_P(AnyInvTestRvalue, NonMoveableResultType) {
-#if ABSL_INTERNAL_CPLUSPLUS_LANG < 201703L
-  GTEST_SKIP() << "Copy/move elision was not standard before C++17";
-#else
   // Define a result type that cannot be copy- or move-constructed.
   struct Result {
     int x;
@@ -1395,7 +1366,6 @@
       GiveQualifiersToFun<typename TypeParam::Qualifiers, UnqualifiedFun>;
 
   EXPECT_EQ(17, AnyInvocable<Fun>(return_17)().x);
-#endif
 }
 
 TYPED_TEST_P(AnyInvTestRvalue, ConversionAssignReferenceWrapper) {
@@ -1507,9 +1477,6 @@
     TestParams<Movable::yes, Destructible::nothrow, _, NothrowCall::no,
                ObjSize::large, ObjAlign::normal>  //
 
-// Dynamic memory allocation for over-aligned data was introduced in C++17.
-// See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0035r4.html
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
     // Types that must use remote storage because of a large alignment.
     ,
     TestParams<Movable::trivial, Destructible::trivial, _, NothrowCall::no,
@@ -1520,7 +1487,6 @@
                ObjSize::small, ObjAlign::large>,  //
     TestParams<Movable::nothrow, Destructible::nothrow, _, NothrowCall::no,
                ObjSize::small, ObjAlign::large>  //
-#endif
     >;
 using TestParameterListRemoteNonMovable = ::testing::Types<
     // "Normal" aligned types that are large and have trivial destructors
@@ -1714,6 +1680,4 @@
 static_assert(!std::is_convertible<void*, absl::AnyInvocable<void() &&>>::value,
               "");
 
-#undef ABSL_INTERNAL_NOEXCEPT_SPEC
-
 }  // namespace
diff --git a/absl/functional/bind_front_test.cc b/absl/functional/bind_front_test.cc
index 4801a81..5d94ecc 100644
--- a/absl/functional/bind_front_test.cc
+++ b/absl/functional/bind_front_test.cc
@@ -210,13 +210,9 @@
   constexpr auto plus5 = absl::bind_front(Plus, five);
   EXPECT_EQ(plus5(1), 6);
 
-  // There seems to be a bug in MSVC dealing constexpr construction of
-  // char[]. Notice 'plus5' above; 'int' works just fine.
-#if !(defined(_MSC_VER) && _MSC_VER < 1910)
   static constexpr char data[] = "DEF";
   constexpr auto g = absl::bind_front(CharAt, data);
   EXPECT_EQ(g(1), 'E');
-#endif
 }
 
 struct ManglingCall {
diff --git a/absl/functional/function_ref.h b/absl/functional/function_ref.h
index 96cece5..f1d087a 100644
--- a/absl/functional/function_ref.h
+++ b/absl/functional/function_ref.h
@@ -82,17 +82,12 @@
 //   // replaced by an `absl::FunctionRef`:
 //   bool Visitor(absl::FunctionRef<void(my_proto&, absl::string_view)>
 //                  callback);
-//
-// Note: the assignment operator within an `absl::FunctionRef` is intentionally
-// deleted to prevent misuse; because the `absl::FunctionRef` does not own the
-// underlying type, assignment likely indicates misuse.
 template <typename R, typename... Args>
 class FunctionRef<R(Args...)> {
  private:
   // Used to disable constructors for objects that are not compatible with the
   // signature of this FunctionRef.
-  template <typename F,
-            typename FR = absl::base_internal::invoke_result_t<F, Args&&...>>
+  template <typename F, typename FR = std::invoke_result_t<F, Args&&...>>
   using EnableIfCompatible =
       typename std::enable_if<std::is_void<R>::value ||
                               std::is_convertible<FR, R>::value>::type;
@@ -122,9 +117,7 @@
     ptr_.fun = reinterpret_cast<decltype(ptr_.fun)>(f);
   }
 
-  // To help prevent subtle lifetime bugs, FunctionRef is not assignable.
-  // Typically, it should only be used as an argument type.
-  FunctionRef& operator=(const FunctionRef& rhs) = delete;
+  FunctionRef& operator=(const FunctionRef& rhs) = default;
   FunctionRef(const FunctionRef& rhs) = default;
 
   // Call the underlying object.
diff --git a/absl/functional/function_ref_test.cc b/absl/functional/function_ref_test.cc
index c021113..98d11f7 100644
--- a/absl/functional/function_ref_test.cc
+++ b/absl/functional/function_ref_test.cc
@@ -52,6 +52,16 @@
   EXPECT_EQ(1337, ref());
 }
 
+TEST(FunctionRefTest, CopyAssignment) {
+  FunctionRef<int()> a = +[]() -> int {
+    ADD_FAILURE() << "Unexpectedly called";
+    return 0;
+  };
+  FunctionRef<int()> b = +[] { return 1337; };
+  a = b;
+  EXPECT_EQ(1337, a());
+}
+
 int NoExceptFunction() noexcept { return 1337; }
 
 // TODO(jdennett): Add a test for noexcept member functions.
diff --git a/absl/functional/function_type_benchmark.cc b/absl/functional/function_type_benchmark.cc
index 03dc31d..513233b 100644
--- a/absl/functional/function_type_benchmark.cc
+++ b/absl/functional/function_type_benchmark.cc
@@ -16,10 +16,10 @@
 #include <memory>
 #include <string>
 
-#include "benchmark/benchmark.h"
 #include "absl/base/attributes.h"
 #include "absl/functional/any_invocable.h"
 #include "absl/functional/function_ref.h"
+#include "benchmark/benchmark.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/functional/internal/any_invocable.h b/absl/functional/internal/any_invocable.h
index c2d8cd4..167d947 100644
--- a/absl/functional/internal/any_invocable.h
+++ b/absl/functional/internal/any_invocable.h
@@ -65,7 +65,6 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
-#include "absl/base/internal/invoke.h"
 #include "absl/base/macros.h"
 #include "absl/base/optimization.h"
 #include "absl/meta/type_traits.h"
@@ -74,15 +73,6 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-// Helper macro used to prevent spelling `noexcept` in language versions older
-// than C++17, where it is not part of the type system, in order to avoid
-// compilation failures and internal compiler errors.
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
-#define ABSL_INTERNAL_NOEXCEPT_SPEC(noex) noexcept(noex)
-#else
-#define ABSL_INTERNAL_NOEXCEPT_SPEC(noex)
-#endif
-
 // Defined in functional/any_invocable.h
 template <class Sig>
 class AnyInvocable;
@@ -107,44 +97,30 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 
-// A type trait that tells us whether or not a target function type should be
+// A metafunction that tells us whether or not a target function type should be
 // stored locally in the small object optimization storage
 template <class T>
-using IsStoredLocally = std::integral_constant<
-    bool, sizeof(T) <= kStorageSize && alignof(T) <= kAlignment &&
-              kAlignment % alignof(T) == 0 &&
-              std::is_nothrow_move_constructible<T>::value>;
+constexpr bool IsStoredLocally() {
+  if constexpr (sizeof(T) <= kStorageSize && alignof(T) <= kAlignment &&
+                kAlignment % alignof(T) == 0) {
+    return std::is_nothrow_move_constructible<T>::value;
+  }
+  return false;
+}
 
 // An implementation of std::remove_cvref_t of C++20.
 template <class T>
 using RemoveCVRef =
     typename std::remove_cv<typename std::remove_reference<T>::type>::type;
 
-////////////////////////////////////////////////////////////////////////////////
-//
-// An implementation of the C++ standard INVOKE<R> pseudo-macro, operation is
-// equivalent to std::invoke except that it forces an implicit conversion to the
-// specified return type. If "R" is void, the function is executed and the
-// return value is simply ignored.
-template <class ReturnType, class F, class... P,
-          typename = absl::enable_if_t<std::is_void<ReturnType>::value>>
-void InvokeR(F&& f, P&&... args) {
-  absl::base_internal::invoke(std::forward<F>(f), std::forward<P>(args)...);
-}
-
-template <class ReturnType, class F, class... P,
-          absl::enable_if_t<!std::is_void<ReturnType>::value, int> = 0>
+// An implementation of std::invoke_r of C++23.
+template <class ReturnType, class F, class... P>
 ReturnType InvokeR(F&& f, P&&... args) {
-  // GCC 12 has a false-positive -Wmaybe-uninitialized warning here.
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
-  return absl::base_internal::invoke(std::forward<F>(f),
-                                     std::forward<P>(args)...);
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
-#pragma GCC diagnostic pop
-#endif
+  if constexpr (std::is_void_v<ReturnType>) {
+    std::invoke(std::forward<F>(f), std::forward<P>(args)...);
+  } else {
+    return std::invoke(std::forward<F>(f), std::forward<P>(args)...);
+  }
 }
 
 //
@@ -198,32 +174,14 @@
   } remote;
 
   // Local-storage for the type-erased object when small and trivial enough
-  alignas(kAlignment) char storage[kStorageSize];
+  alignas(kAlignment) unsigned char storage[kStorageSize];
 };
 
 // A typed accessor for the object in `TypeErasedState` storage
 template <class T>
 T& ObjectInLocalStorage(TypeErasedState* const state) {
   // We launder here because the storage may be reused with the same type.
-#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606L
   return *std::launder(reinterpret_cast<T*>(&state->storage));
-#elif ABSL_HAVE_BUILTIN(__builtin_launder)
-  return *__builtin_launder(reinterpret_cast<T*>(&state->storage));
-#else
-
-  // When `std::launder` or equivalent are not available, we rely on undefined
-  // behavior, which works as intended on Abseil's officially supported
-  // platforms as of Q2 2022.
-#if !defined(__clang__) && defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
-  return *reinterpret_cast<T*>(&state->storage);
-#if !defined(__clang__) && defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
-#endif
 }
 
 // The type for functions issuing lifetime-related operations: move and dispose
@@ -231,14 +189,14 @@
 // NOTE: When specifying `FunctionToCall::`dispose, the same state must be
 // passed as both "from" and "to".
 using ManagerType = void(FunctionToCall /*operation*/,
-                         TypeErasedState* /*from*/, TypeErasedState* /*to*/)
-    ABSL_INTERNAL_NOEXCEPT_SPEC(true);
+                         TypeErasedState* /*from*/,
+                         TypeErasedState* /*to*/) noexcept(true);
 
 // The type for functions issuing the actual invocation of the object
 // A pointer to such a function is contained in each AnyInvocable instance.
 template <bool SigIsNoexcept, class ReturnType, class... P>
-using InvokerType = ReturnType(TypeErasedState*, ForwardedParameterType<P>...)
-    ABSL_INTERNAL_NOEXCEPT_SPEC(SigIsNoexcept);
+using InvokerType = ReturnType(
+    TypeErasedState*, ForwardedParameterType<P>...) noexcept(SigIsNoexcept);
 
 // The manager that is used when AnyInvocable is empty
 inline void EmptyManager(FunctionToCall /*operation*/,
@@ -275,7 +233,7 @@
 void LocalManagerNontrivial(FunctionToCall operation,
                             TypeErasedState* const from,
                             TypeErasedState* const to) noexcept {
-  static_assert(IsStoredLocally<T>::value,
+  static_assert(IsStoredLocally<T>(),
                 "Local storage must only be used for supported types.");
   static_assert(!std::is_trivially_copyable<T>::value,
                 "Locally stored types must be trivially copyable.");
@@ -303,7 +261,7 @@
     ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {
   using RawT = RemoveCVRef<QualTRef>;
   static_assert(
-      IsStoredLocally<RawT>::value,
+      IsStoredLocally<RawT>(),
       "Target object must be in local storage in order to be invoked from it.");
 
   auto& f = (ObjectInLocalStorage<RawT>)(state);
@@ -338,7 +296,7 @@
 void RemoteManagerNontrivial(FunctionToCall operation,
                              TypeErasedState* const from,
                              TypeErasedState* const to) noexcept {
-  static_assert(!IsStoredLocally<T>::value,
+  static_assert(!IsStoredLocally<T>(),
                 "Remote storage must only be used for types that do not "
                 "qualify for local storage.");
 
@@ -360,7 +318,7 @@
     TypeErasedState* const state,
     ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {
   using RawT = RemoveCVRef<QualTRef>;
-  static_assert(!IsStoredLocally<RawT>::value,
+  static_assert(!IsStoredLocally<RawT>(),
                 "Target object must be in remote storage in order to be "
                 "invoked from it.");
 
@@ -440,13 +398,6 @@
 
   CoreImpl() noexcept : manager_(EmptyManager), invoker_(nullptr) {}
 
-  enum class TargetType {
-    kPointer,
-    kCompatibleAnyInvocable,
-    kIncompatibleAnyInvocable,
-    kOther,
-  };
-
   // Note: QualDecayedTRef here includes the cv-ref qualifiers associated with
   // the invocation of the Invocable. The unqualified type is the target object
   // type to be stored.
@@ -454,19 +405,47 @@
   explicit CoreImpl(TypedConversionConstruct<QualDecayedTRef>, F&& f) {
     using DecayedT = RemoveCVRef<QualDecayedTRef>;
 
-    constexpr TargetType kTargetType =
-        (std::is_pointer<DecayedT>::value ||
-         std::is_member_pointer<DecayedT>::value)
-            ? TargetType::kPointer
-        : IsCompatibleAnyInvocable<DecayedT>::value
-            ? TargetType::kCompatibleAnyInvocable
-        : IsAnyInvocable<DecayedT>::value
-            ? TargetType::kIncompatibleAnyInvocable
-            : TargetType::kOther;
-    // NOTE: We only use integers instead of enums as template parameters in
-    // order to work around a bug on C++14 under MSVC 2017.
-    // See b/236131881.
-    Initialize<kTargetType, QualDecayedTRef>(std::forward<F>(f));
+    if constexpr (std::is_pointer<DecayedT>::value ||
+                  std::is_member_pointer<DecayedT>::value) {
+      // This condition handles types that decay into pointers. This includes
+      // function references, which cannot be null. GCC warns against comparing
+      // their decayed form with nullptr (https://godbolt.org/z/9r9TMTcPK).
+      // We could work around this warning with constexpr programming, using
+      // std::is_function_v<std::remove_reference_t<F>>, but we choose to ignore
+      // it instead of writing more code.
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Waddress"
+#pragma GCC diagnostic ignored "-Wnonnull-compare"
+#endif
+      if (static_cast<DecayedT>(f) == nullptr) {
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+        manager_ = EmptyManager;
+        invoker_ = nullptr;
+      } else {
+        InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
+      }
+    } else if constexpr (IsCompatibleAnyInvocable<DecayedT>::value) {
+      // In this case we can "steal the guts" of the other AnyInvocable.
+      f.manager_(FunctionToCall::relocate_from_to, &f.state_, &state_);
+      manager_ = f.manager_;
+      invoker_ = f.invoker_;
+
+      f.manager_ = EmptyManager;
+      f.invoker_ = nullptr;
+    } else if constexpr (IsAnyInvocable<DecayedT>::value) {
+      if (f.HasValue()) {
+        InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
+      } else {
+        manager_ = EmptyManager;
+        invoker_ = nullptr;
+      }
+    } else {
+      InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
+    }
   }
 
   // Note: QualTRef here includes the cv-ref qualifiers associated with the
@@ -517,122 +496,43 @@
     invoker_ = nullptr;
   }
 
-  template <TargetType target_type, class QualDecayedTRef, class F,
-            absl::enable_if_t<target_type == TargetType::kPointer, int> = 0>
-  void Initialize(F&& f) {
-// This condition handles types that decay into pointers, which includes
-// function references. Since function references cannot be null, GCC warns
-// against comparing their decayed form with nullptr.
-// Since this is template-heavy code, we prefer to disable these warnings
-// locally instead of adding yet another overload of this function.
-#if !defined(__clang__) && defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wpragmas"
-#pragma GCC diagnostic ignored "-Waddress"
-#pragma GCC diagnostic ignored "-Wnonnull-compare"
-#endif
-    if (static_cast<RemoveCVRef<QualDecayedTRef>>(f) == nullptr) {
-#if !defined(__clang__) && defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-      manager_ = EmptyManager;
-      invoker_ = nullptr;
-      return;
-    }
-    InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
-  }
-
-  template <TargetType target_type, class QualDecayedTRef, class F,
-            absl::enable_if_t<
-                target_type == TargetType::kCompatibleAnyInvocable, int> = 0>
-  void Initialize(F&& f) {
-    // In this case we can "steal the guts" of the other AnyInvocable.
-    f.manager_(FunctionToCall::relocate_from_to, &f.state_, &state_);
-    manager_ = f.manager_;
-    invoker_ = f.invoker_;
-
-    f.manager_ = EmptyManager;
-    f.invoker_ = nullptr;
-  }
-
-  template <TargetType target_type, class QualDecayedTRef, class F,
-            absl::enable_if_t<
-                target_type == TargetType::kIncompatibleAnyInvocable, int> = 0>
-  void Initialize(F&& f) {
-    if (f.HasValue()) {
-      InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
-    } else {
-      manager_ = EmptyManager;
-      invoker_ = nullptr;
-    }
-  }
-
-  template <TargetType target_type, class QualDecayedTRef, class F,
-            typename = absl::enable_if_t<target_type == TargetType::kOther>>
-  void Initialize(F&& f) {
-    InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
-  }
-
   // Use local (inline) storage for applicable target object types.
-  template <class QualTRef, class... Args,
-            typename = absl::enable_if_t<
-                IsStoredLocally<RemoveCVRef<QualTRef>>::value>>
+  template <class QualTRef, class... Args>
   void InitializeStorage(Args&&... args) {
     using RawT = RemoveCVRef<QualTRef>;
-    ::new (static_cast<void*>(&state_.storage))
-        RawT(std::forward<Args>(args)...);
-
-    invoker_ = LocalInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
-    // We can simplify our manager if we know the type is trivially copyable.
-    InitializeLocalManager<RawT>();
+    if constexpr (IsStoredLocally<RawT>()) {
+      ::new (static_cast<void*>(&state_.storage))
+          RawT(std::forward<Args>(args)...);
+      invoker_ = LocalInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
+      // We can simplify our manager if we know the type is trivially copyable.
+      if constexpr (std::is_trivially_copyable_v<RawT>) {
+        manager_ = LocalManagerTrivial;
+      } else {
+        manager_ = LocalManagerNontrivial<RawT>;
+      }
+    } else {
+      InitializeRemoteManager<RawT>(std::forward<Args>(args)...);
+      // This is set after everything else in case an exception is thrown in an
+      // earlier step of the initialization.
+      invoker_ = RemoteInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
+    }
   }
 
-  // Use remote storage for target objects that cannot be stored locally.
-  template <class QualTRef, class... Args,
-            absl::enable_if_t<!IsStoredLocally<RemoveCVRef<QualTRef>>::value,
-                              int> = 0>
-  void InitializeStorage(Args&&... args) {
-    InitializeRemoteManager<RemoveCVRef<QualTRef>>(std::forward<Args>(args)...);
-    // This is set after everything else in case an exception is thrown in an
-    // earlier step of the initialization.
-    invoker_ = RemoteInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
-  }
-
-  template <class T,
-            typename = absl::enable_if_t<std::is_trivially_copyable<T>::value>>
-  void InitializeLocalManager() {
-    manager_ = LocalManagerTrivial;
-  }
-
-  template <class T,
-            absl::enable_if_t<!std::is_trivially_copyable<T>::value, int> = 0>
-  void InitializeLocalManager() {
-    manager_ = LocalManagerNontrivial<T>;
-  }
-
-  template <class T>
-  using HasTrivialRemoteStorage =
-      std::integral_constant<bool, std::is_trivially_destructible<T>::value &&
-                                       alignof(T) <=
-                                           ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT>;
-
-  template <class T, class... Args,
-            typename = absl::enable_if_t<HasTrivialRemoteStorage<T>::value>>
+  template <class T, class... Args>
   void InitializeRemoteManager(Args&&... args) {
-    // unique_ptr is used for exception-safety in case construction throws.
-    std::unique_ptr<void, TrivialDeleter> uninitialized_target(
-        ::operator new(sizeof(T)), TrivialDeleter(sizeof(T)));
-    ::new (uninitialized_target.get()) T(std::forward<Args>(args)...);
-    state_.remote.target = uninitialized_target.release();
-    state_.remote.size = sizeof(T);
-    manager_ = RemoteManagerTrivial;
-  }
-
-  template <class T, class... Args,
-            absl::enable_if_t<!HasTrivialRemoteStorage<T>::value, int> = 0>
-  void InitializeRemoteManager(Args&&... args) {
-    state_.remote.target = ::new T(std::forward<Args>(args)...);
-    manager_ = RemoteManagerNontrivial<T>;
+    if constexpr (std::is_trivially_destructible_v<T> &&
+                  alignof(T) <= ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT) {
+      // unique_ptr is used for exception-safety in case construction throws.
+      std::unique_ptr<void, TrivialDeleter> uninitialized_target(
+          ::operator new(sizeof(T)), TrivialDeleter(sizeof(T)));
+      ::new (uninitialized_target.get()) T(std::forward<Args>(args)...);
+      state_.remote.target = uninitialized_target.release();
+      state_.remote.size = sizeof(T);
+      manager_ = RemoteManagerTrivial;
+    } else {
+      state_.remote.target = ::new T(std::forward<Args>(args)...);
+      manager_ = RemoteManagerNontrivial<T>;
+    }
   }
 
   //////////////////////////////////////////////////////////////////////////////
@@ -734,17 +634,12 @@
     absl::enable_if_t<Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<
         std::reference_wrapper<F>>::value>>;
 
-////////////////////////////////////////////////////////////////////////////////
-//
 // The constraint for checking whether or not a call meets the noexcept
-// callability requirements. This is a preprocessor macro because specifying it
+// callability requirements. We use a preprocessor macro because specifying it
 // this way as opposed to a disjunction/branch can improve the user-side error
 // messages and avoids an instantiation of std::is_nothrow_invocable_r in the
 // cases where the user did not specify a noexcept function type.
 //
-#define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT(inv_quals, noex) \
-  ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_##noex(inv_quals)
-
 // The disjunction below is because we can't rely on std::is_nothrow_invocable_r
 // to give the right result when ReturnType is non-moveable in toolchains that
 // don't treat non-moveable result types correctly. For example this was the
@@ -759,7 +654,7 @@
               UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, P...>,  \
           std::is_same<                                                      \
               ReturnType,                                                    \
-              absl::base_internal::invoke_result_t<                          \
+              std::invoke_result_t<                                          \
                   UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals,     \
                   P...>>>>::value>
 
@@ -775,13 +670,13 @@
 // noex is "true" if the function type is noexcept, or false if it is not.
 //
 // The CallIsValid condition is more complicated than simply using
-// absl::base_internal::is_invocable_r because we can't rely on it to give the
-// right result when ReturnType is non-moveable in toolchains that don't treat
-// non-moveable result types correctly. For example this was the case in libc++
-// before commit c3a24882 (2022-05).
+// std::is_invocable_r because we can't rely on it to give the right result
+// when ReturnType is non-moveable in toolchains that don't treat non-moveable
+// result types correctly. For example this was the case in libc++ before commit
+// c3a24882 (2022-05).
 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, noex)            \
   template <class ReturnType, class... P>                                      \
-  class Impl<ReturnType(P...) cv ref ABSL_INTERNAL_NOEXCEPT_SPEC(noex)>        \
+  class Impl<ReturnType(P...) cv ref noexcept(noex)>                           \
       : public CoreImpl<noex, ReturnType, P...> {                              \
    public:                                                                     \
     /*The base class, which contains the datamembers and core operations*/     \
@@ -790,17 +685,16 @@
     /*SFINAE constraint to check if F is invocable with the proper signature*/ \
     template <class F>                                                         \
     using CallIsValid = TrueAlias<absl::enable_if_t<absl::disjunction<         \
-        absl::base_internal::is_invocable_r<ReturnType,                        \
-                                            absl::decay_t<F> inv_quals, P...>, \
-        std::is_same<ReturnType,                                               \
-                     absl::base_internal::invoke_result_t<                     \
-                         absl::decay_t<F> inv_quals, P...>>>::value>>;         \
+        std::is_invocable_r<ReturnType, absl::decay_t<F> inv_quals, P...>,     \
+        std::is_same<                                                          \
+            ReturnType,                                                        \
+            std::invoke_result_t<absl::decay_t<F> inv_quals, P...>>>::value>>; \
                                                                                \
     /*SFINAE constraint to check if F is nothrow-invocable when necessary*/    \
     template <class F>                                                         \
     using CallIsNoexceptIfSigIsNoexcept =                                      \
-        TrueAlias<ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT(inv_quals,   \
-                                                                  noex)>;      \
+        TrueAlias<ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_##noex(      \
+            inv_quals)>;                                                       \
                                                                                \
     /*Put the AnyInvocable into an empty state.*/                              \
     Impl() = default;                                                          \
@@ -822,8 +716,7 @@
                                                                                \
     /*Raises a fatal error when the AnyInvocable is invoked after a move*/     \
     static ReturnType InvokedAfterMove(                                        \
-      TypeErasedState*,                                                        \
-      ForwardedParameterType<P>...) noexcept(noex) {                           \
+        TypeErasedState*, ForwardedParameterType<P>...) noexcept(noex) {       \
       ABSL_HARDENING_ASSERT(false && "AnyInvocable use-after-move");           \
       std::terminate();                                                        \
     }                                                                          \
@@ -851,18 +744,11 @@
     }                                                                          \
   }
 
-// Define the `noexcept(true)` specialization only for C++17 and beyond, when
-// `noexcept` is part of the type system.
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
 // A convenience macro that defines specializations for the noexcept(true) and
 // noexcept(false) forms, given the other properties.
 #define ABSL_INTERNAL_ANY_INVOCABLE_IMPL(cv, ref, inv_quals)    \
   ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, false); \
   ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, true)
-#else
-#define ABSL_INTERNAL_ANY_INVOCABLE_IMPL(cv, ref, inv_quals) \
-  ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, false)
-#endif
 
 // Non-ref-qualified partial specializations
 ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, , &);
@@ -881,8 +767,6 @@
 #undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL_
 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false
 #undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true
-#undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT
-#undef ABSL_INTERNAL_NOEXCEPT_SPEC
 
 }  // namespace internal_any_invocable
 ABSL_NAMESPACE_END
diff --git a/absl/functional/internal/front_binder.h b/absl/functional/internal/front_binder.h
index 44a5492..62f373f 100644
--- a/absl/functional/internal/front_binder.h
+++ b/absl/functional/internal/front_binder.h
@@ -21,7 +21,6 @@
 #include <type_traits>
 #include <utility>
 
-#include "absl/base/internal/invoke.h"
 #include "absl/container/internal/compressed_tuple.h"
 #include "absl/meta/type_traits.h"
 #include "absl/utility/utility.h"
@@ -33,9 +32,8 @@
 // Invoke the method, expanding the tuple of bound arguments.
 template <class R, class Tuple, size_t... Idx, class... Args>
 R Apply(Tuple&& bound, absl::index_sequence<Idx...>, Args&&... free) {
-  return base_internal::invoke(
-      std::forward<Tuple>(bound).template get<Idx>()...,
-      std::forward<Args>(free)...);
+  return std::invoke(std::forward<Tuple>(bound).template get<Idx>()...,
+                     std::forward<Args>(free)...);
 }
 
 template <class F, class... BoundArgs>
@@ -50,23 +48,23 @@
   constexpr explicit FrontBinder(absl::in_place_t, Ts&&... ts)
       : bound_args_(std::forward<Ts>(ts)...) {}
 
-  template <class... FreeArgs, class R = base_internal::invoke_result_t<
-                                   F&, BoundArgs&..., FreeArgs&&...>>
+  template <class... FreeArgs,
+            class R = std::invoke_result_t<F&, BoundArgs&..., FreeArgs&&...>>
   R operator()(FreeArgs&&... free_args) & {
     return functional_internal::Apply<R>(bound_args_, Idx(),
                                          std::forward<FreeArgs>(free_args)...);
   }
 
   template <class... FreeArgs,
-            class R = base_internal::invoke_result_t<
-                const F&, const BoundArgs&..., FreeArgs&&...>>
+            class R = std::invoke_result_t<const F&, const BoundArgs&...,
+                                           FreeArgs&&...>>
   R operator()(FreeArgs&&... free_args) const& {
     return functional_internal::Apply<R>(bound_args_, Idx(),
                                          std::forward<FreeArgs>(free_args)...);
   }
 
-  template <class... FreeArgs, class R = base_internal::invoke_result_t<
-                                   F&&, BoundArgs&&..., FreeArgs&&...>>
+  template <class... FreeArgs,
+            class R = std::invoke_result_t<F&&, BoundArgs&&..., FreeArgs&&...>>
   R operator()(FreeArgs&&... free_args) && {
     // This overload is called when *this is an rvalue. If some of the bound
     // arguments are stored by value or rvalue reference, we move them.
@@ -75,8 +73,8 @@
   }
 
   template <class... FreeArgs,
-            class R = base_internal::invoke_result_t<
-                const F&&, const BoundArgs&&..., FreeArgs&&...>>
+            class R = std::invoke_result_t<const F&&, const BoundArgs&&...,
+                                           FreeArgs&&...>>
   R operator()(FreeArgs&&... free_args) const&& {
     // This overload is called when *this is an rvalue. If some of the bound
     // arguments are stored by value or rvalue reference, we move them.
diff --git a/absl/functional/internal/function_ref.h b/absl/functional/internal/function_ref.h
index 1cd34a3..27d45b8 100644
--- a/absl/functional/internal/function_ref.h
+++ b/absl/functional/internal/function_ref.h
@@ -19,7 +19,6 @@
 #include <functional>
 #include <type_traits>
 
-#include "absl/base/internal/invoke.h"
 #include "absl/functional/any_invocable.h"
 #include "absl/meta/type_traits.h"
 
@@ -74,15 +73,13 @@
 template <typename Obj, typename R, typename... Args>
 R InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) {
   auto o = static_cast<const Obj*>(ptr.obj);
-  return static_cast<R>(
-      absl::base_internal::invoke(*o, std::forward<Args>(args)...));
+  return static_cast<R>(std::invoke(*o, std::forward<Args>(args)...));
 }
 
 template <typename Fun, typename R, typename... Args>
 R InvokeFunction(VoidPtr ptr, typename ForwardT<Args>::type... args) {
   auto f = reinterpret_cast<Fun>(ptr.fun);
-  return static_cast<R>(
-      absl::base_internal::invoke(f, std::forward<Args>(args)...));
+  return static_cast<R>(std::invoke(f, std::forward<Args>(args)...));
 }
 
 template <typename Sig>
diff --git a/absl/functional/overload.h b/absl/functional/overload.h
index 7e19e70..35eec96 100644
--- a/absl/functional/overload.h
+++ b/absl/functional/overload.h
@@ -23,8 +23,6 @@
 // Before using this function, consider whether named function overloads would
 // be a better design.
 //
-// Note: absl::Overload requires C++17.
-//
 // Example:
 //
 //     std::variant<std::string, int32_t, int64_t> v(int32_t{1});
@@ -46,9 +44,6 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
-    ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
-
 template <typename... T>
 struct Overload final : T... {
   using T::operator()...;
@@ -71,21 +66,6 @@
 template <typename... T>
 Overload(T...) -> Overload<T...>;
 
-#else
-
-namespace functional_internal {
-template <typename T>
-constexpr bool kDependentFalse = false;
-}
-
-template <typename Dependent = int, typename... T>
-auto Overload(T&&...) {
-  static_assert(functional_internal::kDependentFalse<Dependent>,
-                "Overload is only usable with C++17 or above.");
-}
-
-#endif
-
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/functional/overload_test.cc b/absl/functional/overload_test.cc
index fa49d29..802e11f 100644
--- a/absl/functional/overload_test.cc
+++ b/absl/functional/overload_test.cc
@@ -18,16 +18,12 @@
 #include <string>
 #include <type_traits>
 
+#include "gtest/gtest.h"
 #include "absl/base/config.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/variant.h"
 
-#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
-    ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
-
-#include "gtest/gtest.h"
-
 namespace {
 
 TEST(OverloadTest, DispatchConsidersTypeWithAutoFallback) {
@@ -209,5 +205,3 @@
 }
 
 }  // namespace
-
-#endif
diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel
index fe567e9..b2ffcd0 100644
--- a/absl/hash/BUILD.bazel
+++ b/absl/hash/BUILD.bazel
@@ -44,6 +44,7 @@
     deps = [
         ":city",
         ":low_level_hash",
+        ":weakly_mixed_integer",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
@@ -69,7 +70,7 @@
         "//absl/meta:type_traits",
         "//absl/strings",
         "//absl/types:variant",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -86,21 +87,17 @@
         ":hash_testing",
         ":spy_hash_state",
         "//absl/base:config",
-        "//absl/base:core_headers",
-        "//absl/container:btree",
         "//absl/container:flat_hash_map",
         "//absl/container:flat_hash_set",
-        "//absl/container:node_hash_map",
-        "//absl/container:node_hash_set",
         "//absl/memory",
         "//absl/meta:type_traits",
-        "//absl/numeric:int128",
+        "//absl/numeric:bits",
         "//absl/strings:cord_test_helpers",
         "//absl/strings:string_view",
         "//absl/types:optional",
         "//absl/types:variant",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -121,8 +118,8 @@
         "//absl/container:flat_hash_set",
         "//absl/container:node_hash_map",
         "//absl/container:node_hash_set",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -142,7 +139,7 @@
         "//absl/strings",
         "//absl/strings:cord",
         "//absl/strings:cord_test_helpers",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -155,6 +152,7 @@
     visibility = ["//visibility:private"],
     deps = [
         ":hash",
+        ":weakly_mixed_integer",
         "//absl/strings",
         "//absl/strings:str_format",
     ],
@@ -182,8 +180,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":city",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -196,12 +194,28 @@
     visibility = ["//visibility:private"],
     deps = [
         "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/base:endian",
         "//absl/base:prefetch",
         "//absl/numeric:int128",
     ],
 )
 
+cc_library(
+    name = "weakly_mixed_integer",
+    hdrs = ["internal/weakly_mixed_integer.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/container:__pkg__",
+        "//absl/strings:__pkg__",
+        "//absl/types:__pkg__",
+    ],
+    deps = [
+        "//absl/base:config",
+    ],
+)
+
 cc_test(
     name = "low_level_hash_test",
     srcs = ["internal/low_level_hash_test.cc"],
@@ -211,7 +225,7 @@
     deps = [
         ":low_level_hash",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/hash/CMakeLists.txt b/absl/hash/CMakeLists.txt
index 99d6fa1..6996d93 100644
--- a/absl/hash/CMakeLists.txt
+++ b/absl/hash/CMakeLists.txt
@@ -39,6 +39,7 @@
     absl::variant
     absl::utility
     absl::low_level_hash
+    absl::weakly_mixed_integer
   PUBLIC
 )
 
@@ -68,18 +69,14 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
-    absl::btree
+    absl::bits
     absl::cord_test_helpers
-    absl::core_headers
     absl::flat_hash_map
     absl::flat_hash_set
     absl::hash
     absl::hash_testing
-    absl::int128
     absl::memory
     absl::meta
-    absl::node_hash_map
-    absl::node_hash_set
     absl::optional
     absl::spy_hash_state
     absl::string_view
@@ -123,6 +120,7 @@
     absl::hash
     absl::strings
     absl::str_format
+    absl::weakly_mixed_integer
   TESTONLY
   PUBLIC
 )
@@ -167,11 +165,24 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::config
+    absl::core_headers
     absl::endian
     absl::int128
     absl::prefetch
 )
 
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    weakly_mixed_integer
+  HDRS
+    "internal/weakly_mixed_integer.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+)
+
 absl_cc_test(
   NAME
     low_level_hash_test
diff --git a/absl/hash/hash.h b/absl/hash/hash.h
index 470cca4..23f4e9d 100644
--- a/absl/hash/hash.h
+++ b/absl/hash/hash.h
@@ -78,11 +78,17 @@
 #ifndef ABSL_HASH_HASH_H_
 #define ABSL_HASH_HASH_H_
 
+#include <cstddef>
+#include <cstdint>
 #include <tuple>
+#include <type_traits>
 #include <utility>
 
+#include "absl/base/config.h"
 #include "absl/functional/function_ref.h"
 #include "absl/hash/internal/hash.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
+#include "absl/meta/type_traits.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -319,8 +325,12 @@
   // Create a new `HashState` instance that wraps `state`. All calls to
   // `combine()` and `combine_contiguous()` on the new instance will be
   // redirected to the original `state` object. The `state` object must outlive
-  // the `HashState` instance.
-  template <typename T>
+  // the `HashState` instance. `T` must be a subclass of `HashStateBase<T>` -
+  // users should not define their own HashState types.
+  template <
+      typename T,
+      absl::enable_if_t<
+          std::is_base_of<hash_internal::HashStateBase<T>, T>::value, int> = 0>
   static HashState Create(T* state) {
     HashState s;
     s.Init(state);
@@ -347,12 +357,19 @@
     hash_state.combine_contiguous_(hash_state.state_, first, size);
     return hash_state;
   }
+
+  static HashState combine_weakly_mixed_integer(
+      HashState hash_state, hash_internal::WeaklyMixedInteger value) {
+    hash_state.combine_weakly_mixed_integer_(hash_state.state_, value);
+    return hash_state;
+  }
   using HashState::HashStateBase::combine_contiguous;
 
  private:
   HashState() = default;
 
   friend class HashState::HashStateBase;
+  friend struct hash_internal::CombineRaw;
 
   template <typename T>
   static void CombineContiguousImpl(void* p, const unsigned char* first,
@@ -362,9 +379,29 @@
   }
 
   template <typename T>
+  static void CombineWeaklyMixedIntegerImpl(
+      void* p, hash_internal::WeaklyMixedInteger value) {
+    T& state = *static_cast<T*>(p);
+    state = T::combine_weakly_mixed_integer(std::move(state), value);
+  }
+
+  static HashState combine_raw(HashState hash_state, uint64_t value) {
+    hash_state.combine_raw_(hash_state.state_, value);
+    return hash_state;
+  }
+
+  template <typename T>
+  static void CombineRawImpl(void* p, uint64_t value) {
+    T& state = *static_cast<T*>(p);
+    state = hash_internal::CombineRaw()(std::move(state), value);
+  }
+
+  template <typename T>
   void Init(T* state) {
     state_ = state;
+    combine_weakly_mixed_integer_ = &CombineWeaklyMixedIntegerImpl<T>;
     combine_contiguous_ = &CombineContiguousImpl<T>;
+    combine_raw_ = &CombineRawImpl<T>;
     run_combine_unordered_ = &RunCombineUnorderedImpl<T>;
   }
 
@@ -402,7 +439,9 @@
   // Do not erase an already erased state.
   void Init(HashState* state) {
     state_ = state->state_;
+    combine_weakly_mixed_integer_ = state->combine_weakly_mixed_integer_;
     combine_contiguous_ = state->combine_contiguous_;
+    combine_raw_ = state->combine_raw_;
     run_combine_unordered_ = state->run_combine_unordered_;
   }
 
@@ -412,7 +451,10 @@
   }
 
   void* state_;
+  void (*combine_weakly_mixed_integer_)(
+      void*, absl::hash_internal::WeaklyMixedInteger);
   void (*combine_contiguous_)(void*, const unsigned char*, size_t);
+  void (*combine_raw_)(void*, uint64_t);
   HashState (*run_combine_unordered_)(
       HashState state,
       absl::FunctionRef<void(HashState, absl::FunctionRef<void(HashState&)>)>);
diff --git a/absl/hash/hash_benchmark.cc b/absl/hash/hash_benchmark.cc
index 9b73f46..73b037d 100644
--- a/absl/hash/hash_benchmark.cc
+++ b/absl/hash/hash_benchmark.cc
@@ -146,6 +146,59 @@
   return result;
 }
 
+template <typename T>
+struct LongCombine {
+  T a[200]{};
+  template <typename H>
+  friend H AbslHashValue(H state, const LongCombine& v) {
+    // This is testing a single call to `combine` with a lot of arguments to
+    // test the performance of the folding logic.
+    return H::combine(
+        std::move(state),  //
+        v.a[0], v.a[1], v.a[2], v.a[3], v.a[4], v.a[5], v.a[6], v.a[7], v.a[8],
+        v.a[9], v.a[10], v.a[11], v.a[12], v.a[13], v.a[14], v.a[15], v.a[16],
+        v.a[17], v.a[18], v.a[19], v.a[20], v.a[21], v.a[22], v.a[23], v.a[24],
+        v.a[25], v.a[26], v.a[27], v.a[28], v.a[29], v.a[30], v.a[31], v.a[32],
+        v.a[33], v.a[34], v.a[35], v.a[36], v.a[37], v.a[38], v.a[39], v.a[40],
+        v.a[41], v.a[42], v.a[43], v.a[44], v.a[45], v.a[46], v.a[47], v.a[48],
+        v.a[49], v.a[50], v.a[51], v.a[52], v.a[53], v.a[54], v.a[55], v.a[56],
+        v.a[57], v.a[58], v.a[59], v.a[60], v.a[61], v.a[62], v.a[63], v.a[64],
+        v.a[65], v.a[66], v.a[67], v.a[68], v.a[69], v.a[70], v.a[71], v.a[72],
+        v.a[73], v.a[74], v.a[75], v.a[76], v.a[77], v.a[78], v.a[79], v.a[80],
+        v.a[81], v.a[82], v.a[83], v.a[84], v.a[85], v.a[86], v.a[87], v.a[88],
+        v.a[89], v.a[90], v.a[91], v.a[92], v.a[93], v.a[94], v.a[95], v.a[96],
+        v.a[97], v.a[98], v.a[99], v.a[100], v.a[101], v.a[102], v.a[103],
+        v.a[104], v.a[105], v.a[106], v.a[107], v.a[108], v.a[109], v.a[110],
+        v.a[111], v.a[112], v.a[113], v.a[114], v.a[115], v.a[116], v.a[117],
+        v.a[118], v.a[119], v.a[120], v.a[121], v.a[122], v.a[123], v.a[124],
+        v.a[125], v.a[126], v.a[127], v.a[128], v.a[129], v.a[130], v.a[131],
+        v.a[132], v.a[133], v.a[134], v.a[135], v.a[136], v.a[137], v.a[138],
+        v.a[139], v.a[140], v.a[141], v.a[142], v.a[143], v.a[144], v.a[145],
+        v.a[146], v.a[147], v.a[148], v.a[149], v.a[150], v.a[151], v.a[152],
+        v.a[153], v.a[154], v.a[155], v.a[156], v.a[157], v.a[158], v.a[159],
+        v.a[160], v.a[161], v.a[162], v.a[163], v.a[164], v.a[165], v.a[166],
+        v.a[167], v.a[168], v.a[169], v.a[170], v.a[171], v.a[172], v.a[173],
+        v.a[174], v.a[175], v.a[176], v.a[177], v.a[178], v.a[179], v.a[180],
+        v.a[181], v.a[182], v.a[183], v.a[184], v.a[185], v.a[186], v.a[187],
+        v.a[188], v.a[189], v.a[190], v.a[191], v.a[192], v.a[193], v.a[194],
+        v.a[195], v.a[196], v.a[197], v.a[198], v.a[199]);
+  }
+};
+
+template <typename T>
+auto MakeLongTuple() {
+  auto t1 = std::tuple<T>();
+  auto t2 = std::tuple_cat(t1, t1);
+  auto t3 = std::tuple_cat(t2, t2);
+  auto t4 = std::tuple_cat(t3, t3);
+  auto t5 = std::tuple_cat(t4, t4);
+  auto t6 = std::tuple_cat(t5, t5);
+  // Ideally this would be much larger, but some configurations can't handle
+  // making tuples with that many elements. They break inside std::tuple itself.
+  static_assert(std::tuple_size<decltype(t6)>::value == 32, "");
+  return t6;
+}
+
 // Generates a benchmark and a codegen method for the provided types.  The
 // codegen method provides a well known entrypoint for dumping assembly.
 #define MAKE_BENCHMARK(hash, name, ...)                          \
@@ -171,6 +224,10 @@
 MAKE_BENCHMARK(AbslHash, TupleInt32BoolInt64,
                std::tuple<int32_t, bool, int64_t>{});
 MAKE_BENCHMARK(AbslHash, String_0, std::string());
+MAKE_BENCHMARK(AbslHash, String_1, std::string(1, 'a'));
+MAKE_BENCHMARK(AbslHash, String_2, std::string(2, 'a'));
+MAKE_BENCHMARK(AbslHash, String_4, std::string(4, 'a'));
+MAKE_BENCHMARK(AbslHash, String_8, std::string(8, 'a'));
 MAKE_BENCHMARK(AbslHash, String_10, std::string(10, 'a'));
 MAKE_BENCHMARK(AbslHash, String_30, std::string(30, 'a'));
 MAKE_BENCHMARK(AbslHash, String_90, std::string(90, 'a'));
@@ -212,6 +269,10 @@
                std::make_pair(std::string(200, 'a'), std::string(200, 'b')));
 MAKE_BENCHMARK(AbslHash, PairStringString_5000,
                std::make_pair(std::string(5000, 'a'), std::string(5000, 'b')));
+MAKE_BENCHMARK(AbslHash, LongTupleInt32, MakeLongTuple<int>());
+MAKE_BENCHMARK(AbslHash, LongTupleString, MakeLongTuple<std::string>());
+MAKE_BENCHMARK(AbslHash, LongCombineInt32, LongCombine<int>());
+MAKE_BENCHMARK(AbslHash, LongCombineString, LongCombine<std::string>());
 
 MAKE_BENCHMARK(TypeErasedAbslHash, Int32, int32_t{});
 MAKE_BENCHMARK(TypeErasedAbslHash, Int64, int64_t{});
@@ -317,7 +378,10 @@
 
 MAKE_LATENCY_BENCHMARK(AbslHash, Int32, PodRand<int32_t>)
 MAKE_LATENCY_BENCHMARK(AbslHash, Int64, PodRand<int64_t>)
+MAKE_LATENCY_BENCHMARK(AbslHash, String3, StringRand<3>)
+MAKE_LATENCY_BENCHMARK(AbslHash, String5, StringRand<5>)
 MAKE_LATENCY_BENCHMARK(AbslHash, String9, StringRand<9>)
+MAKE_LATENCY_BENCHMARK(AbslHash, String17, StringRand<17>)
 MAKE_LATENCY_BENCHMARK(AbslHash, String33, StringRand<33>)
 MAKE_LATENCY_BENCHMARK(AbslHash, String65, StringRand<65>)
 MAKE_LATENCY_BENCHMARK(AbslHash, String257, StringRand<257>)
diff --git a/absl/hash/hash_instantiated_test.cc b/absl/hash/hash_instantiated_test.cc
index e65de9c..f0df86f 100644
--- a/absl/hash/hash_instantiated_test.cc
+++ b/absl/hash/hash_instantiated_test.cc
@@ -51,7 +51,7 @@
 
 // Dummy type with unordered equality and hashing semantics.  This preserves
 // input order internally, and is used below to ensure we get test coverage
-// for equal sequences with different iteraton orders.
+// for equal sequences with different iteration orders.
 template <typename T>
 class UnorderedSequence {
  public:
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index 7fecf53..7582f54 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -29,20 +29,24 @@
 #include <ostream>
 #include <set>
 #include <string>
+#include <string_view>
 #include <tuple>
 #include <type_traits>
 #include <unordered_map>
 #include <utility>
 #include <vector>
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/config.h"
+#include "absl/container/flat_hash_map.h"
 #include "absl/container/flat_hash_set.h"
 #include "absl/hash/hash_testing.h"
 #include "absl/hash/internal/hash_test.h"
 #include "absl/hash/internal/spy_hash_state.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
+#include "absl/numeric/bits.h"
 #include "absl/strings/cord_test_helpers.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
@@ -52,15 +56,12 @@
 #include <filesystem>  // NOLINT
 #endif
 
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-#include <string_view>
-#endif
-
 namespace {
 
 using ::absl::hash_test_internal::is_hashable;
 using ::absl::hash_test_internal::TypeErasedContainer;
 using ::absl::hash_test_internal::TypeErasedValue;
+using ::testing::SizeIs;
 
 template <typename T>
 using TypeErasedVector = TypeErasedContainer<std::vector<T>>;
@@ -117,6 +118,15 @@
       std::make_tuple(true, false)));
 }
 
+TEST(HashValueTest, HashConsistentAcrossIntTypes){
+  std::vector<size_t> hashes = {
+      absl::Hash<int8_t>{}(1),  absl::Hash<uint8_t>{}(1),
+      absl::Hash<int16_t>{}(1), absl::Hash<uint16_t>{}(1),
+      absl::Hash<int32_t>{}(1), absl::Hash<uint32_t>{}(1),
+      absl::Hash<int64_t>{}(1), absl::Hash<uint64_t>{}(1)};
+  EXPECT_THAT(hashes, testing::Each(absl::Hash<int>{}(1)));
+}
+
 TEST(HashValueTest, FloatingPoint) {
   EXPECT_TRUE((is_hashable<float>::value));
   EXPECT_TRUE((is_hashable<double>::value));
@@ -153,8 +163,8 @@
 }
 
 TEST(HashValueTest, PointerAlignment) {
-  // We want to make sure that pointer alignment will not cause bits to be
-  // stuck.
+  // We want to make sure that pointer alignment will not cause too many bits to
+  // be stuck.
 
   constexpr size_t kTotalSize = 1 << 20;
   std::unique_ptr<char[]> data(new char[kTotalSize]);
@@ -178,7 +188,8 @@
     // Limit the scope to the bits we would be using for Swisstable.
     constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1;
     size_t stuck_bits = (~bits_or | bits_and) & kMask;
-    EXPECT_EQ(stuck_bits, 0u) << "0x" << std::hex << stuck_bits;
+    // Test that there are at most 3 stuck bits.
+    EXPECT_LE(absl::popcount(stuck_bits), 3) << "0x" << std::hex << stuck_bits;
   }
 }
 
@@ -301,7 +312,7 @@
 
 struct DummyDeleter {
   template <typename T>
-  void operator() (T* ptr) {}
+  void operator() (T*) {}
 };
 
 struct SmartPointerEq {
@@ -381,6 +392,37 @@
   return absl::MakeFragmentedCord(parts);
 }
 
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+TEST(HashValueTest, TestIntrinsicInt128) {
+  EXPECT_TRUE((is_hashable<__int128_t>::value));
+  EXPECT_TRUE((is_hashable<__uint128_t>::value));
+
+  absl::flat_hash_map<size_t, int> hash_to_index;
+  std::vector<__uint128_t> values;
+  for (int i = 0; i < 128; ++i) {
+    // Some arbitrary pattern to check if changing each bit changes the hash.
+    static constexpr __uint128_t kPattern =
+        __uint128_t{0x0123456789abcdef} |
+        (__uint128_t{0x0123456789abcdef} << 64);
+    const __uint128_t value = kPattern ^ (__uint128_t{1} << i);
+    const __int128_t as_signed = static_cast<__int128_t>(value);
+
+    values.push_back(value);
+    auto [it, inserted] =
+        hash_to_index.insert({absl::Hash<__uint128_t>{}(value), i});
+    ASSERT_TRUE(inserted) << "Duplicate hash: " << i << " vs " << it->second;
+
+    // Verify that the fast-path for MixingHashState does not break the hash.
+    EXPECT_EQ(absl::HashOf(value), absl::Hash<__uint128_t>{}(value));
+    EXPECT_EQ(absl::HashOf(as_signed), absl::Hash<__int128_t>{}(as_signed));
+  }
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(values));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::vector<__int128_t>(values.begin(), values.end())));
+}
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+
 TEST(HashValueTest, Strings) {
   EXPECT_TRUE((is_hashable<std::string>::value));
 
@@ -389,33 +431,39 @@
   const std::string large = std::string(2048, 'x');  // multiple of chunk size
   const std::string huge = std::string(5000, 'a');   // not a multiple
 
-  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(  //
-      std::string(), absl::string_view(), absl::Cord(),                     //
-      std::string(""), absl::string_view(""), absl::Cord(""),               //
-      std::string(small), absl::string_view(small), absl::Cord(small),      //
-      std::string(dup), absl::string_view(dup), absl::Cord(dup),            //
-      std::string(large), absl::string_view(large), absl::Cord(large),      //
-      std::string(huge), absl::string_view(huge), FlatCord(huge),           //
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::string(), absl::string_view(), absl::Cord(), std::string(""),
+      absl::string_view(""), absl::Cord(""), std::string(small),
+      absl::string_view(small), absl::Cord(small), FragmentedCord(small),
+      std::string(dup), absl::string_view(dup), absl::Cord(dup),
+      std::string(large), absl::string_view(large), absl::Cord(large),
+      std::string(huge), absl::string_view(huge), FlatCord(huge),
       FragmentedCord(huge))));
 
   // Also check that nested types maintain the same hash.
   const WrapInTuple t{};
-  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(  //
-      t(std::string()), t(absl::string_view()), t(absl::Cord()),            //
-      t(std::string("")), t(absl::string_view("")), t(absl::Cord("")),      //
-      t(std::string(small)), t(absl::string_view(small)),                   //
-          t(absl::Cord(small)),                                             //
-      t(std::string(dup)), t(absl::string_view(dup)), t(absl::Cord(dup)),   //
-      t(std::string(large)), t(absl::string_view(large)),                   //
-          t(absl::Cord(large)),                                             //
-      t(std::string(huge)), t(absl::string_view(huge)),                     //
-          t(FlatCord(huge)), t(FragmentedCord(huge)))));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      t(std::string()), t(absl::string_view()), t(absl::Cord()),
+      t(std::string("")), t(absl::string_view("")), t(absl::Cord("")),
+      t(std::string(small)), t(absl::string_view(small)), t(absl::Cord(small)),
+      t(FragmentedCord(small)), t(std::string(dup)), t(absl::string_view(dup)),
+      t(absl::Cord(dup)), t(std::string(large)), t(absl::string_view(large)),
+      t(absl::Cord(large)), t(std::string(huge)), t(absl::string_view(huge)),
+      t(FlatCord(huge)), t(FragmentedCord(huge)))));
 
   // Make sure that hashing a `const char*` does not use its string-value.
   EXPECT_NE(SpyHash(static_cast<const char*>("ABC")),
             SpyHash(absl::string_view("ABC")));
 }
 
+TEST(HashValueTest, StringsVector) {
+  using Vec = std::vector<std::string>;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      Vec{"abc", "def"}, Vec{"abcde", "f"},
+      Vec{"abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"},
+      Vec{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY", "Z"})));
+}
+
 TEST(HashValueTest, WString) {
   EXPECT_TRUE((is_hashable<std::wstring>::value));
 
@@ -444,22 +492,15 @@
 }
 
 TEST(HashValueTest, WStringView) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   EXPECT_TRUE((is_hashable<std::wstring_view>::value));
 
   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
       std::wstring_view(), std::wstring_view(L"ABC"), std::wstring_view(L"ABC"),
       std::wstring_view(L"Some other different string_view"),
       std::wstring_view(L"Iñtërnâtiônàlizætiøn"))));
-#endif
 }
 
 TEST(HashValueTest, U16StringView) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   EXPECT_TRUE((is_hashable<std::u16string_view>::value));
 
   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
@@ -467,13 +508,9 @@
                       std::u16string_view(u"ABC"),
                       std::u16string_view(u"Some other different string_view"),
                       std::u16string_view(u"Iñtërnâtiônàlizætiøn"))));
-#endif
 }
 
 TEST(HashValueTest, U32StringView) {
-#ifndef ABSL_HAVE_STD_STRING_VIEW
-  GTEST_SKIP();
-#else
   EXPECT_TRUE((is_hashable<std::u32string_view>::value));
 
   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
@@ -481,7 +518,6 @@
                       std::u32string_view(U"ABC"),
                       std::u32string_view(U"Some other different string_view"),
                       std::u32string_view(U"Iñtërnâtiônàlizætiøn"))));
-#endif
 }
 
 TEST(HashValueTest, StdFilesystemPath) {
@@ -656,7 +692,9 @@
   //
   // This test is run on a buffer that is a multiple of the stride size, and one
   // that isn't.
-  for (size_t big_buffer_size : {1024u * 2 + 512u, 1024u * 3}) {
+  const size_t kChunkSize = absl::hash_internal::PiecewiseChunkSize();
+  for (size_t big_buffer_size :
+       {2 * kChunkSize + kChunkSize / 2, 3 * kChunkSize}) {
     SCOPED_TRACE(big_buffer_size);
     std::string big_buffer;
     for (size_t i = 0; i < big_buffer_size; ++i) {
@@ -666,8 +704,15 @@
     auto big_buffer_hash = hash(PiecewiseHashTester(big_buffer));
 
     const int possible_breaks = 9;
-    size_t breaks[possible_breaks] = {1,    512,  1023, 1024, 1025,
-                                      1536, 2047, 2048, 2049};
+    size_t breaks[possible_breaks] = {1,
+                                      kChunkSize / 2,
+                                      kChunkSize - 1,
+                                      kChunkSize,
+                                      kChunkSize + 1,
+                                      kChunkSize + kChunkSize / 2,
+                                      2 * kChunkSize - 1,
+                                      2 * kChunkSize,
+                                      2 * kChunkSize + 1};
     for (unsigned test_mask = 0; test_mask < (1u << possible_breaks);
          ++test_mask) {
       SCOPED_TRACE(test_mask);
@@ -677,7 +722,7 @@
           break_locations.insert(breaks[j]);
         }
       }
-      EXPECT_EQ(
+      ASSERT_EQ(
           hash(PiecewiseHashTester(big_buffer, std::move(break_locations))),
           big_buffer_hash);
     }
@@ -1145,4 +1190,38 @@
   EXPECT_FALSE(HashOfExplicitParameter<int>(0));
 }
 
+struct TypeErasedHashStateUser {
+  int a;
+  std::string b;
+
+  template <typename H>
+  friend H AbslHashValue(H state, const TypeErasedHashStateUser& value) {
+    absl::HashState type_erased_state = absl::HashState::Create(&state);
+    absl::HashState::combine(std::move(type_erased_state), value.a, value.b);
+    return state;
+  }
+};
+
+TEST(HashOf, MatchesTypeErasedHashState) {
+  std::string s = "s";
+  EXPECT_EQ(absl::HashOf(1, s), absl::Hash<TypeErasedHashStateUser>{}(
+                                    TypeErasedHashStateUser{1, s}));
+}
+
+struct AutoReturnTypeUser {
+  int a;
+  std::string b;
+
+  template <typename H>
+  friend auto AbslHashValue(H state, const AutoReturnTypeUser& value) {
+    return H::combine(std::move(state), value.a, value.b);
+  }
+};
+
+TEST(HashOf, AutoReturnTypeUser) {
+  std::string s = "s";
+  EXPECT_EQ(absl::HashOf(1, s),
+            absl::Hash<AutoReturnTypeUser>{}(AutoReturnTypeUser{1, s}));
+}
+
 }  // namespace
diff --git a/absl/hash/hash_testing.h b/absl/hash/hash_testing.h
index 1e1c574..817a40d 100644
--- a/absl/hash/hash_testing.h
+++ b/absl/hash/hash_testing.h
@@ -15,7 +15,9 @@
 #ifndef ABSL_HASH_HASH_TESTING_H_
 #define ABSL_HASH_HASH_TESTING_H_
 
+#include <cstddef>
 #include <initializer_list>
+#include <string>
 #include <tuple>
 #include <type_traits>
 #include <vector>
@@ -141,21 +143,20 @@
 // }
 //
 template <int&... ExplicitBarrier, typename Container>
-ABSL_MUST_USE_RESULT testing::AssertionResult
-VerifyTypeImplementsAbslHashCorrectly(const Container& values);
+testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(
+    const Container& values);
 
 template <int&... ExplicitBarrier, typename Container, typename Eq>
-ABSL_MUST_USE_RESULT testing::AssertionResult
-VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals);
+testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(
+    const Container& values, Eq equals);
 
 template <int&..., typename T>
-ABSL_MUST_USE_RESULT testing::AssertionResult
-VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values);
+testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(
+    std::initializer_list<T> values);
 
 template <int&..., typename T, typename Eq>
-ABSL_MUST_USE_RESULT testing::AssertionResult
-VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values,
-                                      Eq equals);
+testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(
+    std::initializer_list<T> values, Eq equals);
 
 namespace hash_internal {
 
@@ -184,8 +185,8 @@
 };
 
 template <typename Container, typename Eq>
-ABSL_MUST_USE_RESULT testing::AssertionResult
-VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) {
+testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(
+    const Container& values, Eq equals) {
   using V = typename Container::value_type;
 
   struct Info {
@@ -244,7 +245,8 @@
       if (v.expand() != expected) {
         return testing::AssertionFailure()
                << "Values " << c[0].ToString() << " and " << v.ToString()
-               << " evaluate as equal but have an unequal hash expansion.";
+               << " evaluate as equal but have unequal hash expansions ("
+               << expected << " vs. " << v.expand() << ").";
       }
     }
 
@@ -256,17 +258,18 @@
         case SpyHashState::CompareResult::kEqual:
           return testing::AssertionFailure()
                  << "Values " << c[0].ToString() << " and " << c2[0].ToString()
-                 << " evaluate as unequal but have an equal hash expansion.";
+                 << " evaluate as unequal but have an equal hash expansion:"
+                 << c2_hash << ".";
         case SpyHashState::CompareResult::kBSuffixA:
           return testing::AssertionFailure()
-                 << "Hash expansion of " << c2[0].ToString()
+                 << "Hash expansion of " << c2[0].ToString() << ";" << c2_hash
                  << " is a suffix of the hash expansion of " << c[0].ToString()
-                 << ".";
+                 << ";" << expected << ".";
         case SpyHashState::CompareResult::kASuffixB:
           return testing::AssertionFailure()
-                 << "Hash expansion of " << c[0].ToString()
-                 << " is a suffix of the hash expansion of " << c2[0].ToString()
-                 << ".";
+                 << "Hash expansion of " << c[0].ToString() << ";"
+                 << expected << " is a suffix of the hash expansion of "
+                 << c2[0].ToString() << ";" << c2_hash << ".";
         case SpyHashState::CompareResult::kUnequal:
           break;
       }
@@ -341,32 +344,31 @@
 }  // namespace hash_internal
 
 template <int&..., typename Container>
-ABSL_MUST_USE_RESULT testing::AssertionResult
-VerifyTypeImplementsAbslHashCorrectly(const Container& values) {
+testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(
+    const Container& values) {
   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
       hash_internal::ContainerAsVector<Container>::Do(values),
       hash_internal::DefaultEquals{});
 }
 
 template <int&..., typename Container, typename Eq>
-ABSL_MUST_USE_RESULT testing::AssertionResult
-VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) {
+testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(
+    const Container& values, Eq equals) {
   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
       hash_internal::ContainerAsVector<Container>::Do(values), equals);
 }
 
 template <int&..., typename T>
-ABSL_MUST_USE_RESULT testing::AssertionResult
-VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values) {
+testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(
+    std::initializer_list<T> values) {
   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
       hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values),
       hash_internal::DefaultEquals{});
 }
 
 template <int&..., typename T, typename Eq>
-ABSL_MUST_USE_RESULT testing::AssertionResult
-VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values,
-                                      Eq equals) {
+testing::AssertionResult VerifyTypeImplementsAbslHashCorrectly(
+    std::initializer_list<T> values, Eq equals) {
   return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
       hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values),
       equals);
diff --git a/absl/hash/internal/hash.cc b/absl/hash/internal/hash.cc
index 93906ef..9abace5 100644
--- a/absl/hash/internal/hash.cc
+++ b/absl/hash/internal/hash.cc
@@ -14,6 +14,14 @@
 
 #include "absl/hash/internal/hash.h"
 
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/hash/internal/low_level_hash.h"
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
@@ -21,9 +29,10 @@
 uint64_t MixingHashState::CombineLargeContiguousImpl32(
     uint64_t state, const unsigned char* first, size_t len) {
   while (len >= PiecewiseChunkSize()) {
-    state = Mix(state,
-                hash_internal::CityHash32(reinterpret_cast<const char*>(first),
-                                          PiecewiseChunkSize()));
+    state = Mix(
+        state ^ hash_internal::CityHash32(reinterpret_cast<const char*>(first),
+                                          PiecewiseChunkSize()),
+        kMul);
     len -= PiecewiseChunkSize();
     first += PiecewiseChunkSize();
   }
@@ -35,7 +44,7 @@
 uint64_t MixingHashState::CombineLargeContiguousImpl64(
     uint64_t state, const unsigned char* first, size_t len) {
   while (len >= PiecewiseChunkSize()) {
-    state = Mix(state, Hash64(first, PiecewiseChunkSize()));
+    state = Mix(state ^ Hash64(first, PiecewiseChunkSize()), kMul);
     len -= PiecewiseChunkSize();
     first += PiecewiseChunkSize();
   }
@@ -46,22 +55,9 @@
 
 ABSL_CONST_INIT const void* const MixingHashState::kSeed = &kSeed;
 
-// The salt array used by LowLevelHash. This array is NOT the mechanism used to
-// make absl::Hash non-deterministic between program invocations.  See `Seed()`
-// for that mechanism.
-//
-// Any random values are fine. These values are just digits from the decimal
-// part of pi.
-// https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number
-constexpr uint64_t kHashSalt[5] = {
-    uint64_t{0x243F6A8885A308D3}, uint64_t{0x13198A2E03707344},
-    uint64_t{0xA4093822299F31D0}, uint64_t{0x082EFA98EC4E6C89},
-    uint64_t{0x452821E638D01377},
-};
-
 uint64_t MixingHashState::LowLevelHashImpl(const unsigned char* data,
                                            size_t len) {
-  return LowLevelHashLenGt16(data, len, Seed(), kHashSalt);
+  return LowLevelHashLenGt32(data, len, Seed(), &kStaticRandomData[0]);
 }
 
 }  // namespace hash_internal
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 03bf183..eb53823 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -24,20 +24,36 @@
 #include <TargetConditionals.h>
 #endif
 
+// We include config.h here to make sure that ABSL_INTERNAL_CPLUSPLUS_LANG is
+// defined.
 #include "absl/base/config.h"
 
+// GCC15 warns that <ciso646> is deprecated in C++17 and suggests using
+// <version> instead, even though <version> is not available in C++17 mode prior
+// to GCC9.
+#if defined(__has_include)
+#if __has_include(<version>)
+#define ABSL_INTERNAL_VERSION_HEADER_AVAILABLE 1
+#endif
+#endif
+
 // For feature testing and determining which headers can be included.
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L || \
+    defined(ABSL_INTERNAL_VERSION_HEADER_AVAILABLE)
 #include <version>
 #else
 #include <ciso646>
 #endif
 
+#undef ABSL_INTERNAL_VERSION_HEADER_AVAILABLE
+
 #include <algorithm>
 #include <array>
 #include <bitset>
+#include <cassert>
 #include <cmath>
 #include <cstddef>
+#include <cstdint>
 #include <cstring>
 #include <deque>
 #include <forward_list>
@@ -49,6 +65,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <string_view>
 #include <tuple>
 #include <type_traits>
 #include <unordered_map>
@@ -56,11 +73,14 @@
 #include <utility>
 #include <vector>
 
+#include "absl/base/attributes.h"
+#include "absl/base/internal/endian.h"
 #include "absl/base/internal/unaligned_access.h"
+#include "absl/base/optimization.h"
 #include "absl/base/port.h"
 #include "absl/container/fixed_array.h"
 #include "absl/hash/internal/city.h"
-#include "absl/hash/internal/low_level_hash.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
 #include "absl/meta/type_traits.h"
 #include "absl/numeric/bits.h"
 #include "absl/numeric/int128.h"
@@ -69,15 +89,10 @@
 #include "absl/types/variant.h"
 #include "absl/utility/utility.h"
 
-#if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \
-    !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
+#if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L
 #include <filesystem>  // NOLINT
 #endif
 
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-#include <string_view>
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
@@ -340,16 +355,57 @@
 template <>
 struct is_uniquely_represented<bool> : std::false_type {};
 
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+// Specialize the trait for GNU extension types.
+template <>
+struct is_uniquely_represented<__int128> : std::true_type {};
+template <>
+struct is_uniquely_represented<unsigned __int128> : std::true_type {};
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+
+template <typename T>
+struct FitsIn64Bits : std::integral_constant<bool, sizeof(T) <= 8> {};
+
+struct CombineRaw {
+  template <typename H>
+  H operator()(H state, uint64_t value) const {
+    return H::combine_raw(std::move(state), value);
+  }
+};
+
 // hash_bytes()
 //
 // Convenience function that combines `hash_state` with the byte representation
 // of `value`.
-template <typename H, typename T>
+template <typename H, typename T,
+          absl::enable_if_t<FitsIn64Bits<T>::value, int> = 0>
+H hash_bytes(H hash_state, const T& value) {
+  const unsigned char* start = reinterpret_cast<const unsigned char*>(&value);
+  uint64_t v;
+  if constexpr (sizeof(T) == 1) {
+    v = *start;
+  } else if constexpr (sizeof(T) == 2) {
+    v = absl::base_internal::UnalignedLoad16(start);
+  } else if constexpr (sizeof(T) == 4) {
+    v = absl::base_internal::UnalignedLoad32(start);
+  } else {
+    static_assert(sizeof(T) == 8);
+    v = absl::base_internal::UnalignedLoad64(start);
+  }
+  return CombineRaw()(std::move(hash_state), v);
+}
+template <typename H, typename T,
+          absl::enable_if_t<!FitsIn64Bits<T>::value, int> = 0>
 H hash_bytes(H hash_state, const T& value) {
   const unsigned char* start = reinterpret_cast<const unsigned char*>(&value);
   return H::combine_contiguous(std::move(hash_state), start, sizeof(value));
 }
 
+template <typename H>
+H hash_weakly_mixed_integer(H hash_state, WeaklyMixedInteger value) {
+  return H::combine_weakly_mixed_integer(std::move(hash_state), value);
+}
+
 // -----------------------------------------------------------------------------
 // AbslHashValue for Basic Types
 // -----------------------------------------------------------------------------
@@ -446,9 +502,9 @@
                                                              T ptr) {
   auto v = reinterpret_cast<uintptr_t>(ptr);
   // Due to alignment, pointers tend to have low bits as zero, and the next few
-  // bits follow a pattern since they are also multiples of some base value.
-  // Mixing the pointer twice helps prevent stuck low bits for certain alignment
-  // values.
+  // bits follow a pattern since they are also multiples of some base value. The
+  // byte swap in WeakMix helps ensure we still have good entropy in low bits.
+  // Mix pointers twice to ensure we have good entropy in low bits.
   return H::combine(std::move(hash_state), v, v);
 }
 
@@ -468,7 +524,7 @@
     // padding (namely when they have 1 or 3 ints). The value below is a lower
     // bound on the number of salient, non-padding bytes that we use for
     // hashing.
-    if (alignof(T C::*) == alignof(int)) {
+    if constexpr (alignof(T C::*) == alignof(int)) {
       // No padding when all subobjects have the same size as the total
       // alignment. This happens in 32-bit mode.
       return n;
@@ -565,7 +621,7 @@
 H AbslHashValue(H hash_state, absl::string_view str) {
   return H::combine(
       H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
-      str.size());
+      WeaklyMixedInteger{str.size()});
 }
 
 // Support std::wstring, std::u16string and std::u32string.
@@ -578,11 +634,9 @@
     const std::basic_string<Char, std::char_traits<Char>, Alloc>& str) {
   return H::combine(
       H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
-      str.size());
+      WeaklyMixedInteger{str.size()});
 }
 
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-
 // Support std::wstring_view, std::u16string_view and std::u32string_view.
 template <typename Char, typename H,
           typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||
@@ -591,13 +645,10 @@
 H AbslHashValue(H hash_state, std::basic_string_view<Char> str) {
   return H::combine(
       H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
-      str.size());
+      WeaklyMixedInteger{str.size()});
 }
 
-#endif  // ABSL_HAVE_STD_STRING_VIEW
-
 #if defined(__cpp_lib_filesystem) && __cpp_lib_filesystem >= 201703L && \
-    !defined(_LIBCPP_HAS_NO_FILESYSTEM_LIBRARY) && \
     (!defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) ||        \
      __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 130000) &&       \
     (!defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) ||         \
@@ -642,7 +693,7 @@
   for (const auto& t : deque) {
     hash_state = H::combine(std::move(hash_state), t);
   }
-  return H::combine(std::move(hash_state), deque.size());
+  return H::combine(std::move(hash_state), WeaklyMixedInteger{deque.size()});
 }
 
 // AbslHashValue for hashing std::forward_list
@@ -654,7 +705,7 @@
     hash_state = H::combine(std::move(hash_state), t);
     ++size;
   }
-  return H::combine(std::move(hash_state), size);
+  return H::combine(std::move(hash_state), WeaklyMixedInteger{size});
 }
 
 // AbslHashValue for hashing std::list
@@ -664,7 +715,7 @@
   for (const auto& t : list) {
     hash_state = H::combine(std::move(hash_state), t);
   }
-  return H::combine(std::move(hash_state), list.size());
+  return H::combine(std::move(hash_state), WeaklyMixedInteger{list.size()});
 }
 
 // AbslHashValue for hashing std::vector
@@ -678,7 +729,7 @@
 AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {
   return H::combine(H::combine_contiguous(std::move(hash_state), vector.data(),
                                           vector.size()),
-                    vector.size());
+                    WeaklyMixedInteger{vector.size()});
 }
 
 // AbslHashValue special cases for hashing std::vector<bool>
@@ -699,7 +750,8 @@
     unsigned char c = static_cast<unsigned char>(i);
     hash_state = combiner.add_buffer(std::move(hash_state), &c, sizeof(c));
   }
-  return H::combine(combiner.finalize(std::move(hash_state)), vector.size());
+  return H::combine(combiner.finalize(std::move(hash_state)),
+                    WeaklyMixedInteger{vector.size()});
 }
 #else
 // When not working around the libstdc++ bug above, we still have to contend
@@ -715,7 +767,7 @@
 AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {
   return H::combine(std::move(hash_state),
                     std::hash<std::vector<T, Allocator>>{}(vector),
-                    vector.size());
+                    WeaklyMixedInteger{vector.size()});
 }
 #endif
 
@@ -732,7 +784,7 @@
   for (const auto& t : map) {
     hash_state = H::combine(std::move(hash_state), t);
   }
-  return H::combine(std::move(hash_state), map.size());
+  return H::combine(std::move(hash_state), WeaklyMixedInteger{map.size()});
 }
 
 // AbslHashValue for hashing std::multimap
@@ -745,7 +797,7 @@
   for (const auto& t : map) {
     hash_state = H::combine(std::move(hash_state), t);
   }
-  return H::combine(std::move(hash_state), map.size());
+  return H::combine(std::move(hash_state), WeaklyMixedInteger{map.size()});
 }
 
 // AbslHashValue for hashing std::set
@@ -755,7 +807,7 @@
   for (const auto& t : set) {
     hash_state = H::combine(std::move(hash_state), t);
   }
-  return H::combine(std::move(hash_state), set.size());
+  return H::combine(std::move(hash_state), WeaklyMixedInteger{set.size()});
 }
 
 // AbslHashValue for hashing std::multiset
@@ -765,7 +817,7 @@
   for (const auto& t : set) {
     hash_state = H::combine(std::move(hash_state), t);
   }
-  return H::combine(std::move(hash_state), set.size());
+  return H::combine(std::move(hash_state), WeaklyMixedInteger{set.size()});
 }
 
 // -----------------------------------------------------------------------------
@@ -779,7 +831,7 @@
     H hash_state, const std::unordered_set<Key, Hash, KeyEqual, Alloc>& s) {
   return H::combine(
       H::combine_unordered(std::move(hash_state), s.begin(), s.end()),
-      s.size());
+      WeaklyMixedInteger{s.size()});
 }
 
 // AbslHashValue for hashing std::unordered_multiset
@@ -790,7 +842,7 @@
     const std::unordered_multiset<Key, Hash, KeyEqual, Alloc>& s) {
   return H::combine(
       H::combine_unordered(std::move(hash_state), s.begin(), s.end()),
-      s.size());
+      WeaklyMixedInteger{s.size()});
 }
 
 // AbslHashValue for hashing std::unordered_set
@@ -802,7 +854,7 @@
               const std::unordered_map<Key, T, Hash, KeyEqual, Alloc>& s) {
   return H::combine(
       H::combine_unordered(std::move(hash_state), s.begin(), s.end()),
-      s.size());
+      WeaklyMixedInteger{s.size()});
 }
 
 // AbslHashValue for hashing std::unordered_multiset
@@ -814,7 +866,7 @@
               const std::unordered_multimap<Key, T, Hash, KeyEqual, Alloc>& s) {
   return H::combine(
       H::combine_unordered(std::move(hash_state), s.begin(), s.end()),
-      s.size());
+      WeaklyMixedInteger{s.size()});
 }
 
 // -----------------------------------------------------------------------------
@@ -925,10 +977,20 @@
 // `false`.
 struct HashSelect {
  private:
+  struct WeaklyMixedIntegerProbe {
+    template <typename H>
+    static H Invoke(H state, WeaklyMixedInteger value) {
+      return hash_internal::hash_weakly_mixed_integer(std::move(state), value);
+    }
+  };
+
   struct State : HashStateBase<State> {
     static State combine_contiguous(State hash_state, const unsigned char*,
                                     size_t);
     using State::HashStateBase::combine_contiguous;
+    static State combine_raw(State state, uint64_t value);
+    static State combine_weakly_mixed_integer(State hash_state,
+                                              WeaklyMixedInteger value);
   };
 
   struct UniquelyRepresentedProbe {
@@ -990,6 +1052,7 @@
   // disjunction provides short circuiting wrt instantiation.
   template <typename T>
   using Apply = absl::disjunction<         //
+      Probe<WeaklyMixedIntegerProbe, T>,   //
       Probe<UniquelyRepresentedProbe, T>,  //
       Probe<HashValueProbe, T>,            //
       Probe<LegacyHashProbe, T>,           //
@@ -1011,13 +1074,20 @@
   using uint128 = absl::uint128;
 #endif  // ABSL_HAVE_INTRINSIC_INT128
 
+  // Random data taken from the hexadecimal digits of Pi's fractional component.
+  // https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number
+  ABSL_CACHELINE_ALIGNED static constexpr uint64_t kStaticRandomData[] = {
+      0x243f'6a88'85a3'08d3, 0x1319'8a2e'0370'7344, 0xa409'3822'299f'31d0,
+      0x082e'fa98'ec4e'6c89, 0x4528'21e6'38d0'1377,
+  };
+
   static constexpr uint64_t kMul =
-  sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51}
-                      : uint64_t{0x9ddfea08eb382d69};
+   uint64_t{0xdcb22ca68cb134ed};
 
   template <typename T>
   using IntegralFastPath =
-      conjunction<std::is_integral<T>, is_uniquely_represented<T>>;
+      conjunction<std::is_integral<T>, is_uniquely_represented<T>,
+                  FitsIn64Bits<T>>;
 
  public:
   // Move only
@@ -1047,7 +1117,7 @@
   template <typename T, absl::enable_if_t<IntegralFastPath<T>::value, int> = 0>
   static size_t hash(T value) {
     return static_cast<size_t>(
-        Mix(Seed(), static_cast<std::make_unsigned_t<T>>(value)));
+        WeakMix(Seed(), static_cast<std::make_unsigned_t<T>>(value)));
   }
 
   // Overload of MixingHashState::hash()
@@ -1062,6 +1132,18 @@
   MixingHashState() : state_(Seed()) {}
 
   friend class MixingHashState::HashStateBase;
+  template <typename H>
+  friend H absl::hash_internal::hash_weakly_mixed_integer(H,
+                                                          WeaklyMixedInteger);
+
+  static MixingHashState combine_weakly_mixed_integer(
+      MixingHashState hash_state, WeaklyMixedInteger value) {
+    // Some transformation for the value is needed to make an empty
+    // string/container change the mixing hash state.
+    // We use constant smaller than 8 bits to make compiler use
+    // `add` with an immediate operand with 1 byte value.
+    return MixingHashState{hash_state.state_ + (0x57 + value.value)};
+  }
 
   template <typename CombinerT>
   static MixingHashState RunCombineUnordered(MixingHashState state,
@@ -1085,6 +1167,7 @@
   // Allow the HashState type-erasure implementation to invoke
   // RunCombinedUnordered() directly.
   friend class absl::HashState;
+  friend struct CombineRaw;
 
   // Workaround for MSVC bug.
   // We make the type copyable to fix the calling convention, even though we
@@ -1094,6 +1177,14 @@
 
   explicit MixingHashState(uint64_t state) : state_(state) {}
 
+  // Combines a raw value from e.g. integrals/floats/pointers/etc. This allows
+  // us to be consistent with IntegralFastPath when combining raw types, but
+  // optimize Read1To3 and Read4To8 differently for the string case.
+  static MixingHashState combine_raw(MixingHashState hash_state,
+                                     uint64_t value) {
+    return MixingHashState(WeakMix(hash_state.state_, value));
+  }
+
   // Implementation of the base case for combine_contiguous where we actually
   // mix the bytes into the state.
   // Dispatch to different implementations of the combine_contiguous depending
@@ -1107,6 +1198,49 @@
                                         std::integral_constant<int, 8>
                                         /* sizeof_size_t */);
 
+  ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t CombineSmallContiguousImpl(
+      uint64_t state, const unsigned char* first, size_t len) {
+    ABSL_ASSUME(len <= 8);
+    uint64_t v;
+    if (len >= 4) {
+      v = Read4To8(first, len);
+    } else if (len > 0) {
+      v = Read1To3(first, len);
+    } else {
+      // Empty ranges have no effect.
+      return state;
+    }
+    return WeakMix(state, v);
+  }
+
+  ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t CombineContiguousImpl9to16(
+      uint64_t state, const unsigned char* first, size_t len) {
+    ABSL_ASSUME(len >= 9);
+    ABSL_ASSUME(len <= 16);
+    // Note: any time one half of the mix function becomes zero it will fail to
+    // incorporate any bits from the other half. However, there is exactly 1 in
+    // 2^64 values for each side that achieve this, and only when the size is
+    // exactly 16 -- for smaller sizes there is an overlapping byte that makes
+    // this impossible unless the seed is *also* incredibly unlucky.
+    auto p = Read9To16(first, len);
+    return Mix(state ^ p.first, kMul ^ p.second);
+  }
+
+  ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t CombineContiguousImpl17to32(
+      uint64_t state, const unsigned char* first, size_t len) {
+    ABSL_ASSUME(len >= 17);
+    ABSL_ASSUME(len <= 32);
+    // Do two mixes of overlapping 16-byte ranges in parallel to minimize
+    // latency.
+    const uint64_t m0 =
+        Mix(Read8(first) ^ kStaticRandomData[1], Read8(first + 8) ^ state);
+
+    const unsigned char* tail_16b_ptr = first + (len - 16);
+    const uint64_t m1 = Mix(Read8(tail_16b_ptr) ^ kStaticRandomData[3],
+                            Read8(tail_16b_ptr + 8) ^ state);
+    return m0 ^ m1;
+  }
+
   // Slow dispatch path for calls to CombineContiguousImpl with a size argument
   // larger than PiecewiseChunkSize().  Has the same effect as calling
   // CombineContiguousImpl() repeatedly with the chunk stride size.
@@ -1118,12 +1252,12 @@
                                                size_t len);
 
   // Reads 9 to 16 bytes from p.
-  // The least significant 8 bytes are in .first, the rest (zero padded) bytes
-  // are in .second.
+  // The least significant 8 bytes are in .first, and the rest of the bytes are
+  // in .second along with duplicated bytes from .first if len<16.
   static std::pair<uint64_t, uint64_t> Read9To16(const unsigned char* p,
                                                  size_t len) {
-    uint64_t low_mem = absl::base_internal::UnalignedLoad64(p);
-    uint64_t high_mem = absl::base_internal::UnalignedLoad64(p + len - 8);
+    uint64_t low_mem = Read8(p);
+    uint64_t high_mem = Read8(p + len - 8);
 #ifdef ABSL_IS_LITTLE_ENDIAN
     uint64_t most_significant = high_mem;
     uint64_t least_significant = low_mem;
@@ -1134,53 +1268,74 @@
     return {least_significant, most_significant};
   }
 
-  // Reads 4 to 8 bytes from p. Zero pads to fill uint64_t.
+  // Reads 8 bytes from p.
+  static uint64_t Read8(const unsigned char* p) {
+    // Suppress erroneous array bounds errors on GCC.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
+#endif
+    return absl::base_internal::UnalignedLoad64(p);
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+  }
+
+  // Reads 4 to 8 bytes from p. Some input bytes may be duplicated in output.
   static uint64_t Read4To8(const unsigned char* p, size_t len) {
-    uint32_t low_mem = absl::base_internal::UnalignedLoad32(p);
-    uint32_t high_mem = absl::base_internal::UnalignedLoad32(p + len - 4);
-#ifdef ABSL_IS_LITTLE_ENDIAN
-    uint32_t most_significant = high_mem;
-    uint32_t least_significant = low_mem;
-#else
-    uint32_t most_significant = low_mem;
-    uint32_t least_significant = high_mem;
-#endif
-    return (static_cast<uint64_t>(most_significant) << (len - 4) * 8) |
-           least_significant;
+    // If `len < 8`, we duplicate bytes in the middle.
+    // E.g.:
+    // `ABCD` will be read as `ABCDABCD`.
+    // `ABCDE` will be read as `ABCDBCDE`.
+    // `ABCDEF` will be read as `ABCDCDEF`.
+    // `ABCDEFG` will be read as `ABCDDEFG`.
+    // We also do not care about endianness. On big-endian platforms, bytes will
+    // be shuffled (it's fine). We always shift low memory by 32, because that
+    // can be pipelined earlier. Reading high memory requires computing
+    // `p + len - 4`.
+    uint64_t most_significant =
+        static_cast<uint64_t>(absl::base_internal::UnalignedLoad32(p)) << 32;
+    uint64_t least_significant =
+        absl::base_internal::UnalignedLoad32(p + len - 4);
+    return most_significant | least_significant;
   }
 
-  // Reads 1 to 3 bytes from p. Zero pads to fill uint32_t.
+  // Reads 1 to 3 bytes from p. Some input bytes may be duplicated in output.
   static uint32_t Read1To3(const unsigned char* p, size_t len) {
-    // The trick used by this implementation is to avoid branches if possible.
-    unsigned char mem0 = p[0];
-    unsigned char mem1 = p[len / 2];
-    unsigned char mem2 = p[len - 1];
-#ifdef ABSL_IS_LITTLE_ENDIAN
-    unsigned char significant2 = mem2;
-    unsigned char significant1 = mem1;
-    unsigned char significant0 = mem0;
-#else
-    unsigned char significant2 = mem0;
-    unsigned char significant1 = len == 2 ? mem0 : mem1;
-    unsigned char significant0 = mem2;
-#endif
-    return static_cast<uint32_t>(significant0 |                     //
-                                 (significant1 << (len / 2 * 8)) |  //
-                                 (significant2 << ((len - 1) * 8)));
+    // The trick used by this implementation is to avoid branches.
+    // We always read three bytes by duplicating.
+    // E.g.,
+    // `A` is read as `AAA`.
+    // `AB` is read as `ABB`.
+    // `ABC` is read as `ABC`.
+    // We always shift `p[0]` so that it can be pipelined better.
+    // Other bytes require extra computation to find indices.
+    uint32_t mem0 = (static_cast<uint32_t>(p[0]) << 16) | p[len - 1];
+    uint32_t mem1 = static_cast<uint32_t>(p[len / 2]) << 8;
+    return mem0 | mem1;
   }
 
-  ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Mix(uint64_t state, uint64_t v) {
+  ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Mix(uint64_t lhs, uint64_t rhs) {
+    // For 32 bit platforms we are trying to use all 64 lower bits.
+    if constexpr (sizeof(size_t) < 8) {
+      uint64_t m = lhs * rhs;
+      return m ^ (m >> 32);
+    }
     // Though the 128-bit product on AArch64 needs two instructions, it is
     // still a good balance between speed and hash quality.
-    using MultType =
-        absl::conditional_t<sizeof(size_t) == 4, uint64_t, uint128>;
-    // We do the addition in 64-bit space to make sure the 128-bit
-    // multiplication is fast. If we were to do it as MultType the compiler has
-    // to assume that the high word is non-zero and needs to perform 2
-    // multiplications instead of one.
-    MultType m = state + v;
-    m *= kMul;
-    return static_cast<uint64_t>(m ^ (m >> (sizeof(m) * 8 / 2)));
+    uint128 m = lhs;
+    m *= rhs;
+    return Uint128High64(m) ^ Uint128Low64(m);
+  }
+
+  // Slightly lower latency than Mix, but with lower quality. The byte swap
+  // helps ensure that low bits still have high quality.
+  ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t WeakMix(uint64_t lhs,
+                                                       uint64_t rhs) {
+    const uint64_t n = lhs ^ rhs;
+    // WeakMix doesn't work well on 32-bit platforms so just use Mix.
+    if constexpr (sizeof(size_t) < 8) return Mix(n, kMul);
+    return absl::gbswap_64(n * kMul);
   }
 
   // An extern to avoid bloat on a direct call to LowLevelHash() with fixed
@@ -1234,21 +1389,15 @@
     std::integral_constant<int, 4> /* sizeof_size_t */) {
   // For large values we use CityHash, for small ones we just use a
   // multiplicative hash.
-  uint64_t v;
-  if (len > 8) {
-    if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
-      return CombineLargeContiguousImpl32(state, first, len);
-    }
-    v = hash_internal::CityHash32(reinterpret_cast<const char*>(first), len);
-  } else if (len >= 4) {
-    v = Read4To8(first, len);
-  } else if (len > 0) {
-    v = Read1To3(first, len);
-  } else {
-    // Empty ranges have no effect.
-    return state;
+  if (len <= 8) {
+    return CombineSmallContiguousImpl(state, first, len);
   }
-  return Mix(state, v);
+  if (ABSL_PREDICT_TRUE(len <= PiecewiseChunkSize())) {
+    return Mix(state ^ hash_internal::CityHash32(
+                           reinterpret_cast<const char*>(first), len),
+               kMul);
+  }
+  return CombineLargeContiguousImpl32(state, first, len);
 }
 
 // Overload of MixingHashState::CombineContiguousImpl()
@@ -1257,38 +1406,19 @@
     std::integral_constant<int, 8> /* sizeof_size_t */) {
   // For large values we use LowLevelHash or CityHash depending on the platform,
   // for small ones we just use a multiplicative hash.
-  uint64_t v;
-  if (len > 16) {
-    if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
-      return CombineLargeContiguousImpl64(state, first, len);
-    }
-    v = Hash64(first, len);
-  } else if (len > 8) {
-    // This hash function was constructed by the ML-driven algorithm discovery
-    // using reinforcement learning. We fed the agent lots of inputs from
-    // microbenchmarks, SMHasher, low hamming distance from generated inputs and
-    // picked up the one that was good on micro and macrobenchmarks.
-    auto p = Read9To16(first, len);
-    uint64_t lo = p.first;
-    uint64_t hi = p.second;
-    // Rotation by 53 was found to be most often useful when discovering these
-    // hashing algorithms with ML techniques.
-    lo = absl::rotr(lo, 53);
-    state += kMul;
-    lo += state;
-    state ^= hi;
-    uint128 m = state;
-    m *= lo;
-    return static_cast<uint64_t>(m ^ (m >> 64));
-  } else if (len >= 4) {
-    v = Read4To8(first, len);
-  } else if (len > 0) {
-    v = Read1To3(first, len);
-  } else {
-    // Empty ranges have no effect.
-    return state;
+  if (len <= 8) {
+    return CombineSmallContiguousImpl(state, first, len);
   }
-  return Mix(state, v);
+  if (len <= 16) {
+    return CombineContiguousImpl9to16(state, first, len);
+  }
+  if (len <= 32) {
+    return CombineContiguousImpl17to32(state, first, len);
+  }
+  if (ABSL_PREDICT_TRUE(len <= PiecewiseChunkSize())) {
+    return Mix(state ^ Hash64(first, len), kMul);
+  }
+  return CombineLargeContiguousImpl64(state, first, len);
 }
 
 struct AggregateBarrier {};
diff --git a/absl/hash/internal/low_level_hash.cc b/absl/hash/internal/low_level_hash.cc
index 6dc71cf..1a107ec 100644
--- a/absl/hash/internal/low_level_hash.cc
+++ b/absl/hash/internal/low_level_hash.cc
@@ -14,36 +14,49 @@
 
 #include "absl/hash/internal/low_level_hash.h"
 
+#include <cassert>
 #include <cstddef>
 #include <cstdint>
 
+#include "absl/base/config.h"
 #include "absl/base/internal/unaligned_access.h"
+#include "absl/base/optimization.h"
 #include "absl/base/prefetch.h"
 #include "absl/numeric/int128.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
-
-static uint64_t Mix(uint64_t v0, uint64_t v1) {
+namespace {
+uint64_t Mix(uint64_t v0, uint64_t v1) {
   absl::uint128 p = v0;
   p *= v1;
   return absl::Uint128Low64(p) ^ absl::Uint128High64(p);
 }
+uint64_t Mix32Bytes(const uint8_t* ptr, uint64_t current_state,
+                    const uint64_t salt[5]) {
+  uint64_t a = absl::base_internal::UnalignedLoad64(ptr);
+  uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);
+  uint64_t c = absl::base_internal::UnalignedLoad64(ptr + 16);
+  uint64_t d = absl::base_internal::UnalignedLoad64(ptr + 24);
 
-uint64_t LowLevelHashLenGt16(const void* data, size_t len, uint64_t seed,
+  uint64_t cs0 = Mix(a ^ salt[1], b ^ current_state);
+  uint64_t cs1 = Mix(c ^ salt[2], d ^ current_state);
+  return cs0 ^ cs1;
+}
+}  // namespace
+
+uint64_t LowLevelHashLenGt32(const void* data, size_t len, uint64_t seed,
                              const uint64_t salt[5]) {
-  // Prefetch the cacheline that data resides in.
-  PrefetchToLocalCache(data);
+  assert(len > 32);
   const uint8_t* ptr = static_cast<const uint8_t*>(data);
-  uint64_t starting_length = static_cast<uint64_t>(len);
-  const uint8_t* last_16_ptr = ptr + starting_length - 16;
-  uint64_t current_state = seed ^ salt[0];
+  uint64_t current_state = seed ^ salt[0] ^ len;
+  const uint8_t* last_32_ptr = ptr + len - 32;
 
   if (len > 64) {
     // 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 two separate hash states
-    // which we will then hash together.
+    // 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.
     uint64_t duplicated_state0 = current_state;
     uint64_t duplicated_state1 = current_state;
     uint64_t duplicated_state2 = current_state;
@@ -78,71 +91,13 @@
   // We now have a data `ptr` with at most 64 bytes and the current state
   // of the hashing state machine stored in current_state.
   if (len > 32) {
-    uint64_t a = absl::base_internal::UnalignedLoad64(ptr);
-    uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);
-    uint64_t c = absl::base_internal::UnalignedLoad64(ptr + 16);
-    uint64_t d = absl::base_internal::UnalignedLoad64(ptr + 24);
-
-    uint64_t cs0 = Mix(a ^ salt[1], b ^ current_state);
-    uint64_t cs1 = Mix(c ^ salt[2], d ^ current_state);
-    current_state = cs0 ^ cs1;
-
-    ptr += 32;
-    len -= 32;
+    current_state = Mix32Bytes(ptr, current_state, salt);
   }
 
   // We now have a data `ptr` with at most 32 bytes and the current state
-  // of the hashing state machine stored in current_state.
-  if (len > 16) {
-    uint64_t a = absl::base_internal::UnalignedLoad64(ptr);
-    uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);
-
-    current_state = Mix(a ^ salt[1], b ^ current_state);
-  }
-
-  // We now have a data `ptr` with at least 1 and at most 16 bytes. But we can
-  // safely read from `ptr + len - 16`.
-  uint64_t a = absl::base_internal::UnalignedLoad64(last_16_ptr);
-  uint64_t b = absl::base_internal::UnalignedLoad64(last_16_ptr + 8);
-
-  return Mix(a ^ salt[1] ^ starting_length, b ^ current_state);
-}
-
-uint64_t LowLevelHash(const void* data, size_t len, uint64_t seed,
-                      const uint64_t salt[5]) {
-  if (len > 16) return LowLevelHashLenGt16(data, len, seed, salt);
-
-  // Prefetch the cacheline that data resides in.
-  PrefetchToLocalCache(data);
-  const uint8_t* ptr = static_cast<const uint8_t*>(data);
-  uint64_t starting_length = static_cast<uint64_t>(len);
-  uint64_t current_state = seed ^ salt[0];
-  if (len == 0) return current_state;
-
-  uint64_t a = 0;
-  uint64_t b = 0;
-
-  // We now have a data `ptr` with at least 1 and at most 16 bytes.
-  if (len > 8) {
-    // When we have at least 9 and at most 16 bytes, set A to the first 64
-    // bits of the input and B to the last 64 bits of the input. Yes, they
-    // will overlap in the middle if we are working with less than the full 16
-    // bytes.
-    a = absl::base_internal::UnalignedLoad64(ptr);
-    b = absl::base_internal::UnalignedLoad64(ptr + len - 8);
-  } else if (len > 3) {
-    // If we have at least 4 and at most 8 bytes, set A to the first 32
-    // bits and B to the last 32 bits.
-    a = absl::base_internal::UnalignedLoad32(ptr);
-    b = absl::base_internal::UnalignedLoad32(ptr + len - 4);
-  } else {
-    // If we have at least 1 and at most 3 bytes, read 2 bytes into A and the
-    // other byte into B, with some adjustments.
-    a = static_cast<uint64_t>((ptr[0] << 8) | ptr[len - 1]);
-    b = static_cast<uint64_t>(ptr[len >> 1]);
-  }
-
-  return Mix(a ^ salt[1] ^ starting_length, b ^ current_state);
+  // of the hashing state machine stored in current_state. But we can
+  // safely read from `ptr + len - 32`.
+  return Mix32Bytes(last_32_ptr, current_state, salt);
 }
 
 }  // namespace hash_internal
diff --git a/absl/hash/internal/low_level_hash.h b/absl/hash/internal/low_level_hash.h
index d460e35..49e9ec4 100644
--- a/absl/hash/internal/low_level_hash.h
+++ b/absl/hash/internal/low_level_hash.h
@@ -35,16 +35,12 @@
 namespace hash_internal {
 
 // Hash function for a byte array. A 64-bit seed and a set of five 64-bit
-// integers are hashed into the result.
+// integers are hashed into the result. The length must be greater than 32.
 //
 // To allow all hashable types (including string_view and Span) to depend on
 // this algorithm, we keep the API low-level, with as few dependencies as
 // possible.
-uint64_t LowLevelHash(const void* data, size_t len, uint64_t seed,
-                      const uint64_t salt[5]);
-
-// Same as above except the length must be greater than 16.
-uint64_t LowLevelHashLenGt16(const void* data, size_t len, uint64_t seed,
+uint64_t LowLevelHashLenGt32(const void* data, size_t len, uint64_t seed,
                              const uint64_t salt[5]);
 
 }  // namespace hash_internal
diff --git a/absl/hash/internal/low_level_hash_test.cc b/absl/hash/internal/low_level_hash_test.cc
index ea781dd..d370dc7 100644
--- a/absl/hash/internal/low_level_hash_test.cc
+++ b/absl/hash/internal/low_level_hash_test.cc
@@ -15,6 +15,7 @@
 #include "absl/hash/internal/low_level_hash.h"
 
 #include <cinttypes>
+#include <cstdint>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
@@ -29,55 +30,11 @@
                                   0x1d8e4e27c47d124f};
 
 TEST(LowLevelHashTest, VerifyGolden) {
-  constexpr size_t kNumGoldenOutputs = 134;
+  constexpr size_t kNumGoldenOutputs = 94;
   static struct {
     absl::string_view base64_data;
     uint64_t seed;
   } cases[] = {
-      {"", uint64_t{0xec42b7ab404b8acb}},
-      {"ICAg", uint64_t{0}},
-      {"YWFhYQ==", uint64_t{0}},
-      {"AQID", uint64_t{0}},
-      {"AQIDBA==", uint64_t{0}},
-      {"dGhpcmRfcGFydHl8d3loYXNofDY0", uint64_t{0}},
-      {"Zw==", uint64_t{0xeeee074043a3ee0f}},
-      {"xmk=", uint64_t{0x857902089c393de}},
-      {"c1H/", uint64_t{0x993df040024ca3af}},
-      {"SuwpzQ==", uint64_t{0xc4e4c2acea740e96}},
-      {"uqvy++M=", uint64_t{0x6a214b3db872d0cf}},
-      {"RnzCVPgb", uint64_t{0x44343db6a89dba4d}},
-      {"6OeNdlouYw==", uint64_t{0x77b5d6d1ae1dd483}},
-      {"M5/JmmYyDbc=", uint64_t{0x89ab8ecb44d221f1}},
-      {"MVijWiVdBRdY", uint64_t{0x60244b17577ca81b}},
-      {"6V7Uq7LNxpu0VA==", uint64_t{0x59a08dcee0717067}},
-      {"EQ6CdEEhPdyHcOk=", uint64_t{0xf5f20db3ade57396}},
-      {"PqFB4fxnPgF+l+rc", uint64_t{0xbf8dee0751ad3efb}},
-      {"a5aPOFwq7LA7+zKvPA==", uint64_t{0x6b7a06b268d63e30}},
-      {"VOwY21wCGv5D+/qqOvs=", uint64_t{0xb8c37f0ae0f54c82}},
-      {"KdHmBTx8lHXYvmGJ+Vy7", uint64_t{0x9fcbed0c38e50eef}},
-      {"qJkPlbHr8bMF7/cA6aE65Q==", uint64_t{0x2af4bade1d8e3a1d}},
-      {"ygvL0EhHZL0fIx6oHHtkxRQ=", uint64_t{0x714e3aa912da2f2c}},
-      {"c1rFXkt5YztwZCQRngncqtSs", uint64_t{0xf5ee75e3cbb82c1c}},
-      {"8hsQrzszzeNQSEcVXLtvIhm6mw==", uint64_t{0x620e7007321b93b9}},
-      {"ffUL4RocfyP4KfikGxO1yk7omDI=", uint64_t{0xc08528cac2e551fc}},
-      {"OOB5TT00vF9Od/rLbAWshiErqhpV", uint64_t{0x6a1debf9cc3ad39}},
-      {"or5wtXM7BFzTNpSzr+Lw5J5PMhVJ/Q==", uint64_t{0x7e0a3c88111fc226}},
-      {"gk6pCHDUsoopVEiaCrzVDhioRKxb844=", uint64_t{0x1301fef15df39edb}},
-      {"TNctmwlC5QbEM6/No4R/La3UdkfeMhzs", uint64_t{0x64e181f3d5817ab}},
-      {"SsQw9iAjhWz7sgcE9OwLuSC6hsM+BfHs2Q==", uint64_t{0xafafc44961078ecb}},
-      {"ZzO3mVCj4xTT2TT3XqDyEKj2BZQBvrS8RHg=", uint64_t{0x4f7bb45549250094}},
-      {"+klp5iPQGtppan5MflEls0iEUzqU+zGZkDJX", uint64_t{0xa30061abaa2818c}},
-      {"RO6bvOnlJc8I9eniXlNgqtKy0IX6VNg16NRmgg==",
-       uint64_t{0xd902ee3e44a5705f}},
-      {"ZJjZqId1ZXBaij9igClE3nyliU5XWdNRrayGlYA=", uint64_t{0x316d36da516f583}},
-      {"7BfkhfGMDGbxfMB8uyL85GbaYQtjr2K8g7RpLzr/",
-       uint64_t{0x402d83f9f834f616}},
-      {"rycWk6wHH7htETQtje9PidS2YzXBx+Qkg2fY7ZYS7A==",
-       uint64_t{0x9c604164c016b72c}},
-      {"RTkC2OUK+J13CdGllsH0H5WqgspsSa6QzRZouqx6pvI=",
-       uint64_t{0x3f4507e01f9e73ba}},
-      {"tKjKmbLCNyrLCM9hycOAXm4DKNpM12oZ7dLTmUx5iwAi",
-       uint64_t{0xc3fe0d5be8d2c7c7}},
       {"VprUGNH+5NnNRaORxgH/ySrZFQFDL+4VAodhfBNinmn8cg==",
        uint64_t{0x531858a40bfa7ea1}},
       {"gc1xZaY+q0nPcUvOOnWnT3bqfmT/geth/f7Dm2e/DemMfk4=",
@@ -405,100 +362,42 @@
   };
 
 #if defined(ABSL_IS_BIG_ENDIAN)
-  constexpr uint64_t kGolden[kNumGoldenOutputs] = {
-      0x4c34aacf38f6eee4, 0x88b1366815e50b88, 0x1a36bd0c6150fb9c,
-      0xa783aba8a67366c7, 0x5e4a92123ae874f2, 0x0cc9ecf27067ee9a,
-      0xbe77aa94940527f9, 0x7ea5c12f2669fe31, 0xa33eed8737d946b9,
-      0x310aec5b1340bb36, 0x354e400861c5d8ff, 0x15be98166adcf42f,
-      0xc51910b62a90ae51, 0x539d47fc7fdf6a1f, 0x3ebba9daa46eef93,
-      0xd96bcd3a9113c17f, 0xc78eaf6256ded15a, 0x98902ed321c2f0d9,
-      0x75a4ac96414b954a, 0x2cb90e00a39e307b, 0x46539574626c3637,
-      0x186ec89a2be3ff45, 0x972a3bf7531519d2, 0xa14df0d25922364b,
-      0xa351e19d22752109, 0x08bd311d8fed4f82, 0xea2b52ddc6af54f9,
-      0x5f20549941338336, 0xd43b07422dc2782e, 0x377c68e2acda4835,
-      0x1b31a0a663b1d7b3, 0x7388ba5d68058a1a, 0xe382794ea816f032,
-      0xd4c3fe7889276ee0, 0x2833030545582ea9, 0x554d32a55e55df32,
-      0x8d6d33d7e17b424d, 0xe51a193d03ae1e34, 0xabb6a80835bd66b3,
-      0x0e4ba5293f9ce9b7, 0x1ebd8642cb762cdf, 0xcb54b555850888ee,
-      0x1e4195e4717c701f, 0x6235a13937f6532a, 0xd460960741e845c0,
-      0x2a72168a2d6af7b1, 0x6be38fbbfc5b17de, 0x4ee97cffa0d0fb39,
-      0xfdf1119ad5e71a55, 0x0dff7f66b3070727, 0x812d791d6ed62744,
-      0x60962919074b70b8, 0x956fa5c7d6872547, 0xee892daa58aae597,
-      0xeeda546e998ee369, 0x454481f5eb9b1fa8, 0x1054394634c98b1b,
-      0x55bb425415f591fb, 0x9601fa97416232c4, 0xd7a18506519daad7,
-      0x90935cb5de039acf, 0xe64054c5146ed359, 0xe5b323fb1e866c09,
-      0x10a472555f5ba1bc, 0xe3c0cd57d26e0972, 0x7ca3db7c121da3e8,
-      0x7004a89c800bb466, 0x865f69c1a1ff7f39, 0xbe0edd48f0cf2b99,
-      0x10e5e4ba3cc400f5, 0xafc2b91a220eef50, 0x6f04a259289b24f1,
-      0x2179a8070e880ef0, 0xd6a9a3d023a740c2, 0x96e6d7954755d9b8,
-      0xc8e4bddecce5af9f, 0x93941f0fbc724c92, 0xbef5fb15bf76a479,
-      0x534dca8f5da86529, 0x70789790feec116b, 0x2a296e167eea1fe9,
-      0x54cb1efd2a3ec7ea, 0x357b43897dfeb9f7, 0xd1eda89bc7ff89d3,
-      0x434f2e10cbb83c98, 0xeec4cdac46ca69ce, 0xd46aafd52a303206,
-      0x4bf05968ff50a5c9, 0x71c533747a6292df, 0xa40bd0d16a36118c,
-      0x597b4ee310c395ab, 0xc5b3e3e386172583, 0x12ca0b32284e6c70,
-      0xb48995fadcf35630, 0x0646368454cd217d, 0xa21c168e40d765b5,
-      0x4260d3811337da30, 0xb72728a01cff78e4, 0x8586920947f4756f,
-      0xc21e5f853cae7dc1, 0xf08c9533be9de285, 0x72df06653b4256d6,
-      0xf7b7f937f8db1779, 0x976db27dd0418127, 0x9ce863b7bc3f9e00,
-      0xebb679854fcf3a0a, 0x2ccebabbcf1afa99, 0x44201d6be451dac5,
-      0xb4af71c0e9a537d1, 0xad8fe9bb33ed2681, 0xcb30128bb68df43b,
-      0x154d8328903e8d07, 0x5844276dabeabdff, 0xd99017d7d36d930b,
-      0xabb0b4774fb261ca, 0x0a43f075d62e67e0, 0x8df7b371355ada6b,
-      0xf4c7a40d06513dcf, 0x257a3615955a0372, 0x987ac410bba74c06,
-      0xa011a46f25a632a2, 0xa14384b963ddd995, 0xf51b6b8cf9d50ba7,
-      0x3acdb91ee3abf18d, 0x34e799be08920e8c, 0x8766748a31304b36,
-      0x0aa239d5d0092f2e, 0xadf473ed26628594, 0xc4094b798eb4b79b,
-      0xe04ee5f33cd130f4, 0x85045d098c341d46, 0xf936cdf115a890ec,
-      0x51d137b6d8d2eb4f, 0xd10738bb2fccc1ef,
-  };
+  constexpr uint64_t kGolden[kNumGoldenOutputs] = {};
+  GTEST_SKIP() << "We only maintain golden data for little endian systems.";
 #else
   constexpr uint64_t kGolden[kNumGoldenOutputs] = {
-      0x4c34aacf38f6eee4, 0x88b1366815e50b88, 0x1a36bd0c6150fb9c,
-      0xa783aba8a67366c7, 0xbc89ebdc622314e4, 0x632bc3cfcc7544d8,
-      0xbe77aa94940527f9, 0x7ea5c12f2669fe31, 0xa33eed8737d946b9,
-      0x74d832ea11fd18ab, 0x49c0487486246cdc, 0x3fdd986c87ddb0a0,
-      0xac3fa52a64d7c09a, 0xbff0e330196e7ed2, 0x8c8138d3ad7d3cce,
-      0x968c7d4b48e93778, 0xa04c78d3a421f529, 0x8854bc9c3c3c0241,
-      0xcccfcdf5a41113fe, 0xe6fc63dc543d984d, 0x00a39ff89e903c05,
-      0xaf7e9da25f9a26f9, 0x6e269a13d01a43df, 0x846d2300ce2ecdf8,
-      0xe7ea8c8f08478260, 0x9a2db0d62f6232f3, 0x6f66c761d168c59f,
-      0x55f9feacaae82043, 0x518084043700f614, 0xb0c8cfc11bead99f,
-      0xe4a68fdab6359d80, 0x97b17caa8f92236e, 0x96edf5e8363643dc,
-      0x9b3fbcd8d5b254cd, 0x22a263621d9b3a8b, 0xde90bf6f81800a6d,
-      0x1b51cae38c2e9513, 0x689215b3c414ef21, 0x064dc85afae8f557,
-      0xa2f3a8b51f408378, 0x6907c197ec1f6a3b, 0xfe83a42ef5c1cf13,
-      0x9b8b1d8f7a20cc13, 0x1f1681d52ca895d0, 0xd7b1670bf28e0f96,
-      0xb32f20f82d8b038a, 0x6a61d030fb2f5253, 0x8eb2bb0bc29ebb39,
-      0x144f36f7a9eef95c, 0xe77aa47d29808d8c, 0xf14d34c1fc568bad,
-      0x9796dcd4383f3c73, 0xa2f685fc1be7225b, 0xf3791295b16068b1,
-      0xb6b8f63424618948, 0x8ac4fd587045db19, 0x7e2aec2c34feb72e,
-      0x72e135a6910ccbb1, 0x661ff16f3c904e6f, 0xdf92cf9d67ca092d,
-      0x98a9953d79722eef, 0xe0649ed2181d1707, 0xcd8b8478636a297b,
-      0x9516258709c8471b, 0xc703b675b51f4394, 0xdb740eae020139f3,
-      0x57d1499ac4212ff2, 0x355cc03713d43825, 0x0e71ac9b8b1e101e,
-      0x8029fa72258ff559, 0xa2159726b4c16a50, 0x04e61582fba43007,
-      0xdab25af835be8cce, 0x13510b1b184705ee, 0xabdbc9e53666fdeb,
-      0x94a788fcb8173cef, 0x750d5e031286e722, 0x02559e72f4f5b497,
-      0x7d6e0e5996a646fa, 0x66e871b73b014132, 0x2ec170083f8b784f,
-      0x34ac9540cfce3fd9, 0x75c5622c6aad1295, 0xf799a6bb2651acc1,
-      0x8f6bcd3145bdc452, 0xddd9d326eb584a04, 0x5411af1e3532f8dc,
-      0xeb34722f2ad0f509, 0x835bc952a82298cc, 0xeb3839ff60ea92ad,
-      0x70bddf1bcdc8a4bc, 0x4bfb3ee86fcde525, 0xc7b3b93b81dfa386,
-      0xe66db544d57997e8, 0xf68a1b83fd363187, 0xe9b99bec615b171b,
-      0x093fba04d04ad28a, 0xba6117ed4231a303, 0x594bef25f9d4e206,
-      0x0a8cba60578b8f67, 0x88f6c7ca10b06019, 0x32a74082aef17b08,
-      0xe758222f971e22df, 0x4af14ff4a593e51e, 0xdba651e16cb09044,
-      0x3f3ac837d181eaac, 0xa5589a3f89610c01, 0xd409a7c3a18d5643,
-      0x8a89444f82962f26, 0x22eb62a13b9771b9, 0xd3a617615256ddd8,
-      0x7089b990c4bba297, 0x7d752893783eac4f, 0x1f2fcbb79372c915,
-      0x67a4446b17eb9839, 0x70d11df5cae46788, 0x52621e1780b47d0f,
-      0xcf63b93a6e590ee6, 0xb6bc96b58ee064b8, 0x2587f8d635ca9c75,
-      0xc6bddd62ec5e5d01, 0x957398ad3009cdb7, 0x05b6890b20bcd0d3,
-      0xbe6e965ff837222e, 0x47383a87d2b04b1a, 0x7d42207e6d8d7950,
-      0x7e981ed12a7f4aa3, 0xdebb05b30769441a, 0xaac5d86f4ff76c49,
-      0x384f195ca3248331, 0xec4c4b855e909ca1, 0x6a7eeb5a657d73d5,
-      0x9efbebe2fa9c2791, 0x19e7fa0546900c4d,
+      0x59b1542b0ff6b7b8, 0x3fb979d297096db9, 0xb391802c536343a9,
+      0x94e0f7e4331081c4, 0x234d95e49e3ce30e, 0xca6351a3e568ed17,
+      0xa62fcf7fa334293d, 0xb03111035f546067, 0x97b8c861e013d558,
+      0xb6683803d9387949, 0xce5d907e0b3cb6a1, 0xab7466fae53ed201,
+      0x8f13ca3f1cac3edd, 0xa2684a99cd909a2a, 0x03194f86b9440843,
+      0xab3a745d96f75a66, 0xef2448606760ec3d, 0xd999e03247d5d5c5,
+      0x4a25ab345d53f926, 0xa511b829ce9fc919, 0x4b76517f8e806cbf,
+      0x006efd7ee09ff8d4, 0x790a4978bd0170a1, 0xc14f6e4b2dff057e,
+      0xe0d2f4ae7c836d09, 0x4e2038a491ed939d, 0x23fd6f408e9598e0,
+      0xa91cf8f1d92bcb08, 0x555cdec06df49d58, 0xe7d3e14bd6a8f3bd,
+      0x4fdd25c1e75c009a, 0x3dffb8acf1ffbd17, 0x56946f33ed73a705,
+      0x154c633d7690f3b0, 0x3e96f8e9a58a04e0, 0xb0279b244d3ccf9c,
+      0x8571e87c882b2142, 0x9d9ada45132e7b41, 0xd5667655533f1dec,
+      0x70607ace4ec36463, 0x691418d2eb63116c, 0xa70179d8e7142980,
+      0xf8388d756bea25a7, 0xe5127c736d9826de, 0x7f1c95f9b6b656b6,
+      0x66ab835b7bf4c7b3, 0xc03423b9a6db9728, 0xe88415a2b416b76d,
+      0x8afd8c14d0b56c36, 0xe9a252b3ba217dad, 0x710150f5cd87a9ff,
+      0xd66b147837fad9ae, 0x1af5f8ffbaa717a7, 0xe01f88d7a9a8ac17,
+      0xd67870a7251fde72, 0xf32b837f845a676b, 0x0827717b1ffe59f7,
+      0x80307212ca7645fb, 0xf0d22af71ea57c80, 0x459373765f2c114b,
+      0x54d26109fab9cbaf, 0xc603da4e257b93db, 0x57fa334b5689d7d5,
+      0x41cd1b2a8a91f620, 0xe1d6e7cd0fb015af, 0x8608e9035eb9d795,
+      0x45c7b9fae739fee1, 0x9f5ae4f7a6b597ee, 0xfb771b6e0017757d,
+      0x8dac6d29cfd8d027, 0x3c9ba4fb62ce6508, 0xa971fad8243844a7,
+      0xd2126f49b2ea3b64, 0x5dd78fe7ac436861, 0xfe4004a6bb3494a8,
+      0xe7c01cc63d770d7c, 0xa117075b8c801d37, 0xdf1dfe75f0e73069,
+      0x7285b39700cefb98, 0x5e97ea1aa9a670eb, 0xe21872db2b9137a3,
+      0x12630b02c6ca405e, 0xfe1f2d802151f97a, 0xb53b0ed3dea4fb02,
+      0xc6d5ed56d1dbf9fd, 0xe5b92b558a5c70cb, 0xccd6eedf97277d08,
+      0x08582fff2e1494ed, 0xa41f2b3d17f1c4c7, 0x29ec07e5ef950f3d,
+      0x96aba32565a97084, 0xf26870eca10cebcd, 0xbe1432feb4d33361,
+      0x21993a779845e6eb,
   };
 #endif
 
@@ -507,8 +406,9 @@
   for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
     std::string str;
     ASSERT_TRUE(absl::Base64Unescape(cases[i].base64_data, &str));
-    uint64_t h = absl::hash_internal::LowLevelHash(str.data(), str.size(),
-                                                   cases[i].seed, kSalt);
+    ASSERT_GT(str.size(), 32);
+    uint64_t h = absl::hash_internal::LowLevelHashLenGt32(
+        str.data(), str.size(), cases[i].seed, kSalt);
     printf("0x%016" PRIx64 ", ", h);
     if (i % 3 == 2) {
       printf("\n");
@@ -522,8 +422,9 @@
                  << "i = " << i << "; input = " << cases[i].base64_data);
     std::string str;
     ASSERT_TRUE(absl::Base64Unescape(cases[i].base64_data, &str));
-    EXPECT_EQ(absl::hash_internal::LowLevelHash(str.data(), str.size(),
-                                                cases[i].seed, kSalt),
+    ASSERT_GT(str.size(), 32);
+    EXPECT_EQ(absl::hash_internal::LowLevelHashLenGt32(str.data(), str.size(),
+                                                       cases[i].seed, kSalt),
               kGolden[i]);
   }
 #endif
diff --git a/absl/hash/internal/spy_hash_state.h b/absl/hash/internal/spy_hash_state.h
index 357c301..e403113 100644
--- a/absl/hash/internal/spy_hash_state.h
+++ b/absl/hash/internal/spy_hash_state.h
@@ -16,11 +16,14 @@
 #define ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_
 
 #include <algorithm>
+#include <cstddef>
+#include <cstdint>
 #include <ostream>
 #include <string>
 #include <vector>
 
 #include "absl/hash/hash.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
 #include "absl/strings/match.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_join.h"
@@ -166,6 +169,11 @@
     return hash_state;
   }
 
+  static SpyHashStateImpl combine_weakly_mixed_integer(
+      SpyHashStateImpl hash_state, WeaklyMixedInteger value) {
+    return combine(std::move(hash_state), value.value);
+  }
+
   using SpyHashStateImpl::HashStateBase::combine_contiguous;
 
   template <typename CombinerT>
@@ -196,6 +204,7 @@
  private:
   template <typename U>
   friend class SpyHashStateImpl;
+  friend struct CombineRaw;
 
   struct UnorderedCombinerCallback {
     std::vector<std::string> element_hash_representations;
@@ -213,6 +222,12 @@
     }
   };
 
+  // Combines raw data from e.g. integrals/floats/pointers/etc.
+  static SpyHashStateImpl combine_raw(SpyHashStateImpl state, uint64_t value) {
+    const unsigned char* data = reinterpret_cast<const unsigned char*>(&value);
+    return SpyHashStateImpl::combine_contiguous(std::move(state), data, 8);
+  }
+
   // This is true if SpyHashStateImpl<T> has been passed to a call of
   // AbslHashValue with the wrong type. This detects that the user called
   // AbslHashValue directly (because the hash state type does not match).
diff --git a/absl/hash/internal/weakly_mixed_integer.h b/absl/hash/internal/weakly_mixed_integer.h
new file mode 100644
index 0000000..5575436
--- /dev/null
+++ b/absl/hash/internal/weakly_mixed_integer.h
@@ -0,0 +1,38 @@
+// Copyright 2025 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_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_
+#define ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_
+
+#include <cstddef>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace hash_internal {
+
+// Contains an integer that will be mixed into a hash state more weakly than
+// regular integers. It is useful for cases in which an integer is a part of a
+// larger object and needs to be mixed as a supplement. E.g., absl::string_view
+// and absl::Span are mixing their size wrapped with WeaklyMixedInteger.
+struct WeaklyMixedInteger {
+  size_t value;
+};
+
+}  // namespace hash_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_
diff --git a/absl/log/BUILD.bazel b/absl/log/BUILD.bazel
index b13cf4d..62ece45 100644
--- a/absl/log/BUILD.bazel
+++ b/absl/log/BUILD.bazel
@@ -152,7 +152,6 @@
 
 cc_library(
     name = "log_entry",
-    srcs = ["log_entry.cc"],
     hdrs = ["log_entry.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -187,6 +186,7 @@
     deps = [
         ":log_sink",
         "//absl/base:config",
+        "//absl/base:nullability",
         "//absl/log/internal:log_sink_set",
     ],
 )
@@ -222,7 +222,7 @@
         "//absl/base:log_severity",
         "//absl/base:raw_logging_internal",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -233,6 +233,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/log/internal:structured",
         "//absl/strings",
     ],
@@ -279,8 +280,8 @@
         "//absl/base:log_severity",
         "//absl/flags:flag",
         "//absl/types:optional",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -301,22 +302,23 @@
     deps = [
         ":absl_check",
         ":check_test_impl",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
 cc_test(
     name = "absl_log_basic_test",
     size = "small",
+    timeout = "moderate",
     srcs = ["absl_log_basic_test.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":absl_log",
         ":log_basic_test_impl",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -335,8 +337,8 @@
     deps = [
         ":check",
         ":check_test_impl",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -359,7 +361,7 @@
         "//absl/status",
         "//absl/strings",
         "//absl/strings:string_view",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -373,8 +375,8 @@
         ":die_if_null",
         "//absl/base:core_headers",
         "//absl/log/internal:test_helpers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -397,8 +399,8 @@
         "//absl/log/internal:test_helpers",
         "//absl/log/internal:test_matchers",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -416,22 +418,23 @@
         "//absl/base:log_severity",
         "//absl/log/internal:globals",
         "//absl/log/internal:test_helpers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
 cc_test(
     name = "log_basic_test",
     size = "small",
+    timeout = "moderate",
     srcs = ["log_basic_test.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":log",
         ":log_basic_test_impl",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -452,7 +455,7 @@
         "//absl/log/internal:test_actions",
         "//absl/log/internal:test_helpers",
         "//absl/log/internal:test_matchers",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -473,8 +476,8 @@
         "//absl/strings",
         "//absl/time",
         "//absl/types:span",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -488,12 +491,13 @@
         ":check",
         ":log",
         ":scoped_mock_log",
+        "//absl/base:config",
         "//absl/log/internal:test_matchers",
         "//absl/strings",
         "//absl/strings:str_format",
         "//absl/types:optional",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -508,8 +512,8 @@
         ":scoped_mock_log",
         "//absl/base:core_headers",
         "//absl/base:log_severity",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -534,8 +538,8 @@
         "//absl/log/internal:test_helpers",
         "//absl/log/internal:test_matchers",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -556,8 +560,8 @@
         "//absl/log/internal:test_helpers",
         "//absl/log/internal:test_matchers",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -576,8 +580,8 @@
         "//absl/log/internal:test_matchers",
         "//absl/strings",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -604,8 +608,8 @@
         "//absl/memory",
         "//absl/strings",
         "//absl/synchronization",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -628,8 +632,8 @@
         "//absl/status",
         "//absl/strings",
         "//absl/strings:str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -646,8 +650,8 @@
         "//absl/base:core_headers",
         "//absl/log/internal:test_helpers",
         "//absl/log/internal:test_matchers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -671,6 +675,6 @@
         "//absl/base:log_severity",
         "//absl/flags:flag",
         "//absl/log/internal:flags",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/log/CMakeLists.txt b/absl/log/CMakeLists.txt
index 4384465..130897f 100644
--- a/absl/log/CMakeLists.txt
+++ b/absl/log/CMakeLists.txt
@@ -44,11 +44,14 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::base
     absl::config
     absl::core_headers
+    absl::leak_check
     absl::log_internal_nullguard
     absl::log_internal_nullstream
     absl::log_internal_strip
+    absl::nullability
     absl::strings
 )
 
@@ -195,25 +198,28 @@
     absl::config
     absl::core_headers
     absl::errno_saver
-    absl::inlined_vector
     absl::examine_stack
+    absl::inlined_vector
     absl::log_internal_append_truncated
     absl::log_internal_format
     absl::log_internal_globals
     absl::log_internal_proto
     absl::log_internal_log_sink_set
     absl::log_internal_nullguard
+    absl::log_internal_structured_proto
     absl::log_globals
     absl::log_entry
     absl::log_severity
     absl::log_sink
     absl::log_sink_registry
     absl::memory
+    absl::nullability
     absl::raw_logging_internal
-    absl::strings
-    absl::strerror
-    absl::time
     absl::span
+    absl::strerror
+    absl::strings
+    absl::strings_internal
+    absl::time
 )
 
 absl_cc_library(
@@ -374,6 +380,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::config
+    absl::core_headers
 )
 
 absl_cc_library(
@@ -389,6 +396,7 @@
   DEPS
     absl::config
     absl::strings
+    absl::strings_internal
     absl::span
 )
 
@@ -552,8 +560,6 @@
 absl_cc_library(
   NAME
     log_entry
-  SRCS
-    "log_entry.cc"
   HDRS
     "log_entry.h"
   COPTS
@@ -602,6 +608,7 @@
     absl::config
     absl::log_sink
     absl::log_internal_log_sink_set
+    absl::nullability
   PUBLIC
 )
 
@@ -661,13 +668,54 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::any_invocable
     absl::config
+    absl::core_headers
     absl::log_internal_message
+    absl::log_internal_structured_proto
     absl::strings
 )
 
 absl_cc_library(
   NAME
+    log_internal_structured_proto
+  SRCS
+    "internal/structured_proto.cc"
+  HDRS
+    "internal/structured_proto.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::log_internal_proto
+    absl::config
+    absl::span
+    absl::strings
+    absl::variant
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    log_internal_structured_proto_test
+  SRCS
+    "internal/structured_proto_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::log_internal_structured_proto
+    absl::span
+    absl::string_view
+    absl::utility
+    GTest::gmock_main
+)
+
+absl_cc_library(
+  NAME
     log_structured
   HDRS
     "structured.h"
@@ -677,6 +725,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::config
+    absl::core_headers
     absl::log_internal_structured
     absl::strings
   PUBLIC
@@ -700,6 +749,7 @@
     absl::log_internal_fnmatch
     absl::memory
     absl::no_destructor
+    absl::nullability
     absl::strings
     absl::synchronization
     absl::optional
@@ -958,6 +1008,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::check
+    absl::config
     absl::log
     absl::log_internal_test_matchers
     absl::optional
diff --git a/absl/log/absl_vlog_is_on.h b/absl/log/absl_vlog_is_on.h
index 6bf6c41..e4ec86d 100644
--- a/absl/log/absl_vlog_is_on.h
+++ b/absl/log/absl_vlog_is_on.h
@@ -40,6 +40,8 @@
 // last . and everything after it) is stripped from each filename prior to
 // matching, as is the special suffix "-inl".
 //
+// Example: --vmodule=module_a=1,module_b=2
+//
 // Files are matched against globs in `--vmodule` in order, and the first match
 // determines the verbosity level.
 //
diff --git a/absl/log/check.h b/absl/log/check.h
index 50f633d..9e2219b 100644
--- a/absl/log/check.h
+++ b/absl/log/check.h
@@ -42,7 +42,8 @@
 
 // CHECK()
 //
-// `CHECK` terminates the program with a fatal error if `condition` is not true.
+// `CHECK` enforces that the `condition` is true. If the condition is false,
+// the program is terminated with a fatal error.
 //
 // The message may include additional information such as stack traces, when
 // available.
diff --git a/absl/log/check_test_impl.inc b/absl/log/check_test_impl.inc
index 6431810..7a0000e 100644
--- a/absl/log/check_test_impl.inc
+++ b/absl/log/check_test_impl.inc
@@ -39,6 +39,7 @@
 namespace absl_log_internal {
 
 using ::testing::AllOf;
+using ::testing::AnyOf;
 using ::testing::HasSubstr;
 using ::testing::Not;
 
@@ -64,7 +65,6 @@
   ABSL_TEST_CHECK(i < 0 || i > 3);
 }
 
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
 ABSL_CONST_INIT const auto global_var_check = [](int i) {
   ABSL_TEST_CHECK(i > 0);  // NOLINT
   return i + 1;
@@ -74,7 +74,6 @@
   ABSL_TEST_CHECK_GE(i, 0);  // NOLINT
   return i + 1;
 }(global_var_check);
-#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG
 
 TEST(CHECKTest, TestPlacementsInCompoundStatements) {
   // check placement inside if/else clauses
@@ -89,13 +88,11 @@
   case 0:
     ABSL_TEST_CHECK(true);  // NOLINT
 
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
   constexpr auto var = [](int i) {
     ABSL_TEST_CHECK(i > 0);  // NOLINT
     return i + 1;
   }(global_var);
   (void)var;
-#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG
 }
 
 TEST(CHECKTest, TestBoolConvertible) {
@@ -354,7 +351,6 @@
   case 0:
     ABSL_TEST_CHECK_STRCASEEQ("A", "a");
 
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
   constexpr auto var = [](int i) {
     ABSL_TEST_CHECK_GT(i, 0);
     return i + 1;
@@ -374,7 +370,6 @@
   int var4 = (({ ABSL_TEST_CHECK_STREQ("a", "a"); }), global_var < 10) ? 1 : 0;
   (void)var4;
 #endif  // __GNUC__
-#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG
 }
 
 TEST(CHECKTest, TestDCHECK) {
@@ -441,7 +436,6 @@
   case 0:
     ABSL_TEST_QCHECK(true);
 
-#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
   constexpr auto var = [](int i) {
     ABSL_TEST_QCHECK(i > 0);  // NOLINT
     return i + 1;
@@ -452,7 +446,6 @@
   int var2 = (({ ABSL_TEST_CHECK_LE(1, 2); }), global_var < 10) ? 1 : 0;
   (void)var2;
 #endif  // __GNUC__
-#endif  // ABSL_INTERNAL_CPLUSPLUS_LANG
 }
 
 class ComparableType {
@@ -642,14 +635,12 @@
 TEST(CHECKDeathTest, TestPointerPrintedAsNumberDespiteAbslStringify) {
   const auto* p = reinterpret_cast<const PointerIsStringifiable*>(0x1234);
 
-#ifdef _MSC_VER
   EXPECT_DEATH(
       ABSL_TEST_CHECK_EQ(p, nullptr),
-      HasSubstr("Check failed: p == nullptr (0000000000001234 vs. (null))"));
-#else   // _MSC_VER
-  EXPECT_DEATH(ABSL_TEST_CHECK_EQ(p, nullptr),
-               HasSubstr("Check failed: p == nullptr (0x1234 vs. (null))"));
-#endif  // _MSC_VER
+      AnyOf(
+        HasSubstr("Check failed: p == nullptr (0000000000001234 vs. (null))"),
+        HasSubstr("Check failed: p == nullptr (0x1234 vs. (null))")
+      ));
 }
 
 // An uncopyable object with operator<<.
diff --git a/absl/log/die_if_null.h b/absl/log/die_if_null.h
index f773aa8..8597976 100644
--- a/absl/log/die_if_null.h
+++ b/absl/log/die_if_null.h
@@ -60,8 +60,8 @@
 
 // Helper for `ABSL_DIE_IF_NULL`.
 template <typename T>
-ABSL_MUST_USE_RESULT T DieIfNull(const char* file, int line,
-                                 const char* exprtext, T&& t) {
+[[nodiscard]] T DieIfNull(const char* file, int line, const char* exprtext,
+                          T&& t) {
   if (ABSL_PREDICT_FALSE(t == nullptr)) {
     // Call a non-inline helper function for a small code size improvement.
     DieBecauseNull(file, line, exprtext);
diff --git a/absl/log/globals.h b/absl/log/globals.h
index 4feec40..9718967 100644
--- a/absl/log/globals.h
+++ b/absl/log/globals.h
@@ -43,7 +43,7 @@
 //
 // Returns the value of the Minimum Log Level parameter.
 // This function is async-signal-safe.
-ABSL_MUST_USE_RESULT absl::LogSeverityAtLeast MinLogLevel();
+[[nodiscard]] absl::LogSeverityAtLeast MinLogLevel();
 
 // SetMinLogLevel()
 //
@@ -82,7 +82,7 @@
 //
 // Returns the value of the Stderr Threshold parameter.
 // This function is async-signal-safe.
-ABSL_MUST_USE_RESULT absl::LogSeverityAtLeast StderrThreshold();
+[[nodiscard]] absl::LogSeverityAtLeast StderrThreshold();
 
 // SetStderrThreshold()
 //
@@ -118,8 +118,7 @@
 //
 // Returns true if we should log a backtrace at the specified location.
 namespace log_internal {
-ABSL_MUST_USE_RESULT bool ShouldLogBacktraceAt(absl::string_view file,
-                                               int line);
+[[nodiscard]] bool ShouldLogBacktraceAt(absl::string_view file, int line);
 }  // namespace log_internal
 
 // SetLogBacktraceLocation()
@@ -145,7 +144,7 @@
 //
 // Returns the value of the Prepend Log Prefix option.
 // This function is async-signal-safe.
-ABSL_MUST_USE_RESULT bool ShouldPrependLogPrefix();
+[[nodiscard]] bool ShouldPrependLogPrefix();
 
 // EnableLogPrefix()
 //
diff --git a/absl/log/globals_test.cc b/absl/log/globals_test.cc
index 0dc54d5..78430d4 100644
--- a/absl/log/globals_test.cc
+++ b/absl/log/globals_test.cc
@@ -100,6 +100,15 @@
   EXPECT_EQ(absl::SetVLogLevel("setvloglevel", 42), 0);
   EXPECT_EQ(absl::SetVLogLevel("setvloglevel", 1337), 42);
   EXPECT_EQ(absl::SetVLogLevel("othersetvloglevel", 50), 0);
+
+  EXPECT_EQ(absl::SetVLogLevel("*pattern*", 1), 0);
+  EXPECT_EQ(absl::SetVLogLevel("*less_generic_pattern*", 2), 1);
+  // "pattern_match" matches the pattern "*pattern*". Therefore, the previous
+  // level must be 1.
+  EXPECT_EQ(absl::SetVLogLevel("pattern_match", 3), 1);
+  // "less_generic_pattern_match" matches the pattern "*pattern*". Therefore,
+  // the previous level must be 2.
+  EXPECT_EQ(absl::SetVLogLevel("less_generic_pattern_match", 4), 2);
 }
 
 TEST(TestGlobals, AndroidLogTag) {
diff --git a/absl/log/internal/BUILD.bazel b/absl/log/internal/BUILD.bazel
index 2dbf337..953b690 100644
--- a/absl/log/internal/BUILD.bazel
+++ b/absl/log/internal/BUILD.bazel
@@ -23,7 +23,7 @@
 
 package(
     default_visibility = [
-        "//absl/log:__pkg__",
+        ":internal_users",
     ],
     features = [
         "header_modules",
@@ -34,6 +34,20 @@
 
 licenses(["notice"])
 
+package_group(
+    name = "internal_users",
+    packages = [
+        "//absl/log",
+    ],
+)
+
+package_group(
+    name = "structured_proto_users",
+    packages = [
+        "//absl/log/...",
+    ],
+)
+
 cc_library(
     name = "check_impl",
     hdrs = ["check_impl.h"],
@@ -54,15 +68,16 @@
     hdrs = ["check_op.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl/log:__pkg__",
-    ],
+    visibility = ["//absl/log:__pkg__"],
     deps = [
         ":nullguard",
         ":nullstream",
         ":strip",
+        "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:nullability",
+        "//absl/debugging:leak_check",
         "//absl/strings",
     ],
 )
@@ -173,11 +188,13 @@
         ":log_sink_set",
         ":nullguard",
         ":proto",
+        ":structured_proto",
         "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:errno_saver",
         "//absl/base:log_severity",
+        "//absl/base:nullability",
         "//absl/base:raw_logging_internal",
         "//absl/base:strerror",
         "//absl/container:inlined_vector",
@@ -188,6 +205,7 @@
         "//absl/log:log_sink_registry",
         "//absl/memory",
         "//absl/strings",
+        "//absl/strings:internal",
         "//absl/time",
         "//absl/types:span",
     ],
@@ -201,6 +219,7 @@
     deps = [
         "//absl/base:config",
         "//absl/strings",
+        "//absl/strings:internal",
         "//absl/types:span",
     ],
 )
@@ -276,10 +295,49 @@
     hdrs = ["structured.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        ":internal_users",
+        ":structured_proto_users",
+    ],
     deps = [
         ":log_message",
+        ":structured_proto",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/functional:any_invocable",
+        "//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "structured_proto",
+    srcs = ["structured_proto.cc"],
+    hdrs = ["structured_proto.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        ":structured_proto_users",
+    ],
+    deps = [
+        ":proto",
         "//absl/base:config",
         "//absl/strings",
+        "//absl/types:span",
+        "//absl/types:variant",
+    ],
+)
+
+cc_test(
+    name = "structured_proto_test",
+    srcs = ["structured_proto_test.cc"],
+    deps = [
+        ":structured_proto",
+        "//absl/base:config",
+        "//absl/strings:string_view",
+        "//absl/types:span",
+        "//absl/utility",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -298,7 +356,7 @@
         "//absl/strings",
         "//absl/time",
     ] + select({
-        "//absl:msvc_compiler": [],
+        "@rules_cc//cc/compiler:msvc-cl": [],
         "//conditions:default": [
         ],
     }),
@@ -311,13 +369,17 @@
     hdrs = ["test_helpers.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        ":internal_users",
+        ":structured_proto_users",
+    ],
     deps = [
         ":globals",
         "//absl/base:config",
         "//absl/base:log_severity",
         "//absl/log:globals",
         "//absl/log:initialize",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -328,6 +390,10 @@
     hdrs = ["test_matchers.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        ":internal_users",
+        ":structured_proto_users",
+    ],
     deps = [
         ":test_helpers",
         "//absl/base:config",
@@ -336,9 +402,9 @@
         "//absl/log:log_entry",
         "//absl/strings",
         "//absl/time",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ] + select({
-        "//absl:msvc_compiler": [],
+        "@rules_cc//cc/compiler:msvc-cl": [],
         "//conditions:default": [
         ],
     }),
@@ -349,7 +415,10 @@
     hdrs = ["voidify.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = ["//absl/base:config"],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+    ],
 )
 
 cc_library(
@@ -389,11 +458,12 @@
         "//absl/log:__subpackages__",
     ],
     deps = [
+        ":fnmatch",
         "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:no_destructor",
-        "//absl/log/internal:fnmatch",
+        "//absl/base:nullability",
         "//absl/memory",
         "//absl/strings",
         "//absl/synchronization",
@@ -419,7 +489,7 @@
         "//absl/memory",
         "//absl/random:distributions",
         "//absl/strings",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -427,6 +497,7 @@
 cc_test(
     name = "stderr_log_sink_test",
     size = "small",
+    timeout = "moderate",
     srcs = ["stderr_log_sink_test.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -434,7 +505,9 @@
         "no_test:os:android",
         "no_test:os:ios",
         "no_test_android",
+        "no_test_darwin_arm64",
         "no_test_darwin_x86_64",
+        "no_test_fuchsia_x64",
         "no_test_ios",
         "no_test_wasm",
     ],
@@ -444,8 +517,8 @@
         "//absl/base:log_severity",
         "//absl/log",
         "//absl/log:globals",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -456,8 +529,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":fnmatch",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -469,6 +542,6 @@
     tags = ["benchmark"],
     deps = [
         ":fnmatch",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/log/internal/append_truncated.h b/absl/log/internal/append_truncated.h
index f0e7912..d420a8b 100644
--- a/absl/log/internal/append_truncated.h
+++ b/absl/log/internal/append_truncated.h
@@ -17,8 +17,10 @@
 
 #include <cstddef>
 #include <cstring>
+#include <string_view>
 
 #include "absl/base/config.h"
+#include "absl/strings/internal/utf8.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/span.h"
 
@@ -33,6 +35,32 @@
   dst.remove_prefix(src.size());
   return src.size();
 }
+// Likewise, but it also takes a wide character string and transforms it into a
+// UTF-8 encoded byte string regardless of the current locale.
+// - On platforms where `wchar_t` is 2 bytes (e.g., Windows), the input is
+//   treated as UTF-16.
+// - On platforms where `wchar_t` is 4 bytes (e.g., Linux, macOS), the input
+//   is treated as UTF-32.
+inline size_t AppendTruncated(std::wstring_view src, absl::Span<char> &dst) {
+  absl::strings_internal::ShiftState state;
+  size_t total_bytes_written = 0;
+  for (const wchar_t wc : src) {
+    // If the destination buffer might not be large enough to write the next
+    // character, stop.
+    if (dst.size() < absl::strings_internal::kMaxEncodedUTF8Size) break;
+    size_t bytes_written =
+        absl::strings_internal::WideToUtf8(wc, dst.data(), state);
+    if (bytes_written == static_cast<size_t>(-1)) {
+      // Invalid character. Encode REPLACEMENT CHARACTER (U+FFFD) instead.
+      constexpr wchar_t kReplacementCharacter = L'\uFFFD';
+      bytes_written = absl::strings_internal::WideToUtf8(kReplacementCharacter,
+                                                         dst.data(), state);
+    }
+    dst.remove_prefix(bytes_written);
+    total_bytes_written += bytes_written;
+  }
+  return total_bytes_written;
+}
 // Likewise, but `n` copies of `c`.
 inline size_t AppendTruncated(char c, size_t n, absl::Span<char> &dst) {
   if (n > dst.size()) n = dst.size();
diff --git a/absl/log/internal/check_op.cc b/absl/log/internal/check_op.cc
index 23c4a3b..23db63b 100644
--- a/absl/log/internal/check_op.cc
+++ b/absl/log/internal/check_op.cc
@@ -14,10 +14,15 @@
 
 #include "absl/log/internal/check_op.h"
 
-#include <string.h>
-
+#include <cstring>
 #include <ostream>
+#include <string>
+#include <utility>
 
+#include "absl/base/config.h"
+#include "absl/base/nullability.h"
+#include "absl/debugging/leak_check.h"
+#include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 
 #ifdef _MSC_VER
@@ -26,34 +31,30 @@
 #include <strings.h>  // for strcasecmp, but msvc does not have this header
 #endif
 
-#include <sstream>
-#include <string>
-
-#include "absl/base/config.h"
-#include "absl/strings/str_cat.h"
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace log_internal {
 
-#define ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(x) \
-  template std::string* MakeCheckOpString(x, x, const char*)
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(bool);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(int64_t);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(uint64_t);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(float);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(double);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(char);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(unsigned char);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const std::string&);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const absl::string_view&);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const char*);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const signed char*);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const unsigned char*);
-ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const void*);
-#undef ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING
+#define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(x) \
+  template const char* absl_nonnull MakeCheckOpString(   \
+      x, x, const char* absl_nonnull)
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(bool);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(int64_t);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(uint64_t);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(float);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(double);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(char);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(unsigned char);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const std::string&);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const absl::string_view&);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const signed char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const unsigned char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const void*);
+#undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING
 
-CheckOpMessageBuilder::CheckOpMessageBuilder(const char* exprtext) {
+CheckOpMessageBuilder::CheckOpMessageBuilder(
+    const char* absl_nonnull exprtext) {
   stream_ << exprtext << " (";
 }
 
@@ -62,9 +63,10 @@
   return stream_;
 }
 
-std::string* CheckOpMessageBuilder::NewString() {
+const char* absl_nonnull CheckOpMessageBuilder::NewString() {
   stream_ << ")";
-  return new std::string(stream_.str());
+  // There's no need to free this string since the process is crashing.
+  return absl::IgnoreLeak(new std::string(std::move(stream_).str()))->c_str();
 }
 
 void MakeCheckOpValueString(std::ostream& os, const char v) {
@@ -100,16 +102,19 @@
 }
 
 // Helper functions for string comparisons.
-#define DEFINE_CHECK_STROP_IMPL(name, func, expected)                      \
-  std::string* Check##func##expected##Impl(const char* s1, const char* s2, \
-                                           const char* exprtext) {         \
-    bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2));                  \
-    if (equal == expected) {                                               \
-      return nullptr;                                                      \
-    } else {                                                               \
-      return new std::string(                                              \
-          absl::StrCat(exprtext, " (", s1, " vs. ", s2, ")"));             \
-    }                                                                      \
+#define DEFINE_CHECK_STROP_IMPL(name, func, expected)                          \
+  const char* absl_nullable Check##func##expected##Impl(                       \
+      const char* absl_nullable s1, const char* absl_nullable s2,              \
+      const char* absl_nonnull exprtext) {                                     \
+    bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2));                      \
+    if (equal == expected) {                                                   \
+      return nullptr;                                                          \
+    } else {                                                                   \
+      /* There's no need to free this string since the process is crashing. */ \
+      return absl::IgnoreLeak(new std::string(absl::StrCat(exprtext, " (", s1, \
+                                                           " vs. ", s2, ")"))) \
+          ->c_str();                                                           \
+    }                                                                          \
   }
 DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true)
 DEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false)
diff --git a/absl/log/internal/check_op.h b/absl/log/internal/check_op.h
index 2159220..7253402 100644
--- a/absl/log/internal/check_op.h
+++ b/absl/log/internal/check_op.h
@@ -32,7 +32,9 @@
 #include <utility>
 
 #include "absl/base/attributes.h"
+#include "absl/base/casts.h"
 #include "absl/base/config.h"
+#include "absl/base/nullability.h"
 #include "absl/base/optimization.h"
 #include "absl/log/internal/nullguard.h"
 #include "absl/log/internal/nullstream.h"
@@ -62,45 +64,51 @@
 #endif
 
 #define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val1_text, val2, val2_text) \
-  while (::std::string* absl_log_internal_check_op_result                      \
-             ABSL_LOG_INTERNAL_ATTRIBUTE_UNUSED_IF_STRIP_LOG =                 \
-                 ::absl::log_internal::name##Impl(                             \
-                     ::absl::log_internal::GetReferenceableValue(val1),        \
-                     ::absl::log_internal::GetReferenceableValue(val2),        \
-                     ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(                   \
-                         val1_text " " #op " " val2_text)))                    \
+  while (const char* absl_nullable absl_log_internal_check_op_result           \
+         [[maybe_unused]] = ::absl::log_internal::name##Impl(                  \
+             ::absl::log_internal::GetReferenceableValue(val1),                \
+             ::absl::log_internal::GetReferenceableValue(val2),                \
+             ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val1_text " " #op          \
+                                                              " " val2_text))) \
     ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                         \
-  ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_op_result).InternalStream()
-#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val1_text, val2, \
-                                    val2_text)                       \
-  while (::std::string* absl_log_internal_qcheck_op_result =         \
-             ::absl::log_internal::name##Impl(                       \
-                 ::absl::log_internal::GetReferenceableValue(val1),  \
-                 ::absl::log_internal::GetReferenceableValue(val2),  \
-                 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(             \
-                     val1_text " " #op " " val2_text)))              \
-    ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)              \
-  ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_op_result).InternalStream()
+  ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>(     \
+                              absl_log_internal_check_op_result))              \
+      .InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val1_text, val2,        \
+                                    val2_text)                              \
+  while (const char* absl_nullable absl_log_internal_qcheck_op_result =     \
+             ::absl::log_internal::name##Impl(                              \
+                 ::absl::log_internal::GetReferenceableValue(val1),         \
+                 ::absl::log_internal::GetReferenceableValue(val2),         \
+                 ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(                    \
+                     val1_text " " #op " " val2_text)))                     \
+    ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                     \
+  ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>( \
+                               absl_log_internal_qcheck_op_result))         \
+      .InternalStream()
 #define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s1_text, s2,     \
                                       s2_text)                                 \
-  while (::std::string* absl_log_internal_check_strop_result =                 \
+  while (const char* absl_nullable absl_log_internal_check_strop_result =      \
              ::absl::log_internal::Check##func##expected##Impl(                \
                  (s1), (s2),                                                   \
                  ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op        \
                                                                 " " s2_text))) \
     ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                         \
-  ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_strop_result)               \
+  ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>(     \
+                              absl_log_internal_check_strop_result))           \
       .InternalStream()
 #define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s1_text, s2,    \
                                        s2_text)                                \
-  while (::std::string* absl_log_internal_qcheck_strop_result =                \
+  while (const char* absl_nullable absl_log_internal_qcheck_strop_result =     \
              ::absl::log_internal::Check##func##expected##Impl(                \
                  (s1), (s2),                                                   \
                  ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op        \
                                                                 " " s2_text))) \
     ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                        \
-  ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_strop_result)             \
+  ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>(    \
+                               absl_log_internal_qcheck_strop_result))         \
       .InternalStream()
+
 // This one is tricky:
 // * We must evaluate `val` exactly once, yet we need to do two things with it:
 //   evaluate `.ok()` and (sometimes) `.ToString()`.
@@ -125,37 +133,41 @@
 //   string literal and abort without doing any streaming.  We don't need to
 //   strip the call to stringify the non-ok `Status` as long as we don't log it;
 //   dropping the `Status`'s message text is out of scope.
-#define ABSL_LOG_INTERNAL_CHECK_OK(val, val_text)                        \
-  for (::std::pair<const ::absl::Status*, ::std::string*>                \
-           absl_log_internal_check_ok_goo;                               \
-       absl_log_internal_check_ok_goo.first =                            \
-           ::absl::log_internal::AsStatus(val),                          \
-       absl_log_internal_check_ok_goo.second =                           \
-           ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \
-               ? nullptr                                                 \
-               : ::absl::status_internal::MakeCheckFailString(           \
-                     absl_log_internal_check_ok_goo.first,               \
-                     ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text     \
-                                                            " is OK")),  \
-       !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());)  \
-    ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                   \
-  ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_ok_goo.second)        \
+#define ABSL_LOG_INTERNAL_CHECK_OK(val, val_text)                          \
+  for (::std::pair<const ::absl::Status* absl_nonnull,                     \
+                   const char* absl_nullable>                              \
+           absl_log_internal_check_ok_goo;                                 \
+       absl_log_internal_check_ok_goo.first =                              \
+           ::absl::log_internal::AsStatus(val),                            \
+       absl_log_internal_check_ok_goo.second =                             \
+           ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok())   \
+               ? nullptr                                                   \
+               : ::absl::status_internal::MakeCheckFailString(             \
+                     absl_log_internal_check_ok_goo.first,                 \
+                     ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text       \
+                                                            " is OK")),    \
+       !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());)    \
+    ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true)                     \
+  ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>( \
+                              absl_log_internal_check_ok_goo.second))      \
       .InternalStream()
-#define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text)                        \
-  for (::std::pair<const ::absl::Status*, ::std::string*>                 \
-           absl_log_internal_qcheck_ok_goo;                               \
-       absl_log_internal_qcheck_ok_goo.first =                            \
-           ::absl::log_internal::AsStatus(val),                           \
-       absl_log_internal_qcheck_ok_goo.second =                           \
-           ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok()) \
-               ? nullptr                                                  \
-               : ::absl::status_internal::MakeCheckFailString(            \
-                     absl_log_internal_qcheck_ok_goo.first,               \
-                     ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text      \
-                                                            " is OK")),   \
-       !ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok());)  \
-    ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                   \
-  ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_ok_goo.second)       \
+#define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text)                          \
+  for (::std::pair<const ::absl::Status* absl_nonnull,                      \
+                   const char* absl_nullable>                               \
+           absl_log_internal_qcheck_ok_goo;                                 \
+       absl_log_internal_qcheck_ok_goo.first =                              \
+           ::absl::log_internal::AsStatus(val),                             \
+       absl_log_internal_qcheck_ok_goo.second =                             \
+           ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok())   \
+               ? nullptr                                                    \
+               : ::absl::status_internal::MakeCheckFailString(              \
+                     absl_log_internal_qcheck_ok_goo.first,                 \
+                     ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text        \
+                                                            " is OK")),     \
+       !ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok());)    \
+    ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true)                     \
+  ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>( \
+                               absl_log_internal_qcheck_ok_goo.second))     \
       .InternalStream()
 
 namespace absl {
@@ -166,8 +178,8 @@
 class StatusOr;
 
 namespace status_internal {
-ABSL_ATTRIBUTE_PURE_FUNCTION std::string* MakeCheckFailString(
-    const absl::Status* status, const char* prefix);
+ABSL_ATTRIBUTE_PURE_FUNCTION const char* absl_nonnull MakeCheckFailString(
+    const absl::Status* absl_nonnull status, const char* absl_nonnull prefix);
 }  // namespace status_internal
 
 namespace log_internal {
@@ -175,9 +187,11 @@
 // Convert a Status or a StatusOr to its underlying status value.
 //
 // (This implementation does not require a dep on absl::Status to work.)
-inline const absl::Status* AsStatus(const absl::Status& s) { return &s; }
+inline const absl::Status* absl_nonnull AsStatus(const absl::Status& s) {
+  return &s;
+}
 template <typename T>
-const absl::Status* AsStatus(const absl::StatusOr<T>& s) {
+const absl::Status* absl_nonnull AsStatus(const absl::StatusOr<T>& s) {
   return &s.status();
 }
 
@@ -186,14 +200,14 @@
 class CheckOpMessageBuilder final {
  public:
   // Inserts `exprtext` and ` (` to the stream.
-  explicit CheckOpMessageBuilder(const char* exprtext);
+  explicit CheckOpMessageBuilder(const char* absl_nonnull exprtext);
   ~CheckOpMessageBuilder() = default;
   // For inserting the first variable.
   std::ostream& ForVar1() { return stream_; }
   // For inserting the second variable (adds an intermediate ` vs. `).
   std::ostream& ForVar2();
   // Get the result (inserts the closing `)`).
-  std::string* NewString();
+  const char* absl_nonnull NewString();
 
  private:
   std::ostringstream stream_;
@@ -210,7 +224,7 @@
 void MakeCheckOpValueString(std::ostream& os, char v);
 void MakeCheckOpValueString(std::ostream& os, signed char v);
 void MakeCheckOpValueString(std::ostream& os, unsigned char v);
-void MakeCheckOpValueString(std::ostream& os, const void* p);
+void MakeCheckOpValueString(std::ostream& os, const void* absl_nullable p);
 
 namespace detect_specialization {
 
@@ -252,8 +266,9 @@
 double operator<<(std::ostream&, double value);
 long double operator<<(std::ostream&, long double value);
 bool operator<<(std::ostream&, bool value);
-const void* operator<<(std::ostream&, const void* value);
-const void* operator<<(std::ostream&, std::nullptr_t);
+const void* absl_nullable operator<<(std::ostream&,
+                                     const void* absl_nullable value);
+const void* absl_nullable operator<<(std::ostream&, std::nullptr_t);
 
 // These `char` overloads are specified like this in the standard, so we have to
 // write them exactly the same to ensure the call is ambiguous.
@@ -267,13 +282,14 @@
 template <typename Traits>
 unsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char);
 template <typename Traits>
-const char* operator<<(std::basic_ostream<char, Traits>&, const char*);
+const char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,
+                                    const char* absl_nonnull);
 template <typename Traits>
-const signed char* operator<<(std::basic_ostream<char, Traits>&,
-                              const signed char*);
+const signed char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,
+                                           const signed char* absl_nonnull);
 template <typename Traits>
-const unsigned char* operator<<(std::basic_ostream<char, Traits>&,
-                                const unsigned char*);
+const unsigned char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,
+                                             const unsigned char* absl_nonnull);
 
 // This overload triggers when the call is not ambiguous.
 // It means that T is being printed with some overload not on this list.
@@ -298,7 +314,8 @@
 
   void Append(absl::string_view text);
   void Append(size_t length, char ch);
-  friend void AbslFormatFlush(StringifySink* sink, absl::string_view text);
+  friend void AbslFormatFlush(StringifySink* absl_nonnull sink,
+                              absl::string_view text);
 
  private:
   std::ostream& os_;
@@ -336,11 +353,12 @@
 
 // Build the error message string.  Specify no inlining for code size.
 template <typename T1, typename T2>
-ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* MakeCheckOpString(
-    T1 v1, T2 v2, const char* exprtext) ABSL_ATTRIBUTE_NOINLINE;
+ABSL_ATTRIBUTE_RETURNS_NONNULL const char* absl_nonnull MakeCheckOpString(
+    T1 v1, T2 v2, const char* absl_nonnull exprtext) ABSL_ATTRIBUTE_NOINLINE;
 
 template <typename T1, typename T2>
-std::string* MakeCheckOpString(T1 v1, T2 v2, const char* exprtext) {
+const char* absl_nonnull MakeCheckOpString(T1 v1, T2 v2,
+                                           const char* absl_nonnull exprtext) {
   CheckOpMessageBuilder comb(exprtext);
   MakeCheckOpValueString(comb.ForVar1(), v1);
   MakeCheckOpValueString(comb.ForVar2(), v2);
@@ -350,7 +368,8 @@
 // Add a few commonly used instantiations as extern to reduce size of objects
 // files.
 #define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \
-  extern template std::string* MakeCheckOpString(x, x, const char*)
+  extern template const char* absl_nonnull MakeCheckOpString(   \
+      x, x, const char* absl_nonnull)
 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool);
 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t);
 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t);
@@ -360,10 +379,12 @@
 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char);
 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&);
 ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&);
-ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char*);
-ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const signed char*);
-ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const unsigned char*);
-ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char* absl_nonnull);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(
+    const signed char* absl_nonnull);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(
+    const unsigned char* absl_nonnull);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void* absl_nonnull);
 #undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN
 
 // `ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT` skips formatting the Check_OP result
@@ -374,7 +395,7 @@
   ((::absl::LogSeverity::kFatal >=                                       \
     static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))                \
        ? MakeCheckOpString<U1, U2>(v1, v2, exprtext)                     \
-       : new std::string())
+       : "")
 #else
 #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \
   MakeCheckOpString<U1, U2>(v1, v2, exprtext)
@@ -386,8 +407,8 @@
 // type.
 #define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op)                          \
   template <typename T1, typename T2>                                      \
-  inline constexpr ::std::string* name##Impl(const T1& v1, const T2& v2,   \
-                                             const char* exprtext) {       \
+  inline constexpr const char* absl_nullable name##Impl(                   \
+      const T1& v1, const T2& v2, const char* absl_nonnull exprtext) {     \
     using U1 = CheckOpStreamType<T1>;                                      \
     using U2 = CheckOpStreamType<T2>;                                      \
     return ABSL_PREDICT_TRUE(v1 op v2)                                     \
@@ -395,8 +416,8 @@
                : ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, U1(v1),    \
                                                         U2(v2), exprtext); \
   }                                                                        \
-  inline constexpr ::std::string* name##Impl(int v1, int v2,               \
-                                             const char* exprtext) {       \
+  inline constexpr const char* absl_nullable name##Impl(                   \
+      int v1, int v2, const char* absl_nonnull exprtext) {                 \
     return name##Impl<int, int>(v1, v2, exprtext);                         \
   }
 
@@ -409,14 +430,18 @@
 #undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT
 #undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL
 
-std::string* CheckstrcmptrueImpl(const char* s1, const char* s2,
-                                 const char* exprtext);
-std::string* CheckstrcmpfalseImpl(const char* s1, const char* s2,
-                                  const char* exprtext);
-std::string* CheckstrcasecmptrueImpl(const char* s1, const char* s2,
-                                     const char* exprtext);
-std::string* CheckstrcasecmpfalseImpl(const char* s1, const char* s2,
-                                      const char* exprtext);
+const char* absl_nullable CheckstrcmptrueImpl(
+    const char* absl_nullable s1, const char* absl_nullable s2,
+    const char* absl_nonnull exprtext);
+const char* absl_nullable CheckstrcmpfalseImpl(
+    const char* absl_nullable s1, const char* absl_nullable s2,
+    const char* absl_nonnull exprtext);
+const char* absl_nullable CheckstrcasecmptrueImpl(
+    const char* absl_nullable s1, const char* absl_nullable s2,
+    const char* absl_nonnull exprtext);
+const char* absl_nullable CheckstrcasecmpfalseImpl(
+    const char* absl_nullable s1, const char* absl_nullable s2,
+    const char* absl_nonnull exprtext);
 
 // `CHECK_EQ` and friends want to pass their arguments by reference, however
 // this winds up exposing lots of cases where people have defined and
@@ -424,6 +449,8 @@
 // file), meaning they are not referenceable.  This function avoids that problem
 // for integers (the most common cases) by overloading for every primitive
 // integer type, even the ones we discourage, and returning them by value.
+// NOLINTBEGIN(runtime/int)
+// NOLINTBEGIN(google-runtime-int)
 template <typename T>
 inline constexpr const T& GetReferenceableValue(const T& t) {
   return t;
@@ -433,27 +460,25 @@
   return t;
 }
 inline constexpr signed char GetReferenceableValue(signed char t) { return t; }
-inline constexpr short GetReferenceableValue(short t) { return t; }  // NOLINT
-inline constexpr unsigned short GetReferenceableValue(               // NOLINT
-    unsigned short t) {                                              // NOLINT
+inline constexpr short GetReferenceableValue(short t) { return t; }
+inline constexpr unsigned short GetReferenceableValue(unsigned short t) {
   return t;
 }
 inline constexpr int GetReferenceableValue(int t) { return t; }
 inline constexpr unsigned int GetReferenceableValue(unsigned int t) {
   return t;
 }
-inline constexpr long GetReferenceableValue(long t) { return t; }  // NOLINT
-inline constexpr unsigned long GetReferenceableValue(              // NOLINT
-    unsigned long t) {                                             // NOLINT
+inline constexpr long GetReferenceableValue(long t) { return t; }
+inline constexpr unsigned long GetReferenceableValue(unsigned long t) {
   return t;
 }
-inline constexpr long long GetReferenceableValue(long long t) {  // NOLINT
+inline constexpr long long GetReferenceableValue(long long t) { return t; }
+inline constexpr unsigned long long GetReferenceableValue(
+    unsigned long long t) {
   return t;
 }
-inline constexpr unsigned long long GetReferenceableValue(  // NOLINT
-    unsigned long long t) {                                 // NOLINT
-  return t;
-}
+// NOLINTEND(google-runtime-int)
+// NOLINTEND(runtime/int)
 
 }  // namespace log_internal
 ABSL_NAMESPACE_END
diff --git a/absl/log/internal/conditions.cc b/absl/log/internal/conditions.cc
index a9f4966..a418c88 100644
--- a/absl/log/internal/conditions.cc
+++ b/absl/log/internal/conditions.cc
@@ -63,8 +63,9 @@
   // myriad2 does not have 8-byte compare and exchange.  Use a racy version that
   // is "good enough" but will over-log in the face of concurrent logging.
   if (now_cycles > next_cycles) {
-    next_log_time_cycles_.store(now_cycles + seconds * CycleClock::Frequency(),
-                                std::memory_order_relaxed);
+    next_log_time_cycles_.store(
+        static_cast<int64_t>(now_cycles + seconds * CycleClock::Frequency()),
+        std::memory_order_relaxed);
     return true;
   }
   return false;
@@ -72,7 +73,8 @@
   do {
     if (now_cycles <= next_cycles) return false;
   } while (!next_log_time_cycles_.compare_exchange_weak(
-      next_cycles, now_cycles + seconds * CycleClock::Frequency(),
+      next_cycles,
+      static_cast<int64_t>(now_cycles + seconds * CycleClock::Frequency()),
       std::memory_order_relaxed, std::memory_order_relaxed));
   return true;
 #endif
diff --git a/absl/log/internal/conditions.h b/absl/log/internal/conditions.h
index 9dc15db..6fb74b1 100644
--- a/absl/log/internal/conditions.h
+++ b/absl/log/internal/conditions.h
@@ -65,7 +65,7 @@
   switch (0)                                             \
   case 0:                                                \
   default:                                               \
-    !(condition) ? (void)0 : ::absl::log_internal::Voidify()&&
+    !(condition) ? (void)0 : ::absl::log_internal::Voidify() &&
 
 // `ABSL_LOG_INTERNAL_STATEFUL_CONDITION` applies a condition like
 // `ABSL_LOG_INTERNAL_STATELESS_CONDITION` but adds to that a series of variable
@@ -96,7 +96,8 @@
     for (const uint32_t COUNTER ABSL_ATTRIBUTE_UNUSED =                   \
              absl_log_internal_stateful_condition_state.counter();        \
          absl_log_internal_stateful_condition_do_log;                     \
-         absl_log_internal_stateful_condition_do_log = false)
+         absl_log_internal_stateful_condition_do_log = false)             \
+  ::absl::log_internal::Voidify() &&
 
 // `ABSL_LOG_INTERNAL_CONDITION_*` serve to combine any conditions from the
 // macro (e.g. `LOG_IF` or `VLOG`) with inherent conditions (e.g.
@@ -117,6 +118,8 @@
   ABSL_LOG_INTERNAL_##type##_CONDITION(                    \
       (condition) && ::absl::LogSeverity::kError >=        \
                          static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+#define ABSL_LOG_INTERNAL_CONDITION_DO_NOT_SUBMIT(type, condition) \
+  ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition)
 // NOTE: Use ternary operators instead of short-circuiting to mitigate
 // https://bugs.llvm.org/show_bug.cgi?id=51928.
 #define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition)                 \
@@ -168,6 +171,8 @@
   ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
 #define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
   ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_DO_NOT_SUBMIT(type, condition) \
+  ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition)
 #define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
   ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
 #define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
diff --git a/absl/log/internal/fnmatch_test.cc b/absl/log/internal/fnmatch_test.cc
index e16a64e..614c7d3 100644
--- a/absl/log/internal/fnmatch_test.cc
+++ b/absl/log/internal/fnmatch_test.cc
@@ -27,6 +27,7 @@
   EXPECT_THAT(FNMatch("foo", "bar"), IsFalse());
   EXPECT_THAT(FNMatch("foo", "fo"), IsFalse());
   EXPECT_THAT(FNMatch("foo", "foo2"), IsFalse());
+  EXPECT_THAT(FNMatch("foo/*", "foo/1/2/3/4"), IsTrue());
   EXPECT_THAT(FNMatch("bar/foo.ext", "bar/foo.ext"), IsTrue());
   EXPECT_THAT(FNMatch("*ba*r/fo*o.ext*", "bar/foo.ext"), IsTrue());
   EXPECT_THAT(FNMatch("bar/foo.ext", "bar/baz.ext"), IsFalse());
diff --git a/absl/log/internal/log_message.cc b/absl/log/internal/log_message.cc
index 4e9b08a..3aed3a2 100644
--- a/absl/log/internal/log_message.cc
+++ b/absl/log/internal/log_message.cc
@@ -31,6 +31,7 @@
 #include <memory>
 #include <ostream>
 #include <string>
+#include <string_view>
 #include <tuple>
 
 #include "absl/base/attributes.h"
@@ -39,6 +40,7 @@
 #include "absl/base/internal/strerror.h"
 #include "absl/base/internal/sysinfo.h"
 #include "absl/base/log_severity.h"
+#include "absl/base/nullability.h"
 #include "absl/container/inlined_vector.h"
 #include "absl/debugging/internal/examine_stack.h"
 #include "absl/log/globals.h"
@@ -46,11 +48,14 @@
 #include "absl/log/internal/globals.h"
 #include "absl/log/internal/log_format.h"
 #include "absl/log/internal/log_sink_set.h"
+#include "absl/log/internal/nullguard.h"
 #include "absl/log/internal/proto.h"
+#include "absl/log/internal/structured_proto.h"
 #include "absl/log/log_entry.h"
 #include "absl/log/log_sink.h"
 #include "absl/log/log_sink_registry.h"
 #include "absl/memory/memory.h"
+#include "absl/strings/internal/utf8.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/clock.h"
 #include "absl/time/time.h"
@@ -145,8 +150,8 @@
 }  // namespace
 
 struct LogMessage::LogMessageData final {
-  LogMessageData(const char* file, int line, absl::LogSeverity severity,
-                 absl::Time timestamp);
+  LogMessageData(const char* absl_nonnull file, int line,
+                 absl::LogSeverity severity, absl::Time timestamp);
   LogMessageData(const LogMessageData&) = delete;
   LogMessageData& operator=(const LogMessageData&) = delete;
 
@@ -161,7 +166,7 @@
   bool is_perror;
 
   // Extra `LogSink`s to log to, in addition to `global_sinks`.
-  absl::InlinedVector<absl::LogSink*, 16> extra_sinks;
+  absl::InlinedVector<absl::LogSink* absl_nonnull, 16> extra_sinks;
   // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded
   // non-sink targets (e.g. stderr, log files).
   bool extra_sinks_only;
@@ -197,8 +202,8 @@
   void FinalizeEncodingAndFormat();
 };
 
-LogMessage::LogMessageData::LogMessageData(const char* file, int line,
-                                           absl::LogSeverity severity,
+LogMessage::LogMessageData::LogMessageData(const char* absl_nonnull file,
+                                           int line, absl::LogSeverity severity,
                                            absl::Time timestamp)
     : extra_sinks_only(false), manipulated(nullptr) {
   // Legacy defaults for LOG's ostream:
@@ -268,7 +273,8 @@
       absl::MakeSpan(string_buf).subspan(0, chars_written);
 }
 
-LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity)
+LogMessage::LogMessage(const char* absl_nonnull file, int line,
+                       absl::LogSeverity severity)
     : data_(absl::make_unique<LogMessageData>(file, line, severity,
                                               absl::Now())) {
   data_->first_fatal = false;
@@ -281,23 +287,15 @@
   LogBacktraceIfNeeded();
 }
 
-LogMessage::LogMessage(const char* file, int line, InfoTag)
+LogMessage::LogMessage(const char* absl_nonnull file, int line, InfoTag)
     : LogMessage(file, line, absl::LogSeverity::kInfo) {}
-LogMessage::LogMessage(const char* file, int line, WarningTag)
+LogMessage::LogMessage(const char* absl_nonnull file, int line, WarningTag)
     : LogMessage(file, line, absl::LogSeverity::kWarning) {}
-LogMessage::LogMessage(const char* file, int line, ErrorTag)
+LogMessage::LogMessage(const char* absl_nonnull file, int line, ErrorTag)
     : LogMessage(file, line, absl::LogSeverity::kError) {}
 
-LogMessage::~LogMessage() {
-#ifdef ABSL_MIN_LOG_LEVEL
-  if (data_->entry.log_severity() <
-          static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
-      data_->entry.log_severity() < absl::LogSeverity::kFatal) {
-    return;
-  }
-#endif
-  Flush();
-}
+// This cannot go in the header since LogMessageData is defined in this file.
+LogMessage::~LogMessage() = default;
 
 LogMessage& LogMessage::AtLocation(absl::string_view file, int line) {
   data_->entry.full_filename_ = file;
@@ -348,13 +346,13 @@
   return *this;
 }
 
-LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) {
+LogMessage& LogMessage::ToSinkAlso(absl::LogSink* absl_nonnull sink) {
   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
   data_->extra_sinks.push_back(sink);
   return *this;
 }
 
-LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) {
+LogMessage& LogMessage::ToSinkOnly(absl::LogSink* absl_nonnull sink) {
   ABSL_INTERNAL_CHECK(sink, "null LogSink*");
   data_->extra_sinks.clear();
   data_->extra_sinks.push_back(sink);
@@ -408,6 +406,34 @@
   CopyToEncodedBuffer<StringType::kNotLiteral>(v);
   return *this;
 }
+
+LogMessage& LogMessage::operator<<(const std::wstring& v) {
+  CopyToEncodedBuffer<StringType::kNotLiteral>(v);
+  return *this;
+}
+
+LogMessage& LogMessage::operator<<(std::wstring_view v) {
+  CopyToEncodedBuffer<StringType::kNotLiteral>(v);
+  return *this;
+}
+
+template <>
+LogMessage& LogMessage::operator<< <const wchar_t*>(
+    const wchar_t* absl_nullable const& v) {
+  if (v == nullptr) {
+    CopyToEncodedBuffer<StringType::kNotLiteral>(
+        absl::string_view(kCharNull.data(), kCharNull.size() - 1));
+  } else {
+    CopyToEncodedBuffer<StringType::kNotLiteral>(v);
+  }
+  return *this;
+}
+
+LogMessage& LogMessage::operator<<(wchar_t v) {
+  CopyToEncodedBuffer<StringType::kNotLiteral>(std::wstring_view(&v, 1));
+  return *this;
+}
+
 LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {
   OstreamView view(*data_);
   data_->manipulated << m;
@@ -418,23 +444,26 @@
   data_->manipulated << m;
   return *this;
 }
+// NOLINTBEGIN(runtime/int)
+// NOLINTBEGIN(google-runtime-int)
 template LogMessage& LogMessage::operator<<(const char& v);
 template LogMessage& LogMessage::operator<<(const signed char& v);
 template LogMessage& LogMessage::operator<<(const unsigned char& v);
-template LogMessage& LogMessage::operator<<(const short& v);           // NOLINT
-template LogMessage& LogMessage::operator<<(const unsigned short& v);  // NOLINT
+template LogMessage& LogMessage::operator<<(const short& v);
+template LogMessage& LogMessage::operator<<(const unsigned short& v);
 template LogMessage& LogMessage::operator<<(const int& v);
 template LogMessage& LogMessage::operator<<(const unsigned int& v);
-template LogMessage& LogMessage::operator<<(const long& v);           // NOLINT
-template LogMessage& LogMessage::operator<<(const unsigned long& v);  // NOLINT
-template LogMessage& LogMessage::operator<<(const long long& v);      // NOLINT
-template LogMessage& LogMessage::operator<<(
-    const unsigned long long& v);  // NOLINT
+template LogMessage& LogMessage::operator<<(const long& v);
+template LogMessage& LogMessage::operator<<(const unsigned long& v);
+template LogMessage& LogMessage::operator<<(const long long& v);
+template LogMessage& LogMessage::operator<<(const unsigned long long& v);
 template LogMessage& LogMessage::operator<<(void* const& v);
 template LogMessage& LogMessage::operator<<(const void* const& v);
 template LogMessage& LogMessage::operator<<(const float& v);
 template LogMessage& LogMessage::operator<<(const double& v);
 template LogMessage& LogMessage::operator<<(const bool& v);
+// NOLINTEND(google-runtime-int)
+// NOLINTEND(runtime/int)
 
 void LogMessage::Flush() {
   if (data_->entry.log_severity() < absl::MinLogLevel()) return;
@@ -575,16 +604,17 @@
 template <LogMessage::StringType str_type>
 void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
   auto encoded_remaining_copy = data_->encoded_remaining();
+  constexpr uint8_t tag_value = str_type == StringType::kLiteral
+                                    ? ValueTag::kStringLiteral
+                                    : ValueTag::kString;
   auto start = EncodeMessageStart(
-      EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(),
+      EventTag::kValue,
+      BufferSizeFor(tag_value, WireType::kLengthDelimited) + str.size(),
       &encoded_remaining_copy);
   // If the `logging.proto.Event.value` field header did not fit,
   // `EncodeMessageStart` will have zeroed `encoded_remaining_copy`'s size and
   // `EncodeStringTruncate` will fail too.
-  if (EncodeStringTruncate(str_type == StringType::kLiteral
-                               ? ValueTag::kStringLiteral
-                               : ValueTag::kString,
-                           str, &encoded_remaining_copy)) {
+  if (EncodeStringTruncate(tag_value, str, &encoded_remaining_copy)) {
     // The string may have been truncated, but the field header fit.
     EncodeMessageLength(start, &encoded_remaining_copy);
     data_->encoded_remaining() = encoded_remaining_copy;
@@ -601,13 +631,14 @@
 template <LogMessage::StringType str_type>
 void LogMessage::CopyToEncodedBuffer(char ch, size_t num) {
   auto encoded_remaining_copy = data_->encoded_remaining();
+  constexpr uint8_t tag_value = str_type == StringType::kLiteral
+                                    ? ValueTag::kStringLiteral
+                                    : ValueTag::kString;
   auto value_start = EncodeMessageStart(
-      EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num,
+      EventTag::kValue,
+      BufferSizeFor(tag_value, WireType::kLengthDelimited) + num,
       &encoded_remaining_copy);
-  auto str_start = EncodeMessageStart(str_type == StringType::kLiteral
-                                          ? ValueTag::kStringLiteral
-                                          : ValueTag::kString,
-                                      num, &encoded_remaining_copy);
+  auto str_start = EncodeMessageStart(tag_value, num, &encoded_remaining_copy);
   if (str_start.data()) {
     // The field headers fit.
     log_internal::AppendTruncated(ch, num, encoded_remaining_copy);
@@ -625,6 +656,78 @@
 template void LogMessage::CopyToEncodedBuffer<
     LogMessage::StringType::kNotLiteral>(char ch, size_t num);
 
+template <LogMessage::StringType str_type>
+void LogMessage::CopyToEncodedBuffer(std::wstring_view str) {
+  auto encoded_remaining_copy = data_->encoded_remaining();
+  constexpr uint8_t tag_value = str_type == StringType::kLiteral
+                                    ? ValueTag::kStringLiteral
+                                    : ValueTag::kString;
+  size_t max_str_byte_length =
+      absl::strings_internal::kMaxEncodedUTF8Size * str.length();
+  auto value_start =
+      EncodeMessageStart(EventTag::kValue,
+                         BufferSizeFor(tag_value, WireType::kLengthDelimited) +
+                             max_str_byte_length,
+                         &encoded_remaining_copy);
+  auto str_start = EncodeMessageStart(tag_value, max_str_byte_length,
+                                      &encoded_remaining_copy);
+  if (str_start.data()) {
+    log_internal::AppendTruncated(str, encoded_remaining_copy);
+    EncodeMessageLength(str_start, &encoded_remaining_copy);
+    EncodeMessageLength(value_start, &encoded_remaining_copy);
+    data_->encoded_remaining() = encoded_remaining_copy;
+  } else {
+    // The field header(s) did not fit; zero `encoded_remaining()` so we don't
+    // write anything else later.
+    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
+  }
+}
+template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
+    std::wstring_view str);
+template void LogMessage::CopyToEncodedBuffer<
+    LogMessage::StringType::kNotLiteral>(std::wstring_view str);
+
+template void LogMessage::CopyToEncodedBufferWithStructuredProtoField<
+    LogMessage::StringType::kLiteral>(StructuredProtoField field,
+                                      absl::string_view str);
+template void LogMessage::CopyToEncodedBufferWithStructuredProtoField<
+    LogMessage::StringType::kNotLiteral>(StructuredProtoField field,
+                                         absl::string_view str);
+
+template <LogMessage::StringType str_type>
+void LogMessage::CopyToEncodedBufferWithStructuredProtoField(
+    StructuredProtoField field, absl::string_view str) {
+  auto encoded_remaining_copy = data_->encoded_remaining();
+  size_t encoded_field_size = BufferSizeForStructuredProtoField(field);
+  constexpr uint8_t tag_value = str_type == StringType::kLiteral
+                                    ? ValueTag::kStringLiteral
+                                    : ValueTag::kString;
+  auto start = EncodeMessageStart(
+      EventTag::kValue,
+      encoded_field_size +
+          BufferSizeFor(tag_value, WireType::kLengthDelimited) + str.size(),
+      &encoded_remaining_copy);
+
+  // Write the encoded proto field.
+  if (!EncodeStructuredProtoField(field, encoded_remaining_copy)) {
+    // The header / field will not fit; zero `encoded_remaining()` so we
+    // don't write anything else later.
+    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
+    return;
+  }
+
+  // Write the string, truncating if necessary.
+  if (!EncodeStringTruncate(ValueTag::kString, str, &encoded_remaining_copy)) {
+    // The length of the string itself did not fit; zero `encoded_remaining()`
+    // so the value is not encoded at all.
+    data_->encoded_remaining().remove_suffix(data_->encoded_remaining().size());
+    return;
+  }
+
+  EncodeMessageLength(start, &encoded_remaining_copy);
+  data_->encoded_remaining() = encoded_remaining_copy;
+}
+
 // We intentionally don't return from these destructors. Disable MSVC's warning
 // about the destructor never returning as we do so intentionally here.
 #if defined(_MSC_VER) && !defined(__clang__)
@@ -632,54 +735,45 @@
 #pragma warning(disable : 4722)
 #endif
 
-LogMessageFatal::LogMessageFatal(const char* file, int line)
+LogMessageFatal::LogMessageFatal(const char* absl_nonnull file, int line)
     : LogMessage(file, line, absl::LogSeverity::kFatal) {}
 
-LogMessageFatal::LogMessageFatal(const char* file, int line,
-                                 absl::string_view failure_msg)
+LogMessageFatal::LogMessageFatal(const char* absl_nonnull file, int line,
+                                 const char* absl_nonnull failure_msg)
     : LogMessage(file, line, absl::LogSeverity::kFatal) {
   *this << "Check failed: " << failure_msg << " ";
 }
 
-LogMessageFatal::~LogMessageFatal() {
-  Flush();
-  FailWithoutStackTrace();
-}
+LogMessageFatal::~LogMessageFatal() { FailWithoutStackTrace(); }
 
-LogMessageDebugFatal::LogMessageDebugFatal(const char* file, int line)
+LogMessageDebugFatal::LogMessageDebugFatal(const char* absl_nonnull file,
+                                           int line)
     : LogMessage(file, line, absl::LogSeverity::kFatal) {}
 
-LogMessageDebugFatal::~LogMessageDebugFatal() {
-  Flush();
-  FailWithoutStackTrace();
-}
+LogMessageDebugFatal::~LogMessageDebugFatal() { FailWithoutStackTrace(); }
 
-LogMessageQuietlyDebugFatal::LogMessageQuietlyDebugFatal(const char* file,
-                                                         int line)
+LogMessageQuietlyDebugFatal::LogMessageQuietlyDebugFatal(
+    const char* absl_nonnull file, int line)
     : LogMessage(file, line, absl::LogSeverity::kFatal) {
   SetFailQuietly();
 }
 
-LogMessageQuietlyDebugFatal::~LogMessageQuietlyDebugFatal() {
-  Flush();
-  FailQuietly();
-}
+LogMessageQuietlyDebugFatal::~LogMessageQuietlyDebugFatal() { FailQuietly(); }
 
-LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
+LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* absl_nonnull file,
+                                               int line)
     : LogMessage(file, line, absl::LogSeverity::kFatal) {
   SetFailQuietly();
 }
 
-LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line,
-                                               absl::string_view failure_msg)
+LogMessageQuietlyFatal::LogMessageQuietlyFatal(
+    const char* absl_nonnull file, int line,
+    const char* absl_nonnull failure_msg)
     : LogMessageQuietlyFatal(file, line) {
-    *this << "Check failed: " << failure_msg << " ";
+  *this << "Check failed: " << failure_msg << " ";
 }
 
-LogMessageQuietlyFatal::~LogMessageQuietlyFatal() {
-  Flush();
-  FailQuietly();
-}
+LogMessageQuietlyFatal::~LogMessageQuietlyFatal() { FailQuietly(); }
 #if defined(_MSC_VER) && !defined(__clang__)
 #pragma warning(pop)
 #endif
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h
index 0c067da..1aaf05e 100644
--- a/absl/log/internal/log_message.h
+++ b/absl/log/internal/log_message.h
@@ -17,27 +17,34 @@
 // -----------------------------------------------------------------------------
 //
 // This file declares `class absl::log_internal::LogMessage`. This class more or
-// less represents a particular log message. LOG/CHECK macros create a
-// temporary instance of `LogMessage` and then stream values to it.  At the end
-// of the LOG/CHECK statement, LogMessage instance goes out of scope and
-// `~LogMessage` directs the message to the registered log sinks.
-// Heap-allocation of `LogMessage` is unsupported.  Construction outside of a
-// `LOG` macro is unsupported.
+// less represents a particular log message. LOG/CHECK macros create a temporary
+// instance of `LogMessage` and then stream values to it.  At the end of the
+// LOG/CHECK statement, the LogMessage is voidified by operator&&, and `Flush()`
+// directs the message to the registered log sinks.  Heap-allocation of
+// `LogMessage` is unsupported.  Construction outside of a `LOG` macro is
+// unsupported.
 
 #ifndef ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
 #define ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
 
+#include <wchar.h>
+
+#include <cstddef>
 #include <ios>
 #include <memory>
 #include <ostream>
 #include <streambuf>
 #include <string>
+#include <string_view>
+#include <type_traits>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/errno_saver.h"
 #include "absl/base/log_severity.h"
+#include "absl/base/nullability.h"
 #include "absl/log/internal/nullguard.h"
+#include "absl/log/internal/structured_proto.h"
 #include "absl/log/log_entry.h"
 #include "absl/log/log_sink.h"
 #include "absl/strings/has_absl_stringify.h"
@@ -49,6 +56,8 @@
 namespace log_internal {
 constexpr int kLogMessageBufferSize = 15000;
 
+enum class StructuredStringType;
+
 class LogMessage {
  public:
   struct InfoTag {};
@@ -56,15 +65,15 @@
   struct ErrorTag {};
 
   // Used for `LOG`.
-  LogMessage(const char* file, int line,
+  LogMessage(const char* absl_nonnull file, int line,
              absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;
   // These constructors are slightly smaller/faster to call; the severity is
   // curried into the function pointer.
-  LogMessage(const char* file, int line,
+  LogMessage(const char* absl_nonnull file, int line,
              InfoTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
-  LogMessage(const char* file, int line,
+  LogMessage(const char* absl_nonnull file, int line,
              WarningTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
-  LogMessage(const char* file, int line,
+  LogMessage(const char* absl_nonnull file, int line,
              ErrorTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
   LogMessage(const LogMessage&) = delete;
   LogMessage& operator=(const LogMessage&) = delete;
@@ -95,59 +104,73 @@
   // of `errno`.
   LogMessage& WithPerror();
   // Sends this message to `*sink` in addition to whatever other sinks it would
-  // otherwise have been sent to.  `sink` must not be null.
-  LogMessage& ToSinkAlso(absl::LogSink* sink);
-  // Sends this message to `*sink` and no others.  `sink` must not be null.
-  LogMessage& ToSinkOnly(absl::LogSink* sink);
+  // otherwise have been sent to.
+  LogMessage& ToSinkAlso(absl::LogSink* absl_nonnull sink);
+  // Sends this message to `*sink` and no others.
+  LogMessage& ToSinkOnly(absl::LogSink* absl_nonnull sink);
 
   // Don't call this method from outside this library.
   LogMessage& InternalStream() { return *this; }
 
   // By-value overloads for small, common types let us overlook common failures
   // to define globals and static data members (i.e. in a .cc file).
-  // clang-format off
-  // The CUDA toolchain cannot handle these <<<'s:
+  // NOLINTBEGIN(runtime/int)
+  // NOLINTBEGIN(google-runtime-int)
+  // clang-format off:  The CUDA toolchain cannot handle these <<<'s
   LogMessage& operator<<(char v) { return operator<< <char>(v); }
   LogMessage& operator<<(signed char v) { return operator<< <signed char>(v); }
   LogMessage& operator<<(unsigned char v) {
     return operator<< <unsigned char>(v);
   }
-  LogMessage& operator<<(signed short v) {  // NOLINT
-    return operator<< <signed short>(v);  // NOLINT
+  LogMessage& operator<<(signed short v) {
+    return operator<< <signed short>(v);
   }
   LogMessage& operator<<(signed int v) { return operator<< <signed int>(v); }
-  LogMessage& operator<<(signed long v) {  // NOLINT
-    return operator<< <signed long>(v);  // NOLINT
+  LogMessage& operator<<(signed long v) {
+    return operator<< <signed long>(v);
   }
-  LogMessage& operator<<(signed long long v) {  // NOLINT
-    return operator<< <signed long long>(v);  // NOLINT
+  LogMessage& operator<<(signed long long v) {
+    return operator<< <signed long long>(v);
   }
-  LogMessage& operator<<(unsigned short v) {  // NOLINT
-    return operator<< <unsigned short>(v);  // NOLINT
+  LogMessage& operator<<(unsigned short v) {
+    return operator<< <unsigned short>(v);
   }
   LogMessage& operator<<(unsigned int v) {
     return operator<< <unsigned int>(v);
   }
-  LogMessage& operator<<(unsigned long v) {  // NOLINT
-    return operator<< <unsigned long>(v);  // NOLINT
+  LogMessage& operator<<(unsigned long v) {
+    return operator<< <unsigned long>(v);
   }
-  LogMessage& operator<<(unsigned long long v) {  // NOLINT
-    return operator<< <unsigned long long>(v);  // NOLINT
+  LogMessage& operator<<(unsigned long long v) {
+    return operator<< <unsigned long long>(v);
   }
-  LogMessage& operator<<(void* v) { return operator<< <void*>(v); }
-  LogMessage& operator<<(const void* v) { return operator<< <const void*>(v); }
+  LogMessage& operator<<(void* absl_nullable  v) {
+    return operator<< <void*>(v);
+  }
+  LogMessage& operator<<(const void* absl_nullable  v) {
+    return operator<< <const void*>(v);
+  }
   LogMessage& operator<<(float v) { return operator<< <float>(v); }
   LogMessage& operator<<(double v) { return operator<< <double>(v); }
   LogMessage& operator<<(bool v) { return operator<< <bool>(v); }
   // clang-format on
+  // NOLINTEND(google-runtime-int)
+  // NOLINTEND(runtime/int)
 
   // These overloads are more efficient since no `ostream` is involved.
   LogMessage& operator<<(const std::string& v);
   LogMessage& operator<<(absl::string_view v);
 
+  // Wide string overloads (since std::ostream does not provide them).
+  LogMessage& operator<<(const std::wstring& v);
+  LogMessage& operator<<(std::wstring_view v);
+  // `const wchar_t*` is handled by `operator<< <const wchar_t*>`.
+  LogMessage& operator<<(wchar_t* absl_nullable v);
+  LogMessage& operator<<(wchar_t v);
+
   // Handle stream manipulators e.g. std::endl.
-  LogMessage& operator<<(std::ostream& (*m)(std::ostream& os));
-  LogMessage& operator<<(std::ios_base& (*m)(std::ios_base& os));
+  LogMessage& operator<<(std::ostream& (*absl_nonnull m)(std::ostream& os));
+  LogMessage& operator<<(std::ios_base& (*absl_nonnull m)(std::ios_base& os));
 
   // Literal strings.  This allows us to record C string literals as literals in
   // the logging.proto.Value.
@@ -156,31 +179,30 @@
   // this template for every value of `SIZE` encountered in each source code
   // file. That significantly increases linker input sizes. Inlining is cheap
   // because the argument to this overload is almost always a string literal so
-  // the call to `strlen` can be replaced at compile time. The overload for
-  // `char[]` below should not be inlined. The compiler typically does not have
-  // the string at compile time and cannot replace the call to `strlen` so
-  // inlining it increases the binary size. See the discussion on
+  // the call to `strlen` can be replaced at compile time. The overloads for
+  // `char[]`/`wchar_t[]` below should not be inlined. The compiler typically
+  // does not have the string at compile time and cannot replace the call to
+  // `strlen` so inlining it increases the binary size. See the discussion on
   // cl/107527369.
   template <int SIZE>
   LogMessage& operator<<(const char (&buf)[SIZE]);
+  template <int SIZE>
+  LogMessage& operator<<(const wchar_t (&buf)[SIZE]);
 
   // This prevents non-const `char[]` arrays from looking like literals.
   template <int SIZE>
   LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE;
+  // `wchar_t[SIZE]` is handled by `operator<< <const wchar_t*>`.
 
   // Types that support `AbslStringify()` are serialized that way.
-  template <typename T,
-            typename std::enable_if<absl::HasAbslStringify<T>::value,
-                                    int>::type = 0>
-  LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
-
   // Types that don't support `AbslStringify()` but do support streaming into a
   // `std::ostream&` are serialized that way.
-  template <typename T,
-            typename std::enable_if<!absl::HasAbslStringify<T>::value,
-                                    int>::type = 0>
+  template <typename T>
   LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
 
+  // Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s.
+  void Flush();
+
   // Note: We explicitly do not support `operator<<` for non-const references
   // because it breaks logging of non-integer bitfield types (i.e., enums).
 
@@ -193,11 +215,6 @@
   // the process with an error exit code.
   [[noreturn]] static void FailQuietly();
 
-  // Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s.
-  // This might as well be inlined into `~LogMessage` except that
-  // `~LogMessageFatal` needs to call it early.
-  void Flush();
-
   // After this is called, failures are done as quiet as possible for this log
   // message.
   void SetFailQuietly();
@@ -206,6 +223,10 @@
   struct LogMessageData;  // Opaque type containing message state
   friend class AsLiteralImpl;
   friend class StringifySink;
+  template <StructuredStringType str_type>
+  friend class AsStructuredStringTypeImpl;
+  template <typename T>
+  friend class AsStructuredValueImpl;
 
   // This streambuf writes directly into the structured logging buffer so that
   // arbitrary types can be encoded as string data (using
@@ -235,6 +256,15 @@
   void CopyToEncodedBuffer(absl::string_view str) ABSL_ATTRIBUTE_NOINLINE;
   template <StringType str_type>
   void CopyToEncodedBuffer(char ch, size_t num) ABSL_ATTRIBUTE_NOINLINE;
+  template <StringType str_type>
+  void CopyToEncodedBuffer(std::wstring_view str) ABSL_ATTRIBUTE_NOINLINE;
+
+  // Copies `field` to the encoded buffer, then appends `str` after it
+  // (truncating `str` if necessary to fit).
+  template <StringType str_type>
+  void CopyToEncodedBufferWithStructuredProtoField(StructuredProtoField field,
+                                                   absl::string_view str)
+      ABSL_ATTRIBUTE_NOINLINE;
 
   // Returns `true` if the message is fatal or enabled debug-fatal.
   bool IsFatal() const;
@@ -255,9 +285,25 @@
 
   // We keep the data in a separate struct so that each instance of `LogMessage`
   // uses less stack space.
-  std::unique_ptr<LogMessageData> data_;
+  absl_nonnull std::unique_ptr<LogMessageData> data_;
 };
 
+// Explicitly specializes the generic operator<< for `const wchar_t*`
+// arguments.
+//
+// This method is used instead of a non-template `const wchar_t*` overload,
+// as the latter was found to take precedence over the array template
+// (`operator<<(const wchar_t(&)[SIZE])`) when handling string literals.
+// This specialization ensures the array template now correctly processes
+// literals.
+template <>
+LogMessage& LogMessage::operator<< <const wchar_t*>(
+    const wchar_t* absl_nullable const& v);
+
+inline LogMessage& LogMessage::operator<<(wchar_t* absl_nullable v) {
+  return operator<<(const_cast<const wchar_t*>(v));
+}
+
 // Helper class so that `AbslStringify()` can modify the LogMessage.
 class StringifySink final {
  public:
@@ -273,7 +319,8 @@
   }
 
   // For types that implement `AbslStringify` using `absl::Format()`.
-  friend void AbslFormatFlush(StringifySink* sink, absl::string_view v) {
+  friend void AbslFormatFlush(StringifySink* absl_nonnull sink,
+                              absl::string_view v) {
     sink->Append(v);
   }
 
@@ -282,21 +329,16 @@
 };
 
 // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
-template <typename T,
-          typename std::enable_if<absl::HasAbslStringify<T>::value, int>::type>
+template <typename T>
 LogMessage& LogMessage::operator<<(const T& v) {
-  StringifySink sink(*this);
-  // Replace with public API.
-  AbslStringify(sink, v);
-  return *this;
-}
-
-// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
-template <typename T,
-          typename std::enable_if<!absl::HasAbslStringify<T>::value, int>::type>
-LogMessage& LogMessage::operator<<(const T& v) {
-  OstreamView view(*data_);
-  view.stream() << log_internal::NullGuard<T>().Guard(v);
+  if constexpr (absl::HasAbslStringify<T>::value) {
+    StringifySink sink(*this);
+    // Replace with public API.
+    AbslStringify(sink, v);
+  } else {
+    OstreamView view(*data_);
+    view.stream() << log_internal::NullGuard<T>().Guard(v);
+  }
   return *this;
 }
 
@@ -306,6 +348,12 @@
   return *this;
 }
 
+template <int SIZE>
+LogMessage& LogMessage::operator<<(const wchar_t (&buf)[SIZE]) {
+  CopyToEncodedBuffer<StringType::kLiteral>(buf);
+  return *this;
+}
+
 // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
 template <int SIZE>
 LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) {
@@ -315,27 +363,28 @@
 // We instantiate these specializations in the library's TU to save space in
 // other TUs.  Since the template is marked `ABSL_ATTRIBUTE_NOINLINE` we will be
 // emitting a function call either way.
+// NOLINTBEGIN(runtime/int)
+// NOLINTBEGIN(google-runtime-int)
 extern template LogMessage& LogMessage::operator<<(const char& v);
 extern template LogMessage& LogMessage::operator<<(const signed char& v);
 extern template LogMessage& LogMessage::operator<<(const unsigned char& v);
-extern template LogMessage& LogMessage::operator<<(const short& v);  // NOLINT
-extern template LogMessage& LogMessage::operator<<(
-    const unsigned short& v);  // NOLINT
+extern template LogMessage& LogMessage::operator<<(const short& v);
+extern template LogMessage& LogMessage::operator<<(const unsigned short& v);
 extern template LogMessage& LogMessage::operator<<(const int& v);
+extern template LogMessage& LogMessage::operator<<(const unsigned int& v);
+extern template LogMessage& LogMessage::operator<<(const long& v);
+extern template LogMessage& LogMessage::operator<<(const unsigned long& v);
+extern template LogMessage& LogMessage::operator<<(const long long& v);
+extern template LogMessage& LogMessage::operator<<(const unsigned long long& v);
 extern template LogMessage& LogMessage::operator<<(
-    const unsigned int& v);                                         // NOLINT
-extern template LogMessage& LogMessage::operator<<(const long& v);  // NOLINT
+    void* absl_nullable const& v);
 extern template LogMessage& LogMessage::operator<<(
-    const unsigned long& v);  // NOLINT
-extern template LogMessage& LogMessage::operator<<(
-    const long long& v);  // NOLINT
-extern template LogMessage& LogMessage::operator<<(
-    const unsigned long long& v);  // NOLINT
-extern template LogMessage& LogMessage::operator<<(void* const& v);
-extern template LogMessage& LogMessage::operator<<(const void* const& v);
+    const void* absl_nullable const& v);
 extern template LogMessage& LogMessage::operator<<(const float& v);
 extern template LogMessage& LogMessage::operator<<(const double& v);
 extern template LogMessage& LogMessage::operator<<(const bool& v);
+// NOLINTEND(google-runtime-int)
+// NOLINTEND(runtime/int)
 
 extern template void LogMessage::CopyToEncodedBuffer<
     LogMessage::StringType::kLiteral>(absl::string_view str);
@@ -346,14 +395,18 @@
                                                                   size_t num);
 extern template void LogMessage::CopyToEncodedBuffer<
     LogMessage::StringType::kNotLiteral>(char ch, size_t num);
+extern template void LogMessage::CopyToEncodedBuffer<
+    LogMessage::StringType::kLiteral>(std::wstring_view str);
+extern template void LogMessage::CopyToEncodedBuffer<
+    LogMessage::StringType::kNotLiteral>(std::wstring_view str);
 
 // `LogMessageFatal` ensures the process will exit in failure after logging this
 // message.
 class LogMessageFatal final : public LogMessage {
  public:
-  LogMessageFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
-  LogMessageFatal(const char* file, int line,
-                  absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD;
+  LogMessageFatal(const char* absl_nonnull file, int line) ABSL_ATTRIBUTE_COLD;
+  LogMessageFatal(const char* absl_nonnull file, int line,
+                  const char* absl_nonnull failure_msg) ABSL_ATTRIBUTE_COLD;
   [[noreturn]] ~LogMessageFatal();
 };
 
@@ -362,7 +415,8 @@
 // for DLOG(FATAL) variants.
 class LogMessageDebugFatal final : public LogMessage {
  public:
-  LogMessageDebugFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
+  LogMessageDebugFatal(const char* absl_nonnull file,
+                       int line) ABSL_ATTRIBUTE_COLD;
   ~LogMessageDebugFatal();
 };
 
@@ -371,16 +425,19 @@
   // DLOG(QFATAL) calls this instead of LogMessageQuietlyFatal to make sure the
   // destructor is not [[noreturn]] even if this is always FATAL as this is only
   // invoked when DLOG() is enabled.
-  LogMessageQuietlyDebugFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
+  LogMessageQuietlyDebugFatal(const char* absl_nonnull file,
+                              int line) ABSL_ATTRIBUTE_COLD;
   ~LogMessageQuietlyDebugFatal();
 };
 
 // Used for LOG(QFATAL) to make sure it's properly understood as [[noreturn]].
 class LogMessageQuietlyFatal final : public LogMessage {
  public:
-  LogMessageQuietlyFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
-  LogMessageQuietlyFatal(const char* file, int line,
-                         absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD;
+  LogMessageQuietlyFatal(const char* absl_nonnull file,
+                         int line) ABSL_ATTRIBUTE_COLD;
+  LogMessageQuietlyFatal(const char* absl_nonnull file, int line,
+                         const char* absl_nonnull failure_msg)
+      ABSL_ATTRIBUTE_COLD;
   [[noreturn]] ~LogMessageQuietlyFatal();
 };
 
diff --git a/absl/log/internal/nullstream.h b/absl/log/internal/nullstream.h
index 973e91a..c87f9aa 100644
--- a/absl/log/internal/nullstream.h
+++ b/absl/log/internal/nullstream.h
@@ -79,6 +79,7 @@
     return *this;
   }
   NullStream& InternalStream() { return *this; }
+  void Flush() {}
 };
 template <typename T>
 inline NullStream& operator<<(NullStream& str, const T&) {
diff --git a/absl/log/internal/proto.cc b/absl/log/internal/proto.cc
index eb699ae..821be2b 100644
--- a/absl/log/internal/proto.cc
+++ b/absl/log/internal/proto.cc
@@ -35,9 +35,6 @@
   }
   buf->remove_prefix(size);
 }
-constexpr uint64_t MakeTagType(uint64_t tag, WireType type) {
-  return tag << 3 | static_cast<uint64_t>(type);
-}
 }  // namespace
 
 bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf) {
@@ -126,8 +123,9 @@
   return true;
 }
 
-ABSL_MUST_USE_RESULT absl::Span<char> EncodeMessageStart(
-    uint64_t tag, uint64_t max_size, absl::Span<char> *buf) {
+[[nodiscard]] absl::Span<char> EncodeMessageStart(uint64_t tag,
+                                                  uint64_t max_size,
+                                                  absl::Span<char> *buf) {
   const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
   const size_t tag_type_size = VarintSize(tag_type);
   max_size = std::min<uint64_t>(max_size, buf->size());
diff --git a/absl/log/internal/proto.h b/absl/log/internal/proto.h
index c8d14ac..23f7954 100644
--- a/absl/log/internal/proto.h
+++ b/absl/log/internal/proto.h
@@ -169,9 +169,9 @@
 // safe to pass to `EncodeMessageLength` but need not be.
 // Used for string, bytes, message, and packed-repeated field type.
 // Consumes up to kMaxVarintSize * 2 bytes (20).
-ABSL_MUST_USE_RESULT absl::Span<char> EncodeMessageStart(uint64_t tag,
-                                                         uint64_t max_size,
-                                                         absl::Span<char> *buf);
+[[nodiscard]] absl::Span<char> EncodeMessageStart(uint64_t tag,
+                                                  uint64_t max_size,
+                                                  absl::Span<char> *buf);
 
 // Finalizes the length field in `msg` so that it encompasses all data encoded
 // since the call to `EncodeMessageStart` which returned `msg`.  Does nothing if
@@ -199,23 +199,33 @@
   return size >= 10 ? (std::numeric_limits<uint64_t>::max)()
                     : (static_cast<uint64_t>(1) << size * 7) - 1;
 }
+constexpr uint64_t MakeTagType(uint64_t tag, WireType type) {
+  return tag << 3 | static_cast<uint64_t>(type);
+}
 
 // `BufferSizeFor` returns a number of bytes guaranteed to be sufficient to
-// store encoded fields of the specified WireTypes regardless of tag numbers and
-// data values.  This only makes sense for `WireType::kLengthDelimited` if you
-// add in the length of the contents yourself, e.g. for string and bytes fields
-// by adding the lengths of any encoded strings to the return value or for
-// submessage fields by enumerating the fields you may encode into their
-// contents.
-constexpr size_t BufferSizeFor() { return 0; }
-template <typename... T>
-constexpr size_t BufferSizeFor(WireType type, T... tail) {
-  // tag_type + data + ...
-  return MaxVarintSize() +
-         (type == WireType::kVarint ? MaxVarintSize() :              //
-              type == WireType::k64Bit ? 8 :                         //
-                  type == WireType::k32Bit ? 4 : MaxVarintSize()) +  //
-         BufferSizeFor(tail...);
+// store encoded fields as `(tag, WireType)`, regardless of data values.  This
+// only makes sense for `WireType::kLengthDelimited` if you add in the length of
+// the contents yourself, e.g. for string and bytes fields by adding the lengths
+// of any encoded strings to the return value or for submessage fields by
+// enumerating the fields you may encode into their contents.
+constexpr size_t BufferSizeFor(uint64_t tag, WireType type) {
+  size_t buffer_size = VarintSize(MakeTagType(tag, type));
+  switch (type) {
+    case WireType::kVarint:
+      buffer_size += MaxVarintSize();
+      break;
+    case WireType::k64Bit:
+      buffer_size += size_t{8};
+      break;
+    case WireType::kLengthDelimited:
+      buffer_size += MaxVarintSize();
+      break;
+    case WireType::k32Bit:
+      buffer_size += size_t{4};
+      break;
+  }
+  return buffer_size;
 }
 
 // absl::Span<const char> represents a view into the un-processed space in a
diff --git a/absl/log/internal/strip.h b/absl/log/internal/strip.h
index 3e55010..60ef878 100644
--- a/absl/log/internal/strip.h
+++ b/absl/log/internal/strip.h
@@ -15,7 +15,8 @@
 // -----------------------------------------------------------------------------
 // File: log/internal/strip.h
 // -----------------------------------------------------------------------------
-//
+
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
 
 #ifndef ABSL_LOG_INTERNAL_STRIP_H_
 #define ABSL_LOG_INTERNAL_STRIP_H_
@@ -31,15 +32,6 @@
 // logging in subtly different ways for subtly different reasons (see below).
 #if defined(STRIP_LOG) && STRIP_LOG
 
-// Attribute for marking variables used in implementation details of logging
-// macros as unused, but only when `STRIP_LOG` is defined.
-// With `STRIP_LOG` on, not marking them triggers `-Wunused-but-set-variable`,
-// With `STRIP_LOG` off, marking them triggers `-Wused-but-marked-unused`.
-//
-// TODO(b/290784225): Replace this macro with attribute [[maybe_unused]] when
-// Abseil stops supporting C++14.
-#define ABSL_LOG_INTERNAL_ATTRIBUTE_UNUSED_IF_STRIP_LOG ABSL_ATTRIBUTE_UNUSED
-
 #define ABSL_LOGGING_INTERNAL_LOG_INFO ::absl::log_internal::NullStream()
 #define ABSL_LOGGING_INTERNAL_LOG_WARNING ::absl::log_internal::NullStream()
 #define ABSL_LOGGING_INTERNAL_LOG_ERROR ::absl::log_internal::NullStream()
@@ -62,8 +54,6 @@
 
 #else  // !defined(STRIP_LOG) || !STRIP_LOG
 
-#define ABSL_LOG_INTERNAL_ATTRIBUTE_UNUSED_IF_STRIP_LOG
-
 #define ABSL_LOGGING_INTERNAL_LOG_INFO \
   ::absl::log_internal::LogMessage(    \
       __FILE__, __LINE__, ::absl::log_internal::LogMessage::InfoTag{})
@@ -105,4 +95,6 @@
 #define ABSL_LOGGING_INTERNAL_DLOG_DFATAL ABSL_LOGGING_INTERNAL_LOG_DFATAL
 #define ABSL_LOGGING_INTERNAL_DLOG_LEVEL ABSL_LOGGING_INTERNAL_LOG_LEVEL
 
+#define ABSL_LOGGING_INTERNAL_LOG_DO_NOT_SUBMIT ABSL_LOGGING_INTERNAL_LOG_ERROR
+
 #endif  // ABSL_LOG_INTERNAL_STRIP_H_
diff --git a/absl/log/internal/structured.h b/absl/log/internal/structured.h
index 5223dbc..70b50e2 100644
--- a/absl/log/internal/structured.h
+++ b/absl/log/internal/structured.h
@@ -20,25 +20,32 @@
 #define ABSL_LOG_INTERNAL_STRUCTURED_H_
 
 #include <ostream>
+#include <string>
 
+#include "absl/base/attributes.h"
 #include "absl/base/config.h"
+#include "absl/functional/any_invocable.h"
 #include "absl/log/internal/log_message.h"
+#include "absl/log/internal/structured_proto.h"
+#include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace log_internal {
 
-class ABSL_MUST_USE_RESULT AsLiteralImpl final {
+class [[nodiscard]] AsLiteralImpl final {
  public:
-  explicit AsLiteralImpl(absl::string_view str) : str_(str) {}
+  explicit AsLiteralImpl(absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : str_(str) {}
   AsLiteralImpl(const AsLiteralImpl&) = default;
   AsLiteralImpl& operator=(const AsLiteralImpl&) = default;
 
  private:
   absl::string_view str_;
 
-  friend std::ostream& operator<<(std::ostream& os, AsLiteralImpl as_literal) {
+  friend std::ostream& operator<<(std::ostream& os,
+                                  AsLiteralImpl&& as_literal) {
     return os << as_literal.str_;
   }
   void AddToMessage(log_internal::LogMessage& m) {
@@ -51,6 +58,101 @@
   }
 };
 
+enum class StructuredStringType {
+  kLiteral,
+  kNotLiteral,
+};
+
+// Structured log data for a string and associated structured proto field,
+// both of which must outlive this object.
+template <StructuredStringType str_type>
+class [[nodiscard]] AsStructuredStringTypeImpl final {
+ public:
+  constexpr AsStructuredStringTypeImpl(
+      absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND,
+      StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : str_(str), field_(field) {}
+
+ private:
+  absl::string_view str_;
+  StructuredProtoField field_;
+
+  friend std::ostream& operator<<(std::ostream& os,
+                                  const AsStructuredStringTypeImpl& impl) {
+    return os << impl.str_;
+  }
+  void AddToMessage(LogMessage& m) const {
+    if (str_type == StructuredStringType::kLiteral) {
+      return m.CopyToEncodedBufferWithStructuredProtoField<
+          log_internal::LogMessage::StringType::kLiteral>(field_, str_);
+    } else {
+      return m.CopyToEncodedBufferWithStructuredProtoField<
+          log_internal::LogMessage::StringType::kNotLiteral>(field_, str_);
+    }
+  }
+  friend LogMessage& operator<<(LogMessage& m,
+                                const AsStructuredStringTypeImpl& impl) {
+    impl.AddToMessage(m);
+    return m;
+  }
+};
+
+using AsStructuredLiteralImpl =
+    AsStructuredStringTypeImpl<StructuredStringType::kLiteral>;
+using AsStructuredNotLiteralImpl =
+    AsStructuredStringTypeImpl<StructuredStringType::kNotLiteral>;
+
+// Structured log data for a stringifyable type T and associated structured
+// proto field, both of which must outlive this object.
+template <typename T>
+class [[nodiscard]] AsStructuredValueImpl final {
+ public:
+  using ValueFormatter = absl::AnyInvocable<std::string(T) const>;
+
+  constexpr AsStructuredValueImpl(
+      T value ABSL_ATTRIBUTE_LIFETIME_BOUND,
+      StructuredProtoField field ABSL_ATTRIBUTE_LIFETIME_BOUND,
+      ValueFormatter value_formatter =
+          [](T value) { return absl::StrCat(value); })
+      : value_(value),
+        field_(field),
+        value_formatter_(std::move(value_formatter)) {}
+
+ private:
+  T value_;
+  StructuredProtoField field_;
+  ValueFormatter value_formatter_;
+
+  friend std::ostream& operator<<(std::ostream& os,
+                                  const AsStructuredValueImpl& impl) {
+    return os << impl.value_formatter_(impl.value_);
+  }
+  void AddToMessage(LogMessage& m) const {
+    m.CopyToEncodedBufferWithStructuredProtoField<
+        log_internal::LogMessage::StringType::kNotLiteral>(
+        field_, value_formatter_(value_));
+  }
+  friend LogMessage& operator<<(LogMessage& m,
+                                const AsStructuredValueImpl& impl) {
+    impl.AddToMessage(m);
+    return m;
+  }
+};
+
+// Template deduction guide so `AsStructuredValueImpl(42, data)` works
+// without specifying the template type.
+template <typename T>
+AsStructuredValueImpl(T value, StructuredProtoField field)
+    -> AsStructuredValueImpl<T>;
+
+// Template deduction guide so `AsStructuredValueImpl(42, data, formatter)`
+// works without specifying the template type.
+template <typename T>
+AsStructuredValueImpl(
+    T value, StructuredProtoField field,
+    typename AsStructuredValueImpl<T>::ValueFormatter value_formatter)
+    -> AsStructuredValueImpl<T>;
+
 }  // namespace log_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/log/internal/structured_proto.cc b/absl/log/internal/structured_proto.cc
new file mode 100644
index 0000000..e3829e4
--- /dev/null
+++ b/absl/log/internal/structured_proto.cc
@@ -0,0 +1,115 @@
+//
+// Copyright 2024 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/log/internal/structured_proto.h"
+
+#include <cstdint>
+
+#include "absl/base/config.h"
+#include "absl/log/internal/proto.h"
+#include "absl/types/span.h"
+#include "absl/types/variant.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+namespace {
+
+// Handles protobuf-encoding a type contained inside
+// `StructuredProtoField::Varint`.
+struct VarintEncoderVisitor final {
+  template <typename T>
+  bool operator()(T value) const {
+    return EncodeVarint(field_number, value, &buf);
+  }
+
+  uint64_t field_number;
+  absl::Span<char>& buf;
+};
+
+// Handles protobuf-encoding a type contained inside
+// `StructuredProtoField::I64`.
+struct I64EncoderVisitor final {
+  bool operator()(uint64_t value) const {
+    return Encode64Bit(field_number, value, &buf);
+  }
+
+  bool operator()(int64_t value) const {
+    return Encode64Bit(field_number, value, &buf);
+  }
+
+  bool operator()(double value) const {
+    return EncodeDouble(field_number, value, &buf);
+  }
+
+  uint64_t field_number;
+  absl::Span<char>& buf;
+};
+
+// Handles protobuf-encoding a type contained inside
+// `StructuredProtoField::I32`.
+struct I32EncoderVisitor final {
+  bool operator()(uint32_t value) const {
+    return Encode32Bit(field_number, value, &buf);
+  }
+
+  bool operator()(int32_t value) const {
+    return Encode32Bit(field_number, value, &buf);
+  }
+
+  bool operator()(float value) const {
+    return EncodeFloat(field_number, value, &buf);
+  }
+
+  uint64_t field_number;
+  absl::Span<char>& buf;
+};
+
+// Handles protobuf-encoding a type contained inside `StructuredProtoField`.
+struct EncoderVisitor final {
+  bool operator()(StructuredProtoField::Varint varint) {
+    return absl::visit(VarintEncoderVisitor{field_number, buf}, varint);
+  }
+
+  bool operator()(StructuredProtoField::I64 i64) {
+    return absl::visit(I64EncoderVisitor{field_number, buf}, i64);
+  }
+
+  bool operator()(StructuredProtoField::LengthDelimited length_delimited) {
+    // No need for a visitor, since `StructuredProtoField::LengthDelimited` is
+    // just `absl::Span<const char>`.
+    return EncodeBytes(field_number, length_delimited, &buf);
+  }
+
+  bool operator()(StructuredProtoField::I32 i32) {
+    return absl::visit(I32EncoderVisitor{field_number, buf}, i32);
+  }
+
+  uint64_t field_number;
+  absl::Span<char>& buf;
+};
+
+}  // namespace
+
+bool EncodeStructuredProtoField(StructuredProtoField field,
+                                absl::Span<char>& buf) {
+  return absl::visit(EncoderVisitor{field.field_number, buf}, field.value);
+}
+
+}  // namespace log_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/structured_proto.h b/absl/log/internal/structured_proto.h
new file mode 100644
index 0000000..3ebc4be
--- /dev/null
+++ b/absl/log/internal/structured_proto.h
@@ -0,0 +1,107 @@
+// Copyright 2024 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: log/internal/structured_proto.h
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_
+#define ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_
+
+#include <cstddef>
+#include <cstdint>
+
+#include "absl/base/config.h"
+#include "absl/log/internal/proto.h"
+#include "absl/types/span.h"
+#include "absl/types/variant.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Sum type holding a single valid protobuf field suitable for encoding.
+struct StructuredProtoField final {
+  // Numeric type encoded with varint encoding:
+  // https://protobuf.dev/programming-guides/encoding/#varints
+  using Varint = absl::variant<uint64_t, int64_t, uint32_t, int32_t, bool>;
+
+  // Fixed-length 64-bit integer encoding:
+  // https://protobuf.dev/programming-guides/encoding/#non-varints
+  using I64 = absl::variant<uint64_t, int64_t, double>;
+
+  // Length-delimited record type (string, sub-message):
+  // https://protobuf.dev/programming-guides/encoding/#length-types
+  using LengthDelimited = absl::Span<const char>;
+
+  // Fixed-length 32-bit integer encoding:
+  // https://protobuf.dev/programming-guides/encoding/#non-varints
+  using I32 = absl::variant<uint32_t, int32_t, float>;
+
+  // Valid record type:
+  // https://protobuf.dev/programming-guides/encoding/#structure
+  using Value = absl::variant<Varint, I64, LengthDelimited, I32>;
+
+  // Field number for the protobuf value.
+  uint64_t field_number;
+
+  // Value to encode.
+  Value value;
+};
+
+// Estimates the number of bytes needed to encode `field` using
+// protobuf encoding.
+//
+// The returned value might be larger than the actual number of bytes needed.
+inline size_t BufferSizeForStructuredProtoField(StructuredProtoField field) {
+  // Visitor to estimate the number of bytes of one of the types contained
+  // inside `StructuredProtoField`.
+  struct BufferSizeVisitor final {
+    size_t operator()(StructuredProtoField::Varint /*unused*/) {
+      return BufferSizeFor(field_number, WireType::kVarint);
+    }
+
+    size_t operator()(StructuredProtoField::I64 /*unused*/) {
+      return BufferSizeFor(field_number, WireType::k64Bit);
+    }
+
+    size_t operator()(StructuredProtoField::LengthDelimited length_delimited) {
+      return BufferSizeFor(field_number, WireType::kLengthDelimited) +
+             length_delimited.size();
+    }
+
+    size_t operator()(StructuredProtoField::I32 /*unused*/) {
+      return BufferSizeFor(field_number, WireType::k32Bit);
+    }
+
+    uint64_t field_number;
+  };
+
+  return absl::visit(BufferSizeVisitor{field.field_number}, field.value);
+}
+
+// Encodes `field` into `buf` using protobuf encoding.
+//
+// On success, returns `true` and advances `buf` to the end of
+// the bytes consumed.
+//
+// On failure (if `buf` was too small), returns `false`.
+bool EncodeStructuredProtoField(StructuredProtoField field,
+                                absl::Span<char>& buf);
+
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_
diff --git a/absl/log/internal/structured_proto_test.cc b/absl/log/internal/structured_proto_test.cc
new file mode 100644
index 0000000..a4deebc
--- /dev/null
+++ b/absl/log/internal/structured_proto_test.cc
@@ -0,0 +1,120 @@
+//
+// Copyright 2024 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/log/internal/structured_proto.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+using ::testing::TestWithParam;
+
+struct StructuredProtoTestCase {
+  std::string test_name;
+  StructuredProtoField field;
+  std::vector<char> expected_encoded_field;
+};
+
+using StructuredProtoTest = TestWithParam<StructuredProtoTestCase>;
+
+TEST_P(StructuredProtoTest, Encoding) {
+  const StructuredProtoTestCase& test_case = GetParam();
+
+  // Greater than or equal to since BufferSizeForStructuredProtoField() is just
+  // an estimate of the data size and not an exact measurement.
+  ASSERT_GE(BufferSizeForStructuredProtoField(test_case.field),
+            test_case.expected_encoded_field.size());
+
+  std::vector<char> buf;
+  buf.resize(1024);
+
+  absl::Span<char> buf_span(buf);
+  EXPECT_TRUE(EncodeStructuredProtoField(test_case.field, buf_span));
+  size_t encoded_field_size = buf.size() - buf_span.size();
+
+  ASSERT_EQ(encoded_field_size, test_case.expected_encoded_field.size());
+  buf.resize(encoded_field_size);
+  EXPECT_EQ(buf, test_case.expected_encoded_field);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+    StructuredProtoTestSuiteInstantiation,
+    StructuredProtoTest,  // This is the name of your parameterized test
+    testing::ValuesIn<StructuredProtoTestCase>({
+        {
+            "Varint",
+            {
+                42,
+                StructuredProtoField::Value{
+                    absl::in_place_type<StructuredProtoField::Varint>,
+                    int32_t{23},
+                },
+            },
+            {'\xD0', '\x02', '\x17'},
+        },
+        {
+            "I64",
+            {
+                42,
+                StructuredProtoField::Value{
+                    absl::in_place_type<StructuredProtoField::I64>,
+                    int64_t{23},
+                },
+            },
+            {'\xD1', '\x02', '\x17', '\x00', '\x00', '\x00', '\x00', '\x00',
+             '\x00', '\x00'},
+        },
+        {
+            "LengthDelimited",
+            {
+                42,
+                // Use a string_view so the terminating NUL is excluded.
+                absl::string_view("Hello"),
+            },
+            {'\xD2', '\x02', '\x05', 'H', 'e', 'l', 'l', 'o'},
+        },
+        {
+            "I32",
+            {
+                42,
+                StructuredProtoField::Value{
+                    absl::in_place_type<StructuredProtoField::I32>,
+                    int32_t{23},
+                },
+            },
+            {'\xD5', '\x02', '\x17', '\x00', '\x00', '\x00'},
+        },
+    }),
+    [](const testing::TestParamInfo<StructuredProtoTest::ParamType>& info) {
+      return info.param.test_name;
+    });
+
+}  // namespace
+}  // namespace log_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/log/internal/vlog_config.cc b/absl/log/internal/vlog_config.cc
index b578850..f7c61be 100644
--- a/absl/log/internal/vlog_config.cc
+++ b/absl/log/internal/vlog_config.cc
@@ -207,7 +207,14 @@
   get_vmodule_info().erase(
       std::remove_if(++iter, get_vmodule_info().end(),
                      [module_pattern](const VModuleInfo& info) {
-                       return FNMatch(info.module_pattern, module_pattern);
+                       // Remove the previous pattern if it is less generic than
+                       // the new one. For example, if the new pattern
+                       // `module_pattern` is "foo*" and the previous pattern
+                       // `info.module_pattern` is "foo", we should remove the
+                       // previous pattern. Because the new pattern "foo*" will
+                       // match all the files that the previous pattern "foo"
+                       // matches.
+                       return FNMatch(module_pattern, info.module_pattern);
                      }),
       get_vmodule_info().cend());
   return old_log_level.value_or(global_v);
diff --git a/absl/log/internal/vlog_config.h b/absl/log/internal/vlog_config.h
index b6e322c..84e817a 100644
--- a/absl/log/internal/vlog_config.h
+++ b/absl/log/internal/vlog_config.h
@@ -34,6 +34,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
+#include "absl/base/nullability.h"
 #include "absl/base/optimization.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/strings/string_view.h"
@@ -45,7 +46,7 @@
 class SyntheticBinary;
 class VLogSite;
 
-int RegisterAndInitialize(VLogSite* v);
+int RegisterAndInitialize(VLogSite* absl_nonnull v);
 void UpdateVLogSites();
 constexpr int kUseFlag = (std::numeric_limits<int16_t>::min)();
 
@@ -60,7 +61,7 @@
 class VLogSite final {
  public:
   // `f` must not be destroyed until the program exits.
-  explicit constexpr VLogSite(const char* f)
+  explicit constexpr VLogSite(const char* absl_nonnull f)
       : file_(f), v_(kUninitialized), next_(nullptr) {}
   VLogSite(const VLogSite&) = delete;
   VLogSite& operator=(const VLogSite&) = delete;
@@ -93,7 +94,7 @@
   }
 
  private:
-  friend int log_internal::RegisterAndInitialize(VLogSite* v);
+  friend int log_internal::RegisterAndInitialize(VLogSite* absl_nonnull v);
   friend void log_internal::UpdateVLogSites();
   friend class log_internal::SyntheticBinary;
   static constexpr int kUninitialized = (std::numeric_limits<int>::max)();
@@ -116,7 +117,7 @@
   ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled5(int stale_v);
 
   // This object is too size-sensitive to use absl::string_view.
-  const char* const file_;
+  const char* absl_nonnull const file_;
   std::atomic<int> v_;
   std::atomic<VLogSite*> next_;
 };
@@ -130,7 +131,7 @@
 // Registers a site `v` to get updated as `vmodule` and `v` change.  Also
 // initializes the site based on their current values, and returns that result.
 // Does not allocate memory.
-int RegisterAndInitialize(VLogSite* v);
+int RegisterAndInitialize(VLogSite* absl_nonnull v);
 
 // Allocates memory.
 void UpdateVLogSites();
@@ -154,7 +155,8 @@
 void OnVLogVerbosityUpdate(std::function<void()> cb);
 
 // Does not allocate memory.
-VLogSite* SetVModuleListHeadForTestOnly(VLogSite* v);
+VLogSite* absl_nullable SetVModuleListHeadForTestOnly(
+    VLogSite* absl_nullable v);
 
 }  // namespace log_internal
 ABSL_NAMESPACE_END
diff --git a/absl/log/internal/voidify.h b/absl/log/internal/voidify.h
index 8f62da2..f42859e 100644
--- a/absl/log/internal/voidify.h
+++ b/absl/log/internal/voidify.h
@@ -16,13 +16,15 @@
 // File: log/internal/voidify.h
 // -----------------------------------------------------------------------------
 //
-// This class is used to explicitly ignore values in the conditional logging
-// macros. This avoids compiler warnings like "value computed is not used" and
-// "statement has no effect".
+// This class does the dispatching of the completed `absl::LogEntry` to
+// applicable `absl::LogSink`s, and is used to explicitly ignore values in the
+// conditional logging macros. This avoids compiler warnings like "value
+// computed is not used" and "statement has no effect".
 
 #ifndef ABSL_LOG_INTERNAL_VOIDIFY_H_
 #define ABSL_LOG_INTERNAL_VOIDIFY_H_
 
+#include "absl/base/attributes.h"
 #include "absl/base/config.h"
 
 namespace absl {
@@ -34,7 +36,11 @@
   // This has to be an operator with a precedence lower than << but higher than
   // ?:
   template <typename T>
-  void operator&&(const T&) const&& {}
+  ABSL_ATTRIBUTE_COLD void operator&&(T&& message) const&& {
+    // The dispatching of the completed `absl::LogEntry` to applicable
+    // `absl::LogSink`s happens here.
+    message.Flush();
+  }
 };
 
 }  // namespace log_internal
diff --git a/absl/log/log.h b/absl/log/log.h
index a4e1d1f..f1cab9d 100644
--- a/absl/log/log.h
+++ b/absl/log/log.h
@@ -34,6 +34,13 @@
 //   running registered error handlers.
 // * The `DFATAL` pseudo-severity level is defined as `FATAL` in debug mode and
 //   as `ERROR` otherwise.
+// * The `DO_NOT_SUBMIT` pseudo-severity level is an alias for `ERROR`, and is
+//   intended for debugging statements that won't be submitted.  The name is
+//   chosen to be easy to spot in review and with tools in order to ensure that
+//   such statements aren't inadvertently checked in.
+//   The contract is that **it may not be checked in**, meaning that no
+//   in-contract uses will be affected if we decide in the future to remove it
+//   or change what it does.
 // Some preprocessor shenanigans are used to ensure that e.g. `LOG(INFO)` has
 // the same meaning even if a local symbol or preprocessor macro named `INFO` is
 // defined.  To specify a severity level using an expression instead of a
@@ -194,6 +201,8 @@
 //   LOG(INFO) << std::hex << 0xdeadbeef;  // logs "0xdeadbeef"
 //   LOG(INFO) << 0xdeadbeef;              // logs "3735928559"
 
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
 #ifndef ABSL_LOG_LOG_H_
 #define ABSL_LOG_LOG_H_
 
@@ -260,44 +269,55 @@
   ABSL_LOG_INTERNAL_DLOG_IF_IMPL(_##severity, condition)
 
 // LOG_EVERY_N
+// LOG_FIRST_N
+// LOG_EVERY_POW_2
+// LOG_EVERY_N_SEC
 //
-// An instance of `LOG_EVERY_N` increments a hidden zero-initialized counter
-// every time execution passes through it and logs the specified message when
-// the counter's value is a multiple of `n`, doing nothing otherwise.  Each
-// instance has its own counter.  The counter's value can be logged by streaming
-// the symbol `COUNTER`.  `LOG_EVERY_N` is thread-safe.
-// Example:
+// These "stateful" macros log conditionally based on a hidden counter or timer.
+// When the condition is false and no logging is done, streamed operands aren't
+// evaluated either.  Each instance has its own state (i.e. counter, timer)
+// that's independent of other instances of the macros.  The macros in this
+// family are thread-safe in the sense that they are meant to be called
+// concurrently and will not invoke undefined behavior, however their
+// implementation prioritizes efficiency over exactness and may occasionally log
+// more or less often than specified.
+//
+//   * `LOG_EVERY_N` logs the first time and once every `n` times thereafter.
+//   * `LOG_FIRST_N` logs the first `n` times and then stops.
+//   * `LOG_EVERY_POW_2` logs the first, second, fourth, eighth, etc. times.
+//   * `LOG_EVERY_N_SEC` logs the first time and no more than once every `n`
+//     seconds thereafter.  `n` is passed as a floating point value.
+//
+// The `LOG_IF`... variations with an extra condition evaluate the specified
+// condition first and short-circuit if it is false.  For example, an evaluation
+// of `LOG_IF_FIRST_N` does not count against the first `n` if the specified
+// condition is false.  Stateful `VLOG`... variations likewise short-circuit
+// if `VLOG` is disabled.
+//
+// An approximate count of the number of times a particular instance's stateful
+// condition has been evaluated (i.e. excluding those where a specified `LOG_IF`
+// condition was false) can be included in the logged message by streaming the
+// symbol `COUNTER`.
+//
+// The `n` parameter need not be a constant.  Conditional logging following a
+// change to `n` isn't fully specified, but it should converge on the new value
+// within roughly `max(old_n, new_n)` evaluations or seconds.
+//
+// Examples:
 //
 //   LOG_EVERY_N(WARNING, 1000) << "Got a packet with a bad CRC (" << COUNTER
 //                              << " total)";
-#define LOG_EVERY_N(severity, n) \
-  ABSL_LOG_INTERNAL_LOG_EVERY_N_IMPL(_##severity, n)
-
-// LOG_FIRST_N
-//
-// `LOG_FIRST_N` behaves like `LOG_EVERY_N` except that the specified message is
-// logged when the counter's value is less than `n`.  `LOG_FIRST_N` is
-// thread-safe.
-#define LOG_FIRST_N(severity, n) \
-  ABSL_LOG_INTERNAL_LOG_FIRST_N_IMPL(_##severity, n)
-
-// LOG_EVERY_POW_2
-//
-// `LOG_EVERY_POW_2` behaves like `LOG_EVERY_N` except that the specified
-// message is logged when the counter's value is a power of 2.
-// `LOG_EVERY_POW_2` is thread-safe.
-#define LOG_EVERY_POW_2(severity) \
-  ABSL_LOG_INTERNAL_LOG_EVERY_POW_2_IMPL(_##severity)
-
-// LOG_EVERY_N_SEC
-//
-// An instance of `LOG_EVERY_N_SEC` uses a hidden state variable to log the
-// specified message at most once every `n_seconds`.  A hidden counter of
-// executions (whether a message is logged or not) is also maintained and can be
-// logged by streaming the symbol `COUNTER`.  `LOG_EVERY_N_SEC` is thread-safe.
-// Example:
 //
 //   LOG_EVERY_N_SEC(INFO, 2.5) << "Got " << COUNTER << " cookies so far";
+//
+//   LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << COUNTER
+//                                           << "th big cookie";
+#define LOG_EVERY_N(severity, n) \
+  ABSL_LOG_INTERNAL_LOG_EVERY_N_IMPL(_##severity, n)
+#define LOG_FIRST_N(severity, n) \
+  ABSL_LOG_INTERNAL_LOG_FIRST_N_IMPL(_##severity, n)
+#define LOG_EVERY_POW_2(severity) \
+  ABSL_LOG_INTERNAL_LOG_EVERY_POW_2_IMPL(_##severity)
 #define LOG_EVERY_N_SEC(severity, n_seconds) \
   ABSL_LOG_INTERNAL_LOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)
 
@@ -328,13 +348,6 @@
 #define VLOG_EVERY_N_SEC(severity, n_seconds) \
   ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(severity, n_seconds)
 
-// `LOG_IF_EVERY_N` and friends behave as the corresponding `LOG_EVERY_N`
-// but neither increment a counter nor log a message if condition is false (as
-// `LOG_IF`).
-// Example:
-//
-//   LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << COUNTER
-//                                           << "th big cookie";
 #define LOG_IF_EVERY_N(severity, condition, n) \
   ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_IMPL(_##severity, condition, n)
 #define LOG_IF_FIRST_N(severity, condition, n) \
diff --git a/absl/log/log_basic_test_impl.inc b/absl/log/log_basic_test_impl.inc
index 7baf5e7..c4b4e24 100644
--- a/absl/log/log_basic_test_impl.inc
+++ b/absl/log/log_basic_test_impl.inc
@@ -13,6 +13,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
 // The testcases in this file are expected to pass or be skipped with any value
 // of ABSL_MIN_LOG_LEVEL
 
@@ -111,7 +113,7 @@
             ENCODED_MESSAGE(MatchesEvent(
                 Eq(__FILE__), Eq(log_line), InMatchWindow(),
                 Eq(logging::proto::INFO), Eq(absl::base_internal::GetTID()),
-                ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))),
+                ElementsAre(ValueWithLiteral(Eq("hello world"))))),
             Stacktrace(IsEmpty()))));
   }
 
@@ -142,7 +144,7 @@
             ENCODED_MESSAGE(MatchesEvent(
                 Eq(__FILE__), Eq(log_line), InMatchWindow(),
                 Eq(logging::proto::WARNING), Eq(absl::base_internal::GetTID()),
-                ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))),
+                ElementsAre(ValueWithLiteral(Eq("hello world"))))),
             Stacktrace(IsEmpty()))));
   }
 
@@ -173,7 +175,38 @@
             ENCODED_MESSAGE(MatchesEvent(
                 Eq(__FILE__), Eq(log_line), InMatchWindow(),
                 Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),
-                ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))),
+                ElementsAre(ValueWithLiteral(Eq("hello world"))))),
+            Stacktrace(IsEmpty()))));
+  }
+
+  test_sink.StartCapturingLogs();
+  do_log();
+}
+
+TEST_P(BasicLogTest, DoNotSubmit) {
+  absl::log_internal::ScopedMinLogLevel scoped_min_log_level(GetParam());
+
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  const int log_line = __LINE__ + 1;
+  auto do_log = [] { ABSL_TEST_LOG(DO_NOT_SUBMIT) << "hello world"; };
+
+  if (LoggingEnabledAt(absl::LogSeverity::kError)) {
+    EXPECT_CALL(
+        test_sink,
+        Send(AllOf(
+            SourceFilename(Eq(__FILE__)),
+            SourceBasename(Eq("log_basic_test_impl.inc")),
+            SourceLine(Eq(log_line)), Prefix(IsTrue()),
+            LogSeverity(Eq(absl::LogSeverity::kError)),
+            Timestamp(InMatchWindow()),
+            ThreadID(Eq(absl::base_internal::GetTID())),
+            TextMessage(Eq("hello world")),
+            Verbosity(Eq(absl::LogEntry::kNoVerbosityLevel)),
+            ENCODED_MESSAGE(MatchesEvent(
+                Eq(__FILE__), Eq(log_line), InMatchWindow(),
+                Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),
+                ElementsAre(ValueWithLiteral(Eq("hello world"))))),
             Stacktrace(IsEmpty()))));
   }
 
@@ -226,8 +259,7 @@
                              Eq(__FILE__), Eq(log_line), InMatchWindow(),
                              Eq(logging::proto::FATAL),
                              Eq(absl::base_internal::GetTID()),
-                             ElementsAre(EqualsProto(
-                                 R"pb(literal: "hello world")pb")))),
+                             ElementsAre(ValueWithLiteral(Eq("hello world"))))),
                          Stacktrace(IsEmpty()))))
               .WillOnce(DeathTestExpectedLogging());
 
@@ -246,8 +278,7 @@
                              Eq(__FILE__), Eq(log_line), InMatchWindow(),
                              Eq(logging::proto::FATAL),
                              Eq(absl::base_internal::GetTID()),
-                             ElementsAre(EqualsProto(
-                                 R"pb(literal: "hello world")pb")))),
+                             ElementsAre(ValueWithLiteral(Eq("hello world"))))),
                          Stacktrace(Not(IsEmpty())))))
               .WillOnce(DeathTestExpectedLogging());
         }
@@ -288,8 +319,7 @@
                              Eq(__FILE__), Eq(log_line), InMatchWindow(),
                              Eq(logging::proto::FATAL),
                              Eq(absl::base_internal::GetTID()),
-                             ElementsAre(EqualsProto(
-                                 R"pb(literal: "hello world")pb")))),
+                             ElementsAre(ValueWithLiteral(Eq("hello world"))))),
                          Stacktrace(IsEmpty()))))
               .WillOnce(DeathTestExpectedLogging());
         }
@@ -325,7 +355,7 @@
             ENCODED_MESSAGE(MatchesEvent(
                 Eq(__FILE__), Eq(log_line), InMatchWindow(),
                 Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),
-                ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))),
+                ElementsAre(ValueWithLiteral(Eq("hello world"))))),
             Stacktrace(IsEmpty()))));
   }
 
@@ -368,8 +398,7 @@
                              Eq(__FILE__), Eq(log_line), InMatchWindow(),
                              Eq(logging::proto::FATAL),
                              Eq(absl::base_internal::GetTID()),
-                             ElementsAre(EqualsProto(
-                                 R"pb(literal: "hello world")pb")))),
+                             ElementsAre(ValueWithLiteral(Eq("hello world"))))),
                          Stacktrace(IsEmpty()))))
               .WillOnce(DeathTestExpectedLogging());
 
@@ -388,8 +417,7 @@
                              Eq(__FILE__), Eq(log_line), InMatchWindow(),
                              Eq(logging::proto::FATAL),
                              Eq(absl::base_internal::GetTID()),
-                             ElementsAre(EqualsProto(
-                                 R"pb(literal: "hello world")pb")))),
+                             ElementsAre(ValueWithLiteral(Eq("hello world"))))),
                          Stacktrace(Not(IsEmpty())))))
               .WillOnce(DeathTestExpectedLogging());
         }
@@ -454,7 +482,7 @@
                          ? logging::proto::ERROR
                          : 0),
                   Eq(absl::base_internal::GetTID()),
-                  ElementsAre(EqualsProto(R"pb(literal: "hello world")pb")))),
+                  ElementsAre(ValueWithLiteral(Eq("hello world"))))),
               Stacktrace(IsEmpty()))));
     }
     test_sink.StartCapturingLogs();
@@ -500,8 +528,7 @@
                              Eq(__FILE__), Eq(log_line), InMatchWindow(),
                              Eq(logging::proto::FATAL),
                              Eq(absl::base_internal::GetTID()),
-                             ElementsAre(EqualsProto(
-                                 R"pb(literal: "hello world")pb")))),
+                             ElementsAre(ValueWithLiteral(Eq("hello world"))))),
                          Stacktrace(IsEmpty()))))
               .WillOnce(DeathTestExpectedLogging());
 
@@ -519,8 +546,7 @@
                              Eq(__FILE__), Eq(log_line), InMatchWindow(),
                              Eq(logging::proto::FATAL),
                              Eq(absl::base_internal::GetTID()),
-                             ElementsAre(EqualsProto(
-                                 R"pb(literal: "hello world")pb")))),
+                             ElementsAre(ValueWithLiteral(Eq("hello world"))))),
                          Stacktrace(Not(IsEmpty())))))
               .WillOnce(DeathTestExpectedLogging());
         }
diff --git a/absl/log/log_entry.cc b/absl/log/log_entry.cc
deleted file mode 100644
index fe58a57..0000000
--- a/absl/log/log_entry.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Copyright 2022 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/log/log_entry.h"
-
-#include "absl/base/config.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr int LogEntry::kNoVerbosityLevel;
-constexpr int LogEntry::kNoVerboseLevel;
-#endif
-
-// https://github.com/abseil/abseil-cpp/issues/1465
-// CMake builds on Apple platforms error when libraries are empty.
-// Our CMake configuration can avoid this error on header-only libraries,
-// but since this library is conditionally empty, including a single
-// variable is an easy workaround.
-#ifdef __APPLE__
-namespace log_internal {
-extern const char kAvoidEmptyLogEntryLibraryWarning;
-const char kAvoidEmptyLogEntryLibraryWarning = 0;
-}  // namespace log_internal
-#endif  // __APPLE__
-
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/log/log_format_test.cc b/absl/log/log_format_test.cc
index beee966..6b7d1e5 100644
--- a/absl/log/log_format_test.cc
+++ b/absl/log/log_format_test.cc
@@ -15,12 +15,14 @@
 
 #include <math.h>
 
+#include <cstring>
 #include <iomanip>
 #include <ios>
 #include <limits>
 #include <ostream>
 #include <sstream>
 #include <string>
+#include <string_view>
 #include <type_traits>
 
 #ifdef __ANDROID__
@@ -28,6 +30,7 @@
 #endif
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 #include "absl/log/check.h"
 #include "absl/log/internal/test_matchers.h"
 #include "absl/log/log.h"
@@ -44,6 +47,7 @@
 using ::absl::log_internal::RawEncodedMessage;
 using ::absl::log_internal::TextMessage;
 using ::absl::log_internal::TextPrefix;
+using ::testing::_;
 using ::testing::AllOf;
 using ::testing::AnyOf;
 using ::testing::Each;
@@ -96,11 +100,11 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("x")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "x")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("x")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("x"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -113,16 +117,44 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("\xee")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "\xee")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("\xee")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("\xee"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
 }
 
+TEST(WideCharLogFormatTest, Printable) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("€")),
+                                    ENCODED_MESSAGE(HasValues(
+                                        ElementsAre(ValueWithStr(Eq("€"))))))));
+
+  test_sink.StartCapturingLogs();
+  const wchar_t value = L'\u20AC';
+  LOG(INFO) << value;
+}
+
+TEST(WideCharLogFormatTest, Unprintable) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  // Using NEL (Next Line) Unicode character (U+0085).
+  // It is encoded as "\xC2\x85" in UTF-8.
+  constexpr wchar_t wide_value = L'\u0085';
+  constexpr char value[] = "\xC2\x85";
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(value)),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq(value))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << wide_value;
+}
+
 template <typename T>
 class UnsignedIntLogFormatTest : public testing::Test {};
 using UnsignedIntTypes = Types<unsigned short, unsigned int,        // NOLINT
@@ -136,11 +168,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("224")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "224")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("224")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("224"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -155,11 +188,11 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value.bits;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("42")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "42")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("42")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("42"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value.bits;
@@ -178,11 +211,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("224")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "224")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("224")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("224"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -195,11 +229,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("-112")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "-112")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("-112")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-112"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -214,11 +249,11 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value.bits;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("21")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "21")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("21")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("21"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value.bits;
@@ -233,11 +268,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value.bits;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("-21")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "-21")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("-21")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-21"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value.bits;
@@ -274,11 +310,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("224")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "224")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("224")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("224"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -293,11 +330,11 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value.bits;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("42")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "42")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("42")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("42"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value.bits;
@@ -333,11 +370,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("224")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "224")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("224")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("224"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -350,11 +388,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("-112")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "-112")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("-112")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-112"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -369,11 +408,11 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value.bits;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("21")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "21")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("21")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("21"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value.bits;
@@ -388,11 +427,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value.bits;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("-21")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "-21")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("-21")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-21"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value.bits;
@@ -409,8 +449,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("6.02e+23")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "6.02e+23")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("6.02e+23"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -426,8 +466,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("-6.02e+23")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "-6.02e+23")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("-6.02e+23"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -443,8 +483,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("6.02e-23")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "6.02e-23")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("6.02e-23"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -460,8 +500,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("6.02e+23")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "6.02e+23")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("6.02e+23"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -477,8 +517,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("-6.02e+23")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "-6.02e+23")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("-6.02e+23"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -494,8 +534,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("6.02e-23")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "6.02e-23")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("6.02e-23"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -513,11 +553,11 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("0")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "0")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("0")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("0"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -530,11 +570,11 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("1")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "1")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("1")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("1"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -547,11 +587,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(AnyOf(Eq("inf"), Eq("Inf"))),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "inf")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(AnyOf(Eq("inf"), Eq("Inf"))),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("inf"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -564,11 +605,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(AnyOf(Eq("-inf"), Eq("-Inf"))),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "-inf")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(AnyOf(Eq("-inf"), Eq("-Inf"))),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("-inf"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -581,11 +623,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(AnyOf(Eq("nan"), Eq("NaN"))),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "nan")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(AnyOf(Eq("nan"), Eq("NaN"))),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("nan"))))))));
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
 }
@@ -602,24 +645,20 @@
   // streaming it. #ifdefing out just the relevant line breaks the MSVC build,
   // so duplicate the entire EXPECT_CALL.
 #ifdef __riscv
-  EXPECT_CALL(
-      test_sink,
-      Send(AllOf(
-          TextMessage(AnyOf(Eq("-nan"), Eq("nan"), Eq("NaN"), Eq("-nan(ind)"))),
-          ENCODED_MESSAGE(HasValues(
-              ElementsAre(AnyOf(EqualsProto(R"pb(str: "-nan")pb"),
-                                EqualsProto(R"pb(str: "nan")pb"),
-                                EqualsProto(R"pb(str: "-nan(ind)")pb"))))))));
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(AnyOf(Eq("-nan"), Eq("nan"), Eq("NaN"),
+                                           Eq("-nan(ind)"))),
+                         ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf(
+                             ValueWithStr(Eq("-nan")), ValueWithStr(Eq("nan")),
+                             ValueWithStr(Eq("-nan(ind)")))))))));
 #else
-  EXPECT_CALL(
-      test_sink,
-      Send(AllOf(
-          TextMessage(MatchesOstream(comparison_stream)),
-          TextMessage(AnyOf(Eq("-nan"), Eq("nan"), Eq("NaN"), Eq("-nan(ind)"))),
-          ENCODED_MESSAGE(HasValues(
-              ElementsAre(AnyOf(EqualsProto(R"pb(str: "-nan")pb"),
-                                EqualsProto(R"pb(str: "nan")pb"),
-                                EqualsProto(R"pb(str: "-nan(ind)")pb"))))))));
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(AnyOf(Eq("-nan"), Eq("nan"), Eq("NaN"),
+                                           Eq("-nan(ind)"))),
+                         ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf(
+                             ValueWithStr(Eq("-nan")), ValueWithStr(Eq("nan")),
+                             ValueWithStr(Eq("-nan(ind)")))))))));
 #endif
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -627,7 +666,7 @@
 
 template <typename T>
 class VoidPtrLogFormatTest : public testing::Test {};
-using VoidPtrTypes = Types<void *, const void *>;
+using VoidPtrTypes = Types<void*, const void*>;
 TYPED_TEST_SUITE(VoidPtrLogFormatTest, VoidPtrTypes);
 
 TYPED_TEST(VoidPtrLogFormatTest, Null) {
@@ -654,14 +693,13 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(
-      test_sink,
-      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                 TextMessage(AnyOf(Eq("0xdeadbeef"), Eq("DEADBEEF"),
-                                   Eq("00000000DEADBEEF"))),
-                 ENCODED_MESSAGE(HasValues(ElementsAre(
-                     AnyOf(EqualsProto(R"pb(str: "0xdeadbeef")pb"),
-                           EqualsProto(R"pb(str: "00000000DEADBEEF")pb"))))))));
+  EXPECT_CALL(test_sink,
+              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                         TextMessage(AnyOf(Eq("0xdeadbeef"), Eq("DEADBEEF"),
+                                           Eq("00000000DEADBEEF"))),
+                         ENCODED_MESSAGE(HasValues(ElementsAre(
+                             AnyOf(ValueWithStr(Eq("0xdeadbeef")),
+                                   ValueWithStr(Eq("00000000DEADBEEF")))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -669,11 +707,10 @@
 
 template <typename T>
 class VolatilePtrLogFormatTest : public testing::Test {};
-using VolatilePtrTypes =
-    Types<volatile void*, const volatile void*, volatile char*,
-          const volatile char*, volatile signed char*,
-          const volatile signed char*, volatile unsigned char*,
-          const volatile unsigned char*>;
+using VolatilePtrTypes = Types<
+    volatile void*, const volatile void*, volatile char*, const volatile char*,
+    volatile signed char*, const volatile signed char*, volatile unsigned char*,
+    const volatile unsigned char*, volatile wchar_t*, const volatile wchar_t*>;
 TYPED_TEST_SUITE(VolatilePtrLogFormatTest, VolatilePtrTypes);
 
 TYPED_TEST(VolatilePtrLogFormatTest, Null) {
@@ -683,11 +720,21 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("false")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "false")pb")))))));
+  // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1147r1.html
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202302L
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(AnyOf(Eq("(nil)"), Eq("0"), Eq("0x0"),
+                                   Eq("00000000"), Eq("0000000000000000"))))));
+#else
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("false")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("false"))))))));
+#endif
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -700,11 +747,23 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
+  // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1147r1.html
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202302L
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("true")),
+                         TextMessage(AnyOf(Eq("0xdeadbeef"), Eq("DEADBEEF"),
+                                           Eq("00000000DEADBEEF"))),
                          ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "true")pb")))))));
+                             AnyOf(ValueWithStr(Eq("0xdeadbeef")),
+                                   ValueWithStr(Eq("00000000DEADBEEF")))))))));
+#else
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("true")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("true"))))))));
+#endif
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -729,9 +788,8 @@
       test_sink,
       Send(AllOf(
           // `MatchesOstream` deliberately omitted since we deliberately differ.
-          TextMessage(Eq("(null)")),
-          ENCODED_MESSAGE(
-              HasValues(ElementsAre(EqualsProto(R"pb(str: "(null)")pb")))))));
+          TextMessage(Eq("(null)")), ENCODED_MESSAGE(HasValues(ElementsAre(
+                                         ValueWithStr(Eq("(null)"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -745,11 +803,44 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("value")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "value")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("value")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("value"))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+template <typename T>
+class WideCharPtrLogFormatTest : public testing::Test {};
+using WideCharPtrTypes = Types<wchar_t, const wchar_t>;
+TYPED_TEST_SUITE(WideCharPtrLogFormatTest, WideCharPtrTypes);
+
+TYPED_TEST(WideCharPtrLogFormatTest, Null) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  TypeParam* const value = nullptr;
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("(null)")),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq("(null)"))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(WideCharPtrLogFormatTest, NonNull) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  TypeParam data[] = {'v', 'a', 'l', 'u', 'e', '\0'};
+  TypeParam* const value = data;
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("value")),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq("value"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -762,11 +853,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("true")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "true")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("true")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("true"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -779,11 +871,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("false")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "false")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("false")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("false"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -798,13 +891,24 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("value")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(literal: "value")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithLiteral(Eq("value"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << "value";
 }
 
+TEST(LogFormatTest, WideStringLiteral) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("value")),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithLiteral(Eq("value"))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << L"value";
+}
+
 TEST(LogFormatTest, CharArray) {
   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
 
@@ -812,16 +916,204 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("value")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "value")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("value")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("value"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
 }
 
+TEST(LogFormatTest, WideCharArray) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  wchar_t value[] = L"value";
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("value")),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq("value"))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+// Comprehensive test string for validating wchar_t to UTF-8 conversion.
+// See details in absl/strings/internal/utf8_test.cc.
+//
+// clang-format off
+#define ABSL_LOG_INTERNAL_WIDE_LITERAL L"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩‍❤️‍💋‍👨 中"
+#define ABSL_LOG_INTERNAL_UTF8_LITERAL u8"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩‍❤️‍💋‍👨 中"
+// clang-format on
+
+absl::string_view GetUtf8TestString() {
+  // `u8""` forces UTF-8 encoding; MSVC will default to e.g. CP1252 (and warn)
+  // without it. However, the resulting character type differs between pre-C++20
+  // (`char`) and C++20 (`char8_t`). So we reinterpret_cast to `char*` and wrap
+  // it in a `string_view`.
+  static const absl::string_view kUtf8TestString(
+      reinterpret_cast<const char*>(ABSL_LOG_INTERNAL_UTF8_LITERAL),
+      sizeof(ABSL_LOG_INTERNAL_UTF8_LITERAL) - 1);
+  return kUtf8TestString;
+}
+
+template <typename T>
+class WideStringLogFormatTest : public testing::Test {};
+using StringTypes =
+    Types<std::wstring, const std::wstring, wchar_t[], const wchar_t*>;
+TYPED_TEST_SUITE(WideStringLogFormatTest, StringTypes);
+
+TYPED_TEST(WideStringLogFormatTest, NonLiterals) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  TypeParam value = ABSL_LOG_INTERNAL_WIDE_LITERAL;
+  absl::string_view utf8_value = GetUtf8TestString();
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq(utf8_value))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(WideStringLogFormatTest, StringView) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  std::wstring_view value = ABSL_LOG_INTERNAL_WIDE_LITERAL;
+  absl::string_view utf8_value = GetUtf8TestString();
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq(utf8_value))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(WideStringLogFormatTest, Literal) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  absl::string_view utf8_value = GetUtf8TestString();
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithLiteral(Eq(utf8_value))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << ABSL_LOG_INTERNAL_WIDE_LITERAL;
+}
+
+#undef ABSL_LOG_INTERNAL_WIDE_LITERAL
+#undef ABSL_LOG_INTERNAL_UTF8_LITERAL
+
+TYPED_TEST(WideStringLogFormatTest, IsolatedLowSurrogatesAreReplaced) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  TypeParam value = L"AAA \xDC00 BBB";
+  // NOLINTNEXTLINE(readability/utf8)
+  absl::string_view utf8_value = "AAA � BBB";
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq(utf8_value))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(WideStringLogFormatTest,
+           DISABLED_IsolatedHighSurrogatesAreReplaced) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  TypeParam value = L"AAA \xD800 BBB";
+  // NOLINTNEXTLINE(readability/utf8)
+  absl::string_view utf8_value = "AAA � BBB";
+  // Currently, this is "AAA \xF0\x90 BBB".
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq(utf8_value))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(WideStringLogFormatTest,
+           DISABLED_ConsecutiveHighSurrogatesAreReplaced) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  TypeParam value = L"AAA \xD800\xD800 BBB";
+  // NOLINTNEXTLINE(readability/utf8)
+  absl::string_view utf8_value = "AAA �� BBB";
+  // Currently, this is "AAA \xF0\x90\xF0\x90 BBB".
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq(utf8_value))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(WideStringLogFormatTest,
+           DISABLED_HighHighLowSurrogateSequencesAreReplaced) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  TypeParam value = L"AAA \xD800\xD800\xDC00 BBB";
+  // NOLINTNEXTLINE(readability/utf8)
+  absl::string_view utf8_value = "AAA �𐀀 BBB";
+  // Currently, this is "AAA \xF0\x90𐀀 BBB".
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq(utf8_value))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(WideStringLogFormatTest,
+           DISABLED_TrailingHighSurrogatesAreReplaced) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  TypeParam value = L"AAA \xD800";
+  // NOLINTNEXTLINE(readability/utf8)
+  absl::string_view utf8_value = "AAA �";
+  // Currently, this is "AAA \xF0\x90".
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq(utf8_value)),
+                                    ENCODED_MESSAGE(HasValues(ElementsAre(
+                                        ValueWithStr(Eq(utf8_value))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TYPED_TEST(WideStringLogFormatTest, EmptyWideString) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  TypeParam value = L"";
+
+  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("")),
+                                    ENCODED_MESSAGE(HasValues(
+                                        ElementsAre(ValueWithStr(Eq(""))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << value;
+}
+
+TEST(WideStringLogFormatTest, MixedNarrowAndWideStrings) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(test_sink, Log(_, _, "1234"));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << "1" << L"2" << "3" << L"4";
+}
+
 class CustomClass {};
 std::ostream& operator<<(std::ostream& os, const CustomClass&) {
   return os << "CustomClass{}";
@@ -838,7 +1130,7 @@
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("CustomClass{}")),
                          ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "CustomClass{}")pb")))))));
+                             ValueWithStr(Eq("CustomClass{}"))))))));
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
 }
@@ -863,8 +1155,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("CustomClassNonCopyable{}")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(EqualsProto(
-                             R"pb(str: "CustomClassNonCopyable{}")pb")))))));
+                         ENCODED_MESSAGE(HasValues(ElementsAre(
+                             ValueWithStr(Eq("CustomClassNonCopyable{}"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value;
@@ -888,8 +1180,8 @@
   EXPECT_CALL(
       test_sink,
       Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))),
-                 ENCODED_MESSAGE(HasValues(
-                     ElementsAre(EqualsProto(R"pb(str: "(10, 20)")pb")))))));
+                 ENCODED_MESSAGE(
+                     HasValues(ElementsAre(ValueWithStr(Eq("(10, 20)"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << p;
@@ -919,8 +1211,8 @@
   EXPECT_CALL(
       test_sink,
       Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))),
-                 ENCODED_MESSAGE(HasValues(
-                     ElementsAre(EqualsProto(R"pb(str: "(10, 20)")pb")))))));
+                 ENCODED_MESSAGE(
+                     HasValues(ElementsAre(ValueWithStr(Eq("(10, 20)"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << p;
@@ -939,10 +1231,11 @@
 
   PointStreamsNothing p;
 
-  EXPECT_CALL(test_sink, Send(AllOf(TextMessage(Eq("77")),
-                                    TextMessage(Eq(absl::StrCat(p, 77))),
-                                    ENCODED_MESSAGE(HasValues(ElementsAre(
-                                        EqualsProto(R"pb(str: "77")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(Eq("77")), TextMessage(Eq(absl::StrCat(p, 77))),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << p << 77;
@@ -967,9 +1260,8 @@
   EXPECT_CALL(
       test_sink,
       Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))),
-                 ENCODED_MESSAGE(HasValues(
-                     ElementsAre(EqualsProto(R"pb(str: "(")pb"),
-                                 EqualsProto(R"pb(str: "10, 20)")pb")))))));
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     ValueWithStr(Eq("(")), ValueWithStr(Eq("10, 20)"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << p;
@@ -984,15 +1276,14 @@
                     << std::boolalpha << value << " "    //
                     << std::noboolalpha << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("1 true 1")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "1")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "true")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "1")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("1 true 1")),
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     ValueWithStr(Eq("1")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("true")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("1"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::noboolalpha << value << " "  //
@@ -1009,15 +1300,14 @@
                     << std::boolalpha << value << " "    //
                     << std::noboolalpha << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("0 false 0")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "0")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "false")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "0")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("0 false 0")),
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     ValueWithStr(Eq("0")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("false")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("0"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::noboolalpha << value << " "  //
@@ -1034,15 +1324,14 @@
                     << std::showpoint << value << " "    //
                     << std::noshowpoint << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("77 77.0000 77")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "77")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "77.0000")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "77")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("77 77.0000 77")),
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     ValueWithStr(Eq("77")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("77.0000")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::noshowpoint << value << " "  //
@@ -1062,12 +1351,10 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("77 +77 77")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "77")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "+77")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "77")pb")))))));
+                         ENCODED_MESSAGE(HasValues(ElementsAre(
+                             ValueWithStr(Eq("77")), ValueWithLiteral(Eq(" ")),
+                             ValueWithStr(Eq("+77")), ValueWithLiteral(Eq(" ")),
+                             ValueWithStr(Eq("77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::noshowpos << value << " "  //
@@ -1084,15 +1371,14 @@
                     << std::uppercase << value << " "    //
                     << std::nouppercase << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("7.7e+07 7.7E+07 7.7e+07")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "7.7e+07")pb"),
-                             EqualsProto(R"pb(literal: " ")pb"),
-                             EqualsProto(R"pb(str: "7.7E+07")pb"),
-                             EqualsProto(R"pb(literal: " ")pb"),
-                             EqualsProto(R"pb(str: "7.7e+07")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("7.7e+07 7.7E+07 7.7e+07")),
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     ValueWithStr(Eq("7.7e+07")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("7.7E+07")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("7.7e+07"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::nouppercase << value << " "  //
@@ -1107,11 +1393,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << std::hex << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("0x77")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "0x77")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("0x77")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("0x77"))))))));
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::hex << value;
 }
@@ -1123,11 +1410,12 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << std::oct << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("077")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "077")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)),
+          TextMessage(Eq("077")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("077"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::oct << value;
@@ -1140,11 +1428,11 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << std::hex << std::dec << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("77")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "77")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("77")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::hex << std::dec << value;
@@ -1160,15 +1448,14 @@
                     << std::showbase << value << " "    //
                     << std::noshowbase << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("77 0x77 77")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "77")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "0x77")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "77")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("77 0x77 77")),
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     ValueWithStr(Eq("77")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("0x77")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::hex                         //
@@ -1190,12 +1477,10 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("77 077 77")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "77")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "077")pb"),
-                                         EqualsProto(R"pb(literal: " ")pb"),
-                                         EqualsProto(R"pb(str: "77")pb")))))));
+                         ENCODED_MESSAGE(HasValues(ElementsAre(
+                             ValueWithStr(Eq("77")), ValueWithLiteral(Eq(" ")),
+                             ValueWithStr(Eq("077")), ValueWithLiteral(Eq(" ")),
+                             ValueWithStr(Eq("77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::oct                         //
@@ -1215,15 +1500,14 @@
       << std::uppercase << value << " "    //
       << std::nouppercase << value;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("0xbeef 0XBEEF 0xbeef")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "0xbeef")pb"),
-                             EqualsProto(R"pb(literal: " ")pb"),
-                             EqualsProto(R"pb(str: "0XBEEF")pb"),
-                             EqualsProto(R"pb(literal: " ")pb"),
-                             EqualsProto(R"pb(str: "0xbeef")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("0xbeef 0XBEEF 0xbeef")),
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     ValueWithStr(Eq("0xbeef")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("0XBEEF")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("0xbeef"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::hex                          //
@@ -1243,7 +1527,7 @@
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("77000000.000000")),
                          ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "77000000.000000")pb")))))));
+                             ValueWithStr(Eq("77000000.000000"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::fixed << value;
@@ -1259,8 +1543,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("7.700000e+07")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "7.700000e+07")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("7.700000e+07"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::scientific << value;
@@ -1286,9 +1570,9 @@
       Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                  TextMessage(AnyOf(Eq("0x1.25bb50p+26"), Eq("0x1.25bb5p+26"),
                                    Eq("0x1.25bb500000000p+26"))),
-                 ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf(
-                     EqualsProto(R"pb(str: "0x1.25bb5p+26")pb"),
-                     EqualsProto(R"pb(str: "0x1.25bb500000000p+26")pb"))))))));
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     AnyOf(ValueWithStr(Eq("0x1.25bb5p+26")),
+                           ValueWithStr(Eq("0x1.25bb500000000p+26")))))))));
 
   test_sink.StartCapturingLogs();
 
@@ -1317,9 +1601,9 @@
       Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                  TextMessage(AnyOf(Eq("0x1.25bb50p+26"), Eq("0x1.25bb5p+26"),
                                    Eq("0x1.25bb500000000p+26"))),
-                 ENCODED_MESSAGE(HasValues(ElementsAre(AnyOf(
-                     EqualsProto(R"pb(str: "0x1.25bb5p+26")pb"),
-                     EqualsProto(R"pb(str: "0x1.25bb500000000p+26")pb"))))))));
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     AnyOf(ValueWithStr(Eq("0x1.25bb5p+26")),
+                           ValueWithStr(Eq("0x1.25bb500000000p+26")))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::hexfloat << value;
@@ -1336,8 +1620,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("7.7e+07")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "7.7e+07")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("7.7e+07"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::hexfloat << std::defaultfloat << value;
@@ -1352,8 +1636,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq(absl::string_view("\0", 1))),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "\0")pb")))))));
+                         ENCODED_MESSAGE(HasValues(ElementsAre(
+                             ValueWithStr(Eq(absl::string_view("\0", 1)))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::ends;
@@ -1370,8 +1654,7 @@
       Send(AllOf(
           TextMessage(MatchesOstream(comparison_stream)),
           TextMessage(Eq("\n")),
-          ENCODED_MESSAGE(HasValues(ElementsAre(EqualsProto(R"pb(str:
-          "\n")pb")))))));
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("\n"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::endl;
@@ -1395,10 +1678,9 @@
           // `std::setiosflags` and `std::resetiosflags` aren't manipulators.
           // We're unable to distinguish their return type(s) from arbitrary
           // user-defined types and thus don't suppress the empty str value.
-          ENCODED_MESSAGE(
-              HasValues(ElementsAre(EqualsProto(R"pb(str: "0x77")pb"),
-                                    EqualsProto(R"pb(literal: " ")pb"),
-                                    EqualsProto(R"pb(str: "119")pb")))))));
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("0x77")),
+                                                ValueWithLiteral(Eq(" ")),
+                                                ValueWithStr(Eq("119"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::resetiosflags(std::ios_base::basefield)
@@ -1422,10 +1704,9 @@
                  // `std::setbase` isn't a manipulator.  We're unable to
                  // distinguish its return type from arbitrary user-defined
                  // types and thus don't suppress the empty str value.
-                 ENCODED_MESSAGE(HasValues(
-                     ElementsAre(EqualsProto(R"pb(str: "0x77")pb"),
-                                 EqualsProto(R"pb(literal: " ")pb"),
-                                 EqualsProto(R"pb(str: "119")pb")))))));
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     ValueWithStr(Eq("0x77")), ValueWithLiteral(Eq(" ")),
+                     ValueWithStr(Eq("119"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::setbase(16) << value << " "  //
@@ -1446,8 +1727,8 @@
                  // `std::setprecision` isn't a manipulator.  We're unable to
                  // distinguish its return type from arbitrary user-defined
                  // types and thus don't suppress the empty str value.
-                 ENCODED_MESSAGE(HasValues(
-                     ElementsAre(EqualsProto(R"pb(str: "6.022e+23")pb")))))));
+                 ENCODED_MESSAGE(
+                     HasValues(ElementsAre(ValueWithStr(Eq("6.022e+23"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::setprecision(4) << value;
@@ -1463,8 +1744,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("602214085700000015187968")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(EqualsProto(
-                             R"pb(str: "602214085700000015187968")pb")))))));
+                         ENCODED_MESSAGE(HasValues(ElementsAre(
+                             ValueWithStr(Eq("602214085700000015187968"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::setprecision(200) << value;
@@ -1484,8 +1765,8 @@
                  // `std::setw` isn't a manipulator.  We're unable to
                  // distinguish its return type from arbitrary user-defined
                  // types and thus don't suppress the empty str value.
-                 ENCODED_MESSAGE(HasValues(
-                     ElementsAre(EqualsProto(R"pb(str: "      77")pb")))))));
+                 ENCODED_MESSAGE(
+                     HasValues(ElementsAre(ValueWithStr(Eq("      77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::setw(8) << value;
@@ -1501,8 +1782,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("-77     ")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "-77     ")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("-77     "))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::left << std::setw(8) << value;
@@ -1518,8 +1799,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("     -77")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "     -77")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("     -77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::right << std::setw(8) << value;
@@ -1535,8 +1816,8 @@
   EXPECT_CALL(test_sink,
               Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
                          TextMessage(Eq("-     77")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "-     77")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("-     77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::internal << std::setw(8) << value;
@@ -1556,8 +1837,8 @@
                          // unable to distinguish its return
                          // type from arbitrary user-defined types and
                          // thus don't suppress the empty str value.
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "00000077")pb")))))));
+                         ENCODED_MESSAGE(HasValues(
+                             ElementsAre(ValueWithStr(Eq("00000077"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::setfill('0') << std::setw(8) << value;
@@ -1575,13 +1856,13 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value << " " << 0x77;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("FromCustomClass{} 0x77")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(str: "FromCustomClass{}")pb"),
-                             EqualsProto(R"pb(literal: " ")pb"),
-                             EqualsProto(R"pb(str: "0x77")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
+                 TextMessage(Eq("FromCustomClass{} 0x77")),
+                 ENCODED_MESSAGE(HasValues(ElementsAre(
+                     ValueWithStr(Eq("FromCustomClass{}")),
+                     ValueWithLiteral(Eq(" ")), ValueWithStr(Eq("0x77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value << " " << 0x77;
@@ -1597,11 +1878,11 @@
   auto comparison_stream = ComparisonStream();
   comparison_stream << value << 77;
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(TextMessage(MatchesOstream(comparison_stream)),
-                         TextMessage(Eq("77")),
-                         ENCODED_MESSAGE(HasValues(
-                             ElementsAre(EqualsProto(R"pb(str: "77")pb")))))));
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(MatchesOstream(comparison_stream)), TextMessage(Eq("77")),
+          ENCODED_MESSAGE(HasValues(ElementsAre(ValueWithStr(Eq("77"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << value << 77;
@@ -1625,8 +1906,8 @@
   EXPECT_CALL(
       test_sink,
       Send(AllOf(TextMessage(Eq("(10, 20)")), TextMessage(Eq(absl::StrCat(p))),
-                 ENCODED_MESSAGE(HasValues(
-                     ElementsAre(EqualsProto(R"pb(str: "(10, 20)")pb")))))));
+                 ENCODED_MESSAGE(
+                     HasValues(ElementsAre(ValueWithStr(Eq("(10, 20)"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(INFO) << std::hex << p;
@@ -1654,6 +1935,29 @@
   LOG(INFO) << std::string(2 * absl::log_internal::kLogMessageBufferSize, 'x');
 }
 
+TEST(StructuredLoggingOverflowTest, TruncatesWideStrings) {
+  absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
+
+  // This message is too long and should be truncated to some unspecified size
+  // no greater than the buffer size but not too much less either.  It should be
+  // truncated rather than discarded.
+  EXPECT_CALL(
+      test_sink,
+      Send(AllOf(
+          TextMessage(AllOf(
+              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),
+                           Le(absl::log_internal::kLogMessageBufferSize))),
+              Each(Eq('x')))),
+          ENCODED_MESSAGE(HasOneStrThat(AllOf(
+              SizeIs(AllOf(Ge(absl::log_internal::kLogMessageBufferSize - 256),
+                           Le(absl::log_internal::kLogMessageBufferSize))),
+              Each(Eq('x'))))))));
+
+  test_sink.StartCapturingLogs();
+  LOG(INFO) << std::wstring(2 * absl::log_internal::kLogMessageBufferSize,
+                            L'x');
+}
+
 struct StringLike {
   absl::string_view data;
 };
diff --git a/absl/log/log_modifier_methods_test.cc b/absl/log/log_modifier_methods_test.cc
index 4ccde40..4cee0c0 100644
--- a/absl/log/log_modifier_methods_test.cc
+++ b/absl/log/log_modifier_methods_test.cc
@@ -15,6 +15,8 @@
 
 #include <errno.h>
 
+#include <string>
+
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/log/internal/test_actions.h"
@@ -77,6 +79,14 @@
       << "hello world";
 }
 
+TEST(TailCallsModifiesTest, AtLocationFileLineLifetime) {
+  // The macro takes care to not use this temporary after its lifetime.
+  // The only salient expectation is "no sanitizer diagnostics".
+  LOG(INFO).AtLocation(std::string("/my/very/very/very_long_source_file.cc"),
+                       777)
+      << "hello world";
+}
+
 TEST(TailCallsModifiesTest, NoPrefix) {
   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
 
@@ -159,8 +169,8 @@
                  ENCODED_MESSAGE(MatchesEvent(
                      Eq("fake/file"), Eq(123), Eq(absl::UnixEpoch()),
                      Eq(logging::proto::WARNING), Eq(456),
-                     ElementsAre(EqualsProto(R"pb(literal: "forwarded: ")pb"),
-                                 EqualsProto(R"pb(str: "hello world")pb")))))));
+                     ElementsAre(ValueWithLiteral(Eq("forwarded: ")),
+                                 ValueWithStr(Eq("hello world"))))))));
 
   test_sink.StartCapturingLogs();
   LOG(WARNING)
@@ -178,18 +188,17 @@
 
   EXPECT_CALL(
       test_sink,
-      Send(AllOf(TextMessage(AnyOf(Eq("hello world: Bad file number [9]"),
-                                   Eq("hello world: Bad file descriptor [9]"),
-                                   Eq("hello world: Bad file descriptor [8]"))),
-                 ENCODED_MESSAGE(HasValues(ElementsAre(
-                     EqualsProto(R"pb(literal: "hello world")pb"),
-                     EqualsProto(R"pb(literal: ": ")pb"),
-                     AnyOf(EqualsProto(R"pb(str: "Bad file number")pb"),
-                           EqualsProto(R"pb(str: "Bad file descriptor")pb")),
-                     EqualsProto(R"pb(literal: " [")pb"),
-                     AnyOf(EqualsProto(R"pb(str: "8")pb"),
-                           EqualsProto(R"pb(str: "9")pb")),
-                     EqualsProto(R"pb(literal: "]")pb")))))));
+      Send(AllOf(
+          TextMessage(AnyOf(Eq("hello world: Bad file number [9]"),
+                            Eq("hello world: Bad file descriptor [9]"),
+                            Eq("hello world: Bad file descriptor [8]"))),
+          ENCODED_MESSAGE(HasValues(ElementsAre(
+              ValueWithLiteral(Eq("hello world")), ValueWithLiteral(Eq(": ")),
+              AnyOf(ValueWithStr(Eq("Bad file number")),
+                    ValueWithStr(Eq("Bad file descriptor"))),
+              ValueWithLiteral(Eq(" [")),
+              AnyOf(ValueWithStr(Eq("8")), ValueWithStr(Eq("9"))),
+              ValueWithLiteral(Eq("]"))))))));
 
   test_sink.StartCapturingLogs();
   errno = EBADF;
diff --git a/absl/log/log_sink_registry.h b/absl/log/log_sink_registry.h
index bf76cce..a3fa9a3 100644
--- a/absl/log/log_sink_registry.h
+++ b/absl/log/log_sink_registry.h
@@ -22,6 +22,7 @@
 #define ABSL_LOG_LOG_SINK_REGISTRY_H_
 
 #include "absl/base/config.h"
+#include "absl/base/nullability.h"
 #include "absl/log/internal/log_sink_set.h"
 #include "absl/log/log_sink.h"
 
@@ -43,8 +44,10 @@
 // sink instead which writes them to `stderr`.
 //
 // Do not call these inside `absl::LogSink::Send`.
-inline void AddLogSink(absl::LogSink* sink) { log_internal::AddLogSink(sink); }
-inline void RemoveLogSink(absl::LogSink* sink) {
+inline void AddLogSink(absl::LogSink* absl_nonnull sink) {
+  log_internal::AddLogSink(sink);
+}
+inline void RemoveLogSink(absl::LogSink* absl_nonnull sink) {
   log_internal::RemoveLogSink(sink);
 }
 
diff --git a/absl/log/log_streamer_test.cc b/absl/log/log_streamer_test.cc
index b9b9428..4fe88e9 100644
--- a/absl/log/log_streamer_test.cc
+++ b/absl/log/log_streamer_test.cc
@@ -69,17 +69,17 @@
 
   EXPECT_CALL(
       test_sink,
-      Send(AllOf(
-          SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
-          Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kInfo)),
-          Timestamp(InMatchWindow()),
-          ThreadID(Eq(absl::base_internal::GetTID())),
-          TextMessage(Eq("WriteToStream: foo")),
-          ENCODED_MESSAGE(MatchesEvent(
-              Eq("path/file.cc"), Eq(1234), InMatchWindow(),
-              Eq(logging::proto::INFO), Eq(absl::base_internal::GetTID()),
-              ElementsAre(EqualsProto(R"pb(str: "WriteToStream: foo")pb")))),
-          Stacktrace(IsEmpty()))));
+      Send(
+          AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kInfo)),
+                Timestamp(InMatchWindow()),
+                ThreadID(Eq(absl::base_internal::GetTID())),
+                TextMessage(Eq("WriteToStream: foo")),
+                ENCODED_MESSAGE(MatchesEvent(
+                    Eq("path/file.cc"), Eq(1234), InMatchWindow(),
+                    Eq(logging::proto::INFO), Eq(absl::base_internal::GetTID()),
+                    ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))),
+                Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
   WriteToStream("foo", &absl::LogInfoStreamer("path/file.cc", 1234).stream());
@@ -99,7 +99,7 @@
           ENCODED_MESSAGE(MatchesEvent(
               Eq("path/file.cc"), Eq(1234), InMatchWindow(),
               Eq(logging::proto::WARNING), Eq(absl::base_internal::GetTID()),
-              ElementsAre(EqualsProto(R"pb(str: "WriteToStream: foo")pb")))),
+              ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))),
           Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
@@ -121,7 +121,7 @@
           ENCODED_MESSAGE(MatchesEvent(
               Eq("path/file.cc"), Eq(1234), InMatchWindow(),
               Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),
-              ElementsAre(EqualsProto(R"pb(str: "WriteToStream: foo")pb")))),
+              ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))),
           Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
@@ -138,19 +138,19 @@
             .Times(AnyNumber())
             .WillRepeatedly(DeathTestUnexpectedLogging());
 
-        EXPECT_CALL(test_sink,
-                    Send(AllOf(SourceFilename(Eq("path/file.cc")),
-                               SourceLine(Eq(1234)), Prefix(IsTrue()),
-                               LogSeverity(Eq(absl::LogSeverity::kFatal)),
-                               Timestamp(InMatchWindow()),
-                               ThreadID(Eq(absl::base_internal::GetTID())),
-                               TextMessage(Eq("WriteToStream: foo")),
-                               ENCODED_MESSAGE(MatchesEvent(
-                                   Eq("path/file.cc"), Eq(1234),
-                                   InMatchWindow(), Eq(logging::proto::FATAL),
-                                   Eq(absl::base_internal::GetTID()),
-                                   ElementsAre(EqualsProto(
-                                       R"pb(str: "WriteToStream: foo")pb")))))))
+        EXPECT_CALL(
+            test_sink,
+            Send(AllOf(
+                SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                Timestamp(InMatchWindow()),
+                ThreadID(Eq(absl::base_internal::GetTID())),
+                TextMessage(Eq("WriteToStream: foo")),
+                ENCODED_MESSAGE(MatchesEvent(
+                    Eq("path/file.cc"), Eq(1234), InMatchWindow(),
+                    Eq(logging::proto::FATAL),
+                    Eq(absl::base_internal::GetTID()),
+                    ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))))))
             .WillOnce(DeathTestExpectedLogging());
 
         test_sink.StartCapturingLogs();
@@ -176,7 +176,7 @@
           ENCODED_MESSAGE(MatchesEvent(
               Eq("path/file.cc"), Eq(1234), InMatchWindow(),
               Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),
-              ElementsAre(EqualsProto(R"pb(str: "WriteToStream: foo")pb")))),
+              ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))),
           Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
@@ -193,19 +193,19 @@
             .Times(AnyNumber())
             .WillRepeatedly(DeathTestUnexpectedLogging());
 
-        EXPECT_CALL(test_sink,
-                    Send(AllOf(SourceFilename(Eq("path/file.cc")),
-                               SourceLine(Eq(1234)), Prefix(IsTrue()),
-                               LogSeverity(Eq(absl::LogSeverity::kFatal)),
-                               Timestamp(InMatchWindow()),
-                               ThreadID(Eq(absl::base_internal::GetTID())),
-                               TextMessage(Eq("WriteToStream: foo")),
-                               ENCODED_MESSAGE(MatchesEvent(
-                                   Eq("path/file.cc"), Eq(1234),
-                                   InMatchWindow(), Eq(logging::proto::FATAL),
-                                   Eq(absl::base_internal::GetTID()),
-                                   ElementsAre(EqualsProto(
-                                       R"pb(str: "WriteToStream: foo")pb")))))))
+        EXPECT_CALL(
+            test_sink,
+            Send(AllOf(
+                SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                Timestamp(InMatchWindow()),
+                ThreadID(Eq(absl::base_internal::GetTID())),
+                TextMessage(Eq("WriteToStream: foo")),
+                ENCODED_MESSAGE(MatchesEvent(
+                    Eq("path/file.cc"), Eq(1234), InMatchWindow(),
+                    Eq(logging::proto::FATAL),
+                    Eq(absl::base_internal::GetTID()),
+                    ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))))))
             .WillOnce(DeathTestExpectedLogging());
 
         test_sink.StartCapturingLogs();
@@ -230,7 +230,7 @@
           ENCODED_MESSAGE(MatchesEvent(
               Eq("path/file.cc"), Eq(1234), InMatchWindow(),
               Eq(logging::proto::ERROR), Eq(absl::base_internal::GetTID()),
-              ElementsAre(EqualsProto(R"pb(str: "WriteToStream: foo")pb")))),
+              ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))),
           Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
@@ -249,19 +249,19 @@
             .Times(AnyNumber())
             .WillRepeatedly(DeathTestUnexpectedLogging());
 
-        EXPECT_CALL(test_sink,
-                    Send(AllOf(SourceFilename(Eq("path/file.cc")),
-                               SourceLine(Eq(1234)), Prefix(IsTrue()),
-                               LogSeverity(Eq(absl::LogSeverity::kFatal)),
-                               Timestamp(InMatchWindow()),
-                               ThreadID(Eq(absl::base_internal::GetTID())),
-                               TextMessage(Eq("WriteToStream: foo")),
-                               ENCODED_MESSAGE(MatchesEvent(
-                                   Eq("path/file.cc"), Eq(1234),
-                                   InMatchWindow(), Eq(logging::proto::FATAL),
-                                   Eq(absl::base_internal::GetTID()),
-                                   ElementsAre(EqualsProto(
-                                       R"pb(str: "WriteToStream: foo")pb")))))))
+        EXPECT_CALL(
+            test_sink,
+            Send(AllOf(
+                SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                Prefix(IsTrue()), LogSeverity(Eq(absl::LogSeverity::kFatal)),
+                Timestamp(InMatchWindow()),
+                ThreadID(Eq(absl::base_internal::GetTID())),
+                TextMessage(Eq("WriteToStream: foo")),
+                ENCODED_MESSAGE(MatchesEvent(
+                    Eq("path/file.cc"), Eq(1234), InMatchWindow(),
+                    Eq(logging::proto::FATAL),
+                    Eq(absl::base_internal::GetTID()),
+                    ElementsAre(ValueWithStr(Eq("WriteToStream: foo"))))))))
             .WillOnce(DeathTestExpectedLogging());
 
         test_sink.StartCapturingLogs();
@@ -278,13 +278,12 @@
 
   EXPECT_CALL(
       test_sink,
-      Send(AllOf(
-          SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
-          TextMessage(Eq("WriteToStreamRef: foo")),
-          ENCODED_MESSAGE(MatchesEvent(
-              Eq("path/file.cc"), Eq(1234), _, _, _,
-              ElementsAre(EqualsProto(R"pb(str: "WriteToStreamRef: foo")pb")))),
-          Stacktrace(IsEmpty()))));
+      Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                 TextMessage(Eq("WriteToStreamRef: foo")),
+                 ENCODED_MESSAGE(MatchesEvent(
+                     Eq("path/file.cc"), Eq(1234), _, _, _,
+                     ElementsAre(ValueWithStr(Eq("WriteToStreamRef: foo"))))),
+                 Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
   WriteToStreamRef("foo", absl::LogInfoStreamer("path/file.cc", 1234).stream());
@@ -303,14 +302,13 @@
   // test would fail.
   EXPECT_CALL(
       test_sink,
-      Send(AllOf(
-          SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
-          TextMessage(Eq("WriteToStream: foo WriteToStreamRef: bar")),
-          ENCODED_MESSAGE(MatchesEvent(
-              Eq("path/file.cc"), Eq(1234), _, _, _,
-              ElementsAre(EqualsProto(
-                  R"pb(str: "WriteToStream: foo WriteToStreamRef: bar")pb")))),
-          Stacktrace(IsEmpty()))));
+      Send(AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                 TextMessage(Eq("WriteToStream: foo WriteToStreamRef: bar")),
+                 ENCODED_MESSAGE(MatchesEvent(
+                     Eq("path/file.cc"), Eq(1234), _, _, _,
+                     ElementsAre(ValueWithStr(
+                         Eq("WriteToStream: foo WriteToStreamRef: bar"))))),
+                 Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
 }
@@ -331,13 +329,12 @@
 TEST(LogStreamerTest, LogsEmptyLine) {
   absl::ScopedMockLog test_sink(absl::MockLogDefault::kDisallowUnexpected);
 
-  EXPECT_CALL(test_sink,
-              Send(AllOf(SourceFilename(Eq("path/file.cc")),
-                         SourceLine(Eq(1234)), TextMessage(Eq("")),
-                         ENCODED_MESSAGE(MatchesEvent(
-                             Eq("path/file.cc"), Eq(1234), _, _, _,
-                             ElementsAre(EqualsProto(R"pb(str: "")pb")))),
-                         Stacktrace(IsEmpty()))));
+  EXPECT_CALL(test_sink, Send(AllOf(SourceFilename(Eq("path/file.cc")),
+                                    SourceLine(Eq(1234)), TextMessage(Eq("")),
+                                    ENCODED_MESSAGE(MatchesEvent(
+                                        Eq("path/file.cc"), Eq(1234), _, _, _,
+                                        ElementsAre(ValueWithStr(Eq(""))))),
+                                    Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
   absl::LogInfoStreamer("path/file.cc", 1234);
@@ -356,9 +353,9 @@
         EXPECT_CALL(
             test_sink,
             Send(AllOf(SourceFilename(Eq("path/file.cc")), TextMessage(Eq("")),
-                       ENCODED_MESSAGE(MatchesEvent(
-                           Eq("path/file.cc"), _, _, _, _,
-                           ElementsAre(EqualsProto(R"pb(str: "")pb")))))))
+                       ENCODED_MESSAGE(
+                           MatchesEvent(Eq("path/file.cc"), _, _, _, _,
+                                        ElementsAre(ValueWithStr(Eq(""))))))))
             .WillOnce(DeathTestExpectedLogging());
 
         test_sink.StartCapturingLogs();
@@ -374,14 +371,14 @@
 
   EXPECT_CALL(
       test_sink,
-      Send(AllOf(
-          SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
-          LogSeverity(Eq(absl::LogSeverity::kInfo)),
-          TextMessage(Eq("hello 0x10 world 0x10")),
-          ENCODED_MESSAGE(MatchesEvent(
-              Eq("path/file.cc"), Eq(1234), _, Eq(logging::proto::INFO), _,
-              ElementsAre(EqualsProto(R"pb(str: "hello 0x10 world 0x10")pb")))),
-          Stacktrace(IsEmpty()))));
+      Send(
+          AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                LogSeverity(Eq(absl::LogSeverity::kInfo)),
+                TextMessage(Eq("hello 0x10 world 0x10")),
+                ENCODED_MESSAGE(MatchesEvent(
+                    Eq("path/file.cc"), Eq(1234), _, Eq(logging::proto::INFO),
+                    _, ElementsAre(ValueWithStr(Eq("hello 0x10 world 0x10"))))),
+                Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
   auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234);
@@ -402,18 +399,18 @@
           TextMessage(Eq("something else")),
           ENCODED_MESSAGE(MatchesEvent(
               Eq("path/file2.cc"), Eq(5678), _, Eq(logging::proto::WARNING), _,
-              ElementsAre(EqualsProto(R"pb(str: "something else")pb")))),
+              ElementsAre(ValueWithStr(Eq("something else"))))),
           Stacktrace(IsEmpty()))));
   EXPECT_CALL(
       test_sink,
-      Send(AllOf(
-          SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
-          LogSeverity(Eq(absl::LogSeverity::kInfo)),
-          TextMessage(Eq("hello 0x10 world 0x10")),
-          ENCODED_MESSAGE(MatchesEvent(
-              Eq("path/file.cc"), Eq(1234), _, Eq(logging::proto::INFO), _,
-              ElementsAre(EqualsProto(R"pb(str: "hello 0x10 world 0x10")pb")))),
-          Stacktrace(IsEmpty()))));
+      Send(
+          AllOf(SourceFilename(Eq("path/file.cc")), SourceLine(Eq(1234)),
+                LogSeverity(Eq(absl::LogSeverity::kInfo)),
+                TextMessage(Eq("hello 0x10 world 0x10")),
+                ENCODED_MESSAGE(MatchesEvent(
+                    Eq("path/file.cc"), Eq(1234), _, Eq(logging::proto::INFO),
+                    _, ElementsAre(ValueWithStr(Eq("hello 0x10 world 0x10"))))),
+                Stacktrace(IsEmpty()))));
 
   test_sink.StartCapturingLogs();
   auto streamer1 = absl::LogInfoStreamer("path/file.cc", 1234);
diff --git a/absl/log/scoped_mock_log.h b/absl/log/scoped_mock_log.h
index 399e604..a383066 100644
--- a/absl/log/scoped_mock_log.h
+++ b/absl/log/scoped_mock_log.h
@@ -40,8 +40,8 @@
 
 // ScopedMockLog
 //
-// ScopedMockLog is a LogSink that intercepts LOG() messages issued during its
-// lifespan.
+// ScopedMockLog is a LogSink that intercepts LOG() messages issued by all
+// threads when active.
 //
 // Using this together with GoogleTest, it's easy to test how a piece of code
 // calls LOG(). The typical usage, noting the distinction between
diff --git a/absl/log/structured.h b/absl/log/structured.h
index 9ad69fb..89d241e 100644
--- a/absl/log/structured.h
+++ b/absl/log/structured.h
@@ -32,6 +32,7 @@
 
 #include <ostream>
 
+#include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/log/internal/structured.h"
 #include "absl/strings/string_view.h"
@@ -60,7 +61,11 @@
 //                                 int line) {
 //     LOG(LEVEL(severity)).AtLocation(file, line) << absl::LogAsLiteral(str);
 //   }
-inline log_internal::AsLiteralImpl LogAsLiteral(absl::string_view s) {
+//
+// `LogAsLiteral` should only be used as a streaming operand and not, for
+// example, as a local variable initializer.
+inline log_internal::AsLiteralImpl LogAsLiteral(
+    absl::string_view s ABSL_ATTRIBUTE_LIFETIME_BOUND) {
   return log_internal::AsLiteralImpl(s);
 }
 
diff --git a/absl/log/structured_test.cc b/absl/log/structured_test.cc
index 6f1df18..9fe0756 100644
--- a/absl/log/structured_test.cc
+++ b/absl/log/structured_test.cc
@@ -51,11 +51,10 @@
 
   absl::ScopedMockLog sink;
 
-  EXPECT_CALL(sink,
-              Send(AllOf(TextMessage(MatchesOstream(stream)),
-                         TextMessage(Eq("hello world")),
-                         ENCODED_MESSAGE(HasValues(ElementsAre(
-                             EqualsProto(R"pb(literal: "hello world")pb")))))));
+  EXPECT_CALL(sink, Send(AllOf(TextMessage(MatchesOstream(stream)),
+                               TextMessage(Eq("hello world")),
+                               ENCODED_MESSAGE(HasValues(ElementsAre(
+                                   ValueWithLiteral(Eq("hello world"))))))));
 
   sink.StartCapturingLogs();
   LOG(INFO) << absl::LogAsLiteral(not_a_literal);
diff --git a/absl/log/vlog_is_on.h b/absl/log/vlog_is_on.h
index f7539df..c33fcc1 100644
--- a/absl/log/vlog_is_on.h
+++ b/absl/log/vlog_is_on.h
@@ -40,6 +40,8 @@
 // last . and everything after it) is stripped from each filename prior to
 // matching, as is the special suffix "-inl".
 //
+// Example: --vmodule=module_a=1,module_b=2
+//
 // Files are matched against globs in `--vmodule` in order, and the first match
 // determines the verbosity level.
 //
diff --git a/absl/log/vlog_is_on_test.cc b/absl/log/vlog_is_on_test.cc
index 883d798..f612283 100644
--- a/absl/log/vlog_is_on_test.cc
+++ b/absl/log/vlog_is_on_test.cc
@@ -44,7 +44,23 @@
 #endif
 }
 
-TEST(VLogIsOn, GlobalWorksWithoutMaxVerbosityAndMinLogLevel) {
+// This fixture is used to reset the VLOG levels to their default values before
+// each test.
+class VLogIsOnTest : public ::testing::Test {
+ protected:
+  void SetUp() override { ResetVLogLevels(); }
+
+ private:
+  // Resets the VLOG levels to their default values.
+  // It is supposed to be called in the SetUp() method of the test fixture to
+  // eliminate any side effects from other tests.
+  static void ResetVLogLevels() {
+    absl::log_internal::UpdateVModule("");
+    absl::SetGlobalVLogLevel(0);
+  }
+};
+
+TEST_F(VLogIsOnTest, GlobalWorksWithoutMaxVerbosityAndMinLogLevel) {
   if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {
     GTEST_SKIP();
   }
@@ -59,7 +75,7 @@
   VLOG(4) << "spam";
 }
 
-TEST(VLogIsOn, FileWorksWithoutMaxVerbosityAndMinLogLevel) {
+TEST_F(VLogIsOnTest, FileWorksWithoutMaxVerbosityAndMinLogLevel) {
   if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {
     GTEST_SKIP();
   }
@@ -74,7 +90,7 @@
   VLOG(4) << "spam";
 }
 
-TEST(VLogIsOn, PatternWorksWithoutMaxVerbosityAndMinLogLevel) {
+TEST_F(VLogIsOnTest, PatternWorksWithoutMaxVerbosityAndMinLogLevel) {
   if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {
     GTEST_SKIP();
   }
@@ -89,7 +105,48 @@
   VLOG(4) << "spam";
 }
 
-TEST(VLogIsOn, GlobalDoesNotFilterBelowMaxVerbosity) {
+TEST_F(VLogIsOnTest,
+       PatternOverridesLessGenericOneWithoutMaxVerbosityAndMinLogLevel) {
+  if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {
+    GTEST_SKIP();
+  }
+
+  // This should disable logging in this file
+  absl::SetVLogLevel("vlog_is_on*", -1);
+  // This overrides the previous setting, because "vlog*" is more generic than
+  // "vlog_is_on*". This should enable VLOG level 3 in this file.
+  absl::SetVLogLevel("vlog*", 3);
+  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "important"));
+
+  log.StartCapturingLogs();
+  VLOG(3) << "important";
+  VLOG(4) << "spam";
+}
+
+TEST_F(VLogIsOnTest,
+       PatternDoesNotOverridesMoreGenericOneWithoutMaxVerbosityAndMinLogLevel) {
+  if (MaxLogVerbosity().has_value() || MinLogLevel().has_value()) {
+    GTEST_SKIP();
+  }
+
+  // This should enable VLOG level 3 in this file.
+  absl::SetVLogLevel("vlog*", 3);
+  // This should not change the VLOG level in this file. The pattern does not
+  // match this file and it is less generic than the previous patter "vlog*".
+  // Therefore, it does not disable VLOG level 3 in this file.
+  absl::SetVLogLevel("vlog_is_on_some_other_test*", -1);
+  absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);
+
+  EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "important"));
+
+  log.StartCapturingLogs();
+  VLOG(3) << "important";
+  VLOG(5) << "spam";
+}
+
+TEST_F(VLogIsOnTest, GlobalDoesNotFilterBelowMaxVerbosity) {
   if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() < 2) {
     GTEST_SKIP();
   }
@@ -104,7 +161,7 @@
   VLOG(2) << "asdf";
 }
 
-TEST(VLogIsOn, FileDoesNotFilterBelowMaxVerbosity) {
+TEST_F(VLogIsOnTest, FileDoesNotFilterBelowMaxVerbosity) {
   if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() < 2) {
     GTEST_SKIP();
   }
@@ -119,7 +176,7 @@
   VLOG(2) << "asdf";
 }
 
-TEST(VLogIsOn, PatternDoesNotFilterBelowMaxVerbosity) {
+TEST_F(VLogIsOnTest, PatternDoesNotFilterBelowMaxVerbosity) {
   if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() < 2) {
     GTEST_SKIP();
   }
@@ -134,7 +191,7 @@
   VLOG(2) << "asdf";
 }
 
-TEST(VLogIsOn, GlobalFiltersAboveMaxVerbosity) {
+TEST_F(VLogIsOnTest, GlobalFiltersAboveMaxVerbosity) {
   if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() >= 4) {
     GTEST_SKIP();
   }
@@ -147,7 +204,7 @@
   VLOG(4) << "dfgh";
 }
 
-TEST(VLogIsOn, FileFiltersAboveMaxVerbosity) {
+TEST_F(VLogIsOnTest, FileFiltersAboveMaxVerbosity) {
   if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() >= 4) {
     GTEST_SKIP();
   }
@@ -160,7 +217,7 @@
   VLOG(4) << "dfgh";
 }
 
-TEST(VLogIsOn, PatternFiltersAboveMaxVerbosity) {
+TEST_F(VLogIsOnTest, PatternFiltersAboveMaxVerbosity) {
   if (!MaxLogVerbosity().has_value() || *MaxLogVerbosity() >= 4) {
     GTEST_SKIP();
   }
diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel
index 4573f17..d50a502 100644
--- a/absl/memory/BUILD.bazel
+++ b/absl/memory/BUILD.bazel
@@ -54,7 +54,7 @@
     deps = [
         ":memory",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel
index cf5df9b..d01cb8a 100644
--- a/absl/meta/BUILD.bazel
+++ b/absl/meta/BUILD.bazel
@@ -53,7 +53,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index ded5582..02c1e63 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -38,6 +38,7 @@
 #include <cstddef>
 #include <functional>
 #include <string>
+#include <string_view>
 #include <type_traits>
 #include <vector>
 
@@ -48,10 +49,6 @@
 #include <span>  // NOLINT(build/c++20)
 #endif
 
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-#include <string_view>
-#endif
-
 // Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17
 // feature.
 #if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
@@ -97,22 +94,6 @@
 template <template <class...> class Op, class... Args>
 struct is_detected : is_detected_impl<void, Op, Args...>::type {};
 
-template <class Enabler, class To, template <class...> class Op, class... Args>
-struct is_detected_convertible_impl {
-  using type = std::false_type;
-};
-
-template <class To, template <class...> class Op, class... Args>
-struct is_detected_convertible_impl<
-    typename std::enable_if<std::is_convertible<Op<Args...>, To>::value>::type,
-    To, Op, Args...> {
-  using type = std::true_type;
-};
-
-template <class To, template <class...> class Op, class... Args>
-struct is_detected_convertible
-    : is_detected_convertible_impl<void, To, Op, Args...>::type {};
-
 }  // namespace type_traits_internal
 
 // void_t()
@@ -121,96 +102,32 @@
 // metafunction allows you to create a general case that maps to `void` while
 // allowing specializations that map to specific types.
 //
-// This metafunction is designed to be a drop-in replacement for the C++17
-// `std::void_t` metafunction.
-//
-// NOTE: `absl::void_t` does not use the standard-specified implementation so
-// that it can remain compatible with gcc < 5.1. This can introduce slightly
-// different behavior, such as when ordering partial specializations.
+// This metafunction is not 100% compatible with the C++17 `std::void_t`
+// metafunction. It has slightly different behavior, such as when ordering
+// partial specializations. It is recommended to use `std::void_t` instead.
 template <typename... Ts>
 using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
 
-// conjunction
-//
-// Performs a compile-time logical AND operation on the passed types (which
-// must have  `::value` members convertible to `bool`. Short-circuits if it
-// encounters any `false` members (and does not compare the `::value` members
-// of any remaining arguments).
-//
-// This metafunction is designed to be a drop-in replacement for the C++17
-// `std::conjunction` metafunction.
-template <typename... Ts>
-struct conjunction : std::true_type {};
-
-template <typename T, typename... Ts>
-struct conjunction<T, Ts...>
-    : std::conditional<T::value, conjunction<Ts...>, T>::type {};
-
-template <typename T>
-struct conjunction<T> : T {};
-
-// disjunction
-//
-// Performs a compile-time logical OR operation on the passed types (which
-// must have  `::value` members convertible to `bool`. Short-circuits if it
-// encounters any `true` members (and does not compare the `::value` members
-// of any remaining arguments).
-//
-// This metafunction is designed to be a drop-in replacement for the C++17
-// `std::disjunction` metafunction.
-template <typename... Ts>
-struct disjunction : std::false_type {};
-
-template <typename T, typename... Ts>
-struct disjunction<T, Ts...>
-    : std::conditional<T::value, T, disjunction<Ts...>>::type {};
-
-template <typename T>
-struct disjunction<T> : T {};
-
-// negation
-//
-// Performs a compile-time logical NOT operation on the passed type (which
-// must have  `::value` members convertible to `bool`.
-//
-// This metafunction is designed to be a drop-in replacement for the C++17
-// `std::negation` metafunction.
-template <typename T>
-struct negation : std::integral_constant<bool, !T::value> {};
-
-// is_function()
-//
-// Determines whether the passed type `T` is a function type.
-//
-// This metafunction is designed to be a drop-in replacement for the C++11
-// `std::is_function()` metafunction for platforms that have incomplete C++11
-// support (such as libstdc++ 4.x).
-//
-// This metafunction works because appending `const` to a type does nothing to
-// function types and reference types (and forms a const-qualified type
-// otherwise).
-template <typename T>
-struct is_function
-    : std::integral_constant<
-          bool, !(std::is_reference<T>::value ||
-                  std::is_const<typename std::add_const<T>::type>::value)> {};
-
-// is_copy_assignable()
-// is_move_assignable()
-// is_trivially_destructible()
-// is_trivially_default_constructible()
-// is_trivially_move_constructible()
-// is_trivially_copy_constructible()
-// is_trivially_move_assignable()
-// is_trivially_copy_assignable()
-//
 // Historical note: Abseil once provided implementations of these type traits
 // for platforms that lacked full support. New code should prefer to use the
 // std variants.
 //
 // See the documentation for the STL <type_traits> header for more information:
 // https://en.cppreference.com/w/cpp/header/type_traits
+using std::add_const_t;
+using std::add_cv_t;
+using std::add_lvalue_reference_t;
+using std::add_pointer_t;
+using std::add_rvalue_reference_t;
+using std::add_volatile_t;
+using std::common_type_t;
+using std::conditional_t;
+using std::conjunction;
+using std::decay_t;
+using std::enable_if_t;
+using std::disjunction;
 using std::is_copy_assignable;
+using std::is_function;
 using std::is_move_assignable;
 using std::is_trivially_copy_assignable;
 using std::is_trivially_copy_constructible;
@@ -218,6 +135,17 @@
 using std::is_trivially_destructible;
 using std::is_trivially_move_assignable;
 using std::is_trivially_move_constructible;
+using std::make_signed_t;
+using std::make_unsigned_t;
+using std::negation;
+using std::remove_all_extents_t;
+using std::remove_const_t;
+using std::remove_cv_t;
+using std::remove_extent_t;
+using std::remove_pointer_t;
+using std::remove_reference_t;
+using std::remove_volatile_t;
+using std::underlying_type_t;
 
 #if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L
 template <typename T>
@@ -240,70 +168,6 @@
 using remove_cvref_t = typename remove_cvref<T>::type;
 #endif
 
-// -----------------------------------------------------------------------------
-// C++14 "_t" trait aliases
-// -----------------------------------------------------------------------------
-
-template <typename T>
-using remove_cv_t = typename std::remove_cv<T>::type;
-
-template <typename T>
-using remove_const_t = typename std::remove_const<T>::type;
-
-template <typename T>
-using remove_volatile_t = typename std::remove_volatile<T>::type;
-
-template <typename T>
-using add_cv_t = typename std::add_cv<T>::type;
-
-template <typename T>
-using add_const_t = typename std::add_const<T>::type;
-
-template <typename T>
-using add_volatile_t = typename std::add_volatile<T>::type;
-
-template <typename T>
-using remove_reference_t = typename std::remove_reference<T>::type;
-
-template <typename T>
-using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
-
-template <typename T>
-using add_rvalue_reference_t = typename std::add_rvalue_reference<T>::type;
-
-template <typename T>
-using remove_pointer_t = typename std::remove_pointer<T>::type;
-
-template <typename T>
-using add_pointer_t = typename std::add_pointer<T>::type;
-
-template <typename T>
-using make_signed_t = typename std::make_signed<T>::type;
-
-template <typename T>
-using make_unsigned_t = typename std::make_unsigned<T>::type;
-
-template <typename T>
-using remove_extent_t = typename std::remove_extent<T>::type;
-
-template <typename T>
-using remove_all_extents_t = typename std::remove_all_extents<T>::type;
-
-template <typename T>
-using decay_t = typename std::decay<T>::type;
-
-template <bool B, typename T = void>
-using enable_if_t = typename std::enable_if<B, T>::type;
-
-template <bool B, typename T, typename F>
-using conditional_t = typename std::conditional<B, T, F>::type;
-
-template <typename... T>
-using common_type_t = typename std::common_type<T...>::type;
-
-template <typename T>
-using underlying_type_t = typename std::underlying_type<T>::type;
-
 namespace type_traits_internal {
 
 #if (defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L) || \
@@ -460,11 +324,17 @@
 
 // absl::is_trivially_relocatable<T>
 //
+// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2786r11.html
+//
 // Detects whether a type is known to be "trivially relocatable" -- meaning it
 // can be relocated from one place to another as if by memcpy/memmove.
 // This implies that its object representation doesn't depend on its address,
 // and also none of its special member functions do anything strange.
 //
+// Note that when relocating the caller code should ensure that if the object is
+// polymorphic, the dynamic type is of the most derived type. Padding bytes
+// should not be copied.
+//
 // This trait is conservative. If it's true then the type is definitely
 // trivially relocatable, but if it's false then the type may or may not be. For
 // example, std::vector<int> is trivially relocatable on every known STL
@@ -482,11 +352,7 @@
 //
 // Upstream documentation:
 //
-// https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__is_trivially_relocatable
-
-// If the compiler offers a builtin that tells us the answer, we can use that.
-// This covers all of the cases in the fallback below, plus types that opt in
-// using e.g. [[clang::trivial_abi]].
+// https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__builtin_is_cpp_trivially_relocatable
 //
 // Clang on Windows has the builtin, but it falsely claims types with a
 // user-provided destructor are trivial (http://b/275003464). So we opt out
@@ -503,19 +369,36 @@
 // remove the condition.
 //
 // Clang on all platforms fails to detect that a type with a user-provided
-// move-assignment operator is not trivially relocatable. So in fact we
-// opt out of Clang altogether, for now.
+// move-assignment operator is not trivially relocatable so we also check for
+// is_trivially_move_assignable for Clang.
 //
-// TODO(b/325479096): Remove the opt-out once Clang's behavior is fixed.
+// TODO(b/325479096): Remove the Clang is_trivially_move_assignable version once
+// Clang's behavior is fixed.
 //
 // According to https://github.com/abseil/abseil-cpp/issues/1479, this does not
 // work with NVCC either.
-#if ABSL_HAVE_BUILTIN(__is_trivially_relocatable) && \
-    (defined(__cpp_impl_trivially_relocatable) ||    \
-     (!defined(__clang__) && !defined(__APPLE__) && !defined(__NVCC__)))
+#if ABSL_HAVE_BUILTIN(__builtin_is_cpp_trivially_relocatable)
+// https://github.com/llvm/llvm-project/pull/127636#pullrequestreview-2637005293
+// In the current implementation, __builtin_is_cpp_trivially_relocatable will
+// only return true for types that are trivially relocatable according to the
+// standard. Notably, this means that marking a type [[clang::trivial_abi]] aka
+// ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI will have no effect on this trait.
 template <class T>
 struct is_trivially_relocatable
-    : std::integral_constant<bool, __is_trivially_relocatable(T)> {};
+    : std::integral_constant<bool, __builtin_is_cpp_trivially_relocatable(T)> {
+};
+#elif ABSL_HAVE_BUILTIN(__is_trivially_relocatable) && defined(__clang__) && \
+    !(defined(_WIN32) || defined(_WIN64)) && !defined(__APPLE__) &&          \
+    !defined(__NVCC__)
+// https://github.com/llvm/llvm-project/pull/139061
+//  __is_trivially_relocatable is deprecated.
+// TODO(b/325479096): Remove this case.
+template <class T>
+struct is_trivially_relocatable
+    : std::integral_constant<
+          bool, std::is_trivially_copyable<T>::value ||
+                    (__is_trivially_relocatable(T) &&
+                     std::is_trivially_move_assignable<T>::value)> {};
 #else
 // Otherwise we use a fallback that detects only those types we can feasibly
 // detect. Any type that is trivially copyable is by definition trivially
@@ -630,10 +513,8 @@
 struct IsView : std::integral_constant<bool, std::is_pointer<T>::value ||
                                                  IsViewImpl<T>::value> {};
 
-#ifdef ABSL_HAVE_STD_STRING_VIEW
 template <typename Char, typename Traits>
 struct IsView<std::basic_string_view<Char, Traits>> : std::true_type {};
-#endif
 
 #ifdef __cpp_lib_span
 template <typename T>
@@ -648,9 +529,9 @@
 // Until then, we consider an assignment from an "owner" (such as std::string)
 // to a "view" (such as std::string_view) to be a lifetime-bound assignment.
 template <typename T, typename U>
-using IsLifetimeBoundAssignment =
-    std::integral_constant<bool, IsView<absl::remove_cvref_t<T>>::value &&
-                                     IsOwner<absl::remove_cvref_t<U>>::value>;
+using IsLifetimeBoundAssignment = absl::conjunction<
+    std::integral_constant<bool, !std::is_lvalue_reference<U>::value>,
+    IsOwner<absl::remove_cvref_t<U>>, IsView<absl::remove_cvref_t<T>>>;
 
 }  // namespace type_traits_internal
 
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index 1e056bb..3d55a00 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -16,6 +16,7 @@
 
 #include <cstdint>
 #include <string>
+#include <string_view>
 #include <type_traits>
 #include <utility>
 #include <vector>
@@ -26,10 +27,6 @@
 #include "absl/time/clock.h"
 #include "absl/time/time.h"
 
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-#include <string_view>
-#endif
-
 namespace {
 
 using ::testing::StaticAssertTypeEq;
@@ -45,12 +42,10 @@
               "string is an owner, not a view");
 static_assert(IsOwnerAndNotView<std::wstring>::value,
               "wstring is an owner, not a view");
-#ifdef ABSL_HAVE_STD_STRING_VIEW
 static_assert(!IsOwnerAndNotView<std::string_view>::value,
               "string_view is a view, not an owner");
 static_assert(!IsOwnerAndNotView<std::wstring_view>::value,
               "wstring_view is a view, not an owner");
-#endif
 
 template <class T, class U>
 struct simple_pair {
@@ -90,10 +85,6 @@
 using BarIsCallable =
     absl::type_traits_internal::is_detected<BarIsCallableImpl, Class, T...>;
 
-template <class Class, class... T>
-using BarIsCallableConv = absl::type_traits_internal::is_detected_convertible<
-    ReturnType, BarIsCallableImpl, Class, T...>;
-
 // NOTE: Test of detail type_traits_internal::is_detected.
 TEST(IsDetectedTest, BasicUsage) {
   EXPECT_TRUE((BarIsCallable<TypeWithBarFunction, StructA&, const StructB&,
@@ -110,286 +101,11 @@
                               StructC>::value));
 }
 
-// NOTE: Test of detail type_traits_internal::is_detected_convertible.
-TEST(IsDetectedConvertibleTest, BasicUsage) {
-  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, const StructB&,
-                                 StructC>::value));
-  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, StructB&,
-                                 StructC>::value));
-  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunction, StructA&, StructB,
-                                 StructC>::value));
-  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType,
-                                 StructA&, const StructB&, StructC>::value));
-  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType,
-                                 StructA&, StructB&, StructC>::value));
-  EXPECT_TRUE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType,
-                                 StructA&, StructB, StructC>::value));
-
-  EXPECT_FALSE(
-      (BarIsCallableConv<int, StructA&, const StructB&, StructC>::value));
-  EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunction&, StructA&,
-                                  const StructB&, StructC>::value));
-  EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunction, StructA, const StructB&,
-                                  StructC>::value));
-  EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType&,
-                                  StructA&, const StructB&, StructC>::value));
-  EXPECT_FALSE((BarIsCallableConv<TypeWithBarFunctionAndConvertibleReturnType,
-                                  StructA, const StructB&, StructC>::value));
-}
-
 TEST(VoidTTest, BasicUsage) {
   StaticAssertTypeEq<void, absl::void_t<Dummy>>();
   StaticAssertTypeEq<void, absl::void_t<Dummy, Dummy, Dummy>>();
 }
 
-TEST(ConjunctionTest, BasicBooleanLogic) {
-  EXPECT_TRUE(absl::conjunction<>::value);
-  EXPECT_TRUE(absl::conjunction<std::true_type>::value);
-  EXPECT_TRUE((absl::conjunction<std::true_type, std::true_type>::value));
-  EXPECT_FALSE((absl::conjunction<std::true_type, std::false_type>::value));
-  EXPECT_FALSE((absl::conjunction<std::false_type, std::true_type>::value));
-  EXPECT_FALSE((absl::conjunction<std::false_type, std::false_type>::value));
-}
-
-struct MyTrueType {
-  static constexpr bool value = true;
-};
-
-struct MyFalseType {
-  static constexpr bool value = false;
-};
-
-TEST(ConjunctionTest, ShortCircuiting) {
-  EXPECT_FALSE(
-      (absl::conjunction<std::true_type, std::false_type, Dummy>::value));
-  EXPECT_TRUE((std::is_base_of<MyFalseType,
-                               absl::conjunction<std::true_type, MyFalseType,
-                                                 std::false_type>>::value));
-  EXPECT_TRUE(
-      (std::is_base_of<MyTrueType,
-                       absl::conjunction<std::true_type, MyTrueType>>::value));
-}
-
-TEST(DisjunctionTest, BasicBooleanLogic) {
-  EXPECT_FALSE(absl::disjunction<>::value);
-  EXPECT_FALSE(absl::disjunction<std::false_type>::value);
-  EXPECT_TRUE((absl::disjunction<std::true_type, std::true_type>::value));
-  EXPECT_TRUE((absl::disjunction<std::true_type, std::false_type>::value));
-  EXPECT_TRUE((absl::disjunction<std::false_type, std::true_type>::value));
-  EXPECT_FALSE((absl::disjunction<std::false_type, std::false_type>::value));
-}
-
-TEST(DisjunctionTest, ShortCircuiting) {
-  EXPECT_TRUE(
-      (absl::disjunction<std::false_type, std::true_type, Dummy>::value));
-  EXPECT_TRUE((
-      std::is_base_of<MyTrueType, absl::disjunction<std::false_type, MyTrueType,
-                                                    std::true_type>>::value));
-  EXPECT_TRUE((
-      std::is_base_of<MyFalseType,
-                      absl::disjunction<std::false_type, MyFalseType>>::value));
-}
-
-TEST(NegationTest, BasicBooleanLogic) {
-  EXPECT_FALSE(absl::negation<std::true_type>::value);
-  EXPECT_FALSE(absl::negation<MyTrueType>::value);
-  EXPECT_TRUE(absl::negation<std::false_type>::value);
-  EXPECT_TRUE(absl::negation<MyFalseType>::value);
-}
-
-// all member functions are trivial
-class Trivial {
-  int n_;
-};
-
-struct TrivialDestructor {
-  ~TrivialDestructor() = default;
-};
-
-struct NontrivialDestructor {
-  ~NontrivialDestructor() {}
-};
-
-struct DeletedDestructor {
-  ~DeletedDestructor() = delete;
-};
-
-class TrivialDefaultCtor {
- public:
-  TrivialDefaultCtor() = default;
-  explicit TrivialDefaultCtor(int n) : n_(n) {}
-
- private:
-  int n_;
-};
-
-class NontrivialDefaultCtor {
- public:
-  NontrivialDefaultCtor() : n_(1) {}
-
- private:
-  int n_;
-};
-
-class DeletedDefaultCtor {
- public:
-  DeletedDefaultCtor() = delete;
-  explicit DeletedDefaultCtor(int n) : n_(n) {}
-
- private:
-  int n_;
-};
-
-class TrivialMoveCtor {
- public:
-  explicit TrivialMoveCtor(int n) : n_(n) {}
-  TrivialMoveCtor(TrivialMoveCtor&&) = default;
-  TrivialMoveCtor& operator=(const TrivialMoveCtor& t) {
-    n_ = t.n_;
-    return *this;
-  }
-
- private:
-  int n_;
-};
-
-class NontrivialMoveCtor {
- public:
-  explicit NontrivialMoveCtor(int n) : n_(n) {}
-  NontrivialMoveCtor(NontrivialMoveCtor&& t) noexcept : n_(t.n_) {}
-  NontrivialMoveCtor& operator=(const NontrivialMoveCtor&) = default;
-
- private:
-  int n_;
-};
-
-class TrivialCopyCtor {
- public:
-  explicit TrivialCopyCtor(int n) : n_(n) {}
-  TrivialCopyCtor(const TrivialCopyCtor&) = default;
-  TrivialCopyCtor& operator=(const TrivialCopyCtor& t) {
-    n_ = t.n_;
-    return *this;
-  }
-
- private:
-  int n_;
-};
-
-class NontrivialCopyCtor {
- public:
-  explicit NontrivialCopyCtor(int n) : n_(n) {}
-  NontrivialCopyCtor(const NontrivialCopyCtor& t) : n_(t.n_) {}
-  NontrivialCopyCtor& operator=(const NontrivialCopyCtor&) = default;
-
- private:
-  int n_;
-};
-
-class DeletedCopyCtor {
- public:
-  explicit DeletedCopyCtor(int n) : n_(n) {}
-  DeletedCopyCtor(const DeletedCopyCtor&) = delete;
-  DeletedCopyCtor& operator=(const DeletedCopyCtor&) = default;
-
- private:
-  int n_;
-};
-
-class TrivialMoveAssign {
- public:
-  explicit TrivialMoveAssign(int n) : n_(n) {}
-  TrivialMoveAssign(const TrivialMoveAssign& t) : n_(t.n_) {}
-  TrivialMoveAssign& operator=(TrivialMoveAssign&&) = default;
-  ~TrivialMoveAssign() {}  // can have nontrivial destructor
- private:
-  int n_;
-};
-
-class NontrivialMoveAssign {
- public:
-  explicit NontrivialMoveAssign(int n) : n_(n) {}
-  NontrivialMoveAssign(const NontrivialMoveAssign&) = default;
-  NontrivialMoveAssign& operator=(NontrivialMoveAssign&& t) noexcept {
-    n_ = t.n_;
-    return *this;
-  }
-
- private:
-  int n_;
-};
-
-class TrivialCopyAssign {
- public:
-  explicit TrivialCopyAssign(int n) : n_(n) {}
-  TrivialCopyAssign(const TrivialCopyAssign& t) : n_(t.n_) {}
-  TrivialCopyAssign& operator=(const TrivialCopyAssign& t) = default;
-  ~TrivialCopyAssign() {}  // can have nontrivial destructor
- private:
-  int n_;
-};
-
-class NontrivialCopyAssign {
- public:
-  explicit NontrivialCopyAssign(int n) : n_(n) {}
-  NontrivialCopyAssign(const NontrivialCopyAssign&) = default;
-  NontrivialCopyAssign& operator=(const NontrivialCopyAssign& t) {
-    n_ = t.n_;
-    return *this;
-  }
-
- private:
-  int n_;
-};
-
-class DeletedCopyAssign {
- public:
-  explicit DeletedCopyAssign(int n) : n_(n) {}
-  DeletedCopyAssign(const DeletedCopyAssign&) = default;
-  DeletedCopyAssign& operator=(const DeletedCopyAssign&) = delete;
-
- private:
-  int n_;
-};
-
-struct MovableNonCopyable {
-  MovableNonCopyable() = default;
-  MovableNonCopyable(const MovableNonCopyable&) = delete;
-  MovableNonCopyable(MovableNonCopyable&&) = default;
-  MovableNonCopyable& operator=(const MovableNonCopyable&) = delete;
-  MovableNonCopyable& operator=(MovableNonCopyable&&) = default;
-};
-
-struct NonCopyableOrMovable {
-  NonCopyableOrMovable() = default;
-  virtual ~NonCopyableOrMovable() = default;
-  NonCopyableOrMovable(const NonCopyableOrMovable&) = delete;
-  NonCopyableOrMovable(NonCopyableOrMovable&&) = delete;
-  NonCopyableOrMovable& operator=(const NonCopyableOrMovable&) = delete;
-  NonCopyableOrMovable& operator=(NonCopyableOrMovable&&) = delete;
-};
-
-class Base {
- public:
-  virtual ~Base() {}
-};
-
-TEST(TypeTraitsTest, TestIsFunction) {
-  struct Callable {
-    void operator()() {}
-  };
-  EXPECT_TRUE(absl::is_function<void()>::value);
-  EXPECT_TRUE(absl::is_function<void()&>::value);
-  EXPECT_TRUE(absl::is_function<void() const>::value);
-  EXPECT_TRUE(absl::is_function<void() noexcept>::value);
-  EXPECT_TRUE(absl::is_function<void(...) noexcept>::value);
-
-  EXPECT_FALSE(absl::is_function<void (*)()>::value);
-  EXPECT_FALSE(absl::is_function<void (&)()>::value);
-  EXPECT_FALSE(absl::is_function<int>::value);
-  EXPECT_FALSE(absl::is_function<Callable>::value);
-}
-
 TEST(TypeTraitsTest, TestRemoveCVRef) {
   EXPECT_TRUE(
       (std::is_same<typename absl::remove_cvref<int>::type, int>::value));
@@ -418,124 +134,6 @@
                             int[2]>::value));
 }
 
-#define ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(trait_name, ...)          \
-  EXPECT_TRUE((std::is_same<typename std::trait_name<__VA_ARGS__>::type, \
-                            absl::trait_name##_t<__VA_ARGS__>>::value))
-
-TEST(TypeTraitsTest, TestRemoveCVAliases) {
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, const int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_cv, const volatile int);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, const int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_const, const volatile int);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, const int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_volatile, const volatile int);
-}
-
-TEST(TypeTraitsTest, TestAddCVAliases) {
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, const int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_cv, const volatile int);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, const int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_const, const volatile int);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, const int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_volatile, const volatile int);
-}
-
-TEST(TypeTraitsTest, TestReferenceAliases) {
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, volatile int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, int&&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_reference, volatile int&&);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, volatile int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, int&&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_lvalue_reference, volatile int&&);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, volatile int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, int&&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_rvalue_reference, volatile int&&);
-}
-
-TEST(TypeTraitsTest, TestPointerAliases) {
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_pointer, int*);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_pointer, volatile int*);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_pointer, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(add_pointer, volatile int);
-}
-
-TEST(TypeTraitsTest, TestSignednessAliases) {
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, unsigned);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_signed, volatile unsigned);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, unsigned);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(make_unsigned, volatile unsigned);
-}
-
-TEST(TypeTraitsTest, TestExtentAliases) {
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[]);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[1]);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[1][1]);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_extent, int[][1]);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[]);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[1]);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[1][1]);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(remove_all_extents, int[][1]);
-}
-
-TEST(TypeTraitsTest, TestDecay) {
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, volatile int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const volatile int);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, volatile int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const volatile int&);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, volatile int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, const volatile int&);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[1]);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[1][1]);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int[][1]);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int());
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(float));      // NOLINT
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(decay, int(char, ...));  // NOLINT
-}
-
 struct TypeA {};
 struct TypeB {};
 struct TypeC {};
@@ -568,36 +166,6 @@
   // NOTE: TypeD is intentionally not handled
 } constexpr GetType = {};
 
-TEST(TypeTraitsTest, TestEnableIf) {
-  EXPECT_EQ(TypeEnum::A, GetType(Wrap<TypeA>()));
-  EXPECT_EQ(TypeEnum::B, GetType(Wrap<TypeB>()));
-  EXPECT_EQ(TypeEnum::C, GetType(Wrap<TypeC>()));
-}
-
-TEST(TypeTraitsTest, TestConditional) {
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(conditional, true, int, char);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(conditional, false, int, char);
-}
-
-// TODO(calabrese) Check with specialized std::common_type
-TEST(TypeTraitsTest, TestCommonType) {
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char, int);
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char&);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(common_type, int, char, int&);
-}
-
-TEST(TypeTraitsTest, TestUnderlyingType) {
-  enum class enum_char : char {};
-  enum class enum_long_long : long long {};  // NOLINT(runtime/int)
-
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(underlying_type, enum_char);
-  ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(underlying_type, enum_long_long);
-}
-
 struct GetTypeExtT {
   template <typename T>
   absl::result_of_t<const GetTypeT&(T)> operator()(T&& arg) const {
@@ -765,29 +333,6 @@
   static_assert(!absl::is_trivially_relocatable<S>::value, "");
 }
 
-// TODO(b/275003464): remove the opt-out for Clang on Windows once
-// __is_trivially_relocatable is used there again.
-// TODO(b/324278148): remove the opt-out for Apple once
-// __is_trivially_relocatable is fixed there.
-#if defined(ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI) &&      \
-    ABSL_HAVE_BUILTIN(__is_trivially_relocatable) && \
-    (defined(__cpp_impl_trivially_relocatable) ||    \
-     (!defined(__clang__) && !defined(__APPLE__) && !defined(__NVCC__)))
-// A type marked with the "trivial ABI" attribute is trivially relocatable even
-// if it has user-provided special members.
-TEST(TriviallyRelocatable, TrivialAbi) {
-  struct ABSL_ATTRIBUTE_TRIVIAL_ABI S {
-    S(S&&) {}       // NOLINT(modernize-use-equals-default)
-    S(const S&) {}  // NOLINT(modernize-use-equals-default)
-    void operator=(S&&) {}
-    void operator=(const S&) {}
-    ~S() {}  // NOLINT(modernize-use-equals-default)
-  };
-
-  static_assert(absl::is_trivially_relocatable<S>::value, "");
-}
-#endif
-
 #ifdef ABSL_HAVE_CONSTANT_EVALUATED
 
 constexpr int64_t NegateIfConstantEvaluated(int64_t i) {
diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel
index f202c6e..f455d1e 100644
--- a/absl/numeric/BUILD.bazel
+++ b/absl/numeric/BUILD.bazel
@@ -41,6 +41,7 @@
     deps = [
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:endian",
     ],
 )
 
@@ -54,8 +55,7 @@
         ":bits",
         "//absl/base:core_headers",
         "//absl/random",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -70,8 +70,8 @@
     deps = [
         ":bits",
         "//absl/random",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -109,13 +109,14 @@
         "//absl/meta:type_traits",
         "//absl/strings",
         "//absl/types:compare",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "int128_benchmark",
+    testonly = True,
     srcs = ["int128_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -123,8 +124,8 @@
     deps = [
         ":int128",
         "//absl/base:config",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "//absl/random",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
diff --git a/absl/numeric/CMakeLists.txt b/absl/numeric/CMakeLists.txt
index da3b6ef..68446b0 100644
--- a/absl/numeric/CMakeLists.txt
+++ b/absl/numeric/CMakeLists.txt
@@ -23,7 +23,9 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::config
     absl::core_headers
+    absl::endian
   PUBLIC
 )
 
diff --git a/absl/numeric/bits.h b/absl/numeric/bits.h
index c76454c..9a0c229 100644
--- a/absl/numeric/bits.h
+++ b/absl/numeric/bits.h
@@ -27,6 +27,10 @@
 //  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html
 // P1956R1:
 //  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf
+// P0463R1
+//  https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0463r1.html
+// P1272R4
+//  https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1272r4.html
 //
 // When using a standard library that implements these functions, we use the
 // standard library's implementation.
@@ -45,6 +49,7 @@
 #endif
 
 #include "absl/base/attributes.h"
+#include "absl/base/internal/endian.h"
 #include "absl/numeric/internal/bits.h"
 
 namespace absl {
@@ -63,14 +68,14 @@
 
 // Rotating functions
 template <class T>
-ABSL_MUST_USE_RESULT constexpr
+[[nodiscard]] constexpr
     typename std::enable_if<std::is_unsigned<T>::value, T>::type
     rotl(T x, int s) noexcept {
   return numeric_internal::RotateLeft(x, s);
 }
 
 template <class T>
-ABSL_MUST_USE_RESULT constexpr
+[[nodiscard]] constexpr
     typename std::enable_if<std::is_unsigned<T>::value, T>::type
     rotr(T x, int s) noexcept {
   return numeric_internal::RotateRight(x, s);
@@ -190,6 +195,67 @@
 
 #endif
 
+#if defined(__cpp_lib_endian) && __cpp_lib_endian >= 201907L
+
+// https://en.cppreference.com/w/cpp/types/endian
+//
+// Indicates the endianness of all scalar types:
+//   * If all scalar types are little-endian, `absl::endian::native` equals
+//     absl::endian::little.
+//   * If all scalar types are big-endian, `absl::endian::native` equals
+//     `absl::endian::big`.
+//   * Platforms that use anything else are unsupported.
+using std::endian;
+
+#else
+
+enum class endian {
+  little,
+  big,
+#if defined(ABSL_IS_LITTLE_ENDIAN)
+  native = little
+#elif defined(ABSL_IS_BIG_ENDIAN)
+  native = big
+#else
+#error "Endian detection needs to be set up for this platform"
+#endif
+};
+
+#endif  // defined(__cpp_lib_endian) && __cpp_lib_endian >= 201907L
+
+#if defined(__cpp_lib_byteswap) && __cpp_lib_byteswap >= 202110L
+
+// https://en.cppreference.com/w/cpp/numeric/byteswap
+//
+// Reverses the bytes in the given integer value `x`.
+//
+// `absl::byteswap` participates in overload resolution only if `T` satisfies
+// integral, i.e., `T` is an integer type. The program is ill-formed if `T` has
+// padding bits.
+using std::byteswap;
+
+#else
+
+template <class T>
+[[nodiscard]] constexpr T byteswap(T x) noexcept {
+  static_assert(std::is_integral_v<T>,
+                "byteswap requires an integral argument");
+  static_assert(
+      sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8,
+      "byteswap works only with 8, 16, 32, or 64-bit integers");
+  if constexpr (sizeof(T) == 1) {
+    return x;
+  } else if constexpr (sizeof(T) == 2) {
+    return static_cast<T>(gbswap_16(static_cast<uint16_t>(x)));
+  } else if constexpr (sizeof(T) == 4) {
+    return static_cast<T>(gbswap_32(static_cast<uint32_t>(x)));
+  } else if constexpr (sizeof(T) == 8) {
+    return static_cast<T>(gbswap_64(static_cast<uint64_t>(x)));
+  }
+}
+
+#endif  // defined(__cpp_lib_byteswap) && __cpp_lib_byteswap >= 202110L
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/numeric/bits_benchmark.cc b/absl/numeric/bits_benchmark.cc
index 2c89afd..429b4ca 100644
--- a/absl/numeric/bits_benchmark.cc
+++ b/absl/numeric/bits_benchmark.cc
@@ -15,10 +15,10 @@
 #include <cstdint>
 #include <vector>
 
-#include "benchmark/benchmark.h"
 #include "absl/base/optimization.h"
 #include "absl/numeric/bits.h"
 #include "absl/random/random.h"
+#include "benchmark/benchmark.h"
 
 namespace absl {
 namespace {
diff --git a/absl/numeric/bits_test.cc b/absl/numeric/bits_test.cc
index 14955eb..3b71ccc 100644
--- a/absl/numeric/bits_test.cc
+++ b/absl/numeric/bits_test.cc
@@ -14,6 +14,7 @@
 
 #include "absl/numeric/bits.h"
 
+#include <cstdint>
 #include <limits>
 #include <type_traits>
 
@@ -636,6 +637,61 @@
 static_assert(ABSL_INTERNAL_HAS_CONSTEXPR_CTZ, "ctz should be constexpr");
 #endif
 
+TEST(Endian, Comparison) {
+#if defined(ABSL_IS_LITTLE_ENDIAN)
+  static_assert(absl::endian::native == absl::endian::little);
+  static_assert(absl::endian::native != absl::endian::big);
+#endif
+#if defined(ABSL_IS_BIG_ENDIAN)
+  static_assert(absl::endian::native != absl::endian::little);
+  static_assert(absl::endian::native == absl::endian::big);
+#endif
+}
+
+TEST(Byteswap, Constexpr) {
+  static_assert(absl::byteswap<int8_t>(0x12) == 0x12);
+  static_assert(absl::byteswap<int16_t>(0x1234) == 0x3412);
+  static_assert(absl::byteswap<int32_t>(0x12345678) == 0x78563412);
+  static_assert(absl::byteswap<int64_t>(0x123456789abcdef0) ==
+                static_cast<int64_t>(0xf0debc9a78563412));
+  static_assert(absl::byteswap<uint8_t>(0x21) == 0x21);
+  static_assert(absl::byteswap<uint16_t>(0x4321) == 0x2143);
+  static_assert(absl::byteswap<uint32_t>(0x87654321) == 0x21436587);
+  static_assert(absl::byteswap<uint64_t>(0xfedcba9876543210) ==
+                static_cast<uint64_t>(0x1032547698badcfe));
+  static_assert(absl::byteswap<int32_t>(static_cast<int32_t>(0xdeadbeef)) ==
+                static_cast<int32_t>(0xefbeadde));
+}
+
+TEST(Byteswap, NotConstexpr) {
+  int8_t a = 0x12;
+  int16_t b = 0x1234;
+  int32_t c = 0x12345678;
+  int64_t d = 0x123456789abcdef0;
+  uint8_t e = 0x21;
+  uint16_t f = 0x4321;
+  uint32_t g = 0x87654321;
+  uint64_t h = 0xfedcba9876543210;
+  EXPECT_EQ(absl::byteswap<int8_t>(a), 0x12);
+  EXPECT_EQ(absl::byteswap<int16_t>(b), 0x3412);
+  EXPECT_EQ(absl::byteswap(c), 0x78563412);
+  EXPECT_EQ(absl::byteswap(d), 0xf0debc9a78563412);
+  EXPECT_EQ(absl::byteswap<uint8_t>(e), 0x21);
+  EXPECT_EQ(absl::byteswap<uint16_t>(f), 0x2143);
+  EXPECT_EQ(absl::byteswap(g), 0x21436587);
+  EXPECT_EQ(absl::byteswap(h), 0x1032547698badcfe);
+  EXPECT_EQ(absl::byteswap(absl::byteswap<int8_t>(a)), a);
+  EXPECT_EQ(absl::byteswap(absl::byteswap<int16_t>(b)), b);
+  EXPECT_EQ(absl::byteswap(absl::byteswap(c)), c);
+  EXPECT_EQ(absl::byteswap(absl::byteswap(d)), d);
+  EXPECT_EQ(absl::byteswap(absl::byteswap<uint8_t>(e)), e);
+  EXPECT_EQ(absl::byteswap(absl::byteswap<uint16_t>(f)), f);
+  EXPECT_EQ(absl::byteswap(absl::byteswap(g)), g);
+  EXPECT_EQ(absl::byteswap(absl::byteswap(h)), h);
+  EXPECT_EQ(absl::byteswap<uint32_t>(0xdeadbeef), 0xefbeadde);
+  EXPECT_EQ(absl::byteswap<const uint32_t>(0xdeadbeef), 0xefbeadde);
+}
+
 }  // namespace
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc
index 5d6c68d..281bf12 100644
--- a/absl/numeric/int128.cc
+++ b/absl/numeric/int128.cc
@@ -342,55 +342,3 @@
 
 ABSL_NAMESPACE_END
 }  // namespace absl
-
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-namespace std {
-constexpr bool numeric_limits<absl::uint128>::is_specialized;
-constexpr bool numeric_limits<absl::uint128>::is_signed;
-constexpr bool numeric_limits<absl::uint128>::is_integer;
-constexpr bool numeric_limits<absl::uint128>::is_exact;
-constexpr bool numeric_limits<absl::uint128>::has_infinity;
-constexpr bool numeric_limits<absl::uint128>::has_quiet_NaN;
-constexpr bool numeric_limits<absl::uint128>::has_signaling_NaN;
-constexpr float_denorm_style numeric_limits<absl::uint128>::has_denorm;
-constexpr bool numeric_limits<absl::uint128>::has_denorm_loss;
-constexpr float_round_style numeric_limits<absl::uint128>::round_style;
-constexpr bool numeric_limits<absl::uint128>::is_iec559;
-constexpr bool numeric_limits<absl::uint128>::is_bounded;
-constexpr bool numeric_limits<absl::uint128>::is_modulo;
-constexpr int numeric_limits<absl::uint128>::digits;
-constexpr int numeric_limits<absl::uint128>::digits10;
-constexpr int numeric_limits<absl::uint128>::max_digits10;
-constexpr int numeric_limits<absl::uint128>::radix;
-constexpr int numeric_limits<absl::uint128>::min_exponent;
-constexpr int numeric_limits<absl::uint128>::min_exponent10;
-constexpr int numeric_limits<absl::uint128>::max_exponent;
-constexpr int numeric_limits<absl::uint128>::max_exponent10;
-constexpr bool numeric_limits<absl::uint128>::traps;
-constexpr bool numeric_limits<absl::uint128>::tinyness_before;
-
-constexpr bool numeric_limits<absl::int128>::is_specialized;
-constexpr bool numeric_limits<absl::int128>::is_signed;
-constexpr bool numeric_limits<absl::int128>::is_integer;
-constexpr bool numeric_limits<absl::int128>::is_exact;
-constexpr bool numeric_limits<absl::int128>::has_infinity;
-constexpr bool numeric_limits<absl::int128>::has_quiet_NaN;
-constexpr bool numeric_limits<absl::int128>::has_signaling_NaN;
-constexpr float_denorm_style numeric_limits<absl::int128>::has_denorm;
-constexpr bool numeric_limits<absl::int128>::has_denorm_loss;
-constexpr float_round_style numeric_limits<absl::int128>::round_style;
-constexpr bool numeric_limits<absl::int128>::is_iec559;
-constexpr bool numeric_limits<absl::int128>::is_bounded;
-constexpr bool numeric_limits<absl::int128>::is_modulo;
-constexpr int numeric_limits<absl::int128>::digits;
-constexpr int numeric_limits<absl::int128>::digits10;
-constexpr int numeric_limits<absl::int128>::max_digits10;
-constexpr int numeric_limits<absl::int128>::radix;
-constexpr int numeric_limits<absl::int128>::min_exponent;
-constexpr int numeric_limits<absl::int128>::min_exponent10;
-constexpr int numeric_limits<absl::int128>::max_exponent;
-constexpr int numeric_limits<absl::int128>::max_exponent10;
-constexpr bool numeric_limits<absl::int128>::traps;
-constexpr bool numeric_limits<absl::int128>::tinyness_before;
-}  // namespace std
-#endif
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index 5a067d1..ae736b2 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -216,7 +216,11 @@
   // Support for absl::Hash.
   template <typename H>
   friend H AbslHashValue(H h, uint128 v) {
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+    return H::combine(std::move(h), static_cast<unsigned __int128>(v));
+#else
     return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v));
+#endif
   }
 
   // Support for absl::StrCat() etc.
@@ -458,7 +462,11 @@
   // Support for absl::Hash.
   template <typename H>
   friend H AbslHashValue(H h, int128 v) {
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+    return H::combine(std::move(h), v.v_);
+#else
     return H::combine(std::move(h), Int128High64(v), Int128Low64(v));
+#endif
   }
 
   // Support for absl::StrCat() etc.
@@ -781,16 +789,20 @@
 // Conversion operators to floating point types.
 
 inline uint128::operator float() const {
-  return static_cast<float>(lo_) + std::ldexp(static_cast<float>(hi_), 64);
+  // Note: This method might return Inf.
+  constexpr float pow_2_64 = 18446744073709551616.0f;
+  return static_cast<float>(lo_) + static_cast<float>(hi_) * pow_2_64;
 }
 
 inline uint128::operator double() const {
-  return static_cast<double>(lo_) + std::ldexp(static_cast<double>(hi_), 64);
+  constexpr double pow_2_64 = 18446744073709551616.0;
+  return static_cast<double>(lo_) + static_cast<double>(hi_) * pow_2_64;
 }
 
 inline uint128::operator long double() const {
+  constexpr long double pow_2_64 = 18446744073709551616.0L;
   return static_cast<long double>(lo_) +
-         std::ldexp(static_cast<long double>(hi_), 64);
+         static_cast<long double>(hi_) * pow_2_64;
 }
 
 // Comparison operators.
diff --git a/absl/numeric/int128_benchmark.cc b/absl/numeric/int128_benchmark.cc
index eab1515..c37abec 100644
--- a/absl/numeric/int128_benchmark.cc
+++ b/absl/numeric/int128_benchmark.cc
@@ -13,31 +13,29 @@
 // limitations under the License.
 
 #include <algorithm>
+#include <cstddef>
 #include <cstdint>
 #include <limits>
 #include <random>
+#include <type_traits>
+#include <utility>
 #include <vector>
 
-#include "benchmark/benchmark.h"
 #include "absl/base/config.h"
 #include "absl/numeric/int128.h"
+#include "absl/random/random.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
 constexpr size_t kSampleSize = 1000000;
 
-std::mt19937 MakeRandomEngine() {
-  std::random_device r;
-  std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()});
-  return std::mt19937(seed);
-}
-
 template <typename T,
           typename H = typename std::conditional<
               std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>
 std::vector<std::pair<T, T>> GetRandomClass128SampleUniformDivisor() {
   std::vector<std::pair<T, T>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   std::uniform_int_distribution<H> uniform_h;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
@@ -77,7 +75,7 @@
               std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>
 std::vector<std::pair<T, H>> GetRandomClass128SampleSmallDivisor() {
   std::vector<std::pair<T, H>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   std::uniform_int_distribution<H> uniform_h;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
@@ -114,7 +112,7 @@
 
 std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() {
   std::vector<std::pair<absl::uint128, absl::uint128>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   std::uniform_int_distribution<uint64_t> uniform_uint64;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
@@ -155,7 +153,8 @@
 class UniformIntDistribution128 {
  public:
   // NOLINTNEXTLINE: mimicking std::uniform_int_distribution API
-  T operator()(std::mt19937& generator) {
+  template <class URBG>
+  T operator()(URBG& generator) {
     return (static_cast<T>(dist64_(generator)) << 64) | dist64_(generator);
   }
 
@@ -168,7 +167,7 @@
               std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
 std::vector<std::pair<T, T>> GetRandomIntrinsic128SampleUniformDivisor() {
   std::vector<std::pair<T, T>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   UniformIntDistribution128<T> uniform_128;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
@@ -209,7 +208,7 @@
               std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
 std::vector<std::pair<T, H>> GetRandomIntrinsic128SampleSmallDivisor() {
   std::vector<std::pair<T, H>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   UniformIntDistribution128<T> uniform_int128;
   std::uniform_int_distribution<H> uniform_int64;
   values.reserve(kSampleSize);
@@ -246,9 +245,9 @@
 BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __int128);
 
 std::vector<std::pair<unsigned __int128, unsigned __int128>>
-      GetRandomIntrinsic128Sample() {
+GetRandomIntrinsic128Sample() {
   std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
-  std::mt19937 random = MakeRandomEngine();
+  absl::InsecureBitGen random;
   UniformIntDistribution128<unsigned __int128> uniform_uint128;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
diff --git a/absl/numeric/int128_have_intrinsic.inc b/absl/numeric/int128_have_intrinsic.inc
index 51e4b9d..216115a 100644
--- a/absl/numeric/int128_have_intrinsic.inc
+++ b/absl/numeric/int128_have_intrinsic.inc
@@ -170,27 +170,29 @@
   // complement overwhelms the precision of the mantissa.
   //
   // Also check to make sure we don't negate Int128Min()
+  constexpr float pow_2_64 = 18446744073709551616.0f;
   return v_ < 0 && *this != Int128Min()
              ? -static_cast<float>(-*this)
              : static_cast<float>(Int128Low64(*this)) +
-                   std::ldexp(static_cast<float>(Int128High64(*this)), 64);
+                   static_cast<float>(Int128High64(*this)) * pow_2_64;
 }
 
 inline int128::operator double() const {
   // See comment in int128::operator float() above.
+  constexpr double pow_2_64 = 18446744073709551616.0;
   return v_ < 0 && *this != Int128Min()
              ? -static_cast<double>(-*this)
              : static_cast<double>(Int128Low64(*this)) +
-                   std::ldexp(static_cast<double>(Int128High64(*this)), 64);
+                   static_cast<double>(Int128High64(*this)) * pow_2_64;
 }
 
 inline int128::operator long double() const {
   // See comment in int128::operator float() above.
+  constexpr long double pow_2_64 = 18446744073709551616.0L;
   return v_ < 0 && *this != Int128Min()
              ? -static_cast<long double>(-*this)
              : static_cast<long double>(Int128Low64(*this)) +
-                   std::ldexp(static_cast<long double>(Int128High64(*this)),
-                              64);
+                   static_cast<long double>(Int128High64(*this)) * pow_2_64;
 }
 #endif  // Clang on PowerPC
 
diff --git a/absl/numeric/int128_no_intrinsic.inc b/absl/numeric/int128_no_intrinsic.inc
index 195b745..a7cdcea 100644
--- a/absl/numeric/int128_no_intrinsic.inc
+++ b/absl/numeric/int128_no_intrinsic.inc
@@ -139,26 +139,29 @@
   // complement overwhelms the precision of the mantissa.
   //
   // Also check to make sure we don't negate Int128Min()
+  constexpr float pow_2_64 = 18446744073709551616.0f;
   return hi_ < 0 && *this != Int128Min()
              ? -static_cast<float>(-*this)
              : static_cast<float>(lo_) +
-                   std::ldexp(static_cast<float>(hi_), 64);
+                   static_cast<float>(hi_) * pow_2_64;
 }
 
 inline int128::operator double() const {
   // See comment in int128::operator float() above.
+  constexpr double pow_2_64 = 18446744073709551616.0;
   return hi_ < 0 && *this != Int128Min()
              ? -static_cast<double>(-*this)
              : static_cast<double>(lo_) +
-                   std::ldexp(static_cast<double>(hi_), 64);
+                   static_cast<double>(hi_) * pow_2_64;
 }
 
 inline int128::operator long double() const {
   // See comment in int128::operator float() above.
+  constexpr long double pow_2_64 = 18446744073709551616.0L;
   return hi_ < 0 && *this != Int128Min()
              ? -static_cast<long double>(-*this)
              : static_cast<long double>(lo_) +
-                   std::ldexp(static_cast<long double>(hi_), 64);
+                   static_cast<long double>(hi_) * pow_2_64;
 }
 
 // Comparison operators.
diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc
index 3f16e05..13a0e7f 100644
--- a/absl/numeric/int128_test.cc
+++ b/absl/numeric/int128_test.cc
@@ -17,11 +17,13 @@
 #include <algorithm>
 #include <limits>
 #include <random>
+#include <tuple>
 #include <type_traits>
 #include <utility>
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/casts.h"
 #include "absl/base/internal/cycleclock.h"
 #include "absl/hash/hash_testing.h"
 #include "absl/meta/type_traits.h"
@@ -473,29 +475,51 @@
   EXPECT_EQ(absl::Uint128Max(), std::numeric_limits<absl::uint128>::max());
 }
 
+// Some arbitrary constant to test hashing. The first hex digits of pi.
+constexpr absl::uint128 kPi = (absl::uint128(0x3243f6a8885a308d) << 64) |
+                              absl::uint128(0x313198a2e0370734);
+
 TEST(Uint128, Hash) {
-  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+  using Ext128 = unsigned __int128;
+#endif
+  // Make the tuple outside the EXPECT_TRUE because putting the #if inside the
+  // macro argument is not ok.
+  const auto values = std::make_tuple(
       // Some simple values
-      absl::uint128{0},
-      absl::uint128{1},
-      ~absl::uint128{},
+      absl::uint128{0}, absl::uint128{1}, ~absl::uint128{},
       // 64 bit limits
       absl::uint128{std::numeric_limits<int64_t>::max()},
       absl::uint128{std::numeric_limits<uint64_t>::max()} + 0,
       absl::uint128{std::numeric_limits<uint64_t>::max()} + 1,
       absl::uint128{std::numeric_limits<uint64_t>::max()} + 2,
       // Keeping high same
-      absl::uint128{1} << 62,
-      absl::uint128{1} << 63,
+      absl::uint128{1} << 62, absl::uint128{1} << 63,
       // Keeping low same
-      absl::uint128{1} << 64,
-      absl::uint128{1} << 65,
+      absl::uint128{1} << 64, absl::uint128{1} << 65,
       // 128 bit limits
       std::numeric_limits<absl::uint128>::max(),
       std::numeric_limits<absl::uint128>::max() - 1,
       std::numeric_limits<absl::uint128>::min() + 1,
       std::numeric_limits<absl::uint128>::min(),
-  }));
+      // arbitrary constant
+      kPi
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+      // Same but with the intrinsic to verify that they match
+      ,
+      Ext128{0}, Ext128{1}, ~Ext128{},
+      Ext128{std::numeric_limits<int64_t>::max()},
+      Ext128{std::numeric_limits<uint64_t>::max()} + 0,
+      Ext128{std::numeric_limits<uint64_t>::max()} + 1,
+      Ext128{std::numeric_limits<uint64_t>::max()} + 2, Ext128{1} << 62,
+      Ext128{1} << 63, Ext128{1} << 64, Ext128{1} << 65,
+      std::numeric_limits<Ext128>::max(),
+      std::numeric_limits<Ext128>::max() - 1,
+      std::numeric_limits<Ext128>::min() + 1,
+      std::numeric_limits<Ext128>::min(), static_cast<Ext128>(kPi)
+#endif
+  );
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(values));
 }
 
 
@@ -1249,19 +1273,24 @@
     }
   }
 
+  // Signed integer overflow is undefined behavior, so in these cases enough
+  // high bits must be zero to avoid over-shifting.
+  EXPECT_EQ(MAKE_INT128(0x0, 0x123456789abcdef0) << 63,
+            MAKE_INT128(0x91a2b3c4d5e6f78, 0x0));
+  EXPECT_EQ(MAKE_INT128(0x0, 0x123456789abcdef0) << 64,
+            MAKE_INT128(0x123456789abcdef0, 0x0));
+  EXPECT_EQ(MAKE_INT128(0x1, 0xfedcba0987654321) << 63,
+            MAKE_INT128(0xff6e5d04c3b2a190, 0x8000000000000000));
+  EXPECT_EQ(MAKE_INT128(0x0, 0xfedcba0987654321) << 64,
+            MAKE_INT128(0xfedcba0987654321, 0x0));
+  EXPECT_EQ(MAKE_INT128(0x0, 0x0) << 126, MAKE_INT128(0x0, 0x0));
+  EXPECT_EQ(MAKE_INT128(0x0, 0x1) << 126, MAKE_INT128(0x4000000000000000, 0x0));
+
   // Manually calculated cases with shift count for positive (val1) and negative
   // (val2) values
   absl::int128 val1 = MAKE_INT128(0x123456789abcdef0, 0x123456789abcdef0);
   absl::int128 val2 = MAKE_INT128(0xfedcba0987654321, 0xfedcba0987654321);
 
-  EXPECT_EQ(val1 << 63, MAKE_INT128(0x91a2b3c4d5e6f78, 0x0));
-  EXPECT_EQ(val1 << 64, MAKE_INT128(0x123456789abcdef0, 0x0));
-  EXPECT_EQ(val2 << 63, MAKE_INT128(0xff6e5d04c3b2a190, 0x8000000000000000));
-  EXPECT_EQ(val2 << 64, MAKE_INT128(0xfedcba0987654321, 0x0));
-
-  EXPECT_EQ(val1 << 126, MAKE_INT128(0x0, 0x0));
-  EXPECT_EQ(val2 << 126, MAKE_INT128(0x4000000000000000, 0x0));
-
   EXPECT_EQ(val1 >> 63, MAKE_INT128(0x0, 0x2468acf13579bde0));
   EXPECT_EQ(val1 >> 64, MAKE_INT128(0x0, 0x123456789abcdef0));
   EXPECT_EQ(val2 >> 63, MAKE_INT128(0xffffffffffffffff, 0xfdb974130eca8643));
@@ -1282,4 +1311,50 @@
   EXPECT_EQ(absl::Int128Max(), std::numeric_limits<absl::int128>::max());
 }
 
+TEST(Int128, BitCastable) {
+  // NOTE: This test is not intended to be an example that demonstrate usages of
+  // `static_cast` and `std::bit_cast`, rather it is here simply to verify
+  // behavior. When deciding whether you should use `static_cast` or
+  // `std::bit_cast` when converting between `absl::int128` and `absl::uint128`,
+  // use your best judgement. As a rule of thumb, use the same cast that you
+  // would use when converting between the signed and unsigned counterparts of a
+  // builtin integral type.
+
+  // Verify bit casting between signed and unsigned works with regards to two's
+  // complement. This verifies we exhibit the same behavior as a theoretical
+  // builtin int128_t and uint128_t in C++20 onwards.
+  EXPECT_EQ(absl::bit_cast<absl::uint128>(absl::int128(-1)),
+            std::numeric_limits<absl::uint128>::max());
+  EXPECT_EQ(
+      absl::bit_cast<absl::int128>(std::numeric_limits<absl::uint128>::max()),
+      absl::int128(-1));
+  EXPECT_EQ(
+      absl::bit_cast<absl::uint128>(std::numeric_limits<absl::int128>::min()),
+      absl::uint128(1) << 127);
+  EXPECT_EQ(absl::bit_cast<absl::int128>(absl::uint128(1) << 127),
+            std::numeric_limits<absl::int128>::min());
+  EXPECT_EQ(
+      absl::bit_cast<absl::uint128>(std::numeric_limits<absl::int128>::max()),
+      (absl::uint128(1) << 127) - 1);
+  EXPECT_EQ(absl::bit_cast<absl::int128>((absl::uint128(1) << 127) - 1),
+            std::numeric_limits<absl::int128>::max());
+
+  // Also verify static casting has the same behavior as bit casting.
+  EXPECT_EQ(static_cast<absl::uint128>(absl::int128(-1)),
+            std::numeric_limits<absl::uint128>::max());
+  EXPECT_EQ(
+      static_cast<absl::int128>(std::numeric_limits<absl::uint128>::max()),
+      absl::int128(-1));
+  EXPECT_EQ(
+      static_cast<absl::uint128>(std::numeric_limits<absl::int128>::min()),
+      absl::uint128(1) << 127);
+  EXPECT_EQ(static_cast<absl::int128>(absl::uint128(1) << 127),
+            std::numeric_limits<absl::int128>::min());
+  EXPECT_EQ(
+      static_cast<absl::uint128>(std::numeric_limits<absl::int128>::max()),
+      (absl::uint128(1) << 127) - 1);
+  EXPECT_EQ(static_cast<absl::int128>((absl::uint128(1) << 127) - 1),
+            std::numeric_limits<absl::int128>::max());
+}
+
 }  // namespace
diff --git a/absl/numeric/internal/bits.h b/absl/numeric/internal/bits.h
index 0917464..e1d18b8 100644
--- a/absl/numeric/internal/bits.h
+++ b/absl/numeric/internal/bits.h
@@ -71,7 +71,7 @@
 }
 
 template <class T>
-ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight(
+[[nodiscard]] ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight(
     T x, int s) noexcept {
   static_assert(std::is_unsigned<T>::value, "T must be unsigned");
   static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
@@ -82,7 +82,7 @@
 }
 
 template <class T>
-ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft(
+[[nodiscard]] ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft(
     T x, int s) noexcept {
   static_assert(std::is_unsigned<T>::value, "T must be unsigned");
   static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
@@ -126,7 +126,11 @@
   static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
                 "T must have a power-of-2 size");
   static_assert(sizeof(x) <= sizeof(uint64_t), "T is too large");
-  return sizeof(x) <= sizeof(uint32_t) ? Popcount32(x) : Popcount64(x);
+  if constexpr (sizeof(x) <= sizeof(uint32_t)) {
+    return Popcount32(x);
+  } else {
+    return Popcount64(x);
+  }
 }
 
 ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
diff --git a/absl/profiling/BUILD.bazel b/absl/profiling/BUILD.bazel
index abe127e..ee4800d 100644
--- a/absl/profiling/BUILD.bazel
+++ b/absl/profiling/BUILD.bazel
@@ -56,11 +56,12 @@
     deps = [
         ":sample_recorder",
         "//absl/base:core_headers",
+        "//absl/random",
         "//absl/synchronization",
         "//absl/synchronization:thread_pool",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -88,8 +89,8 @@
     deps = [
         ":exponential_biased",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -119,8 +120,8 @@
     deps = [
         ":periodic_sampler",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -135,6 +136,6 @@
     deps = [
         ":periodic_sampler",
         "//absl/base:core_headers",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/profiling/CMakeLists.txt b/absl/profiling/CMakeLists.txt
index 9b3a710..84b8b3b 100644
--- a/absl/profiling/CMakeLists.txt
+++ b/absl/profiling/CMakeLists.txt
@@ -32,6 +32,7 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::random_random
     absl::sample_recorder
     absl::time
     GTest::gmock_main
diff --git a/absl/profiling/internal/exponential_biased.cc b/absl/profiling/internal/exponential_biased.cc
index 81d9a75..918d063 100644
--- a/absl/profiling/internal/exponential_biased.cc
+++ b/absl/profiling/internal/exponential_biased.cc
@@ -66,7 +66,7 @@
   }
   double value = std::rint(interval);
   bias_ = interval - value;
-  return value;
+  return static_cast<int64_t>(value);
 }
 
 int64_t ExponentialBiased::GetStride(int64_t mean) {
diff --git a/absl/profiling/internal/sample_recorder_test.cc b/absl/profiling/internal/sample_recorder_test.cc
index 3373329..a037f9d 100644
--- a/absl/profiling/internal/sample_recorder_test.cc
+++ b/absl/profiling/internal/sample_recorder_test.cc
@@ -15,14 +15,20 @@
 #include "absl/profiling/internal/sample_recorder.h"
 
 #include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
 #include <random>
 #include <vector>
 
 #include "gmock/gmock.h"
+#include "gtest/gtest.h"
 #include "absl/base/thread_annotations.h"
+#include "absl/random/random.h"
 #include "absl/synchronization/internal/thread_pool.h"
 #include "absl/synchronization/mutex.h"
 #include "absl/synchronization/notification.h"
+#include "absl/time/clock.h"
 #include "absl/time/time.h"
 
 namespace absl {
@@ -112,9 +118,7 @@
 
   for (int i = 0; i < 10; ++i) {
     pool.Schedule([&sampler, &stop, i]() {
-      std::random_device rd;
-      std::mt19937 gen(rd());
-
+      absl::InsecureBitGen gen;
       std::vector<Info*> infoz;
       while (!stop.HasBeenNotified()) {
         if (infoz.empty()) {
diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel
index f276cc0..887ab0f 100644
--- a/absl/random/BUILD.bazel
+++ b/absl/random/BUILD.bazel
@@ -42,9 +42,9 @@
     deps = [
         ":distributions",
         ":seed_sequences",
+        "//absl/base:config",
         "//absl/random/internal:nonsecure_base",
         "//absl/random/internal:pcg_engine",
-        "//absl/random/internal:pool_urbg",
         "//absl/random/internal:randen_engine",
     ],
 )
@@ -75,7 +75,6 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
-        "//absl/numeric:bits",
         "//absl/random/internal:distribution_caller",
         "//absl/random/internal:fast_uniform_bits",
         "//absl/random/internal:fastmath",
@@ -94,7 +93,10 @@
     hdrs = ["seed_gen_exception.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = ["//absl/base:config"],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:raw_logging_internal",
+    ],
 )
 
 cc_library(
@@ -109,7 +111,7 @@
         ":seed_gen_exception",
         "//absl/base:config",
         "//absl/base:nullability",
-        "//absl/random/internal:pool_urbg",
+        "//absl/random/internal:entropy_pool",
         "//absl/random/internal:salted_seed_seq",
         "//absl/random/internal:seed_material",
         "//absl/strings:string_view",
@@ -124,6 +126,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":random",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:fast_type_id",
         "//absl/meta:type_traits",
@@ -156,13 +159,12 @@
     deps = [
         ":random",
         "//absl/base:config",
-        "//absl/base:core_headers",
         "//absl/base:fast_type_id",
         "//absl/container:flat_hash_map",
         "//absl/meta:type_traits",
         "//absl/random/internal:mock_helpers",
         "//absl/utility",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -178,8 +180,8 @@
         ":random",
         "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -204,8 +206,8 @@
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "//absl/strings:str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -224,8 +226,8 @@
         "//absl/meta:type_traits",
         "//absl/numeric:int128",
         "//absl/random/internal:distribution_test_util",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -238,8 +240,8 @@
     deps = [
         ":distributions",
         ":random",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -263,8 +265,8 @@
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "//absl/strings:str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -284,8 +286,8 @@
         "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -314,8 +316,8 @@
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "//absl/strings:str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -337,8 +339,8 @@
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "//absl/strings:str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -361,8 +363,8 @@
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "//absl/strings:str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -383,8 +385,8 @@
         "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -410,8 +412,8 @@
         "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -431,8 +433,8 @@
         "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -445,10 +447,11 @@
     deps = [
         ":bit_gen_ref",
         ":random",
+        "//absl/base:config",
         "//absl/base:fast_type_id",
         "//absl/random/internal:sequence_urbg",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -466,14 +469,15 @@
         ":mock_distributions",
         ":mocking_bit_gen",
         ":random",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
 cc_test(
     name = "mock_distributions_test",
     size = "small",
+    timeout = "moderate",
     srcs = ["mock_distributions_test.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -486,8 +490,8 @@
         ":mocking_bit_gen",
         ":random",
         "//absl/numeric:int128",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -502,8 +506,8 @@
     ],
     deps = [
         ":random",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -517,8 +521,8 @@
         ":random",
         ":seed_sequences",
         "//absl/random/internal:nonsecure_base",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -535,11 +539,9 @@
     deps = [
         ":distributions",
         ":random",
-        ":seed_sequences",
         "//absl/base:core_headers",
-        "//absl/meta:type_traits",
         "//absl/random/internal:fast_uniform_bits",
         "//absl/random/internal:randen_engine",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index ad5477e..e0294a1 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -24,10 +24,10 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
     absl::random_distributions
     absl::random_internal_nonsecure_base
     absl::random_internal_pcg_engine
-    absl::random_internal_pool_urbg
     absl::random_internal_randen_engine
     absl::random_seed_sequences
 )
@@ -42,6 +42,7 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
     absl::core_headers
     absl::random_internal_distribution_caller
     absl::random_internal_fast_uniform_bits
@@ -58,6 +59,7 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
     absl::random_bit_gen_ref
     absl::random_random
     absl::random_internal_sequence_urbg
@@ -210,6 +212,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::config
+    absl::raw_logging_internal
 )
 
 absl_cc_library(
@@ -227,7 +230,7 @@
     absl::config
     absl::inlined_vector
     absl::nullability
-    absl::random_internal_pool_urbg
+    absl::random_internal_entropy_pool
     absl::random_internal_salted_seed_seq
     absl::random_internal_seed_material
     absl::random_seed_gen_exception
@@ -549,6 +552,7 @@
     absl::config
     absl::utility
     absl::fast_type_id
+    absl::type_traits
 )
 
 # Internal-only target, do not depend on directly.
@@ -579,7 +583,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
     $<$<BOOL:${MINGW}>:-lbcrypt>
   DEPS
-    absl::core_headers
+    absl::config
     absl::optional
     absl::random_internal_fast_uniform_bits
     absl::raw_logging_internal
@@ -590,11 +594,11 @@
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
-    random_internal_pool_urbg
+    random_internal_entropy_pool
   SRCS
-    "internal/pool_urbg.cc"
+    "internal/entropy_pool.cc"
   HDRS
-    "internal/pool_urbg.h"
+    "internal/entropy_pool.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
@@ -603,13 +607,12 @@
     absl::base
     absl::config
     absl::core_headers
-    absl::endian
+    absl::random_internal_platform
     absl::random_internal_randen
     absl::random_internal_seed_material
-    absl::random_internal_traits
     absl::random_seed_gen_exception
-    absl::raw_logging_internal
     absl::span
+    absl::synchronization
 )
 
 # Internal-only target, do not depend on directly.
@@ -672,6 +675,7 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
     absl::int128
     absl::type_traits
 )
@@ -734,12 +738,11 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::core_headers
+    absl::config
     absl::inlined_vector
-    absl::random_internal_pool_urbg
+    absl::random_internal_entropy_pool
     absl::random_internal_salted_seed_seq
     absl::random_internal_seed_material
-    absl::span
     absl::type_traits
 )
 
@@ -849,6 +852,7 @@
     absl::random_internal_platform
     absl::random_internal_randen_hwaes_impl
     absl::config
+    absl::optional
 )
 
 # Internal-only target, do not depend on directly.
@@ -1028,11 +1032,12 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::flat_hash_map
+    absl::random_distributions
     absl::random_internal_nonsecure_base
     absl::random_random
-    absl::random_distributions
-    absl::random_seed_sequences
-    absl::strings
+    absl::synchronization
+    absl::type_traits
     GTest::gtest_main
 )
 
@@ -1048,6 +1053,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::random_internal_seed_material
+    absl::span
     GTest::gmock
     GTest::gtest_main
 )
@@ -1055,17 +1061,17 @@
 # Internal-only target, do not depend on directly.
 absl_cc_test(
   NAME
-    random_internal_pool_urbg_test
+    random_internal_entropy_pool_test
   SRCS
-    "internal/pool_urbg_test.cc"
+    "internal/entropy_pool_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::random_internal_pool_urbg
-    absl::span
-    absl::type_traits
+    absl::flat_hash_map
+    absl::random_internal_entropy_pool
+    absl::synchronization
     GTest::gtest_main
 )
 
@@ -1238,7 +1244,6 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::random_internal_wide_multiply
-    absl::bits
     absl::int128
     GTest::gmock
     GTest::gtest_main
diff --git a/absl/random/benchmarks.cc b/absl/random/benchmarks.cc
index 26bc95e..958dfe4 100644
--- a/absl/random/benchmarks.cc
+++ b/absl/random/benchmarks.cc
@@ -26,7 +26,6 @@
 #include <vector>
 
 #include "absl/base/macros.h"
-#include "absl/meta/type_traits.h"
 #include "absl/random/bernoulli_distribution.h"
 #include "absl/random/beta_distribution.h"
 #include "absl/random/exponential_distribution.h"
@@ -65,10 +64,10 @@
   PrecompiledSeedSeq() = default;
 
   template <typename Iterator>
-  PrecompiledSeedSeq(Iterator begin, Iterator end) {}
+  PrecompiledSeedSeq(Iterator, Iterator) {}
 
   template <typename T>
-  PrecompiledSeedSeq(std::initializer_list<T> il) {}
+  PrecompiledSeedSeq(std::initializer_list<T>) {}
 
   template <typename OutIterator>
   void generate(OutIterator begin, OutIterator end) {
@@ -89,30 +88,23 @@
   }
 };
 
-// use_default_initialization<T> indicates whether the random engine
-// T must be default initialized, or whether we may initialize it using
-// a seed sequence. This is used because some engines do not accept seed
-// sequence-based initialization.
-template <typename E>
-using use_default_initialization = std::false_type;
+// Triggers default constructor initialization.
+class DefaultConstructorSeedSeq {};
 
 // make_engine<T, SSeq> returns a random_engine which is initialized,
 // either via the default constructor, when use_default_initialization<T>
 // is true, or via the indicated seed sequence, SSeq.
-template <typename Engine, typename SSeq = PrecompiledSeedSeq>
-typename absl::enable_if_t<!use_default_initialization<Engine>::value, Engine>
-make_engine() {
-  // Initialize the random engine using the seed sequence SSeq, which
-  // is constructed from the precompiled seed data.
-  SSeq seq(std::begin(kSeedData), std::end(kSeedData));
-  return Engine(seq);
-}
-
-template <typename Engine, typename SSeq = PrecompiledSeedSeq>
-typename absl::enable_if_t<use_default_initialization<Engine>::value, Engine>
-make_engine() {
-  // Initialize the random engine using the default constructor.
-  return Engine();
+template <typename Engine, typename SSeq = DefaultConstructorSeedSeq>
+Engine make_engine() {
+  constexpr bool use_default_initialization =
+    std::is_same_v<SSeq, DefaultConstructorSeedSeq>;
+  if constexpr (use_default_initialization) {
+    return Engine();
+  } else {
+    // Otherwise, use the provided seed sequence.
+    SSeq seq(std::begin(kSeedData), std::end(kSeedData));
+    return Engine(seq);
+  }
 }
 
 template <typename Engine, typename SSeq>
@@ -248,6 +240,7 @@
 
 // Normal benchmark suite
 #define BM_BASIC(Engine)                                                       \
+  BENCHMARK_TEMPLATE(BM_Construct, Engine, DefaultConstructorSeedSeq);         \
   BENCHMARK_TEMPLATE(BM_Construct, Engine, PrecompiledSeedSeq);                \
   BENCHMARK_TEMPLATE(BM_Construct, Engine, std::seed_seq);                     \
   BENCHMARK_TEMPLATE(BM_Direct, Engine);                                       \
@@ -359,7 +352,7 @@
 
 // ABSL Recommended interfaces.
 BM_BASIC(absl::InsecureBitGen);  // === pcg64_2018_engine
-BM_BASIC(absl::BitGen);    // === randen_engine<uint64_t>.
+BM_BASIC(absl::BitGen);          // === randen_engine<uint64_t>.
 BM_THREAD(absl::BitGen);
 BM_EXTENDED(absl::BitGen);
 
diff --git a/absl/random/bernoulli_distribution.h b/absl/random/bernoulli_distribution.h
index d81b6ae..10c24e6 100644
--- a/absl/random/bernoulli_distribution.h
+++ b/absl/random/bernoulli_distribution.h
@@ -15,10 +15,12 @@
 #ifndef ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_
 #define ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_
 
+#include <cassert>
 #include <cstdint>
 #include <istream>
-#include <limits>
+#include <ostream>
 
+#include "absl/base/config.h"
 #include "absl/base/optimization.h"
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/random/internal/iostream_state_saver.h"
diff --git a/absl/random/beta_distribution.h b/absl/random/beta_distribution.h
index 432c516..a362345 100644
--- a/absl/random/beta_distribution.h
+++ b/absl/random/beta_distribution.h
@@ -17,14 +17,16 @@
 
 #include <cassert>
 #include <cmath>
+#include <cstdint>
 #include <istream>
 #include <limits>
 #include <ostream>
 #include <type_traits>
 
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/internal/fast_uniform_bits.h"
-#include "absl/random/internal/fastmath.h"
 #include "absl/random/internal/generate_real.h"
 #include "absl/random/internal/iostream_state_saver.h"
 
diff --git a/absl/random/bit_gen_ref.h b/absl/random/bit_gen_ref.h
index ac26d9d..dfce2c4 100644
--- a/absl/random/bit_gen_ref.h
+++ b/absl/random/bit_gen_ref.h
@@ -24,13 +24,14 @@
 #ifndef ABSL_RANDOM_BIT_GEN_REF_H_
 #define ABSL_RANDOM_BIT_GEN_REF_H_
 
+#include <cstdint>
 #include <limits>
 #include <type_traits>
 #include <utility>
 
 #include "absl/base/attributes.h"
-#include "absl/base/internal/fast_type_id.h"
-#include "absl/base/macros.h"
+#include "absl/base/config.h"
+#include "absl/base/fast_type_id.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/internal/distribution_caller.h"
 #include "absl/random/internal/fast_uniform_bits.h"
@@ -87,7 +88,7 @@
 //
 class BitGenRef {
   // SFINAE to detect whether the URBG type includes a member matching
-  // bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
+  // bool InvokeMock(key_id, args_tuple*, result*).
   //
   // These live inside BitGenRef so that they have friend access
   // to MockingBitGen. (see similar methods in DistributionCaller).
@@ -99,7 +100,7 @@
 
   template <class T>
   using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
-      std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(),
+      std::declval<FastTypeIdType>(), std::declval<void*>(),
       std::declval<void*>()));
 
   template <typename T>
@@ -144,8 +145,7 @@
 
  private:
   using impl_fn = result_type (*)(uintptr_t);
-  using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*,
-                                void*);
+  using mock_call_fn = bool (*)(uintptr_t, FastTypeIdType, void*, void*);
 
   template <typename URBG>
   static result_type ImplFn(uintptr_t ptr) {
@@ -157,19 +157,19 @@
 
   // Get a type-erased InvokeMock pointer.
   template <typename URBG>
-  static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type,
-                       void* result, void* arg_tuple) {
-    return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result,
+  static bool MockCall(uintptr_t gen_ptr, FastTypeIdType key_id, void* result,
+                       void* arg_tuple) {
+    return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(key_id, result,
                                                         arg_tuple);
   }
-  static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) {
+  static bool NotAMock(uintptr_t, FastTypeIdType, void*, void*) {
     return false;
   }
 
-  inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
+  inline bool InvokeMock(FastTypeIdType key_id, void* args_tuple,
                          void* result) {
     if (mock_call_ == NotAMock) return false;  // avoids an indirect call.
-    return mock_call_(t_erased_gen_ptr_, type, args_tuple, result);
+    return mock_call_(t_erased_gen_ptr_, key_id, args_tuple, result);
   }
 
   uintptr_t t_erased_gen_ptr_;
diff --git a/absl/random/bit_gen_ref_test.cc b/absl/random/bit_gen_ref_test.cc
index 1135cf2..d581352 100644
--- a/absl/random/bit_gen_ref_test.cc
+++ b/absl/random/bit_gen_ref_test.cc
@@ -15,9 +15,14 @@
 //
 #include "absl/random/bit_gen_ref.h"
 
+#include <cstdint>
+#include <random>
+#include <vector>
+
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-#include "absl/base/internal/fast_type_id.h"
+#include "absl/base/config.h"
+#include "absl/base/fast_type_id.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 
@@ -34,7 +39,7 @@
   result_type operator()() { return 1; }
 
   // InvokeMock method
-  bool InvokeMock(base_internal::FastTypeIdType index, void*, void* result) {
+  bool InvokeMock(FastTypeIdType, void*, void* result) {
     *static_cast<int*>(result) = 42;
     return true;
   }
diff --git a/absl/random/discrete_distribution.cc b/absl/random/discrete_distribution.cc
index 081acce..247faa8 100644
--- a/absl/random/discrete_distribution.cc
+++ b/absl/random/discrete_distribution.cc
@@ -14,6 +14,16 @@
 
 #include "absl/random/discrete_distribution.h"
 
+#include <cassert>
+#include <cmath>
+#include <cstddef>
+#include <iterator>
+#include <numeric>
+#include <utility>
+#include <vector>
+
+#include "absl/base/config.h"
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace random_internal {
diff --git a/absl/random/discrete_distribution.h b/absl/random/discrete_distribution.h
index 171aa11..f579a64 100644
--- a/absl/random/discrete_distribution.h
+++ b/absl/random/discrete_distribution.h
@@ -16,14 +16,16 @@
 #define ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_
 
 #include <cassert>
-#include <cmath>
+#include <cstddef>
+#include <initializer_list>
 #include <istream>
 #include <limits>
-#include <numeric>
+#include <ostream>
 #include <type_traits>
 #include <utility>
 #include <vector>
 
+#include "absl/base/config.h"
 #include "absl/random/bernoulli_distribution.h"
 #include "absl/random/internal/iostream_state_saver.h"
 #include "absl/random/uniform_int_distribution.h"
diff --git a/absl/random/distributions.h b/absl/random/distributions.h
index b6ade68..dced895 100644
--- a/absl/random/distributions.h
+++ b/absl/random/distributions.h
@@ -50,7 +50,6 @@
 #include <type_traits>
 
 #include "absl/base/config.h"
-#include "absl/base/internal/inline_variable.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/bernoulli_distribution.h"
 #include "absl/random/beta_distribution.h"
@@ -68,13 +67,12 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosedClosed,
-                               {});
-ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosed, {});
-ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedOpenTag, IntervalClosedOpen, {});
-ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpenOpen, {});
-ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpen, {});
-ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenClosedTag, IntervalOpenClosed, {});
+inline constexpr IntervalClosedClosedTag IntervalClosedClosed = {};
+inline constexpr IntervalClosedClosedTag IntervalClosed = {};
+inline constexpr IntervalClosedOpenTag IntervalClosedOpen = {};
+inline constexpr IntervalOpenOpenTag IntervalOpenOpen = {};
+inline constexpr IntervalOpenOpenTag IntervalOpen = {};
+inline constexpr IntervalOpenClosedTag IntervalOpenClosed = {};
 
 // -----------------------------------------------------------------------------
 // absl::Uniform<T>(tag, bitgen, lo, hi)
diff --git a/absl/random/distributions_test.cc b/absl/random/distributions_test.cc
index ea32183..4340aeb 100644
--- a/absl/random/distributions_test.cc
+++ b/absl/random/distributions_test.cc
@@ -97,17 +97,16 @@
 
 template <typename A, typename B, typename ExplicitRet>
 auto ExplicitUniformReturnT(int) -> decltype(absl::Uniform<ExplicitRet>(
-                                     std::declval<absl::InsecureBitGen&>(),
-                                     std::declval<A>(), std::declval<B>()));
+    std::declval<absl::InsecureBitGen&>(), std::declval<A>(),
+    std::declval<B>()));
 
 template <typename, typename, typename ExplicitRet>
 Invalid ExplicitUniformReturnT(...);
 
 template <typename TagType, typename A, typename B, typename ExplicitRet>
-auto ExplicitTaggedUniformReturnT(int)
-    -> decltype(absl::Uniform<ExplicitRet>(
-        std::declval<TagType>(), std::declval<absl::InsecureBitGen&>(),
-        std::declval<A>(), std::declval<B>()));
+auto ExplicitTaggedUniformReturnT(int) -> decltype(absl::Uniform<ExplicitRet>(
+    std::declval<TagType>(), std::declval<absl::InsecureBitGen&>(),
+    std::declval<A>(), std::declval<B>()));
 
 template <typename, typename, typename, typename ExplicitRet>
 Invalid ExplicitTaggedUniformReturnT(...);
@@ -471,6 +470,13 @@
   EXPECT_NEAR(6.5944, moments.mean, 2000) << moments;
 }
 
+TEST_F(RandomDistributionsTest, ZipfWithZeroMax) {
+  absl::InsecureBitGen gen;
+  for (int i = 0; i < 100; ++i) {
+    EXPECT_EQ(0, absl::Zipf(gen, 0));
+  }
+}
+
 TEST_F(RandomDistributionsTest, Gaussian) {
   std::vector<double> values(kSize);
 
diff --git a/absl/random/examples_test.cc b/absl/random/examples_test.cc
index 1dcb514..29c27f1 100644
--- a/absl/random/examples_test.cc
+++ b/absl/random/examples_test.cc
@@ -96,4 +96,3 @@
     EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2));
   }
 }
-
diff --git a/absl/random/exponential_distribution.h b/absl/random/exponential_distribution.h
index b5caf8a..4af2fb4 100644
--- a/absl/random/exponential_distribution.h
+++ b/absl/random/exponential_distribution.h
@@ -21,6 +21,7 @@
 #include <limits>
 #include <type_traits>
 
+#include "absl/base/config.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/random/internal/generate_real.h"
diff --git a/absl/random/gaussian_distribution.h b/absl/random/gaussian_distribution.h
index 4b07a5c..eb75bfe 100644
--- a/absl/random/gaussian_distribution.h
+++ b/absl/random/gaussian_distribution.h
@@ -26,6 +26,7 @@
 #include <cstdint>
 #include <istream>
 #include <limits>
+#include <ostream>
 #include <type_traits>
 
 #include "absl/base/config.h"
@@ -57,7 +58,7 @@
                                 bool neg);
 
   // Constants used for the gaussian distribution.
-  static constexpr double kR = 3.442619855899;  // Start of the tail.
+  static constexpr double kR = 3.442619855899;          // Start of the tail.
   static constexpr double kRInv = 0.29047645161474317;  // ~= (1.0 / kR) .
   static constexpr double kV = 9.91256303526217e-3;
   static constexpr uint64_t kMask = 0x07f;
@@ -243,7 +244,7 @@
         bits);  // U(-1, 1)
     const double x = j * zg_.x[i];
 
-    // Retangular box. Handles >97% of all cases.
+    // Rectangular box. Handles >97% of all cases.
     // For any given box, this handles between 75% and 99% of values.
     // Equivalent to U(01) < (x[i+1] / x[i]), and when i == 0, ~93.5%
     if (std::abs(x) < zg_.x[i + 1]) {
diff --git a/absl/random/generators_test.cc b/absl/random/generators_test.cc
index 2009130..c367567 100644
--- a/absl/random/generators_test.cc
+++ b/absl/random/generators_test.cc
@@ -117,7 +117,6 @@
   absl::Bernoulli(*gen, 0.5);
 }
 
-
 template <typename URBG>
 void TestZipf(URBG* gen) {
   absl::Zipf<int>(*gen, 100);
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index 5e05130..994fb5c 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -14,14 +14,14 @@
 # limitations under the License.
 #
 
+load("@bazel_skylib//lib:selects.bzl", "selects")
+
 # Internal-only implementation classes for Abseil Random
 load(
     "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_DEFAULT_LINKOPTS",
-    "ABSL_RANDOM_RANDEN_COPTS",
     "ABSL_TEST_COPTS",
-    "absl_random_randen_copts_init",
 )
 
 default_package_visibility = [
@@ -39,6 +39,72 @@
 
 licenses(["notice"])
 
+# Used to select on compilers that support GCC-compatible options
+# (e.g. "-maes").
+selects.config_setting_group(
+    name = "gcc_compatible",
+    match_any = [
+        "@rules_cc//cc/compiler:clang",
+        "@rules_cc//cc/compiler:gcc",
+    ],
+)
+
+selects.config_setting_group(
+    name = "gcc_compatible-aarch32",
+    match_all = [
+        ":gcc_compatible",
+        "@platforms//cpu:aarch32",
+    ],
+)
+
+selects.config_setting_group(
+    name = "gcc_compatible-aarch64",
+    match_all = [
+        ":gcc_compatible",
+        "@platforms//cpu:aarch64",
+    ],
+)
+
+selects.config_setting_group(
+    name = "ppc_crypto",
+    match_any = [
+        "@platforms//cpu:ppc",
+        "@platforms//cpu:ppc32",
+        "@platforms//cpu:ppc64le",
+    ],
+)
+
+selects.config_setting_group(
+    name = "gcc_compatible-ppc_crypto",
+    match_all = [
+        ":gcc_compatible",
+        ":ppc_crypto",
+    ],
+)
+
+selects.config_setting_group(
+    name = "gcc_compatible-x86_64",
+    match_all = [
+        ":gcc_compatible",
+        "@platforms//cpu:x86_64",
+    ],
+)
+
+# Some libraries are compiled with options to generate AES-NI
+# instructions, and runtime dispatch is used to determine if the host
+# microarchitecture supports AES-NI or if a portable fallback library
+# should be called.
+ABSL_RANDOM_RANDEN_COPTS = select({
+    ":gcc_compatible-aarch32": ["-mfpu=neon"],
+    ":gcc_compatible-aarch64": ["-march=armv8-a+crypto"],
+    ":gcc_compatible-ppc_crypto": ["-mcrypto"],
+    ":gcc_compatible-x86_64": [
+        "-maes",
+        "-msse4.1",
+    ],
+    "//conditions:default": [],
+})
+
 cc_library(
     name = "traits",
     hdrs = ["traits.h"],
@@ -59,6 +125,7 @@
     deps = [
         "//absl/base:config",
         "//absl/base:fast_type_id",
+        "//absl/meta:type_traits",
         "//absl/utility",
     ],
 )
@@ -87,8 +154,8 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS + select({
-        "//absl:msvc_compiler": ["-DEFAULTLIB:bcrypt.lib"],
-        "//absl:clang-cl_compiler": ["-DEFAULTLIB:bcrypt.lib"],
+        "@rules_cc//cc/compiler:msvc-cl": ["-DEFAULTLIB:bcrypt.lib"],
+        "@rules_cc//cc/compiler:clang-cl": ["-DEFAULTLIB:bcrypt.lib"],
         "//absl:mingw_compiler": [
             "-DEFAULTLIB:bcrypt.lib",
             "-lbcrypt",
@@ -97,7 +164,7 @@
     }),
     deps = [
         ":fast_uniform_bits",
-        "//absl/base:core_headers",
+        "//absl/base:config",
         "//absl/base:dynamic_annotations",
         "//absl/base:raw_logging_internal",
         "//absl/strings",
@@ -107,29 +174,23 @@
 )
 
 cc_library(
-    name = "pool_urbg",
-    srcs = [
-        "pool_urbg.cc",
-    ],
-    hdrs = [
-        "pool_urbg.h",
-    ],
+    name = "entropy_pool",
+    srcs = ["entropy_pool.cc"],
+    hdrs = ["entropy_pool.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
-        "//absl:msvc_compiler": [],
-        "//absl:clang-cl_compiler": [],
-        "//absl:wasm": [],
+        "@rules_cc//cc/compiler:msvc-cl": [],
+        "@rules_cc//cc/compiler:clang-cl": [],
+        "@rules_cc//cc/compiler:emscripten": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":platform",
         ":randen",
         ":seed_material",
-        ":traits",
         "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
-        "//absl/base:endian",
-        "//absl/base:raw_logging_internal",
         "//absl/random:seed_gen_exception",
         "//absl/types:span",
     ],
@@ -182,6 +243,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        "//absl/base:config",
         "//absl/meta:type_traits",
         "//absl/numeric:int128",
     ],
@@ -231,13 +293,12 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        ":pool_urbg",
+        ":entropy_pool",
         ":salted_seed_seq",
         ":seed_material",
-        "//absl/base:core_headers",
+        "//absl/base:config",
         "//absl/container:inlined_vector",
         "//absl/meta:type_traits",
-        "//absl/types:span",
     ],
 )
 
@@ -320,8 +381,6 @@
     ],
 )
 
-absl_random_randen_copts_init()
-
 cc_library(
     name = "randen_hwaes",
     srcs = [
@@ -337,6 +396,7 @@
         ":platform",
         ":randen_hwaes_impl",
         "//absl/base:config",
+        "//absl/types:optional",
     ],
 )
 
@@ -348,8 +408,8 @@
         "randen_hwaes.h",
     ],
     copts = ABSL_DEFAULT_COPTS + ABSL_RANDOM_RANDEN_COPTS + select({
-        "//absl:msvc_compiler": [],
-        "//absl:clang-cl_compiler": [],
+        "@rules_cc//cc/compiler:msvc-cl": [],
+        "@rules_cc//cc/compiler:clang-cl": [],
         "//conditions:default": ["-Wno-pass-failed"],
     }),
     linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -416,8 +476,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":traits",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -433,8 +493,8 @@
         ":generate_real",
         "//absl/flags:flag",
         "//absl/numeric:bits",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -446,8 +506,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":distribution_test_util",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -459,8 +519,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":fastmath",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -473,8 +533,8 @@
     deps = [
         ":explicit_seed_seq",
         "//absl/random:seed_sequences",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -486,8 +546,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":salted_seed_seq",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -502,8 +562,8 @@
     deps = [
         ":distribution_test_util",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -517,8 +577,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":fast_uniform_bits",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -542,7 +602,7 @@
         ":mock_helpers",
         "//absl/base:config",
         "//absl/random:mocking_bit_gen",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -556,12 +616,13 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":nonsecure_base",
+        "//absl/container:flat_hash_set",
+        "//absl/meta:type_traits",
         "//absl/random",
         "//absl/random:distributions",
-        "//absl/random:seed_sequences",
-        "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "//absl/synchronization",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -573,25 +634,26 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":seed_material",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "//absl/types:span",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
 cc_test(
-    name = "pool_urbg_test",
+    name = "entropy_pool_test",
     size = "small",
     srcs = [
-        "pool_urbg_test.cc",
+        "entropy_pool_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        ":pool_urbg",
-        "//absl/meta:type_traits",
-        "//absl/types:span",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        ":entropy_pool",
+        "//absl/container:flat_hash_set",
+        "//absl/synchronization",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -606,8 +668,8 @@
         ":explicit_seed_seq",
         ":pcg_engine",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -625,8 +687,8 @@
         "//absl/log",
         "//absl/strings",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -639,8 +701,8 @@
     deps = [
         ":randen",
         "//absl/meta:type_traits",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -654,8 +716,8 @@
         ":platform",
         ":randen_slow",
         "//absl/base:endian",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -672,7 +734,7 @@
         ":randen_hwaes_impl",  # build_cleaner: keep
         "//absl/log",
         "//absl/strings:str_format",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -684,10 +746,9 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":wide_multiply",
-        "//absl/numeric:bits",
         "//absl/numeric:int128",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -779,8 +840,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":iostream_state_saver",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -792,7 +853,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":uniform_helper",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/random/internal/chi_square.cc b/absl/random/internal/chi_square.cc
index fbe0173..4cfc4d7 100644
--- a/absl/random/internal/chi_square.cc
+++ b/absl/random/internal/chi_square.cc
@@ -25,9 +25,7 @@
 
 #if defined(__EMSCRIPTEN__)
 // Workaround __EMSCRIPTEN__ error: llvm_fma_f64 not found.
-inline double fma(double x, double y, double z) {
-  return (x * y) + z;
-}
+inline double fma(double x, double y, double z) { return (x * y) + z; }
 #endif
 
 // Use Horner's method to evaluate a polynomial.
@@ -105,9 +103,8 @@
 // p-value, usually using bisection. Also known by the name CRITCHI.
 double ChiSquareValue(int dof, double p) {
   static constexpr double kChiEpsilon =
-      0.000001;  // Accuracy of the approximation.
-  static constexpr double kChiMax =
-      99999.0;  // Maximum chi-squared value.
+      0.000001;                               // Accuracy of the approximation.
+  static constexpr double kChiMax = 99999.0;  // Maximum chi-squared value.
 
   const double p_value = 1.0 - p;
   if (dof < 1 || p_value > 1.0) {
diff --git a/absl/random/internal/chi_square_test.cc b/absl/random/internal/chi_square_test.cc
index 5025def..29fd988 100644
--- a/absl/random/internal/chi_square_test.cc
+++ b/absl/random/internal/chi_square_test.cc
@@ -291,8 +291,7 @@
       /*97*/ {115.223, 120.990, 126.141, 132.309, 145.789},
       /*98*/ {116.315, 122.108, 127.282, 133.476, 147.010},
       /*99*/ {117.407, 123.225, 128.422, 134.642, 148.230},
-      /*100*/ {118.498, 124.342, 129.561, 135.807, 149.449}
-      /**/};
+      /*100*/ {118.498, 124.342, 129.561, 135.807, 149.449} /**/};
 
   //    0.90      0.95     0.975      0.99     0.999
   for (int i = 0; i < ABSL_ARRAYSIZE(data); i++) {
diff --git a/absl/random/internal/distribution_caller.h b/absl/random/internal/distribution_caller.h
index 0f162a4..e84ec8c 100644
--- a/absl/random/internal/distribution_caller.h
+++ b/absl/random/internal/distribution_caller.h
@@ -17,11 +17,13 @@
 #ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
 #define ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
 
-#include <utility>
+#include <tuple>
 #include <type_traits>
+#include <utility>
 
 #include "absl/base/config.h"
-#include "absl/base/internal/fast_type_id.h"
+#include "absl/base/fast_type_id.h"
+#include "absl/meta/type_traits.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
@@ -36,7 +38,7 @@
   static_assert(!std::is_pointer<URBG>::value,
                 "You must pass a reference, not a pointer.");
   // SFINAE to detect whether the URBG type includes a member matching
-  // bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
+  // bool InvokeMock(key_id, args_tuple*, result*).
   //
   // These live inside BitGenRef so that they have friend access
   // to MockingBitGen. (see similar methods in DistributionCaller).
@@ -48,8 +50,8 @@
 
   template <class T>
   using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
-      std::declval<::absl::base_internal::FastTypeIdType>(),
-      std::declval<void*>(), std::declval<void*>()));
+      std::declval<FastTypeIdType>(), std::declval<void*>(),
+      std::declval<void*>()));
 
   using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
 
@@ -72,8 +74,7 @@
 
     ArgTupleT arg_tuple(std::forward<Args>(args)...);
     ResultT result;
-    if (!urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
-                          &result)) {
+    if (!urbg->InvokeMock(FastTypeId<KeyT>(), &arg_tuple, &result)) {
       auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
       result = dist(*urbg);
     }
diff --git a/absl/random/internal/distribution_test_util.h b/absl/random/internal/distribution_test_util.h
index 6d94cf6..1189340 100644
--- a/absl/random/internal/distribution_test_util.h
+++ b/absl/random/internal/distribution_test_util.h
@@ -16,9 +16,9 @@
 #define ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_
 
 #include <cstddef>
-#include <iostream>
-#include <vector>
+#include <ostream>
 
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/span.h"
 
@@ -96,7 +96,7 @@
 //   https://www.jstor.org/stable/2346798
 //   https://www.jstor.org/stable/2346887
 //
-// BetaIncompleteInv(p, q, beta, alhpa)
+// BetaIncompleteInv(p, q, beta, alpha)
 //   `p` is beta parameter p, `q` is beta parameter q.
 //   `alpha` is the value of the lower tail area.
 //
diff --git a/absl/random/internal/pool_urbg.cc b/absl/random/internal/entropy_pool.cc
similarity index 63%
rename from absl/random/internal/pool_urbg.cc
rename to absl/random/internal/entropy_pool.cc
index 5aefa7d..fa47d0d 100644
--- a/absl/random/internal/pool_urbg.cc
+++ b/absl/random/internal/entropy_pool.cc
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/random/internal/pool_urbg.h"
+#include "absl/random/internal/entropy_pool.h"
 
 #include <algorithm>
 #include <atomic>
@@ -23,15 +23,14 @@
 #include "absl/base/attributes.h"
 #include "absl/base/call_once.h"
 #include "absl/base/config.h"
-#include "absl/base/internal/endian.h"
-#include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/spinlock.h"
-#include "absl/base/internal/sysinfo.h"
-#include "absl/base/internal/unaligned_access.h"
 #include "absl/base/optimization.h"
+#include "absl/base/thread_annotations.h"
 #include "absl/random/internal/randen.h"
+#include "absl/random/internal/randen_traits.h"
 #include "absl/random/internal/seed_material.h"
 #include "absl/random/seed_gen_exception.h"
+#include "absl/types/span.h"
 
 using absl::base_internal::SpinLock;
 using absl::base_internal::SpinLockHolder;
@@ -45,9 +44,11 @@
 // single generator within a RandenPool<T>. It is an internal implementation
 // detail, and does not aim to conform to [rand.req.urng].
 //
-// NOTE: There are alignment issues when used on ARM, for instance.
-// See the allocation code in PoolAlignedAlloc().
-class RandenPoolEntry {
+// At least 32-byte alignment is required for the state_ array on some ARM
+// platforms.  We also want this aligned to a cacheline to eliminate false
+// sharing.
+class alignas(std::max(size_t{ABSL_CACHELINE_SIZE}, size_t{32}))
+    RandenPoolEntry {
  public:
   static constexpr size_t kState = RandenTraits::kStateBytes / sizeof(uint32_t);
   static constexpr size_t kCapacity =
@@ -62,10 +63,6 @@
   // Copy bytes into out.
   void Fill(uint8_t* out, size_t bytes) ABSL_LOCKS_EXCLUDED(mu_);
 
-  // Returns random bits from the buffer in units of T.
-  template <typename T>
-  inline T Generate() ABSL_LOCKS_EXCLUDED(mu_);
-
   inline void MaybeRefill() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
     if (next_ >= kState) {
       next_ = kCapacity;
@@ -73,55 +70,24 @@
     }
   }
 
+  inline size_t available() const ABSL_SHARED_LOCKS_REQUIRED(mu_) {
+    return kState - next_;
+  }
+
  private:
   // Randen URBG state.
-  uint32_t state_[kState] ABSL_GUARDED_BY(mu_);  // First to satisfy alignment.
+  // At least 32-byte alignment is required by ARM platform code.
+  alignas(32) uint32_t state_[kState] ABSL_GUARDED_BY(mu_);
   SpinLock mu_;
   const Randen impl_;
   size_t next_ ABSL_GUARDED_BY(mu_);
 };
 
-template <>
-inline uint8_t RandenPoolEntry::Generate<uint8_t>() {
-  SpinLockHolder l(&mu_);
-  MaybeRefill();
-  return static_cast<uint8_t>(state_[next_++]);
-}
-
-template <>
-inline uint16_t RandenPoolEntry::Generate<uint16_t>() {
-  SpinLockHolder l(&mu_);
-  MaybeRefill();
-  return static_cast<uint16_t>(state_[next_++]);
-}
-
-template <>
-inline uint32_t RandenPoolEntry::Generate<uint32_t>() {
-  SpinLockHolder l(&mu_);
-  MaybeRefill();
-  return state_[next_++];
-}
-
-template <>
-inline uint64_t RandenPoolEntry::Generate<uint64_t>() {
-  SpinLockHolder l(&mu_);
-  if (next_ >= kState - 1) {
-    next_ = kCapacity;
-    impl_.Generate(state_);
-  }
-  auto p = state_ + next_;
-  next_ += 2;
-
-  uint64_t result;
-  std::memcpy(&result, p, sizeof(result));
-  return result;
-}
-
 void RandenPoolEntry::Fill(uint8_t* out, size_t bytes) {
   SpinLockHolder l(&mu_);
   while (bytes > 0) {
     MaybeRefill();
-    size_t remaining = (kState - next_) * sizeof(state_[0]);
+    size_t remaining = available() * sizeof(state_[0]);
     size_t to_copy = std::min(bytes, remaining);
     std::memcpy(out, &state_[next_], to_copy);
     out += to_copy;
@@ -185,38 +151,17 @@
 #endif
 }
 
-// Allocate a RandenPoolEntry with at least 32-byte alignment, which is required
-// by ARM platform code.
-RandenPoolEntry* PoolAlignedAlloc() {
-  constexpr size_t kAlignment =
-      ABSL_CACHELINE_SIZE > 32 ? ABSL_CACHELINE_SIZE : 32;
-
-  // Not all the platforms that we build for have std::aligned_alloc, however
-  // since we never free these objects, we can over allocate and munge the
-  // pointers to the correct alignment.
-  uintptr_t x = reinterpret_cast<uintptr_t>(
-      new char[sizeof(RandenPoolEntry) + kAlignment]);
-  auto y = x % kAlignment;
-  void* aligned = reinterpret_cast<void*>(y == 0 ? x : (x + kAlignment - y));
-  return new (aligned) RandenPoolEntry();
-}
-
 // Allocate and initialize kPoolSize objects of type RandenPoolEntry.
-//
-// The initialization strategy is to initialize one object directly from
-// OS entropy, then to use that object to seed all of the individual
-// pool instances.
 void InitPoolURBG() {
   static constexpr size_t kSeedSize =
       RandenTraits::kStateBytes / sizeof(uint32_t);
-  // Read the seed data from OS entropy once.
+  // Read OS entropy once, and use it to initialize each pool entry.
   uint32_t seed_material[kPoolSize * kSeedSize];
-  if (!random_internal::ReadSeedMaterialFromOSEntropy(
-          absl::MakeSpan(seed_material))) {
-    random_internal::ThrowSeedGenException();
+  if (!ReadSeedMaterialFromOSEntropy(absl::MakeSpan(seed_material))) {
+    ThrowSeedGenException();
   }
   for (size_t i = 0; i < kPoolSize; i++) {
-    shared_pools[i] = PoolAlignedAlloc();
+    shared_pools[i] = new RandenPoolEntry();
     shared_pools[i]->Init(
         absl::MakeSpan(&seed_material[i * kSeedSize], kSeedSize));
   }
@@ -230,24 +175,11 @@
 
 }  // namespace
 
-template <typename T>
-typename RandenPool<T>::result_type RandenPool<T>::Generate() {
+void GetEntropyFromRandenPool(void* dest, size_t bytes) {
   auto* pool = GetPoolForCurrentThread();
-  return pool->Generate<T>();
+  pool->Fill(reinterpret_cast<uint8_t*>(dest), bytes);
 }
 
-template <typename T>
-void RandenPool<T>::Fill(absl::Span<result_type> data) {
-  auto* pool = GetPoolForCurrentThread();
-  pool->Fill(reinterpret_cast<uint8_t*>(data.data()),
-             data.size() * sizeof(result_type));
-}
-
-template class RandenPool<uint8_t>;
-template class RandenPool<uint16_t>;
-template class RandenPool<uint32_t>;
-template class RandenPool<uint64_t>;
-
 }  // namespace random_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/entropy_pool.h b/absl/random/internal/entropy_pool.h
new file mode 100644
index 0000000..970ef87
--- /dev/null
+++ b/absl/random/internal/entropy_pool.h
@@ -0,0 +1,35 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_ENTROPY_POOL_H_
+#define ABSL_RANDOM_INTERNAL_ENTROPY_POOL_H_
+
+#include <cstddef>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// GetEntropyFromRandenPool() is a helper function that fills a memory region
+// with random bytes from the RandenPool.  This is used by the absl::BitGen
+// implementation to fill the internal buffer.
+void GetEntropyFromRandenPool(void* dest, size_t bytes);
+
+}  // namespace random_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_INTERNAL_ENTROPY_POOL_H_
diff --git a/absl/random/internal/entropy_pool_test.cc b/absl/random/internal/entropy_pool_test.cc
new file mode 100644
index 0000000..89ea72f
--- /dev/null
+++ b/absl/random/internal/entropy_pool_test.cc
@@ -0,0 +1,119 @@
+// Copyright 2017 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/random/internal/entropy_pool.h"
+
+#include <bitset>
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <thread>  // NOLINT
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/synchronization/mutex.h"
+
+namespace {
+
+using ::absl::random_internal::GetEntropyFromRandenPool;
+
+TEST(EntropyPoolTest, DistinctSequencesPerThread) {
+  using result_type = uint32_t;
+  constexpr int kNumThreads = 12;
+  constexpr size_t kValuesPerThread = 32;
+
+  // Acquire entropy from multiple threads.
+  std::vector<std::vector<result_type>> data;
+  {
+    absl::Mutex mu;
+    std::vector<std::thread> threads;
+    for (int i = 0; i < kNumThreads; i++) {
+      threads.emplace_back([&]() {
+        std::vector<result_type> v(kValuesPerThread);
+        GetEntropyFromRandenPool(v.data(), sizeof(result_type) * v.size());
+        absl::MutexLock l(&mu);
+        data.push_back(std::move(v));
+      });
+    }
+    for (auto& t : threads) t.join();
+  }
+
+  EXPECT_EQ(data.size(), kNumThreads);
+
+  // There should be essentially no duplicates in the sequences.
+  size_t expected_size = 0;
+  absl::flat_hash_set<result_type> seen;
+  for (const auto& v : data) {
+    expected_size += v.size();
+    for (result_type x : v) seen.insert(x);
+  }
+  EXPECT_GE(seen.size(), expected_size - 1);
+}
+
+// This validates that sequences are independent.
+TEST(EntropyPoolTest, ValidateDistribution) {
+  using result_type = uint32_t;
+  constexpr int kNumOutputs = 16;
+  std::vector<result_type> a(kNumOutputs);
+  std::vector<result_type> b(kNumOutputs);
+
+  GetEntropyFromRandenPool(a.data(), sizeof(a[0]) * a.size());
+  GetEntropyFromRandenPool(b.data(), sizeof(b[0]) * b.size());
+
+  // Compare the two sequences, counting the number of bits that are different,
+  // then verify using a normal-approximation of the binomial distribution.
+  size_t changed_bits = 0;
+  size_t total_set = 0;
+  size_t equal_count = 0;
+  size_t zero_count = 0;
+  for (size_t i = 0; i < a.size(); ++i) {
+    std::bitset<sizeof(result_type) * 8> changed_set(a[i] ^ b[i]);
+    changed_bits += changed_set.count();
+
+    std::bitset<sizeof(result_type) * 8> a_set(a[i]);
+    std::bitset<sizeof(result_type) * 8> b_set(b[i]);
+    total_set += a_set.count() + b_set.count();
+
+    equal_count += (a[i] == b[i]) ? 1 : 0;
+
+    zero_count += (a[i] == 0) ? 1 : 0;
+    zero_count += (b[i] == 0) ? 1 : 0;
+  }
+
+  constexpr size_t kNBits = kNumOutputs * sizeof(result_type) * 8;
+
+  // This should be a binomial distribution with:
+  //    p = 0.5
+  //    n = kNBits
+  //    sigma =~ 11.3 (sqrt(n * 0.5 * 0.5))
+  // So we expect the number of changed bits to be within 5 standard deviations
+  // of the mean; this should fail less than one in 3 million times.
+  EXPECT_NEAR(changed_bits, kNBits * 0.5, 5 * std::sqrt(kNBits))
+      << "@" << changed_bits / static_cast<double>(kNBits);
+
+  // Verify that the number of set bits is also within the expected range;
+  // Note that this is summed over the two sequences, so the number of trials
+  // is twice the number of bits.
+  EXPECT_NEAR(total_set, kNBits, 5 * std::sqrt(2 * kNBits))
+      << "@" << total_set / static_cast<double>(2 * kNBits);
+
+  // A[i] == B[i] with probability ~= 16 * 1/2^32; certainly less than 1.
+  EXPECT_LE(equal_count, 1);
+
+  // Zeros values must be rare; 32 / 2^32 is certainly less than 1.
+  EXPECT_LE(zero_count, 1);
+}
+}  // namespace
diff --git a/absl/random/internal/explicit_seed_seq_test.cc b/absl/random/internal/explicit_seed_seq_test.cc
index e36d5fa..68c9ab2 100644
--- a/absl/random/internal/explicit_seed_seq_test.cc
+++ b/absl/random/internal/explicit_seed_seq_test.cc
@@ -29,14 +29,18 @@
 template <typename Sseq>
 bool ConformsToInterface() {
   // Check that the SeedSequence can be default-constructed.
-  { Sseq default_constructed_seq; }
+  {
+    Sseq default_constructed_seq;
+  }
   // Check that the SeedSequence can be constructed with two iterators.
   {
     uint32_t init_array[] = {1, 3, 5, 7, 9};
     Sseq iterator_constructed_seq(init_array, &init_array[5]);
   }
   // Check that the SeedSequence can be std::initializer_list-constructed.
-  { Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13}; }
+  {
+    Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13};
+  }
   // Check that param() and size() return state provided to constructor.
   {
     uint32_t init_array[] = {1, 2, 3, 4, 5};
diff --git a/absl/random/internal/gaussian_distribution_gentables.cc b/absl/random/internal/gaussian_distribution_gentables.cc
index a95333d..3561251 100644
--- a/absl/random/internal/gaussian_distribution_gentables.cc
+++ b/absl/random/internal/gaussian_distribution_gentables.cc
@@ -16,8 +16,6 @@
 //
 // $ blaze run :gaussian_distribution_gentables > gaussian_distribution.cc
 //
-#include "absl/random/gaussian_distribution.h"
-
 #include <cmath>
 #include <cstddef>
 #include <iostream>
@@ -25,6 +23,7 @@
 #include <string>
 
 #include "absl/base/macros.h"
+#include "absl/random/gaussian_distribution.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/random/internal/iostream_state_saver.h b/absl/random/internal/iostream_state_saver.h
index e6e242e..0f56bcb 100644
--- a/absl/random/internal/iostream_state_saver.h
+++ b/absl/random/internal/iostream_state_saver.h
@@ -16,10 +16,14 @@
 #define ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_
 
 #include <cmath>
-#include <iostream>
+#include <cstdint>
+#include <ios>
+#include <istream>
 #include <limits>
+#include <ostream>
 #include <type_traits>
 
+#include "absl/base/config.h"
 #include "absl/meta/type_traits.h"
 #include "absl/numeric/int128.h"
 
@@ -95,7 +99,6 @@
                            null_state_saver<T>>
 make_ostream_state_saver(T& is,  // NOLINT(runtime/references)
                          std::ios_base::fmtflags flags = std::ios_base::dec) {
-  std::cerr << "null_state_saver";
   using result_type = null_state_saver<T>;
   return result_type(is, flags);
 }
diff --git a/absl/random/internal/mock_helpers.h b/absl/random/internal/mock_helpers.h
index 19d0561..85f7387 100644
--- a/absl/random/internal/mock_helpers.h
+++ b/absl/random/internal/mock_helpers.h
@@ -19,7 +19,7 @@
 #include <utility>
 
 #include "absl/base/config.h"
-#include "absl/base/internal/fast_type_id.h"
+#include "absl/base/fast_type_id.h"
 #include "absl/types/optional.h"
 
 namespace absl {
@@ -48,7 +48,7 @@
 //   result_type(args...)
 //
 class MockHelpers {
-  using IdType = ::absl::base_internal::FastTypeIdType;
+  using IdType = ::absl::FastTypeIdType;
 
   // Given a key signature type used to index the mock, extract the components.
   // KeyT is expected to have the form:
@@ -82,8 +82,7 @@
                                                 Args&&... args) {
     ArgTupleT arg_tuple(std::forward<Args>(args)...);
     ReturnT result;
-    if (urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
-                         &result)) {
+    if (urbg->InvokeMock(FastTypeId<KeyT>(), &arg_tuple, &result)) {
       return result;
     }
     return absl::nullopt;
@@ -92,9 +91,9 @@
  public:
   // InvokeMock is private; this provides access for some specialized use cases.
   template <typename URBG>
-  static inline bool PrivateInvokeMock(URBG* urbg, IdType type,
+  static inline bool PrivateInvokeMock(URBG* urbg, IdType key_id,
                                        void* args_tuple, void* result) {
-    return urbg->InvokeMock(type, args_tuple, result);
+    return urbg->InvokeMock(key_id, args_tuple, result);
   }
 
   // Invoke a mock for the KeyT (may or may not be a signature).
@@ -138,7 +137,7 @@
           m, std::declval<IdType>(), ValidatorT())) {
     return m.template RegisterMock<typename KeySignature<KeyT>::result_type,
                                    typename KeySignature<KeyT>::arg_tuple_type>(
-        m, ::absl::base_internal::FastTypeId<KeyT>(), ValidatorT());
+        m, ::absl::FastTypeId<KeyT>(), ValidatorT());
   }
 
   // Acquire a mock for the KeyT (may or may not be a signature).
diff --git a/absl/random/internal/mock_overload_set.h b/absl/random/internal/mock_overload_set.h
index cfaeeee..a09f035 100644
--- a/absl/random/internal/mock_overload_set.h
+++ b/absl/random/internal/mock_overload_set.h
@@ -51,10 +51,8 @@
   auto gmock_Call(MockURBG& gen, const ::testing::Matcher<Args>&... matchers)
       -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())
                       .gmock_Call(matchers...)) {
-    static_assert(
-        std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value ||
-            std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value,
-        "Mocking requires an absl::MockingBitGen");
+    static_assert(std::is_base_of<MockingBitGen, MockURBG>::value,
+                  "Mocking requires an absl::MockingBitGen");
     return MockHelpers::MockFor<KeyT>(gen, ValidatorT())
         .gmock_Call(matchers...);
   }
@@ -74,10 +72,8 @@
                   const ::testing::Matcher<Args>&... matchers)
       -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())
                       .gmock_Call(matcher, matchers...)) {
-    static_assert(
-        std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value ||
-            std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value,
-        "Mocking requires an absl::MockingBitGen");
+    static_assert(std::is_base_of<MockingBitGen, MockURBG>::value,
+                  "Mocking requires an absl::MockingBitGen");
     return MockHelpers::MockFor<KeyT>(gen, ValidatorT())
         .gmock_Call(matcher, matchers...);
   }
diff --git a/absl/random/internal/nonsecure_base.h b/absl/random/internal/nonsecure_base.h
index c3b8033..e8c2bb9 100644
--- a/absl/random/internal/nonsecure_base.h
+++ b/absl/random/internal/nonsecure_base.h
@@ -16,19 +16,19 @@
 #define ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_
 
 #include <algorithm>
+#include <cstddef>
 #include <cstdint>
 #include <iterator>
 #include <type_traits>
 #include <utility>
 #include <vector>
 
-#include "absl/base/macros.h"
+#include "absl/base/config.h"
 #include "absl/container/inlined_vector.h"
 #include "absl/meta/type_traits.h"
-#include "absl/random/internal/pool_urbg.h"
+#include "absl/random/internal/entropy_pool.h"
 #include "absl/random/internal/salted_seed_seq.h"
 #include "absl/random/internal/seed_material.h"
-#include "absl/types/span.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -46,8 +46,7 @@
   void generate_impl(ContiguousTag, Contiguous begin, Contiguous end) {
     const size_t n = static_cast<size_t>(std::distance(begin, end));
     auto* a = &(*begin);
-    RandenPool<uint8_t>::Fill(
-        absl::MakeSpan(reinterpret_cast<uint8_t*>(a), sizeof(*a) * n));
+    GetEntropyFromRandenPool(a, sizeof(*a) * n);
   }
 
   // Construct a buffer of size n and fill it with values, then copy
@@ -57,7 +56,7 @@
                      RandomAccessIterator end) {
     const size_t n = std::distance(begin, end);
     absl::InlinedVector<uint32_t, 8> data(n, 0);
-    RandenPool<uint32_t>::Fill(absl::MakeSpan(data.begin(), data.end()));
+    GetEntropyFromRandenPool(data.begin(), sizeof(data[0]) * n);
     std::copy(std::begin(data), std::end(data), begin);
   }
 
diff --git a/absl/random/internal/nonsecure_base_test.cc b/absl/random/internal/nonsecure_base_test.cc
index 3502243..6b6f2d5 100644
--- a/absl/random/internal/nonsecure_base_test.cc
+++ b/absl/random/internal/nonsecure_base_test.cc
@@ -15,16 +15,21 @@
 #include "absl/random/internal/nonsecure_base.h"
 
 #include <algorithm>
+#include <cstddef>
 #include <cstdint>
-#include <iostream>
-#include <memory>
+#include <iterator>
 #include <random>
-#include <sstream>
+#include <thread>  // NOLINT
+#include <type_traits>
+#include <utility>
+#include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/meta/type_traits.h"
 #include "absl/random/distributions.h"
 #include "absl/random/random.h"
-#include "absl/strings/str_cat.h"
+#include "absl/synchronization/mutex.h"
 
 namespace {
 
@@ -193,6 +198,41 @@
   }
 }
 
+TEST(NonsecureURBGBase, DistinctSequencesPerThread) {
+  constexpr int kNumThreads = 12;
+  constexpr size_t kValuesPerThread = 32;
+  using result_type = absl::BitGen::result_type;
+
+  // Acquire initial sequences from multiple threads.
+  std::vector<std::vector<result_type>> data;
+  {
+    absl::Mutex mu;
+    std::vector<std::thread> threads;
+    for (int i = 0; i < kNumThreads; i++) {
+      threads.emplace_back([&]() {
+        absl::BitGen gen;
+
+        std::vector<result_type> v(kValuesPerThread);
+        std::generate(v.begin(), v.end(), [&]() { return gen(); });
+        absl::MutexLock l(&mu);
+        data.push_back(std::move(v));
+      });
+    }
+    for (auto& t : threads) t.join();
+  }
+
+  EXPECT_EQ(data.size(), kNumThreads);
+
+  // There should be essentially no duplicates in the sequences.
+  size_t expected_size = 0;
+  absl::flat_hash_set<result_type> seen;
+  for (const auto& v : data) {
+    expected_size += v.size();
+    for (result_type x : v) seen.insert(x);
+  }
+  EXPECT_GE(seen.size(), expected_size - 1);
+}
+
 TEST(RandenPoolSeedSeqTest, SeederWorksForU32) {
   absl::random_internal::RandenPoolSeedSeq seeder;
 
diff --git a/absl/random/internal/platform.h b/absl/random/internal/platform.h
index d779f48..bd2993e 100644
--- a/absl/random/internal/platform.h
+++ b/absl/random/internal/platform.h
@@ -12,6 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// SKIP_ABSL_INLINE_NAMESPACE_CHECK
+
 #ifndef ABSL_RANDOM_INTERNAL_PLATFORM_H_
 #define ABSL_RANDOM_INTERNAL_PLATFORM_H_
 
@@ -134,7 +136,14 @@
 // accelerated Randen implementation.
 #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
 
-#if defined(ABSL_ARCH_X86_64)
+// iOS does not support dispatch, even on x86, since applications
+// should be bundled as fat binaries, with a different build tailored for
+// each specific supported platform/architecture.
+#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
+    (defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR)
+#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
+#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
+#elif defined(ABSL_ARCH_X86_64)
 // Dispatch is available on x86_64
 #undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
 #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
@@ -142,8 +151,8 @@
 // Or when running linux PPC
 #undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
 #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
-#elif defined(__linux__) && defined(ABSL_ARCH_AARCH64)
-// Or when running linux AArch64
+#elif (defined(__linux__) || defined(__APPLE__)) && defined(ABSL_ARCH_AARCH64)
+// Or when running linux or macOS AArch64
 #undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
 #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
 #elif defined(__linux__) && defined(ABSL_ARCH_ARM) && (__ARM_ARCH >= 8)
@@ -159,13 +168,4 @@
 #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
 #endif
 
-// iOS does not support dispatch, even on x86, since applications
-// should be bundled as fat binaries, with a different build tailored for
-// each specific supported platform/architecture.
-#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
-    (defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR)
-#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
-#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
-#endif
-
 #endif  // ABSL_RANDOM_INTERNAL_PLATFORM_H_
diff --git a/absl/random/internal/pool_urbg.h b/absl/random/internal/pool_urbg.h
deleted file mode 100644
index 0572192..0000000
--- a/absl/random/internal/pool_urbg.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_RANDOM_INTERNAL_POOL_URBG_H_
-#define ABSL_RANDOM_INTERNAL_POOL_URBG_H_
-
-#include <cinttypes>
-#include <limits>
-
-#include "absl/random/internal/traits.h"
-#include "absl/types/span.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace random_internal {
-
-// RandenPool is a thread-safe random number generator [random.req.urbg] that
-// uses an underlying pool of Randen generators to generate values.  Each thread
-// has affinity to one instance of the underlying pool generators.  Concurrent
-// access is guarded by a spin-lock.
-template <typename T>
-class RandenPool {
- public:
-  using result_type = T;
-  static_assert(std::is_unsigned<result_type>::value,
-                "RandenPool template argument must be a built-in unsigned "
-                "integer type");
-
-  static constexpr result_type(min)() {
-    return (std::numeric_limits<result_type>::min)();
-  }
-
-  static constexpr result_type(max)() {
-    return (std::numeric_limits<result_type>::max)();
-  }
-
-  RandenPool() {}
-
-  // Returns a single value.
-  inline result_type operator()() { return Generate(); }
-
-  // Fill data with random values.
-  static void Fill(absl::Span<result_type> data);
-
- protected:
-  // Generate returns a single value.
-  static result_type Generate();
-};
-
-extern template class RandenPool<uint8_t>;
-extern template class RandenPool<uint16_t>;
-extern template class RandenPool<uint32_t>;
-extern template class RandenPool<uint64_t>;
-
-// PoolURBG uses an underlying pool of random generators to implement a
-// thread-compatible [random.req.urbg] interface with an internal cache of
-// values.
-template <typename T, size_t kBufferSize>
-class PoolURBG {
-  // Inheritance to access the protected static members of RandenPool.
-  using unsigned_type = typename make_unsigned_bits<T>::type;
-  using PoolType = RandenPool<unsigned_type>;
-  using SpanType = absl::Span<unsigned_type>;
-
-  static constexpr size_t kInitialBuffer = kBufferSize + 1;
-  static constexpr size_t kHalfBuffer = kBufferSize / 2;
-
- public:
-  using result_type = T;
-
-  static_assert(std::is_unsigned<result_type>::value,
-                "PoolURBG must be parameterized by an unsigned integer type");
-
-  static_assert(kBufferSize > 1,
-                "PoolURBG must be parameterized by a buffer-size > 1");
-
-  static_assert(kBufferSize <= 256,
-                "PoolURBG must be parameterized by a buffer-size <= 256");
-
-  static constexpr result_type(min)() {
-    return (std::numeric_limits<result_type>::min)();
-  }
-
-  static constexpr result_type(max)() {
-    return (std::numeric_limits<result_type>::max)();
-  }
-
-  PoolURBG() : next_(kInitialBuffer) {}
-
-  // copy-constructor does not copy cache.
-  PoolURBG(const PoolURBG&) : next_(kInitialBuffer) {}
-  const PoolURBG& operator=(const PoolURBG&) {
-    next_ = kInitialBuffer;
-    return *this;
-  }
-
-  // move-constructor does move cache.
-  PoolURBG(PoolURBG&&) = default;
-  PoolURBG& operator=(PoolURBG&&) = default;
-
-  inline result_type operator()() {
-    if (next_ >= kBufferSize) {
-      next_ = (kBufferSize > 2 && next_ > kBufferSize) ? kHalfBuffer : 0;
-      PoolType::Fill(SpanType(reinterpret_cast<unsigned_type*>(state_ + next_),
-                              kBufferSize - next_));
-    }
-    return state_[next_++];
-  }
-
- private:
-  // Buffer size.
-  size_t next_;  // index within state_
-  result_type state_[kBufferSize];
-};
-
-}  // namespace random_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_RANDOM_INTERNAL_POOL_URBG_H_
diff --git a/absl/random/internal/pool_urbg_test.cc b/absl/random/internal/pool_urbg_test.cc
deleted file mode 100644
index 53f4eac..0000000
--- a/absl/random/internal/pool_urbg_test.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2017 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/random/internal/pool_urbg.h"
-
-#include <algorithm>
-#include <bitset>
-#include <cmath>
-#include <cstdint>
-#include <iterator>
-
-#include "gtest/gtest.h"
-#include "absl/meta/type_traits.h"
-#include "absl/types/span.h"
-
-using absl::random_internal::PoolURBG;
-using absl::random_internal::RandenPool;
-
-namespace {
-
-// is_randen_pool trait is true when parameterized by an RandenPool
-template <typename T>
-using is_randen_pool = typename absl::disjunction<  //
-    std::is_same<T, RandenPool<uint8_t>>,           //
-    std::is_same<T, RandenPool<uint16_t>>,          //
-    std::is_same<T, RandenPool<uint32_t>>,          //
-    std::is_same<T, RandenPool<uint64_t>>>;         //
-
-// MyFill either calls RandenPool::Fill() or std::generate(..., rng)
-template <typename T, typename V>
-typename absl::enable_if_t<absl::negation<is_randen_pool<T>>::value, void>  //
-MyFill(T& rng, absl::Span<V> data) {  // NOLINT(runtime/references)
-  std::generate(std::begin(data), std::end(data), rng);
-}
-
-template <typename T, typename V>
-typename absl::enable_if_t<is_randen_pool<T>::value, void>  //
-MyFill(T& rng, absl::Span<V> data) {  // NOLINT(runtime/references)
-  rng.Fill(data);
-}
-
-template <typename EngineType>
-class PoolURBGTypedTest : public ::testing::Test {};
-
-using EngineTypes = ::testing::Types<  //
-    RandenPool<uint8_t>,               //
-    RandenPool<uint16_t>,              //
-    RandenPool<uint32_t>,              //
-    RandenPool<uint64_t>,              //
-    PoolURBG<uint8_t, 2>,              //
-    PoolURBG<uint16_t, 2>,             //
-    PoolURBG<uint32_t, 2>,             //
-    PoolURBG<uint64_t, 2>,             //
-    PoolURBG<unsigned int, 8>,         // NOLINT(runtime/int)
-    PoolURBG<unsigned long, 8>,        // NOLINT(runtime/int)
-    PoolURBG<unsigned long int, 4>,    // NOLINT(runtime/int)
-    PoolURBG<unsigned long long, 4>>;  // NOLINT(runtime/int)
-
-TYPED_TEST_SUITE(PoolURBGTypedTest, EngineTypes);
-
-// This test is checks that the engines meet the URBG interface requirements
-// defined in [rand.req.urbg].
-TYPED_TEST(PoolURBGTypedTest, URBGInterface) {
-  using E = TypeParam;
-  using T = typename E::result_type;
-
-  static_assert(std::is_copy_constructible<E>::value,
-                "engine must be copy constructible");
-
-  static_assert(absl::is_copy_assignable<E>::value,
-                "engine must be copy assignable");
-
-  E e;
-  const E x;
-
-  e();
-
-  static_assert(std::is_same<decltype(e()), T>::value,
-                "return type of operator() must be result_type");
-
-  E u0(x);
-  u0();
-
-  E u1 = e;
-  u1();
-}
-
-// This validates that sequences are independent.
-TYPED_TEST(PoolURBGTypedTest, VerifySequences) {
-  using E = TypeParam;
-  using result_type = typename E::result_type;
-
-  E rng;
-  (void)rng();  // Discard one value.
-
-  constexpr int kNumOutputs = 64;
-  result_type a[kNumOutputs];
-  result_type b[kNumOutputs];
-  std::fill(std::begin(b), std::end(b), 0);
-
-  // Fill a using Fill or generate, depending on the engine type.
-  {
-    E x = rng;
-    MyFill(x, absl::MakeSpan(a));
-  }
-
-  // Fill b using std::generate().
-  {
-    E x = rng;
-    std::generate(std::begin(b), std::end(b), x);
-  }
-
-  // Test that generated sequence changed as sequence of bits, i.e. if about
-  // half of the bites were flipped between two non-correlated values.
-  size_t changed_bits = 0;
-  size_t unchanged_bits = 0;
-  size_t total_set = 0;
-  size_t total_bits = 0;
-  size_t equal_count = 0;
-  for (size_t i = 0; i < kNumOutputs; ++i) {
-    equal_count += (a[i] == b[i]) ? 1 : 0;
-    std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]);
-    changed_bits += bitset.count();
-    unchanged_bits += bitset.size() - bitset.count();
-
-    std::bitset<sizeof(result_type) * 8> a_set(a[i]);
-    std::bitset<sizeof(result_type) * 8> b_set(b[i]);
-    total_set += a_set.count() + b_set.count();
-    total_bits += 2 * 8 * sizeof(result_type);
-  }
-  // On average, half the bits are changed between two calls.
-  EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits));
-  EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits));
-
-  // verify using a quick normal-approximation to the binomial.
-  EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits))
-      << "@" << total_set / static_cast<double>(total_bits);
-
-  // Also, A[i] == B[i] with probability (1/range) * N.
-  // Give this a pretty wide latitude, though.
-  const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8);
-  EXPECT_LE(equal_count, 1.0 + kExpected);
-}
-
-}  // namespace
-
-/*
-$ nanobenchmarks 1 RandenPool construct
-$ nanobenchmarks 1 PoolURBG construct
-
-RandenPool<uint32_t> | 1    | 1000 |    48482.00 ticks | 48.48 ticks | 13.9 ns
-RandenPool<uint32_t> | 10   | 2000 |  1028795.00 ticks | 51.44 ticks | 14.7 ns
-RandenPool<uint32_t> | 100  | 1000 |  5119968.00 ticks | 51.20 ticks | 14.6 ns
-RandenPool<uint32_t> | 1000 |  500 | 25867936.00 ticks | 51.74 ticks | 14.8 ns
-
-RandenPool<uint64_t> | 1    | 1000 |    49921.00 ticks | 49.92 ticks | 14.3 ns
-RandenPool<uint64_t> | 10   | 2000 |  1208269.00 ticks | 60.41 ticks | 17.3 ns
-RandenPool<uint64_t> | 100  | 1000 |  5844955.00 ticks | 58.45 ticks | 16.7 ns
-RandenPool<uint64_t> | 1000 |  500 | 28767404.00 ticks | 57.53 ticks | 16.4 ns
-
-PoolURBG<uint32_t,8> | 1    | 1000 |    86431.00 ticks | 86.43 ticks | 24.7 ns
-PoolURBG<uint32_t,8> | 10   | 1000 |   206191.00 ticks | 20.62 ticks |  5.9 ns
-PoolURBG<uint32_t,8> | 100  | 1000 |  1516049.00 ticks | 15.16 ticks |  4.3 ns
-PoolURBG<uint32_t,8> | 1000 |  500 |  7613936.00 ticks | 15.23 ticks |  4.4 ns
-
-PoolURBG<uint64_t,4> | 1    | 1000 |    96668.00 ticks | 96.67 ticks | 27.6 ns
-PoolURBG<uint64_t,4> | 10   | 1000 |   282423.00 ticks | 28.24 ticks |  8.1 ns
-PoolURBG<uint64_t,4> | 100  | 1000 |  2609587.00 ticks | 26.10 ticks |  7.5 ns
-PoolURBG<uint64_t,4> | 1000 |  500 | 12408757.00 ticks | 24.82 ticks |  7.1 ns
-
-*/
diff --git a/absl/random/internal/randen_benchmarks.cc b/absl/random/internal/randen_benchmarks.cc
index ec086ce..1acc2c3 100644
--- a/absl/random/internal/randen_benchmarks.cc
+++ b/absl/random/internal/randen_benchmarks.cc
@@ -12,8 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-#include "absl/random/internal/randen.h"
-
 #include <cstdint>
 #include <cstdio>
 #include <cstring>
@@ -21,6 +19,8 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/internal/nanobenchmark.h"
 #include "absl/random/internal/platform.h"
+#include "absl/random/internal/randen.h"
+#include "absl/random/internal/randen_detect.h"
 #include "absl/random/internal/randen_engine.h"
 #include "absl/random/internal/randen_hwaes.h"
 #include "absl/random/internal/randen_slow.h"
@@ -28,6 +28,7 @@
 
 namespace {
 
+using absl::random_internal::CPUSupportsRandenHwAes;
 using absl::random_internal::Randen;
 using absl::random_internal::RandenHwAes;
 using absl::random_internal::RandenSlow;
@@ -151,14 +152,14 @@
   const FuncInput unpredictable = (argc != 999);
   static const FuncInput inputs[] = {unpredictable * 100, unpredictable * 1000};
 
-#if !defined(ABSL_INTERNAL_DISABLE_AES) && ABSL_HAVE_ACCELERATED_AES
-  Measure<AbsorbFn<RandenHwAes>>("Absorb (HwAes)", inputs);
-#endif
+  if (CPUSupportsRandenHwAes()) {
+    Measure<AbsorbFn<RandenHwAes>>("Absorb (HwAes)", inputs);
+  }
   Measure<AbsorbFn<RandenSlow>>("Absorb (Slow)", inputs);
 
-#if !defined(ABSL_INTERNAL_DISABLE_AES) && ABSL_HAVE_ACCELERATED_AES
-  Measure<GenerateFn<RandenHwAes>>("Generate (HwAes)", inputs);
-#endif
+  if (CPUSupportsRandenHwAes()) {
+    Measure<GenerateFn<RandenHwAes>>("Generate (HwAes)", inputs);
+  }
   Measure<GenerateFn<RandenSlow>>("Generate (Slow)", inputs);
 
   // Measure the production engine.
diff --git a/absl/random/internal/randen_detect.cc b/absl/random/internal/randen_detect.cc
index bdeab87..63e8379 100644
--- a/absl/random/internal/randen_detect.cc
+++ b/absl/random/internal/randen_detect.cc
@@ -19,10 +19,21 @@
 
 #include "absl/random/internal/randen_detect.h"
 
+#if defined(__APPLE__) && defined(__aarch64__)
+#if defined(__has_include)
+#if __has_include(<arm/cpu_capabilities_public.h>)
+#include <arm/cpu_capabilities_public.h>
+#endif
+#endif
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#endif
+
 #include <cstdint>
 #include <cstring>
 
 #include "absl/random/internal/platform.h"
+#include "absl/types/optional.h"  // IWYU pragma: keep
 
 #if !defined(__UCLIBC__) && defined(__GLIBC__) && \
     (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16))
@@ -63,7 +74,7 @@
 // On linux, just use the c-library getauxval call.
 #if defined(ABSL_INTERNAL_USE_LINUX_GETAUXVAL)
 
-extern "C" unsigned long getauxval(unsigned long type);  // NOLINT(runtime/int)
+#include <sys/auxv.h>
 
 static uint32_t GetAuxval(uint32_t hwcap_type) {
   return static_cast<uint32_t>(getauxval(hwcap_type));
@@ -102,6 +113,19 @@
 
 #endif
 
+#if defined(__APPLE__) && defined(ABSL_ARCH_AARCH64)
+template <typename T>
+static absl::optional<T> ReadSysctlByName(const char* name) {
+  T val;
+  size_t val_size = sizeof(T);
+  int ret = sysctlbyname(name, &val, &val_size, nullptr, 0);
+  if (ret == -1) {
+    return absl::nullopt;
+  }
+  return val;
+}
+#endif
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace random_internal {
@@ -129,7 +153,9 @@
 //    cpu capabilities, and should allow us to enable crypto in the android
 //    builds where it is supported.
 //
-// 3. Use the default for the compiler architecture.
+// 3. When __APPLE__ is defined on AARCH64, use sysctlbyname().
+//
+// 4. Use the default for the compiler architecture.
 //
 
 bool CPUSupportsRandenHwAes() {
@@ -178,8 +204,36 @@
   return ((hwcap & kNEON) != 0) && ((hwcap & kAES) != 0);
 #endif
 
+#elif defined(__APPLE__) && defined(ABSL_ARCH_AARCH64)
+  // 3. Use sysctlbyname.
+
+  // Newer XNU kernels support querying all capabilities in a single
+  // sysctlbyname.
+#if defined(CAP_BIT_AdvSIMD) && defined(CAP_BIT_FEAT_AES)
+  static const absl::optional<uint64_t> caps =
+      ReadSysctlByName<uint64_t>("hw.optional.arm.caps");
+  if (caps.has_value()) {
+    constexpr uint64_t kNeonAndAesCaps =
+        (uint64_t{1} << CAP_BIT_AdvSIMD) | (uint64_t{1} << CAP_BIT_FEAT_AES);
+    return (*caps & kNeonAndAesCaps) == kNeonAndAesCaps;
+  }
+#endif
+
+  // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#overview
+  static const absl::optional<int> adv_simd =
+      ReadSysctlByName<int>("hw.optional.AdvSIMD");
+  if (adv_simd.value_or(0) == 0) {
+    return false;
+  }
+  // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics#3918855
+  static const absl::optional<int> feat_aes =
+      ReadSysctlByName<int>("hw.optional.arm.FEAT_AES");
+  if (feat_aes.value_or(0) == 0) {
+    return false;
+  }
+  return true;
 #else  // ABSL_INTERNAL_USE_GETAUXVAL
-  // 3. By default, assume that the compiler default.
+  // 4. By default, assume that the compiler default.
   return ABSL_HAVE_ACCELERATED_AES ? true : false;
 
 #endif
@@ -215,9 +269,6 @@
   //   __asm __volatile("mrs %0, id_aa64isar0_el1" :"=&r" (val));
   //
   // * Use a CPUID-style heuristic database.
-  //
-  // * On Apple (__APPLE__), AES is available on Arm v8.
-  //   https://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
 }
 
 #if defined(__clang__)
diff --git a/absl/random/internal/randen_engine.h b/absl/random/internal/randen_engine.h
index fe2d9f6..925e1bb 100644
--- a/absl/random/internal/randen_engine.h
+++ b/absl/random/internal/randen_engine.h
@@ -18,9 +18,10 @@
 #include <algorithm>
 #include <cinttypes>
 #include <cstdlib>
-#include <iostream>
+#include <istream>
 #include <iterator>
 #include <limits>
+#include <ostream>
 #include <type_traits>
 
 #include "absl/base/internal/endian.h"
diff --git a/absl/random/internal/randen_hwaes_test.cc b/absl/random/internal/randen_hwaes_test.cc
index 00d96ef..0378972 100644
--- a/absl/random/internal/randen_hwaes_test.cc
+++ b/absl/random/internal/randen_hwaes_test.cc
@@ -89,7 +89,7 @@
   LOG(INFO) << "HasRandenHwAesImplementation = " << x;
 
   int y = absl::random_internal::CPUSupportsRandenHwAes();
-  LOG(INFO) << "CPUSupportsRandenHwAes = " << x;
+  LOG(INFO) << "CPUSupportsRandenHwAes = " << y;
 
   if (!x || !y) {
     LOG(INFO) << "Skipping Randen HWAES tests.";
diff --git a/absl/random/internal/salted_seed_seq_test.cc b/absl/random/internal/salted_seed_seq_test.cc
index 0bf19a6..6f48c61 100644
--- a/absl/random/internal/salted_seed_seq_test.cc
+++ b/absl/random/internal/salted_seed_seq_test.cc
@@ -33,14 +33,18 @@
 template <typename Sseq>
 void ConformsToInterface() {
   // Check that the SeedSequence can be default-constructed.
-  { Sseq default_constructed_seq; }
+  {
+    Sseq default_constructed_seq;
+  }
   // Check that the SeedSequence can be constructed with two iterators.
   {
     uint32_t init_array[] = {1, 3, 5, 7, 9};
     Sseq iterator_constructed_seq(std::begin(init_array), std::end(init_array));
   }
   // Check that the SeedSequence can be std::initializer_list-constructed.
-  { Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13}; }
+  {
+    Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13};
+  }
   // Check that param() and size() return state provided to constructor.
   {
     uint32_t init_array[] = {1, 2, 3, 4, 5};
diff --git a/absl/random/internal/seed_material.cc b/absl/random/internal/seed_material.cc
index 1041302..8099ec7 100644
--- a/absl/random/internal/seed_material.cc
+++ b/absl/random/internal/seed_material.cc
@@ -23,17 +23,23 @@
 #endif
 
 #include <algorithm>
+#include <cassert>
 #include <cerrno>
 #include <cstdint>
 #include <cstdlib>
 #include <cstring>
+#include <string>
+#include <vector>
 
+#include "absl/base/config.h"
 #include "absl/base/dynamic_annotations.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/strings/ascii.h"
 #include "absl/strings/escaping.h"
 #include "absl/strings/string_view.h"
 #include "absl/strings/strip.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
 
 #if defined(__native_client__)
 
@@ -167,24 +173,27 @@
   size_t buffer_size = sizeof(uint32_t) * values.size();
 
   int dev_urandom = open(kEntropyFile, O_RDONLY);
-  bool success = (-1 != dev_urandom);
-  if (!success) {
+  if (dev_urandom < 0) {
+    ABSL_RAW_LOG(ERROR, "Failed to open /dev/urandom.");
     return false;
   }
 
-  while (success && buffer_size > 0) {
+  while (buffer_size > 0) {
     ssize_t bytes_read = read(dev_urandom, buffer, buffer_size);
     int read_error = errno;
-    success = (bytes_read > 0);
-    if (success) {
-      buffer += bytes_read;
-      buffer_size -= static_cast<size_t>(bytes_read);
-    } else if (bytes_read == -1 && read_error == EINTR) {
-      success = true;  // Need to try again.
+    if (bytes_read == -1 && read_error == EINTR) {
+      // Interrupted, try again.
+      continue;
+    } else if (bytes_read <= 0) {
+      // EOF, or error.
+      break;
     }
+    buffer += bytes_read;
+    buffer_size -= static_cast<size_t>(bytes_read);
   }
+
   close(dev_urandom);
-  return success;
+  return buffer_size == 0;
 }
 
 bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
@@ -251,8 +260,7 @@
   static const auto salt_material = []() -> absl::optional<uint32_t> {
     uint32_t salt_value = 0;
 
-    if (random_internal::ReadSeedMaterialFromOSEntropy(
-            MakeSpan(&salt_value, 1))) {
+    if (ReadSeedMaterialFromOSEntropy(absl::MakeSpan(&salt_value, 1))) {
       return salt_value;
     }
 
diff --git a/absl/random/internal/seed_material.h b/absl/random/internal/seed_material.h
index 4be10e9..b671a8c 100644
--- a/absl/random/internal/seed_material.h
+++ b/absl/random/internal/seed_material.h
@@ -21,7 +21,7 @@
 #include <string>
 #include <vector>
 
-#include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/types/optional.h"
 #include "absl/types/span.h"
@@ -54,7 +54,7 @@
 // to the C++ Standard "Seed Sequence" concept [rand.req.seedseq].
 //
 // If values.data() == nullptr, the behavior is undefined.
-ABSL_MUST_USE_RESULT
+[[nodiscard]]
 bool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values);
 
 // Attempts to fill a span of uint32_t-values using variates generated by an
@@ -65,8 +65,8 @@
 //
 // If urbg == nullptr or values.data() == nullptr, the behavior is undefined.
 template <typename URBG>
-ABSL_MUST_USE_RESULT bool ReadSeedMaterialFromURBG(
-    URBG* urbg, absl::Span<uint32_t> values) {
+[[nodiscard]] bool ReadSeedMaterialFromURBG(URBG* urbg,
+                                            absl::Span<uint32_t> values) {
   random_internal::FastUniformBits<uint32_t> distr;
 
   assert(urbg != nullptr && values.data() != nullptr);
@@ -94,7 +94,7 @@
 //
 // Salt is obtained only once and stored in static variable.
 //
-// May return empty value if optaining the salt was not possible.
+// May return empty value if obtaining the salt was not possible.
 absl::optional<uint32_t> GetSaltMaterial();
 
 }  // namespace random_internal
diff --git a/absl/random/internal/seed_material_test.cc b/absl/random/internal/seed_material_test.cc
index 6db2820..45db765 100644
--- a/absl/random/internal/seed_material_test.cc
+++ b/absl/random/internal/seed_material_test.cc
@@ -15,12 +15,15 @@
 #include "absl/random/internal/seed_material.h"
 
 #include <bitset>
+#include <cstdint>
 #include <cstdlib>
 #include <cstring>
 #include <random>
+#include <vector>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/types/span.h"
 
 #ifdef __ANDROID__
 // Android assert messages only go to system log, so death tests cannot inspect
diff --git a/absl/random/internal/traits_test.cc b/absl/random/internal/traits_test.cc
index a844887..2164582 100644
--- a/absl/random/internal/traits_test.cc
+++ b/absl/random/internal/traits_test.cc
@@ -104,14 +104,11 @@
 TEST(TraitsTest, IsWideningConvertibleTest) {
   constexpr bool kInvalid = false;
 
-  CheckWideningConvertsToSelf<
-      uint8_t, uint16_t, uint32_t, uint64_t,
-      int8_t,  int16_t,  int32_t,  int64_t,
-      float,   double>();
-  CheckNotWideningConvertibleWithSigned<
-      uint8_t, uint16_t, uint32_t, uint64_t>();
-  CheckWideningConvertsToLargerTypes<
-      uint8_t, uint16_t, uint32_t, uint64_t>();
+  CheckWideningConvertsToSelf<uint8_t, uint16_t, uint32_t, uint64_t, int8_t,
+                              int16_t, int32_t, int64_t, float, double>();
+  CheckNotWideningConvertibleWithSigned<uint8_t, uint16_t, uint32_t,
+                                        uint64_t>();
+  CheckWideningConvertsToLargerTypes<uint8_t, uint16_t, uint32_t, uint64_t>();
 
   CheckWideningConvertsTo<float, double>();
   CheckWideningConvertsTo<uint16_t, float>();
diff --git a/absl/random/internal/uniform_helper.h b/absl/random/internal/uniform_helper.h
index db737e1..d230073 100644
--- a/absl/random/internal/uniform_helper.h
+++ b/absl/random/internal/uniform_helper.h
@@ -201,8 +201,8 @@
 }
 
 template <typename IntType>
-absl::enable_if_t<IsIntegral<IntType>::value, bool>
-is_uniform_range_valid(IntType a, IntType b) {
+absl::enable_if_t<IsIntegral<IntType>::value, bool> is_uniform_range_valid(
+    IntType a, IntType b) {
   return a <= b;
 }
 
diff --git a/absl/random/internal/wide_multiply.h b/absl/random/internal/wide_multiply.h
index 891e363..b125681 100644
--- a/absl/random/internal/wide_multiply.h
+++ b/absl/random/internal/wide_multiply.h
@@ -75,7 +75,6 @@
           c00 + (c64a << 64) + (c64b << 64)};
 }
 
-
 template <>
 struct wide_multiply<uint128> {
   using input_type = uint128;
diff --git a/absl/random/log_uniform_int_distribution.h b/absl/random/log_uniform_int_distribution.h
index 4afff8f..cbd5e0c 100644
--- a/absl/random/log_uniform_int_distribution.h
+++ b/absl/random/log_uniform_int_distribution.h
@@ -21,11 +21,8 @@
 #include <istream>
 #include <limits>
 #include <ostream>
-#include <type_traits>
 
-#include "absl/numeric/bits.h"
-#include "absl/random/internal/fastmath.h"
-#include "absl/random/internal/generate_real.h"
+#include "absl/base/config.h"
 #include "absl/random/internal/iostream_state_saver.h"
 #include "absl/random/internal/traits.h"
 #include "absl/random/uniform_int_distribution.h"
diff --git a/absl/random/log_uniform_int_distribution_test.cc b/absl/random/log_uniform_int_distribution_test.cc
index 5df3eda..2530c9e 100644
--- a/absl/random/log_uniform_int_distribution_test.cc
+++ b/absl/random/log_uniform_int_distribution_test.cc
@@ -148,8 +148,8 @@
   const auto bucket_index = [base_log, is_2, &param](int32_t x) {
     uint64_t y = static_cast<uint64_t>(x) - param.min();
     return (y == 0) ? 0
-                    : is_2 ? static_cast<int>(1 + std::log2(y))
-                           : static_cast<int>(1 + std::log(y) * base_log);
+           : is_2   ? static_cast<int>(1 + std::log2(y))
+                    : static_cast<int>(1 + std::log(y) * base_log);
   };
   const int max_bucket = bucket_index(param.max());  // inclusive
   const size_t trials = 15 + (max_bucket + 1) * 10;
diff --git a/absl/random/mock_distributions.h b/absl/random/mock_distributions.h
index b379262..1983547 100644
--- a/absl/random/mock_distributions.h
+++ b/absl/random/mock_distributions.h
@@ -17,14 +17,14 @@
 // -----------------------------------------------------------------------------
 //
 // This file contains mock distribution functions for use alongside an
-// `absl::MockingBitGen` object within the Googletest testing framework. Such
+// `absl::MockingBitGen` object within the GoogleTest testing framework. Such
 // mocks are useful to provide deterministic values as return values within
 // (otherwise random) Abseil distribution functions.
 //
 // The return type of each function is a mock expectation object which
 // is used to set the match result.
 //
-// More information about the Googletest testing framework is available at
+// More information about the GoogleTest testing framework is available at
 // https://github.com/google/googletest
 //
 // EXPECT_CALL and ON_CALL need to be made within the same DLL component as
diff --git a/absl/random/mock_distributions_test.cc b/absl/random/mock_distributions_test.cc
index 05e313c..622aff7 100644
--- a/absl/random/mock_distributions_test.cc
+++ b/absl/random/mock_distributions_test.cc
@@ -75,14 +75,7 @@
   EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
 }
 
-TEST(MockUniform, OutOfBoundsIsAllowed) {
-  absl::UnvalidatedMockingBitGen gen;
-
-  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 100)).WillOnce(Return(0));
-  EXPECT_EQ(absl::Uniform<int>(gen, 1, 100), 0);
-}
-
-TEST(ValidatedMockDistributions, UniformUInt128Works) {
+TEST(MockDistributions, UniformUInt128BoundariesAreAllowed) {
   absl::MockingBitGen gen;
 
   EXPECT_CALL(absl::MockUniform<absl::uint128>(), Call(gen))
@@ -90,7 +83,7 @@
   EXPECT_EQ(absl::Uniform<absl::uint128>(gen), absl::Uint128Max());
 }
 
-TEST(ValidatedMockDistributions, UniformDoubleBoundaryCases) {
+TEST(MockDistributions, UniformDoubleBoundaryCasesAreAllowed) {
   absl::MockingBitGen gen;
 
   EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 1.0, 10.0))
@@ -114,7 +107,7 @@
             std::nextafter(1.0, std::numeric_limits<double>::infinity()));
 }
 
-TEST(ValidatedMockDistributions, UniformDoubleEmptyRangeCases) {
+TEST(MockDistributions, UniformDoubleEmptyRangesAllowTheBoundary) {
   absl::MockingBitGen gen;
 
   ON_CALL(absl::MockUniform<double>(), Call(absl::IntervalOpen, gen, 1.0, 1.0))
@@ -134,7 +127,7 @@
             1.0);
 }
 
-TEST(ValidatedMockDistributions, UniformIntEmptyRangeCases) {
+TEST(MockDistributions, UniformIntEmptyRangeCasesAllowTheBoundary) {
   absl::MockingBitGen gen;
 
   ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalOpen, gen, 1, 1))
@@ -150,7 +143,7 @@
   EXPECT_EQ(absl::Uniform<int>(absl::IntervalClosedOpen, gen, 1, 1), 1);
 }
 
-TEST(ValidatedMockUniformDeathTest, Examples) {
+TEST(MockUniformDeathTest, OutOfBoundsValuesAreRejected) {
   absl::MockingBitGen gen;
 
   EXPECT_DEATH_IF_SUPPORTED(
@@ -252,7 +245,7 @@
       " 101 is not in \\[1, 100\\]");
 }
 
-TEST(ValidatedMockUniformDeathTest, DoubleBoundaryCases) {
+TEST(MockUniformDeathTest, OutOfBoundsDoublesAreRejected) {
   absl::MockingBitGen gen;
 
   EXPECT_DEATH_IF_SUPPORTED(
diff --git a/absl/random/mocking_bit_gen.h b/absl/random/mocking_bit_gen.h
index 041989d..1680ff4 100644
--- a/absl/random/mocking_bit_gen.h
+++ b/absl/random/mocking_bit_gen.h
@@ -17,12 +17,12 @@
 // -----------------------------------------------------------------------------
 //
 // This file includes an `absl::MockingBitGen` class to use as a mock within the
-// Googletest testing framework. Such a mock is useful to provide deterministic
+// GoogleTest testing framework. Such a mock is useful to provide deterministic
 // values as return values within (otherwise random) Abseil distribution
 // functions. Such determinism within a mock is useful within testing frameworks
 // to test otherwise indeterminate APIs.
 //
-// More information about the Googletest testing framework is available at
+// More information about the GoogleTest testing framework is available at
 // https://github.com/google/googletest
 
 #ifndef ABSL_RANDOM_MOCKING_BIT_GEN_H_
@@ -34,9 +34,8 @@
 #include <utility>
 
 #include "gmock/gmock.h"
-#include "absl/base/attributes.h"
 #include "absl/base/config.h"
-#include "absl/base/internal/fast_type_id.h"
+#include "absl/base/fast_type_id.h"
 #include "absl/container/flat_hash_map.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/internal/mock_helpers.h"
@@ -52,13 +51,53 @@
 template <typename>
 struct DistributionCaller;
 class MockHelpers;
+}  // namespace random_internal
 
-// Implements MockingBitGen with an option to turn on extra validation.
-template <bool EnableValidation>
-class MockingBitGenImpl {
+// MockingBitGen
+//
+// `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class
+// which can act in place of an `absl::BitGen` URBG within tests using the
+// GoogleTest testing framework.
+//
+// Usage:
+//
+// Use an `absl::MockingBitGen` along with a mock distribution object (within
+// mock_distributions.h) inside Googletest constructs such as ON_CALL(),
+// EXPECT_TRUE(), etc. to produce deterministic results conforming to the
+// distribution's API contract.
+//
+// Example:
+//
+//  // Mock a call to an `absl::Bernoulli` distribution using Googletest
+//   absl::MockingBitGen bitgen;
+//
+//   ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5))
+//       .WillByDefault(testing::Return(true));
+//   EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5));
+//
+//  // Mock a call to an `absl::Uniform` distribution within Googletest
+//  absl::MockingBitGen bitgen;
+//
+//   ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_))
+//       .WillByDefault([] (int low, int high) {
+//           return low + (high - low) / 2;
+//       });
+//
+//   EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5);
+//   EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35);
+//
+// At this time, only mock distributions supplied within the Abseil random
+// library are officially supported.
+//
+// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
+// the call to absl::Uniform and related methods, otherwise mocking will fail
+// since the  underlying implementation creates a type-specific pointer which
+// will be distinct across different DLL boundaries.
+//
+class MockingBitGen {
  public:
-  MockingBitGenImpl() = default;
-  ~MockingBitGenImpl() = default;
+  MockingBitGen() = default;
+  ~MockingBitGen() = default;
 
   // URBG interface
   using result_type = absl::BitGen::result_type;
@@ -136,27 +175,25 @@
   // distribution parameters of the expectation.
   template <typename ResultT, typename ArgTupleT, typename SelfT,
             typename ValidatorT>
-  auto RegisterMock(SelfT&, base_internal::FastTypeIdType type, ValidatorT)
+  auto RegisterMock(SelfT&, FastTypeIdType type, ValidatorT)
       -> decltype(GetMockFnType(std::declval<ResultT>(),
                                 std::declval<ArgTupleT>()))& {
-    using ActualValidatorT =
-        std::conditional_t<EnableValidation, ValidatorT, NoOpValidator>;
     using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(),
                                               std::declval<ArgTupleT>()));
 
     using WrappedFnType = absl::conditional_t<
-        std::is_same<SelfT, ::testing::NiceMock<MockingBitGenImpl>>::value,
+        std::is_same<SelfT, ::testing::NiceMock<MockingBitGen>>::value,
         ::testing::NiceMock<MockFnType>,
         absl::conditional_t<
-            std::is_same<SelfT, ::testing::NaggyMock<MockingBitGenImpl>>::value,
+            std::is_same<SelfT, ::testing::NaggyMock<MockingBitGen>>::value,
             ::testing::NaggyMock<MockFnType>,
             absl::conditional_t<
                 std::is_same<SelfT,
-                             ::testing::StrictMock<MockingBitGenImpl>>::value,
+                             ::testing::StrictMock<MockingBitGen>>::value,
                 ::testing::StrictMock<MockFnType>, MockFnType>>>;
 
     using ImplT =
-        FunctionHolderImpl<WrappedFnType, ActualValidatorT, ResultT, ArgTupleT>;
+        FunctionHolderImpl<WrappedFnType, ValidatorT, ResultT, ArgTupleT>;
     auto& mock = mocks_[type];
     if (!mock) {
       mock = absl::make_unique<ImplT>();
@@ -166,8 +203,8 @@
 
   // MockingBitGen::InvokeMock
   //
-  // InvokeMock(FastTypeIdType, args, result) is the entrypoint for invoking
-  // mocks registered on MockingBitGen.
+  // bool InvokeMock(key_id, args_tuple*, result*) is the entrypoint
+  // for invoking mocks registered on MockingBitGen.
   //
   // When no mocks are registered on the provided FastTypeIdType, returns false.
   // Otherwise attempts to invoke the mock function ResultT(Args...) that
@@ -175,18 +212,16 @@
   // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...>
   // used to invoke the mock function.
   // Requires result to point to a ResultT, which is the result of the call.
-  inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
+  inline bool InvokeMock(FastTypeIdType key_id, void* args_tuple,
                          void* result) {
     // Trigger a mock, if there exists one that matches `param`.
-    auto it = mocks_.find(type);
+    auto it = mocks_.find(key_id);
     if (it == mocks_.end()) return false;
     it->second->Apply(args_tuple, result);
     return true;
   }
 
-  absl::flat_hash_map<base_internal::FastTypeIdType,
-                      std::unique_ptr<FunctionHolder>>
-      mocks_;
+  absl::flat_hash_map<FastTypeIdType, std::unique_ptr<FunctionHolder>> mocks_;
   absl::BitGen gen_;
 
   template <typename>
@@ -196,58 +231,6 @@
                                                       // InvokeMock
 };
 
-}  // namespace random_internal
-
-// MockingBitGen
-//
-// `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class
-// which can act in place of an `absl::BitGen` URBG within tests using the
-// Googletest testing framework.
-//
-// Usage:
-//
-// Use an `absl::MockingBitGen` along with a mock distribution object (within
-// mock_distributions.h) inside Googletest constructs such as ON_CALL(),
-// EXPECT_TRUE(), etc. to produce deterministic results conforming to the
-// distribution's API contract.
-//
-// Example:
-//
-//  // Mock a call to an `absl::Bernoulli` distribution using Googletest
-//   absl::MockingBitGen bitgen;
-//
-//   ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5))
-//       .WillByDefault(testing::Return(true));
-//   EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5));
-//
-//  // Mock a call to an `absl::Uniform` distribution within Googletest
-//  absl::MockingBitGen bitgen;
-//
-//   ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_))
-//       .WillByDefault([] (int low, int high) {
-//           return low + (high - low) / 2;
-//       });
-//
-//   EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5);
-//   EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35);
-//
-// At this time, only mock distributions supplied within the Abseil random
-// library are officially supported.
-//
-// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
-// the call to absl::Uniform and related methods, otherwise mocking will fail
-// since the  underlying implementation creates a type-specific pointer which
-// will be distinct across different DLL boundaries.
-//
-using MockingBitGen = random_internal::MockingBitGenImpl<true>;
-
-// UnvalidatedMockingBitGen
-//
-// UnvalidatedMockingBitGen is a variant of MockingBitGen which does no extra
-// validation.
-using UnvalidatedMockingBitGen ABSL_DEPRECATED("Use MockingBitGen instead") =
-    random_internal::MockingBitGenImpl<false>;
-
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/random/poisson_distribution.h b/absl/random/poisson_distribution.h
index f457308..ae2e095 100644
--- a/absl/random/poisson_distribution.h
+++ b/absl/random/poisson_distribution.h
@@ -17,11 +17,12 @@
 
 #include <cassert>
 #include <cmath>
+#include <cstdint>
 #include <istream>
 #include <limits>
 #include <ostream>
-#include <type_traits>
 
+#include "absl/base/config.h"
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/random/internal/fastmath.h"
 #include "absl/random/internal/generate_real.h"
@@ -48,8 +49,8 @@
 // the distribution results are limited to the max() value.
 //
 // The goals of this implementation are to provide good performance while still
-// beig thread-safe: This limits the implementation to not using lgamma provided
-// by <math.h>.
+// being thread-safe: This limits the implementation to not using lgamma
+// provided by <math.h>.
 //
 template <typename IntType = int>
 class poisson_distribution {
diff --git a/absl/random/poisson_distribution_test.cc b/absl/random/poisson_distribution_test.cc
index 5475596..3a1d238 100644
--- a/absl/random/poisson_distribution_test.cc
+++ b/absl/random/poisson_distribution_test.cc
@@ -106,7 +106,6 @@
                      0.0),  // denorm_max
   };
 
-
   constexpr int kCount = 1000;
   absl::InsecureBitGen gen;
   for (const double m : kParams) {
diff --git a/absl/random/random.h b/absl/random/random.h
index 7672086..b55b361 100644
--- a/absl/random/random.h
+++ b/absl/random/random.h
@@ -31,12 +31,13 @@
 #ifndef ABSL_RANDOM_RANDOM_H_
 #define ABSL_RANDOM_RANDOM_H_
 
+#include <cstdint>
 #include <random>
 
+#include "absl/base/config.h"
 #include "absl/random/distributions.h"  // IWYU pragma: export
-#include "absl/random/internal/nonsecure_base.h"  // IWYU pragma: export
-#include "absl/random/internal/pcg_engine.h"  // IWYU pragma: export
-#include "absl/random/internal/pool_urbg.h"
+#include "absl/random/internal/nonsecure_base.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/randen_engine.h"
 #include "absl/random/seed_sequences.h"  // IWYU pragma: export
 
@@ -94,31 +95,46 @@
 // types on modern x86, ARM, and PPC architectures.
 //
 // This type is thread-compatible, but not thread-safe.
+class BitGen : private random_internal::NonsecureURBGBase<
+                   random_internal::randen_engine<uint64_t>> {
+  using Base = random_internal::NonsecureURBGBase<
+      random_internal::randen_engine<uint64_t>>;
 
-// ---------------------------------------------------------------------------
-// absl::BitGen member functions
-// ---------------------------------------------------------------------------
+ public:
+  using result_type = typename Base::result_type;
 
-// absl::BitGen::operator()()
-//
-// Calls the BitGen, returning a generated value.
+  // BitGen()
+  // BitGen(SeedSequence seed_seq)
+  //
+  // Copy disallowed.
+  // Move allowed.
+  using Base::Base;
+  using Base::operator=;
 
-// absl::BitGen::min()
-//
-// Returns the smallest possible value from this bit generator.
+  // BitGen::min()
+  //
+  // Returns the smallest possible value from this bit generator.
+  using Base::min;
 
-// absl::BitGen::max()
-//
-// Returns the largest possible value from this bit generator.
+  // BitGen::max()
+  //
+  // Returns the largest possible value from this bit generator.
+  using Base::max;
 
-// absl::BitGen::discard(num)
-//
-// Advances the internal state of this bit generator by `num` times, and
-// discards the intermediate results.
-// ---------------------------------------------------------------------------
+  // BitGen::discard(num)
+  //
+  // Advances the internal state of this bit generator by `num` times, and
+  // discards the intermediate results.
+  using Base::discard;
 
-using BitGen = random_internal::NonsecureURBGBase<
-    random_internal::randen_engine<uint64_t>>;
+  // BitGen::operator()()
+  //
+  // Invoke the URBG, returning a generated value.
+  using Base::operator();
+
+  using Base::operator==;
+  using Base::operator!=;
+};
 
 // -----------------------------------------------------------------------------
 // absl::InsecureBitGen
@@ -156,32 +172,51 @@
 // `absl::InsecureBitGen` is not cryptographically secure.
 //
 // Prefer `absl::BitGen` over `absl::InsecureBitGen` as the general type is
-// often fast enough for the vast majority of applications.
-
-using InsecureBitGen =
-    random_internal::NonsecureURBGBase<random_internal::pcg64_2018_engine>;
-
-// ---------------------------------------------------------------------------
-// absl::InsecureBitGen member functions
-// ---------------------------------------------------------------------------
-
-// absl::InsecureBitGen::operator()()
+// often fast enough for the vast majority of applications. However, it is
+// reasonable to use `absl::InsecureBitGen` in tests or when using a URBG
+// in small isolated tasks such as in `std::shuffle`.
 //
-// Calls the InsecureBitGen, returning a generated value.
+// This type is thread-compatible, but not thread-safe.
+class InsecureBitGen : private random_internal::NonsecureURBGBase<
+                           random_internal::pcg64_2018_engine> {
+  using Base =
+      random_internal::NonsecureURBGBase<random_internal::pcg64_2018_engine>;
 
-// absl::InsecureBitGen::min()
-//
-// Returns the smallest possible value from this bit generator.
+ public:
+  using result_type = typename Base::result_type;
 
-// absl::InsecureBitGen::max()
-//
-// Returns the largest possible value from this bit generator.
+  // InsecureBitGen()
+  // InsecureBitGen(SeedSequence seed_seq)
+  //
+  // Copy disallowed.
+  // Move allowed.
+  using Base::Base;
+  using Base::operator=;
 
-// absl::InsecureBitGen::discard(num)
-//
-// Advances the internal state of this bit generator by `num` times, and
-// discards the intermediate results.
-// ---------------------------------------------------------------------------
+  // InsecureBitGen::min()
+  //
+  // Returns the smallest possible value from this bit generator.
+  using Base::min;
+
+  // InsecureBitGen::max()
+  //
+  // Returns the largest possible value from this bit generator.
+  using Base::max;
+
+  // InsecureBitGen::discard(num)
+  //
+  // Advances the internal state of this bit generator by `num` times, and
+  // discards the intermediate results.
+  using Base::discard;
+
+  // InsecureBitGen::operator()()
+  //
+  // Invoke the URBG, returning a generated value.
+  using Base::operator();
+
+  using Base::operator==;
+  using Base::operator!=;
+};
 
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/seed_gen_exception.cc b/absl/random/seed_gen_exception.cc
index fdcb54a..6fb4ad3 100644
--- a/absl/random/seed_gen_exception.cc
+++ b/absl/random/seed_gen_exception.cc
@@ -14,9 +14,8 @@
 
 #include "absl/random/seed_gen_exception.h"
 
-#include <iostream>
-
 #include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -36,7 +35,7 @@
 #ifdef ABSL_HAVE_EXCEPTIONS
   throw absl::SeedGenException();
 #else
-  std::cerr << kExceptionMessage << std::endl;
+  ABSL_RAW_LOG(FATAL, "%s", kExceptionMessage);
   std::terminate();
 #endif
 }
diff --git a/absl/random/seed_sequences.cc b/absl/random/seed_sequences.cc
index 426eafd..316381b 100644
--- a/absl/random/seed_sequences.cc
+++ b/absl/random/seed_sequences.cc
@@ -14,14 +14,18 @@
 
 #include "absl/random/seed_sequences.h"
 
-#include "absl/random/internal/pool_urbg.h"
+#include <iterator>
+
+#include "absl/base/config.h"
+#include "absl/random/internal/entropy_pool.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
 SeedSeq MakeSeedSeq() {
   SeedSeq::result_type seed_material[8];
-  random_internal::RandenPool<uint32_t>::Fill(absl::MakeSpan(seed_material));
+  random_internal::GetEntropyFromRandenPool(&seed_material[0],
+                                            sizeof(seed_material[0]) * 8);
   return SeedSeq(std::begin(seed_material), std::end(seed_material));
 }
 
diff --git a/absl/random/seed_sequences.h b/absl/random/seed_sequences.h
index 33970be..dacc5b9 100644
--- a/absl/random/seed_sequences.h
+++ b/absl/random/seed_sequences.h
@@ -80,8 +80,7 @@
 //
 template <typename URBG>
 SeedSeq CreateSeedSeqFrom(URBG* urbg) {
-  SeedSeq::result_type
-      seed_material[random_internal::kEntropyBlocksNeeded];
+  SeedSeq::result_type seed_material[random_internal::kEntropyBlocksNeeded];
 
   if (!random_internal::ReadSeedMaterialFromURBG(
           urbg, absl::MakeSpan(seed_material))) {
diff --git a/absl/random/uniform_int_distribution.h b/absl/random/uniform_int_distribution.h
index fae8025..0dc7c62 100644
--- a/absl/random/uniform_int_distribution.h
+++ b/absl/random/uniform_int_distribution.h
@@ -31,8 +31,9 @@
 #include <cassert>
 #include <istream>
 #include <limits>
-#include <type_traits>
+#include <ostream>
 
+#include "absl/base/config.h"
 #include "absl/base/optimization.h"
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/random/internal/iostream_state_saver.h"
diff --git a/absl/random/uniform_int_distribution_test.cc b/absl/random/uniform_int_distribution_test.cc
index b40d618..8134ab6 100644
--- a/absl/random/uniform_int_distribution_test.cc
+++ b/absl/random/uniform_int_distribution_test.cc
@@ -114,8 +114,8 @@
 TYPED_TEST(UniformIntDistributionTest, ViolatesPreconditionsDeathTest) {
 #if GTEST_HAS_DEATH_TEST
   // Hi < Lo
-  EXPECT_DEBUG_DEATH({ absl::uniform_int_distribution<TypeParam> dist(10, 1); },
-                     "");
+  EXPECT_DEBUG_DEATH(
+      { absl::uniform_int_distribution<TypeParam> dist(10, 1); }, "");
 #endif  // GTEST_HAS_DEATH_TEST
 #if defined(NDEBUG)
   // opt-mode, for invalid parameters, will generate a garbage value,
diff --git a/absl/random/uniform_real_distribution.h b/absl/random/uniform_real_distribution.h
index 1968334..8bef946 100644
--- a/absl/random/uniform_real_distribution.h
+++ b/absl/random/uniform_real_distribution.h
@@ -37,8 +37,10 @@
 #include <cstdint>
 #include <istream>
 #include <limits>
+#include <ostream>
 #include <type_traits>
 
+#include "absl/base/config.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/random/internal/generate_real.h"
diff --git a/absl/random/uniform_real_distribution_test.cc b/absl/random/uniform_real_distribution_test.cc
index 260aac9..4d544ca 100644
--- a/absl/random/uniform_real_distribution_test.cc
+++ b/absl/random/uniform_real_distribution_test.cc
@@ -190,7 +190,7 @@
 
 #ifdef _MSC_VER
 #pragma warning(push)
-#pragma warning(disable:4756)  // Constant arithmetic overflow.
+#pragma warning(disable : 4756)  // Constant arithmetic overflow.
 #endif
 TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) {
   using DistributionType = absl::uniform_real_distribution<TypeParam>;
diff --git a/absl/random/zipf_distribution.h b/absl/random/zipf_distribution.h
index 03497b1..21e3b70 100644
--- a/absl/random/zipf_distribution.h
+++ b/absl/random/zipf_distribution.h
@@ -22,6 +22,7 @@
 #include <ostream>
 #include <type_traits>
 
+#include "absl/base/config.h"
 #include "absl/random/internal/iostream_state_saver.h"
 #include "absl/random/internal/traits.h"
 #include "absl/random/uniform_real_distribution.h"
@@ -57,8 +58,8 @@
    public:
     using distribution_type = zipf_distribution;
 
-    // Preconditions: k > 0, v > 0, q > 1
-    // The precondidtions are validated when NDEBUG is not defined via
+    // Preconditions: k >= 0, v > 0, q > 1
+    // The preconditions are validated when NDEBUG is not defined via
     // a pair of assert() directives.
     // If NDEBUG is defined and either or both of these parameters take invalid
     // values, the behavior of the class is undefined.
@@ -152,7 +153,7 @@
     : k_(k), q_(q), v_(v), one_minus_q_(1 - q) {
   assert(q > 1);
   assert(v > 0);
-  assert(k > 0);
+  assert(k >= 0);
   one_minus_q_inv_ = 1 / one_minus_q_;
 
   // Setup for the ZRI algorithm (pg 17 of the paper).
@@ -221,7 +222,7 @@
     const double v = uniform_double(g);
     const double u = p.hxm_ + v * p.hx0_minus_hxm_;
     const double x = p.hinv(u);
-    k = rint(x);              // std::floor(x + 0.5);
+    k = rint(x);                                   // std::floor(x + 0.5);
     if (k > static_cast<double>(p.k())) continue;  // reject k > max_k
     if (k - x <= p.s_) break;
     const double h = p.h(k + 0.5);
diff --git a/absl/random/zipf_distribution_test.cc b/absl/random/zipf_distribution_test.cc
index 801ec4f..71548ca 100644
--- a/absl/random/zipf_distribution_test.cc
+++ b/absl/random/zipf_distribution_test.cc
@@ -176,15 +176,15 @@
       const double x = v_ + i;
 
       // H(n, q-1)
-      const double hnqm1 =
-          (q_ == 2.0) ? (1.0 / x)
-                      : (q_ == 3.0) ? (1.0 / (x * x)) : std::pow(x, -qm1);
+      const double hnqm1 = (q_ == 2.0)   ? (1.0 / x)
+                           : (q_ == 3.0) ? (1.0 / (x * x))
+                                         : std::pow(x, -qm1);
       sum_hnq_m1 += hnqm1;
 
       // H(n, q)
-      const double hnq =
-          (q_ == 2.0) ? (1.0 / (x * x))
-                      : (q_ == 3.0) ? (1.0 / (x * x * x)) : std::pow(x, -q_);
+      const double hnq = (q_ == 2.0)   ? (1.0 / (x * x))
+                         : (q_ == 3.0) ? (1.0 / (x * x * x))
+                                       : std::pow(x, -q_);
       sum_hnq_ += hnq;
       hnq_.push_back(hnq);
       if (i > 1000 && hnq <= 1e-10) {
diff --git a/absl/status/BUILD.bazel b/absl/status/BUILD.bazel
index 8822e0f..b61abeb 100644
--- a/absl/status/BUILD.bazel
+++ b/absl/status/BUILD.bazel
@@ -58,6 +58,7 @@
         "//absl/base:raw_logging_internal",
         "//absl/base:strerror",
         "//absl/container:inlined_vector",
+        "//absl/debugging:leak_check",
         "//absl/debugging:stacktrace",
         "//absl/debugging:symbolize",
         "//absl/functional:function_ref",
@@ -80,8 +81,19 @@
         "//absl/strings",
         "//absl/strings:cord",
         "//absl/strings:str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_binary(
+    name = "status_benchmark",
+    testonly = True,
+    srcs = ["status_benchmark.cc"],
+    tags = ["benchmark"],
+    deps = [
+        ":status",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -126,8 +138,20 @@
         "//absl/types:any",
         "//absl/types:variant",
         "//absl/utility",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
+    ],
+)
+
+cc_binary(
+    name = "statusor_benchmark",
+    testonly = True,
+    srcs = ["statusor_benchmark.cc"],
+    tags = ["benchmark"],
+    deps = [
+        ":status",
+        ":statusor",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -146,7 +170,7 @@
         ":statusor",
         "//absl/base:config",
         "//absl/strings:string_view",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -161,7 +185,7 @@
         ":status_matchers",
         ":statusor",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/status/CMakeLists.txt b/absl/status/CMakeLists.txt
index 24c01e7..e140365 100644
--- a/absl/status/CMakeLists.txt
+++ b/absl/status/CMakeLists.txt
@@ -35,6 +35,7 @@
     absl::core_headers
     absl::function_ref
     absl::inlined_vector
+    absl::leak_check
     absl::memory
     absl::no_destructor
     absl::nullability
@@ -42,8 +43,8 @@
     absl::raw_logging_internal
     absl::span
     absl::stacktrace
-    absl::strerror
     absl::str_format
+    absl::strerror
     absl::strings
     absl::symbolize
   PUBLIC
diff --git a/absl/status/internal/status_internal.cc b/absl/status/internal/status_internal.cc
index a915675..9884189 100644
--- a/absl/status/internal/status_internal.cc
+++ b/absl/status/internal/status_internal.cc
@@ -28,6 +28,7 @@
 #include "absl/base/config.h"
 #include "absl/base/macros.h"
 #include "absl/base/nullability.h"
+#include "absl/debugging/leak_check.h"
 #include "absl/debugging/stacktrace.h"
 #include "absl/debugging/symbolize.h"
 #include "absl/memory/memory.h"
@@ -188,7 +189,7 @@
   return true;
 }
 
-absl::Nonnull<StatusRep*> StatusRep::CloneAndUnref() const {
+StatusRep* absl_nonnull StatusRep::CloneAndUnref() const {
   // Optimization: no need to create a clone if we already have a refcount of 1.
   if (ref_.load(std::memory_order_acquire) == 1) {
     // All StatusRep instances are heap allocated and mutable, therefore this
@@ -234,12 +235,14 @@
   }
 }
 
-absl::Nonnull<std::string*> MakeCheckFailString(
-    absl::Nonnull<const absl::Status*> status,
-    absl::Nonnull<const char*> prefix) {
-  return new std::string(
-      absl::StrCat(prefix, " (",
-                   status->ToString(StatusToStringMode::kWithEverything), ")"));
+const char* absl_nonnull MakeCheckFailString(
+    const absl::Status* absl_nonnull status, const char* absl_nonnull prefix) {
+  // There's no need to free this string since the process is crashing.
+  return absl::IgnoreLeak(
+             new std::string(absl::StrCat(
+                 prefix, " (",
+                 status->ToString(StatusToStringMode::kWithEverything), ")")))
+      ->c_str();
 }
 
 }  // namespace status_internal
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h
index c9f4383..45b90f3 100644
--- a/absl/status/internal/status_internal.h
+++ b/absl/status/internal/status_internal.h
@@ -100,7 +100,7 @@
   // Returns an equivalent heap allocated StatusRep with refcount 1.
   //
   // `this` is not safe to be used after calling as it may have been deleted.
-  absl::Nonnull<StatusRep*> CloneAndUnref() const;
+  StatusRep* absl_nonnull CloneAndUnref() const;
 
  private:
   mutable std::atomic<int32_t> ref_;
@@ -120,9 +120,8 @@
 //
 // This is an internal implementation detail for Abseil logging.
 ABSL_ATTRIBUTE_PURE_FUNCTION
-absl::Nonnull<std::string*> MakeCheckFailString(
-    absl::Nonnull<const absl::Status*> status,
-    absl::Nonnull<const char*> prefix);
+const char* absl_nonnull MakeCheckFailString(
+    const absl::Status* absl_nonnull status, const char* absl_nonnull prefix);
 
 }  // namespace status_internal
 
diff --git a/absl/status/internal/status_matchers.cc b/absl/status/internal/status_matchers.cc
index 908b70b..c2912bb 100644
--- a/absl/status/internal/status_matchers.cc
+++ b/absl/status/internal/status_matchers.cc
@@ -30,14 +30,14 @@
 namespace status_internal {
 
 void StatusIsMatcherCommonImpl::DescribeTo(std::ostream* os) const {
-  *os << ", has a status code that ";
+  *os << "has a status code that ";
   code_matcher_.DescribeTo(os);
   *os << ", and has an error message that ";
   message_matcher_.DescribeTo(os);
 }
 
 void StatusIsMatcherCommonImpl::DescribeNegationTo(std::ostream* os) const {
-  *os << ", or has a status code that ";
+  *os << "either has a status code that ";
   code_matcher_.DescribeNegationTo(os);
   *os << ", or has an error message that ";
   message_matcher_.DescribeNegationTo(os);
@@ -49,7 +49,8 @@
   ::testing::StringMatchResultListener inner_listener;
   if (!code_matcher_.MatchAndExplain(status.code(), &inner_listener)) {
     *result_listener << (inner_listener.str().empty()
-                             ? "whose status code is wrong"
+                             ? status.ok() ? "which is OK"
+                                           : "whose status code is wrong"
                              : "which has a status code " +
                                    inner_listener.str());
     return false;
diff --git a/absl/status/internal/statusor_internal.h b/absl/status/internal/statusor_internal.h
index 6760315..e986611 100644
--- a/absl/status/internal/statusor_internal.h
+++ b/absl/status/internal/statusor_internal.h
@@ -39,7 +39,8 @@
 struct HasConversionOperatorToStatusOr : std::false_type {};
 
 template <typename T, typename U>
-void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
+void test(char (*absl_nullable)[sizeof(
+    std::declval<U>().operator absl::StatusOr<T>())]);
 
 template <typename T, typename U>
 struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
@@ -185,7 +186,7 @@
 class Helper {
  public:
   // Move type-agnostic error handling to the .cc.
-  static void HandleInvalidStatusCtorArg(absl::Nonnull<Status*>);
+  static void HandleInvalidStatusCtorArg(Status* absl_nonnull);
   [[noreturn]] static void Crash(const absl::Status& status);
 };
 
@@ -194,7 +195,7 @@
 // This abstraction is here mostly for the gcc performance fix.
 template <typename T, typename... Args>
 ABSL_ATTRIBUTE_NONNULL(1)
-void PlacementNew(absl::Nonnull<void*> p, Args&&... args) {
+void PlacementNew(void* absl_nonnull p, Args&&... args) {
   new (p) T(std::forward<Args>(args)...);
 }
 
diff --git a/absl/status/status.cc b/absl/status/status.cc
index 745ab88..963dab6 100644
--- a/absl/status/status.cc
+++ b/absl/status/status.cc
@@ -91,16 +91,12 @@
   return os << StatusCodeToString(code);
 }
 
-absl::Nonnull<const std::string*> Status::EmptyString() {
+const std::string* absl_nonnull Status::EmptyString() {
   static const absl::NoDestructor<std::string> kEmpty;
   return kEmpty.get();
 }
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr const char Status::kMovedFromString[];
-#endif
-
-absl::Nonnull<const std::string*> Status::MovedFromString() {
+const std::string* absl_nonnull Status::MovedFromString() {
   static const absl::NoDestructor<std::string> kMovedFrom(kMovedFromString);
   return kMovedFrom.get();
 }
@@ -112,7 +108,7 @@
   }
 }
 
-absl::Nonnull<status_internal::StatusRep*> Status::PrepareToModify(
+status_internal::StatusRep* absl_nonnull Status::PrepareToModify(
     uintptr_t rep) {
   if (IsInlined(rep)) {
     return new status_internal::StatusRep(InlinedRepToCode(rep),
@@ -410,7 +406,7 @@
                 MessageForErrnoToStatus(error_number, message));
 }
 
-absl::Nonnull<const char*> StatusMessageAsCStr(const Status& status) {
+const char* absl_nonnull StatusMessageAsCStr(const Status& status) {
   // As an internal implementation detail, we guarantee that if status.message()
   // is non-empty, then the resulting string_view is null terminated.
   auto sv_message = status.message();
diff --git a/absl/status/status.h b/absl/status/status.h
index 6cfe49f..4516822 100644
--- a/absl/status/status.h
+++ b/absl/status/status.h
@@ -623,15 +623,15 @@
 
   // REQUIRES: !ok()
   // Ensures rep is not inlined or shared with any other Status.
-  static absl::Nonnull<status_internal::StatusRep*> PrepareToModify(
+  static status_internal::StatusRep* absl_nonnull PrepareToModify(
       uintptr_t rep);
 
   // MSVC 14.0 limitation requires the const.
   static constexpr const char kMovedFromString[] =
       "Status accessed after move.";
 
-  static absl::Nonnull<const std::string*> EmptyString();
-  static absl::Nonnull<const std::string*> MovedFromString();
+  static const std::string* absl_nonnull EmptyString();
+  static const std::string* absl_nonnull MovedFromString();
 
   // Returns whether rep contains an inlined representation.
   // See rep_ for details.
@@ -649,8 +649,8 @@
 
   // Converts between StatusRep* and the external uintptr_t representation used
   // by rep_. See rep_ for details.
-  static uintptr_t PointerToRep(status_internal::StatusRep* r);
-  static absl::Nonnull<const status_internal::StatusRep*> RepToPointer(
+  static uintptr_t PointerToRep(status_internal::StatusRep* absl_nonnull r);
+  static const status_internal::StatusRep* absl_nonnull RepToPointer(
       uintptr_t r);
 
   static std::string ToStringSlow(uintptr_t rep, StatusToStringMode mode);
@@ -902,14 +902,14 @@
   return CodeToInlinedRep(absl::StatusCode::kInternal) | 2;
 }
 
-inline absl::Nonnull<const status_internal::StatusRep*> Status::RepToPointer(
+inline const status_internal::StatusRep* absl_nonnull Status::RepToPointer(
     uintptr_t rep) {
   assert(!IsInlined(rep));
   return reinterpret_cast<const status_internal::StatusRep*>(rep);
 }
 
 inline uintptr_t Status::PointerToRep(
-    absl::Nonnull<status_internal::StatusRep*> rep) {
+    status_internal::StatusRep* absl_nonnull rep) {
   return reinterpret_cast<uintptr_t>(rep);
 }
 
@@ -934,7 +934,7 @@
 // If the status's message is empty, the empty string is returned.
 //
 // StatusMessageAsCStr exists for C support. Use `status.message()` in C++.
-absl::Nonnull<const char*> StatusMessageAsCStr(
+const char* absl_nonnull StatusMessageAsCStr(
     const Status& status ABSL_ATTRIBUTE_LIFETIME_BOUND);
 
 ABSL_NAMESPACE_END
diff --git a/absl/status/status_benchmark.cc b/absl/status/status_benchmark.cc
new file mode 100644
index 0000000..a9146fb
--- /dev/null
+++ b/absl/status/status_benchmark.cc
@@ -0,0 +1,37 @@
+// Copyright 2025 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 <utility>
+#include "absl/status/status.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+void BM_CreateOk(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::Status s;  // ok.
+    benchmark::DoNotOptimize(s);
+  }
+}
+BENCHMARK(BM_CreateOk);
+
+void BM_CreateBad(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::Status s(absl::StatusCode::kInvalidArgument, "message");
+    benchmark::DoNotOptimize(s);
+  }
+}
+BENCHMARK(BM_CreateBad);
+
+}  // namespace
diff --git a/absl/status/status_matchers_test.cc b/absl/status/status_matchers_test.cc
index 3af0305..b8ccaa4 100644
--- a/absl/status/status_matchers_test.cc
+++ b/absl/status/status_matchers_test.cc
@@ -17,6 +17,8 @@
 // -----------------------------------------------------------------------------
 #include "absl/status/status_matchers.h"
 
+#include <string>
+
 #include "gmock/gmock.h"
 #include "gtest/gtest-spi.h"
 #include "gtest/gtest.h"
@@ -29,7 +31,9 @@
 using ::absl_testing::IsOk;
 using ::absl_testing::IsOkAndHolds;
 using ::absl_testing::StatusIs;
+using ::testing::Eq;
 using ::testing::Gt;
+using ::testing::MatchesRegex;
 
 TEST(StatusMatcherTest, StatusIsOk) { EXPECT_THAT(absl::OkStatus(), IsOk()); }
 
@@ -66,6 +70,13 @@
                           "actual");
 }
 
+template <typename MatcherType, typename Value>
+std::string Explain(const MatcherType& m, const Value& x) {
+  ::testing::StringMatchResultListener listener;
+  ExplainMatchResult(m, x, &listener);
+  return listener.str();
+}
+
 TEST(StatusMatcherTest, StatusIs) {
   absl::Status unknown = absl::UnknownError("unbekannt");
   absl::Status invalid = absl::InvalidArgumentError("ungueltig");
@@ -78,6 +89,20 @@
   EXPECT_THAT(invalid, StatusIs(3));
   EXPECT_THAT(invalid,
               StatusIs(absl::StatusCode::kInvalidArgument, "ungueltig"));
+
+  auto m = StatusIs(absl::StatusCode::kInternal, "internal error");
+  EXPECT_THAT(
+      ::testing::DescribeMatcher<absl::Status>(m),
+      MatchesRegex(
+          "has a status code that .*, and has an error message that .*"));
+  EXPECT_THAT(
+      ::testing::DescribeMatcher<absl::Status>(m, /*negation=*/true),
+      MatchesRegex(
+          "either has a status code that .*, or has an error message that .*"));
+  EXPECT_THAT(Explain(m, absl::InvalidArgumentError("internal error")),
+              Eq("whose status code is wrong"));
+  EXPECT_THAT(Explain(m, absl::InternalError("unexpected error")),
+              Eq("whose error message is wrong"));
 }
 
 TEST(StatusMatcherTest, StatusOrIs) {
@@ -94,6 +119,23 @@
   EXPECT_THAT(invalid, StatusIs(3));
   EXPECT_THAT(invalid,
               StatusIs(absl::StatusCode::kInvalidArgument, "ungueltig"));
+
+  auto m = StatusIs(absl::StatusCode::kInternal, "internal error");
+  EXPECT_THAT(
+      ::testing::DescribeMatcher<absl::StatusOr<int>>(m),
+      MatchesRegex(
+          "has a status code that .*, and has an error message that .*"));
+  EXPECT_THAT(
+      ::testing::DescribeMatcher<absl::StatusOr<int>>(m, /*negation=*/true),
+      MatchesRegex(
+          "either has a status code that .*, or has an error message that .*"));
+  EXPECT_THAT(Explain(m, absl::StatusOr<int>(57)), Eq("which is OK"));
+  EXPECT_THAT(Explain(m, absl::StatusOr<int>(
+                             absl::InvalidArgumentError("internal error"))),
+              Eq("whose status code is wrong"));
+  EXPECT_THAT(
+      Explain(m, absl::StatusOr<int>(absl::InternalError("unexpected error"))),
+      Eq("whose error message is wrong"));
 }
 
 TEST(StatusMatcherTest, StatusIsFailure) {
diff --git a/absl/status/status_payload_printer.h b/absl/status/status_payload_printer.h
index f22255e..fc55515 100644
--- a/absl/status/status_payload_printer.h
+++ b/absl/status/status_payload_printer.h
@@ -35,8 +35,8 @@
 // NOTE: This is an internal API and the design is subject to change in the
 // future in a non-backward-compatible way. Since it's only meant for debugging
 // purpose, you should not rely on it in any critical logic.
-using StatusPayloadPrinter = absl::Nullable<absl::optional<std::string> (*)(
-    absl::string_view, const absl::Cord&)>;
+using StatusPayloadPrinter = absl::optional<std::string> (*absl_nullable)(
+    absl::string_view, const absl::Cord&);
 
 // Sets the global payload printer. Only one printer should be set per process.
 // If multiple printers are set, it's undefined which one will be used.
diff --git a/absl/status/statusor.cc b/absl/status/statusor.cc
index 7e6b334..d8f66a6 100644
--- a/absl/status/statusor.cc
+++ b/absl/status/statusor.cc
@@ -55,7 +55,7 @@
 BadStatusOrAccess::BadStatusOrAccess(BadStatusOrAccess&& other)
     : status_(std::move(other.status_)) {}
 
-absl::Nonnull<const char*> BadStatusOrAccess::what() const noexcept {
+const char* absl_nonnull BadStatusOrAccess::what() const noexcept {
   InitWhat();
   return what_.c_str();
 }
@@ -70,7 +70,7 @@
 
 namespace internal_statusor {
 
-void Helper::HandleInvalidStatusCtorArg(absl::Nonnull<absl::Status*> status) {
+void Helper::HandleInvalidStatusCtorArg(absl::Status* absl_nonnull status) {
   const char* kMessage =
       "An OK status is not a valid constructor argument to StatusOr<T>";
 #ifdef NDEBUG
diff --git a/absl/status/statusor.h b/absl/status/statusor.h
index b1da45e..6142a2f 100644
--- a/absl/status/statusor.h
+++ b/absl/status/statusor.h
@@ -93,7 +93,7 @@
   //
   // The pointer of this string is guaranteed to be valid until any non-const
   // function is invoked on the exception object.
-  absl::Nonnull<const char*> what() const noexcept override;
+  const char* absl_nonnull what() const noexcept override;
 
   // BadStatusOrAccess::status()
   //
@@ -464,7 +464,7 @@
   // Returns a reference to the current `absl::Status` contained within the
   // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this
   // function returns `absl::OkStatus()`.
-  const Status& status() const&;
+  ABSL_MUST_USE_RESULT const Status& status() const&;
   Status status() &&;
 
   // StatusOr<T>::value()
@@ -520,8 +520,8 @@
   // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
   //
   // Use `this->ok()` to verify that there is a current value.
-  const T* operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
-  T* operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND;
+  const T* absl_nonnull operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
+  T* absl_nonnull operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND;
 
   // StatusOr<T>::value_or()
   //
@@ -756,13 +756,13 @@
 }
 
 template <typename T>
-absl::Nonnull<const T*> StatusOr<T>::operator->() const {
+const T* absl_nonnull StatusOr<T>::operator->() const {
   this->EnsureOk();
   return &this->data_;
 }
 
 template <typename T>
-absl::Nonnull<T*> StatusOr<T>::operator->() {
+T* absl_nonnull StatusOr<T>::operator->() {
   this->EnsureOk();
   return &this->data_;
 }
diff --git a/absl/status/statusor_benchmark.cc b/absl/status/statusor_benchmark.cc
new file mode 100644
index 0000000..bb99547
--- /dev/null
+++ b/absl/status/statusor_benchmark.cc
@@ -0,0 +1,480 @@
+// Copyright 2025 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 <string>
+
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+void BM_StatusOrInt_CtorStatus(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> status(absl::CancelledError());
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_CtorStatus);
+
+void BM_StatusOrInt_CtorStatusWithMessage(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> status(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_CtorStatusWithMessage);
+
+void BM_StatusOrInt_CopyCtor_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> original(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<int> status(original);
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_CopyCtor_Error);
+
+void BM_StatusOrInt_CopyCtor_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> original(42);
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<int> status(original);
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_CopyCtor_Ok);
+
+void BM_StatusOrInt_MoveCtor_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> original(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<int> status(std::move(original));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_MoveCtor_Error);
+
+void BM_StatusOrInt_MoveCtor_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> original(42);
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<int> status(std::move(original));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_MoveCtor_Ok);
+
+void BM_StatusOrInt_CopyAssign_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> original(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<int> status(42);
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status = original);
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_CopyAssign_Error);
+
+void BM_StatusOrInt_CopyAssign_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> original(42);
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<int> status(42);
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status = original);
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_CopyAssign_Ok);
+
+void BM_StatusOrInt_MoveAssign_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> original(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<int> status(42);
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status = std::move(original));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_MoveAssign_Error);
+
+void BM_StatusOrInt_MoveAssign_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> original(42);
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<int> status(42);
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status = std::move(original));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrInt_MoveAssign_Ok);
+
+void BM_StatusOrInt_OkMethod_Error(benchmark::State& state) {
+  absl::StatusOr<int> status(
+      absl::UnknownError("This string is 28 characters"));
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status.ok());
+  }
+}
+BENCHMARK(BM_StatusOrInt_OkMethod_Error);
+
+void BM_StatusOrInt_OkMethod_Ok(benchmark::State& state) {
+  absl::StatusOr<int> status(42);
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status.ok());
+  }
+}
+BENCHMARK(BM_StatusOrInt_OkMethod_Ok);
+
+void BM_StatusOrInt_StatusMethod_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> status(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status.status().ok());
+  }
+}
+BENCHMARK(BM_StatusOrInt_StatusMethod_Error);
+
+void BM_StatusOrInt_StatusMethod_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> status(42);
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(std::move(status).status().ok());
+  }
+}
+BENCHMARK(BM_StatusOrInt_StatusMethod_Ok);
+
+void BM_StatusOrInt_StatusMethodRvalue_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> status(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(std::move(status).status().ok());
+  }
+}
+BENCHMARK(BM_StatusOrInt_StatusMethodRvalue_Error);
+
+void BM_StatusOrInt_StatusMethodRvalue_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<int> status(42);
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(std::move(status).status());
+  }
+}
+BENCHMARK(BM_StatusOrInt_StatusMethodRvalue_Ok);
+
+void BM_StatusOrString_CtorStatus(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> status(absl::CancelledError());
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_CtorStatus);
+
+void BM_StatusOrString_CtorStatusWithMessage(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> status(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_CtorStatusWithMessage);
+
+void BM_StatusOrString_CopyCtor_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> original(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<std::string> status(original);
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_CopyCtor_Error);
+
+void BM_StatusOrString_CopyCtor_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> original("This string is 28 characters");
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<std::string> status(original);
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_CopyCtor_Ok);
+
+void BM_StatusOrString_MoveCtor_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> original(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<std::string> status(std::move(original));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_MoveCtor_Error);
+
+void BM_StatusOrString_MoveCtor_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> original("This string is 28 characters");
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<std::string> status(std::move(original));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_MoveCtor_Ok);
+
+void BM_StatusOrString_CopyAssign_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> original(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<std::string> status("This string is 28 characters");
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status = original);
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_CopyAssign_Error);
+
+void BM_StatusOrString_CopyAssign_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> original("This string is 28 characters");
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<std::string> status("This string is 28 characters");
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status = original);
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_CopyAssign_Ok);
+
+void BM_StatusOrString_MoveAssign_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> original(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<std::string> status("This string is 28 characters");
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status = std::move(original));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_MoveAssign_Error);
+
+void BM_StatusOrString_MoveAssign_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> original("This string is 28 characters");
+    benchmark::DoNotOptimize(original);
+    absl::StatusOr<std::string> status("This string is 28 characters");
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status = std::move(original));
+    benchmark::DoNotOptimize(status);
+  }
+}
+BENCHMARK(BM_StatusOrString_MoveAssign_Ok);
+
+void BM_StatusOrString_OkMethod_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> status(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status.ok());
+  }
+}
+BENCHMARK(BM_StatusOrString_OkMethod_Error);
+
+void BM_StatusOrString_OkMethod_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> status("This string is 28 characters");
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status.ok());
+  }
+}
+BENCHMARK(BM_StatusOrString_OkMethod_Ok);
+
+void BM_StatusOrString_StatusMethod_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> status(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status.status().ok());
+  }
+}
+BENCHMARK(BM_StatusOrString_StatusMethod_Error);
+
+void BM_StatusOrString_StatusMethod_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> status("This string is 28 characters");
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(status.status().ok());
+  }
+}
+BENCHMARK(BM_StatusOrString_StatusMethod_Ok);
+
+void BM_StatusOrString_StatusMethodRvalue_Error(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> status(
+        absl::UnknownError("This string is 28 characters"));
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(std::move(status).status());
+  }
+}
+BENCHMARK(BM_StatusOrString_StatusMethodRvalue_Error);
+
+void BM_StatusOrString_StatusMethodRvalue_Ok(benchmark::State& state) {
+  for (auto _ : state) {
+    absl::StatusOr<std::string> status("This string is 28 characters");
+    benchmark::DoNotOptimize(status);
+    benchmark::DoNotOptimize(std::move(status).status());
+  }
+}
+BENCHMARK(BM_StatusOrString_StatusMethodRvalue_Ok);
+
+// Benchmarks comparing a few alternative ways of structuring an interface
+// for returning an int64 on success or an error.  See (a), (b), (c), (d)
+// below for the variants.
+bool bm_cond = true;
+
+bool SimpleIntInterface(int64_t* v) ABSL_ATTRIBUTE_NOINLINE;
+bool SimpleIntInterfaceWithErrorMessage(int64_t* v, std::string* msg)
+    ABSL_ATTRIBUTE_NOINLINE;
+absl::Status SimpleIntInterfaceWithErrorStatus(int64_t* v)
+    ABSL_ATTRIBUTE_NOINLINE;
+absl::StatusOr<int64_t> SimpleIntStatusOrInterface() ABSL_ATTRIBUTE_NOINLINE;
+
+// (a): Just a boolean return value with an out int64* parameter
+bool SimpleIntInterface(int64_t* v) {
+  benchmark::DoNotOptimize(bm_cond);
+  if (bm_cond) {
+    *v = 42;
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// (b): A boolean return value and a string error message filled in on failure
+// and an out int64* parameter filled on success
+bool SimpleIntInterfaceWithErrorMessage(int64_t* v, std::string* msg) {
+  benchmark::DoNotOptimize(bm_cond);
+  if (bm_cond) {
+    *v = 42;
+    return true;
+  } else {
+    *msg = "This is an error message";
+    return false;
+  }
+}
+
+// (c): A Status return value with an out int64* parameter on success
+absl::Status SimpleIntInterfaceWithErrorStatus(int64_t* v) {
+  benchmark::DoNotOptimize(bm_cond);
+  if (bm_cond) {
+    *v = 42;
+    return absl::OkStatus();
+  } else {
+    return absl::UnknownError("This is an error message");
+  }
+}
+
+// (d): A StatusOr<int64> return value
+absl::StatusOr<int64_t> SimpleIntStatusOrInterface() {
+  benchmark::DoNotOptimize(bm_cond);
+  if (bm_cond) {
+    return 42;
+  } else {
+    return absl::StatusOr<int64_t>(
+        absl::UnknownError("This is an error message"));
+  }
+}
+
+void SetCondition(benchmark::State& state) {
+  bm_cond = (state.range(0) == 0);
+  state.SetLabel(bm_cond ? "Success" : "Failure");
+}
+
+void BM_SimpleIntInterface(benchmark::State& state) {
+  SetCondition(state);
+  int64_t sum = 0;
+  for (auto s : state) {
+    int64_t v;
+    if (SimpleIntInterface(&v)) {
+      sum += v;
+    }
+    benchmark::DoNotOptimize(sum);
+  }
+}
+
+void BM_SimpleIntInterfaceMsg(benchmark::State& state) {
+  SetCondition(state);
+  int64_t sum = 0;
+  std::string msg;
+  for (auto s : state) {
+    int64_t v;
+    if (SimpleIntInterfaceWithErrorMessage(&v, &msg)) {
+      sum += v;
+    }
+    benchmark::DoNotOptimize(sum);
+    benchmark::DoNotOptimize(msg);
+  }
+}
+
+void BM_SimpleIntInterfaceStatus(benchmark::State& state) {
+  SetCondition(state);
+  int64_t sum = 0;
+  for (auto s : state) {
+    int64_t v;
+    auto result = SimpleIntInterfaceWithErrorStatus(&v);
+    if (result.ok()) {
+      sum += v;
+    }
+    benchmark::DoNotOptimize(sum);
+  }
+}
+
+void BM_SimpleIntStatusOrInterface(benchmark::State& state) {
+  SetCondition(state);
+  int64_t sum = 0;
+  for (auto s : state) {
+    auto v_s = SimpleIntStatusOrInterface();
+    if (v_s.ok()) {
+      sum += *v_s;
+    }
+    benchmark::DoNotOptimize(sum);
+  }
+}
+
+// Ordered like this so all the success path benchmarks (Arg(0)) show up,
+// then all the failure benchmarks (Arg(1))
+BENCHMARK(BM_SimpleIntInterface)->Arg(0);
+BENCHMARK(BM_SimpleIntInterfaceMsg)->Arg(0);
+BENCHMARK(BM_SimpleIntInterfaceStatus)->Arg(0);
+BENCHMARK(BM_SimpleIntStatusOrInterface)->Arg(0);
+BENCHMARK(BM_SimpleIntInterface)->Arg(1);
+BENCHMARK(BM_SimpleIntInterfaceMsg)->Arg(1);
+BENCHMARK(BM_SimpleIntInterfaceStatus)->Arg(1);
+BENCHMARK(BM_SimpleIntStatusOrInterface)->Arg(1);
+
+}  // namespace
diff --git a/absl/status/statusor_test.cc b/absl/status/statusor_test.cc
index 8341040..17a3384 100644
--- a/absl/status/statusor_test.cc
+++ b/absl/status/statusor_test.cc
@@ -459,7 +459,7 @@
     EXPECT_EQ(p, *source);
   }
 
-  // Move asssignment
+  // Move assignment
   {
     const auto p = std::make_shared<int>(17);
     absl::StatusOr<std::shared_ptr<int>> source(p);
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 2cc014e..bb152ac 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -104,6 +104,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
+        "//absl/base:iterator_traits_internal",
         "//absl/base:nullability",
         "//absl/base:raw_logging_internal",
         "//absl/base:throw_delegate",
@@ -146,8 +147,8 @@
     visibility = ["//visibility:private"],
     deps = [
         ":strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -166,13 +167,14 @@
         "//absl/base:core_headers",
         "//absl/container:fixed_array",
         "//absl/log:check",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "escaping_benchmark",
+    testonly = True,
     srcs = [
         "escaping_benchmark.cc",
         "internal/escaping_test_common.h",
@@ -183,8 +185,7 @@
     deps = [
         ":strings",
         "//absl/base:raw_logging_internal",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -197,8 +198,8 @@
     deps = [
         ":strings",
         "//absl/types:optional",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -221,8 +222,8 @@
     deps = [
         ":has_ostream_operator",
         "//absl/types:optional",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -235,21 +236,22 @@
     deps = [
         ":strings",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "ascii_benchmark",
+    testonly = True,
     srcs = ["ascii_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     tags = ["benchmark"],
     visibility = ["//visibility:private"],
     deps = [
         ":strings",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "//absl/random",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -262,13 +264,30 @@
     copts = ABSL_TEST_COPTS,
     deps = [
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
+    name = "damerau_levenshtein_distance_benchmark",
+    testonly = True,
+    srcs = [
+        "internal/damerau_levenshtein_distance_benchmark.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":strings",
+        "@google_benchmark//:benchmark_main",
+    ],
+)
+
+cc_binary(
     name = "memutil_benchmark",
+    testonly = True,
     srcs = [
         "internal/memutil.h",
         "internal/memutil_benchmark.cc",
@@ -279,8 +298,7 @@
     deps = [
         ":strings",
         "//absl/base:core_headers",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -296,8 +314,8 @@
     deps = [
         ":strings",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -311,9 +329,10 @@
     visibility = ["//visibility:private"],
     deps = [
         ":internal",
+        ":string_view",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -326,13 +345,14 @@
     deps = [
         ":strings",
         "//absl/meta:type_traits",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "string_view_benchmark",
+    testonly = True,
     srcs = ["string_view_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     tags = ["benchmark"],
@@ -342,8 +362,8 @@
         ":strings",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "//absl/random",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -359,14 +379,14 @@
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
         "//absl/meta:type_traits",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "charset_benchmark",
-    size = "small",
+    testonly = True,
     srcs = [
         "charset_benchmark.cc",
     ],
@@ -378,8 +398,7 @@
     deps = [
         ":charset",
         "//absl/log:check",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -392,7 +411,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":string_view",
-        "//absl/base:core_headers",
+        "//absl/base:config",
     ],
 )
 
@@ -405,8 +424,8 @@
     deps = [
         ":charset",
         ":strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -437,19 +456,16 @@
     ],
     deps = [
         ":strings",
-        "//absl/base:base_internal",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
+        "//absl/base:nullability",
         "//absl/base:raw_logging_internal",
-        "//absl/base:throw_delegate",
         "//absl/container:compressed_tuple",
         "//absl/container:container_memory",
         "//absl/container:inlined_vector",
-        "//absl/container:layout",
         "//absl/crc:crc_cord_state",
         "//absl/functional:function_ref",
-        "//absl/meta:type_traits",
         "//absl/types:span",
     ],
 )
@@ -465,8 +481,8 @@
         ":cord_rep_test_util",
         ":strings",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -484,8 +500,8 @@
         "//absl/base:config",
         "//absl/base:raw_logging_internal",
         "//absl/cleanup",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -501,8 +517,8 @@
         ":strings",
         "//absl/base:config",
         "//absl/base:raw_logging_internal",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -519,8 +535,8 @@
         ":strings",
         "//absl/base:config",
         "//absl/base:raw_logging_internal",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -535,8 +551,8 @@
         ":cord_rep_test_util",
         "//absl/base:config",
         "//absl/crc:crc_cord_state",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -559,8 +575,8 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/synchronization",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -570,7 +586,6 @@
         "cord.cc",
         "cord_analysis.cc",
         "cord_analysis.h",
-        "cord_buffer.cc",
     ],
     hdrs = [
         "cord.h",
@@ -580,14 +595,11 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":cord_internal",
-        ":cordz_functions",
         ":cordz_info",
-        ":cordz_statistics",
         ":cordz_update_scope",
         ":cordz_update_tracker",
         ":internal",
         ":strings",
-        "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
@@ -597,6 +609,7 @@
         "//absl/crc:crc32c",
         "//absl/crc:crc_cord_state",
         "//absl/functional:function_ref",
+        "//absl/hash:weakly_mixed_integer",
         "//absl/meta:type_traits",
         "//absl/numeric:bits",
         "//absl/types:compare",
@@ -611,9 +624,7 @@
     hdrs = ["internal/cordz_handle.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl:__subpackages__",
-    ],
+    visibility = ["//absl:__subpackages__"],
     deps = [
         "//absl/base:config",
         "//absl/base:no_destructor",
@@ -654,9 +665,7 @@
     hdrs = ["internal/cordz_update_scope.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl:__subpackages__",
-    ],
+    visibility = ["//absl:__subpackages__"],
     deps = [
         ":cord_internal",
         ":cordz_info",
@@ -677,8 +686,8 @@
         ":cordz_update_scope",
         ":cordz_update_tracker",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -738,8 +747,8 @@
         ":cordz_functions",
         ":cordz_test_helpers",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -757,8 +766,8 @@
         "//absl/synchronization",
         "//absl/synchronization:thread_pool",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -779,8 +788,8 @@
         "//absl/debugging:stacktrace",
         "//absl/debugging:symbolize",
         "//absl/types:span",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -801,8 +810,8 @@
         "//absl/crc:crc_cord_state",
         "//absl/synchronization",
         "//absl/synchronization:thread_pool",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -823,8 +832,8 @@
         "//absl/synchronization",
         "//absl/synchronization:thread_pool",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -875,7 +884,7 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:nullability",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
 )
 
@@ -892,8 +901,8 @@
         ":string_view",
         "//absl/base:config",
         "//absl/types:span",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -927,8 +936,8 @@
         "//absl/random",
         "//absl/types:compare",
         "//absl/types:optional",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -938,7 +947,6 @@
     srcs = ["cordz_test.cc"],
     copts = ABSL_TEST_COPTS,
     tags = [
-        "benchmark",
         "no_test_android_arm",
         "no_test_android_arm64",
         "no_test_android_x86",
@@ -961,8 +969,8 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -975,13 +983,30 @@
     deps = [
         ":strings",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
+    name = "substitute_benchmark",
+    testonly = True,
+    srcs = ["substitute_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    tags = [
+        "benchmark",
+    ],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":strings",
+        "//absl/base:core_headers",
+        "@google_benchmark//:benchmark_main",
+    ],
+)
+
+cc_binary(
     name = "str_replace_benchmark",
+    testonly = True,
     srcs = ["str_replace_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     tags = ["benchmark"],
@@ -989,8 +1014,7 @@
     deps = [
         ":strings",
         "//absl/base:raw_logging_internal",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -1002,8 +1026,8 @@
     visibility = ["//visibility:private"],
     deps = [
         ":strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1019,13 +1043,14 @@
         "//absl/container:btree",
         "//absl/container:flat_hash_map",
         "//absl/container:node_hash_map",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "str_split_benchmark",
+    testonly = True,
     srcs = ["str_split_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     tags = ["benchmark"],
@@ -1033,8 +1058,7 @@
     deps = [
         ":strings",
         "//absl/base:raw_logging_internal",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -1046,21 +1070,21 @@
     visibility = ["//visibility:private"],
     deps = [
         ":internal",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "ostringstream_benchmark",
+    testonly = True,
     srcs = ["internal/ostringstream_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     tags = ["benchmark"],
     visibility = ["//visibility:private"],
     deps = [
         ":internal",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -1076,8 +1100,8 @@
     deps = [
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1091,21 +1115,21 @@
         ":strings",
         "//absl/base:core_headers",
         "//absl/memory",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "str_join_benchmark",
+    testonly = True,
     srcs = ["str_join_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     tags = ["benchmark"],
     visibility = ["//visibility:private"],
     deps = [
         ":strings",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -1118,23 +1142,25 @@
     deps = [
         ":str_format",
         ":strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "//absl/base:config",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "str_cat_benchmark",
+    testonly = True,
     srcs = ["str_cat_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     tags = ["benchmark"],
     visibility = ["//visibility:private"],
     deps = [
+        ":str_format",
         ":strings",
         "//absl/random",
         "//absl/random:distributions",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -1156,13 +1182,14 @@
         "//absl/numeric:int128",
         "//absl/random",
         "//absl/random:distributions",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "numbers_benchmark",
+    testonly = True,
     srcs = ["numbers_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
     tags = ["benchmark"],
@@ -1172,8 +1199,7 @@
         "//absl/base:raw_logging_internal",
         "//absl/random",
         "//absl/random:distributions",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -1185,8 +1211,8 @@
     visibility = ["//visibility:private"],
     deps = [
         ":strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1198,8 +1224,8 @@
         ":pow10_helper",
         ":str_format",
         ":strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1214,8 +1240,8 @@
         ":strings",
         "//absl/base:config",
         "//absl/log:check",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1230,13 +1256,14 @@
     deps = [
         ":strings",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "charconv_benchmark",
+    testonly = True,
     srcs = [
         "charconv_benchmark.cc",
     ],
@@ -1245,8 +1272,7 @@
     ],
     deps = [
         ":strings",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -1291,6 +1317,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = ["//visibility:private"],
     deps = [
+        ":internal",
         ":strings",
         "//absl/base:config",
         "//absl/base:core_headers",
@@ -1319,8 +1346,8 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/types:span",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1335,8 +1362,9 @@
         ":str_format",
         ":str_format_internal",
         ":strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "//absl/random",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1349,8 +1377,8 @@
         ":str_format",
         ":str_format_internal",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1361,8 +1389,8 @@
     visibility = ["//visibility:private"],
     deps = [
         ":str_format_internal",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1373,8 +1401,8 @@
     visibility = ["//visibility:private"],
     deps = [
         ":str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1396,8 +1424,8 @@
         "//absl/numeric:int128",
         "//absl/types:optional",
         "//absl/types:span",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1409,8 +1437,8 @@
     deps = [
         ":cord",
         ":str_format_internal",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1424,8 +1452,8 @@
         ":string_view",
         "//absl/base:config",
         "//absl/base:core_headers",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1447,8 +1475,8 @@
     deps = [
         ":pow10_helper",
         ":str_format",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -1475,7 +1503,7 @@
     deps = [
         ":str_format",
         ":strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index 3a1619e..547ef26 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -84,6 +84,7 @@
     absl::core_headers
     absl::endian
     absl::int128
+    absl::iterator_traits_internal
     absl::memory
     absl::nullability
     absl::raw_logging_internal
@@ -100,7 +101,7 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::core_headers
+    absl::config
     absl::string_view
   PUBLIC
 )
@@ -242,6 +243,7 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::string_view
     absl::strings_internal
     absl::base
     absl::core_headers
@@ -371,6 +373,7 @@
   DEPS
     absl::strings
     absl::str_format
+    absl::config
     absl::core_headers
     GTest::gmock_main
 )
@@ -516,6 +519,7 @@
     absl::utility
     absl::int128
     absl::span
+    absl::strings_internal
 )
 
 absl_cc_test(
@@ -543,6 +547,7 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::random_random
     absl::str_format
     absl::str_format_internal
     absl::strings
@@ -700,7 +705,6 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::base_internal
     absl::compressed_tuple
     absl::config
     absl::container_memory
@@ -975,7 +979,6 @@
     "cord.cc"
     "cord_analysis.cc"
     "cord_analysis.h"
-    "cord_buffer.cc"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
@@ -998,6 +1001,7 @@
     absl::span
     absl::strings
     absl::type_traits
+    absl::weakly_mixed_integer
   PUBLIC
 )
 
diff --git a/absl/strings/ascii.cc b/absl/strings/ascii.cc
index 20a696a..4cd9ff9 100644
--- a/absl/strings/ascii.cc
+++ b/absl/strings/ascii.cc
@@ -19,10 +19,8 @@
 #include <cstring>
 #include <string>
 
-#include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/nullability.h"
-#include "absl/base/optimization.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -177,10 +175,17 @@
   return static_cast<signed char>(u) < threshold;
 }
 
-// Force-inline so the compiler won't merge the short and long implementations.
 template <bool ToUpper>
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline constexpr void AsciiStrCaseFoldImpl(
-    absl::Nonnull<char*> p, size_t size) {
+constexpr bool AsciiInAZRangeNaive(unsigned char c) {
+  constexpr unsigned char a = (ToUpper ? 'a' : 'A');
+  constexpr unsigned char z = (ToUpper ? 'z' : 'Z');
+  return a <= c && c <= z;
+}
+
+template <bool ToUpper, bool Naive>
+constexpr void AsciiStrCaseFoldImpl(char* absl_nonnull dst,
+                                    const char* absl_nullable src,
+                                    size_t size) {
   // The upper- and lowercase versions of ASCII characters differ by only 1 bit.
   // When we need to flip the case, we can xor with this bit to achieve the
   // desired result. Note that the choice of 'a' and 'A' here is arbitrary. We
@@ -189,29 +194,37 @@
   constexpr unsigned char kAsciiCaseBitFlip = 'a' ^ 'A';
 
   for (size_t i = 0; i < size; ++i) {
-    unsigned char v = static_cast<unsigned char>(p[i]);
-    v ^= AsciiInAZRange<ToUpper>(v) ? kAsciiCaseBitFlip : 0;
-    p[i] = static_cast<char>(v);
+    unsigned char v = static_cast<unsigned char>(src[i]);
+    if ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 (Naive) {
+      v ^= AsciiInAZRangeNaive<ToUpper>(v) ? kAsciiCaseBitFlip : 0;
+    } else {
+      v ^= AsciiInAZRange<ToUpper>(v) ? kAsciiCaseBitFlip : 0;
+    }
+    dst[i] = static_cast<char>(v);
   }
 }
 
-// The string size threshold for starting using the long string version.
-constexpr size_t kCaseFoldThreshold = 16;
-
-// No-inline so the compiler won't merge the short and long implementations.
-template <bool ToUpper>
-ABSL_ATTRIBUTE_NOINLINE constexpr void AsciiStrCaseFoldLong(
-    absl::Nonnull<char*> p, size_t size) {
-  ABSL_ASSUME(size >= kCaseFoldThreshold);
-  AsciiStrCaseFoldImpl<ToUpper>(p, size);
-}
-
 // Splitting to short and long strings to allow vectorization decisions
 // to be made separately in the long and short cases.
+// Using slightly different implementations so the compiler won't optimize them
+// into the same code (the non-naive version is needed for SIMD, so for short
+// strings it's not important).
+// `src` may be null iff `size` is zero.
 template <bool ToUpper>
-constexpr void AsciiStrCaseFold(absl::Nonnull<char*> p, size_t size) {
-  size < kCaseFoldThreshold ? AsciiStrCaseFoldImpl<ToUpper>(p, size)
-                            : AsciiStrCaseFoldLong<ToUpper>(p, size);
+constexpr void AsciiStrCaseFold(char* absl_nonnull dst,
+                                const char* absl_nullable src, size_t size) {
+  size < 16 ? AsciiStrCaseFoldImpl<ToUpper, /*Naive=*/true>(dst, src, size)
+            : AsciiStrCaseFoldImpl<ToUpper, /*Naive=*/false>(dst, src, size);
+}
+
+void AsciiStrToLower(char* absl_nonnull dst, const char* absl_nullable src,
+                     size_t n) {
+  return AsciiStrCaseFold<false>(dst, src, n);
+}
+
+void AsciiStrToUpper(char* absl_nonnull dst, const char* absl_nullable src,
+                     size_t n) {
+  return AsciiStrCaseFold<true>(dst, src, n);
 }
 
 static constexpr size_t ValidateAsciiCasefold() {
@@ -222,8 +235,8 @@
   for (unsigned int i = 0; i < num_chars; ++i) {
     uppered[i] = lowered[i] = static_cast<char>(i);
   }
-  AsciiStrCaseFold<false>(&lowered[0], num_chars);
-  AsciiStrCaseFold<true>(&uppered[0], num_chars);
+  AsciiStrCaseFold<false>(&lowered[0], &lowered[0], num_chars);
+  AsciiStrCaseFold<true>(&uppered[0], &uppered[0], num_chars);
   for (size_t i = 0; i < num_chars; ++i) {
     const char ch = static_cast<char>(i),
                ch_upper = ('a' <= ch && ch <= 'z' ? 'A' + (ch - 'a') : ch),
@@ -240,15 +253,17 @@
 
 }  // namespace ascii_internal
 
-void AsciiStrToLower(absl::Nonnull<std::string*> s) {
-  return ascii_internal::AsciiStrCaseFold<false>(&(*s)[0], s->size());
+void AsciiStrToLower(std::string* absl_nonnull s) {
+  char* p = &(*s)[0];
+  return ascii_internal::AsciiStrCaseFold<false>(p, p, s->size());
 }
 
-void AsciiStrToUpper(absl::Nonnull<std::string*> s) {
-  return ascii_internal::AsciiStrCaseFold<true>(&(*s)[0], s->size());
+void AsciiStrToUpper(std::string* absl_nonnull s) {
+  char* p = &(*s)[0];
+  return ascii_internal::AsciiStrCaseFold<true>(p, p, s->size());
 }
 
-void RemoveExtraAsciiWhitespace(absl::Nonnull<std::string*> str) {
+void RemoveExtraAsciiWhitespace(std::string* absl_nonnull str) {
   auto stripped = StripAsciiWhitespace(*str);
 
   if (stripped.empty()) {
diff --git a/absl/strings/ascii.h b/absl/strings/ascii.h
index c238f4d..ca0747e 100644
--- a/absl/strings/ascii.h
+++ b/absl/strings/ascii.h
@@ -55,10 +55,12 @@
 #include <algorithm>
 #include <cstddef>
 #include <string>
+#include <utility>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/nullability.h"
+#include "absl/strings/internal/resize_uninitialized.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
@@ -74,6 +76,12 @@
 // Declaration for the array of characters to lower-case characters.
 ABSL_DLL extern const char kToLower[256];
 
+void AsciiStrToLower(char* absl_nonnull dst, const char* absl_nullable src,
+                     size_t n);
+
+void AsciiStrToUpper(char* absl_nonnull dst, const char* absl_nullable src,
+                     size_t n);
+
 }  // namespace ascii_internal
 
 // ascii_isalpha()
@@ -131,32 +139,42 @@
 //
 // Determines whether the given character can be represented as a decimal
 // digit character (i.e. {0-9}).
-inline bool ascii_isdigit(unsigned char c) { return c >= '0' && c <= '9'; }
+inline constexpr bool ascii_isdigit(unsigned char c) {
+  return c >= '0' && c <= '9';
+}
 
 // ascii_isprint()
 //
 // Determines whether the given character is printable, including spaces.
-inline bool ascii_isprint(unsigned char c) { return c >= 32 && c < 127; }
+inline constexpr bool ascii_isprint(unsigned char c) {
+  return c >= 32 && c < 127;
+}
 
 // ascii_isgraph()
 //
 // Determines whether the given character has a graphical representation.
-inline bool ascii_isgraph(unsigned char c) { return c > 32 && c < 127; }
+inline constexpr bool ascii_isgraph(unsigned char c) {
+  return c > 32 && c < 127;
+}
 
 // ascii_isupper()
 //
 // Determines whether the given character is uppercase.
-inline bool ascii_isupper(unsigned char c) { return c >= 'A' && c <= 'Z'; }
+inline constexpr bool ascii_isupper(unsigned char c) {
+  return c >= 'A' && c <= 'Z';
+}
 
 // ascii_islower()
 //
 // Determines whether the given character is lowercase.
-inline bool ascii_islower(unsigned char c) { return c >= 'a' && c <= 'z'; }
+inline constexpr bool ascii_islower(unsigned char c) {
+  return c >= 'a' && c <= 'z';
+}
 
 // ascii_isascii()
 //
 // Determines whether the given character is ASCII.
-inline bool ascii_isascii(unsigned char c) { return c < 128; }
+inline constexpr bool ascii_isascii(unsigned char c) { return c < 128; }
 
 // ascii_tolower()
 //
@@ -167,11 +185,22 @@
 }
 
 // Converts the characters in `s` to lowercase, changing the contents of `s`.
-void AsciiStrToLower(absl::Nonnull<std::string*> s);
+void AsciiStrToLower(std::string* absl_nonnull s);
 
 // Creates a lowercase string from a given absl::string_view.
-ABSL_MUST_USE_RESULT inline std::string AsciiStrToLower(absl::string_view s) {
-  std::string result(s);
+[[nodiscard]] inline std::string AsciiStrToLower(absl::string_view s) {
+  std::string result;
+  strings_internal::STLStringResizeUninitialized(&result, s.size());
+  ascii_internal::AsciiStrToLower(&result[0], s.data(), s.size());
+  return result;
+}
+
+// Creates a lowercase string from a given std::string&&.
+//
+// (Template is used to lower priority of this overload.)
+template <int&... DoNotSpecify>
+[[nodiscard]] inline std::string AsciiStrToLower(std::string&& s) {
+  std::string result = std::move(s);
   absl::AsciiStrToLower(&result);
   return result;
 }
@@ -185,58 +214,69 @@
 }
 
 // Converts the characters in `s` to uppercase, changing the contents of `s`.
-void AsciiStrToUpper(absl::Nonnull<std::string*> s);
+void AsciiStrToUpper(std::string* absl_nonnull s);
 
 // Creates an uppercase string from a given absl::string_view.
-ABSL_MUST_USE_RESULT inline std::string AsciiStrToUpper(absl::string_view s) {
-  std::string result(s);
+[[nodiscard]] inline std::string AsciiStrToUpper(absl::string_view s) {
+  std::string result;
+  strings_internal::STLStringResizeUninitialized(&result, s.size());
+  ascii_internal::AsciiStrToUpper(&result[0], s.data(), s.size());
+  return result;
+}
+
+// Creates an uppercase string from a given std::string&&.
+//
+// (Template is used to lower priority of this overload.)
+template <int&... DoNotSpecify>
+[[nodiscard]] inline std::string AsciiStrToUpper(std::string&& s) {
+  std::string result = std::move(s);
   absl::AsciiStrToUpper(&result);
   return result;
 }
 
 // Returns absl::string_view with whitespace stripped from the beginning of the
 // given string_view.
-ABSL_MUST_USE_RESULT inline absl::string_view StripLeadingAsciiWhitespace(
-    absl::string_view str) {
+[[nodiscard]] inline absl::string_view StripLeadingAsciiWhitespace(
+    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND) {
   auto it = std::find_if_not(str.begin(), str.end(), absl::ascii_isspace);
   return str.substr(static_cast<size_t>(it - str.begin()));
 }
 
 // Strips in place whitespace from the beginning of the given string.
-inline void StripLeadingAsciiWhitespace(absl::Nonnull<std::string*> str) {
+inline void StripLeadingAsciiWhitespace(std::string* absl_nonnull str) {
   auto it = std::find_if_not(str->begin(), str->end(), absl::ascii_isspace);
   str->erase(str->begin(), it);
 }
 
 // Returns absl::string_view with whitespace stripped from the end of the given
 // string_view.
-ABSL_MUST_USE_RESULT inline absl::string_view StripTrailingAsciiWhitespace(
-    absl::string_view str) {
+[[nodiscard]] inline absl::string_view StripTrailingAsciiWhitespace(
+    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND) {
   auto it = std::find_if_not(str.rbegin(), str.rend(), absl::ascii_isspace);
   return str.substr(0, static_cast<size_t>(str.rend() - it));
 }
 
 // Strips in place whitespace from the end of the given string
-inline void StripTrailingAsciiWhitespace(absl::Nonnull<std::string*> str) {
+inline void StripTrailingAsciiWhitespace(std::string* absl_nonnull str) {
   auto it = std::find_if_not(str->rbegin(), str->rend(), absl::ascii_isspace);
   str->erase(static_cast<size_t>(str->rend() - it));
 }
 
 // Returns absl::string_view with whitespace stripped from both ends of the
 // given string_view.
-ABSL_MUST_USE_RESULT inline absl::string_view StripAsciiWhitespace(
-    absl::string_view str) {
+[[nodiscard]] inline absl::string_view StripAsciiWhitespace(
+    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND) {
   return StripTrailingAsciiWhitespace(StripLeadingAsciiWhitespace(str));
 }
 
 // Strips in place whitespace from both ends of the given string
-inline void StripAsciiWhitespace(absl::Nonnull<std::string*> str) {
+inline void StripAsciiWhitespace(std::string* absl_nonnull str) {
   StripTrailingAsciiWhitespace(str);
   StripLeadingAsciiWhitespace(str);
 }
 
 // Removes leading, trailing, and consecutive internal whitespace.
-void RemoveExtraAsciiWhitespace(absl::Nonnull<std::string*> str);
+void RemoveExtraAsciiWhitespace(std::string* absl_nonnull str);
 
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/ascii_benchmark.cc b/absl/strings/ascii_benchmark.cc
index 4ae7317..435090d 100644
--- a/absl/strings/ascii_benchmark.cc
+++ b/absl/strings/ascii_benchmark.cc
@@ -12,15 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/ascii.h"
-
 #include <algorithm>
+#include <array>
 #include <cctype>
 #include <cstddef>
 #include <string>
-#include <array>
-#include <random>
 
+#include "absl/random/random.h"
+#include "absl/strings/ascii.h"
 #include "benchmark/benchmark.h"
 
 namespace {
@@ -28,10 +27,8 @@
 std::array<unsigned char, 256> MakeShuffledBytes() {
   std::array<unsigned char, 256> bytes;
   for (size_t i = 0; i < 256; ++i) bytes[i] = static_cast<unsigned char>(i);
-  std::random_device rd;
-  std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()});
-  std::mt19937 g(seed);
-  std::shuffle(bytes.begin(), bytes.end(), g);
+  absl::InsecureBitGen gen;
+  std::shuffle(bytes.begin(), bytes.end(), gen);
   return bytes;
 }
 
@@ -102,7 +99,7 @@
 BENCHMARK_TEMPLATE(BM_Ascii, absl::ascii_toupper);
 
 static void BM_StrToLower(benchmark::State& state) {
-  const int size = state.range(0);
+  const size_t size = static_cast<size_t>(state.range(0));
   std::string s(size, 'X');
   for (auto _ : state) {
     benchmark::DoNotOptimize(s);
@@ -116,7 +113,7 @@
     ->Range(64, 1 << 26);
 
 static void BM_StrToUpper(benchmark::State& state) {
-  const int size = state.range(0);
+  const size_t size = static_cast<size_t>(state.range(0));
   std::string s(size, 'x');
   for (auto _ : state) {
     benchmark::DoNotOptimize(s);
@@ -129,4 +126,32 @@
     ->RangeMultiplier(2)
     ->Range(64, 1 << 26);
 
+static void BM_StrToUpperFromRvalref(benchmark::State& state) {
+  const size_t size = static_cast<size_t>(state.range(0));
+  std::string s(size, 'X');
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(s);
+    std::string res = absl::AsciiStrToUpper(std::string(s));
+    benchmark::DoNotOptimize(res);
+  }
+}
+BENCHMARK(BM_StrToUpperFromRvalref)
+    ->DenseRange(0, 32)
+    ->RangeMultiplier(2)
+    ->Range(64, 1 << 26);
+
+static void BM_StrToLowerFromRvalref(benchmark::State& state) {
+  const size_t size = static_cast<size_t>(state.range(0));
+  std::string s(size, 'x');
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(s);
+    std::string res = absl::AsciiStrToLower(std::string(s));
+    benchmark::DoNotOptimize(res);
+  }
+}
+BENCHMARK(BM_StrToLowerFromRvalref)
+    ->DenseRange(0, 32)
+    ->RangeMultiplier(2)
+    ->Range(64, 1 << 26);
+
 }  // namespace
diff --git a/absl/strings/ascii_test.cc b/absl/strings/ascii_test.cc
index 8885bb1..fe1083a 100644
--- a/absl/strings/ascii_test.cc
+++ b/absl/strings/ascii_test.cc
@@ -192,11 +192,17 @@
   const absl::string_view sp(str2);
   const std::string long_str("ABCDEFGHIJKLMNOPQRSTUVWXYZ1!a");
   std::string mutable_str("_`?@[{AMNOPQRSTUVWXYZ");
+  auto fun = []() -> std::string { return "PQRSTU"; };
 
   EXPECT_EQ("abcdef", absl::AsciiStrToLower(buf));
   EXPECT_EQ("ghijkl", absl::AsciiStrToLower(str));
   EXPECT_EQ("mnopqr", absl::AsciiStrToLower(sp));
   EXPECT_EQ("abcdefghijklmnopqrstuvwxyz1!a", absl::AsciiStrToLower(long_str));
+  EXPECT_EQ("pqrstu", absl::AsciiStrToLower(fun()));
+
+  // An empty `string_view` specifically exercises the case where a null data
+  // pointer is passed to internal functions.
+  EXPECT_EQ("", absl::AsciiStrToLower(absl::string_view()));
 
   absl::AsciiStrToLower(&mutable_str);
   EXPECT_EQ("_`?@[{amnopqrstuvwxyz", mutable_str);
@@ -213,11 +219,17 @@
   const std::string str2("_`?@[{amnopqrstuvwxyz");
   const absl::string_view sp(str2);
   const std::string long_str("abcdefghijklmnopqrstuvwxyz1!A");
+  auto fun = []() -> std::string { return "pqrstu"; };
 
   EXPECT_EQ("ABCDEF", absl::AsciiStrToUpper(buf));
   EXPECT_EQ("GHIJKL", absl::AsciiStrToUpper(str));
   EXPECT_EQ("_`?@[{AMNOPQRSTUVWXYZ", absl::AsciiStrToUpper(sp));
   EXPECT_EQ("ABCDEFGHIJKLMNOPQRSTUVWXYZ1!A", absl::AsciiStrToUpper(long_str));
+  EXPECT_EQ("PQRSTU", absl::AsciiStrToUpper(fun()));
+
+  // An empty `string_view` specifically exercises the case where a null data
+  // pointer is passed to internal functions.
+  EXPECT_EQ("", absl::AsciiStrToUpper(absl::string_view()));
 
   char mutable_buf[] = "Mutable";
   std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),
diff --git a/absl/strings/charconv.cc b/absl/strings/charconv.cc
index 0c9227f..6f36773 100644
--- a/absl/strings/charconv.cc
+++ b/absl/strings/charconv.cc
@@ -120,7 +120,7 @@
   // Parsing a smaller N will produce something finite.
   static constexpr int kEiselLemireMaxExclusiveExp10 = 309;
 
-  static double MakeNan(absl::Nonnull<const char*> tagp) {
+  static double MakeNan(const char* absl_nonnull tagp) {
 #if ABSL_HAVE_BUILTIN(__builtin_nan)
     // Use __builtin_nan() if available since it has a fix for
     // https://bugs.llvm.org/show_bug.cgi?id=37778
@@ -193,7 +193,7 @@
   static constexpr int kEiselLemireMinInclusiveExp10 = -46 - 18;
   static constexpr int kEiselLemireMaxExclusiveExp10 = 39;
 
-  static float MakeNan(absl::Nonnull<const char*> tagp) {
+  static float MakeNan(const char* absl_nonnull tagp) {
 #if ABSL_HAVE_BUILTIN(__builtin_nanf)
     // Use __builtin_nanf() if available since it has a fix for
     // https://bugs.llvm.org/show_bug.cgi?id=37778
@@ -345,7 +345,7 @@
 // `value` must be wider than the requested bit width.
 //
 // Returns the number of bits shifted.
-int TruncateToBitWidth(int bit_width, absl::Nonnull<uint128*> value) {
+int TruncateToBitWidth(int bit_width, uint128* absl_nonnull value) {
   const int current_bit_width = BitWidth(*value);
   const int shift = current_bit_width - bit_width;
   *value >>= shift;
@@ -357,18 +357,15 @@
 // the appropriate double, and returns true.
 template <typename FloatType>
 bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative,
-                    absl::Nonnull<FloatType*> value) {
+                    FloatType* absl_nonnull value) {
   if (input.type == strings_internal::FloatType::kNan) {
-    // A bug in both clang < 7 and gcc would cause the compiler to optimize
-    // away the buffer we are building below.  Declaring the buffer volatile
-    // avoids the issue, and has no measurable performance impact in
-    // microbenchmarks.
+    // A bug in gcc would cause the compiler to optimize away the buffer we are
+    // building below.  Declaring the buffer volatile avoids the issue, and has
+    // no measurable performance impact in microbenchmarks.
     //
-    // https://bugs.llvm.org/show_bug.cgi?id=37778
     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86113
     constexpr ptrdiff_t kNanBufferSize = 128;
-#if (defined(__GNUC__) && !defined(__clang__)) || \
-    (defined(__clang__) && __clang_major__ < 7)
+#if (defined(__GNUC__) && !defined(__clang__))
     volatile char n_char_sequence[kNanBufferSize];
 #else
     char n_char_sequence[kNanBufferSize];
@@ -392,7 +389,7 @@
     return true;
   }
   if (input.mantissa == 0) {
-    *value = negative ? -0.0 : 0.0;
+    *value = negative ? -0.0f : 0.0f;
     return true;
   }
   return false;
@@ -406,8 +403,8 @@
 // number is stored in *value.
 template <typename FloatType>
 void EncodeResult(const CalculatedFloat& calculated, bool negative,
-                  absl::Nonnull<absl::from_chars_result*> result,
-                  absl::Nonnull<FloatType*> value) {
+                  absl::from_chars_result* absl_nonnull result,
+                  FloatType* absl_nonnull value) {
   if (calculated.exponent == kOverflow) {
     result->ec = std::errc::result_out_of_range;
     *value = negative ? -std::numeric_limits<FloatType>::max()
@@ -415,7 +412,7 @@
     return;
   } else if (calculated.mantissa == 0 || calculated.exponent == kUnderflow) {
     result->ec = std::errc::result_out_of_range;
-    *value = negative ? -0.0 : 0.0;
+    *value = negative ? -0.0f : 0.0f;
     return;
   }
   *value = FloatTraits<FloatType>::Make(
@@ -453,7 +450,7 @@
 // Zero and negative values of `shift` are accepted, in which case the word is
 // shifted left, as necessary.
 uint64_t ShiftRightAndRound(uint128 value, int shift, bool input_exact,
-                            absl::Nonnull<bool*> output_exact) {
+                            bool* absl_nonnull output_exact) {
   if (shift <= 0) {
     *output_exact = input_exact;
     return static_cast<uint64_t>(value << -shift);
@@ -687,12 +684,11 @@
 // this function returns false) is both fast and correct.
 template <typename FloatType>
 bool EiselLemire(const strings_internal::ParsedFloat& input, bool negative,
-                 absl::Nonnull<FloatType*> value,
-                 absl::Nonnull<std::errc*> ec) {
+                 FloatType* absl_nonnull value, std::errc* absl_nonnull ec) {
   uint64_t man = input.mantissa;
   int exp10 = input.exponent;
   if (exp10 < FloatTraits<FloatType>::kEiselLemireMinInclusiveExp10) {
-    *value = negative ? -0.0 : 0.0;
+    *value = negative ? -0.0f : 0.0f;
     *ec = std::errc::result_out_of_range;
     return true;
   } else if (exp10 >= FloatTraits<FloatType>::kEiselLemireMaxExclusiveExp10) {
@@ -845,7 +841,7 @@
     if (negative) {
       ret_bits |= 0x8000000000000000u;
     }
-    *value = absl::bit_cast<double>(ret_bits);
+    *value = static_cast<FloatType>(absl::bit_cast<double>(ret_bits));
     return true;
   } else if (FloatTraits<FloatType>::kTargetBits == 32) {
     uint32_t ret_bits = (static_cast<uint32_t>(ret_exp2) << 23) |
@@ -853,7 +849,7 @@
     if (negative) {
       ret_bits |= 0x80000000u;
     }
-    *value = absl::bit_cast<float>(ret_bits);
+    *value = static_cast<FloatType>(absl::bit_cast<float>(ret_bits));
     return true;
   }
 #endif  // ABSL_BIT_PACK_FLOATS
@@ -861,9 +857,9 @@
 }
 
 template <typename FloatType>
-from_chars_result FromCharsImpl(absl::Nonnull<const char*> first,
-                                absl::Nonnull<const char*> last,
-                                FloatType& value, chars_format fmt_flags) {
+from_chars_result FromCharsImpl(const char* absl_nonnull first,
+                                const char* absl_nonnull last, FloatType& value,
+                                chars_format fmt_flags) {
   from_chars_result result;
   result.ptr = first;  // overwritten on successful parse
   result.ec = std::errc();
@@ -893,7 +889,7 @@
         result.ec = std::errc::invalid_argument;
       } else {
         result.ptr = first + 1;
-        value = negative ? -0.0 : 0.0;
+        value = negative ? -0.0f : 0.0f;
       }
       return result;
     }
@@ -948,14 +944,14 @@
 }
 }  // namespace
 
-from_chars_result from_chars(absl::Nonnull<const char*> first,
-                             absl::Nonnull<const char*> last, double& value,
+from_chars_result from_chars(const char* absl_nonnull first,
+                             const char* absl_nonnull last, double& value,
                              chars_format fmt) {
   return FromCharsImpl(first, last, value, fmt);
 }
 
-from_chars_result from_chars(absl::Nonnull<const char*> first,
-                             absl::Nonnull<const char*> last, float& value,
+from_chars_result from_chars(const char* absl_nonnull first,
+                             const char* absl_nonnull last, float& value,
                              chars_format fmt) {
   return FromCharsImpl(first, last, value, fmt);
 }
diff --git a/absl/strings/charconv.h b/absl/strings/charconv.h
index be25090..e5733f8 100644
--- a/absl/strings/charconv.h
+++ b/absl/strings/charconv.h
@@ -45,7 +45,7 @@
 // characters that were successfully parsed.  If none was found, `ptr` is set
 // to the `first` argument to from_chars.
 struct from_chars_result {
-  absl::Nonnull<const char*> ptr;
+  const char* absl_nonnull ptr;
   std::errc ec;
 };
 
@@ -77,13 +77,13 @@
 // format that strtod() accepts, except that a "0x" prefix is NOT matched.
 // (In particular, in `hex` mode, the input "0xff" results in the largest
 // matching pattern "0".)
-absl::from_chars_result from_chars(absl::Nonnull<const char*> first,
-                                   absl::Nonnull<const char*> last,
+absl::from_chars_result from_chars(const char* absl_nonnull first,
+                                   const char* absl_nonnull last,
                                    double& value,  // NOLINT
                                    chars_format fmt = chars_format::general);
 
-absl::from_chars_result from_chars(absl::Nonnull<const char*> first,
-                                   absl::Nonnull<const char*> last,
+absl::from_chars_result from_chars(const char* absl_nonnull first,
+                                   const char* absl_nonnull last,
                                    float& value,  // NOLINT
                                    chars_format fmt = chars_format::general);
 
diff --git a/absl/strings/charconv_benchmark.cc b/absl/strings/charconv_benchmark.cc
index e8c7371..0ee9363 100644
--- a/absl/strings/charconv_benchmark.cc
+++ b/absl/strings/charconv_benchmark.cc
@@ -12,12 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/charconv.h"
-
 #include <cstdlib>
 #include <cstring>
 #include <string>
 
+#include "absl/strings/charconv.h"
 #include "benchmark/benchmark.h"
 
 namespace {
diff --git a/absl/strings/charset.h b/absl/strings/charset.h
index ff4e81a..04ad459 100644
--- a/absl/strings/charset.h
+++ b/absl/strings/charset.h
@@ -46,15 +46,13 @@
 #ifndef ABSL_STRINGS_CHARSET_H_
 #define ABSL_STRINGS_CHARSET_H_
 
-#include <cstddef>
 #include <cstdint>
-#include <cstring>
 
-#include "absl/base/macros.h"
-#include "absl/base/port.h"
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 class CharSet {
  public:
@@ -159,6 +157,7 @@
   uint64_t m_[4];
 };
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_CHARSET_H_
diff --git a/absl/strings/charset_benchmark.cc b/absl/strings/charset_benchmark.cc
index bf7ae56..7133985 100644
--- a/absl/strings/charset_benchmark.cc
+++ b/absl/strings/charset_benchmark.cc
@@ -14,9 +14,9 @@
 
 #include <cstdint>
 
-#include "benchmark/benchmark.h"
 #include "absl/log/check.h"
 #include "absl/strings/charset.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index f0f4f31..e53f914 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -75,21 +75,19 @@
 using ::absl::cord_internal::kInlinedVectorSize;
 using ::absl::cord_internal::kMaxBytesToCopy;
 
-static void DumpNode(absl::Nonnull<CordRep*> nonnull_rep, bool include_data,
-                     absl::Nonnull<std::ostream*> os, int indent = 0);
-static bool VerifyNode(absl::Nonnull<CordRep*> root,
-                       absl::Nonnull<CordRep*> start_node);
+static void DumpNode(CordRep* absl_nonnull nonnull_rep, bool include_data,
+                     std::ostream* absl_nonnull os, int indent = 0);
+static bool VerifyNode(CordRep* absl_nonnull root,
+                       CordRep* absl_nonnull start_node);
 
-static inline absl::Nullable<CordRep*> VerifyTree(
-    absl::Nullable<CordRep*> node) {
+static inline CordRep* absl_nullable VerifyTree(CordRep* absl_nullable node) {
   assert(node == nullptr || VerifyNode(node, node));
   static_cast<void>(&VerifyNode);
   return node;
 }
 
-static absl::Nonnull<CordRepFlat*> CreateFlat(absl::Nonnull<const char*> data,
-                                              size_t length,
-                                              size_t alloc_hint) {
+static CordRepFlat* absl_nonnull CreateFlat(const char* absl_nonnull data,
+                                            size_t length, size_t alloc_hint) {
   CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);
   flat->length = length;
   memcpy(flat->Data(), data, length);
@@ -98,8 +96,8 @@
 
 // Creates a new flat or Btree out of the specified array.
 // The returned node has a refcount of 1.
-static absl::Nonnull<CordRep*> NewBtree(absl::Nonnull<const char*> data,
-                                        size_t length, size_t alloc_hint) {
+static CordRep* absl_nonnull NewBtree(const char* absl_nonnull data,
+                                      size_t length, size_t alloc_hint) {
   if (length <= kMaxFlatLength) {
     return CreateFlat(data, length, alloc_hint);
   }
@@ -112,8 +110,8 @@
 
 // Create a new tree out of the specified array.
 // The returned node has a refcount of 1.
-static absl::Nullable<CordRep*> NewTree(absl::Nullable<const char*> data,
-                                        size_t length, size_t alloc_hint) {
+static CordRep* absl_nullable NewTree(const char* absl_nullable data,
+                                      size_t length, size_t alloc_hint) {
   if (length == 0) return nullptr;
   return NewBtree(data, length, alloc_hint);
 }
@@ -121,7 +119,7 @@
 namespace cord_internal {
 
 void InitializeCordRepExternal(absl::string_view data,
-                               absl::Nonnull<CordRepExternal*> rep) {
+                               CordRepExternal* absl_nonnull rep) {
   assert(!data.empty());
   rep->length = data.size();
   rep->tag = EXTERNAL;
@@ -135,7 +133,7 @@
 // and not wasteful, we move the string into an external cord rep, preserving
 // the already allocated string contents.
 // Requires the provided string length to be larger than `kMaxInline`.
-static absl::Nonnull<CordRep*> CordRepFromString(std::string&& src) {
+static CordRep* absl_nonnull CordRepFromString(std::string&& src) {
   assert(src.length() > cord_internal::kMaxInline);
   if (
       // String is short: copy data to avoid external block overhead.
@@ -163,17 +161,12 @@
 // --------------------------------------------------------------------
 // Cord::InlineRep functions
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr unsigned char Cord::InlineRep::kMaxInline;
-#endif
-
-inline void Cord::InlineRep::set_data(absl::Nonnull<const char*> data,
-                                      size_t n) {
+inline void Cord::InlineRep::set_data(const char* absl_nonnull data, size_t n) {
   static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
   data_.set_inline_data(data, n);
 }
 
-inline absl::Nonnull<char*> Cord::InlineRep::set_data(size_t n) {
+inline char* absl_nonnull Cord::InlineRep::set_data(size_t n) {
   assert(n <= kMaxInline);
   ResetToEmpty();
   set_inline_size(n);
@@ -197,13 +190,13 @@
 
 // Returns `rep` converted into a CordRepBtree.
 // Directly returns `rep` if `rep` is already a CordRepBtree.
-static absl::Nonnull<CordRepBtree*> ForceBtree(CordRep* rep) {
+static CordRepBtree* absl_nonnull ForceBtree(CordRep* rep) {
   return rep->IsBtree()
              ? rep->btree()
              : CordRepBtree::Create(cord_internal::RemoveCrcNode(rep));
 }
 
-void Cord::InlineRep::AppendTreeToInlined(absl::Nonnull<CordRep*> tree,
+void Cord::InlineRep::AppendTreeToInlined(CordRep* absl_nonnull tree,
                                           MethodIdentifier method) {
   assert(!is_tree());
   if (!data_.is_empty()) {
@@ -213,7 +206,7 @@
   EmplaceTree(tree, method);
 }
 
-void Cord::InlineRep::AppendTreeToTree(absl::Nonnull<CordRep*> tree,
+void Cord::InlineRep::AppendTreeToTree(CordRep* absl_nonnull tree,
                                        MethodIdentifier method) {
   assert(is_tree());
   const CordzUpdateScope scope(data_.cordz_info(), method);
@@ -221,7 +214,7 @@
   SetTree(tree, scope);
 }
 
-void Cord::InlineRep::AppendTree(absl::Nonnull<CordRep*> tree,
+void Cord::InlineRep::AppendTree(CordRep* absl_nonnull tree,
                                  MethodIdentifier method) {
   assert(tree != nullptr);
   assert(tree->length != 0);
@@ -233,7 +226,7 @@
   }
 }
 
-void Cord::InlineRep::PrependTreeToInlined(absl::Nonnull<CordRep*> tree,
+void Cord::InlineRep::PrependTreeToInlined(CordRep* absl_nonnull tree,
                                            MethodIdentifier method) {
   assert(!is_tree());
   if (!data_.is_empty()) {
@@ -243,7 +236,7 @@
   EmplaceTree(tree, method);
 }
 
-void Cord::InlineRep::PrependTreeToTree(absl::Nonnull<CordRep*> tree,
+void Cord::InlineRep::PrependTreeToTree(CordRep* absl_nonnull tree,
                                         MethodIdentifier method) {
   assert(is_tree());
   const CordzUpdateScope scope(data_.cordz_info(), method);
@@ -251,7 +244,7 @@
   SetTree(tree, scope);
 }
 
-void Cord::InlineRep::PrependTree(absl::Nonnull<CordRep*> tree,
+void Cord::InlineRep::PrependTree(CordRep* absl_nonnull tree,
                                   MethodIdentifier method) {
   assert(tree != nullptr);
   assert(tree->length != 0);
@@ -267,9 +260,10 @@
 // suitable leaf is found, the function will update the length field for all
 // nodes to account for the size increase. The append region address will be
 // written to region and the actual size increase will be written to size.
-static inline bool PrepareAppendRegion(
-    absl::Nonnull<CordRep*> root, absl::Nonnull<absl::Nullable<char*>*> region,
-    absl::Nonnull<size_t*> size, size_t max_length) {
+static inline bool PrepareAppendRegion(CordRep* absl_nonnull root,
+                                       char* absl_nullable* absl_nonnull region,
+                                       size_t* absl_nonnull size,
+                                       size_t max_length) {
   if (root->IsBtree() && root->refcount.IsOne()) {
     Span<char> span = root->btree()->GetAppendBuffer(max_length);
     if (!span.empty()) {
@@ -472,11 +466,11 @@
   CommitTree(root, rep, scope, method);
 }
 
-inline absl::Nonnull<CordRep*> Cord::TakeRep() const& {
+inline CordRep* absl_nonnull Cord::TakeRep() const& {
   return CordRep::Ref(contents_.tree());
 }
 
-inline absl::Nonnull<CordRep*> Cord::TakeRep() && {
+inline CordRep* absl_nonnull Cord::TakeRep() && {
   CordRep* rep = contents_.tree();
   contents_.clear();
   return rep;
@@ -534,7 +528,7 @@
   contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord);
 }
 
-static CordRep::ExtractResult ExtractAppendBuffer(absl::Nonnull<CordRep*> rep,
+static CordRep::ExtractResult ExtractAppendBuffer(CordRep* absl_nonnull rep,
                                                   size_t min_capacity) {
   switch (rep->tag) {
     case cord_internal::BTREE:
@@ -781,9 +775,9 @@
   return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0);
 }
 
-int CompareChunks(absl::Nonnull<absl::string_view*> lhs,
-                  absl::Nonnull<absl::string_view*> rhs,
-                  absl::Nonnull<size_t*> size_to_compare) {
+int CompareChunks(absl::string_view* absl_nonnull lhs,
+                  absl::string_view* absl_nonnull rhs,
+                  size_t* absl_nonnull size_to_compare) {
   size_t compared_size = std::min(lhs->size(), rhs->size());
   assert(*size_to_compare >= compared_size);
   *size_to_compare -= compared_size;
@@ -881,7 +875,7 @@
   SetCrcCordState(std::move(state));
 }
 
-absl::Nullable<const crc_internal::CrcCordState*> Cord::MaybeGetCrcCordState()
+const crc_internal::CrcCordState* absl_nullable Cord::MaybeGetCrcCordState()
     const {
   if (!contents_.is_tree() || !contents_.tree()->IsCrc()) {
     return nullptr;
@@ -899,8 +893,8 @@
 
 inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,
                                  size_t size_to_compare) const {
-  auto advance = [](absl::Nonnull<Cord::ChunkIterator*> it,
-                    absl::Nonnull<absl::string_view*> chunk) {
+  auto advance = [](Cord::ChunkIterator* absl_nonnull it,
+                    absl::string_view* absl_nonnull chunk) {
     if (!chunk->empty()) return true;
     ++*it;
     if (it->bytes_remaining_ == 0) return false;
@@ -930,8 +924,8 @@
 
 inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size,
                                  size_t size_to_compare) const {
-  auto advance = [](absl::Nonnull<Cord::ChunkIterator*> it,
-                    absl::Nonnull<absl::string_view*> chunk) {
+  auto advance = [](Cord::ChunkIterator* absl_nonnull it,
+                    absl::string_view* absl_nonnull chunk) {
     if (!chunk->empty()) return true;
     ++*it;
     if (it->bytes_remaining_ == 0) return false;
@@ -981,7 +975,9 @@
 
   size_t compared_size = std::min(lhs_chunk.size(), rhs_chunk.size());
   assert(size_to_compare >= compared_size);
-  int memcmp_res = ::memcmp(lhs_chunk.data(), rhs_chunk.data(), compared_size);
+  int memcmp_res = compared_size > 0 ? ::memcmp(lhs_chunk.data(),
+                                                rhs_chunk.data(), compared_size)
+                                     : 0;
   if (compared_size == size_to_compare || memcmp_res != 0) {
     return ComputeCompareResult<ResultType>(memcmp_res);
   }
@@ -1053,7 +1049,7 @@
   return s;
 }
 
-void CopyCordToString(const Cord& src, absl::Nonnull<std::string*> dst) {
+void CopyCordToString(const Cord& src, std::string* absl_nonnull dst) {
   if (!src.contents_.is_tree()) {
     src.contents_.CopyTo(dst);
   } else {
@@ -1062,7 +1058,7 @@
   }
 }
 
-void AppendCordToString(const Cord& src, absl::Nonnull<std::string*> dst) {
+void AppendCordToString(const Cord& src, std::string* absl_nonnull dst) {
   const size_t cur_dst_size = dst->size();
   const size_t new_dst_size = cur_dst_size + src.size();
   absl::strings_internal::STLStringResizeUninitializedAmortized(dst,
@@ -1071,10 +1067,10 @@
   src.CopyToArrayImpl(append_ptr);
 }
 
-void Cord::CopyToArraySlowPath(absl::Nonnull<char*> dst) const {
+void Cord::CopyToArraySlowPath(char* absl_nonnull dst) const {
   assert(contents_.is_tree());
   absl::string_view fragment;
-  if (GetFlatAux(contents_.tree(), &fragment)) {
+  if (GetFlatAux(contents_.tree(), &fragment) && !fragment.empty()) {
     memcpy(dst, fragment.data(), fragment.size());
     return;
   }
@@ -1397,8 +1393,8 @@
   return absl::string_view(new_buffer, total_size);
 }
 
-/* static */ bool Cord::GetFlatAux(absl::Nonnull<CordRep*> rep,
-                                   absl::Nonnull<absl::string_view*> fragment) {
+/* static */ bool Cord::GetFlatAux(CordRep* absl_nonnull rep,
+                                   absl::string_view* absl_nonnull fragment) {
   assert(rep != nullptr);
   if (rep->length == 0) {
     *fragment = absl::string_view();
@@ -1432,7 +1428,7 @@
 }
 
 /* static */ void Cord::ForEachChunkAux(
-    absl::Nonnull<absl::cord_internal::CordRep*> rep,
+    absl::cord_internal::CordRep* absl_nonnull rep,
     absl::FunctionRef<void(absl::string_view)> callback) {
   assert(rep != nullptr);
   if (rep->length == 0) return;
@@ -1457,8 +1453,8 @@
   }
 }
 
-static void DumpNode(absl::Nonnull<CordRep*> nonnull_rep, bool include_data,
-                     absl::Nonnull<std::ostream*> os, int indent) {
+static void DumpNode(CordRep* absl_nonnull nonnull_rep, bool include_data,
+                     std::ostream* absl_nonnull os, int indent) {
   CordRep* rep = nonnull_rep;
   const int kIndentStep = 1;
   for (;;) {
@@ -1504,17 +1500,17 @@
   }
 }
 
-static std::string ReportError(absl::Nonnull<CordRep*> root,
-                               absl::Nonnull<CordRep*> node) {
+static std::string ReportError(CordRep* absl_nonnull root,
+                               CordRep* absl_nonnull node) {
   std::ostringstream buf;
   buf << "Error at node " << node << " in:";
   DumpNode(root, true, &buf);
   return buf.str();
 }
 
-static bool VerifyNode(absl::Nonnull<CordRep*> root,
-                       absl::Nonnull<CordRep*> start_node) {
-  absl::InlinedVector<absl::Nonnull<CordRep*>, 2> worklist;
+static bool VerifyNode(CordRep* absl_nonnull root,
+                       CordRep* absl_nonnull start_node) {
+  absl::InlinedVector<CordRep* absl_nonnull, 2> worklist;
   worklist.push_back(start_node);
   do {
     CordRep* node = worklist.back();
diff --git a/absl/strings/cord.h b/absl/strings/cord.h
index 69aa8ef..7afa419 100644
--- a/absl/strings/cord.h
+++ b/absl/strings/cord.h
@@ -61,6 +61,7 @@
 #define ABSL_STRINGS_CORD_H_
 
 #include <algorithm>
+#include <cassert>
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
@@ -68,18 +69,17 @@
 #include <iterator>
 #include <string>
 #include <type_traits>
+#include <utility>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/endian.h"
-#include "absl/base/internal/per_thread_tls.h"
 #include "absl/base/macros.h"
 #include "absl/base/nullability.h"
 #include "absl/base/optimization.h"
-#include "absl/base/port.h"
-#include "absl/container/inlined_vector.h"
 #include "absl/crc/internal/crc_cord_state.h"
 #include "absl/functional/function_ref.h"
+#include "absl/hash/internal/weakly_mixed_integer.h"
 #include "absl/meta/type_traits.h"
 #include "absl/strings/cord_analysis.h"
 #include "absl/strings/cord_buffer.h"
@@ -88,12 +88,10 @@
 #include "absl/strings/internal/cord_rep_btree.h"
 #include "absl/strings/internal/cord_rep_btree_reader.h"
 #include "absl/strings/internal/cord_rep_crc.h"
-#include "absl/strings/internal/cordz_functions.h"
+#include "absl/strings/internal/cord_rep_flat.h"
 #include "absl/strings/internal/cordz_info.h"
-#include "absl/strings/internal/cordz_statistics.h"
 #include "absl/strings/internal/cordz_update_scope.h"
 #include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/strings/internal/resize_uninitialized.h"
 #include "absl/strings/internal/string_constant.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/compare.h"
@@ -105,8 +103,8 @@
 class CordTestPeer;
 template <typename Releaser>
 Cord MakeCordFromExternal(absl::string_view, Releaser&&);
-void CopyCordToString(const Cord& src, absl::Nonnull<std::string*> dst);
-void AppendCordToString(const Cord& src, absl::Nonnull<std::string*> dst);
+void CopyCordToString(const Cord& src, std::string* absl_nonnull dst);
+void AppendCordToString(const Cord& src, std::string* absl_nonnull dst);
 
 // Cord memory accounting modes
 enum class CordMemoryAccounting {
@@ -420,8 +418,7 @@
   // guarantee that pointers previously returned by `dst->data()` remain valid
   // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new
   // object, prefer to simply use the conversion operator to `std::string`.
-  friend void CopyCordToString(const Cord& src,
-                               absl::Nonnull<std::string*> dst);
+  friend void CopyCordToString(const Cord& src, std::string* absl_nonnull dst);
 
   // AppendCordToString()
   //
@@ -433,7 +430,7 @@
   // `dst->data()`. If `*dst` is a new object, prefer to simply use the
   // conversion operator to `std::string`.
   friend void AppendCordToString(const Cord& src,
-                                 absl::Nonnull<std::string*> dst);
+                                 std::string* absl_nonnull dst);
 
   class CharIterator;
 
@@ -470,7 +467,7 @@
     using iterator_category = std::input_iterator_tag;
     using value_type = absl::string_view;
     using difference_type = ptrdiff_t;
-    using pointer = absl::Nonnull<const value_type*>;
+    using pointer = const value_type* absl_nonnull;
     using reference = value_type;
 
     ChunkIterator() = default;
@@ -491,13 +488,13 @@
     using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader;
 
     // Constructs a `begin()` iterator from `tree`.
-    explicit ChunkIterator(absl::Nonnull<cord_internal::CordRep*> tree);
+    explicit ChunkIterator(cord_internal::CordRep* absl_nonnull tree);
 
     // Constructs a `begin()` iterator from `cord`.
-    explicit ChunkIterator(absl::Nonnull<const Cord*> cord);
+    explicit ChunkIterator(const Cord* absl_nonnull cord);
 
     // Initializes this instance from a tree. Invoked by constructors.
-    void InitTree(absl::Nonnull<cord_internal::CordRep*> tree);
+    void InitTree(cord_internal::CordRep* absl_nonnull tree);
 
     // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than
     // `current_chunk_.size()`.
@@ -515,7 +512,7 @@
     // The current leaf, or `nullptr` if the iterator points to short data.
     // If the current chunk is a substring node, current_leaf_ points to the
     // underlying flat or external node.
-    absl::Nullable<absl::cord_internal::CordRep*> current_leaf_ = nullptr;
+    absl::cord_internal::CordRep* absl_nullable current_leaf_ = nullptr;
     // The number of bytes left in the `Cord` over which we are iterating.
     size_t bytes_remaining_ = 0;
 
@@ -572,13 +569,13 @@
     using iterator = ChunkIterator;
     using const_iterator = ChunkIterator;
 
-    explicit ChunkRange(absl::Nonnull<const Cord*> cord) : cord_(cord) {}
+    explicit ChunkRange(const Cord* absl_nonnull cord) : cord_(cord) {}
 
     ChunkIterator begin() const;
     ChunkIterator end() const;
 
    private:
-    absl::Nonnull<const Cord*> cord_;
+    const Cord* absl_nonnull cord_;
   };
 
   // Cord::Chunks()
@@ -631,7 +628,7 @@
     using iterator_category = std::input_iterator_tag;
     using value_type = char;
     using difference_type = ptrdiff_t;
-    using pointer = absl::Nonnull<const char*>;
+    using pointer = const char* absl_nonnull;
     using reference = const char&;
 
     CharIterator() = default;
@@ -641,12 +638,11 @@
     bool operator==(const CharIterator& other) const;
     bool operator!=(const CharIterator& other) const;
     reference operator*() const;
-    pointer operator->() const;
 
     friend Cord;
 
    private:
-    explicit CharIterator(absl::Nonnull<const Cord*> cord)
+    explicit CharIterator(const Cord* absl_nonnull cord)
         : chunk_iterator_(cord) {}
 
     ChunkIterator chunk_iterator_;
@@ -658,14 +654,14 @@
   // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the
   // number of bytes within the Cord; otherwise, behavior is undefined. It is
   // valid to pass `char_end()` and `0`.
-  static Cord AdvanceAndRead(absl::Nonnull<CharIterator*> it, size_t n_bytes);
+  static Cord AdvanceAndRead(CharIterator* absl_nonnull it, size_t n_bytes);
 
   // Cord::Advance()
   //
   // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than
   // or equal to the number of bytes remaining within the Cord; otherwise,
   // behavior is undefined. It is valid to pass `char_end()` and `0`.
-  static void Advance(absl::Nonnull<CharIterator*> it, size_t n_bytes);
+  static void Advance(CharIterator* absl_nonnull it, size_t n_bytes);
 
   // Cord::ChunkRemaining()
   //
@@ -674,6 +670,13 @@
   // `it` must be dereferenceable.
   static absl::string_view ChunkRemaining(const CharIterator& it);
 
+  // Cord::Distance()
+  //
+  // Returns the distance between `first` and `last`, as if
+  // `std::distance(first, last)` was called.
+  static ptrdiff_t Distance(const CharIterator& first,
+                            const CharIterator& last);
+
   // Cord::char_begin()
   //
   // Returns an iterator to the first character of the `Cord`.
@@ -714,13 +717,13 @@
     using iterator = CharIterator;
     using const_iterator = CharIterator;
 
-    explicit CharRange(absl::Nonnull<const Cord*> cord) : cord_(cord) {}
+    explicit CharRange(const Cord* absl_nonnull cord) : cord_(cord) {}
 
     CharIterator begin() const;
     CharIterator end() const;
 
    private:
-    absl::Nonnull<const Cord*> cord_;
+    const Cord* absl_nonnull cord_;
   };
 
   // Cord::Chars()
@@ -779,7 +782,7 @@
   CharIterator Find(const absl::Cord& needle) const;
 
   // Supports absl::Cord as a sink object for absl::Format().
-  friend void AbslFormatFlush(absl::Nonnull<absl::Cord*> cord,
+  friend void AbslFormatFlush(absl::Cord* absl_nonnull cord,
                               absl::string_view part) {
     cord->Append(part);
   }
@@ -882,7 +885,7 @@
   }
 #endif
 
-  friend absl::Nullable<const CordzInfo*> GetCordzInfoForTesting(
+  friend const CordzInfo* absl_nullable GetCordzInfoForTesting(
       const Cord& cord);
 
   // Calls the provided function once for each cord chunk, in order.  Unlike
@@ -911,21 +914,21 @@
     InlineRep& operator=(InlineRep&& src) noexcept;
 
     explicit constexpr InlineRep(absl::string_view sv,
-                                 absl::Nullable<CordRep*> rep);
+                                 CordRep* absl_nullable rep);
 
-    void Swap(absl::Nonnull<InlineRep*> rhs);
+    void Swap(InlineRep* absl_nonnull rhs);
     size_t size() const;
     // Returns nullptr if holding pointer
-    absl::Nullable<const char*> data() const;
+    const char* absl_nullable data() const;
     // Discards pointer, if any
-    void set_data(absl::Nonnull<const char*> data, size_t n);
-    absl::Nonnull<char*> set_data(size_t n);  // Write data to the result
+    void set_data(const char* absl_nonnull data, size_t n);
+    char* absl_nonnull set_data(size_t n);  // Write data to the result
     // Returns nullptr if holding bytes
-    absl::Nullable<absl::cord_internal::CordRep*> tree() const;
-    absl::Nonnull<absl::cord_internal::CordRep*> as_tree() const;
-    absl::Nonnull<const char*> as_chars() const;
+    absl::cord_internal::CordRep* absl_nullable tree() const;
+    absl::cord_internal::CordRep* absl_nonnull as_tree() const;
+    const char* absl_nonnull as_chars() const;
     // Returns non-null iff was holding a pointer
-    absl::Nullable<absl::cord_internal::CordRep*> clear();
+    absl::cord_internal::CordRep* absl_nullable clear();
     // Converts to pointer if necessary.
     void reduce_size(size_t n);    // REQUIRES: holding data
     void remove_prefix(size_t n);  // REQUIRES: holding data
@@ -934,64 +937,56 @@
 
     // Creates a CordRepFlat instance from the current inlined data with `extra'
     // bytes of desired additional capacity.
-    absl::Nonnull<CordRepFlat*> MakeFlatWithExtraCapacity(size_t extra);
+    CordRepFlat* absl_nonnull MakeFlatWithExtraCapacity(size_t extra);
 
     // Sets the tree value for this instance. `rep` must not be null.
     // Requires the current instance to hold a tree, and a lock to be held on
     // any CordzInfo referenced by this instance. The latter is enforced through
     // the CordzUpdateScope argument. If the current instance is sampled, then
     // the CordzInfo instance is updated to reference the new `rep` value.
-    void SetTree(absl::Nonnull<CordRep*> rep, const CordzUpdateScope& scope);
+    void SetTree(CordRep* absl_nonnull rep, const CordzUpdateScope& scope);
 
     // Identical to SetTree(), except that `rep` is allowed to be null, in
     // which case the current instance is reset to an empty value.
-    void SetTreeOrEmpty(absl::Nullable<CordRep*> rep,
+    void SetTreeOrEmpty(CordRep* absl_nullable rep,
                         const CordzUpdateScope& scope);
 
     // Sets the tree value for this instance, and randomly samples this cord.
     // This function disregards existing contents in `data_`, and should be
     // called when a Cord is 'promoted' from an 'uninitialized' or 'inlined'
     // value to a non-inlined (tree / ring) value.
-    void EmplaceTree(absl::Nonnull<CordRep*> rep, MethodIdentifier method);
+    void EmplaceTree(CordRep* absl_nonnull rep, MethodIdentifier method);
 
     // Identical to EmplaceTree, except that it copies the parent stack from
     // the provided `parent` data if the parent is sampled.
-    void EmplaceTree(absl::Nonnull<CordRep*> rep, const InlineData& parent,
+    void EmplaceTree(CordRep* absl_nonnull rep, const InlineData& parent,
                      MethodIdentifier method);
 
     // Commits the change of a newly created, or updated `rep` root value into
     // this cord. `old_rep` indicates the old (inlined or tree) value of the
     // cord, and determines if the commit invokes SetTree() or EmplaceTree().
-    void CommitTree(absl::Nullable<const CordRep*> old_rep,
-                    absl::Nonnull<CordRep*> rep, const CordzUpdateScope& scope,
+    void CommitTree(const CordRep* absl_nullable old_rep,
+                    CordRep* absl_nonnull rep, const CordzUpdateScope& scope,
                     MethodIdentifier method);
 
-    void AppendTreeToInlined(absl::Nonnull<CordRep*> tree,
+    void AppendTreeToInlined(CordRep* absl_nonnull tree,
                              MethodIdentifier method);
-    void AppendTreeToTree(absl::Nonnull<CordRep*> tree,
-                          MethodIdentifier method);
-    void AppendTree(absl::Nonnull<CordRep*> tree, MethodIdentifier method);
-    void PrependTreeToInlined(absl::Nonnull<CordRep*> tree,
+    void AppendTreeToTree(CordRep* absl_nonnull tree, MethodIdentifier method);
+    void AppendTree(CordRep* absl_nonnull tree, MethodIdentifier method);
+    void PrependTreeToInlined(CordRep* absl_nonnull tree,
                               MethodIdentifier method);
-    void PrependTreeToTree(absl::Nonnull<CordRep*> tree,
-                           MethodIdentifier method);
-    void PrependTree(absl::Nonnull<CordRep*> tree, MethodIdentifier method);
+    void PrependTreeToTree(CordRep* absl_nonnull tree, MethodIdentifier method);
+    void PrependTree(CordRep* absl_nonnull tree, MethodIdentifier method);
 
     bool IsSame(const InlineRep& other) const { return data_ == other.data_; }
 
-    void CopyTo(absl::Nonnull<std::string*> dst) const {
-      // memcpy is much faster when operating on a known size. On most supported
-      // platforms, the small string optimization is large enough that resizing
-      // to 15 bytes does not cause a memory allocation.
-      absl::strings_internal::STLStringResizeUninitialized(dst, kMaxInline);
-      data_.copy_max_inline_to(&(*dst)[0]);
-      // erase is faster than resize because the logic for memory allocation is
-      // not needed.
-      dst->erase(inline_size());
+    // Copies the inline contents into `dst`. Assumes the cord is not empty.
+    void CopyTo(std::string* absl_nonnull dst) const {
+      data_.CopyInlineToString(dst);
     }
 
     // Copies the inline contents into `dst`. Assumes the cord is not empty.
-    void CopyToArray(absl::Nonnull<char*> dst) const;
+    void CopyToArray(char* absl_nonnull dst) const;
 
     bool is_tree() const { return data_.is_tree(); }
 
@@ -1004,12 +999,12 @@
     }
 
     // Returns the profiled CordzInfo, or nullptr if not sampled.
-    absl::Nullable<absl::cord_internal::CordzInfo*> cordz_info() const {
+    absl::cord_internal::CordzInfo* absl_nullable cordz_info() const {
       return data_.cordz_info();
     }
 
     // Sets the profiled CordzInfo.
-    void set_cordz_info(absl::Nonnull<cord_internal::CordzInfo*> cordz_info) {
+    void set_cordz_info(cord_internal::CordzInfo* absl_nonnull cordz_info) {
       assert(cordz_info != nullptr);
       data_.set_cordz_info(cordz_info);
     }
@@ -1041,19 +1036,19 @@
   InlineRep contents_;
 
   // Helper for GetFlat() and TryFlat().
-  static bool GetFlatAux(absl::Nonnull<absl::cord_internal::CordRep*> rep,
-                         absl::Nonnull<absl::string_view*> fragment);
+  static bool GetFlatAux(absl::cord_internal::CordRep* absl_nonnull rep,
+                         absl::string_view* absl_nonnull fragment);
 
   // Helper for ForEachChunk().
   static void ForEachChunkAux(
-      absl::Nonnull<absl::cord_internal::CordRep*> rep,
+      absl::cord_internal::CordRep* absl_nonnull rep,
       absl::FunctionRef<void(absl::string_view)> callback);
 
   // The destructor for non-empty Cords.
   void DestroyCordSlow();
 
   // Out-of-line implementation of slower parts of logic.
-  void CopyToArraySlowPath(absl::Nonnull<char*> dst) const;
+  void CopyToArraySlowPath(char* absl_nonnull dst) const;
   int CompareSlowPath(absl::string_view rhs, size_t compared_size,
                       size_t size_to_compare) const;
   int CompareSlowPath(const Cord& rhs, size_t compared_size,
@@ -1070,8 +1065,8 @@
 
   // Returns a new reference to contents_.tree(), or steals an existing
   // reference if called on an rvalue.
-  absl::Nonnull<absl::cord_internal::CordRep*> TakeRep() const&;
-  absl::Nonnull<absl::cord_internal::CordRep*> TakeRep() &&;
+  absl::cord_internal::CordRep* absl_nonnull TakeRep() const&;
+  absl::cord_internal::CordRep* absl_nonnull TakeRep() &&;
 
   // Helper for Append().
   template <typename C>
@@ -1103,17 +1098,17 @@
       hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(),
                                        chunk.size());
     });
-    return H::combine(combiner.finalize(std::move(hash_state)), size());
+    return H::combine(combiner.finalize(std::move(hash_state)),
+                      hash_internal::WeaklyMixedInteger{size()});
   }
 
   friend class CrcCord;
   void SetCrcCordState(crc_internal::CrcCordState state);
-  absl::Nullable<const crc_internal::CrcCordState*> MaybeGetCrcCordState()
-      const;
+  const crc_internal::CrcCordState* absl_nullable MaybeGetCrcCordState() const;
 
   CharIterator FindImpl(CharIterator it, absl::string_view needle) const;
 
-  void CopyToArrayImpl(absl::Nonnull<char*> dst) const;
+  void CopyToArrayImpl(char* absl_nonnull dst) const;
 };
 
 ABSL_NAMESPACE_END
@@ -1133,14 +1128,14 @@
 // Does non-template-specific `CordRepExternal` initialization.
 // Requires `data` to be non-empty.
 void InitializeCordRepExternal(absl::string_view data,
-                               absl::Nonnull<CordRepExternal*> rep);
+                               CordRepExternal* absl_nonnull rep);
 
 // Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
 // to it. Requires `data` to be non-empty.
 template <typename Releaser>
 // NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
-absl::Nonnull<CordRep*> NewExternalRep(absl::string_view data,
-                                       Releaser&& releaser) {
+CordRep* absl_nonnull NewExternalRep(absl::string_view data,
+                                     Releaser&& releaser) {
   assert(!data.empty());
   using ReleaserType = absl::decay_t<Releaser>;
   CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
@@ -1152,7 +1147,7 @@
 // Overload for function reference types that dispatches using a function
 // pointer because there are no `alignof()` or `sizeof()` a function reference.
 // NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
-inline absl::Nonnull<CordRep*> NewExternalRep(
+inline CordRep* absl_nonnull NewExternalRep(
     absl::string_view data, void (&releaser)(absl::string_view)) {
   return NewExternalRep(data, &releaser);
 }
@@ -1176,7 +1171,7 @@
 }
 
 constexpr Cord::InlineRep::InlineRep(absl::string_view sv,
-                                     absl::Nullable<CordRep*> rep)
+                                     CordRep* absl_nullable rep)
     : data_(sv, rep) {}
 
 inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)
@@ -1215,7 +1210,7 @@
   return *this;
 }
 
-inline void Cord::InlineRep::Swap(absl::Nonnull<Cord::InlineRep*> rhs) {
+inline void Cord::InlineRep::Swap(Cord::InlineRep* absl_nonnull rhs) {
   if (rhs == this) {
     return;
   }
@@ -1223,22 +1218,22 @@
   swap(data_, rhs->data_);
 }
 
-inline absl::Nullable<const char*> Cord::InlineRep::data() const {
+inline const char* absl_nullable Cord::InlineRep::data() const {
   return is_tree() ? nullptr : data_.as_chars();
 }
 
-inline absl::Nonnull<const char*> Cord::InlineRep::as_chars() const {
+inline const char* absl_nonnull Cord::InlineRep::as_chars() const {
   assert(!data_.is_tree());
   return data_.as_chars();
 }
 
-inline absl::Nonnull<absl::cord_internal::CordRep*> Cord::InlineRep::as_tree()
+inline absl::cord_internal::CordRep* absl_nonnull Cord::InlineRep::as_tree()
     const {
   assert(data_.is_tree());
   return data_.as_tree();
 }
 
-inline absl::Nullable<absl::cord_internal::CordRep*> Cord::InlineRep::tree()
+inline absl::cord_internal::CordRep* absl_nullable Cord::InlineRep::tree()
     const {
   if (is_tree()) {
     return as_tree();
@@ -1251,7 +1246,7 @@
   return is_tree() ? as_tree()->length : inline_size();
 }
 
-inline absl::Nonnull<cord_internal::CordRepFlat*>
+inline cord_internal::CordRepFlat* absl_nonnull
 Cord::InlineRep::MakeFlatWithExtraCapacity(size_t extra) {
   static_assert(cord_internal::kMinFlatLength >= sizeof(data_), "");
   size_t len = data_.inline_size();
@@ -1261,21 +1256,21 @@
   return result;
 }
 
-inline void Cord::InlineRep::EmplaceTree(absl::Nonnull<CordRep*> rep,
+inline void Cord::InlineRep::EmplaceTree(CordRep* absl_nonnull rep,
                                          MethodIdentifier method) {
   assert(rep);
   data_.make_tree(rep);
   CordzInfo::MaybeTrackCord(data_, method);
 }
 
-inline void Cord::InlineRep::EmplaceTree(absl::Nonnull<CordRep*> rep,
+inline void Cord::InlineRep::EmplaceTree(CordRep* absl_nonnull rep,
                                          const InlineData& parent,
                                          MethodIdentifier method) {
   data_.make_tree(rep);
   CordzInfo::MaybeTrackCord(data_, parent, method);
 }
 
-inline void Cord::InlineRep::SetTree(absl::Nonnull<CordRep*> rep,
+inline void Cord::InlineRep::SetTree(CordRep* absl_nonnull rep,
                                      const CordzUpdateScope& scope) {
   assert(rep);
   assert(data_.is_tree());
@@ -1283,7 +1278,7 @@
   scope.SetCordRep(rep);
 }
 
-inline void Cord::InlineRep::SetTreeOrEmpty(absl::Nullable<CordRep*> rep,
+inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* absl_nullable rep,
                                             const CordzUpdateScope& scope) {
   assert(data_.is_tree());
   if (rep) {
@@ -1294,8 +1289,8 @@
   scope.SetCordRep(rep);
 }
 
-inline void Cord::InlineRep::CommitTree(absl::Nullable<const CordRep*> old_rep,
-                                        absl::Nonnull<CordRep*> rep,
+inline void Cord::InlineRep::CommitTree(const CordRep* absl_nullable old_rep,
+                                        CordRep* absl_nonnull rep,
                                         const CordzUpdateScope& scope,
                                         MethodIdentifier method) {
   if (old_rep) {
@@ -1305,7 +1300,7 @@
   }
 }
 
-inline absl::Nullable<absl::cord_internal::CordRep*> Cord::InlineRep::clear() {
+inline absl::cord_internal::CordRep* absl_nullable Cord::InlineRep::clear() {
   if (is_tree()) {
     CordzInfo::MaybeUntrackCord(cordz_info());
   }
@@ -1314,7 +1309,7 @@
   return result;
 }
 
-inline void Cord::InlineRep::CopyToArray(absl::Nonnull<char*> dst) const {
+inline void Cord::InlineRep::CopyToArray(char* absl_nonnull dst) const {
   assert(!is_tree());
   size_t n = inline_size();
   assert(n != 0);
@@ -1498,7 +1493,7 @@
   return EqualsImpl(rhs, rhs_size);
 }
 
-inline void Cord::CopyToArrayImpl(absl::Nonnull<char*> dst) const {
+inline void Cord::CopyToArrayImpl(char* absl_nonnull dst) const {
   if (!contents_.is_tree()) {
     if (!empty()) contents_.CopyToArray(dst);
   } else {
@@ -1507,7 +1502,7 @@
 }
 
 inline void Cord::ChunkIterator::InitTree(
-    absl::Nonnull<cord_internal::CordRep*> tree) {
+    cord_internal::CordRep* absl_nonnull tree) {
   tree = cord_internal::SkipCrcNode(tree);
   if (tree->tag == cord_internal::BTREE) {
     current_chunk_ = btree_reader_.Init(tree->btree());
@@ -1518,12 +1513,12 @@
 }
 
 inline Cord::ChunkIterator::ChunkIterator(
-    absl::Nonnull<cord_internal::CordRep*> tree) {
+    cord_internal::CordRep* absl_nonnull tree) {
   bytes_remaining_ = tree->length;
   InitTree(tree);
 }
 
-inline Cord::ChunkIterator::ChunkIterator(absl::Nonnull<const Cord*> cord) {
+inline Cord::ChunkIterator::ChunkIterator(const Cord* absl_nonnull cord) {
   if (CordRep* tree = cord->contents_.tree()) {
     bytes_remaining_ = tree->length;
     if (ABSL_PREDICT_TRUE(bytes_remaining_ != 0)) {
@@ -1659,17 +1654,13 @@
   return *chunk_iterator_->data();
 }
 
-inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const {
-  return chunk_iterator_->data();
-}
-
-inline Cord Cord::AdvanceAndRead(absl::Nonnull<CharIterator*> it,
+inline Cord Cord::AdvanceAndRead(CharIterator* absl_nonnull it,
                                  size_t n_bytes) {
   assert(it != nullptr);
   return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);
 }
 
-inline void Cord::Advance(absl::Nonnull<CharIterator*> it, size_t n_bytes) {
+inline void Cord::Advance(CharIterator* absl_nonnull it, size_t n_bytes) {
   assert(it != nullptr);
   it->chunk_iterator_.AdvanceBytes(n_bytes);
 }
@@ -1678,6 +1669,12 @@
   return *it.chunk_iterator_;
 }
 
+inline ptrdiff_t Cord::Distance(const CharIterator& first,
+                                const CharIterator& last) {
+  return static_cast<ptrdiff_t>(first.chunk_iterator_.bytes_remaining_ -
+                                last.chunk_iterator_.bytes_remaining_);
+}
+
 inline Cord::CharIterator Cord::char_begin() const {
   return CharIterator(this);
 }
diff --git a/absl/strings/cord_analysis.cc b/absl/strings/cord_analysis.cc
index 19b0fa4..dcbc826 100644
--- a/absl/strings/cord_analysis.cc
+++ b/absl/strings/cord_analysis.cc
@@ -39,15 +39,15 @@
 template <Mode mode>
 struct CordRepRef {
   // Instantiates a CordRepRef instance.
-  explicit CordRepRef(absl::Nonnull<const CordRep*> r) : rep(r) {}
+  explicit CordRepRef(const CordRep* absl_nonnull r) : rep(r) {}
 
   // Creates a child reference holding the provided child.
   // Overloaded to add cumulative reference count for kFairShare.
-  CordRepRef Child(absl::Nonnull<const CordRep*> child) const {
+  CordRepRef Child(const CordRep* absl_nonnull child) const {
     return CordRepRef(child);
   }
 
-  absl::Nonnull<const CordRep*> rep;
+  const CordRep* absl_nonnull rep;
 };
 
 // RawUsage holds the computed total number of bytes.
@@ -66,7 +66,7 @@
 struct RawUsage<Mode::kTotalMorePrecise> {
   size_t total = 0;
   // TODO(b/289250880): Replace this with a flat_hash_set.
-  std::unordered_set<absl::Nonnull<const CordRep*>> counted;
+  std::unordered_set<const CordRep* absl_nonnull> counted;
 
   void Add(size_t size, CordRepRef<Mode::kTotalMorePrecise> repref) {
     if (counted.insert(repref.rep).second) {
@@ -90,15 +90,15 @@
 template <>
 struct CordRepRef<Mode::kFairShare> {
   // Creates a CordRepRef with the provided rep and top (parent) fraction.
-  explicit CordRepRef(absl::Nonnull<const CordRep*> r, double frac = 1.0)
+  explicit CordRepRef(const CordRep* absl_nonnull r, double frac = 1.0)
       : rep(r), fraction(MaybeDiv(frac, r->refcount.Get())) {}
 
   // Returns a CordRepRef with a fraction of `this->fraction / child.refcount`
-  CordRepRef Child(absl::Nonnull<const CordRep*> child) const {
+  CordRepRef Child(const CordRep* absl_nonnull child) const {
     return CordRepRef(child, fraction);
   }
 
-  absl::Nonnull<const CordRep*> rep;
+  const CordRep* absl_nonnull rep;
   double fraction;
 };
 
@@ -150,7 +150,7 @@
 }
 
 template <Mode mode>
-size_t GetEstimatedUsage(absl::Nonnull<const CordRep*> rep) {
+size_t GetEstimatedUsage(const CordRep* absl_nonnull rep) {
   // Zero initialized memory usage totals.
   RawUsage<mode> raw_usage;
 
@@ -179,15 +179,15 @@
 
 }  // namespace
 
-size_t GetEstimatedMemoryUsage(absl::Nonnull<const CordRep*> rep) {
+size_t GetEstimatedMemoryUsage(const CordRep* absl_nonnull rep) {
   return GetEstimatedUsage<Mode::kTotal>(rep);
 }
 
-size_t GetEstimatedFairShareMemoryUsage(absl::Nonnull<const CordRep*> rep) {
+size_t GetEstimatedFairShareMemoryUsage(const CordRep* absl_nonnull rep) {
   return GetEstimatedUsage<Mode::kFairShare>(rep);
 }
 
-size_t GetMorePreciseMemoryUsage(absl::Nonnull<const CordRep*> rep) {
+size_t GetMorePreciseMemoryUsage(const CordRep* absl_nonnull rep) {
   return GetEstimatedUsage<Mode::kTotalMorePrecise>(rep);
 }
 
diff --git a/absl/strings/cord_analysis.h b/absl/strings/cord_analysis.h
index f8ce348..db50f3a 100644
--- a/absl/strings/cord_analysis.h
+++ b/absl/strings/cord_analysis.h
@@ -29,7 +29,7 @@
 // Returns the *approximate* number of bytes held in full or in part by this
 // Cord (which may not remain the same between invocations). Cords that share
 // memory could each be "charged" independently for the same shared memory.
-size_t GetEstimatedMemoryUsage(absl::Nonnull<const CordRep*> rep);
+size_t GetEstimatedMemoryUsage(const CordRep* absl_nonnull rep);
 
 // Returns the *approximate* number of bytes held in full or in part by this
 // Cord for the distinct memory held by this cord. This is similar to
@@ -47,13 +47,13 @@
 //
 // This is more expensive than `GetEstimatedMemoryUsage()` as it requires
 // deduplicating all memory references.
-size_t GetMorePreciseMemoryUsage(absl::Nonnull<const CordRep*> rep);
+size_t GetMorePreciseMemoryUsage(const CordRep* absl_nonnull rep);
 
 // Returns the *approximate* number of bytes held in full or in part by this
 // CordRep weighted by the sharing ratio of that data. For example, if some data
 // edge is shared by 4 different Cords, then each cord is attribute 1/4th of
 // the total memory usage as a 'fair share' of the total memory usage.
-size_t GetEstimatedFairShareMemoryUsage(absl::Nonnull<const CordRep*> rep);
+size_t GetEstimatedFairShareMemoryUsage(const CordRep* absl_nonnull rep);
 
 }  // namespace cord_internal
 ABSL_NAMESPACE_END
diff --git a/absl/strings/cord_buffer.cc b/absl/strings/cord_buffer.cc
deleted file mode 100644
index fad6269..0000000
--- a/absl/strings/cord_buffer.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2022 The Abseil Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/strings/cord_buffer.h"
-
-#include <cstddef>
-
-#include "absl/base/config.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr size_t CordBuffer::kDefaultLimit;
-constexpr size_t CordBuffer::kCustomLimit;
-#endif
-
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc
index eaf6d71..55007bb 100644
--- a/absl/strings/cord_test.cc
+++ b/absl/strings/cord_test.cc
@@ -1309,6 +1309,7 @@
   absl::Cord c;
   c.Append(absl::Cord(std::string(100, 'x')));
   absl::Cord other_ref = c;  // Prevent inplace appends
+  EXPECT_THAT(other_ref, testing::Eq(c));
   MaybeHarden(c);
   c.Append(absl::Cord(std::string(200, 'y')));
   c.RemoveSuffix(200);
@@ -1665,6 +1666,7 @@
     auto releaser = [&invoked](absl::string_view) { invoked = true; };
     {
       auto c = absl::MakeCordFromExternal("", releaser);
+      EXPECT_THAT(c, testing::Eq(""));
       EXPECT_TRUE(invoked);
     }
   }
@@ -1679,6 +1681,7 @@
     auto releaser = [&invoked](absl::string_view) { invoked = true; };
     {
       auto c = absl::MakeCordFromExternal(large_dummy, releaser);
+      EXPECT_THAT(c, testing::Eq(large_dummy));
       EXPECT_FALSE(invoked);
     }
     EXPECT_TRUE(invoked);
@@ -2167,6 +2170,7 @@
   absl::Cord cord;
   for (char c : expected) {
     absl::Cord shared(cord);
+    EXPECT_THAT(cord, testing::Eq(shared));
     cord.Append(absl::string_view(&c, 1));
     MaybeHarden(cord);
   }
@@ -2514,6 +2518,10 @@
   absl::Cord::CharRange range = cord.Chars();
   EXPECT_EQ(range.begin() == range.end(), cord.empty());
   EXPECT_EQ(range.begin() != range.end(), !cord.empty());
+  EXPECT_EQ(absl::Cord::Distance(range.begin(), range.end()),
+            static_cast<ptrdiff_t>(cord.size()));
+  EXPECT_EQ(absl::Cord::Distance(range.end(), range.begin()),
+            -static_cast<ptrdiff_t>(cord.size()));
 
   size_t i = 0;
   absl::Cord::CharIterator pre_iter = cord.char_begin();
@@ -2530,8 +2538,6 @@
     EXPECT_EQ(*pre_iter, *post_iter);
     EXPECT_EQ(&*pre_iter, &*post_iter);
 
-    EXPECT_EQ(&*pre_iter, pre_iter.operator->());
-
     const char* character_address = &*pre_iter;
     absl::Cord::CharIterator copy = pre_iter;
     ++copy;
@@ -2546,19 +2552,29 @@
     absl::Cord::CharIterator advance_iter = range.begin();
     absl::Cord::Advance(&advance_iter, i);
     EXPECT_EQ(pre_iter, advance_iter);
+    EXPECT_EQ(absl::Cord::Distance(range.begin(), advance_iter),
+              static_cast<ptrdiff_t>(i));
 
     advance_iter = range.begin();
     EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, i), cord.Subcord(0, i));
     EXPECT_EQ(pre_iter, advance_iter);
+    EXPECT_EQ(absl::Cord::Distance(range.begin(), advance_iter),
+              static_cast<ptrdiff_t>(i));
 
     advance_iter = pre_iter;
     absl::Cord::Advance(&advance_iter, cord.size() - i);
     EXPECT_EQ(range.end(), advance_iter);
+    EXPECT_EQ(absl::Cord::Distance(range.begin(), advance_iter),
+              static_cast<ptrdiff_t>(cord.size()));
+    EXPECT_EQ(absl::Cord::Distance(advance_iter, range.end()), 0);
 
     advance_iter = pre_iter;
     EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, cord.size() - i),
               cord.Subcord(i, cord.size() - i));
     EXPECT_EQ(range.end(), advance_iter);
+    EXPECT_EQ(absl::Cord::Distance(range.begin(), advance_iter),
+              static_cast<ptrdiff_t>(cord.size()));
+    EXPECT_EQ(absl::Cord::Distance(advance_iter, range.end()), 0);
 
     ++i;
     ++pre_iter;
@@ -2640,16 +2656,25 @@
 
   MaybeHarden(cord);
 
+
   for (size_t chunk_size :
        {kChunkSize1, kChunkSize2, kChunkSize3, kChunkSize4}) {
     absl::Cord::CharIterator it = cord.char_begin();
+    size_t it_remaining = cord.size();
+    size_t it_advanced = 0;
     size_t offset = 0;
     while (offset < data.length()) {
+      EXPECT_EQ(absl::Cord::Distance(it, cord.char_end()), it_remaining);
+      EXPECT_EQ(absl::Cord::Distance(cord.char_begin(), it), it_advanced);
       const size_t n = std::min<size_t>(data.length() - offset, chunk_size);
       absl::Cord chunk = cord.AdvanceAndRead(&it, n);
       ASSERT_EQ(chunk.size(), n);
       ASSERT_EQ(chunk.Compare(data.substr(offset, n)), 0);
       offset += n;
+      it_remaining -= n;
+      it_advanced += n;
+      EXPECT_EQ(absl::Cord::Distance(it, cord.char_end()), it_remaining);
+      EXPECT_EQ(absl::Cord::Distance(cord.char_begin(), it), it_advanced);
     }
   }
 }
@@ -3278,6 +3303,26 @@
   EXPECT_EQ(absl::HashOf(c3), absl::HashOf(absl::string_view()));
 }
 
+// This must not be static to avoid aggressive optimizations.
+ABSL_ATTRIBUTE_WEAK
+size_t FalseReport(const absl::Cord& a, bool f);
+
+ABSL_ATTRIBUTE_NOINLINE
+size_t FalseReport(const absl::Cord& a, bool f) {
+  absl::Cord b;
+  const absl::Cord& ref = f ? b : a;
+  // Test that sanitizers report nothing here. Without
+  // InlineData::Rep::annotated_this() compiler can unconditionally load
+  // poisoned parts, assuming that local variable is fully accessible.
+  return ref.size();
+}
+
+TEST(CordSanitizerTest, SanitizesCordFalseReport) {
+  absl::Cord c;
+  for (int i = 0; i < 1000; ++i) c.Append("a");
+  FalseReport(c, false);
+}
+
 TEST(CrcCordTest, ChecksummedEmptyCordEstimateMemoryUsage) {
   absl::Cord cord;
   cord.SetExpectedChecksum(0);
diff --git a/absl/strings/cordz_test_helpers.h b/absl/strings/cordz_test_helpers.h
index 619f13c..66232db 100644
--- a/absl/strings/cordz_test_helpers.h
+++ b/absl/strings/cordz_test_helpers.h
@@ -34,16 +34,15 @@
 ABSL_NAMESPACE_BEGIN
 
 // Returns the CordzInfo for the cord, or nullptr if the cord is not sampled.
-inline absl::Nullable<const cord_internal::CordzInfo*> GetCordzInfoForTesting(
+inline const cord_internal::CordzInfo* GetCordzInfoForTesting(
     const Cord& cord) {
   if (!cord.contents_.is_tree()) return nullptr;
   return cord.contents_.cordz_info();
 }
 
 // Returns true if the provided cordz_info is in the list of sampled cords.
-inline bool CordzInfoIsListed(
-    absl::Nonnull<const cord_internal::CordzInfo*> cordz_info,
-    cord_internal::CordzSampleToken token = {}) {
+inline bool CordzInfoIsListed(const cord_internal::CordzInfo* cordz_info,
+                              cord_internal::CordzSampleToken token = {}) {
   for (const cord_internal::CordzInfo& info : token) {
     if (cordz_info == &info) return true;
   }
@@ -121,7 +120,7 @@
 
 // Wrapper struct managing a small CordRep `rep`
 struct TestCordRep {
-  absl::Nonnull<cord_internal::CordRepFlat*> rep;
+  cord_internal::CordRepFlat* rep;
 
   TestCordRep() {
     rep = cord_internal::CordRepFlat::New(100);
diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc
index 4ffef94..e551c66 100644
--- a/absl/strings/escaping.cc
+++ b/absl/strings/escaping.cc
@@ -15,6 +15,7 @@
 #include "absl/strings/escaping.h"
 
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -24,6 +25,7 @@
 #include <utility>
 
 #include "absl/base/config.h"
+#include "absl/base/internal/endian.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/unaligned_access.h"
 #include "absl/base/nullability.h"
@@ -57,7 +59,7 @@
 }
 
 inline bool IsSurrogate(char32_t c, absl::string_view src,
-                        absl::Nullable<std::string*> error) {
+                        std::string* absl_nullable error) {
   if (c >= 0xD800 && c <= 0xDFFF) {
     if (error) {
       *error = absl::StrCat("invalid surrogate character (0xD800-DFFF): \\",
@@ -74,49 +76,49 @@
 //
 //    Unescapes C escape sequences and is the reverse of CEscape().
 //
-//    If 'source' is valid, stores the unescaped string and its size in
-//    'dest' and 'dest_len' respectively, and returns true. Otherwise
-//    returns false and optionally stores the error description in
-//    'error'. Set 'error' to nullptr to disable error reporting.
+//    If `src` is valid, stores the unescaped string `dst`, and returns
+//    true. Otherwise returns false and optionally stores the error
+//    description in `error`. Set `error` to nullptr to disable error
+//    reporting.
 //
-//    'dest' should point to a buffer that is at least as big as 'source'.
-//    'source' and 'dest' may be the same.
-//
-//     NOTE: any changes to this function must also be reflected in the older
-//     UnescapeCEscapeSequences().
+//    `src` and `dst` may use the same underlying buffer.
 // ----------------------------------------------------------------------
-bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
-                       absl::Nonnull<char*> dest,
-                       absl::Nonnull<ptrdiff_t*> dest_len,
-                       absl::Nullable<std::string*> error) {
-  char* d = dest;
-  const char* p = source.data();
-  const char* end = p + source.size();
-  const char* last_byte = end - 1;
 
-  // Small optimization for case where source = dest and there's no escaping
-  while (p == d && p < end && *p != '\\') p++, d++;
+bool CUnescapeInternal(absl::string_view src, bool leave_nulls_escaped,
+                       std::string* absl_nonnull dst,
+                       std::string* absl_nullable error) {
+  strings_internal::STLStringResizeUninitialized(dst, src.size());
 
-  while (p < end) {
-    if (*p != '\\') {
-      *d++ = *p++;
+  absl::string_view::size_type p = 0;  // Current src position.
+  std::string::size_type d = 0;        // Current dst position.
+
+  // When unescaping in-place, skip any prefix that does not have escaping.
+  if (src.data() == dst->data()) {
+    while (p < src.size() && src[p] != '\\') p++, d++;
+  }
+
+  while (p < src.size()) {
+    if (src[p] != '\\') {
+      (*dst)[d++] = src[p++];
     } else {
-      if (++p > last_byte) {  // skip past the '\\'
-        if (error) *error = "String cannot end with \\";
+      if (++p >= src.size()) {  // skip past the '\\'
+        if (error != nullptr) {
+          *error = "String cannot end with \\";
+        }
         return false;
       }
-      switch (*p) {
-        case 'a':  *d++ = '\a';  break;
-        case 'b':  *d++ = '\b';  break;
-        case 'f':  *d++ = '\f';  break;
-        case 'n':  *d++ = '\n';  break;
-        case 'r':  *d++ = '\r';  break;
-        case 't':  *d++ = '\t';  break;
-        case 'v':  *d++ = '\v';  break;
-        case '\\': *d++ = '\\';  break;
-        case '?':  *d++ = '\?';  break;    // \?  Who knew?
-        case '\'': *d++ = '\'';  break;
-        case '"':  *d++ = '\"';  break;
+      switch (src[p]) {
+        case 'a':  (*dst)[d++] = '\a';  break;
+        case 'b':  (*dst)[d++] = '\b';  break;
+        case 'f':  (*dst)[d++] = '\f';  break;
+        case 'n':  (*dst)[d++] = '\n';  break;
+        case 'r':  (*dst)[d++] = '\r';  break;
+        case 't':  (*dst)[d++] = '\t';  break;
+        case 'v':  (*dst)[d++] = '\v';  break;
+        case '\\': (*dst)[d++] = '\\';  break;
+        case '?':  (*dst)[d++] = '\?';  break;
+        case '\'': (*dst)[d++] = '\'';  break;
+        case '"':  (*dst)[d++] = '\"';  break;
         case '0':
         case '1':
         case '2':
@@ -126,188 +128,170 @@
         case '6':
         case '7': {
           // octal digit: 1 to 3 digits
-          const char* octal_start = p;
-          unsigned int ch = static_cast<unsigned int>(*p - '0');  // digit 1
-          if (p < last_byte && is_octal_digit(p[1]))
-            ch = ch * 8 + static_cast<unsigned int>(*++p - '0');  // digit 2
-          if (p < last_byte && is_octal_digit(p[1]))
-            ch = ch * 8 + static_cast<unsigned int>(*++p - '0');  // digit 3
+          auto octal_start = p;
+          unsigned int ch = static_cast<unsigned int>(src[p] - '0');  // digit 1
+          if (p + 1 < src.size() && is_octal_digit(src[p + 1]))
+            ch = ch * 8 + static_cast<unsigned int>(src[++p] - '0');  // digit 2
+          if (p + 1 < src.size() && is_octal_digit(src[p + 1]))
+            ch = ch * 8 + static_cast<unsigned int>(src[++p] - '0');  // digit 3
           if (ch > 0xff) {
-            if (error) {
-              *error = "Value of \\" +
-                       std::string(octal_start,
-                                   static_cast<size_t>(p + 1 - octal_start)) +
-                       " exceeds 0xff";
+            if (error != nullptr) {
+              *error =
+                  "Value of \\" +
+                  std::string(src.substr(octal_start, p + 1 - octal_start)) +
+                  " exceeds 0xff";
             }
             return false;
           }
           if ((ch == 0) && leave_nulls_escaped) {
             // Copy the escape sequence for the null character
-            const size_t octal_size = static_cast<size_t>(p + 1 - octal_start);
-            *d++ = '\\';
-            memmove(d, octal_start, octal_size);
-            d += octal_size;
+            (*dst)[d++] = '\\';
+            while (octal_start <= p) {
+              (*dst)[d++] = src[octal_start++];
+            }
             break;
           }
-          *d++ = static_cast<char>(ch);
+          (*dst)[d++] = static_cast<char>(ch);
           break;
         }
         case 'x':
         case 'X': {
-          if (p >= last_byte) {
-            if (error) *error = "String cannot end with \\x";
+          if (p + 1 >= src.size()) {
+            if (error != nullptr) {
+              *error = "String cannot end with \\x";
+            }
             return false;
-          } else if (!absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
-            if (error) *error = "\\x cannot be followed by a non-hex digit";
+          } else if (!absl::ascii_isxdigit(
+              static_cast<unsigned char>(src[p + 1]))) {
+            if (error != nullptr) {
+              *error = "\\x cannot be followed by a non-hex digit";
+            }
             return false;
           }
           unsigned int ch = 0;
-          const char* hex_start = p;
-          while (p < last_byte &&
-                 absl::ascii_isxdigit(static_cast<unsigned char>(p[1])))
+          auto hex_start = p;
+          while (p + 1 < src.size() &&
+                 absl::ascii_isxdigit(static_cast<unsigned char>(src[p + 1]))) {
             // Arbitrarily many hex digits
-            ch = (ch << 4) + hex_digit_to_int(*++p);
+            ch = (ch << 4) + hex_digit_to_int(src[++p]);
+          }
           if (ch > 0xFF) {
-            if (error) {
+            if (error != nullptr) {
               *error = "Value of \\" +
-                       std::string(hex_start,
-                                   static_cast<size_t>(p + 1 - hex_start)) +
+                       std::string(src.substr(hex_start, p + 1 - hex_start)) +
                        " exceeds 0xff";
             }
             return false;
           }
           if ((ch == 0) && leave_nulls_escaped) {
             // Copy the escape sequence for the null character
-            const size_t hex_size = static_cast<size_t>(p + 1 - hex_start);
-            *d++ = '\\';
-            memmove(d, hex_start, hex_size);
-            d += hex_size;
+            (*dst)[d++] = '\\';
+            while (hex_start <= p) {
+              (*dst)[d++] = src[hex_start++];
+            }
             break;
           }
-          *d++ = static_cast<char>(ch);
+          (*dst)[d++] = static_cast<char>(ch);
           break;
         }
         case 'u': {
           // \uhhhh => convert 4 hex digits to UTF-8
           char32_t rune = 0;
-          const char* hex_start = p;
-          if (p + 4 >= end) {
-            if (error) {
-              *error = "\\u must be followed by 4 hex digits: \\" +
-                       std::string(hex_start,
-                                   static_cast<size_t>(p + 1 - hex_start));
+          auto hex_start = p;
+          if (p + 4 >= src.size()) {
+            if (error != nullptr) {
+              *error = "\\u must be followed by 4 hex digits";
             }
             return false;
           }
           for (int i = 0; i < 4; ++i) {
             // Look one char ahead.
-            if (absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
-              rune = (rune << 4) + hex_digit_to_int(*++p);  // Advance p.
+            if (absl::ascii_isxdigit(static_cast<unsigned char>(src[p + 1]))) {
+              rune = (rune << 4) + hex_digit_to_int(src[++p]);
             } else {
-              if (error) {
+              if (error != nullptr) {
                 *error = "\\u must be followed by 4 hex digits: \\" +
-                         std::string(hex_start,
-                                     static_cast<size_t>(p + 1 - hex_start));
+                         std::string(src.substr(hex_start, p + 1 - hex_start));
               }
               return false;
             }
           }
           if ((rune == 0) && leave_nulls_escaped) {
             // Copy the escape sequence for the null character
-            *d++ = '\\';
-            memmove(d, hex_start, 5);  // u0000
-            d += 5;
+            (*dst)[d++] = '\\';
+            while (hex_start <= p) {
+              (*dst)[d++] = src[hex_start++];
+            }
             break;
           }
-          if (IsSurrogate(rune, absl::string_view(hex_start, 5), error)) {
+          if (IsSurrogate(rune, src.substr(hex_start, 5), error)) {
             return false;
           }
-          d += strings_internal::EncodeUTF8Char(d, rune);
+          d += strings_internal::EncodeUTF8Char(dst->data() + d, rune);
           break;
         }
         case 'U': {
           // \Uhhhhhhhh => convert 8 hex digits to UTF-8
           char32_t rune = 0;
-          const char* hex_start = p;
-          if (p + 8 >= end) {
-            if (error) {
-              *error = "\\U must be followed by 8 hex digits: \\" +
-                       std::string(hex_start,
-                                   static_cast<size_t>(p + 1 - hex_start));
+          auto hex_start = p;
+          if (p + 8 >= src.size()) {
+            if (error != nullptr) {
+              *error = "\\U must be followed by 8 hex digits";
             }
             return false;
           }
           for (int i = 0; i < 8; ++i) {
             // Look one char ahead.
-            if (absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
+            if (absl::ascii_isxdigit(static_cast<unsigned char>(src[p + 1]))) {
               // Don't change rune until we're sure this
               // is within the Unicode limit, but do advance p.
-              uint32_t newrune = (rune << 4) + hex_digit_to_int(*++p);
+              uint32_t newrune = (rune << 4) + hex_digit_to_int(src[++p]);
               if (newrune > 0x10FFFF) {
-                if (error) {
-                  *error = "Value of \\" +
-                           std::string(hex_start,
-                                       static_cast<size_t>(p + 1 - hex_start)) +
-                           " exceeds Unicode limit (0x10FFFF)";
+                if (error != nullptr) {
+                  *error =
+                      "Value of \\" +
+                      std::string(src.substr(hex_start, p + 1 - hex_start)) +
+                      " exceeds Unicode limit (0x10FFFF)";
                 }
                 return false;
               } else {
                 rune = newrune;
               }
             } else {
-              if (error) {
+              if (error != nullptr) {
                 *error = "\\U must be followed by 8 hex digits: \\" +
-                         std::string(hex_start,
-                                     static_cast<size_t>(p + 1 - hex_start));
+                         std::string(src.substr(hex_start, p + 1 - hex_start));
               }
               return false;
             }
           }
           if ((rune == 0) && leave_nulls_escaped) {
             // Copy the escape sequence for the null character
-            *d++ = '\\';
-            memmove(d, hex_start, 9);  // U00000000
-            d += 9;
+            (*dst)[d++] = '\\';
+            // U00000000
+            while (hex_start <= p) {
+              (*dst)[d++] = src[hex_start++];
+            }
             break;
           }
-          if (IsSurrogate(rune, absl::string_view(hex_start, 9), error)) {
+          if (IsSurrogate(rune, src.substr(hex_start, 9), error)) {
             return false;
           }
-          d += strings_internal::EncodeUTF8Char(d, rune);
+          d += strings_internal::EncodeUTF8Char(dst->data() + d, rune);
           break;
         }
         default: {
-          if (error) *error = std::string("Unknown escape sequence: \\") + *p;
+          if (error != nullptr) {
+            *error = std::string("Unknown escape sequence: \\") + src[p];
+          }
           return false;
         }
       }
-      p++;                                 // read past letter we escaped
+      p++;  // Read past letter we escaped.
     }
   }
-  *dest_len = d - dest;
-  return true;
-}
 
-// ----------------------------------------------------------------------
-// CUnescapeInternal()
-//
-//    Same as above but uses a std::string for output. 'source' and 'dest'
-//    may be the same.
-// ----------------------------------------------------------------------
-bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
-                       absl::Nonnull<std::string*> dest,
-                       absl::Nullable<std::string*> error) {
-  strings_internal::STLStringResizeUninitialized(dest, source.size());
-
-  ptrdiff_t dest_size;
-  if (!CUnescapeInternal(source,
-                         leave_nulls_escaped,
-                         &(*dest)[0],
-                         &dest_size,
-                         error)) {
-    return false;
-  }
-  dest->erase(static_cast<size_t>(dest_size));
+  dst->erase(d);
   return true;
 }
 
@@ -368,7 +352,7 @@
 }
 
 /* clang-format off */
-constexpr unsigned char kCEscapedLen[256] = {
+constexpr std::array<unsigned char, 256> kCEscapedLen = {
     4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4,  // \t, \n, \r
     4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
     1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,  // ", '
@@ -388,6 +372,40 @@
 };
 /* clang-format on */
 
+constexpr uint32_t MakeCEscapedLittleEndianUint32(size_t c) {
+  size_t char_len = kCEscapedLen[c];
+  if (char_len == 1) {
+    return static_cast<uint32_t>(c);
+  }
+  if (char_len == 2) {
+    switch (c) {
+      case '\n':
+        return '\\' | (static_cast<uint32_t>('n') << 8);
+      case '\r':
+        return '\\' | (static_cast<uint32_t>('r') << 8);
+      case '\t':
+        return '\\' | (static_cast<uint32_t>('t') << 8);
+      case '\"':
+        return '\\' | (static_cast<uint32_t>('\"') << 8);
+      case '\'':
+        return '\\' | (static_cast<uint32_t>('\'') << 8);
+      case '\\':
+        return '\\' | (static_cast<uint32_t>('\\') << 8);
+    }
+  }
+  return static_cast<uint32_t>('\\' | (('0' + (c / 64)) << 8) |
+                               (('0' + ((c % 64) / 8)) << 16) |
+                               (('0' + (c % 8)) << 24));
+}
+
+template <size_t... indexes>
+inline constexpr std::array<uint32_t, sizeof...(indexes)>
+MakeCEscapedLittleEndianUint32Array(std::index_sequence<indexes...>) {
+  return {MakeCEscapedLittleEndianUint32(indexes)...};
+}
+constexpr std::array<uint32_t, 256> kCEscapedLittleEndianUint32Array =
+    MakeCEscapedLittleEndianUint32Array(std::make_index_sequence<256>());
+
 // Calculates the length of the C-style escaped version of 'src'.
 // Assumes that non-printable characters are escaped using octal sequences, and
 // that UTF-8 bytes are not handled specially.
@@ -414,67 +432,39 @@
 }
 
 void CEscapeAndAppendInternal(absl::string_view src,
-                              absl::Nonnull<std::string*> dest) {
+                              std::string* absl_nonnull dest) {
   size_t escaped_len = CEscapedLength(src);
   if (escaped_len == src.size()) {
     dest->append(src.data(), src.size());
     return;
   }
 
+  // We keep 3 slop bytes so that we can call `little_endian::Store32`
+  // invariably regardless of the length of the escaped character.
+  constexpr size_t slop_bytes = 3;
   size_t cur_dest_len = dest->size();
-  ABSL_INTERNAL_CHECK(
-      cur_dest_len <= std::numeric_limits<size_t>::max() - escaped_len,
-      "std::string size overflow");
-  strings_internal::STLStringResizeUninitialized(dest,
-                                                 cur_dest_len + escaped_len);
+  size_t new_dest_len = cur_dest_len + escaped_len + slop_bytes;
+  ABSL_INTERNAL_CHECK(new_dest_len > cur_dest_len, "std::string size overflow");
+  strings_internal::AppendUninitializedTraits<std::string>::Append(
+      dest, escaped_len + slop_bytes);
   char* append_ptr = &(*dest)[cur_dest_len];
 
   for (char c : src) {
-    size_t char_len = kCEscapedLen[static_cast<unsigned char>(c)];
-    if (char_len == 1) {
-      *append_ptr++ = c;
-    } else if (char_len == 2) {
-      switch (c) {
-        case '\n':
-          *append_ptr++ = '\\';
-          *append_ptr++ = 'n';
-          break;
-        case '\r':
-          *append_ptr++ = '\\';
-          *append_ptr++ = 'r';
-          break;
-        case '\t':
-          *append_ptr++ = '\\';
-          *append_ptr++ = 't';
-          break;
-        case '\"':
-          *append_ptr++ = '\\';
-          *append_ptr++ = '\"';
-          break;
-        case '\'':
-          *append_ptr++ = '\\';
-          *append_ptr++ = '\'';
-          break;
-        case '\\':
-          *append_ptr++ = '\\';
-          *append_ptr++ = '\\';
-          break;
-      }
-    } else {
-      *append_ptr++ = '\\';
-      *append_ptr++ = '0' + static_cast<unsigned char>(c) / 64;
-      *append_ptr++ = '0' + (static_cast<unsigned char>(c) % 64) / 8;
-      *append_ptr++ = '0' + static_cast<unsigned char>(c) % 8;
-    }
+    unsigned char uc = static_cast<unsigned char>(c);
+    size_t char_len = kCEscapedLen[uc];
+    uint32_t little_endian_uint32 = kCEscapedLittleEndianUint32Array[uc];
+    little_endian::Store32(append_ptr, little_endian_uint32);
+    append_ptr += char_len;
   }
+  dest->resize(new_dest_len - slop_bytes);
 }
 
 // Reverses the mapping in Base64EscapeInternal; see that method's
 // documentation for details of the mapping.
-bool Base64UnescapeInternal(absl::Nullable<const char*> src_param, size_t szsrc,
-                            absl::Nullable<char*> dest, size_t szdest,
-                            absl::Nonnull<const signed char*> unbase64,
-                            absl::Nonnull<size_t*> len) {
+bool Base64UnescapeInternal(const char* absl_nullable src_param, size_t szsrc,
+                            char* absl_nullable dest, size_t szdest,
+                            const std::array<signed char, 256>& unbase64,
+                            size_t* absl_nonnull len) {
   static const char kPad64Equals = '=';
   static const char kPad64Dot = '.';
 
@@ -738,7 +728,7 @@
 // where the value of "Base64[]" was replaced by one of k(WebSafe)Base64Chars
 // in the internal escaping.cc.
 /* clang-format off */
-constexpr signed char kUnBase64[] = {
+constexpr std::array<signed char, 256> kUnBase64 = {
     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
@@ -773,7 +763,7 @@
     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1
 };
 
-constexpr signed char kUnWebSafeBase64[] = {
+constexpr std::array<signed char, 256> kUnWebSafeBase64 = {
     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
@@ -810,9 +800,9 @@
 /* clang-format on */
 
 template <typename String>
-bool Base64UnescapeInternal(absl::Nullable<const char*> src, size_t slen,
-                            absl::Nonnull<String*> dest,
-                            absl::Nonnull<const signed char*> unbase64) {
+bool Base64UnescapeInternal(const char* absl_nullable src, size_t slen,
+                            String* absl_nonnull dest,
+                            const std::array<signed char, 256>& unbase64) {
   // Determine the size of the output string.  Base64 encodes every 3 bytes into
   // 4 characters.  Any leftover chars are added directly for good measure.
   const size_t dest_len = 3 * (slen / 4) + (slen % 4);
@@ -837,7 +827,7 @@
 }
 
 /* clang-format off */
-constexpr char kHexValueLenient[256] = {
+constexpr std::array<char, 256> kHexValueLenient = {
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -856,7 +846,7 @@
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 };
 
-constexpr signed char kHexValueStrict[256] = {
+constexpr std::array<signed char, 256> kHexValueStrict = {
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
@@ -880,7 +870,7 @@
 // or a string.  This works because we use the [] operator to access
 // individual characters at a time.
 template <typename T>
-void HexStringToBytesInternal(absl::Nullable<const char*> from, T to,
+void HexStringToBytesInternal(const char* absl_nullable from, T to,
                               size_t num) {
   for (size_t i = 0; i < num; i++) {
     to[i] = static_cast<char>(kHexValueLenient[from[i * 2] & 0xFF] << 4) +
@@ -891,7 +881,7 @@
 // This is a templated function so that T can be either a char* or a
 // std::string.
 template <typename T>
-void BytesToHexStringInternal(absl::Nullable<const unsigned char*> src, T dest,
+void BytesToHexStringInternal(const unsigned char* absl_nullable src, T dest,
                               size_t num) {
   auto dest_ptr = &dest[0];
   for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest_ptr += 2) {
@@ -907,8 +897,8 @@
 //
 // See CUnescapeInternal() for implementation details.
 // ----------------------------------------------------------------------
-bool CUnescape(absl::string_view source, absl::Nonnull<std::string*> dest,
-               absl::Nullable<std::string*> error) {
+bool CUnescape(absl::string_view source, std::string* absl_nonnull dest,
+               std::string* absl_nullable error) {
   return CUnescapeInternal(source, kUnescapeNulls, dest, error);
 }
 
@@ -930,23 +920,23 @@
   return CEscapeInternal(src, true, true);
 }
 
-bool Base64Unescape(absl::string_view src, absl::Nonnull<std::string*> dest) {
+bool Base64Unescape(absl::string_view src, std::string* absl_nonnull dest) {
   return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64);
 }
 
 bool WebSafeBase64Unescape(absl::string_view src,
-                           absl::Nonnull<std::string*> dest) {
+                           std::string* absl_nonnull dest) {
   return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64);
 }
 
-void Base64Escape(absl::string_view src, absl::Nonnull<std::string*> dest) {
+void Base64Escape(absl::string_view src, std::string* absl_nonnull dest) {
   strings_internal::Base64EscapeInternal(
       reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
       true, strings_internal::kBase64Chars);
 }
 
 void WebSafeBase64Escape(absl::string_view src,
-                         absl::Nonnull<std::string*> dest) {
+                         std::string* absl_nonnull dest) {
   strings_internal::Base64EscapeInternal(
       reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
       false, strings_internal::kWebSafeBase64Chars);
@@ -968,8 +958,7 @@
   return dest;
 }
 
-bool HexStringToBytes(absl::string_view hex,
-                      absl::Nonnull<std::string*> bytes) {
+bool HexStringToBytes(absl::string_view hex, std::string* absl_nonnull bytes) {
   std::string output;
 
   size_t num_bytes = hex.size() / 2;
diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h
index 3f34fbf..3aaf39c 100644
--- a/absl/strings/escaping.h
+++ b/absl/strings/escaping.h
@@ -71,12 +71,12 @@
 //     ...
 //   }
 //   EXPECT_EQ(unescaped_s, "foo\rbar\nbaz\t");
-bool CUnescape(absl::string_view source, absl::Nonnull<std::string*> dest,
-               absl::Nullable<std::string*> error);
+bool CUnescape(absl::string_view source, std::string* absl_nonnull dest,
+               std::string* absl_nullable error);
 
 // Overload of `CUnescape()` with no error reporting.
 inline bool CUnescape(absl::string_view source,
-                      absl::Nonnull<std::string*> dest) {
+                      std::string* absl_nonnull dest) {
   return CUnescape(source, dest, nullptr);
 }
 
@@ -126,7 +126,7 @@
 // Encodes a `src` string into a base64-encoded 'dest' string with padding
 // characters. This function conforms with RFC 4648 section 4 (base64) and RFC
 // 2045.
-void Base64Escape(absl::string_view src, absl::Nonnull<std::string*> dest);
+void Base64Escape(absl::string_view src, std::string* absl_nonnull dest);
 std::string Base64Escape(absl::string_view src);
 
 // WebSafeBase64Escape()
@@ -134,8 +134,7 @@
 // Encodes a `src` string into a base64 string, like Base64Escape() does, but
 // outputs '-' instead of '+' and '_' instead of '/', and does not pad 'dest'.
 // This function conforms with RFC 4648 section 5 (base64url).
-void WebSafeBase64Escape(absl::string_view src,
-                         absl::Nonnull<std::string*> dest);
+void WebSafeBase64Escape(absl::string_view src, std::string* absl_nonnull dest);
 std::string WebSafeBase64Escape(absl::string_view src);
 
 // Base64Unescape()
@@ -145,7 +144,7 @@
 // `src` contains invalid characters, `dest` is cleared and returns `false`.
 // If padding is included (note that `Base64Escape()` does produce it), it must
 // be correct. In the padding, '=' and '.' are treated identically.
-bool Base64Unescape(absl::string_view src, absl::Nonnull<std::string*> dest);
+bool Base64Unescape(absl::string_view src, std::string* absl_nonnull dest);
 
 // WebSafeBase64Unescape()
 //
@@ -155,7 +154,7 @@
 // included (note that `WebSafeBase64Escape()` does not produce it), it must be
 // correct. In the padding, '=' and '.' are treated identically.
 bool WebSafeBase64Unescape(absl::string_view src,
-                           absl::Nonnull<std::string*> dest);
+                           std::string* absl_nonnull dest);
 
 // HexStringToBytes()
 //
@@ -163,8 +162,8 @@
 // output string.  If `hex` does not consist of valid hexadecimal data, this
 // function returns false and leaves `bytes` in an unspecified state. Returns
 // true on success.
-ABSL_MUST_USE_RESULT bool HexStringToBytes(absl::string_view hex,
-                                           absl::Nonnull<std::string*> bytes);
+[[nodiscard]] bool HexStringToBytes(absl::string_view hex,
+                                    std::string* absl_nonnull bytes);
 
 // HexStringToBytes()
 //
diff --git a/absl/strings/escaping_benchmark.cc b/absl/strings/escaping_benchmark.cc
index f792226..32b8f6e 100644
--- a/absl/strings/escaping_benchmark.cc
+++ b/absl/strings/escaping_benchmark.cc
@@ -12,19 +12,17 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/escaping.h"
-
 #include <cstdint>
-#include <cstdio>
-#include <cstring>
 #include <memory>
 #include <random>
 #include <string>
 
-#include "benchmark/benchmark.h"
 #include "absl/base/internal/raw_logging.h"
+#include "absl/strings/escaping.h"
 #include "absl/strings/internal/escaping_test_common.h"
 #include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
@@ -33,9 +31,12 @@
   for (int i = 0; i < 50; i++) {
     src += "\\x55";
   }
-  std::string dest;
   for (auto _ : state) {
-    absl::CUnescape(src, &dest);
+    std::string dest;
+    benchmark::DoNotOptimize(src);
+    bool result = absl::CUnescape(src, &dest);
+    benchmark::DoNotOptimize(result);
+    benchmark::DoNotOptimize(dest);
   }
 }
 BENCHMARK(BM_CUnescapeHexString);
@@ -47,22 +48,45 @@
       raw += std::string(test_set.plaintext);
     }
   }
-
-  // The actual benchmark loop is tiny...
-  std::string escaped;
   for (auto _ : state) {
+    std::string escaped;
+    benchmark::DoNotOptimize(raw);
     absl::WebSafeBase64Escape(raw, &escaped);
+    benchmark::DoNotOptimize(escaped);
   }
-
-  // We want to be sure the compiler doesn't throw away the loop above,
-  // and the easiest way to ensure that is to round-trip the results and verify
-  // them.
-  std::string round_trip;
-  absl::WebSafeBase64Unescape(escaped, &round_trip);
-  ABSL_RAW_CHECK(round_trip == raw, "");
 }
 BENCHMARK(BM_WebSafeBase64Escape_string);
 
+void BM_HexStringToBytes(benchmark::State& state) {
+  const int size = state.range(0);
+  std::string input, output;
+  for (int i = 0; i < size; ++i) input += "1c";
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(input);
+    bool result = absl::HexStringToBytes(input, &output);
+    benchmark::DoNotOptimize(result);
+    benchmark::DoNotOptimize(output);
+  }
+}
+BENCHMARK(BM_HexStringToBytes)->Range(1, 1 << 8);
+
+void BM_HexStringToBytes_Fail(benchmark::State& state) {
+  std::string binary;
+  absl::string_view hex_input1 = "1c2f003";
+  absl::string_view hex_input2 = "1c2f0032f40123456789abcdef**";
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(hex_input1);
+    bool result1 = absl::HexStringToBytes(hex_input1, &binary);
+    benchmark::DoNotOptimize(result1);
+    benchmark::DoNotOptimize(binary);
+    benchmark::DoNotOptimize(hex_input2);
+    bool result2 = absl::HexStringToBytes(hex_input2, &binary);
+    benchmark::DoNotOptimize(result2);
+    benchmark::DoNotOptimize(binary);
+  }
+}
+BENCHMARK(BM_HexStringToBytes_Fail);
+
 // Used for the CEscape benchmarks
 const char kStringValueNoEscape[] = "1234567890";
 const char kStringValueSomeEscaped[] = "123\n56789\xA1";
@@ -76,7 +100,9 @@
   }
 
   for (auto _ : state) {
-    absl::CEscape(src);
+    benchmark::DoNotOptimize(src);
+    std::string result = absl::CEscape(src);
+    benchmark::DoNotOptimize(result);
   }
 }
 
diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc
index 25cb685..4786c88 100644
--- a/absl/strings/escaping_test.cc
+++ b/absl/strings/escaping_test.cc
@@ -169,15 +169,25 @@
     EXPECT_TRUE(absl::CUnescape(val.escaped, &out));
     EXPECT_EQ(out, val.unescaped);
   }
-  std::string bad[] = {"\\u1",         // too short
-                       "\\U1",         // too short
-                       "\\Uffffff",    // exceeds 0x10ffff (largest Unicode)
-                       "\\U00110000",  // exceeds 0x10ffff (largest Unicode)
-                       "\\uD835",      // surrogate character (D800-DFFF)
-                       "\\U0000DD04",  // surrogate character (D800-DFFF)
-                       "\\777",        // exceeds 0xff
-                       "\\xABCD"};     // exceeds 0xff
-  for (const std::string& e : bad) {
+  constexpr absl::string_view bad[] = {
+      "\\u1",         // too short
+      "\\U1",         // too short
+      "\\Uffffff",    // exceeds 0x10ffff (largest Unicode)
+      "\\U00110000",  // exceeds 0x10ffff (largest Unicode)
+      "\\uD835",      // surrogate character (D800-DFFF)
+      "\\U0000DD04",  // surrogate character (D800-DFFF)
+      "\\777",        // exceeds 0xff
+      "\\xABCD",      // exceeds 0xff
+      "endswith\\",   // ends with "\"
+      "endswith\\x",  // ends with "\x"
+      "endswith\\X",  // ends with "\X"
+      "\\x.2345678",  // non-hex follows "\x"
+      "\\X.2345678",  // non-hex follows "\X"
+      "\\u.2345678",  // non-hex follows "\U"
+      "\\U.2345678",  // non-hex follows "\U"
+      "\\.unknown",   // unknown escape sequence
+  };
+  for (const auto e : bad) {
     std::string error;
     std::string out;
     EXPECT_FALSE(absl::CUnescape(e, &out, &error));
diff --git a/absl/strings/internal/charconv_bigint.cc b/absl/strings/internal/charconv_bigint.cc
index 46b5289..9185f1f 100644
--- a/absl/strings/internal/charconv_bigint.cc
+++ b/absl/strings/internal/charconv_bigint.cc
@@ -279,7 +279,7 @@
     // Either way, [begin, decimal_point) will contain the set of dropped digits
     // that require an exponent adjustment.
     const char* decimal_point = std::find(begin, end, '.');
-    exponent_adjust += (decimal_point - begin);
+    exponent_adjust += static_cast<int>(decimal_point - begin);
   }
   return exponent_adjust;
 }
diff --git a/absl/strings/internal/charconv_bigint.h b/absl/strings/internal/charconv_bigint.h
index cb29767..2c7a336 100644
--- a/absl/strings/internal/charconv_bigint.h
+++ b/absl/strings/internal/charconv_bigint.h
@@ -17,7 +17,7 @@
 
 #include <algorithm>
 #include <cstdint>
-#include <iostream>
+#include <ostream>
 #include <string>
 
 #include "absl/base/config.h"
diff --git a/absl/strings/internal/charconv_bigint_test.cc b/absl/strings/internal/charconv_bigint_test.cc
index a8b9945..7bbf16d 100644
--- a/absl/strings/internal/charconv_bigint_test.cc
+++ b/absl/strings/internal/charconv_bigint_test.cc
@@ -176,7 +176,7 @@
 
 TEST(BigUnsigned, MultiplyByOverflow) {
   {
-    // Check that multiplcation overflow predictably truncates.
+    // Check that multiplication overflow predictably truncates.
 
     // A big int with all bits on.
     BigUnsigned<4> all_bits_on("340282366920938463463374607431768211455");
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h
index f0060f1..cf1f703 100644
--- a/absl/strings/internal/cord_internal.h
+++ b/absl/strings/internal/cord_internal.h
@@ -19,16 +19,17 @@
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
-#include <type_traits>
+#include <cstring>
+#include <string>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/endian.h"
-#include "absl/base/internal/invoke.h"
+#include "absl/base/macros.h"
+#include "absl/base/nullability.h"
 #include "absl/base/optimization.h"
 #include "absl/container/internal/compressed_tuple.h"
 #include "absl/container/internal/container_memory.h"
-#include "absl/meta/type_traits.h"
 #include "absl/strings/string_view.h"
 
 // We can only add poisoning if we can detect consteval executions.
@@ -356,16 +357,15 @@
 struct Rank0 {};
 struct Rank1 : Rank0 {};
 
-template <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
-                                 Releaser, absl::string_view>>
+template <typename Releaser,
+          typename = ::std::invoke_result_t<Releaser, absl::string_view>>
 void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view data) {
-  ::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
+  ::std::invoke(std::forward<Releaser>(releaser), data);
 }
 
-template <typename Releaser,
-          typename = ::absl::base_internal::invoke_result_t<Releaser>>
+template <typename Releaser, typename = ::std::invoke_result_t<Releaser>>
 void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view) {
-  ::absl::base_internal::invoke(std::forward<Releaser>(releaser));
+  ::std::invoke(std::forward<Releaser>(releaser));
 }
 
 // We use CompressedTuple so that we can benefit from EBCO.
@@ -635,6 +635,19 @@
     poison();
   }
 
+  void CopyInlineToString(std::string* dst) const {
+    assert(!is_tree());
+    // As Cord can store only 15 bytes it is smaller than std::string's
+    // small string optimization buffer size. Therefore we will always trigger
+    // the fast assign short path.
+    //
+    // Copying with a size equal to the maximum allows more efficient, wider
+    // stores to be used and no branching.
+    dst->assign(rep_.SanitizerSafeCopy().as_chars(), kMaxInline);
+    // After the copy we then change the size and put in a 0 byte.
+    dst->erase(inline_size());
+  }
+
   void copy_max_inline_to(char* dst) const {
     assert(!is_tree());
     memcpy(dst, rep_.SanitizerSafeCopy().as_chars(), kMaxInline);
@@ -713,35 +726,53 @@
                GetOrNull(chars, 13),
                GetOrNull(chars, 14)} {}
 
+#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
+    // Break compiler optimization for cases when value is allocated on the
+    // stack. Compiler assumes that the the variable is fully accessible
+    // regardless of our poisoning.
+    // Missing report: https://github.com/llvm/llvm-project/issues/100640
+    const Rep* self() const {
+      const Rep* volatile ptr = this;
+      return ptr;
+    }
+    Rep* self() {
+      Rep* volatile ptr = this;
+      return ptr;
+    }
+#else
+    constexpr const Rep* self() const { return this; }
+    constexpr Rep* self() { return this; }
+#endif
+
     // Disable sanitizer as we must always be able to read `tag`.
     ABSL_CORD_INTERNAL_NO_SANITIZE
     int8_t tag() const { return reinterpret_cast<const int8_t*>(this)[0]; }
-    void set_tag(int8_t rhs) { reinterpret_cast<int8_t*>(this)[0] = rhs; }
+    void set_tag(int8_t rhs) { reinterpret_cast<int8_t*>(self())[0] = rhs; }
 
-    char* as_chars() { return data + 1; }
-    const char* as_chars() const { return data + 1; }
+    char* as_chars() { return self()->data + 1; }
+    const char* as_chars() const { return self()->data + 1; }
 
-    bool is_tree() const { return (tag() & 1) != 0; }
+    bool is_tree() const { return (self()->tag() & 1) != 0; }
 
     size_t inline_size() const {
-      ABSL_ASSERT(!is_tree());
-      return static_cast<size_t>(tag()) >> 1;
+      ABSL_ASSERT(!self()->is_tree());
+      return static_cast<size_t>(self()->tag()) >> 1;
     }
 
     void set_inline_size(size_t size) {
       ABSL_ASSERT(size <= kMaxInline);
-      set_tag(static_cast<int8_t>(size << 1));
+      self()->set_tag(static_cast<int8_t>(size << 1));
     }
 
-    CordRep* tree() const { return as_tree.rep; }
-    void set_tree(CordRep* rhs) { as_tree.rep = rhs; }
+    CordRep* tree() const { return self()->as_tree.rep; }
+    void set_tree(CordRep* rhs) { self()->as_tree.rep = rhs; }
 
-    cordz_info_t cordz_info() const { return as_tree.cordz_info; }
-    void set_cordz_info(cordz_info_t rhs) { as_tree.cordz_info = rhs; }
+    cordz_info_t cordz_info() const { return self()->as_tree.cordz_info; }
+    void set_cordz_info(cordz_info_t rhs) { self()->as_tree.cordz_info = rhs; }
 
     void make_tree(CordRep* tree) {
-      as_tree.rep = tree;
-      as_tree.cordz_info = kNullCordzInfo;
+      self()->as_tree.rep = tree;
+      self()->as_tree.cordz_info = kNullCordzInfo;
     }
 
 #ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
diff --git a/absl/strings/internal/cord_rep_btree.cc b/absl/strings/internal/cord_rep_btree.cc
index 05bd0e2..33ea820 100644
--- a/absl/strings/internal/cord_rep_btree.cc
+++ b/absl/strings/internal/cord_rep_btree.cc
@@ -36,10 +36,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace cord_internal {
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr size_t CordRepBtree::kMaxCapacity;
-#endif
-
 namespace {
 
 using NodeStack = CordRepBtree * [CordRepBtree::kMaxDepth];
diff --git a/absl/strings/internal/cordz_info.cc b/absl/strings/internal/cordz_info.cc
index b7c7fed..4baaecd 100644
--- a/absl/strings/internal/cordz_info.cc
+++ b/absl/strings/internal/cordz_info.cc
@@ -34,10 +34,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace cord_internal {
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr size_t CordzInfo::kMaxStackDepth;
-#endif
-
 ABSL_CONST_INIT CordzInfo::List CordzInfo::global_list_{absl::kConstInit};
 
 namespace {
diff --git a/absl/strings/internal/cordz_info.h b/absl/strings/internal/cordz_info.h
index 2dc9d16..aa92a8f 100644
--- a/absl/strings/internal/cordz_info.h
+++ b/absl/strings/internal/cordz_info.h
@@ -291,10 +291,15 @@
 
 inline void CordzInfo::UnsafeSetCordRep(CordRep* rep) { rep_ = rep; }
 
+// Android local modification: locally silence an incorrect warning that
+// causes build failures in code that uses -Werror.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wthread-safety-negative"
 inline CordRep* CordzInfo::RefCordRep() const ABSL_LOCKS_EXCLUDED(mutex_) {
   MutexLock lock(&mutex_);
   return rep_ ? CordRep::Ref(rep_) : nullptr;
 }
+#pragma clang diagnostic pop
 
 }  // namespace cord_internal
 ABSL_NAMESPACE_END
diff --git a/absl/strings/internal/damerau_levenshtein_distance_benchmark.cc b/absl/strings/internal/damerau_levenshtein_distance_benchmark.cc
new file mode 100644
index 0000000..76d6db4
--- /dev/null
+++ b/absl/strings/internal/damerau_levenshtein_distance_benchmark.cc
@@ -0,0 +1,56 @@
+// Copyright 2022 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 <string>
+
+#include "absl/strings/internal/damerau_levenshtein_distance.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+std::string MakeTestString(int desired_length, int num_edits) {
+  std::string test(desired_length, 'x');
+  for (int i = 0; (i < num_edits) && (i * 8 < desired_length); ++i) {
+    test[i * 8] = 'y';
+  }
+  return test;
+}
+
+void BenchmarkArgs(benchmark::internal::Benchmark* benchmark) {
+  // Each column is 8 bytes.
+  const auto string_size = {1, 8, 64, 100};
+  const auto num_edits = {1, 2, 16, 16, 64, 80};
+  const auto distance_cap = {1, 2, 3, 16, 64, 80};
+  for (const int s : string_size) {
+    for (const int n : num_edits) {
+      for (const int d : distance_cap) {
+        if (n > s) continue;
+        benchmark->Args({s, n, d});
+      }
+    }
+  }
+}
+
+using absl::strings_internal::CappedDamerauLevenshteinDistance;
+void BM_Distance(benchmark::State& state) {
+  std::string s1 = MakeTestString(state.range(0), 0);
+  std::string s2 = MakeTestString(state.range(0), state.range(1));
+  const size_t cap = state.range(2);
+  for (auto _ : state) {
+    CappedDamerauLevenshteinDistance(s1, s2, cap);
+  }
+}
+BENCHMARK(BM_Distance)->Apply(BenchmarkArgs);
+
+}  // namespace
diff --git a/absl/strings/internal/memutil_benchmark.cc b/absl/strings/internal/memutil_benchmark.cc
index 61e323a..1186752 100644
--- a/absl/strings/internal/memutil_benchmark.cc
+++ b/absl/strings/internal/memutil_benchmark.cc
@@ -12,13 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/internal/memutil.h"
-
 #include <algorithm>
 #include <cstdlib>
 
-#include "benchmark/benchmark.h"
 #include "absl/strings/ascii.h"
+#include "absl/strings/internal/memutil.h"
+#include "benchmark/benchmark.h"
 
 // We fill the haystack with aaaaaaaaaaaaaaaaaa...aaaab.
 // That gives us:
diff --git a/absl/strings/internal/ostringstream_benchmark.cc b/absl/strings/internal/ostringstream_benchmark.cc
index 5979f18..a95cf4d 100644
--- a/absl/strings/internal/ostringstream_benchmark.cc
+++ b/absl/strings/internal/ostringstream_benchmark.cc
@@ -12,11 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/internal/ostringstream.h"
-
 #include <sstream>
 #include <string>
 
+#include "absl/strings/internal/ostringstream.h"
 #include "benchmark/benchmark.h"
 
 namespace {
diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc
index eeb2108..01e4e42 100644
--- a/absl/strings/internal/str_format/arg.cc
+++ b/absl/strings/internal/str_format/arg.cc
@@ -26,6 +26,7 @@
 #include <cstring>
 #include <cwchar>
 #include <string>
+#include <string_view>
 #include <type_traits>
 
 #include "absl/base/config.h"
@@ -34,13 +35,10 @@
 #include "absl/numeric/int128.h"
 #include "absl/strings/internal/str_format/extension.h"
 #include "absl/strings/internal/str_format/float_conversion.h"
+#include "absl/strings/internal/utf8.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/string_view.h"
 
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
-#include <string_view>
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
@@ -311,68 +309,16 @@
                                conv.has_left_flag());
 }
 
-struct ShiftState {
-  bool saw_high_surrogate = false;
-  uint8_t bits = 0;
-};
-
-// Converts `v` from UTF-16 or UTF-32 to UTF-8 and writes to `buf`. `buf` is
-// assumed to have enough space for the output. `s` is used to carry state
-// between successive calls with a UTF-16 surrogate pair. Returns the number of
-// chars written, or `static_cast<size_t>(-1)` on failure.
-//
-// This is basically std::wcrtomb(), but always outputting UTF-8 instead of
-// respecting the current locale.
-inline size_t WideToUtf8(wchar_t wc, char *buf, ShiftState &s) {
-  const auto v = static_cast<uint32_t>(wc);
-  if (v < 0x80) {
-    *buf = static_cast<char>(v);
-    return 1;
-  } else if (v < 0x800) {
-    *buf++ = static_cast<char>(0xc0 | (v >> 6));
-    *buf = static_cast<char>(0x80 | (v & 0x3f));
-    return 2;
-  } else if (v < 0xd800 || (v - 0xe000) < 0x2000) {
-    *buf++ = static_cast<char>(0xe0 | (v >> 12));
-    *buf++ = static_cast<char>(0x80 | ((v >> 6) & 0x3f));
-    *buf = static_cast<char>(0x80 | (v & 0x3f));
-    return 3;
-  } else if ((v - 0x10000) < 0x100000) {
-    *buf++ = static_cast<char>(0xf0 | (v >> 18));
-    *buf++ = static_cast<char>(0x80 | ((v >> 12) & 0x3f));
-    *buf++ = static_cast<char>(0x80 | ((v >> 6) & 0x3f));
-    *buf = static_cast<char>(0x80 | (v & 0x3f));
-    return 4;
-  } else if (v < 0xdc00) {
-    s.saw_high_surrogate = true;
-    s.bits = static_cast<uint8_t>(v & 0x3);
-    const uint8_t high_bits = ((v >> 6) & 0xf) + 1;
-    *buf++ = static_cast<char>(0xf0 | (high_bits >> 2));
-    *buf =
-        static_cast<char>(0x80 | static_cast<uint8_t>((high_bits & 0x3) << 4) |
-                          static_cast<uint8_t>((v >> 2) & 0xf));
-    return 2;
-  } else if (v < 0xe000 && s.saw_high_surrogate) {
-    *buf++ = static_cast<char>(0x80 | static_cast<uint8_t>(s.bits << 4) |
-                               static_cast<uint8_t>((v >> 6) & 0xf));
-    *buf = static_cast<char>(0x80 | (v & 0x3f));
-    s.saw_high_surrogate = false;
-    s.bits = 0;
-    return 2;
-  } else {
-    return static_cast<size_t>(-1);
-  }
-}
-
 inline bool ConvertStringArg(const wchar_t *v,
                              size_t len,
                              const FormatConversionSpecImpl conv,
                              FormatSinkImpl *sink) {
   FixedArray<char> mb(len * 4);
-  ShiftState s;
+  strings_internal::ShiftState s;
   size_t chars_written = 0;
   for (size_t i = 0; i < len; ++i) {
-    const size_t chars = WideToUtf8(v[i], &mb[chars_written], s);
+    const size_t chars =
+        strings_internal::WideToUtf8(v[i], &mb[chars_written], s);
     if (chars == static_cast<size_t>(-1)) { return false; }
     chars_written += chars;
   }
@@ -382,8 +328,8 @@
 bool ConvertWCharTImpl(wchar_t v, const FormatConversionSpecImpl conv,
                        FormatSinkImpl *sink) {
   char mb[4];
-  ShiftState s;
-  const size_t chars_written = WideToUtf8(v, mb, s);
+  strings_internal::ShiftState s;
+  const size_t chars_written = strings_internal::WideToUtf8(v, mb, s);
   return chars_written != static_cast<size_t>(-1) && !s.saw_high_surrogate &&
          ConvertStringArg(string_view(mb, chars_written), conv, sink);
 }
@@ -510,13 +456,11 @@
   return {ConvertStringArg(v, conv, sink)};
 }
 
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
 StringConvertResult FormatConvertImpl(std::wstring_view v,
                                       const FormatConversionSpecImpl conv,
                                       FormatSinkImpl* sink) {
   return {ConvertStringArg(v.data(), v.size(), conv, sink)};
 }
-#endif
 
 StringPtrConvertResult FormatConvertImpl(const char* v,
                                          const FormatConversionSpecImpl conv,
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index 309161d..021013f 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -26,6 +26,7 @@
 #include <memory>
 #include <sstream>
 #include <string>
+#include <string_view>
 #include <type_traits>
 #include <utility>
 
@@ -37,10 +38,6 @@
 #include "absl/strings/internal/str_format/extension.h"
 #include "absl/strings/string_view.h"
 
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
-#include <string_view>
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
@@ -228,7 +225,6 @@
 StringConvertResult FormatConvertImpl(string_view v,
                                       FormatConversionSpecImpl conv,
                                       FormatSinkImpl* sink);
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
 StringConvertResult FormatConvertImpl(std::wstring_view v,
                                       FormatConversionSpecImpl conv,
                                       FormatSinkImpl* sink);
@@ -239,7 +235,6 @@
   return FormatConvertImpl(absl::string_view(v.data(), v.size()), conv, sink);
 }
 #endif  // !ABSL_USES_STD_STRING_VIEW
-#endif  // ABSL_HAVE_STD_STRING_VIEW
 
 using StringPtrConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
     FormatConversionCharSetInternal::s,
@@ -651,15 +646,10 @@
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const wchar_t*, __VA_ARGS__);     \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring, __VA_ARGS__)
 
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...)       \
   ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_( \
       __VA_ARGS__);                                                \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring_view, __VA_ARGS__)
-#else
-#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
-  ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(__VA_ARGS__)
-#endif
 
 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
 
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index baffe05..e4fa44e 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -27,6 +27,7 @@
 #include <set>
 #include <sstream>
 #include <string>
+#include <string_view>
 #include <thread>  // NOLINT
 #include <type_traits>
 #include <vector>
@@ -46,10 +47,6 @@
 #include "absl/types/optional.h"
 #include "absl/types/span.h"
 
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
-#include <string_view>
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
@@ -322,10 +319,8 @@
   TestStringConvert(std::string("hello"));
   TestStringConvert(std::wstring(L"hello"));
   TestStringConvert(string_view("hello"));
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
   TestStringConvert(std::string_view("hello"));
   TestStringConvert(std::wstring_view(L"hello"));
-#endif  // ABSL_HAVE_STD_STRING_VIEW
 }
 
 TEST_F(FormatConvertTest, NullString) {
diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc
index 2a0ceb1..2d441c2 100644
--- a/absl/strings/internal/str_format/extension.cc
+++ b/absl/strings/internal/str_format/extension.cc
@@ -33,28 +33,6 @@
   return s;
 }
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-
-#define ABSL_INTERNAL_X_VAL(id) \
-  constexpr absl::FormatConversionChar FormatConversionCharInternal::id;
-ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
-#undef ABSL_INTERNAL_X_VAL
-// NOLINTNEXTLINE(readability-redundant-declaration)
-constexpr absl::FormatConversionChar FormatConversionCharInternal::kNone;
-
-#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
-  constexpr FormatConversionCharSet FormatConversionCharSetInternal::c;
-ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
-#undef ABSL_INTERNAL_CHAR_SET_CASE
-
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kStar;
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kIntegral;
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kFloating;
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kNumeric;
-constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer;
-
-#endif  // ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-
 bool FormatSinkImpl::PutPaddedString(string_view value, int width,
                                      int precision, bool left) {
   size_t space_remaining = 0;
diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc
index 694c126..fc4dc4f 100644
--- a/absl/strings/internal/str_format/extension_test.cc
+++ b/absl/strings/internal/str_format/extension_test.cc
@@ -16,11 +16,13 @@
 
 #include "absl/strings/internal/str_format/extension.h"
 
+#include <cstddef>
 #include <random>
 #include <string>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/random/random.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/string_view.h"
 
@@ -44,8 +46,7 @@
 namespace {
 
 std::string MakeRandomString(size_t len) {
-  std::random_device rd;
-  std::mt19937 gen(rd());
+  absl::InsecureBitGen gen;
   std::uniform_int_distribution<> dis('a', 'z');
   std::string s(len, '0');
   for (char& c : s) {
diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc
index 8edf520..aa31998 100644
--- a/absl/strings/internal/str_format/float_conversion.cc
+++ b/absl/strings/internal/str_format/float_conversion.cc
@@ -17,6 +17,7 @@
 #include <string.h>
 
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <cmath>
 #include <limits>
@@ -159,7 +160,7 @@
 
   // See the current block of digits.
   absl::string_view CurrentDigits() const {
-    return absl::string_view(digits_ + kDigitsPerChunk - size_, size_);
+    return absl::string_view(&digits_[kDigitsPerChunk - size_], size_);
   }
 
   // Advance the current view of digits.
@@ -234,7 +235,7 @@
   size_t decimal_start_;
   size_t decimal_end_;
 
-  char digits_[kDigitsPerChunk];
+  std::array<char, kDigitsPerChunk> digits_;
   size_t size_ = 0;
 
   absl::Span<uint32_t> data_;
diff --git a/absl/strings/internal/str_format/output.cc b/absl/strings/internal/str_format/output.cc
index c4b2470..068091c 100644
--- a/absl/strings/internal/str_format/output.cc
+++ b/absl/strings/internal/str_format/output.cc
@@ -33,9 +33,11 @@
 
 void BufferRawSink::Write(string_view v) {
   size_t to_write = std::min(v.size(), size_);
-  std::memcpy(buffer_, v.data(), to_write);
-  buffer_ += to_write;
-  size_ -= to_write;
+  if (to_write > 0) {
+    std::memcpy(buffer_, v.data(), to_write);
+    buffer_ += to_write;
+    size_ -= to_write;
+  }
   total_written_ += v.size();
 }
 
diff --git a/absl/strings/internal/str_format/parser.h b/absl/strings/internal/str_format/parser.h
index b1d6d5f..329b060 100644
--- a/absl/strings/internal/str_format/parser.h
+++ b/absl/strings/internal/str_format/parser.h
@@ -132,8 +132,10 @@
     has_error_ = other.has_error_;
     items_ = other.items_;
     size_t text_size = items_.empty() ? 0 : items_.back().text_end;
-    data_.reset(new char[text_size]);
-    memcpy(data_.get(), other.data_.get(), text_size);
+    data_ = std::make_unique<char[]>(text_size);
+    if (text_size > 0) {
+      memcpy(data_.get(), other.data_.get(), text_size);
+    }
     return *this;
   }
 
diff --git a/absl/strings/internal/str_join_internal.h b/absl/strings/internal/str_join_internal.h
index 3e730c7..31fcf6d 100644
--- a/absl/strings/internal/str_join_internal.h
+++ b/absl/strings/internal/str_join_internal.h
@@ -43,6 +43,7 @@
 #include <utility>
 
 #include "absl/base/config.h"
+#include "absl/base/internal/iterator_traits.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/strings/internal/ostringstream.h"
 #include "absl/strings/internal/resize_uninitialized.h"
@@ -228,9 +229,8 @@
 // range will be traversed twice: once to calculate the total needed size, and
 // then again to copy the elements and delimiters to the output string.
 template <typename Iterator,
-          typename = typename std::enable_if<std::is_convertible<
-              typename std::iterator_traits<Iterator>::iterator_category,
-              std::forward_iterator_tag>::value>::type>
+          typename = std::enable_if_t<
+              base_internal::IsAtLeastForwardIterator<Iterator>::value>>
 std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
                           NoFormatter) {
   std::string result;
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h
index 11ea96f..ed1f117 100644
--- a/absl/strings/internal/str_split_internal.h
+++ b/absl/strings/internal/str_split_internal.h
@@ -253,6 +253,10 @@
               (std::is_same<First, absl::string_view>::value ||
                std::is_same<Second, absl::string_view>::value)>;
 
+template <typename StringType, typename ElementType, std::size_t Size>
+using ShouldUseLifetimeBoundForArray = std::integral_constant<
+    bool, std::is_same<StringType, std::string>::value &&
+              std::is_same<ElementType, absl::string_view>::value>;
 
 // This class implements the range that is returned by absl::StrSplit(). This
 // class has templated conversion operators that allow it to be implicitly
@@ -344,7 +348,38 @@
     return ConvertToPair<First, Second>();
   }
 
+  // Returns an array with its elements set to the first few strings returned by
+  // the begin() iterator.  If there is not a corresponding value the empty
+  // string is used.
+  template <typename ElementType, std::size_t Size,
+            std::enable_if_t<ShouldUseLifetimeBoundForArray<
+                                 StringType, ElementType, Size>::value,
+                             std::nullptr_t> = nullptr>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  operator std::array<ElementType, Size>() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+    return ConvertToArray<ElementType, Size>();
+  }
+
+  template <typename ElementType, std::size_t Size,
+            std::enable_if_t<!ShouldUseLifetimeBoundForArray<
+                                 StringType, ElementType, Size>::value,
+                             std::nullptr_t> = nullptr>
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  operator std::array<ElementType, Size>() const {
+    return ConvertToArray<ElementType, Size>();
+  }
+
  private:
+  template <typename ElementType, std::size_t Size>
+  std::array<ElementType, Size> ConvertToArray() const {
+    std::array<ElementType, Size> a;
+    auto it = begin();
+    for (std::size_t i = 0; i < Size && it != end(); ++i, ++it) {
+      a[i] = ElementType(*it);
+    }
+    return a;
+  }
+
   template <typename First, typename Second>
   std::pair<First, Second> ConvertToPair() const {
     absl::string_view first, second;
diff --git a/absl/strings/internal/string_constant.h b/absl/strings/internal/string_constant.h
index f68b17d..d52c330 100644
--- a/absl/strings/internal/string_constant.h
+++ b/absl/strings/internal/string_constant.h
@@ -50,11 +50,6 @@
                 "The input string_view must point to constant data.");
 };
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-template <typename T>
-constexpr absl::string_view StringConstant<T>::value;
-#endif
-
 // Factory function for `StringConstant` instances.
 // It supports callables that have a constexpr default constructor and a
 // constexpr operator().
diff --git a/absl/strings/internal/utf8.cc b/absl/strings/internal/utf8.cc
index 7ecb93d..61945f5 100644
--- a/absl/strings/internal/utf8.cc
+++ b/absl/strings/internal/utf8.cc
@@ -16,11 +16,17 @@
 
 #include "absl/strings/internal/utf8.h"
 
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include "absl/base/config.h"
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
-size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) {
+size_t EncodeUTF8Char(char* buffer, char32_t utf8_char) {
   if (utf8_char <= 0x7F) {
     *buffer = static_cast<char>(utf8_char);
     return 1;
@@ -48,6 +54,95 @@
   }
 }
 
+size_t WideToUtf8(wchar_t wc, char* buf, ShiftState& s) {
+  // Reinterpret the output buffer `buf` as `unsigned char*` for subsequent
+  // bitwise operations. This ensures well-defined behavior for bit
+  // manipulations (avoiding issues with signed `char`) and is safe under C++
+  // aliasing rules, as `unsigned char` can alias any type.
+  auto* ubuf = reinterpret_cast<unsigned char*>(buf);
+  const uint32_t v = static_cast<uint32_t>(wc);
+  constexpr size_t kError = static_cast<size_t>(-1);
+
+  if (v <= 0x007F) {
+    // 1-byte sequence (U+0000 to U+007F).
+    // 0xxxxxxx.
+    ubuf[0] = (0b0111'1111 & v);
+    s = {};  // Reset surrogate state.
+    return 1;
+  } else if (0x0080 <= v && v <= 0x07FF) {
+    // 2-byte sequence (U+0080 to U+07FF).
+    // 110xxxxx 10xxxxxx.
+    ubuf[0] = 0b1100'0000 | (0b0001'1111 & (v >> 6));
+    ubuf[1] = 0b1000'0000 | (0b0011'1111 & v);
+    s = {};  // Reset surrogate state.
+    return 2;
+  } else if ((0x0800 <= v && v <= 0xD7FF) || (0xE000 <= v && v <= 0xFFFF)) {
+    // 3-byte sequence (U+0800 to U+D7FF or U+E000 to U+FFFF).
+    // Excludes surrogate code points U+D800-U+DFFF.
+    // 1110xxxx 10xxxxxx 10xxxxxx.
+    ubuf[0] = 0b1110'0000 | (0b0000'1111 & (v >> 12));
+    ubuf[1] = 0b1000'0000 | (0b0011'1111 & (v >> 6));
+    ubuf[2] = 0b1000'0000 | (0b0011'1111 & v);
+    s = {};  // Reset surrogate state.
+    return 3;
+  } else if (0xD800 <= v && v <= 0xDBFF) {
+    // High Surrogate (U+D800 to U+DBFF).
+    // This part forms the first two bytes of an eventual 4-byte UTF-8 sequence.
+    const unsigned char high_bits_val = (0b0000'1111 & (v >> 6)) + 1;
+
+    // First byte of the 4-byte UTF-8 sequence (11110xxx).
+    ubuf[0] = 0b1111'0000 | (0b0000'0111 & (high_bits_val >> 2));
+    // Second byte of the 4-byte UTF-8 sequence (10xxxxxx).
+    ubuf[1] = 0b1000'0000 |                           //
+              (0b0011'0000 & (high_bits_val << 4)) |  //
+              (0b0000'1111 & (v >> 2));
+    // Set state for high surrogate after writing to buffer.
+    s = {true, static_cast<unsigned char>(0b0000'0011 & v)};
+    return 2;  // Wrote 2 bytes, expecting 2 more from a low surrogate.
+  } else if (0xDC00 <= v && v <= 0xDFFF) {
+    // Low Surrogate (U+DC00 to U+DFFF).
+    // This part forms the last two bytes of a 4-byte UTF-8 sequence,
+    // using state from a preceding high surrogate.
+    if (!s.saw_high_surrogate) {
+      // Error: Isolated low surrogate without a preceding high surrogate.
+      // s remains in its current (problematic) state.
+      // Caller should handle error.
+      return kError;
+    }
+
+    // Third byte of the 4-byte UTF-8 sequence (10xxxxxx).
+    ubuf[0] = 0b1000'0000 |                    //
+              (0b0011'0000 & (s.bits << 4)) |  //
+              (0b0000'1111 & (v >> 6));
+    // Fourth byte of the 4-byte UTF-8 sequence (10xxxxxx).
+    ubuf[1] = 0b1000'0000 | (0b0011'1111 & v);
+
+    s = {};    // Reset surrogate state, pair complete.
+    return 2;  // Wrote 2 more bytes, completing the 4-byte sequence.
+  } else if constexpr (0xFFFF < std::numeric_limits<wchar_t>::max()) {
+    // Conditionally compile the 4-byte direct conversion branch.
+    // This block is compiled only if wchar_t can represent values > 0xFFFF.
+    // It's placed after surrogate checks to ensure surrogates are handled by
+    // their specific logic. This inner 'if' is the runtime check for the 4-byte
+    // range. At this point, v is known not to be in the 1, 2, or 3-byte BMP
+    // ranges, nor is it a surrogate code point.
+    if (0x10000 <= v && v <= 0x10FFFF) {
+      // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx.
+      ubuf[0] = 0b1111'0000 | (0b0000'0111 & (v >> 18));
+      ubuf[1] = 0b1000'0000 | (0b0011'1111 & (v >> 12));
+      ubuf[2] = 0b1000'0000 | (0b0011'1111 & (v >> 6));
+      ubuf[3] = 0b1000'0000 | (0b0011'1111 & v);
+      s = {};  // Reset surrogate state.
+      return 4;
+    }
+  }
+
+  // Invalid wchar_t value (e.g., out of Unicode range, or unhandled after all
+  // checks).
+  s = {};  // Reset surrogate state.
+  return kError;
+}
+
 }  // namespace strings_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/utf8.h b/absl/strings/internal/utf8.h
index 32fb109..ed1db11 100644
--- a/absl/strings/internal/utf8.h
+++ b/absl/strings/internal/utf8.h
@@ -41,7 +41,21 @@
 // characters into buffer, however never will more than kMaxEncodedUTF8Size
 // bytes be written, regardless of the value of utf8_char.
 enum { kMaxEncodedUTF8Size = 4 };
-size_t EncodeUTF8Char(char *buffer, char32_t utf8_char);
+size_t EncodeUTF8Char(char* buffer, char32_t utf8_char);
+
+struct ShiftState {
+  bool saw_high_surrogate = false;
+  unsigned char bits = 0;
+};
+
+// Converts `wc` from UTF-16 or UTF-32 to UTF-8 and writes to `buf`. `buf` is
+// assumed to have enough space for the output. `s` is used to carry state
+// between successive calls with a UTF-16 surrogate pair. Returns the number of
+// chars written, or `static_cast<size_t>(-1)` on failure.
+//
+// This is basically std::wcrtomb(), but always outputting UTF-8 instead of
+// respecting the current locale.
+size_t WideToUtf8(wchar_t wc, char* buf, ShiftState& s);
 
 }  // namespace strings_internal
 ABSL_NAMESPACE_END
diff --git a/absl/strings/internal/utf8_test.cc b/absl/strings/internal/utf8_test.cc
index 88dd503..b88d7bb 100644
--- a/absl/strings/internal/utf8_test.cc
+++ b/absl/strings/internal/utf8_test.cc
@@ -14,14 +14,29 @@
 
 #include "absl/strings/internal/utf8.h"
 
+#include <cstddef>
 #include <cstdint>
+#include <cstring>
+#include <string>
+#include <type_traits>
 #include <utility>
+#include <vector>
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/port.h"
+#include "absl/strings/string_view.h"
 
 namespace {
 
+using ::absl::strings_internal::kMaxEncodedUTF8Size;
+using ::absl::strings_internal::ShiftState;
+using ::absl::strings_internal::WideToUtf8;
+using ::testing::StartsWith;
+using ::testing::TestParamInfo;
+using ::testing::TestWithParam;
+using ::testing::ValuesIn;
+
 #if !defined(__cpp_char8_t)
 #if defined(__clang__)
 #pragma clang diagnostic push
@@ -33,12 +48,12 @@
                                               {0x00010000, u8"\U00010000"},
                                               {0x0000FFFF, u8"\U0000FFFF"},
                                               {0x0010FFFD, u8"\U0010FFFD"}};
-  for (auto &test : tests) {
+  for (auto& test : tests) {
     char buf0[7] = {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'};
     char buf1[7] = {'\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF'};
-    char *buf0_written =
+    char* buf0_written =
         &buf0[absl::strings_internal::EncodeUTF8Char(buf0, test.first)];
-    char *buf1_written =
+    char* buf1_written =
         &buf1[absl::strings_internal::EncodeUTF8Char(buf1, test.first)];
     int apparent_length = 7;
     while (buf0[apparent_length - 1] == '\x00' &&
@@ -63,4 +78,182 @@
 #endif
 #endif  // !defined(__cpp_char8_t)
 
+struct WideToUtf8TestCase {
+  std::string description;
+  wchar_t input;
+  std::string expected_utf8_str;
+  size_t expected_bytes_written;
+  ShiftState initial_state = {false, 0};
+  ShiftState expected_state = {false, 0};
+};
+
+std::vector<WideToUtf8TestCase> GetWideToUtf8TestCases() {
+  constexpr size_t kError = static_cast<size_t>(-1);
+  std::vector<WideToUtf8TestCase> cases = {
+      {"ASCII_A", L'A', "A", 1},
+      {"NullChar", L'\0', std::string("\0", 1), 1},
+      {"ASCII_Max_7F", L'\x7F', "\x7F", 1},
+
+      {"TwoByte_Min_80", L'\u0080', "\xC2\x80", 2},
+      {"PoundSign_A3", L'\u00A3', "\xC2\xA3", 2},
+      {"TwoByte_Max_7FF", L'\u07FF', "\xDF\xBF", 2},
+
+      {"ThreeByte_Min_800", L'\u0800', "\xE0\xA0\x80", 3},
+      {"EuroSign_20AC", L'\u20AC', "\xE2\x82\xAC", 3},
+      {"BMP_MaxBeforeSurrogates_D7FF", L'\uD7FF', "\xED\x9F\xBF", 3},
+      {"BMP_FFFF", L'\uFFFF', "\xEF\xBF\xBF", 3},
+
+      {"IsolatedHighSurr_D800", L'\xD800', "\xF0\x90", 2, {}, {true, 0}},
+      {"IsolatedHighSurr_DBFF", L'\xDBFF', "\xF4\x8F", 2, {}, {true, 3}},
+
+      {"HighSurr_D800_after_HighD800",
+       L'\xD800',
+       "\xF0\x90",
+       2,
+       {true, 0},
+       {true, 0}},
+      {"HighSurr_DBFF_after_HighDBFF",
+       L'\xDBFF',
+       "\xF4\x8F",
+       2,
+       {true, 3},
+       {true, 3}},
+
+      {"LowSurr_DC00_after_HighD800", L'\xDC00', "\x80\x80", 2, {true, 0}, {}},
+      {"LowSurr_DFFD_after_HighDBFF", L'\xDFFD', "\xBF\xBD", 2, {true, 3}, {}},
+      {"LowSurr_DC00_with_InitialState_saw_high_bits_1",
+       L'\xDC00',
+       "\x90\x80",
+       2,
+       {true, 1},
+       {}},
+
+      // Final state = initial on error.
+      {"Error_IsolatedLowSurr_DC00_NoPriorHigh", L'\xDC00', "", kError, {}, {}},
+      {"Error_IsolatedLowSurr_DFFF_NoPriorHigh", L'\xDFFF', "", kError, {}, {}},
+
+#if (defined(WCHAR_MAX) && WCHAR_MAX > 0xFFFF)
+      {"DirectSupplementaryChars_U10000", static_cast<wchar_t>(0x10000),
+       "\xF0\x90\x80\x80", 4},
+      {"DirectSupplementaryChars_U10FFFD", static_cast<wchar_t>(0x10FFFD),
+       "\xF4\x8F\xBF\xBD", 4},
+#endif
+  };
+
+  wchar_t minus_one = static_cast<wchar_t>(-1);
+  if constexpr (sizeof(wchar_t) == 2) {
+    cases.push_back({"WChar_MinusOne_as_FFFF", minus_one, "\xEF\xBF\xBF", 3});
+  } else {
+    cases.push_back(
+        {"Error_WChar_MinusOne_as_FFFFFFFF", minus_one, "", kError, {}, {}});
+  }
+
+  if constexpr (sizeof(wchar_t) >= 4) {
+#ifdef WCHAR_MAX
+    if (static_cast<uintmax_t>(WCHAR_MAX) >= 0x110000UL) {
+      cases.push_back({"Error_OutOfRange_110000",
+                       static_cast<wchar_t>(0x110000UL),
+                       "",
+                       kError,
+                       {},
+                       {}});
+    }
+#else
+    cases.push_back({"Error_OutOfRange_110000_fallback",
+                     static_cast<wchar_t>(0x110000UL),
+                     "",
+                     kError,
+                     {},
+                     {}});
+#endif
+  }
+  return cases;
+}
+
+class WideToUtf8ParamTest : public TestWithParam<WideToUtf8TestCase> {};
+
+TEST_P(WideToUtf8ParamTest, SingleCharConversion) {
+  const auto& test_case = GetParam();
+  ShiftState state = test_case.initial_state;
+  constexpr char kFillChar = '\xAB';
+  std::string buffer(32, kFillChar);
+
+  size_t bytes_written = WideToUtf8(test_case.input, buffer.data(), state);
+
+  EXPECT_EQ(bytes_written, test_case.expected_bytes_written);
+  EXPECT_THAT(buffer, StartsWith(test_case.expected_utf8_str));
+
+  // The remaining bytes should be unchanged.
+  ASSERT_LT(test_case.expected_utf8_str.length(), buffer.size());
+  EXPECT_EQ(buffer[test_case.expected_utf8_str.length()], kFillChar);
+
+  EXPECT_EQ(state.saw_high_surrogate,
+            test_case.expected_state.saw_high_surrogate);
+  EXPECT_EQ(state.bits, test_case.expected_state.bits);
+}
+
+INSTANTIATE_TEST_SUITE_P(WideCharToUtf8Conversion, WideToUtf8ParamTest,
+                         ValuesIn(GetWideToUtf8TestCases()),
+                         [](auto info) { return info.param.description; });
+
+// Comprehensive test string for validating wchar_t to UTF-8 conversion.
+// This string is designed to cover a variety of Unicode character types and
+// sequences:
+// 1. Basic ASCII characters (within names, numbers, and spacing).
+// 2. Common 2-byte UTF-8 sequences:
+//    - Accented Latin characters (e.g., 'á' in "Holá").
+//    - Hebrew text with combining vowel points (e.g., "שָׁלוֹם").
+// 3. Common 3-byte UTF-8 sequences:
+//    - Currency symbols (e.g., '€').
+//    - CJK characters (e.g., "你好", "中").
+//    - Components of complex emojis like the Zero Width Joiner (ZWJ) and
+//      Heart symbol.
+// 4. Various 4-byte UTF-8 sequences (representing Supplementary Plane
+// characters):
+//    - An emoji with a skin tone modifier ("👍🏻").
+//    - A flag emoji composed of regional indicators ("🇺🇸").
+//    - A complex ZWJ emoji sequence ("👩‍❤️‍💋‍👨") combining
+//      SP characters (👩, 💋, 👨) with BMP characters (ZWJ and ❤️).
+//    - These are critical for testing the correct handling of surrogate pairs
+//      when wchar_t is 2 bytes (e.g., on Windows).
+// The goal is to ensure accurate conversion across a diverse set of
+// characters.
+//
+// clang-format off
+#define WIDE_STRING_LITERAL L"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩‍❤️‍💋‍👨 中"
+#define UTF8_STRING_LITERAL u8"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩‍❤️‍💋‍👨 中"
+// clang-format on
+
+absl::string_view GetUtf8TestString() {
+  // `u8""` forces UTF-8 encoding; MSVC will default to e.g. CP1252 (and warn)
+  // without it. However, the resulting character type differs between pre-C++20
+  // (`char`) and C++20 (`char8_t`). So deduce the right character type for all
+  // C++ versions, init it with UTF-8, then `memcpy()` to get the result as a
+  // `char*`
+  static absl::string_view kUtf8TestString = [] {
+    using ConstChar8T = std::remove_reference_t<decltype(*u8"a")>;
+    constexpr ConstChar8T kOutputUtf8[] = UTF8_STRING_LITERAL;
+    static char output[sizeof kOutputUtf8];
+    std::memcpy(output, kOutputUtf8, sizeof kOutputUtf8);
+    return output;
+  }();
+
+  return kUtf8TestString;
+}
+
+TEST(WideToUtf8, FullString) {
+  std::string buffer(kMaxEncodedUTF8Size * sizeof(WIDE_STRING_LITERAL), '\0');
+  char* buffer_ptr = buffer.data();
+
+  ShiftState state;
+  for (const wchar_t wc : WIDE_STRING_LITERAL) {
+    buffer_ptr += WideToUtf8(wc, buffer_ptr, state);
+  }
+
+  EXPECT_THAT(buffer, StartsWith(GetUtf8TestString()));
+}
+
+#undef WIDE_STRING_LITERAL
+#undef UTF8_STRING_LITERAL
+
 }  // namespace
diff --git a/absl/strings/match.h b/absl/strings/match.h
index 1eeafbb..ce4fe78 100644
--- a/absl/strings/match.h
+++ b/absl/strings/match.h
@@ -55,22 +55,32 @@
 // StartsWith()
 //
 // Returns whether a given string `text` begins with `prefix`.
-inline bool StartsWith(absl::string_view text,
-                       absl::string_view prefix) noexcept {
-  return prefix.empty() ||
-         (text.size() >= prefix.size() &&
-          memcmp(text.data(), prefix.data(), prefix.size()) == 0);
+inline constexpr bool StartsWith(absl::string_view text,
+                                 absl::string_view prefix) noexcept {
+  if (prefix.empty()) {
+    return true;
+  }
+  if (text.size() < prefix.size()) {
+    return false;
+  }
+  absl::string_view possible_match = text.substr(0, prefix.size());
+
+  return possible_match == prefix;
 }
 
 // EndsWith()
 //
 // Returns whether a given string `text` ends with `suffix`.
-inline bool EndsWith(absl::string_view text,
-                     absl::string_view suffix) noexcept {
-  return suffix.empty() ||
-         (text.size() >= suffix.size() &&
-          memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
-                 suffix.size()) == 0);
+inline constexpr bool EndsWith(absl::string_view text,
+                               absl::string_view suffix) noexcept {
+  if (suffix.empty()) {
+    return true;
+  }
+  if (text.size() < suffix.size()) {
+    return false;
+  }
+  absl::string_view possible_match = text.substr(text.size() - suffix.size());
+  return possible_match == suffix;
 }
 // StrContainsIgnoreCase()
 //
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index b57d9e8..a83fd2c 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -18,6 +18,7 @@
 #include "absl/strings/numbers.h"
 
 #include <algorithm>
+#include <array>
 #include <cassert>
 #include <cfloat>  // for DBL_DIG and FLT_DIG
 #include <cmath>   // for HUGE_VAL
@@ -46,7 +47,7 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-bool SimpleAtof(absl::string_view str, absl::Nonnull<float*> out) {
+bool SimpleAtof(absl::string_view str, float* absl_nonnull out) {
   *out = 0.0;
   str = StripAsciiWhitespace(str);
   // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one
@@ -77,7 +78,7 @@
   return true;
 }
 
-bool SimpleAtod(absl::string_view str, absl::Nonnull<double*> out) {
+bool SimpleAtod(absl::string_view str, double* absl_nonnull out) {
   *out = 0.0;
   str = StripAsciiWhitespace(str);
   // std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one
@@ -108,7 +109,7 @@
   return true;
 }
 
-bool SimpleAtob(absl::string_view str, absl::Nonnull<bool*> out) {
+bool SimpleAtob(absl::string_view str, bool* absl_nonnull out) {
   ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr.");
   if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") ||
       EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") ||
@@ -167,7 +168,7 @@
 constexpr uint64_t kDivisionBy100Div = 1 << 20;
 
 // Encode functions write the ASCII output of input `n` to `out_str`.
-inline char* EncodeHundred(uint32_t n, absl::Nonnull<char*> out_str) {
+inline char* EncodeHundred(uint32_t n, char* absl_nonnull out_str) {
   int num_digits = static_cast<int>(n - 10) >> 8;
   uint32_t div10 = (n * kDivisionBy10Mul) / kDivisionBy10Div;
   uint32_t mod10 = n - 10u * div10;
@@ -177,7 +178,7 @@
   return out_str + 2 + num_digits;
 }
 
-inline char* EncodeTenThousand(uint32_t n, absl::Nonnull<char*> out_str) {
+inline char* EncodeTenThousand(uint32_t n, char* absl_nonnull out_str) {
   // We split lower 2 digits and upper 2 digits of n into 2 byte consecutive
   // blocks. 123 ->  [\0\1][\0\23]. We divide by 10 both blocks
   // (it's 1 division + zeroing upper bits), and compute modulo 10 as well "in
@@ -233,8 +234,8 @@
   return tens;
 }
 
-inline ABSL_ATTRIBUTE_ALWAYS_INLINE absl::Nonnull<char*> EncodeFullU32(
-    uint32_t n, absl::Nonnull<char*> out_str) {
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE char* absl_nonnull EncodeFullU32(
+    uint32_t n, char* absl_nonnull out_str) {
   if (n < 10) {
     *out_str = static_cast<char>('0' + n);
     return out_str + 1;
@@ -283,7 +284,7 @@
 
 }  // namespace
 
-void numbers_internal::PutTwoDigits(uint32_t i, absl::Nonnull<char*> buf) {
+void numbers_internal::PutTwoDigits(uint32_t i, char* absl_nonnull buf) {
   assert(i < 100);
   uint32_t base = kTwoZeroBytes;
   uint32_t div10 = (i * kDivisionBy10Mul) / kDivisionBy10Div;
@@ -292,15 +293,15 @@
   little_endian::Store16(buf, static_cast<uint16_t>(base));
 }
 
-absl::Nonnull<char*> numbers_internal::FastIntToBuffer(
-    uint32_t n, absl::Nonnull<char*> out_str) {
+char* absl_nonnull numbers_internal::FastIntToBuffer(
+    uint32_t n, char* absl_nonnull out_str) {
   out_str = EncodeFullU32(n, out_str);
   *out_str = '\0';
   return out_str;
 }
 
-absl::Nonnull<char*> numbers_internal::FastIntToBuffer(
-    int32_t i, absl::Nonnull<char*> buffer) {
+char* absl_nonnull numbers_internal::FastIntToBuffer(
+    int32_t i, char* absl_nonnull buffer) {
   uint32_t u = static_cast<uint32_t>(i);
   if (i < 0) {
     *buffer++ = '-';
@@ -314,15 +315,15 @@
   return buffer;
 }
 
-absl::Nonnull<char*> numbers_internal::FastIntToBuffer(
-    uint64_t i, absl::Nonnull<char*> buffer) {
+char* absl_nonnull numbers_internal::FastIntToBuffer(
+    uint64_t i, char* absl_nonnull buffer) {
   buffer = EncodeFullU64(i, buffer);
   *buffer = '\0';
   return buffer;
 }
 
-absl::Nonnull<char*> numbers_internal::FastIntToBuffer(
-    int64_t i, absl::Nonnull<char*> buffer) {
+char* absl_nonnull numbers_internal::FastIntToBuffer(
+    int64_t i, char* absl_nonnull buffer) {
   uint64_t u = static_cast<uint64_t>(i);
   if (i < 0) {
     *buffer++ = '-';
@@ -463,7 +464,7 @@
   // Since we'd like to know if the fractional part of d is close to a half,
   // we multiply it by 65536 and see if the fractional part is close to 32768.
   // (The number doesn't have to be a power of two,but powers of two are faster)
-  uint64_t d64k = d * 65536;
+  uint64_t d64k = static_cast<uint64_t>(d * 65536);
   uint32_t dddddd;  // A 6-digit decimal integer.
   if ((d64k % 65536) == 32767 || (d64k % 65536) == 32768) {
     // OK, it's fairly likely that precision was lost above, which is
@@ -477,7 +478,8 @@
     // value we're representing, of course, is M.mmm... * 2^exp2.
     int exp2;
     double m = std::frexp(value, &exp2);
-    uint64_t mantissa = m * (32768.0 * 65536.0 * 65536.0 * 65536.0);
+    uint64_t mantissa =
+        static_cast<uint64_t>(m * (32768.0 * 65536.0 * 65536.0 * 65536.0));
     // std::frexp returns an m value in the range [0.5, 1.0), however we
     // can't multiply it by 2^64 and convert to an integer because some FPUs
     // throw an exception when converting an number higher than 2^63 into an
@@ -544,7 +546,7 @@
 // Helper function for fast formatting of floating-point.
 // The result is the same as "%g", a.k.a. "%.6g".
 size_t numbers_internal::SixDigitsToBuffer(double d,
-                                           absl::Nonnull<char*> const buffer) {
+                                           char* absl_nonnull const buffer) {
   static_assert(std::numeric_limits<float>::is_iec559,
                 "IEEE-754/IEC-559 support only");
 
@@ -674,7 +676,7 @@
 // Represents integer values of digits.
 // Uses 36 to indicate an invalid character since we support
 // bases up to 36.
-static const int8_t kAsciiToInt[256] = {
+static constexpr std::array<int8_t, 256> kAsciiToInt = {
     36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,  // 16 36s.
     36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
     36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 0,  1,  2,  3,  4,  5,
@@ -692,9 +694,9 @@
 
 // Parse the sign and optional hex or oct prefix in text.
 inline bool safe_parse_sign_and_base(
-    absl::Nonnull<absl::string_view*> text /*inout*/,
-    absl::Nonnull<int*> base_ptr /*inout*/,
-    absl::Nonnull<bool*> negative_ptr /*output*/) {
+    absl::string_view* absl_nonnull text /*inout*/,
+    int* absl_nonnull base_ptr /*inout*/,
+    bool* absl_nonnull negative_ptr /*output*/) {
   if (text->data() == nullptr) {
     return false;
   }
@@ -979,7 +981,7 @@
 
 template <typename IntType>
 inline bool safe_parse_positive_int(absl::string_view text, int base,
-                                    absl::Nonnull<IntType*> value_p) {
+                                    IntType* absl_nonnull value_p) {
   IntType value = 0;
   const IntType vmax = std::numeric_limits<IntType>::max();
   assert(vmax > 0);
@@ -1016,7 +1018,7 @@
 
 template <typename IntType>
 inline bool safe_parse_negative_int(absl::string_view text, int base,
-                                    absl::Nonnull<IntType*> value_p) {
+                                    IntType* absl_nonnull value_p) {
   IntType value = 0;
   const IntType vmin = std::numeric_limits<IntType>::min();
   assert(vmin < 0);
@@ -1061,7 +1063,7 @@
 // http://pubs.opengroup.org/onlinepubs/9699919799/functions/strtol.html
 template <typename IntType>
 inline bool safe_int_internal(absl::string_view text,
-                              absl::Nonnull<IntType*> value_p, int base) {
+                              IntType* absl_nonnull value_p, int base) {
   *value_p = 0;
   bool negative;
   if (!safe_parse_sign_and_base(&text, &base, &negative)) {
@@ -1076,7 +1078,7 @@
 
 template <typename IntType>
 inline bool safe_uint_internal(absl::string_view text,
-                               absl::Nonnull<IntType*> value_p, int base) {
+                               IntType* absl_nonnull value_p, int base) {
   *value_p = 0;
   bool negative;
   if (!safe_parse_sign_and_base(&text, &base, &negative) || negative) {
@@ -1110,32 +1112,52 @@
     "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
 
-bool safe_strto32_base(absl::string_view text, absl::Nonnull<int32_t*> value,
+bool safe_strto8_base(absl::string_view text, int8_t* absl_nonnull value,
+                      int base) {
+  return safe_int_internal<int8_t>(text, value, base);
+}
+
+bool safe_strto16_base(absl::string_view text, int16_t* absl_nonnull value,
+                       int base) {
+  return safe_int_internal<int16_t>(text, value, base);
+}
+
+bool safe_strto32_base(absl::string_view text, int32_t* absl_nonnull value,
                        int base) {
   return safe_int_internal<int32_t>(text, value, base);
 }
 
-bool safe_strto64_base(absl::string_view text, absl::Nonnull<int64_t*> value,
+bool safe_strto64_base(absl::string_view text, int64_t* absl_nonnull value,
                        int base) {
   return safe_int_internal<int64_t>(text, value, base);
 }
 
-bool safe_strto128_base(absl::string_view text, absl::Nonnull<int128*> value,
+bool safe_strto128_base(absl::string_view text, int128* absl_nonnull value,
                         int base) {
   return safe_int_internal<absl::int128>(text, value, base);
 }
 
-bool safe_strtou32_base(absl::string_view text, absl::Nonnull<uint32_t*> value,
+bool safe_strtou8_base(absl::string_view text, uint8_t* absl_nonnull value,
+                       int base) {
+  return safe_uint_internal<uint8_t>(text, value, base);
+}
+
+bool safe_strtou16_base(absl::string_view text, uint16_t* absl_nonnull value,
+                        int base) {
+  return safe_uint_internal<uint16_t>(text, value, base);
+}
+
+bool safe_strtou32_base(absl::string_view text, uint32_t* absl_nonnull value,
                         int base) {
   return safe_uint_internal<uint32_t>(text, value, base);
 }
 
-bool safe_strtou64_base(absl::string_view text, absl::Nonnull<uint64_t*> value,
+bool safe_strtou64_base(absl::string_view text, uint64_t* absl_nonnull value,
                         int base) {
   return safe_uint_internal<uint64_t>(text, value, base);
 }
 
-bool safe_strtou128_base(absl::string_view text, absl::Nonnull<uint128*> value,
+bool safe_strtou128_base(absl::string_view text, uint128* absl_nonnull value,
                          int base) {
   return safe_uint_internal<absl::uint128>(text, value, base);
 }
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index 739dbb2..9c67974 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -32,6 +32,7 @@
 #endif
 
 #include <cstddef>
+#include <cstdint>
 #include <cstdlib>
 #include <cstring>
 #include <ctime>
@@ -39,6 +40,7 @@
 #include <string>
 #include <type_traits>
 
+#include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/endian.h"
 #include "absl/base/macros.h"
@@ -60,8 +62,8 @@
 // encountered, this function returns `false`, leaving `out` in an unspecified
 // state.
 template <typename int_type>
-ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str,
-                                     absl::Nonnull<int_type*> out);
+[[nodiscard]] bool SimpleAtoi(absl::string_view str,
+                              int_type* absl_nonnull out);
 
 // SimpleAtof()
 //
@@ -72,8 +74,7 @@
 // allowed formats for `str`, except SimpleAtof() is locale-independent and will
 // always use the "C" locale. If any errors are encountered, this function
 // returns `false`, leaving `out` in an unspecified state.
-ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str,
-                                     absl::Nonnull<float*> out);
+[[nodiscard]] bool SimpleAtof(absl::string_view str, float* absl_nonnull out);
 
 // SimpleAtod()
 //
@@ -84,8 +85,7 @@
 // allowed formats for `str`, except SimpleAtod is locale-independent and will
 // always use the "C" locale. If any errors are encountered, this function
 // returns `false`, leaving `out` in an unspecified state.
-ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str,
-                                     absl::Nonnull<double*> out);
+[[nodiscard]] bool SimpleAtod(absl::string_view str, double* absl_nonnull out);
 
 // SimpleAtob()
 //
@@ -95,8 +95,7 @@
 // are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any
 // errors are encountered, this function returns `false`, leaving `out` in an
 // unspecified state.
-ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str,
-                                     absl::Nonnull<bool*> out);
+[[nodiscard]] bool SimpleAtob(absl::string_view str, bool* absl_nonnull out);
 
 // SimpleHexAtoi()
 //
@@ -109,14 +108,14 @@
 // by this function. If any errors are encountered, this function returns
 // `false`, leaving `out` in an unspecified state.
 template <typename int_type>
-ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str,
-                                        absl::Nonnull<int_type*> out);
+[[nodiscard]] bool SimpleHexAtoi(absl::string_view str,
+                                 int_type* absl_nonnull out);
 
 // Overloads of SimpleHexAtoi() for 128 bit integers.
-ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(
-    absl::string_view str, absl::Nonnull<absl::int128*> out);
-ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(
-    absl::string_view str, absl::Nonnull<absl::uint128*> out);
+[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,
+                                        absl::int128* absl_nonnull out);
+[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,
+                                        absl::uint128* absl_nonnull out);
 
 ABSL_NAMESPACE_END
 }  // namespace absl
@@ -127,6 +126,18 @@
 ABSL_NAMESPACE_BEGIN
 namespace numbers_internal {
 
+template <typename int_type>
+constexpr bool is_signed() {
+  if constexpr (std::is_arithmetic<int_type>::value) {
+    // Use std::numeric_limits<T>::is_signed where it's defined to work.
+    return std::numeric_limits<int_type>::is_signed;
+  }
+  // TODO(jorg): This signed-ness check is used because it works correctly
+  // with enums, and it also serves to check that int_type is not a pointer.
+  // If one day something like std::is_signed<enum E> works, switch to it.
+  return static_cast<int_type>(1) - 2 < 0;
+}
+
 // Digit conversion.
 ABSL_DLL extern const char kHexChar[17];  // 0123456789abcdef
 ABSL_DLL extern const char
@@ -138,22 +149,30 @@
 //   PutTwoDigits(42, buf);
 //   // buf[0] == '4'
 //   // buf[1] == '2'
-void PutTwoDigits(uint32_t i, absl::Nonnull<char*> buf);
+void PutTwoDigits(uint32_t i, char* absl_nonnull buf);
 
 // safe_strto?() functions for implementing SimpleAtoi()
 
-bool safe_strto32_base(absl::string_view text, absl::Nonnull<int32_t*> value,
+bool safe_strto8_base(absl::string_view text, int8_t* absl_nonnull value,
+                      int base);
+bool safe_strto16_base(absl::string_view text, int16_t* absl_nonnull value,
                        int base);
-bool safe_strto64_base(absl::string_view text, absl::Nonnull<int64_t*> value,
+bool safe_strto32_base(absl::string_view text, int32_t* absl_nonnull value,
+                       int base);
+bool safe_strto64_base(absl::string_view text, int64_t* absl_nonnull value,
                        int base);
 bool safe_strto128_base(absl::string_view text,
-                        absl::Nonnull<absl::int128*> value, int base);
-bool safe_strtou32_base(absl::string_view text, absl::Nonnull<uint32_t*> value,
+                        absl::int128* absl_nonnull value, int base);
+bool safe_strtou8_base(absl::string_view text, uint8_t* absl_nonnull value,
+                       int base);
+bool safe_strtou16_base(absl::string_view text, uint16_t* absl_nonnull value,
                         int base);
-bool safe_strtou64_base(absl::string_view text, absl::Nonnull<uint64_t*> value,
+bool safe_strtou32_base(absl::string_view text, uint32_t* absl_nonnull value,
+                        int base);
+bool safe_strtou64_base(absl::string_view text, uint64_t* absl_nonnull value,
                         int base);
 bool safe_strtou128_base(absl::string_view text,
-                         absl::Nonnull<absl::uint128*> value, int base);
+                         absl::uint128* absl_nonnull value, int base);
 
 static const int kFastToBufferSize = 32;
 static const int kSixDigitsToBufferSize = 16;
@@ -164,33 +183,30 @@
 // outside the range 0.0001-999999 are output using scientific notation
 // (1.23456e+06). This routine is heavily optimized.
 // Required buffer size is `kSixDigitsToBufferSize`.
-size_t SixDigitsToBuffer(double d, absl::Nonnull<char*> buffer);
+size_t SixDigitsToBuffer(double d, char* absl_nonnull buffer);
 
 // WARNING: These functions may write more characters than necessary, because
 // they are intended for speed. All functions take an output buffer
 // as an argument and return a pointer to the last byte they wrote, which is the
 // terminating '\0'. At most `kFastToBufferSize` bytes are written.
-absl::Nonnull<char*> FastIntToBuffer(int32_t i, absl::Nonnull<char*> buffer)
+char* absl_nonnull FastIntToBuffer(int32_t i, char* absl_nonnull buffer)
     ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize);
-absl::Nonnull<char*> FastIntToBuffer(uint32_t n, absl::Nonnull<char*> out_str)
+char* absl_nonnull FastIntToBuffer(uint32_t n, char* absl_nonnull out_str)
     ABSL_INTERNAL_NEED_MIN_SIZE(out_str, kFastToBufferSize);
-absl::Nonnull<char*> FastIntToBuffer(int64_t i, absl::Nonnull<char*> buffer)
+char* absl_nonnull FastIntToBuffer(int64_t i, char* absl_nonnull buffer)
     ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize);
-absl::Nonnull<char*> FastIntToBuffer(uint64_t i, absl::Nonnull<char*> buffer)
+char* absl_nonnull FastIntToBuffer(uint64_t i, char* absl_nonnull buffer)
     ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize);
 
 // For enums and integer types that are not an exact match for the types above,
 // use templates to call the appropriate one of the four overloads above.
 template <typename int_type>
-absl::Nonnull<char*> FastIntToBuffer(int_type i, absl::Nonnull<char*> buffer)
+char* absl_nonnull FastIntToBuffer(int_type i, char* absl_nonnull buffer)
     ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize) {
   static_assert(sizeof(i) <= 64 / 8,
                 "FastIntToBuffer works only with 64-bit-or-less integers.");
-  // TODO(jorg): This signed-ness check is used because it works correctly
-  // with enums, and it also serves to check that int_type is not a pointer.
-  // If one day something like std::is_signed<enum E> works, switch to it.
   // These conditions are constexpr bools to suppress MSVC warning C4127.
-  constexpr bool kIsSigned = static_cast<int_type>(1) - 2 < 0;
+  constexpr bool kIsSigned = is_signed<int_type>();
   constexpr bool kUse64Bit = sizeof(i) > 32 / 8;
   if (kIsSigned) {
     if (kUse64Bit) {
@@ -210,39 +226,52 @@
 // Implementation of SimpleAtoi, generalized to support arbitrary base (used
 // with base different from 10 elsewhere in Abseil implementation).
 template <typename int_type>
-ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s,
-                                           absl::Nonnull<int_type*> out,
-                                           int base) {
-  static_assert(sizeof(*out) == 4 || sizeof(*out) == 8,
-                "SimpleAtoi works only with 32-bit or 64-bit integers.");
+[[nodiscard]] bool safe_strtoi_base(absl::string_view s,
+                                    int_type* absl_nonnull out, int base) {
+  static_assert(sizeof(*out) == 1 || sizeof(*out) == 2 || sizeof(*out) == 4 ||
+                    sizeof(*out) == 8,
+                "SimpleAtoi works only with 8, 16, 32, or 64-bit integers.");
   static_assert(!std::is_floating_point<int_type>::value,
                 "Use SimpleAtof or SimpleAtod instead.");
   bool parsed;
-  // TODO(jorg): This signed-ness check is used because it works correctly
-  // with enums, and it also serves to check that int_type is not a pointer.
-  // If one day something like std::is_signed<enum E> works, switch to it.
   // These conditions are constexpr bools to suppress MSVC warning C4127.
-  constexpr bool kIsSigned = static_cast<int_type>(1) - 2 < 0;
-  constexpr bool kUse64Bit = sizeof(*out) == 64 / 8;
+  constexpr bool kIsSigned = is_signed<int_type>();
+  constexpr int kIntTypeSize = sizeof(*out) * 8;
   if (kIsSigned) {
-    if (kUse64Bit) {
+    if (kIntTypeSize == 64) {
       int64_t val;
       parsed = numbers_internal::safe_strto64_base(s, &val, base);
       *out = static_cast<int_type>(val);
-    } else {
+    } else if (kIntTypeSize == 32) {
       int32_t val;
       parsed = numbers_internal::safe_strto32_base(s, &val, base);
       *out = static_cast<int_type>(val);
+    } else if (kIntTypeSize == 16) {
+      int16_t val;
+      parsed = numbers_internal::safe_strto16_base(s, &val, base);
+      *out = static_cast<int_type>(val);
+    } else if (kIntTypeSize == 8) {
+      int8_t val;
+      parsed = numbers_internal::safe_strto8_base(s, &val, base);
+      *out = static_cast<int_type>(val);
     }
   } else {
-    if (kUse64Bit) {
+    if (kIntTypeSize == 64) {
       uint64_t val;
       parsed = numbers_internal::safe_strtou64_base(s, &val, base);
       *out = static_cast<int_type>(val);
-    } else {
+    } else if (kIntTypeSize == 32) {
       uint32_t val;
       parsed = numbers_internal::safe_strtou32_base(s, &val, base);
       *out = static_cast<int_type>(val);
+    } else if (kIntTypeSize == 16) {
+      uint16_t val;
+      parsed = numbers_internal::safe_strtou16_base(s, &val, base);
+      *out = static_cast<int_type>(val);
+    } else if (kIntTypeSize == 8) {
+      uint8_t val;
+      parsed = numbers_internal::safe_strtou8_base(s, &val, base);
+      *out = static_cast<int_type>(val);
     }
   }
   return parsed;
@@ -254,7 +283,7 @@
 // without the terminating null character. Thus `out` must be of length >= 16.
 // Returns the number of non-pad digits of the output (it can never be zero
 // since 0 has one digit).
-inline size_t FastHexToBufferZeroPad16(uint64_t val, absl::Nonnull<char*> out) {
+inline size_t FastHexToBufferZeroPad16(uint64_t val, char* absl_nonnull out) {
 #ifdef ABSL_INTERNAL_HAVE_SSSE3
   uint64_t be = absl::big_endian::FromHost64(val);
   const auto kNibbleMask = _mm_set1_epi8(0xf);
@@ -280,34 +309,34 @@
 }  // namespace numbers_internal
 
 template <typename int_type>
-ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str,
-                                     absl::Nonnull<int_type*> out) {
+[[nodiscard]] bool SimpleAtoi(absl::string_view str,
+                              int_type* absl_nonnull out) {
   return numbers_internal::safe_strtoi_base(str, out, 10);
 }
 
-ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
-                                            absl::Nonnull<absl::int128*> out) {
+[[nodiscard]] inline bool SimpleAtoi(absl::string_view str,
+                                     absl::int128* absl_nonnull out) {
   return numbers_internal::safe_strto128_base(str, out, 10);
 }
 
-ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
-                                            absl::Nonnull<absl::uint128*> out) {
+[[nodiscard]] inline bool SimpleAtoi(absl::string_view str,
+                                     absl::uint128* absl_nonnull out) {
   return numbers_internal::safe_strtou128_base(str, out, 10);
 }
 
 template <typename int_type>
-ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str,
-                                        absl::Nonnull<int_type*> out) {
+[[nodiscard]] bool SimpleHexAtoi(absl::string_view str,
+                                 int_type* absl_nonnull out) {
   return numbers_internal::safe_strtoi_base(str, out, 16);
 }
 
-ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(
-    absl::string_view str, absl::Nonnull<absl::int128*> out) {
+[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,
+                                        absl::int128* absl_nonnull out) {
   return numbers_internal::safe_strto128_base(str, out, 16);
 }
 
-ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(
-    absl::string_view str, absl::Nonnull<absl::uint128*> out) {
+[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,
+                                        absl::uint128* absl_nonnull out) {
   return numbers_internal::safe_strtou128_base(str, out, 16);
 }
 
diff --git a/absl/strings/numbers_benchmark.cc b/absl/strings/numbers_benchmark.cc
index e7cb60a..c58f861 100644
--- a/absl/strings/numbers_benchmark.cc
+++ b/absl/strings/numbers_benchmark.cc
@@ -19,12 +19,12 @@
 #include <type_traits>
 #include <vector>
 
-#include "benchmark/benchmark.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/distributions.h"
 #include "absl/random/random.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/string_view.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 75c2dcf..1a82087 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -34,13 +34,13 @@
 #include <random>
 #include <set>
 #include <string>
+#include <type_traits>
 #include <vector>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/log/log.h"
 #include "absl/numeric/int128.h"
-#include "absl/random/distributions.h"
 #include "absl/random/random.h"
 #include "absl/strings/internal/numbers_test_common.h"
 #include "absl/strings/internal/ostringstream.h"
@@ -53,10 +53,14 @@
 using absl::SimpleAtoi;
 using absl::SimpleHexAtoi;
 using absl::numbers_internal::kSixDigitsToBufferSize;
+using absl::numbers_internal::safe_strto16_base;
 using absl::numbers_internal::safe_strto32_base;
 using absl::numbers_internal::safe_strto64_base;
+using absl::numbers_internal::safe_strto8_base;
+using absl::numbers_internal::safe_strtou16_base;
 using absl::numbers_internal::safe_strtou32_base;
 using absl::numbers_internal::safe_strtou64_base;
+using absl::numbers_internal::safe_strtou8_base;
 using absl::numbers_internal::SixDigitsToBuffer;
 using absl::strings_internal::Itoa;
 using absl::strings_internal::strtouint32_test_cases;
@@ -256,9 +260,7 @@
 
 template <typename int_type, typename in_val_type>
 void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
-  std::string s;
-  // (u)int128 can be streamed but not StrCat'd.
-  absl::strings_internal::OStringStream(&s) << in_value;
+  std::string s = absl::StrCat(in_value);
   int_type x = static_cast<int_type>(~exp_value);
   EXPECT_TRUE(SimpleAtoi(s, &x))
       << "in_value=" << in_value << " s=" << s << " x=" << x;
@@ -270,15 +272,71 @@
 
 template <typename int_type, typename in_val_type>
 void VerifySimpleAtoiBad(in_val_type in_value) {
-  std::string s;
-  // (u)int128 can be streamed but not StrCat'd.
-  absl::strings_internal::OStringStream(&s) << in_value;
+  std::string s = absl::StrCat(in_value);
   int_type x;
   EXPECT_FALSE(SimpleAtoi(s, &x));
   EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));
 }
 
 TEST(NumbersTest, Atoi) {
+  // SimpleAtoi(absl::string_view, int8_t)
+  VerifySimpleAtoiGood<int8_t>(0, 0);
+  VerifySimpleAtoiGood<int8_t>(42, 42);
+  VerifySimpleAtoiGood<int8_t>(-42, -42);
+
+  VerifySimpleAtoiGood<int8_t>(std::numeric_limits<int8_t>::min(),
+                               std::numeric_limits<int8_t>::min());
+  VerifySimpleAtoiGood<int8_t>(std::numeric_limits<int8_t>::max(),
+                               std::numeric_limits<int8_t>::max());
+
+  VerifySimpleAtoiBad<int8_t>(std::numeric_limits<uint8_t>::max());
+  VerifySimpleAtoiBad<int8_t>(std::numeric_limits<int16_t>::min());
+  VerifySimpleAtoiBad<int8_t>(std::numeric_limits<int16_t>::max());
+
+  // SimpleAtoi(absl::string_view, uint8_t)
+  VerifySimpleAtoiGood<uint8_t>(0, 0);
+  VerifySimpleAtoiGood<uint8_t>(42, 42);
+  VerifySimpleAtoiBad<uint8_t>(-42);
+
+  VerifySimpleAtoiBad<uint8_t>(std::numeric_limits<int8_t>::min());
+  VerifySimpleAtoiGood<uint8_t>(std::numeric_limits<int8_t>::max(),
+                                std::numeric_limits<int8_t>::max());
+  VerifySimpleAtoiGood<uint8_t>(std::numeric_limits<uint8_t>::max(),
+                                std::numeric_limits<uint8_t>::max());
+
+  VerifySimpleAtoiBad<uint8_t>(std::numeric_limits<int16_t>::min());
+  VerifySimpleAtoiBad<uint8_t>(std::numeric_limits<int16_t>::max());
+  VerifySimpleAtoiBad<uint8_t>(std::numeric_limits<uint16_t>::max());
+
+  // SimpleAtoi(absl::string_view, uint16_t)
+  VerifySimpleAtoiGood<int16_t>(0, 0);
+  VerifySimpleAtoiGood<int16_t>(42, 42);
+  VerifySimpleAtoiGood<int16_t>(-42, -42);
+
+  VerifySimpleAtoiGood<int16_t>(std::numeric_limits<int16_t>::min(),
+                                std::numeric_limits<int16_t>::min());
+  VerifySimpleAtoiGood<int16_t>(std::numeric_limits<int16_t>::max(),
+                                std::numeric_limits<int16_t>::max());
+
+  VerifySimpleAtoiBad<int16_t>(std::numeric_limits<uint16_t>::max());
+  VerifySimpleAtoiBad<int16_t>(std::numeric_limits<int32_t>::min());
+  VerifySimpleAtoiBad<int16_t>(std::numeric_limits<int32_t>::max());
+
+  // SimpleAtoi(absl::string_view, uint16_t)
+  VerifySimpleAtoiGood<uint16_t>(0, 0);
+  VerifySimpleAtoiGood<uint16_t>(42, 42);
+  VerifySimpleAtoiBad<uint16_t>(-42);
+
+  VerifySimpleAtoiBad<uint16_t>(std::numeric_limits<int16_t>::min());
+  VerifySimpleAtoiGood<uint16_t>(std::numeric_limits<int16_t>::max(),
+                                 std::numeric_limits<int16_t>::max());
+  VerifySimpleAtoiGood<uint16_t>(std::numeric_limits<uint16_t>::max(),
+                                 std::numeric_limits<uint16_t>::max());
+
+  VerifySimpleAtoiBad<uint16_t>(std::numeric_limits<int16_t>::min());
+  VerifySimpleAtoiBad<uint16_t>(std::numeric_limits<int32_t>::max());
+  VerifySimpleAtoiBad<uint16_t>(std::numeric_limits<uint32_t>::max());
+
   // SimpleAtoi(absl::string_view, int32_t)
   VerifySimpleAtoiGood<int32_t>(0, 0);
   VerifySimpleAtoiGood<int32_t>(42, 42);
@@ -381,6 +439,7 @@
   VerifySimpleAtoiBad<absl::int128>(std::numeric_limits<absl::uint128>::max());
 
   // Some other types
+  VerifySimpleAtoiGood<short>(-42, -42);  // NOLINT: runtime-int
   VerifySimpleAtoiGood<int>(-42, -42);
   VerifySimpleAtoiGood<int32_t>(-42, -42);
   VerifySimpleAtoiGood<uint32_t>(42, 42);
@@ -677,10 +736,14 @@
 template <typename int_type, typename in_val_type>
 void VerifySimpleHexAtoiGood(in_val_type in_value, int_type exp_value) {
   std::string s;
-  // uint128 can be streamed but not StrCat'd
   absl::strings_internal::OStringStream strm(&s);
   if (in_value >= 0) {
-    strm << std::hex << in_value;
+    if constexpr (std::is_arithmetic<in_val_type>::value) {
+      absl::StrAppend(&s, absl::Hex(in_value));
+    } else {
+      // absl::Hex doesn't work with absl::(u)int128.
+      strm << std::hex << in_value;
+    }
   } else {
     // Inefficient for small integers, but works with all integral types.
     strm << "-" << std::hex << -absl::uint128(in_value);
@@ -698,10 +761,14 @@
 template <typename int_type, typename in_val_type>
 void VerifySimpleHexAtoiBad(in_val_type in_value) {
   std::string s;
-  // uint128 can be streamed but not StrCat'd
   absl::strings_internal::OStringStream strm(&s);
   if (in_value >= 0) {
-    strm << std::hex << in_value;
+    if constexpr (std::is_arithmetic<in_val_type>::value) {
+      absl::StrAppend(&s, absl::Hex(in_value));
+    } else {
+      // absl::Hex doesn't work with absl::(u)int128.
+      strm << std::hex << in_value;
+    }
   } else {
     // Inefficient for small integers, but works with all integral types.
     strm << "-" << std::hex << -absl::uint128(in_value);
@@ -713,6 +780,54 @@
 }
 
 TEST(NumbersTest, HexAtoi) {
+  // SimpleHexAtoi(absl::string_view, int8_t)
+  VerifySimpleHexAtoiGood<int8_t>(0, 0);
+  VerifySimpleHexAtoiGood<int8_t>(0x42, 0x42);
+  VerifySimpleHexAtoiGood<int8_t>(-0x42, -0x42);
+
+  VerifySimpleHexAtoiGood<int8_t>(std::numeric_limits<int8_t>::min(),
+                                  std::numeric_limits<int8_t>::min());
+  VerifySimpleHexAtoiGood<int8_t>(std::numeric_limits<int8_t>::max(),
+                                  std::numeric_limits<int8_t>::max());
+
+  // SimpleHexAtoi(absl::string_view, uint8_t)
+  VerifySimpleHexAtoiGood<uint8_t>(0, 0);
+  VerifySimpleHexAtoiGood<uint8_t>(0x42, 0x42);
+  VerifySimpleHexAtoiBad<uint8_t>(-0x42);
+
+  VerifySimpleHexAtoiBad<uint8_t>(std::numeric_limits<int8_t>::min());
+  VerifySimpleHexAtoiGood<uint8_t>(std::numeric_limits<int8_t>::max(),
+                                   std::numeric_limits<int8_t>::max());
+  VerifySimpleHexAtoiGood<uint8_t>(std::numeric_limits<uint8_t>::max(),
+                                   std::numeric_limits<uint8_t>::max());
+  VerifySimpleHexAtoiBad<uint8_t>(std::numeric_limits<int16_t>::min());
+  VerifySimpleHexAtoiBad<uint8_t>(std::numeric_limits<int16_t>::max());
+  VerifySimpleHexAtoiBad<uint8_t>(std::numeric_limits<uint16_t>::max());
+
+  // SimpleHexAtoi(absl::string_view, int16_t)
+  VerifySimpleHexAtoiGood<int16_t>(0, 0);
+  VerifySimpleHexAtoiGood<int16_t>(0x42, 0x42);
+  VerifySimpleHexAtoiGood<int16_t>(-0x42, -0x42);
+
+  VerifySimpleHexAtoiGood<int16_t>(std::numeric_limits<int16_t>::min(),
+                                   std::numeric_limits<int16_t>::min());
+  VerifySimpleHexAtoiGood<int16_t>(std::numeric_limits<int16_t>::max(),
+                                   std::numeric_limits<int16_t>::max());
+
+  // SimpleHexAtoi(absl::string_view, uint16_t)
+  VerifySimpleHexAtoiGood<uint16_t>(0, 0);
+  VerifySimpleHexAtoiGood<uint16_t>(0x42, 0x42);
+  VerifySimpleHexAtoiBad<uint16_t>(-0x42);
+
+  VerifySimpleHexAtoiBad<uint16_t>(std::numeric_limits<int16_t>::min());
+  VerifySimpleHexAtoiGood<uint16_t>(std::numeric_limits<int16_t>::max(),
+                                    std::numeric_limits<int16_t>::max());
+  VerifySimpleHexAtoiGood<uint16_t>(std::numeric_limits<uint16_t>::max(),
+                                    std::numeric_limits<uint16_t>::max());
+  VerifySimpleHexAtoiBad<uint16_t>(std::numeric_limits<int32_t>::min());
+  VerifySimpleHexAtoiBad<uint16_t>(std::numeric_limits<int32_t>::max());
+  VerifySimpleHexAtoiBad<uint16_t>(std::numeric_limits<uint32_t>::max());
+
   // SimpleHexAtoi(absl::string_view, int32_t)
   VerifySimpleHexAtoiGood<int32_t>(0, 0);
   VerifySimpleHexAtoiGood<int32_t>(0x42, 0x42);
@@ -790,6 +905,7 @@
       std::numeric_limits<absl::uint128>::max());
 
   // Some other types
+  VerifySimpleHexAtoiGood<short>(-0x42, -0x42);  // NOLINT: runtime-int
   VerifySimpleHexAtoiGood<int>(-0x42, -0x42);
   VerifySimpleHexAtoiGood<int32_t>(-0x42, -0x42);
   VerifySimpleHexAtoiGood<uint32_t>(0x42, 0x42);
@@ -816,6 +932,154 @@
   EXPECT_EQ(0x34234324, value);
 }
 
+TEST(stringtest, safe_strto8_base) {
+  int8_t value;
+  EXPECT_TRUE(safe_strto8_base("0x34", &value, 16));
+  EXPECT_EQ(0x34, value);
+
+  EXPECT_TRUE(safe_strto8_base("0X34", &value, 16));
+  EXPECT_EQ(0x34, value);
+
+  EXPECT_TRUE(safe_strto8_base("34", &value, 16));
+  EXPECT_EQ(0x34, value);
+
+  EXPECT_TRUE(safe_strto8_base("0", &value, 16));
+  EXPECT_EQ(0, value);
+
+  EXPECT_TRUE(safe_strto8_base(" \t\n -0x34", &value, 16));
+  EXPECT_EQ(-0x34, value);
+
+  EXPECT_TRUE(safe_strto8_base(" \t\n -34", &value, 16));
+  EXPECT_EQ(-0x34, value);
+
+  EXPECT_TRUE(safe_strto8_base("76", &value, 8));
+  EXPECT_EQ(076, value);
+
+  EXPECT_TRUE(safe_strto8_base("-0123", &value, 8));
+  EXPECT_EQ(-0123, value);
+
+  EXPECT_FALSE(safe_strto8_base("183", &value, 8));
+
+  // Autodetect base.
+  EXPECT_TRUE(safe_strto8_base("0", &value, 0));
+  EXPECT_EQ(0, value);
+
+  EXPECT_TRUE(safe_strto8_base("077", &value, 0));
+  EXPECT_EQ(077, value);  // Octal interpretation
+
+  // Leading zero indicates octal, but then followed by invalid digit.
+  EXPECT_FALSE(safe_strto8_base("088", &value, 0));
+
+  // Leading 0x indicated hex, but then followed by invalid digit.
+  EXPECT_FALSE(safe_strto8_base("0xG", &value, 0));
+
+  // Base-10 version.
+  EXPECT_TRUE(safe_strto8_base("124", &value, 10));
+  EXPECT_EQ(124, value);
+
+  EXPECT_TRUE(safe_strto8_base("0", &value, 10));
+  EXPECT_EQ(0, value);
+
+  EXPECT_TRUE(safe_strto8_base(" \t\n -124", &value, 10));
+  EXPECT_EQ(-124, value);
+
+  EXPECT_TRUE(safe_strto8_base("124 \n\t ", &value, 10));
+  EXPECT_EQ(124, value);
+
+  // Invalid ints.
+  EXPECT_FALSE(safe_strto8_base("", &value, 10));
+  EXPECT_FALSE(safe_strto8_base("  ", &value, 10));
+  EXPECT_FALSE(safe_strto8_base("abc", &value, 10));
+  EXPECT_FALSE(safe_strto8_base("34a", &value, 10));
+  EXPECT_FALSE(safe_strto8_base("34.3", &value, 10));
+
+  // Out of bounds.
+  EXPECT_FALSE(safe_strto8_base("128", &value, 10));
+  EXPECT_FALSE(safe_strto8_base("-129", &value, 10));
+
+  // String version.
+  EXPECT_TRUE(safe_strto8_base(std::string("0x12"), &value, 16));
+  EXPECT_EQ(0x12, value);
+
+  // Base-10 string version.
+  EXPECT_TRUE(safe_strto8_base("123", &value, 10));
+  EXPECT_EQ(123, value);
+}
+
+TEST(stringtest, safe_strto16_base) {
+  int16_t value;
+  EXPECT_TRUE(safe_strto16_base("0x3423", &value, 16));
+  EXPECT_EQ(0x3423, value);
+
+  EXPECT_TRUE(safe_strto16_base("0X3423", &value, 16));
+  EXPECT_EQ(0x3423, value);
+
+  EXPECT_TRUE(safe_strto16_base("3423", &value, 16));
+  EXPECT_EQ(0x3423, value);
+
+  EXPECT_TRUE(safe_strto16_base("0", &value, 16));
+  EXPECT_EQ(0, value);
+
+  EXPECT_TRUE(safe_strto16_base(" \t\n -0x3423", &value, 16));
+  EXPECT_EQ(-0x3423, value);
+
+  EXPECT_TRUE(safe_strto16_base(" \t\n -3423", &value, 16));
+  EXPECT_EQ(-0x3423, value);
+
+  EXPECT_TRUE(safe_strto16_base("34567", &value, 8));
+  EXPECT_EQ(034567, value);
+
+  EXPECT_TRUE(safe_strto16_base("-01234", &value, 8));
+  EXPECT_EQ(-01234, value);
+
+  EXPECT_FALSE(safe_strto16_base("1834", &value, 8));
+
+  // Autodetect base.
+  EXPECT_TRUE(safe_strto16_base("0", &value, 0));
+  EXPECT_EQ(0, value);
+
+  EXPECT_TRUE(safe_strto16_base("077", &value, 0));
+  EXPECT_EQ(077, value);  // Octal interpretation
+
+  // Leading zero indicates octal, but then followed by invalid digit.
+  EXPECT_FALSE(safe_strto16_base("088", &value, 0));
+
+  // Leading 0x indicated hex, but then followed by invalid digit.
+  EXPECT_FALSE(safe_strto16_base("0xG", &value, 0));
+
+  // Base-10 version.
+  EXPECT_TRUE(safe_strto16_base("3423", &value, 10));
+  EXPECT_EQ(3423, value);
+
+  EXPECT_TRUE(safe_strto16_base("0", &value, 10));
+  EXPECT_EQ(0, value);
+
+  EXPECT_TRUE(safe_strto16_base(" \t\n -3423", &value, 10));
+  EXPECT_EQ(-3423, value);
+
+  EXPECT_TRUE(safe_strto16_base("3423 \n\t ", &value, 10));
+  EXPECT_EQ(3423, value);
+
+  // Invalid ints.
+  EXPECT_FALSE(safe_strto16_base("", &value, 10));
+  EXPECT_FALSE(safe_strto16_base("  ", &value, 10));
+  EXPECT_FALSE(safe_strto16_base("abc", &value, 10));
+  EXPECT_FALSE(safe_strto16_base("324a", &value, 10));
+  EXPECT_FALSE(safe_strto16_base("4234.3", &value, 10));
+
+  // Out of bounds.
+  EXPECT_FALSE(safe_strto16_base("32768", &value, 10));
+  EXPECT_FALSE(safe_strto16_base("-32769", &value, 10));
+
+  // String version.
+  EXPECT_TRUE(safe_strto16_base(std::string("0x1234"), &value, 16));
+  EXPECT_EQ(0x1234, value);
+
+  // Base-10 string version.
+  EXPECT_TRUE(safe_strto16_base("1234", &value, 10));
+  EXPECT_EQ(1234, value);
+}
+
 TEST(stringtest, safe_strto32_base) {
   int32_t value;
   EXPECT_TRUE(safe_strto32_base("0x34234324", &value, 16));
@@ -890,76 +1154,6 @@
   EXPECT_EQ(1234, value);
 }
 
-TEST(stringtest, safe_strto32_range) {
-  // These tests verify underflow/overflow behaviour.
-  int32_t value;
-  EXPECT_FALSE(safe_strto32_base("2147483648", &value, 10));
-  EXPECT_EQ(std::numeric_limits<int32_t>::max(), value);
-
-  EXPECT_TRUE(safe_strto32_base("-2147483648", &value, 10));
-  EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);
-
-  EXPECT_FALSE(safe_strto32_base("-2147483649", &value, 10));
-  EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);
-}
-
-TEST(stringtest, safe_strto64_range) {
-  // These tests verify underflow/overflow behaviour.
-  int64_t value;
-  EXPECT_FALSE(safe_strto64_base("9223372036854775808", &value, 10));
-  EXPECT_EQ(std::numeric_limits<int64_t>::max(), value);
-
-  EXPECT_TRUE(safe_strto64_base("-9223372036854775808", &value, 10));
-  EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
-
-  EXPECT_FALSE(safe_strto64_base("-9223372036854775809", &value, 10));
-  EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
-}
-
-TEST(stringtest, safe_strto32_leading_substring) {
-  // These tests verify this comment in numbers.h:
-  // On error, returns false, and sets *value to: [...]
-  //   conversion of leading substring if available ("123@@@" -> 123)
-  //   0 if no leading substring available
-  int32_t value;
-  EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 10));
-  EXPECT_EQ(4069, value);
-
-  EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 8));
-  EXPECT_EQ(0406, value);
-
-  EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 10));
-  EXPECT_EQ(4069, value);
-
-  EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 16));
-  EXPECT_EQ(0x4069ba, value);
-
-  EXPECT_FALSE(safe_strto32_base("@@@", &value, 10));
-  EXPECT_EQ(0, value);  // there was no leading substring
-}
-
-TEST(stringtest, safe_strto64_leading_substring) {
-  // These tests verify this comment in numbers.h:
-  // On error, returns false, and sets *value to: [...]
-  //   conversion of leading substring if available ("123@@@" -> 123)
-  //   0 if no leading substring available
-  int64_t value;
-  EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 10));
-  EXPECT_EQ(4069, value);
-
-  EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 8));
-  EXPECT_EQ(0406, value);
-
-  EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 10));
-  EXPECT_EQ(4069, value);
-
-  EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 16));
-  EXPECT_EQ(0x4069ba, value);
-
-  EXPECT_FALSE(safe_strto64_base("@@@", &value, 10));
-  EXPECT_EQ(0, value);  // there was no leading substring
-}
-
 TEST(stringtest, safe_strto64_base) {
   int64_t value;
   EXPECT_TRUE(safe_strto64_base("0x3423432448783446", &value, 16));
@@ -1031,18 +1225,155 @@
   EXPECT_EQ(1234, value);
 }
 
+TEST(stringtest, safe_strto8_range) {
+  // These tests verify underflow/overflow behaviour.
+  int8_t value;
+  EXPECT_FALSE(safe_strto8_base("128", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int8_t>::max(), value);
+
+  EXPECT_TRUE(safe_strto8_base("-128", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int8_t>::min(), value);
+
+  EXPECT_FALSE(safe_strto8_base("-129", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int8_t>::min(), value);
+}
+
+TEST(stringtest, safe_strto16_range) {
+  // These tests verify underflow/overflow behaviour.
+  int16_t value;
+  EXPECT_FALSE(safe_strto16_base("32768", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int16_t>::max(), value);
+
+  EXPECT_TRUE(safe_strto16_base("-32768", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int16_t>::min(), value);
+
+  EXPECT_FALSE(safe_strto16_base("-32769", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int16_t>::min(), value);
+}
+
+TEST(stringtest, safe_strto32_range) {
+  // These tests verify underflow/overflow behaviour.
+  int32_t value;
+  EXPECT_FALSE(safe_strto32_base("2147483648", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int32_t>::max(), value);
+
+  EXPECT_TRUE(safe_strto32_base("-2147483648", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);
+
+  EXPECT_FALSE(safe_strto32_base("-2147483649", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int32_t>::min(), value);
+}
+
+TEST(stringtest, safe_strto64_range) {
+  // These tests verify underflow/overflow behaviour.
+  int64_t value;
+  EXPECT_FALSE(safe_strto64_base("9223372036854775808", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int64_t>::max(), value);
+
+  EXPECT_TRUE(safe_strto64_base("-9223372036854775808", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
+
+  EXPECT_FALSE(safe_strto64_base("-9223372036854775809", &value, 10));
+  EXPECT_EQ(std::numeric_limits<int64_t>::min(), value);
+}
+
+TEST(stringtest, safe_strto8_leading_substring) {
+  // These tests verify this comment in numbers.h:
+  // On error, returns false, and sets *value to: [...]
+  //   conversion of leading substring if available ("123@@@" -> 123)
+  //   0 if no leading substring available
+  int8_t value;
+  EXPECT_FALSE(safe_strto8_base("069@@@", &value, 10));
+  EXPECT_EQ(69, value);
+
+  EXPECT_FALSE(safe_strto8_base("01769@@@", &value, 8));
+  EXPECT_EQ(0176, value);
+
+  EXPECT_FALSE(safe_strto8_base("069balloons", &value, 10));
+  EXPECT_EQ(69, value);
+
+  EXPECT_FALSE(safe_strto8_base("07bland", &value, 16));
+  EXPECT_EQ(0x7b, value);
+
+  EXPECT_FALSE(safe_strto8_base("@@@", &value, 10));
+  EXPECT_EQ(0, value);  // there was no leading substring
+}
+
+TEST(stringtest, safe_strto16_leading_substring) {
+  // These tests verify this comment in numbers.h:
+  // On error, returns false, and sets *value to: [...]
+  //   conversion of leading substring if available ("123@@@" -> 123)
+  //   0 if no leading substring available
+  int16_t value;
+  EXPECT_FALSE(safe_strto16_base("04069@@@", &value, 10));
+  EXPECT_EQ(4069, value);
+
+  EXPECT_FALSE(safe_strto16_base("04069@@@", &value, 8));
+  EXPECT_EQ(0406, value);
+
+  EXPECT_FALSE(safe_strto16_base("04069balloons", &value, 10));
+  EXPECT_EQ(4069, value);
+
+  EXPECT_FALSE(safe_strto16_base("069balloons", &value, 16));
+  EXPECT_EQ(0x69ba, value);
+
+  EXPECT_FALSE(safe_strto16_base("@@@", &value, 10));
+  EXPECT_EQ(0, value);  // there was no leading substring
+}
+
+TEST(stringtest, safe_strto32_leading_substring) {
+  // These tests verify this comment in numbers.h:
+  // On error, returns false, and sets *value to: [...]
+  //   conversion of leading substring if available ("123@@@" -> 123)
+  //   0 if no leading substring available
+  int32_t value;
+  EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 10));
+  EXPECT_EQ(4069, value);
+
+  EXPECT_FALSE(safe_strto32_base("04069@@@", &value, 8));
+  EXPECT_EQ(0406, value);
+
+  EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 10));
+  EXPECT_EQ(4069, value);
+
+  EXPECT_FALSE(safe_strto32_base("04069balloons", &value, 16));
+  EXPECT_EQ(0x4069ba, value);
+
+  EXPECT_FALSE(safe_strto32_base("@@@", &value, 10));
+  EXPECT_EQ(0, value);  // there was no leading substring
+}
+
+TEST(stringtest, safe_strto64_leading_substring) {
+  // These tests verify this comment in numbers.h:
+  // On error, returns false, and sets *value to: [...]
+  //   conversion of leading substring if available ("123@@@" -> 123)
+  //   0 if no leading substring available
+  int64_t value;
+  EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 10));
+  EXPECT_EQ(4069, value);
+
+  EXPECT_FALSE(safe_strto64_base("04069@@@", &value, 8));
+  EXPECT_EQ(0406, value);
+
+  EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 10));
+  EXPECT_EQ(4069, value);
+
+  EXPECT_FALSE(safe_strto64_base("04069balloons", &value, 16));
+  EXPECT_EQ(0x4069ba, value);
+
+  EXPECT_FALSE(safe_strto64_base("@@@", &value, 10));
+  EXPECT_EQ(0, value);  // there was no leading substring
+}
+
 const size_t kNumRandomTests = 10000;
 
-template <typename IntType>
-void test_random_integer_parse_base(bool (*parse_func)(absl::string_view,
-                                                       IntType* value,
-                                                       int base)) {
-  using RandomEngine = std::minstd_rand0;
-  std::random_device rd;
-  RandomEngine rng(rd());
+template <typename IntType,
+          bool parse_func(absl::string_view, IntType* value, int base)>
+void test_random_integer_parse_base() {
+  absl::InsecureBitGen rng;
   std::uniform_int_distribution<IntType> random_int(
       std::numeric_limits<IntType>::min());
-  std::uniform_int_distribution<int> random_base(2, 35);
+  std::uniform_int_distribution<int> random_base(2, 36);
   for (size_t i = 0; i < kNumRandomTests; i++) {
     IntType value = random_int(rng);
     int base = random_base(rng);
@@ -1070,33 +1401,36 @@
   }
 }
 
+TEST(stringtest, safe_strto16_random) {
+  test_random_integer_parse_base<int16_t, safe_strto16_base>();
+}
 TEST(stringtest, safe_strto32_random) {
-  test_random_integer_parse_base<int32_t>(&safe_strto32_base);
+  test_random_integer_parse_base<int32_t, safe_strto32_base>();
 }
 TEST(stringtest, safe_strto64_random) {
-  test_random_integer_parse_base<int64_t>(&safe_strto64_base);
+  test_random_integer_parse_base<int64_t, safe_strto64_base>();
+}
+TEST(stringtest, safe_strtou16_random) {
+  test_random_integer_parse_base<uint16_t, safe_strtou16_base>();
 }
 TEST(stringtest, safe_strtou32_random) {
-  test_random_integer_parse_base<uint32_t>(&safe_strtou32_base);
+  test_random_integer_parse_base<uint32_t, safe_strtou32_base>();
 }
 TEST(stringtest, safe_strtou64_random) {
-  test_random_integer_parse_base<uint64_t>(&safe_strtou64_base);
+  test_random_integer_parse_base<uint64_t, safe_strtou64_base>();
 }
 TEST(stringtest, safe_strtou128_random) {
-  // random number generators don't work for uint128, and
-  // uint128 can be streamed but not StrCat'd, so this code must be custom
+  // random number generators don't work for uint128 so this code must be custom
   // implemented for uint128, but is generally the same as what's above.
   // test_random_integer_parse_base<absl::uint128>(
   //     &absl::numbers_internal::safe_strtou128_base);
-  using RandomEngine = std::minstd_rand0;
   using IntType = absl::uint128;
   constexpr auto parse_func = &absl::numbers_internal::safe_strtou128_base;
 
-  std::random_device rd;
-  RandomEngine rng(rd());
+  absl::InsecureBitGen rng;
   std::uniform_int_distribution<uint64_t> random_uint64(
       std::numeric_limits<uint64_t>::min());
-  std::uniform_int_distribution<int> random_base(2, 35);
+  std::uniform_int_distribution<int> random_base(2, 36);
 
   for (size_t i = 0; i < kNumRandomTests; i++) {
     IntType value = random_uint64(rng);
@@ -1111,34 +1445,28 @@
     EXPECT_EQ(parsed_value, value);
 
     // Test overflow
-    std::string s;
-    absl::strings_internal::OStringStream(&s)
-        << std::numeric_limits<IntType>::max() << value;
-    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+    EXPECT_FALSE(
+        parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),
+                   &parsed_value, base));
 
     // Test underflow
-    s.clear();
-    absl::strings_internal::OStringStream(&s) << "-" << value;
-    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+    EXPECT_FALSE(parse_func(absl::StrCat("-", value), &parsed_value, base));
   }
 }
 TEST(stringtest, safe_strto128_random) {
-  // random number generators don't work for int128, and
-  // int128 can be streamed but not StrCat'd, so this code must be custom
+  // random number generators don't work for int128 so this code must be custom
   // implemented for int128, but is generally the same as what's above.
   // test_random_integer_parse_base<absl::int128>(
   //     &absl::numbers_internal::safe_strto128_base);
-  using RandomEngine = std::minstd_rand0;
   using IntType = absl::int128;
   constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base;
 
-  std::random_device rd;
-  RandomEngine rng(rd());
+  absl::InsecureBitGen rng;
   std::uniform_int_distribution<int64_t> random_int64(
       std::numeric_limits<int64_t>::min());
   std::uniform_int_distribution<uint64_t> random_uint64(
       std::numeric_limits<uint64_t>::min());
-  std::uniform_int_distribution<int> random_base(2, 35);
+  std::uniform_int_distribution<int> random_base(2, 36);
 
   for (size_t i = 0; i < kNumRandomTests; ++i) {
     int64_t high = random_int64(rng);
@@ -1155,16 +1483,70 @@
     EXPECT_EQ(parsed_value, value);
 
     // Test overflow
-    std::string s;
-    absl::strings_internal::OStringStream(&s)
-        << std::numeric_limits<IntType>::max() << value;
-    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+    EXPECT_FALSE(
+        parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),
+                   &parsed_value, base));
 
     // Test underflow
-    s.clear();
-    absl::strings_internal::OStringStream(&s)
-        << std::numeric_limits<IntType>::min() << value;
-    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+    EXPECT_FALSE(
+        parse_func(absl::StrCat(std::numeric_limits<IntType>::min(), value),
+                   &parsed_value, base));
+  }
+}
+
+TEST(stringtest, safe_strtou8_exhaustive) {
+  // Testing the entire space for uint8_t since it is small.
+  using IntType = uint8_t;
+  constexpr auto parse_func = &absl::numbers_internal::safe_strtou8_base;
+
+  for (int i = std::numeric_limits<IntType>::min();
+       i <= std::numeric_limits<IntType>::max(); i++) {
+    IntType value = static_cast<IntType>(i);
+    for (int base = 2; base <= 36; base++) {
+      std::string str_value;
+      EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
+      IntType parsed_value;
+
+      // Test successful parse
+      EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
+      EXPECT_EQ(parsed_value, value);
+
+      // Test overflow
+      EXPECT_FALSE(
+          parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),
+                     &parsed_value, base));
+      // Test underflow
+      EXPECT_FALSE(parse_func(absl::StrCat("-", value), &parsed_value, base));
+    }
+  }
+}
+
+TEST(stringtest, safe_strto8_exhaustive) {
+  // Testing the entire space for int8_t since it is small.
+  using IntType = int8_t;
+  constexpr auto parse_func = &absl::numbers_internal::safe_strto8_base;
+
+  for (int i = std::numeric_limits<IntType>::min();
+       i <= std::numeric_limits<IntType>::max(); i++) {
+    IntType value = static_cast<IntType>(i);
+    for (int base = 2; base <= 36; base++) {
+      std::string str_value;
+      EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
+      IntType parsed_value;
+
+      // Test successful parse
+      EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
+      EXPECT_EQ(parsed_value, value);
+
+      // Test overflow
+      EXPECT_FALSE(
+          parse_func(absl::StrCat(std::numeric_limits<IntType>::max(), value),
+                     &parsed_value, base));
+      // Test underflow
+      EXPECT_FALSE(
+          parse_func(absl::StrCat(std::numeric_limits<IntType>::min(), value),
+                     &parsed_value, base));
+    }
   }
 }
 
@@ -1434,6 +1816,134 @@
   }
 }
 
+TEST(StrToInt8, Partial) {
+  struct Int8TestLine {
+    std::string input;
+    bool status;
+    int8_t value;
+  };
+  const int8_t int8_min = std::numeric_limits<int8_t>::min();
+  const int8_t int8_max = std::numeric_limits<int8_t>::max();
+  Int8TestLine int8_test_line[] = {
+      {"", false, 0},
+      {" ", false, 0},
+      {"-", false, 0},
+      {"123@@@", false, 123},
+      {absl::StrCat(int8_min, int8_max), false, int8_min},
+      {absl::StrCat(int8_max, int8_max), false, int8_max},
+  };
+
+  for (const Int8TestLine& test_line : int8_test_line) {
+    int8_t value = -2;
+    bool status = safe_strto8_base(test_line.input, &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+    value = -2;
+    status = safe_strto8_base(test_line.input, &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+    value = -2;
+    status = safe_strto8_base(absl::string_view(test_line.input), &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+  }
+}
+
+TEST(StrToUint8, Partial) {
+  struct Uint8TestLine {
+    std::string input;
+    bool status;
+    uint8_t value;
+  };
+  const uint8_t uint8_max = std::numeric_limits<uint8_t>::max();
+  Uint8TestLine uint8_test_line[] = {
+      {"", false, 0},
+      {" ", false, 0},
+      {"-", false, 0},
+      {"123@@@", false, 123},
+      {absl::StrCat(uint8_max, uint8_max), false, uint8_max},
+  };
+
+  for (const Uint8TestLine& test_line : uint8_test_line) {
+    uint8_t value = 2;
+    bool status = safe_strtou8_base(test_line.input, &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+    value = 2;
+    status = safe_strtou8_base(test_line.input, &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+    value = 2;
+    status = safe_strtou8_base(absl::string_view(test_line.input), &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+  }
+}
+
+TEST(StrToInt16, Partial) {
+  struct Int16TestLine {
+    std::string input;
+    bool status;
+    int16_t value;
+  };
+  const int16_t int16_min = std::numeric_limits<int16_t>::min();
+  const int16_t int16_max = std::numeric_limits<int16_t>::max();
+  Int16TestLine int16_test_line[] = {
+      {"", false, 0},
+      {" ", false, 0},
+      {"-", false, 0},
+      {"123@@@", false, 123},
+      {absl::StrCat(int16_min, int16_max), false, int16_min},
+      {absl::StrCat(int16_max, int16_max), false, int16_max},
+  };
+
+  for (const Int16TestLine& test_line : int16_test_line) {
+    int16_t value = -2;
+    bool status = safe_strto16_base(test_line.input, &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+    value = -2;
+    status = safe_strto16_base(test_line.input, &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+    value = -2;
+    status = safe_strto16_base(absl::string_view(test_line.input), &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+  }
+}
+
+TEST(StrToUint16, Partial) {
+  struct Uint16TestLine {
+    std::string input;
+    bool status;
+    uint16_t value;
+  };
+  const uint16_t uint16_max = std::numeric_limits<uint16_t>::max();
+  Uint16TestLine uint16_test_line[] = {
+      {"", false, 0},
+      {" ", false, 0},
+      {"-", false, 0},
+      {"123@@@", false, 123},
+      {absl::StrCat(uint16_max, uint16_max), false, uint16_max},
+  };
+
+  for (const Uint16TestLine& test_line : uint16_test_line) {
+    uint16_t value = 2;
+    bool status = safe_strtou16_base(test_line.input, &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+    value = 2;
+    status = safe_strtou16_base(test_line.input, &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+    value = 2;
+    status = safe_strtou16_base(absl::string_view(test_line.input), &value, 10);
+    EXPECT_EQ(test_line.status, status) << test_line.input;
+    EXPECT_EQ(test_line.value, value) << test_line.input;
+  }
+}
+
 TEST(StrToInt32, Partial) {
   struct Int32TestLine {
     std::string input;
@@ -1731,6 +2241,10 @@
 }
 
 TEST(FastIntToBuffer, WritesNull) {
+  ExpectWritesNull<int8_t>();
+  ExpectWritesNull<uint8_t>();
+  ExpectWritesNull<int16_t>();
+  ExpectWritesNull<uint16_t>();
   ExpectWritesNull<int32_t>();
   ExpectWritesNull<uint32_t>();
   ExpectWritesNull<int64_t>();
diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc
index c51c137..1f3cfbf 100644
--- a/absl/strings/str_cat.cc
+++ b/absl/strings/str_cat.cc
@@ -42,8 +42,7 @@
 namespace {
 // Append is merely a version of memcpy that returns the address of the byte
 // after the area just overwritten.
-inline absl::Nonnull<char*> Append(absl::Nonnull<char*> out,
-                                   const AlphaNum& x) {
+inline char* absl_nonnull Append(char* absl_nonnull out, const AlphaNum& x) {
   // memcpy is allowed to overwrite arbitrary memory, so doing this after the
   // call would force an extra fetch of x.size().
   char* after = out + x.size();
@@ -159,7 +158,7 @@
   assert(((src).size() == 0) ||      \
          (uintptr_t((src).data() - (dest).data()) > uintptr_t((dest).size())))
 
-void AppendPieces(absl::Nonnull<std::string*> dest,
+void AppendPieces(std::string* absl_nonnull dest,
                   std::initializer_list<absl::string_view> pieces) {
   size_t old_size = dest->size();
   size_t to_append = 0;
@@ -183,7 +182,7 @@
 
 }  // namespace strings_internal
 
-void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a) {
+void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a) {
   ASSERT_NO_OVERLAP(*dest, a);
   std::string::size_type old_size = dest->size();
   STLStringAppendUninitializedAmortized(dest, a.size());
@@ -193,7 +192,7 @@
   assert(out == begin + dest->size());
 }
 
-void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
+void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
                const AlphaNum& b) {
   ASSERT_NO_OVERLAP(*dest, a);
   ASSERT_NO_OVERLAP(*dest, b);
@@ -206,7 +205,7 @@
   assert(out == begin + dest->size());
 }
 
-void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
+void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
                const AlphaNum& b, const AlphaNum& c) {
   ASSERT_NO_OVERLAP(*dest, a);
   ASSERT_NO_OVERLAP(*dest, b);
@@ -221,7 +220,7 @@
   assert(out == begin + dest->size());
 }
 
-void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
+void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
                const AlphaNum& b, const AlphaNum& c, const AlphaNum& d) {
   ASSERT_NO_OVERLAP(*dest, a);
   ASSERT_NO_OVERLAP(*dest, b);
diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h
index b98adc0..84db0f6 100644
--- a/absl/strings/str_cat.h
+++ b/absl/strings/str_cat.h
@@ -101,6 +101,7 @@
 #include <vector>
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/nullability.h"
 #include "absl/base/port.h"
 #include "absl/meta/type_traits.h"
@@ -110,6 +111,10 @@
 #include "absl/strings/numbers.h"
 #include "absl/strings/string_view.h"
 
+#if !defined(ABSL_USES_STD_STRING_VIEW)
+#include <string_view>
+#endif
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
@@ -186,29 +191,29 @@
   template <typename Int>
   explicit Hex(
       Int v, PadSpec spec = absl::kNoPad,
-      typename std::enable_if<sizeof(Int) == 1 &&
-                              !std::is_pointer<Int>::value>::type* = nullptr)
+      std::enable_if_t<sizeof(Int) == 1 && !std::is_pointer<Int>::value, bool> =
+          true)
       : Hex(spec, static_cast<uint8_t>(v)) {}
   template <typename Int>
   explicit Hex(
       Int v, PadSpec spec = absl::kNoPad,
-      typename std::enable_if<sizeof(Int) == 2 &&
-                              !std::is_pointer<Int>::value>::type* = nullptr)
+      std::enable_if_t<sizeof(Int) == 2 && !std::is_pointer<Int>::value, bool> =
+          true)
       : Hex(spec, static_cast<uint16_t>(v)) {}
   template <typename Int>
   explicit Hex(
       Int v, PadSpec spec = absl::kNoPad,
-      typename std::enable_if<sizeof(Int) == 4 &&
-                              !std::is_pointer<Int>::value>::type* = nullptr)
+      std::enable_if_t<sizeof(Int) == 4 && !std::is_pointer<Int>::value, bool> =
+          true)
       : Hex(spec, static_cast<uint32_t>(v)) {}
   template <typename Int>
   explicit Hex(
       Int v, PadSpec spec = absl::kNoPad,
-      typename std::enable_if<sizeof(Int) == 8 &&
-                              !std::is_pointer<Int>::value>::type* = nullptr)
+      std::enable_if_t<sizeof(Int) == 8 && !std::is_pointer<Int>::value, bool> =
+          true)
       : Hex(spec, static_cast<uint64_t>(v)) {}
   template <typename Pointee>
-  explicit Hex(absl::Nullable<Pointee*> v, PadSpec spec = absl::kNoPad)
+  explicit Hex(Pointee* absl_nullable v, PadSpec spec = absl::kNoPad)
       : Hex(spec, reinterpret_cast<uintptr_t>(v)) {}
 
   template <typename S>
@@ -257,7 +262,7 @@
 
   template <typename Int>
   explicit Dec(Int v, PadSpec spec = absl::kNoPad,
-               typename std::enable_if<(sizeof(Int) <= 8)>::type* = nullptr)
+               std::enable_if_t<sizeof(Int) <= 8, bool> = true)
       : value(v >= 0 ? static_cast<uint64_t>(v)
                      : uint64_t{0} - static_cast<uint64_t>(v)),
         width(spec == absl::kNoPad       ? 1
@@ -354,13 +359,19 @@
           ABSL_ATTRIBUTE_LIFETIME_BOUND)
       : piece_(&buf.data[0], buf.size) {}
 
-  AlphaNum(absl::Nullable<const char*> c_str  // NOLINT(runtime/explicit)
+  AlphaNum(const char* absl_nullable c_str  // NOLINT(runtime/explicit)
                ABSL_ATTRIBUTE_LIFETIME_BOUND)
       : piece_(NullSafeStringView(c_str)) {}
   AlphaNum(absl::string_view pc  // NOLINT(runtime/explicit)
                ABSL_ATTRIBUTE_LIFETIME_BOUND)
       : piece_(pc) {}
 
+#if !defined(ABSL_USES_STD_STRING_VIEW)
+  AlphaNum(std::string_view pc  // NOLINT(runtime/explicit)
+               ABSL_ATTRIBUTE_LIFETIME_BOUND)
+      : piece_(pc.data(), pc.size()) {}
+#endif  // !ABSL_USES_STD_STRING_VIEW
+
   template <typename T, typename = typename std::enable_if<
                             HasAbslStringify<T>::value>::type>
   AlphaNum(  // NOLINT(runtime/explicit)
@@ -381,7 +392,7 @@
   AlphaNum& operator=(const AlphaNum&) = delete;
 
   absl::string_view::size_type size() const { return piece_.size(); }
-  absl::Nullable<const char*> data() const { return piece_.data(); }
+  const char* absl_nullable data() const { return piece_.data(); }
   absl::string_view Piece() const { return piece_; }
 
   // Match unscoped enums.  Use integral promotion so that a `char`-backed
@@ -451,7 +462,7 @@
 
 // Do not call directly - this is not part of the public API.
 std::string CatPieces(std::initializer_list<absl::string_view> pieces);
-void AppendPieces(absl::Nonnull<std::string*> dest,
+void AppendPieces(std::string* absl_nonnull dest,
                   std::initializer_list<absl::string_view> pieces);
 
 template <typename Integer>
@@ -527,28 +538,28 @@
 
 }  // namespace strings_internal
 
-ABSL_MUST_USE_RESULT inline std::string StrCat() { return std::string(); }
+[[nodiscard]] inline std::string StrCat() { return std::string(); }
 
 template <typename T>
-ABSL_MUST_USE_RESULT inline std::string StrCat(
+[[nodiscard]] inline std::string StrCat(
     strings_internal::EnableIfFastCase<T> a) {
   return strings_internal::SingleArgStrCat(a);
 }
-ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a) {
+[[nodiscard]] inline std::string StrCat(const AlphaNum& a) {
   return std::string(a.data(), a.size());
 }
 
-ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
-ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
-                                        const AlphaNum& c);
-ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
-                                        const AlphaNum& c, const AlphaNum& d);
+[[nodiscard]] std::string StrCat(const AlphaNum& a, const AlphaNum& b);
+[[nodiscard]] std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                 const AlphaNum& c);
+[[nodiscard]] std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                 const AlphaNum& c, const AlphaNum& d);
 
 // Support 5 or more arguments
 template <typename... AV>
-ABSL_MUST_USE_RESULT inline std::string StrCat(
-    const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
-    const AlphaNum& e, const AV&... args) {
+[[nodiscard]] inline std::string StrCat(const AlphaNum& a, const AlphaNum& b,
+                                        const AlphaNum& c, const AlphaNum& d,
+                                        const AlphaNum& e, const AV&... args) {
   return strings_internal::CatPieces(
       {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
        static_cast<const AlphaNum&>(args).Piece()...});
@@ -581,18 +592,18 @@
 //   absl::string_view p = s;
 //   StrAppend(&s, p);
 
-inline void StrAppend(absl::Nonnull<std::string*>) {}
-void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a);
-void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
+inline void StrAppend(std::string* absl_nonnull) {}
+void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a);
+void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
                const AlphaNum& b);
-void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
+void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
                const AlphaNum& b, const AlphaNum& c);
-void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
+void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
                const AlphaNum& b, const AlphaNum& c, const AlphaNum& d);
 
 // Support 5 or more arguments
 template <typename... AV>
-inline void StrAppend(absl::Nonnull<std::string*> dest, const AlphaNum& a,
+inline void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
                       const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
                       const AlphaNum& e, const AV&... args) {
   strings_internal::AppendPieces(
diff --git a/absl/strings/str_cat_benchmark.cc b/absl/strings/str_cat_benchmark.cc
index 0a851e7..7695e8f 100644
--- a/absl/strings/str_cat_benchmark.cc
+++ b/absl/strings/str_cat_benchmark.cc
@@ -21,12 +21,13 @@
 #include <tuple>
 #include <utility>
 
-#include "benchmark/benchmark.h"
 #include "absl/random/log_uniform_int_distribution.h"
 #include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 #include "absl/strings/string_view.h"
 #include "absl/strings/substitute.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
@@ -111,6 +112,17 @@
 }
 BENCHMARK(BM_HexCat_By_StrCat);
 
+void BM_HexCat_By_StrFormat(benchmark::State& state) {
+  int i = 0;
+  for (auto _ : state) {
+    std::string result =
+        absl::StrFormat("%s %x", kStringOne, int64_t{i} + 0x10000000);
+    benchmark::DoNotOptimize(result);
+    i = IncrementAlternatingSign(i);
+  }
+}
+BENCHMARK(BM_HexCat_By_StrFormat);
+
 void BM_HexCat_By_Substitute(benchmark::State& state) {
   int i = 0;
   for (auto _ : state) {
@@ -145,6 +157,18 @@
 }
 BENCHMARK(BM_DoubleToString_By_SixDigits);
 
+void BM_FloatToString_By_StrFormat(benchmark::State& state) {
+  int i = 0;
+  float foo = 0.0f;
+  for (auto _ : state) {
+    std::string result =
+        absl::StrFormat("%f != %lld", foo += 1.001f, int64_t{i});
+    benchmark::DoNotOptimize(result);
+    i = IncrementAlternatingSign(i);
+  }
+}
+BENCHMARK(BM_FloatToString_By_StrFormat);
+
 template <typename Table, size_t... Index>
 void BM_StrAppendImpl(benchmark::State& state, Table table, size_t total_bytes,
                       std::index_sequence<Index...>) {
diff --git a/absl/strings/str_cat_test.cc b/absl/strings/str_cat_test.cc
index 66eddf0..a3bd42c 100644
--- a/absl/strings/str_cat_test.cc
+++ b/absl/strings/str_cat_test.cc
@@ -21,9 +21,11 @@
 #include <cstdlib>
 #include <limits>
 #include <string>
+#include <string_view>
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/string_view.h"
 
@@ -73,7 +75,7 @@
 TEST(StrCat, Enums) {
   enum SmallNumbers { One = 1, Ten = 10 } e = Ten;
   EXPECT_EQ("10", absl::StrCat(e));
-  EXPECT_EQ("-5", absl::StrCat(SmallNumbers(-5)));
+  EXPECT_EQ("1", absl::StrCat(One));
 
   enum class Option { Boxers = 1, Briefs = -1 };
 
@@ -214,6 +216,12 @@
   EXPECT_EQ(result, "");
 }
 
+TEST(StrCat, StdStringView) {
+  std::string_view pieces[] = {"Hello", ", ", "World", "!"};
+  EXPECT_EQ(absl::StrCat(pieces[0], pieces[1], pieces[2], pieces[3]),
+                         "Hello, World!");
+}
+
 TEST(StrCat, NullConstCharPtr) {
   const char* null = nullptr;
   EXPECT_EQ(absl::StrCat("mon", null, "key"), "monkey");
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h
index 76904d3..ffa7f11 100644
--- a/absl/strings/str_format.h
+++ b/absl/strings/str_format.h
@@ -112,7 +112,7 @@
 
  protected:
   explicit UntypedFormatSpec(
-      absl::Nonnull<const str_format_internal::ParsedFormatBase*> pc)
+      const str_format_internal::ParsedFormatBase* absl_nonnull pc)
       : spec_(pc) {}
 
  private:
@@ -152,7 +152,7 @@
 //   EXPECT_EQ(8, n);
 class FormatCountCapture {
  public:
-  explicit FormatCountCapture(absl::Nonnull<int*> p) : p_(p) {}
+  explicit FormatCountCapture(int* absl_nonnull p) : p_(p) {}
 
  private:
   // FormatCountCaptureHelper is used to define FormatConvertImpl() for this
@@ -161,8 +161,8 @@
   // Unused() is here because of the false positive from -Wunused-private-field
   // p_ is used in the templated function of the friend FormatCountCaptureHelper
   // class.
-  absl::Nonnull<int*> Unused() { return p_; }
-  absl::Nonnull<int*> p_;
+  int* absl_nonnull Unused() { return p_; }
+  int* absl_nonnull p_;
 };
 
 // FormatSpec
@@ -359,8 +359,8 @@
 //
 // Returns an empty string in case of error.
 template <typename... Args>
-ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format,
-                                           const Args&... args) {
+[[nodiscard]] std::string StrFormat(const FormatSpec<Args...>& format,
+                                    const Args&... args) {
   return str_format_internal::FormatPack(
       str_format_internal::UntypedFormatSpecImpl::Extract(format),
       {str_format_internal::FormatArgImpl(args)...});
@@ -377,7 +377,7 @@
 //   std::string orig("For example PI is approximately ");
 //   std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
 template <typename... Args>
-std::string& StrAppendFormat(absl::Nonnull<std::string*> dst,
+std::string& StrAppendFormat(std::string* absl_nonnull dst,
                              const FormatSpec<Args...>& format,
                              const Args&... args) {
   return str_format_internal::AppendPack(
@@ -396,7 +396,7 @@
 //
 //   std::cout << StreamFormat("%12.6f", 3.14);
 template <typename... Args>
-ABSL_MUST_USE_RESULT str_format_internal::Streamable StreamFormat(
+[[nodiscard]] str_format_internal::Streamable StreamFormat(
     const FormatSpec<Args...>& format, const Args&... args) {
   return str_format_internal::Streamable(
       str_format_internal::UntypedFormatSpecImpl::Extract(format),
@@ -437,7 +437,7 @@
 //   Outputs: "The capital of Mongolia is Ulaanbaatar"
 //
 template <typename... Args>
-int FPrintF(absl::Nonnull<std::FILE*> output, const FormatSpec<Args...>& format,
+int FPrintF(std::FILE* absl_nonnull output, const FormatSpec<Args...>& format,
             const Args&... args) {
   return str_format_internal::FprintF(
       output, str_format_internal::UntypedFormatSpecImpl::Extract(format),
@@ -466,7 +466,7 @@
 //   Post-condition: output == "The capital of Mongolia is Ulaanbaatar"
 //
 template <typename... Args>
-int SNPrintF(absl::Nonnull<char*> output, std::size_t size,
+int SNPrintF(char* absl_nonnull output, std::size_t size,
              const FormatSpec<Args...>& format, const Args&... args) {
   return str_format_internal::SnprintF(
       output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format),
@@ -500,7 +500,7 @@
   template <typename T,
             typename = typename std::enable_if<std::is_constructible<
                 str_format_internal::FormatRawSinkImpl, T*>::value>::type>
-  FormatRawSink(absl::Nonnull<T*> raw)  // NOLINT
+  FormatRawSink(T* absl_nonnull raw)  // NOLINT
       : sink_(raw) {}
 
  private:
@@ -582,9 +582,9 @@
 //     return std::move(out);
 //   }
 //
-ABSL_MUST_USE_RESULT inline bool FormatUntyped(
-    FormatRawSink raw_sink, const UntypedFormatSpec& format,
-    absl::Span<const FormatArg> args) {
+[[nodiscard]] inline bool FormatUntyped(FormatRawSink raw_sink,
+                                        const UntypedFormatSpec& format,
+                                        absl::Span<const FormatArg> args) {
   return str_format_internal::FormatUntyped(
       str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
       str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
@@ -609,7 +609,7 @@
 //
 // Note that unlike with AbslFormatConvert(), AbslStringify() does not allow
 // customization of allowed conversion characters. AbslStringify() uses `%v` as
-// the underlying conversion specififer. Additionally, AbslStringify() supports
+// the underlying conversion specifier. Additionally, AbslStringify() supports
 // use with absl::StrCat while AbslFormatConvert() does not.
 //
 // Example:
@@ -857,16 +857,16 @@
   }
 
   // Support `absl::Format(&sink, format, args...)`.
-  friend void AbslFormatFlush(absl::Nonnull<FormatSink*> sink,
+  friend void AbslFormatFlush(FormatSink* absl_nonnull sink,
                               absl::string_view v) {
     sink->Append(v);
   }
 
  private:
   friend str_format_internal::FormatSinkImpl;
-  explicit FormatSink(absl::Nonnull<str_format_internal::FormatSinkImpl*> s)
+  explicit FormatSink(str_format_internal::FormatSinkImpl* absl_nonnull s)
       : sink_(s) {}
-  absl::Nonnull<str_format_internal::FormatSinkImpl*> sink_;
+  str_format_internal::FormatSinkImpl* absl_nonnull sink_;
 };
 
 // FormatConvertResult
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index 3c52be1..969e1f9 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -516,7 +516,13 @@
   EXPECT_EQ(result, 17);
   EXPECT_EQ(std::string(buffer), "NUMBER: 1234567");
 
-  result = SNPrintF(nullptr, 0, "Just checking the %s of the output.", "size");
+  // The `output` parameter is annotated nonnull, but we want to test that
+  // it is never written to if the size is zero.
+  // Use a variable instead of passing nullptr directly to avoid a `-Wnonnull`
+  // warning.
+  char* null_output = nullptr;
+  result =
+      SNPrintF(null_output, 0, "Just checking the %s of the output.", "size");
   EXPECT_EQ(result, 37);
 }
 
@@ -545,7 +551,13 @@
 
   std::string size = "size";
 
-  result = SNPrintF(nullptr, 0, "Just checking the %v of the output.", size);
+  // The `output` parameter is annotated nonnull, but we want to test that
+  // it is never written to if the size is zero.
+  // Use a variable instead of passing nullptr directly to avoid a `-Wnonnull`
+  // warning.
+  char* null_output = nullptr;
+  result =
+      SNPrintF(null_output, 0, "Just checking the %v of the output.", size);
   EXPECT_EQ(result, 37);
 }
 
diff --git a/absl/strings/str_join_benchmark.cc b/absl/strings/str_join_benchmark.cc
index be7a725..ffe6696 100644
--- a/absl/strings/str_join_benchmark.cc
+++ b/absl/strings/str_join_benchmark.cc
@@ -13,13 +13,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/str_join.h"
-
 #include <string>
 #include <tuple>
-#include <vector>
 #include <utility>
+#include <vector>
 
+#include "absl/strings/str_join.h"
 #include "benchmark/benchmark.h"
 
 namespace {
diff --git a/absl/strings/str_replace.cc b/absl/strings/str_replace.cc
index a7ab52f..377e30c 100644
--- a/absl/strings/str_replace.cc
+++ b/absl/strings/str_replace.cc
@@ -37,8 +37,8 @@
 // occurred.
 int ApplySubstitutions(
     absl::string_view s,
-    absl::Nonnull<std::vector<strings_internal::ViableSubstitution>*> subs_ptr,
-    absl::Nonnull<std::string*> result_ptr) {
+    std::vector<strings_internal::ViableSubstitution>* absl_nonnull subs_ptr,
+    std::string* absl_nonnull result_ptr) {
   auto& subs = *subs_ptr;
   int substitutions = 0;
   size_t pos = 0;
@@ -83,7 +83,7 @@
 }
 
 int StrReplaceAll(strings_internal::FixedMapping replacements,
-                  absl::Nonnull<std::string*> target) {
+                  std::string* absl_nonnull target) {
   return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
 }
 
diff --git a/absl/strings/str_replace.h b/absl/strings/str_replace.h
index e77ced3..91b920b 100644
--- a/absl/strings/str_replace.h
+++ b/absl/strings/str_replace.h
@@ -66,7 +66,7 @@
 //        {"$who", "Bob"},
 //        {"#Noun", "Apples"}});
 //   EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
-ABSL_MUST_USE_RESULT std::string StrReplaceAll(
+[[nodiscard]] std::string StrReplaceAll(
     absl::string_view s,
     std::initializer_list<std::pair<absl::string_view, absl::string_view>>
         replacements);
@@ -114,7 +114,7 @@
 int StrReplaceAll(
     std::initializer_list<std::pair<absl::string_view, absl::string_view>>
         replacements,
-    absl::Nonnull<std::string*> target);
+    std::string* absl_nonnull target);
 
 // Overload of `StrReplaceAll()` to replace patterns within a given output
 // string *in place* with replacements provided within a container of key/value
@@ -130,7 +130,7 @@
 //  EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
 template <typename StrToStrMapping>
 int StrReplaceAll(const StrToStrMapping& replacements,
-                  absl::Nonnull<std::string*> target);
+                  std::string* absl_nonnull target);
 
 // Implementation details only, past this point.
 namespace strings_internal {
@@ -187,8 +187,8 @@
 }
 
 int ApplySubstitutions(absl::string_view s,
-                       absl::Nonnull<std::vector<ViableSubstitution>*> subs_ptr,
-                       absl::Nonnull<std::string*> result_ptr);
+                       std::vector<ViableSubstitution>* absl_nonnull subs_ptr,
+                       std::string* absl_nonnull result_ptr);
 
 }  // namespace strings_internal
 
@@ -204,7 +204,7 @@
 
 template <typename StrToStrMapping>
 int StrReplaceAll(const StrToStrMapping& replacements,
-                  absl::Nonnull<std::string*> target) {
+                  std::string* absl_nonnull target) {
   auto subs = strings_internal::FindSubstitutions(*target, replacements);
   if (subs.empty()) return 0;
 
diff --git a/absl/strings/str_replace_benchmark.cc b/absl/strings/str_replace_benchmark.cc
index 01331da..cbe7572 100644
--- a/absl/strings/str_replace_benchmark.cc
+++ b/absl/strings/str_replace_benchmark.cc
@@ -12,13 +12,12 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/str_replace.h"
-
 #include <cstring>
 #include <string>
 
-#include "benchmark/benchmark.h"
 #include "absl/base/internal/raw_logging.h"
+#include "absl/strings/str_replace.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
diff --git a/absl/strings/str_split.h b/absl/strings/str_split.h
index ba176fc..7e8e31c 100644
--- a/absl/strings/str_split.h
+++ b/absl/strings/str_split.h
@@ -444,8 +444,10 @@
 // behavior works for:
 //
 // 1) All standard STL containers including `std::vector`, `std::list`,
-//    `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`
+//    `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`.
 // 2) `std::pair` (which is not actually a container). See below.
+// 3) `std::array`, which is a container but has different behavior due to its
+//    fixed size. See below.
 //
 // Example:
 //
@@ -487,6 +489,21 @@
 //   std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ',');
 //   // p.first == "a", p.second == "b"       // "c" is omitted.
 //
+//
+// Splitting to `std::array` is similar to splitting to `std::pair`, but for
+// N elements instead of two; missing elements are filled with the empty string
+// and extra elements are discarded.
+//
+// Examples:
+//
+//   // Stores first two split strings as the elements in a std::array.
+//   std::array<std::string, 2> a = absl::StrSplit("a,b,c", ',');
+//   // a[0] == "a", a[1] == "b"   // "c" is omitted.
+//
+//   // The second element is empty.
+//   std::array<std::string, 2> a = absl::StrSplit("a,", ',');
+//   // a[0] == "a", a[1] == ""
+//
 // The `StrSplit()` function can be used multiple times to perform more
 // complicated splitting logic, such as intelligently parsing key-value pairs.
 //
diff --git a/absl/strings/str_split_benchmark.cc b/absl/strings/str_split_benchmark.cc
index 003a66b..5a2e953 100644
--- a/absl/strings/str_split_benchmark.cc
+++ b/absl/strings/str_split_benchmark.cc
@@ -12,8 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/str_split.h"
-
 #include <cstddef>
 #include <iterator>
 #include <string>
@@ -21,9 +19,10 @@
 #include <unordered_set>
 #include <vector>
 
-#include "benchmark/benchmark.h"
 #include "absl/base/internal/raw_logging.h"
+#include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc
index df6c460..b083975 100644
--- a/absl/strings/str_split_test.cc
+++ b/absl/strings/str_split_test.cc
@@ -14,6 +14,7 @@
 
 #include "absl/strings/str_split.h"
 
+#include <array>
 #include <cstddef>
 #include <cstdint>
 #include <deque>
@@ -397,6 +398,12 @@
   EXPECT_EQ(p, (std::pair<FirstType, SecondType>("a", "b")));
 }
 
+template <typename StringType, typename Splitter>
+void TestArrayConversionOperator(const Splitter& splitter) {
+  std::array<StringType, 2> a = splitter;
+  EXPECT_THAT(a, ElementsAre("a", "b"));
+}
+
 TEST(Splitter, ConversionOperator) {
   auto splitter = absl::StrSplit("a,b,c,d", ',');
 
@@ -467,6 +474,10 @@
   TestPairConversionOperator<absl::string_view, std::string>(splitter);
   TestPairConversionOperator<std::string, absl::string_view>(splitter);
   TestPairConversionOperator<std::string, std::string>(splitter);
+
+  // Tests conversion to std::array
+  TestArrayConversionOperator<std::string>(splitter);
+  TestArrayConversionOperator<absl::string_view>(splitter);
 }
 
 // A few additional tests for conversion to std::pair. This conversion is
@@ -511,6 +522,41 @@
   }
 }
 
+// std::array tests similar to std::pair tests above, testing fewer, exactly,
+// or more elements than the array size.
+TEST(Splitter, ToArray) {
+  {
+    // Empty string
+    std::array<std::string, 2> p = absl::StrSplit("", ',');
+    EXPECT_THAT(p, ElementsAre("", ""));
+  }
+
+  {
+    // Only first
+    std::array<std::string, 2> p = absl::StrSplit("a", ',');
+    EXPECT_THAT(p, ElementsAre("a", ""));
+  }
+
+  {
+    // Only second
+    std::array<std::string, 2> p = absl::StrSplit(",b", ',');
+    EXPECT_THAT(p, ElementsAre("", "b"));
+  }
+
+  {
+    // First and second.
+    std::array<std::string, 2> p = absl::StrSplit("a,b", ',');
+    EXPECT_THAT(p, ElementsAre("a", "b"));
+  }
+
+  {
+    // First and second and then more stuff that will be ignored.
+    std::array<std::string, 2> p = absl::StrSplit("a,b,c", ',');
+    EXPECT_THAT(p, ElementsAre("a", "b"));
+    // "c" is omitted.
+  }
+}
+
 TEST(Splitter, Predicates) {
   static const char kTestChars[] = ",a, ,b,";
   using absl::AllowEmpty;
diff --git a/absl/strings/string_view.cc b/absl/strings/string_view.cc
index 97025c3..33bd1bb 100644
--- a/absl/strings/string_view.cc
+++ b/absl/strings/string_view.cc
@@ -30,10 +30,10 @@
 
 // This is significantly faster for case-sensitive matches with very
 // few possible matches.
-absl::Nullable<const char*> memmatch(absl::Nullable<const char*> phaystack,
-                                     size_t haylen,
-                                     absl::Nullable<const char*> pneedle,
-                                     size_t neelen) {
+const char* absl_nullable memmatch(const char* absl_nullable phaystack,
+                                   size_t haylen,
+                                   const char* absl_nullable pneedle,
+                                   size_t neelen) {
   if (0 == neelen) {
     return phaystack;  // even if haylen is 0
   }
@@ -233,11 +233,6 @@
   return npos;
 }
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr string_view::size_type string_view::npos;
-constexpr string_view::size_type string_view::kMaxSize;
-#endif
-
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index ff76001..9a1933b 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -159,15 +159,15 @@
 //
 //   absl::string_view() == absl::string_view("", 0)
 //   absl::string_view(nullptr, 0) == absl::string_view("abcdef"+6, 0)
-class ABSL_INTERNAL_ATTRIBUTE_VIEW string_view {
+class ABSL_ATTRIBUTE_VIEW string_view {
  public:
   using traits_type = std::char_traits<char>;
   using value_type = char;
-  using pointer = absl::Nullable<char*>;
-  using const_pointer = absl::Nullable<const char*>;
+  using pointer = char* absl_nullable;
+  using const_pointer = const char* absl_nullable;
   using reference = char&;
   using const_reference = const char&;
-  using const_iterator = absl::Nullable<const char*>;
+  using const_iterator = const char* absl_nullable;
   using iterator = const_iterator;
   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
   using reverse_iterator = const_reverse_iterator;
@@ -197,16 +197,15 @@
   // instead (see below).
   // The length check is skipped since it is unnecessary and causes code bloat.
   constexpr string_view(  // NOLINT(runtime/explicit)
-      absl::Nonnull<const char*> str)
+      const char* absl_nonnull str)
       : ptr_(str), length_(str ? StrlenInternal(str) : 0) {}
 
-  // Implicit constructor of a `string_view` from a `const char*` and length.
-  constexpr string_view(absl::Nullable<const char*> data, size_type len)
+  // Constructor of a `string_view` from a `const char*` and length.
+  constexpr string_view(const char* absl_nullable data, size_type len)
       : ptr_(data), length_(CheckLengthInternal(len)) {}
 
-  // NOTE: Harmlessly omitted to work around gdb bug.
-  //   constexpr string_view(const string_view&) noexcept = default;
-  //   string_view& operator=(const string_view&) noexcept = default;
+  constexpr string_view(const string_view&) noexcept = default;
+  string_view& operator=(const string_view&) noexcept = default;
 
   // Iterators
 
@@ -293,7 +292,8 @@
   // Returns the ith element of the `string_view` using the array operator.
   // Note that this operator does not perform any bounds checking.
   constexpr const_reference operator[](size_type i) const {
-    return ABSL_HARDENING_ASSERT(i < size()), ptr_[i];
+    ABSL_HARDENING_ASSERT(i < size());
+    return ptr_[i];
   }
 
   // string_view::at()
@@ -302,25 +302,26 @@
   // and an exception of type `std::out_of_range` will be thrown on invalid
   // access.
   constexpr const_reference at(size_type i) const {
-    return ABSL_PREDICT_TRUE(i < size())
-               ? ptr_[i]
-               : ((void)base_internal::ThrowStdOutOfRange(
-                      "absl::string_view::at"),
-                  ptr_[i]);
+    if (ABSL_PREDICT_FALSE(i >= size())) {
+      base_internal::ThrowStdOutOfRange("absl::string_view::at");
+    }
+    return ptr_[i];
   }
 
   // string_view::front()
   //
   // Returns the first element of a `string_view`.
   constexpr const_reference front() const {
-    return ABSL_HARDENING_ASSERT(!empty()), ptr_[0];
+    ABSL_HARDENING_ASSERT(!empty());
+    return ptr_[0];
   }
 
   // string_view::back()
   //
   // Returns the last element of a `string_view`.
   constexpr const_reference back() const {
-    return ABSL_HARDENING_ASSERT(!empty()), ptr_[size() - 1];
+    ABSL_HARDENING_ASSERT(!empty());
+    return ptr_[size() - 1];
   }
 
   // string_view::data()
@@ -394,11 +395,10 @@
   // `pos > size`.
   // Use absl::ClippedSubstr if you need a truncating substr operation.
   constexpr string_view substr(size_type pos = 0, size_type n = npos) const {
-    return ABSL_PREDICT_FALSE(pos > length_)
-               ? (base_internal::ThrowStdOutOfRange(
-                      "absl::string_view::substr"),
-                  string_view())
-               : string_view(ptr_ + pos, Min(n, length_ - pos));
+    if (ABSL_PREDICT_FALSE(pos > length_)) {
+      base_internal::ThrowStdOutOfRange("absl::string_view::substr");
+    }
+    return string_view(ptr_ + pos, (std::min)(n, length_ - pos));
   }
 
   // string_view::compare()
@@ -409,10 +409,10 @@
   // is greater than `x`.
   constexpr int compare(string_view x) const noexcept {
     return CompareImpl(length_, x.length_,
-                       Min(length_, x.length_) == 0
+                       (std::min)(length_, x.length_) == 0
                            ? 0
                            : ABSL_INTERNAL_STRING_VIEW_MEMCMP(
-                                 ptr_, x.ptr_, Min(length_, x.length_)));
+                                 ptr_, x.ptr_, (std::min)(length_, x.length_)));
   }
 
   // Overload of `string_view::compare()` for comparing a substring of the
@@ -430,21 +430,21 @@
 
   // Overload of `string_view::compare()` for comparing a `string_view` and a
   // a different C-style string `s`.
-  constexpr int compare(absl::Nonnull<const char*> s) const {
+  constexpr int compare(const char* absl_nonnull s) const {
     return compare(string_view(s));
   }
 
   // Overload of `string_view::compare()` for comparing a substring of the
   // `string_view` and a different string C-style string `s`.
   constexpr int compare(size_type pos1, size_type count1,
-                        absl::Nonnull<const char*> s) const {
+                        const char* absl_nonnull s) const {
     return substr(pos1, count1).compare(string_view(s));
   }
 
   // Overload of `string_view::compare()` for comparing a substring of the
   // `string_view` and a substring of a different C-style string `s`.
   constexpr int compare(size_type pos1, size_type count1,
-                        absl::Nonnull<const char*> s, size_type count2) const {
+                        const char* absl_nonnull s, size_type count2) const {
     return substr(pos1, count1).compare(string_view(s, count2));
   }
 
@@ -463,14 +463,14 @@
 
   // Overload of `string_view::find()` for finding a substring of a different
   // C-style string `s` within the `string_view`.
-  size_type find(absl::Nonnull<const char*> s, size_type pos,
+  size_type find(const char* absl_nonnull s, size_type pos,
                  size_type count) const {
     return find(string_view(s, count), pos);
   }
 
   // Overload of `string_view::find()` for finding a different C-style string
   // `s` within the `string_view`.
-  size_type find(absl::Nonnull<const char *> s, size_type pos = 0) const {
+  size_type find(const char* absl_nonnull s, size_type pos = 0) const {
     return find(string_view(s), pos);
   }
 
@@ -487,14 +487,14 @@
 
   // Overload of `string_view::rfind()` for finding a substring of a different
   // C-style string `s` within the `string_view`.
-  size_type rfind(absl::Nonnull<const char*> s, size_type pos,
+  size_type rfind(const char* absl_nonnull s, size_type pos,
                   size_type count) const {
     return rfind(string_view(s, count), pos);
   }
 
   // Overload of `string_view::rfind()` for finding a different C-style string
   // `s` within the `string_view`.
-  size_type rfind(absl::Nonnull<const char*> s, size_type pos = npos) const {
+  size_type rfind(const char* absl_nonnull s, size_type pos = npos) const {
     return rfind(string_view(s), pos);
   }
 
@@ -513,15 +513,14 @@
 
   // Overload of `string_view::find_first_of()` for finding a substring of a
   // different C-style string `s` within the `string_view`.
-  size_type find_first_of(absl::Nonnull<const char*> s, size_type pos,
+  size_type find_first_of(const char* absl_nonnull s, size_type pos,
                           size_type count) const {
     return find_first_of(string_view(s, count), pos);
   }
 
   // Overload of `string_view::find_first_of()` for finding a different C-style
   // string `s` within the `string_view`.
-  size_type find_first_of(absl::Nonnull<const char*> s,
-                          size_type pos = 0) const {
+  size_type find_first_of(const char* absl_nonnull s, size_type pos = 0) const {
     return find_first_of(string_view(s), pos);
   }
 
@@ -540,14 +539,14 @@
 
   // Overload of `string_view::find_last_of()` for finding a substring of a
   // different C-style string `s` within the `string_view`.
-  size_type find_last_of(absl::Nonnull<const char*> s, size_type pos,
+  size_type find_last_of(const char* absl_nonnull s, size_type pos,
                          size_type count) const {
     return find_last_of(string_view(s, count), pos);
   }
 
   // Overload of `string_view::find_last_of()` for finding a different C-style
   // string `s` within the `string_view`.
-  size_type find_last_of(absl::Nonnull<const char*> s,
+  size_type find_last_of(const char* absl_nonnull s,
                          size_type pos = npos) const {
     return find_last_of(string_view(s), pos);
   }
@@ -565,14 +564,14 @@
 
   // Overload of `string_view::find_first_not_of()` for finding a substring of a
   // different C-style string `s` within the `string_view`.
-  size_type find_first_not_of(absl::Nonnull<const char*> s, size_type pos,
+  size_type find_first_not_of(const char* absl_nonnull s, size_type pos,
                               size_type count) const {
     return find_first_not_of(string_view(s, count), pos);
   }
 
   // Overload of `string_view::find_first_not_of()` for finding a different
   // C-style string `s` within the `string_view`.
-  size_type find_first_not_of(absl::Nonnull<const char*> s,
+  size_type find_first_not_of(const char* absl_nonnull s,
                               size_type pos = 0) const {
     return find_first_not_of(string_view(s), pos);
   }
@@ -591,14 +590,14 @@
 
   // Overload of `string_view::find_last_not_of()` for finding a substring of a
   // different C-style string `s` within the `string_view`.
-  size_type find_last_not_of(absl::Nonnull<const char*> s, size_type pos,
+  size_type find_last_not_of(const char* absl_nonnull s, size_type pos,
                              size_type count) const {
     return find_last_not_of(string_view(s, count), pos);
   }
 
   // Overload of `string_view::find_last_not_of()` for finding a different
   // C-style string `s` within the `string_view`.
-  size_type find_last_not_of(absl::Nonnull<const char*> s,
+  size_type find_last_not_of(const char* absl_nonnull s,
                              size_type pos = npos) const {
     return find_last_not_of(string_view(s), pos);
   }
@@ -659,7 +658,7 @@
   // The constructor from std::string delegates to this constructor.
   // See the comment on that constructor for the rationale.
   struct SkipCheckLengthTag {};
-  string_view(absl::Nullable<const char*> data, size_type len,
+  string_view(const char* absl_nullable data, size_type len,
               SkipCheckLengthTag) noexcept
       : ptr_(data), length_(len) {}
 
@@ -667,10 +666,11 @@
       (std::numeric_limits<difference_type>::max)();
 
   static constexpr size_type CheckLengthInternal(size_type len) {
-    return ABSL_HARDENING_ASSERT(len <= kMaxSize), len;
+    ABSL_HARDENING_ASSERT(len <= kMaxSize);
+    return len;
   }
 
-  static constexpr size_type StrlenInternal(absl::Nonnull<const char*> str) {
+  static constexpr size_type StrlenInternal(const char* absl_nonnull str) {
 #if defined(_MSC_VER) && !defined(__clang__)
     // MSVC 2017+ can evaluate this at compile-time.
     const char* begin = str;
@@ -688,10 +688,6 @@
 #endif
   }
 
-  static constexpr size_t Min(size_type length_a, size_type length_b) {
-    return length_a < length_b ? length_a : length_b;
-  }
-
   static constexpr int CompareImpl(size_type length_a, size_type length_b,
                                    int compare_result) {
     return compare_result == 0 ? static_cast<int>(length_a > length_b) -
@@ -699,7 +695,7 @@
                                : (compare_result < 0 ? -1 : 1);
   }
 
-  absl::Nullable<const char*> ptr_;
+  const char* absl_nullable ptr_;
   size_type length_;
 };
 
@@ -760,7 +756,7 @@
 // Creates an `absl::string_view` from a pointer `p` even if it's null-valued.
 // This function should be used where an `absl::string_view` can be created from
 // a possibly-null pointer.
-constexpr string_view NullSafeStringView(absl::Nullable<const char*> p) {
+constexpr string_view NullSafeStringView(const char* absl_nullable p) {
   return p ? string_view(p) : string_view();
 }
 
diff --git a/absl/strings/string_view_benchmark.cc b/absl/strings/string_view_benchmark.cc
index 98f747c..546f6ed 100644
--- a/absl/strings/string_view_benchmark.cc
+++ b/absl/strings/string_view_benchmark.cc
@@ -12,8 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/strings/string_view.h"
-
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
@@ -23,11 +21,13 @@
 #include <unordered_set>
 #include <vector>
 
-#include "benchmark/benchmark.h"
 #include "absl/base/attributes.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/macros.h"
+#include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
@@ -287,9 +287,7 @@
                          "found", "a",      "large",    "mushroom", "and",
                          "a",     "couple", "crickets", "eating",   "pie"};
   // Create some keys that consist of words in random order.
-  std::random_device r;
-  std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()});
-  std::mt19937 rng(seed);
+  absl::InsecureBitGen rng;
   std::vector<std::string> keys(table_size);
   std::vector<int> all_indices;
   const int kBlockSize = 1 << 12;
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc
index e978fc3..0a2a7a9 100644
--- a/absl/strings/string_view_test.cc
+++ b/absl/strings/string_view_test.cc
@@ -34,7 +34,7 @@
 #include "absl/base/config.h"
 #include "absl/meta/type_traits.h"
 
-#if defined(ABSL_HAVE_STD_STRING_VIEW) || defined(__ANDROID__)
+#if defined(ABSL_USES_STD_STRING_VIEW) || defined(__ANDROID__)
 // We don't control the death messaging when using std::string_view.
 // Android assert messages only go to system log, so death tests cannot inspect
 // the message for matching.
@@ -894,7 +894,11 @@
   EXPECT_EQ(s.size(), 0u);
 
 #ifdef ABSL_HAVE_STRING_VIEW_FROM_NULLPTR
-  s = absl::string_view(nullptr);
+  // The `str` parameter is annotated nonnull, but we want to test the defensive
+  // null check. Use a variable instead of passing nullptr directly to avoid a
+  // `-Wnonnull` warning.
+  char* null_str = nullptr;
+  s = absl::string_view(null_str);
   EXPECT_EQ(s.data(), nullptr);
   EXPECT_EQ(s.size(), 0u);
 
@@ -1076,9 +1080,22 @@
 
 TEST(StringViewTest, ConstexprCompiles) {
   constexpr absl::string_view sp;
+  // With `-Wnonnull` turned on, there is no way to test the defensive null
+  // check in the `string_view(const char*)` constructor in a constexpr context,
+  // as the argument needs to be constexpr. The compiler will therefore always
+  // know at compile time that the argument is nullptr and complain because the
+  // parameter is annotated nonnull. We hence turn the warning off for this
+  // test.
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wnonnull"
+#endif
 #ifdef ABSL_HAVE_STRING_VIEW_FROM_NULLPTR
   constexpr absl::string_view cstr(nullptr);
 #endif
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
   constexpr absl::string_view cstr_len("cstr", 4);
 
 #if defined(ABSL_USES_STD_STRING_VIEW)
@@ -1106,7 +1123,7 @@
 #endif
 
 // MSVC 2017+ should be able to construct a constexpr string_view from a cstr.
-#if defined(_MSC_VER) && _MSC_VER >= 1910
+#if defined(_MSC_VER)
 #define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
 #endif
 
@@ -1142,10 +1159,6 @@
 #endif
 #endif
 
-#if !defined(__clang__) || 3 < __clang_major__ || \
-  (3 == __clang_major__ && 4 < __clang_minor__)
-  // older clang versions (< 3.5) complain that:
-  //   "cannot perform pointer arithmetic on null pointer"
   constexpr absl::string_view::iterator const_begin_empty = sp.begin();
   constexpr absl::string_view::iterator const_end_empty = sp.end();
   EXPECT_EQ(const_begin_empty, const_end_empty);
@@ -1155,7 +1168,6 @@
   constexpr absl::string_view::iterator const_end_nullptr = cstr.end();
   EXPECT_EQ(const_begin_nullptr, const_end_nullptr);
 #endif  // ABSL_HAVE_STRING_VIEW_FROM_NULLPTR
-#endif  // !defined(__clang__) || ...
 
   constexpr absl::string_view::iterator const_begin = cstr_len.begin();
   constexpr absl::string_view::iterator const_end = cstr_len.end();
diff --git a/absl/strings/strip.h b/absl/strings/strip.h
index e3cda5b..55398ff 100644
--- a/absl/strings/strip.h
+++ b/absl/strings/strip.h
@@ -24,6 +24,7 @@
 #include <cstddef>
 #include <string>
 
+#include "absl/base/attributes.h"
 #include "absl/base/macros.h"
 #include "absl/base/nullability.h"
 #include "absl/strings/ascii.h"
@@ -44,8 +45,8 @@
 //   absl::string_view input("abc");
 //   EXPECT_TRUE(absl::ConsumePrefix(&input, "a"));
 //   EXPECT_EQ(input, "bc");
-inline bool ConsumePrefix(absl::Nonnull<absl::string_view*> str,
-                          absl::string_view expected) {
+inline constexpr bool ConsumePrefix(absl::string_view* absl_nonnull str,
+                                    absl::string_view expected) {
   if (!absl::StartsWith(*str, expected)) return false;
   str->remove_prefix(expected.size());
   return true;
@@ -61,8 +62,8 @@
 //   absl::string_view input("abcdef");
 //   EXPECT_TRUE(absl::ConsumeSuffix(&input, "def"));
 //   EXPECT_EQ(input, "abc");
-inline bool ConsumeSuffix(absl::Nonnull<absl::string_view*> str,
-                          absl::string_view expected) {
+inline constexpr bool ConsumeSuffix(absl::string_view* absl_nonnull str,
+                                    absl::string_view expected) {
   if (!absl::EndsWith(*str, expected)) return false;
   str->remove_suffix(expected.size());
   return true;
@@ -73,8 +74,9 @@
 // Returns a view into the input string `str` with the given `prefix` removed,
 // but leaving the original string intact. If the prefix does not match at the
 // start of the string, returns the original string instead.
-ABSL_MUST_USE_RESULT inline absl::string_view StripPrefix(
-    absl::string_view str, absl::string_view prefix) {
+[[nodiscard]] inline constexpr absl::string_view StripPrefix(
+    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND,
+    absl::string_view prefix) {
   if (absl::StartsWith(str, prefix)) str.remove_prefix(prefix.size());
   return str;
 }
@@ -84,8 +86,9 @@
 // Returns a view into the input string `str` with the given `suffix` removed,
 // but leaving the original string intact. If the suffix does not match at the
 // end of the string, returns the original string instead.
-ABSL_MUST_USE_RESULT inline absl::string_view StripSuffix(
-    absl::string_view str, absl::string_view suffix) {
+[[nodiscard]] inline constexpr absl::string_view StripSuffix(
+    absl::string_view str ABSL_ATTRIBUTE_LIFETIME_BOUND,
+    absl::string_view suffix) {
   if (absl::EndsWith(str, suffix)) str.remove_suffix(suffix.size());
   return str;
 }
diff --git a/absl/strings/substitute.cc b/absl/strings/substitute.cc
index a71f565..3c2ca5d 100644
--- a/absl/strings/substitute.cc
+++ b/absl/strings/substitute.cc
@@ -35,9 +35,10 @@
 ABSL_NAMESPACE_BEGIN
 namespace substitute_internal {
 
-void SubstituteAndAppendArray(
-    absl::Nonnull<std::string*> output, absl::string_view format,
-    absl::Nullable<const absl::string_view*> args_array, size_t num_args) {
+void SubstituteAndAppendArray(std::string* absl_nonnull output,
+                              absl::string_view format,
+                              const absl::string_view* absl_nullable args_array,
+                              size_t num_args) {
   // Determine total size needed.
   size_t size = 0;
   for (size_t i = 0; i < format.size(); i++) {
@@ -109,7 +110,7 @@
   assert(target == output->data() + output->size());
 }
 
-Arg::Arg(absl::Nullable<const void*> value) {
+Arg::Arg(const void* absl_nullable value) {
   static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2,
                 "fix sizeof(scratch_)");
   if (value == nullptr) {
diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h
index 6c7cba4..c93b1cc 100644
--- a/absl/strings/substitute.h
+++ b/absl/strings/substitute.h
@@ -106,7 +106,7 @@
   // Overloads for string-y things
   //
   // Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
-  Arg(absl::Nullable<const char*> value)  // NOLINT(google-explicit-constructor)
+  Arg(const char* absl_nullable value)  // NOLINT(google-explicit-constructor)
       : piece_(absl::NullSafeStringView(value)) {}
   template <typename Allocator>
   Arg(  // NOLINT
@@ -187,19 +187,20 @@
 
   // vector<bool>::reference and const_reference require special help to convert
   // to `Arg` because it requires two user defined conversions.
-  template <typename T,
-            absl::enable_if_t<
-                std::is_class<T>::value &&
-                (std::is_same<T, std::vector<bool>::reference>::value ||
-                 std::is_same<T, std::vector<bool>::const_reference>::value)>* =
-                nullptr>
+  template <
+      typename T,
+      std::enable_if_t<
+          std::is_class<T>::value &&
+              (std::is_same<T, std::vector<bool>::reference>::value ||
+               std::is_same<T, std::vector<bool>::const_reference>::value),
+          bool> = true>
   Arg(T value)  // NOLINT(google-explicit-constructor)
       : Arg(static_cast<bool>(value)) {}
 
   // `void*` values, with the exception of `char*`, are printed as
   // "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed.
   Arg(  // NOLINT(google-explicit-constructor)
-      absl::Nullable<const void*> value);
+      const void* absl_nullable value);
 
   // Normal enums are already handled by the integer formatters.
   // This overload matches only scoped enums.
@@ -222,12 +223,13 @@
 
 // Internal helper function. Don't call this from outside this implementation.
 // This interface may change without notice.
-void SubstituteAndAppendArray(
-    absl::Nonnull<std::string*> output, absl::string_view format,
-    absl::Nullable<const absl::string_view*> args_array, size_t num_args);
+void SubstituteAndAppendArray(std::string* absl_nonnull output,
+                              absl::string_view format,
+                              const absl::string_view* absl_nullable args_array,
+                              size_t num_args);
 
 #if defined(ABSL_BAD_CALL_IF)
-constexpr int CalculateOneBit(absl::Nonnull<const char*> format) {
+constexpr int CalculateOneBit(const char* absl_nonnull format) {
   // Returns:
   // * 2^N for '$N' when N is in [0-9]
   // * 0 for correct '$' escaping: '$$'.
@@ -236,11 +238,11 @@
                                           : (1 << (*format - '0'));
 }
 
-constexpr const char* SkipNumber(absl::Nonnull<const char*> format) {
+constexpr const char* absl_nonnull SkipNumber(const char* absl_nonnull format) {
   return !*format ? format : (format + 1);
 }
 
-constexpr int PlaceholderBitmask(absl::Nonnull<const char*> format) {
+constexpr int PlaceholderBitmask(const char* absl_nonnull format) {
   return !*format
              ? 0
              : *format != '$' ? PlaceholderBitmask(format + 1)
@@ -273,12 +275,12 @@
 //    absl::SubstituteAndAppend(boilerplate, format, args...);
 //  }
 //
-inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
+inline void SubstituteAndAppend(std::string* absl_nonnull output,
                                 absl::string_view format) {
   substitute_internal::SubstituteAndAppendArray(output, format, nullptr, 0);
 }
 
-inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
+inline void SubstituteAndAppend(std::string* absl_nonnull output,
                                 absl::string_view format,
                                 const substitute_internal::Arg& a0) {
   const absl::string_view args[] = {a0.piece()};
@@ -286,7 +288,7 @@
                                                 ABSL_ARRAYSIZE(args));
 }
 
-inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
+inline void SubstituteAndAppend(std::string* absl_nonnull output,
                                 absl::string_view format,
                                 const substitute_internal::Arg& a0,
                                 const substitute_internal::Arg& a1) {
@@ -295,7 +297,7 @@
                                                 ABSL_ARRAYSIZE(args));
 }
 
-inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
+inline void SubstituteAndAppend(std::string* absl_nonnull output,
                                 absl::string_view format,
                                 const substitute_internal::Arg& a0,
                                 const substitute_internal::Arg& a1,
@@ -305,7 +307,7 @@
                                                 ABSL_ARRAYSIZE(args));
 }
 
-inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
+inline void SubstituteAndAppend(std::string* absl_nonnull output,
                                 absl::string_view format,
                                 const substitute_internal::Arg& a0,
                                 const substitute_internal::Arg& a1,
@@ -317,7 +319,7 @@
                                                 ABSL_ARRAYSIZE(args));
 }
 
-inline void SubstituteAndAppend(absl::Nonnull<std::string*> output,
+inline void SubstituteAndAppend(std::string* absl_nonnull output,
                                 absl::string_view format,
                                 const substitute_internal::Arg& a0,
                                 const substitute_internal::Arg& a1,
@@ -331,7 +333,7 @@
 }
 
 inline void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::string_view format,
+    std::string* absl_nonnull output, absl::string_view format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5) {
@@ -342,7 +344,7 @@
 }
 
 inline void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::string_view format,
+    std::string* absl_nonnull output, absl::string_view format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
@@ -355,7 +357,7 @@
 }
 
 inline void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::string_view format,
+    std::string* absl_nonnull output, absl::string_view format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
@@ -368,7 +370,7 @@
 }
 
 inline void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::string_view format,
+    std::string* absl_nonnull output, absl::string_view format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
@@ -382,7 +384,7 @@
 }
 
 inline void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::string_view format,
+    std::string* absl_nonnull output, absl::string_view format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
@@ -398,16 +400,16 @@
 #if defined(ABSL_BAD_CALL_IF)
 // This body of functions catches cases where the number of placeholders
 // doesn't match the number of data arguments.
-void SubstituteAndAppend(absl::Nonnull<std::string*> output,
-                         absl::Nonnull<const char*> format)
+void SubstituteAndAppend(std::string* absl_nonnull output,
+                         const char* absl_nonnull format)
     ABSL_BAD_CALL_IF(
         substitute_internal::PlaceholderBitmask(format) != 0,
         "There were no substitution arguments "
         "but this format string either has a $[0-9] in it or contains "
         "an unescaped $ character (use $$ instead)");
 
-void SubstituteAndAppend(absl::Nonnull<std::string*> output,
-                         absl::Nonnull<const char*> format,
+void SubstituteAndAppend(std::string* absl_nonnull output,
+                         const char* absl_nonnull format,
                          const substitute_internal::Arg& a0)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
                      "There was 1 substitution argument given, but "
@@ -415,8 +417,8 @@
                      "one of $1-$9, or contains an unescaped $ character (use "
                      "$$ instead)");
 
-void SubstituteAndAppend(absl::Nonnull<std::string*> output,
-                         absl::Nonnull<const char*> format,
+void SubstituteAndAppend(std::string* absl_nonnull output,
+                         const char* absl_nonnull format,
                          const substitute_internal::Arg& a0,
                          const substitute_internal::Arg& a1)
     ABSL_BAD_CALL_IF(
@@ -425,8 +427,8 @@
         "missing its $0/$1, contains one of $2-$9, or contains an "
         "unescaped $ character (use $$ instead)");
 
-void SubstituteAndAppend(absl::Nonnull<std::string*> output,
-                         absl::Nonnull<const char*> format,
+void SubstituteAndAppend(std::string* absl_nonnull output,
+                         const char* absl_nonnull format,
                          const substitute_internal::Arg& a0,
                          const substitute_internal::Arg& a1,
                          const substitute_internal::Arg& a2)
@@ -436,8 +438,8 @@
         "this format string is missing its $0/$1/$2, contains one of "
         "$3-$9, or contains an unescaped $ character (use $$ instead)");
 
-void SubstituteAndAppend(absl::Nonnull<std::string*> output,
-                         absl::Nonnull<const char*> format,
+void SubstituteAndAppend(std::string* absl_nonnull output,
+                         const char* absl_nonnull format,
                          const substitute_internal::Arg& a0,
                          const substitute_internal::Arg& a1,
                          const substitute_internal::Arg& a2,
@@ -448,8 +450,8 @@
         "this format string is missing its $0-$3, contains one of "
         "$4-$9, or contains an unescaped $ character (use $$ instead)");
 
-void SubstituteAndAppend(absl::Nonnull<std::string*> output,
-                         absl::Nonnull<const char*> format,
+void SubstituteAndAppend(std::string* absl_nonnull output,
+                         const char* absl_nonnull format,
                          const substitute_internal::Arg& a0,
                          const substitute_internal::Arg& a1,
                          const substitute_internal::Arg& a2,
@@ -462,7 +464,7 @@
         "$5-$9, or contains an unescaped $ character (use $$ instead)");
 
 void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
+    std::string* absl_nonnull output, const char* absl_nonnull format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5)
@@ -473,7 +475,7 @@
         "$6-$9, or contains an unescaped $ character (use $$ instead)");
 
 void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
+    std::string* absl_nonnull output, const char* absl_nonnull format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
@@ -485,7 +487,7 @@
         "$7-$9, or contains an unescaped $ character (use $$ instead)");
 
 void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
+    std::string* absl_nonnull output, const char* absl_nonnull format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
@@ -497,7 +499,7 @@
         "$8-$9, or contains an unescaped $ character (use $$ instead)");
 
 void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
+    std::string* absl_nonnull output, const char* absl_nonnull format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
@@ -510,7 +512,7 @@
         "contains an unescaped $ character (use $$ instead)");
 
 void SubstituteAndAppend(
-    absl::Nonnull<std::string*> output, absl::Nonnull<const char*> format,
+    std::string* absl_nonnull output, const char* absl_nonnull format,
     const substitute_internal::Arg& a0, const substitute_internal::Arg& a1,
     const substitute_internal::Arg& a2, const substitute_internal::Arg& a3,
     const substitute_internal::Arg& a4, const substitute_internal::Arg& a5,
@@ -539,20 +541,20 @@
 //  void VarMsg(absl::string_view format, const Args&... args) {
 //    std::string s = absl::Substitute(format, args...);
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(absl::string_view format) {
+[[nodiscard]] inline std::string Substitute(absl::string_view format) {
   std::string result;
   SubstituteAndAppend(&result, format);
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0) {
   std::string result;
   SubstituteAndAppend(&result, format, a0);
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1) {
   std::string result;
@@ -560,7 +562,7 @@
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2) {
   std::string result;
@@ -568,7 +570,7 @@
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3) {
@@ -577,7 +579,7 @@
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4) {
@@ -586,7 +588,7 @@
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
@@ -596,7 +598,7 @@
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
@@ -606,7 +608,7 @@
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
@@ -617,7 +619,7 @@
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
@@ -628,7 +630,7 @@
   return result;
 }
 
-ABSL_MUST_USE_RESULT inline std::string Substitute(
+[[nodiscard]] inline std::string Substitute(
     absl::string_view format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
@@ -643,13 +645,13 @@
 #if defined(ABSL_BAD_CALL_IF)
 // This body of functions catches cases where the number of placeholders
 // doesn't match the number of data arguments.
-std::string Substitute(absl::Nonnull<const char*> format)
+std::string Substitute(const char* absl_nonnull format)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
                      "There were no substitution arguments "
                      "but this format string either has a $[0-9] in it or "
                      "contains an unescaped $ character (use $$ instead)");
 
-std::string Substitute(absl::Nonnull<const char*> format,
+std::string Substitute(const char* absl_nonnull format,
                        const substitute_internal::Arg& a0)
     ABSL_BAD_CALL_IF(
         substitute_internal::PlaceholderBitmask(format) != 1,
@@ -657,7 +659,7 @@
         "this format string is missing its $0, contains one of $1-$9, "
         "or contains an unescaped $ character (use $$ instead)");
 
-std::string Substitute(absl::Nonnull<const char*> format,
+std::string Substitute(const char* absl_nonnull format,
                        const substitute_internal::Arg& a0,
                        const substitute_internal::Arg& a1)
     ABSL_BAD_CALL_IF(
@@ -666,7 +668,7 @@
         "this format string is missing its $0/$1, contains one of "
         "$2-$9, or contains an unescaped $ character (use $$ instead)");
 
-std::string Substitute(absl::Nonnull<const char*> format,
+std::string Substitute(const char* absl_nonnull format,
                        const substitute_internal::Arg& a0,
                        const substitute_internal::Arg& a1,
                        const substitute_internal::Arg& a2)
@@ -676,7 +678,7 @@
         "this format string is missing its $0/$1/$2, contains one of "
         "$3-$9, or contains an unescaped $ character (use $$ instead)");
 
-std::string Substitute(absl::Nonnull<const char*> format,
+std::string Substitute(const char* absl_nonnull format,
                        const substitute_internal::Arg& a0,
                        const substitute_internal::Arg& a1,
                        const substitute_internal::Arg& a2,
@@ -687,7 +689,7 @@
         "this format string is missing its $0-$3, contains one of "
         "$4-$9, or contains an unescaped $ character (use $$ instead)");
 
-std::string Substitute(absl::Nonnull<const char*> format,
+std::string Substitute(const char* absl_nonnull format,
                        const substitute_internal::Arg& a0,
                        const substitute_internal::Arg& a1,
                        const substitute_internal::Arg& a2,
@@ -699,7 +701,7 @@
         "this format string is missing its $0-$4, contains one of "
         "$5-$9, or contains an unescaped $ character (use $$ instead)");
 
-std::string Substitute(absl::Nonnull<const char*> format,
+std::string Substitute(const char* absl_nonnull format,
                        const substitute_internal::Arg& a0,
                        const substitute_internal::Arg& a1,
                        const substitute_internal::Arg& a2,
@@ -713,7 +715,7 @@
         "$6-$9, or contains an unescaped $ character (use $$ instead)");
 
 std::string Substitute(
-    absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
+    const char* absl_nonnull format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6)
@@ -724,7 +726,7 @@
         "$7-$9, or contains an unescaped $ character (use $$ instead)");
 
 std::string Substitute(
-    absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
+    const char* absl_nonnull format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
@@ -736,7 +738,7 @@
         "$8-$9, or contains an unescaped $ character (use $$ instead)");
 
 std::string Substitute(
-    absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
+    const char* absl_nonnull format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
@@ -748,7 +750,7 @@
         "contains an unescaped $ character (use $$ instead)");
 
 std::string Substitute(
-    absl::Nonnull<const char*> format, const substitute_internal::Arg& a0,
+    const char* absl_nonnull format, const substitute_internal::Arg& a0,
     const substitute_internal::Arg& a1, const substitute_internal::Arg& a2,
     const substitute_internal::Arg& a3, const substitute_internal::Arg& a4,
     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
diff --git a/absl/strings/substitute_benchmark.cc b/absl/strings/substitute_benchmark.cc
new file mode 100644
index 0000000..e58ec86
--- /dev/null
+++ b/absl/strings/substitute_benchmark.cc
@@ -0,0 +1,158 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cstddef>
+#include <cstdint>
+#include <string>
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/substitute.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+void BM_Substitute(benchmark::State& state) {
+  std::string s(state.range(0), 'x');
+  int64_t bytes = 0;
+  for (auto _ : state) {
+    std::string result = absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$", s,
+                                          s, s, s, s, s, s, s, s, s);
+    bytes += result.size();
+  }
+  state.SetBytesProcessed(bytes);
+}
+BENCHMARK(BM_Substitute)->Range(0, 1024);
+
+// Like BM_Substitute, but use char* strings (which must then be copied
+// to STL strings) for all parameters.  This demonstrates that it is faster
+// to use absl::Substitute() even if your inputs are char* strings.
+void BM_SubstituteCstr(benchmark::State& state) {
+  std::string s(state.range(0), 'x');
+  int64_t bytes = 0;
+  for (auto _ : state) {
+    std::string result =
+        absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$", s.c_str(),
+                         s.c_str(), s.c_str(), s.c_str(), s.c_str(), s.c_str(),
+                         s.c_str(), s.c_str(), s.c_str(), s.c_str());
+    bytes += result.size();
+  }
+  state.SetBytesProcessed(bytes);
+}
+BENCHMARK(BM_SubstituteCstr)->Range(0, 1024);
+
+// For comparison with BM_Substitute.
+void BM_StringPrintf(benchmark::State& state) {
+  std::string s(state.range(0), 'x');
+  int64_t bytes = 0;
+  for (auto _ : state) {
+    std::string result = absl::StrCat(s, " ", s, " ", s, " ", s, " ", s, " ", s,
+                                      " ", s, " ", s, " ", s, " ", s);
+    bytes += result.size();
+  }
+  state.SetBytesProcessed(bytes);
+}
+BENCHMARK(BM_StringPrintf)->Range(0, 1024);
+
+// Benchmark using absl::Substitute() together with SimpleItoa() to print
+// numbers.  This demonstrates that absl::Substitute() is faster than
+// StringPrintf() even when the inputs are numbers.
+void BM_SubstituteNumber(benchmark::State& state) {
+  const int n = state.range(0);
+  int64_t bytes = 0;
+  for (auto _ : state) {
+    std::string result =
+        absl::Substitute("$0 $1 $2 $3 $4 $5 $6 $7 $8 $9 $$", n, n + 1, n + 2,
+                         n + 3, n + 4, n + 5, n + 6, n + 7, n + 8, n + 9);
+    bytes += result.size();
+  }
+  state.SetBytesProcessed(bytes);
+}
+BENCHMARK(BM_SubstituteNumber)->Arg(0)->Arg(1 << 20);
+
+// For comparison with BM_SubstituteNumber.
+void BM_StrCatNumber(benchmark::State& state) {
+  const int n = state.range(0);
+  int64_t bytes = 0;
+  for (auto _ : state) {
+    std::string result =
+        absl::StrCat(n, " ", n + 1, " ", n + 2, " ", n + 3, " ", n + 4, " ",
+                     n + 5, " ", n + 6, " ", n + 7, " ", n + 8, " ", n + 9);
+    bytes += result.size();
+  }
+  state.SetBytesProcessed(bytes);
+}
+BENCHMARK(BM_StrCatNumber)->Arg(0)->Arg(1 << 20);
+
+// Benchmark using absl::Substitute() with a single substitution, to test the
+// speed at which it copies simple text.  Even in this case, it's faster
+// that StringPrintf().
+void BM_SubstituteSimpleText(benchmark::State& state) {
+  std::string s(state.range(0), 'x');
+  int64_t bytes = 0;
+  for (auto _ : state) {
+    std::string result = absl::Substitute("$0", s.c_str());
+    bytes += result.size();
+  }
+  state.SetBytesProcessed(bytes);
+}
+BENCHMARK(BM_SubstituteSimpleText)->Range(0, 1024);
+
+// For comparison with BM_SubstituteSimpleText.
+void BM_StrCatSimpleText(benchmark::State& state) {
+  std::string s(state.range(0), 'x');
+  int64_t bytes = 0;
+  for (auto _ : state) {
+    std::string result = absl::StrCat("", s);
+    bytes += result.size();
+  }
+  state.SetBytesProcessed(bytes);
+}
+BENCHMARK(BM_StrCatSimpleText)->Range(0, 1024);
+
+std::string MakeFormatByDensity(int density, bool subs_mode) {
+  std::string format((2 + density) * 10, 'x');
+  for (size_t i = 0; i < 10; ++i) {
+    format[density * i] = subs_mode ? '$' : '%';
+    format[density * i + 1] = subs_mode ? ('0' + i) : 's';
+  }
+  return format;
+}
+
+void BM_SubstituteDensity(benchmark::State& state) {
+  const std::string s(10, 'x');
+  const std::string format = MakeFormatByDensity(state.range(0), true);
+  int64_t bytes = 0;
+  for (auto _ : state) {
+    std::string result = absl::Substitute(format, s, s, s, s, s, s, s, s, s, s);
+    bytes += result.size();
+  }
+  state.SetBytesProcessed(bytes);
+}
+BENCHMARK(BM_SubstituteDensity)->Range(0, 256);
+
+void BM_StrCatDensity(benchmark::State& state) {
+  const std::string s(10, 'x');
+  const std::string format(state.range(0), 'x');
+  int64_t bytes = 0;
+  for (auto _ : state) {
+    std::string result =
+        absl::StrCat(s, format, s, format, s, format, s, format, s, format, s,
+                     format, s, format, s, format, s, format, s, format);
+    bytes += result.size();
+  }
+  state.SetBytesProcessed(bytes);
+}
+BENCHMARK(BM_StrCatDensity)->Range(0, 256);
+
+}  // namespace
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index dafeba3..920928e 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -85,8 +85,8 @@
         "//absl/base:config",
         "//absl/random",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -124,9 +124,9 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
-        "//absl:msvc_compiler": [],
-        "//absl:clang-cl_compiler": [],
-        "//absl:wasm": [],
+        "@rules_cc//cc/compiler:msvc-cl": [],
+        "@rules_cc//cc/compiler:clang-cl": [],
+        "@rules_cc//cc/compiler:emscripten": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     visibility = ["//visibility:public"],
@@ -140,7 +140,9 @@
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
         "//absl/base:malloc_internal",
+        "//absl/base:nullability",
         "//absl/base:raw_logging_internal",
+        "//absl/base:tracing_internal",
         "//absl/debugging:stacktrace",
         "//absl/debugging:symbolize",
         "//absl/time",
@@ -161,8 +163,8 @@
     deps = [
         ":synchronization",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -177,9 +179,12 @@
     ],
     deps = [
         ":synchronization",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:tracing_internal",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -194,7 +199,7 @@
         ":synchronization",
         ":thread_pool",
         "//absl/base:no_destructor",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -209,8 +214,8 @@
         "//absl/base:core_headers",
         "//absl/log",
         "//absl/log:check",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -225,8 +230,7 @@
     deps = [
         ":graphcycles_internal",
         "//absl/base:raw_logging_internal",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
@@ -262,9 +266,10 @@
         "//absl/log",
         "//absl/log:check",
         "//absl/memory",
+        "//absl/random",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -276,8 +281,8 @@
     deps = [
         ":synchronization",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -295,7 +300,7 @@
         "//absl/base",
         "//absl/base:config",
         "//absl/base:no_destructor",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
     alwayslink = 1,
 )
@@ -320,9 +325,12 @@
     tags = ["no_test_lexan"],
     deps = [
         ":synchronization",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:tracing_internal",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -340,7 +348,7 @@
         "//absl/base:config",
         "//absl/strings",
         "//absl/time",
-        "@com_google_googletest//:gtest",
+        "@googletest//:gtest",
     ],
     alwayslink = 1,
 )
@@ -358,7 +366,7 @@
         ":synchronization",
         "//absl/strings",
         "//absl/time",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -375,8 +383,8 @@
         "//absl/base:config",
         "//absl/random",
         "//absl/time",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index a0f64e5..9d4844d 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -109,10 +109,13 @@
     absl::core_headers
     absl::dynamic_annotations
     absl::malloc_internal
+    absl::nullability
     absl::raw_logging_internal
     absl::stacktrace
     absl::symbolize
+    absl::tracing_internal
     absl::time
+    absl::tracing_internal
     Threads::Threads
   PUBLIC
 )
@@ -140,6 +143,7 @@
   DEPS
     absl::synchronization
     absl::time
+    absl::tracing_internal
     GTest::gmock_main
 )
 
@@ -189,6 +193,7 @@
     absl::core_headers
     absl::log
     absl::memory
+    absl::random_random
     absl::time
     GTest::gmock_main
 )
@@ -215,8 +220,12 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::base
+    absl::config
+    absl::core_headers
     absl::synchronization
     absl::time
+    absl::tracing_internal
     GTest::gmock_main
 )
 
diff --git a/absl/synchronization/blocking_counter.cc b/absl/synchronization/blocking_counter.cc
index d2f82da..a530baf 100644
--- a/absl/synchronization/blocking_counter.cc
+++ b/absl/synchronization/blocking_counter.cc
@@ -17,6 +17,7 @@
 #include <atomic>
 
 #include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/tracing.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -40,6 +41,7 @@
   ABSL_RAW_CHECK(count >= 0,
                  "BlockingCounter::DecrementCount() called too many times");
   if (count == 0) {
+    base_internal::TraceSignal(this, TraceObjectKind());
     MutexLock l(&lock_);
     done_ = true;
     return true;
@@ -48,19 +50,23 @@
 }
 
 void BlockingCounter::Wait() {
-  MutexLock l(&this->lock_);
+  base_internal::TraceWait(this, TraceObjectKind());
+  {
+    MutexLock l(&this->lock_);
 
-  // only one thread may call Wait(). To support more than one thread,
-  // implement a counter num_to_exit, like in the Barrier class.
-  ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()");
-  num_waiting_++;
+    // only one thread may call Wait(). To support more than one thread,
+    // implement a counter num_to_exit, like in the Barrier class.
+    ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()");
+    num_waiting_++;
 
-  this->lock_.Await(Condition(IsDone, &this->done_));
+    this->lock_.Await(Condition(IsDone, &this->done_));
 
-  // At this point, we know that all threads executing DecrementCount
-  // will not touch this object again.
-  // Therefore, the thread calling this method is free to delete the object
-  // after we return from this method.
+    // At this point, we know that all threads executing DecrementCount
+    // will not touch this object again.
+    // Therefore, the thread calling this method is free to delete the object
+    // after we return from this method.
+  }
+  base_internal::TraceContinue(this, TraceObjectKind());
 }
 
 ABSL_NAMESPACE_END
diff --git a/absl/synchronization/blocking_counter.h b/absl/synchronization/blocking_counter.h
index 1908fdb..d0504a1 100644
--- a/absl/synchronization/blocking_counter.h
+++ b/absl/synchronization/blocking_counter.h
@@ -22,6 +22,7 @@
 
 #include <atomic>
 
+#include "absl/base/internal/tracing.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/synchronization/mutex.h"
 
@@ -89,6 +90,11 @@
   void Wait();
 
  private:
+  // Convenience helper to reduce verbosity at call sites.
+  static inline constexpr base_internal::ObjectKind TraceObjectKind() {
+    return base_internal::ObjectKind::kBlockingCounter;
+  }
+
   Mutex lock_;
   std::atomic<int> count_;
   int num_waiting_ ABSL_GUARDED_BY(lock_);
diff --git a/absl/synchronization/blocking_counter_test.cc b/absl/synchronization/blocking_counter_test.cc
index 06885f5..0c42b56 100644
--- a/absl/synchronization/blocking_counter_test.cc
+++ b/absl/synchronization/blocking_counter_test.cc
@@ -15,9 +15,13 @@
 #include "absl/synchronization/blocking_counter.h"
 
 #include <thread>  // NOLINT(build/c++11)
+#include <tuple>
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/tracing.h"
 #include "absl/time/clock.h"
 #include "absl/time/time.h"
 
@@ -76,5 +80,67 @@
 #endif
 
 }  // namespace
+
+#if ABSL_HAVE_ATTRIBUTE_WEAK
+
+namespace base_internal {
+
+namespace {
+
+using TraceRecord = std::tuple<const void*, ObjectKind>;
+
+thread_local TraceRecord tls_signal;
+thread_local TraceRecord tls_wait;
+thread_local TraceRecord tls_continue;
+
+}  // namespace
+
+// Strong extern "C" implementation.
+extern "C" {
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
+                                                   ObjectKind kind) {
+  tls_wait = {object, kind};
+}
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
+                                                       ObjectKind kind) {
+  tls_continue = {object, kind};
+}
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
+                                                     ObjectKind kind) {
+  tls_signal = {object, kind};
+}
+
+}  // extern "C"
+
+TEST(BlockingCounterTest, TracesSignal) {
+  BlockingCounter counter(2);
+
+  tls_signal = {};
+  counter.DecrementCount();
+  EXPECT_EQ(tls_signal, TraceRecord(nullptr, ObjectKind::kUnknown));
+
+  tls_signal = {};
+  counter.DecrementCount();
+  EXPECT_EQ(tls_signal, TraceRecord(&counter, ObjectKind::kBlockingCounter));
+}
+
+TEST(BlockingCounterTest, TracesWaitContinue) {
+  BlockingCounter counter(1);
+  counter.DecrementCount();
+
+  tls_wait = {};
+  tls_continue = {};
+  counter.Wait();
+  EXPECT_EQ(tls_wait, TraceRecord(&counter, ObjectKind::kBlockingCounter));
+  EXPECT_EQ(tls_continue, TraceRecord(&counter, ObjectKind::kBlockingCounter));
+}
+
+}  // namespace base_internal
+
+#endif  // ABSL_HAVE_ATTRIBUTE_WEAK
+
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/internal/create_thread_identity.cc b/absl/synchronization/internal/create_thread_identity.cc
index eacaa28..93cd376 100644
--- a/absl/synchronization/internal/create_thread_identity.cc
+++ b/absl/synchronization/internal/create_thread_identity.cc
@@ -39,7 +39,8 @@
 ABSL_CONST_INIT static base_internal::ThreadIdentity* thread_identity_freelist;
 
 // A per-thread destructor for reclaiming associated ThreadIdentity objects.
-// Since we must preserve their storage we cache them for re-use.
+// Since we must preserve their storage, we cache them for re-use instead of
+// truly destructing the object.
 static void ReclaimThreadIdentity(void* v) {
   base_internal::ThreadIdentity* identity =
       static_cast<base_internal::ThreadIdentity*>(v);
@@ -124,6 +125,9 @@
     identity = reinterpret_cast<base_internal::ThreadIdentity*>(
         RoundUp(reinterpret_cast<intptr_t>(allocation),
                 base_internal::PerThreadSynch::kAlignment));
+    // Note that *identity is never constructed.
+    // TODO(b/357097463): change this "one time init" to be a proper
+    // constructor.
     OneTimeInitThreadIdentity(identity);
   }
   ResetThreadIdentityBetweenReuse(identity);
diff --git a/absl/synchronization/internal/futex_waiter.cc b/absl/synchronization/internal/futex_waiter.cc
index 87eb3b2..8945c17 100644
--- a/absl/synchronization/internal/futex_waiter.cc
+++ b/absl/synchronization/internal/futex_waiter.cc
@@ -31,10 +31,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr char FutexWaiter::kName[];
-#endif
-
 int FutexWaiter::WaitUntil(std::atomic<int32_t>* v, int32_t val,
                            KernelTimeout t) {
 #ifdef CLOCK_MONOTONIC
diff --git a/absl/synchronization/internal/graphcycles_benchmark.cc b/absl/synchronization/internal/graphcycles_benchmark.cc
index 54823e0..9012801 100644
--- a/absl/synchronization/internal/graphcycles_benchmark.cc
+++ b/absl/synchronization/internal/graphcycles_benchmark.cc
@@ -12,14 +12,13 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/synchronization/internal/graphcycles.h"
-
 #include <algorithm>
 #include <cstdint>
 #include <vector>
 
-#include "benchmark/benchmark.h"
 #include "absl/base/internal/raw_logging.h"
+#include "absl/synchronization/internal/graphcycles.h"
+#include "benchmark/benchmark.h"
 
 namespace {
 
diff --git a/absl/synchronization/internal/graphcycles_test.cc b/absl/synchronization/internal/graphcycles_test.cc
index 47410aa..b7988c4 100644
--- a/absl/synchronization/internal/graphcycles_test.cc
+++ b/absl/synchronization/internal/graphcycles_test.cc
@@ -15,6 +15,7 @@
 #include "absl/synchronization/internal/graphcycles.h"
 
 #include <climits>
+#include <cstdint>
 #include <map>
 #include <random>
 #include <unordered_set>
@@ -461,20 +462,20 @@
 
 TEST(GraphCycles, IntegerOverflow) {
   GraphCycles graph_cycles;
-  char *buf = (char *)nullptr;
-  GraphId prev_id = graph_cycles.GetId(buf);
+  uintptr_t buf = 0;
+  GraphId prev_id = graph_cycles.GetId(reinterpret_cast<void*>(buf));
   buf += 1;
-  GraphId id = graph_cycles.GetId(buf);
+  GraphId id = graph_cycles.GetId(reinterpret_cast<void*>(buf));
   ASSERT_TRUE(graph_cycles.InsertEdge(prev_id, id));
 
   // INT_MAX / 40 is enough to cause an overflow when multiplied by 41.
   graph_cycles.TestOnlyAddNodes(INT_MAX / 40);
 
   buf += 1;
-  GraphId newid = graph_cycles.GetId(buf);
+  GraphId newid = graph_cycles.GetId(reinterpret_cast<void*>(buf));
   graph_cycles.HasEdge(prev_id, newid);
 
-  graph_cycles.RemoveNode(buf);
+  graph_cycles.RemoveNode(reinterpret_cast<void*>(buf));
 }
 
 }  // namespace synchronization_internal
diff --git a/absl/synchronization/internal/kernel_timeout.cc b/absl/synchronization/internal/kernel_timeout.cc
index 48ea628..252397a 100644
--- a/absl/synchronization/internal/kernel_timeout.cc
+++ b/absl/synchronization/internal/kernel_timeout.cc
@@ -35,11 +35,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr uint64_t KernelTimeout::kNoTimeout;
-constexpr int64_t KernelTimeout::kMaxNanos;
-#endif
-
 int64_t KernelTimeout::SteadyClockNow() {
   if (!SupportsSteadyClock()) {
     return absl::GetCurrentTimeNanos();
diff --git a/absl/synchronization/internal/pthread_waiter.cc b/absl/synchronization/internal/pthread_waiter.cc
index bf700e9..eead9de 100644
--- a/absl/synchronization/internal/pthread_waiter.cc
+++ b/absl/synchronization/internal/pthread_waiter.cc
@@ -58,10 +58,6 @@
 };
 }  // namespace
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr char PthreadWaiter::kName[];
-#endif
-
 PthreadWaiter::PthreadWaiter() : waiter_count_(0), wakeup_count_(0) {
   const int err = pthread_mutex_init(&mu_, 0);
   if (err != 0) {
diff --git a/absl/synchronization/internal/sem_waiter.cc b/absl/synchronization/internal/sem_waiter.cc
index d62dbdc..2119290 100644
--- a/absl/synchronization/internal/sem_waiter.cc
+++ b/absl/synchronization/internal/sem_waiter.cc
@@ -33,10 +33,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr char SemWaiter::kName[];
-#endif
-
 SemWaiter::SemWaiter() : wakeups_(0) {
   if (sem_init(&sem_, 0, 0) != 0) {
     ABSL_RAW_LOG(FATAL, "sem_init failed with errno %d\n", errno);
diff --git a/absl/synchronization/internal/stdcpp_waiter.cc b/absl/synchronization/internal/stdcpp_waiter.cc
index 355718a..607d683 100644
--- a/absl/synchronization/internal/stdcpp_waiter.cc
+++ b/absl/synchronization/internal/stdcpp_waiter.cc
@@ -30,10 +30,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr char StdcppWaiter::kName[];
-#endif
-
 StdcppWaiter::StdcppWaiter() : waiter_count_(0), wakeup_count_(0) {}
 
 bool StdcppWaiter::Wait(KernelTimeout t) {
diff --git a/absl/synchronization/internal/waiter_base.cc b/absl/synchronization/internal/waiter_base.cc
index 46928b4..e9797f8 100644
--- a/absl/synchronization/internal/waiter_base.cc
+++ b/absl/synchronization/internal/waiter_base.cc
@@ -21,10 +21,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr int WaiterBase::kIdlePeriods;
-#endif
-
 void WaiterBase::MaybeBecomeIdle() {
   base_internal::ThreadIdentity *identity =
       base_internal::CurrentThreadIdentityIfPresent();
diff --git a/absl/synchronization/internal/waiter_test.cc b/absl/synchronization/internal/waiter_test.cc
index da13896..6e37415 100644
--- a/absl/synchronization/internal/waiter_test.cc
+++ b/absl/synchronization/internal/waiter_test.cc
@@ -108,7 +108,10 @@
       absl::synchronization_internal::KernelTimeout(absl::Seconds(10))));
   absl::Duration waited = absl::Now() - start;
   EXPECT_GE(waited, WithTolerance(absl::Milliseconds(500)));
+#ifndef _MSC_VER
+  // Skip on MSVC due to flakiness.
   EXPECT_LT(waited, absl::Seconds(2));
+#endif
 }
 
 TYPED_TEST_P(WaiterTest, WaitTimeWoken) {
diff --git a/absl/synchronization/internal/win32_waiter.cc b/absl/synchronization/internal/win32_waiter.cc
index bd95ff0..b2fe402 100644
--- a/absl/synchronization/internal/win32_waiter.cc
+++ b/absl/synchronization/internal/win32_waiter.cc
@@ -28,10 +28,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr char Win32Waiter::kName[];
-#endif
-
 class Win32Waiter::WinHelper {
  public:
   static SRWLOCK *GetLock(Win32Waiter *w) {
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index cb3c7e7..5091b8f 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -651,6 +651,13 @@
 static const intptr_t kMuLow = 0x00ffL;   // mask all mutex bits
 static const intptr_t kMuHigh = ~kMuLow;  // mask pointer/reader count
 
+static_assert((0xab & (kMuWriter | kMuReader)) == (kMuWriter | kMuReader),
+              "The debug allocator's uninitialized pattern (0xab) must be an "
+              "invalid mutex state");
+static_assert((0xcd & (kMuWriter | kMuReader)) == (kMuWriter | kMuReader),
+              "The debug allocator's freed pattern (0xcd) must be an invalid "
+              "mutex state");
+
 // Hack to make constant values available to gdb pretty printer
 enum {
   kGdbMuSpin = kMuSpin,
@@ -1332,7 +1339,7 @@
     } else {
       snprintf(buf + len, count, " %p", pcs[i]);
     }
-    len += strlen(&buf[len]);
+    len += static_cast<int>(strlen(&buf[len]));
   }
   return buf;
 }
@@ -1713,25 +1720,44 @@
   // NOTE: optimized out when kDebugMode is false.
   bool should_try_cas = ((v & (kMuEvent | kMuWriter)) == kMuWriter &&
                          (v & (kMuWait | kMuDesig)) != kMuWait);
+
   // But, we can use an alternate computation of it, that compilers
   // currently don't find on their own.  When that changes, this function
   // can be simplified.
-  intptr_t x = (v ^ (kMuWriter | kMuWait)) & (kMuWriter | kMuEvent);
-  intptr_t y = (v ^ (kMuWriter | kMuWait)) & (kMuWait | kMuDesig);
-  // Claim: "x == 0 && y > 0" is equal to should_try_cas.
-  // Also, because kMuWriter and kMuEvent exceed kMuDesig and kMuWait,
-  // all possible non-zero values for x exceed all possible values for y.
-  // Therefore, (x == 0 && y > 0) == (x < y).
-  if (kDebugMode && should_try_cas != (x < y)) {
+  //
+  // should_try_cas is true iff the bits satisfy the following conditions:
+  //
+  //                   Ev Wr Wa De
+  // equal to           0  1
+  // and not equal to         1  0
+  //
+  // after xoring by    0  1  0  1,  this is equivalent to:
+  //
+  // equal to           0  0
+  // and not equal to         1  1,  which is the same as:
+  //
+  // smaller than       0  0  1  1
+  static_assert(kMuEvent > kMuWait, "Needed for should_try_cas_fast");
+  static_assert(kMuEvent > kMuDesig, "Needed for should_try_cas_fast");
+  static_assert(kMuWriter > kMuWait, "Needed for should_try_cas_fast");
+  static_assert(kMuWriter > kMuDesig, "Needed for should_try_cas_fast");
+
+  bool should_try_cas_fast =
+      ((v ^ (kMuWriter | kMuDesig)) &
+       (kMuEvent | kMuWriter | kMuWait | kMuDesig)) < (kMuWait | kMuDesig);
+
+  if (kDebugMode && should_try_cas != should_try_cas_fast) {
     // We would usually use PRIdPTR here, but is not correctly implemented
     // within the android toolchain.
     ABSL_RAW_LOG(FATAL, "internal logic error %llx %llx %llx\n",
-                 static_cast<long long>(v), static_cast<long long>(x),
-                 static_cast<long long>(y));
+                 static_cast<long long>(v),
+                 static_cast<long long>(should_try_cas),
+                 static_cast<long long>(should_try_cas_fast));
   }
-  if (x < y && mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter),
-                                           std::memory_order_release,
-                                           std::memory_order_relaxed)) {
+  if (should_try_cas_fast &&
+      mu_.compare_exchange_strong(v, v & ~(kMuWrWait | kMuWriter),
+                                  std::memory_order_release,
+                                  std::memory_order_relaxed)) {
     // fast writer release (writer with no waiters or with designated waker)
   } else {
     this->UnlockSlow(nullptr /*no waitp*/);  // take slow path
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index be3f1f5..78b1c7a 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -70,6 +70,7 @@
 #include "absl/base/internal/low_level_alloc.h"
 #include "absl/base/internal/thread_identity.h"
 #include "absl/base/internal/tsan_mutex_interface.h"
+#include "absl/base/nullability.h"
 #include "absl/base/port.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/synchronization/internal/kernel_timeout.h"
@@ -190,7 +191,7 @@
   // If the mutex can be acquired without blocking, does so exclusively and
   // returns `true`. Otherwise, returns `false`. Returns `true` with high
   // probability if the `Mutex` was free.
-  ABSL_MUST_USE_RESULT bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true);
+  [[nodiscard]] bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true);
 
   // Mutex::AssertHeld()
   //
@@ -255,7 +256,7 @@
   // If the mutex can be acquired without blocking, acquires this mutex for
   // shared access and returns `true`. Otherwise, returns `false`. Returns
   // `true` with high probability if the `Mutex` was free or shared.
-  ABSL_MUST_USE_RESULT bool ReaderTryLock() ABSL_SHARED_TRYLOCK_FUNCTION(true);
+  [[nodiscard]] bool ReaderTryLock() ABSL_SHARED_TRYLOCK_FUNCTION(true);
 
   // Mutex::AssertReaderHeld()
   //
@@ -281,8 +282,7 @@
 
   void WriterUnlock() ABSL_UNLOCK_FUNCTION() { this->Unlock(); }
 
-  ABSL_MUST_USE_RESULT bool WriterTryLock()
-      ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
+  [[nodiscard]] bool WriterTryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
     return this->TryLock();
   }
 
@@ -450,7 +450,9 @@
   // substantially reduce `Mutex` performance; it should be set only for
   // non-production runs.  Optimization options may also disable invariant
   // checks.
-  void EnableInvariantDebugging(void (*invariant)(void*), void* arg);
+  void EnableInvariantDebugging(
+      void (*absl_nullable invariant)(void* absl_nullability_unknown),
+      void* absl_nullability_unknown arg);
 
   // Mutex::EnableDebugLog()
   //
@@ -459,7 +461,7 @@
   // call to `EnableInvariantDebugging()` or `EnableDebugLog()` has been made.
   //
   // Note: This method substantially reduces `Mutex` performance.
-  void EnableDebugLog(const char* name);
+  void EnableDebugLog(const char* absl_nullable name);
 
   // Deadlock detection
 
@@ -509,20 +511,23 @@
 
   // Post()/Wait() versus associated PerThreadSem; in class for required
   // friendship with PerThreadSem.
-  static void IncrementSynchSem(Mutex* mu, base_internal::PerThreadSynch* w);
-  static bool DecrementSynchSem(Mutex* mu, base_internal::PerThreadSynch* w,
+  static void IncrementSynchSem(Mutex* absl_nonnull mu,
+                                base_internal::PerThreadSynch* absl_nonnull w);
+  static bool DecrementSynchSem(Mutex* absl_nonnull mu,
+                                base_internal::PerThreadSynch* absl_nonnull w,
                                 synchronization_internal::KernelTimeout t);
 
   // slow path acquire
-  void LockSlowLoop(SynchWaitParams* waitp, int flags);
+  void LockSlowLoop(SynchWaitParams* absl_nonnull waitp, int flags);
   // wrappers around LockSlowLoop()
-  bool LockSlowWithDeadline(MuHow how, const Condition* cond,
+  bool LockSlowWithDeadline(MuHow absl_nonnull how,
+                            const Condition* absl_nullable cond,
                             synchronization_internal::KernelTimeout t,
                             int flags);
-  void LockSlow(MuHow how, const Condition* cond,
+  void LockSlow(MuHow absl_nonnull how, const Condition* absl_nullable cond,
                 int flags) ABSL_ATTRIBUTE_COLD;
   // slow path release
-  void UnlockSlow(SynchWaitParams* waitp) ABSL_ATTRIBUTE_COLD;
+  void UnlockSlow(SynchWaitParams* absl_nullable waitp) ABSL_ATTRIBUTE_COLD;
   // TryLock slow path.
   bool TryLockSlow();
   // ReaderTryLock slow path.
@@ -533,20 +538,21 @@
   bool LockWhenCommon(const Condition& cond,
                       synchronization_internal::KernelTimeout t, bool write);
   // Attempt to remove thread s from queue.
-  void TryRemove(base_internal::PerThreadSynch* s);
+  void TryRemove(base_internal::PerThreadSynch* absl_nonnull s);
   // Block a thread on mutex.
-  void Block(base_internal::PerThreadSynch* s);
+  void Block(base_internal::PerThreadSynch* absl_nonnull s);
   // Wake a thread; return successor.
-  base_internal::PerThreadSynch* Wakeup(base_internal::PerThreadSynch* w);
+  base_internal::PerThreadSynch* absl_nullable Wakeup(
+      base_internal::PerThreadSynch* absl_nonnull w);
   void Dtor();
 
   friend class CondVar;   // for access to Trans()/Fer().
-  void Trans(MuHow how);  // used for CondVar->Mutex transfer
-  void Fer(
-      base_internal::PerThreadSynch* w);  // used for CondVar->Mutex transfer
+  void Trans(MuHow absl_nonnull how);  // used for CondVar->Mutex transfer
+  void Fer(base_internal::PerThreadSynch* absl_nonnull
+           w);  // used for CondVar->Mutex transfer
 
   // Catch the error of writing Mutex when intending MutexLock.
-  explicit Mutex(const volatile Mutex* /*ignored*/) {}
+  explicit Mutex(const volatile Mutex* absl_nullable /*ignored*/) {}
 
   Mutex(const Mutex&) = delete;
   Mutex& operator=(const Mutex&) = delete;
@@ -581,14 +587,15 @@
   // Calls `mu->Lock()` and returns when that call returns. That is, `*mu` is
   // guaranteed to be locked when this object is constructed. Requires that
   // `mu` be dereferenceable.
-  explicit MutexLock(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
+  explicit MutexLock(Mutex* absl_nonnull mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
     this->mu_->Lock();
   }
 
   // Like above, but calls `mu->LockWhen(cond)` instead. That is, in addition to
   // the above, the condition given by `cond` is also guaranteed to hold when
   // this object is constructed.
-  explicit MutexLock(Mutex* mu, const Condition& cond)
+  explicit MutexLock(Mutex* absl_nonnull mu, const Condition& cond)
       ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
       : mu_(mu) {
     this->mu_->LockWhen(cond);
@@ -602,7 +609,7 @@
   ~MutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->Unlock(); }
 
  private:
-  Mutex* const mu_;
+  Mutex* absl_nonnull const mu_;
 };
 
 // ReaderMutexLock
@@ -611,11 +618,12 @@
 // releases a shared lock on a `Mutex` via RAII.
 class ABSL_SCOPED_LOCKABLE ReaderMutexLock {
  public:
-  explicit ReaderMutexLock(Mutex* mu) ABSL_SHARED_LOCK_FUNCTION(mu) : mu_(mu) {
+  explicit ReaderMutexLock(Mutex* absl_nonnull mu) ABSL_SHARED_LOCK_FUNCTION(mu)
+      : mu_(mu) {
     mu->ReaderLock();
   }
 
-  explicit ReaderMutexLock(Mutex* mu, const Condition& cond)
+  explicit ReaderMutexLock(Mutex* absl_nonnull mu, const Condition& cond)
       ABSL_SHARED_LOCK_FUNCTION(mu)
       : mu_(mu) {
     mu->ReaderLockWhen(cond);
@@ -629,7 +637,7 @@
   ~ReaderMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->ReaderUnlock(); }
 
  private:
-  Mutex* const mu_;
+  Mutex* absl_nonnull const mu_;
 };
 
 // WriterMutexLock
@@ -638,12 +646,13 @@
 // releases a write (exclusive) lock on a `Mutex` via RAII.
 class ABSL_SCOPED_LOCKABLE WriterMutexLock {
  public:
-  explicit WriterMutexLock(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+  explicit WriterMutexLock(Mutex* absl_nonnull mu)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
       : mu_(mu) {
     mu->WriterLock();
   }
 
-  explicit WriterMutexLock(Mutex* mu, const Condition& cond)
+  explicit WriterMutexLock(Mutex* absl_nonnull mu, const Condition& cond)
       ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
       : mu_(mu) {
     mu->WriterLockWhen(cond);
@@ -657,7 +666,7 @@
   ~WriterMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->WriterUnlock(); }
 
  private:
-  Mutex* const mu_;
+  Mutex* absl_nonnull const mu_;
 };
 
 // -----------------------------------------------------------------------------
@@ -715,7 +724,8 @@
 class Condition {
  public:
   // A Condition that returns the result of "(*func)(arg)"
-  Condition(bool (*func)(void*), void* arg);
+  Condition(bool (*absl_nonnull func)(void* absl_nullability_unknown),
+            void* absl_nullability_unknown arg);
 
   // Templated version for people who are averse to casts.
   //
@@ -727,7 +737,8 @@
   //
   // See class comment for performance advice.
   template <typename T>
-  Condition(bool (*func)(T*), T* arg);
+  Condition(bool (*absl_nonnull func)(T* absl_nullability_unknown),
+            T* absl_nullability_unknown arg);
 
   // Same as above, but allows for cases where `arg` comes from a pointer that
   // is convertible to the function parameter type `T*` but not an exact match.
@@ -741,8 +752,10 @@
   // a function template is passed as `func`. Also, the dummy `typename = void`
   // template parameter exists just to work around a MSVC mangling bug.
   template <typename T, typename = void>
-  Condition(bool (*func)(T*),
-            typename absl::internal::type_identity<T>::type* arg);
+  Condition(
+      bool (*absl_nonnull func)(T* absl_nullability_unknown),
+      typename absl::internal::type_identity<T>::type* absl_nullability_unknown
+      arg);
 
   // Templated version for invoking a method that returns a `bool`.
   //
@@ -753,16 +766,19 @@
   // methods to come from base classes. A simpler signature like
   // `Condition(T*, bool (T::*)())` does not suffice.
   template <typename T>
-  Condition(T* object,
-            bool (absl::internal::type_identity<T>::type::*method)());
+  Condition(
+      T* absl_nonnull object,
+      bool (absl::internal::type_identity<T>::type::* absl_nonnull method)());
 
   // Same as above, for const members
   template <typename T>
-  Condition(const T* object,
-            bool (absl::internal::type_identity<T>::type::*method)() const);
+  Condition(
+      const T* absl_nonnull object,
+      bool (absl::internal::type_identity<T>::type::* absl_nonnull method)()
+          const);
 
   // A Condition that returns the value of `*cond`
-  explicit Condition(const bool* cond);
+  explicit Condition(const bool* absl_nonnull cond);
 
   // Templated version for invoking a functor that returns a `bool`.
   // This approach accepts pointers to non-mutable lambdas, `std::function`,
@@ -791,7 +807,7 @@
   // `bool operator() const`.
   template <typename T, typename E = decltype(static_cast<bool (T::*)() const>(
                             &T::operator()))>
-  explicit Condition(const T* obj)
+  explicit Condition(const T* absl_nonnull obj)
       : Condition(obj, static_cast<bool (T::*)() const>(&T::operator())) {}
 
   // A Condition that always returns `true`.
@@ -817,7 +833,8 @@
   // Two `Condition` values are guaranteed equal if both their `func` and `arg`
   // components are the same. A null pointer is equivalent to a `true`
   // condition.
-  static bool GuaranteedEqual(const Condition* a, const Condition* b);
+  static bool GuaranteedEqual(const Condition* absl_nullable a,
+                              const Condition* absl_nullable b);
 
  private:
   // Sizing an allocation for a method pointer can be subtle. In the Itanium
@@ -842,17 +859,17 @@
 #endif
 
   // Function with which to evaluate callbacks and/or arguments.
-  bool (*eval_)(const Condition*) = nullptr;
+  bool (*absl_nullable eval_)(const Condition* absl_nonnull) = nullptr;
 
   // Either an argument for a function call or an object for a method call.
-  void* arg_ = nullptr;
+  void* absl_nullable arg_ = nullptr;
 
   // Various functions eval_ can point to:
-  static bool CallVoidPtrFunction(const Condition*);
+  static bool CallVoidPtrFunction(const Condition* absl_nonnull c);
   template <typename T>
-  static bool CastAndCallFunction(const Condition* c);
+  static bool CastAndCallFunction(const Condition* absl_nonnull c);
   template <typename T, typename ConditionMethodPtr>
-  static bool CastAndCallMethod(const Condition* c);
+  static bool CastAndCallMethod(const Condition* absl_nonnull c);
 
   // Helper methods for storing, validating, and reading callback arguments.
   template <typename T>
@@ -864,11 +881,11 @@
   }
 
   template <typename T>
-  inline void ReadCallback(T* callback) const {
+  inline void ReadCallback(T* absl_nonnull callback) const {
     std::memcpy(callback, callback_, sizeof(*callback));
   }
 
-  static bool AlwaysTrue(const Condition*) { return true; }
+  static bool AlwaysTrue(const Condition* absl_nullable) { return true; }
 
   // Used only to create kTrue.
   constexpr Condition() : eval_(AlwaysTrue), arg_(nullptr) {}
@@ -922,7 +939,7 @@
   // spurious wakeup), then reacquires the `Mutex` and returns.
   //
   // Requires and ensures that the current thread holds the `Mutex`.
-  void Wait(Mutex* mu) {
+  void Wait(Mutex* absl_nonnull mu) {
     WaitCommon(mu, synchronization_internal::KernelTimeout::Never());
   }
 
@@ -939,7 +956,7 @@
   // to return `true` or `false`.
   //
   // Requires and ensures that the current thread holds the `Mutex`.
-  bool WaitWithTimeout(Mutex* mu, absl::Duration timeout) {
+  bool WaitWithTimeout(Mutex* absl_nonnull mu, absl::Duration timeout) {
     return WaitCommon(mu, synchronization_internal::KernelTimeout(timeout));
   }
 
@@ -958,7 +975,7 @@
   // to return `true` or `false`.
   //
   // Requires and ensures that the current thread holds the `Mutex`.
-  bool WaitWithDeadline(Mutex* mu, absl::Time deadline) {
+  bool WaitWithDeadline(Mutex* absl_nonnull mu, absl::Time deadline) {
     return WaitCommon(mu, synchronization_internal::KernelTimeout(deadline));
   }
 
@@ -977,11 +994,12 @@
   // Causes all subsequent uses of this `CondVar` to be logged via
   // `ABSL_RAW_LOG(INFO)`. Log entries are tagged with `name` if `name != 0`.
   // Note: this method substantially reduces `CondVar` performance.
-  void EnableDebugLog(const char* name);
+  void EnableDebugLog(const char* absl_nullable name);
 
  private:
-  bool WaitCommon(Mutex* mutex, synchronization_internal::KernelTimeout t);
-  void Remove(base_internal::PerThreadSynch* s);
+  bool WaitCommon(Mutex* absl_nonnull mutex,
+                  synchronization_internal::KernelTimeout t);
+  void Remove(base_internal::PerThreadSynch* absl_nonnull s);
   std::atomic<intptr_t> cv_;  // Condition variable state.
   CondVar(const CondVar&) = delete;
   CondVar& operator=(const CondVar&) = delete;
@@ -997,14 +1015,15 @@
 // MutexLockMaybe is like MutexLock, but is a no-op when mu is null.
 class ABSL_SCOPED_LOCKABLE MutexLockMaybe {
  public:
-  explicit MutexLockMaybe(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+  explicit MutexLockMaybe(Mutex* absl_nullable mu)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
       : mu_(mu) {
     if (this->mu_ != nullptr) {
       this->mu_->Lock();
     }
   }
 
-  explicit MutexLockMaybe(Mutex* mu, const Condition& cond)
+  explicit MutexLockMaybe(Mutex* absl_nullable mu, const Condition& cond)
       ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
       : mu_(mu) {
     if (this->mu_ != nullptr) {
@@ -1019,7 +1038,7 @@
   }
 
  private:
-  Mutex* const mu_;
+  Mutex* absl_nullable const mu_;
   MutexLockMaybe(const MutexLockMaybe&) = delete;
   MutexLockMaybe(MutexLockMaybe&&) = delete;
   MutexLockMaybe& operator=(const MutexLockMaybe&) = delete;
@@ -1032,12 +1051,13 @@
 // mutex before destruction. `Release()` may be called at most once.
 class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
  public:
-  explicit ReleasableMutexLock(Mutex* mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+  explicit ReleasableMutexLock(Mutex* absl_nonnull mu)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
       : mu_(mu) {
     this->mu_->Lock();
   }
 
-  explicit ReleasableMutexLock(Mutex* mu, const Condition& cond)
+  explicit ReleasableMutexLock(Mutex* absl_nonnull mu, const Condition& cond)
       ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
       : mu_(mu) {
     this->mu_->LockWhen(cond);
@@ -1052,7 +1072,7 @@
   void Release() ABSL_UNLOCK_FUNCTION();
 
  private:
-  Mutex* mu_;
+  Mutex* absl_nonnull mu_;
   ReleasableMutexLock(const ReleasableMutexLock&) = delete;
   ReleasableMutexLock(ReleasableMutexLock&&) = delete;
   ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete;
@@ -1084,7 +1104,7 @@
 
 // static
 template <typename T, typename ConditionMethodPtr>
-bool Condition::CastAndCallMethod(const Condition* c) {
+bool Condition::CastAndCallMethod(const Condition* absl_nonnull c) {
   T* object = static_cast<T*>(c->arg_);
   ConditionMethodPtr condition_method_pointer;
   c->ReadCallback(&condition_method_pointer);
@@ -1093,7 +1113,7 @@
 
 // static
 template <typename T>
-bool Condition::CastAndCallFunction(const Condition* c) {
+bool Condition::CastAndCallFunction(const Condition* absl_nonnull c) {
   bool (*function)(T*);
   c->ReadCallback(&function);
   T* argument = static_cast<T*>(c->arg_);
@@ -1101,7 +1121,9 @@
 }
 
 template <typename T>
-inline Condition::Condition(bool (*func)(T*), T* arg)
+inline Condition::Condition(
+    bool (*absl_nonnull func)(T* absl_nullability_unknown),
+    T* absl_nullability_unknown arg)
     : eval_(&CastAndCallFunction<T>),
       arg_(const_cast<void*>(static_cast<const void*>(arg))) {
   static_assert(sizeof(&func) <= sizeof(callback_),
@@ -1111,13 +1133,16 @@
 
 template <typename T, typename>
 inline Condition::Condition(
-    bool (*func)(T*), typename absl::internal::type_identity<T>::type* arg)
+    bool (*absl_nonnull func)(T* absl_nullability_unknown),
+    typename absl::internal::type_identity<T>::type* absl_nullability_unknown
+    arg)
     // Just delegate to the overload above.
     : Condition(func, arg) {}
 
 template <typename T>
 inline Condition::Condition(
-    T* object, bool (absl::internal::type_identity<T>::type::*method)())
+    T* absl_nonnull object,
+    bool (absl::internal::type_identity<T>::type::* absl_nonnull method)())
     : eval_(&CastAndCallMethod<T, decltype(method)>), arg_(object) {
   static_assert(sizeof(&method) <= sizeof(callback_),
                 "An overlarge method pointer was passed to Condition.");
@@ -1126,8 +1151,9 @@
 
 template <typename T>
 inline Condition::Condition(
-    const T* object,
-    bool (absl::internal::type_identity<T>::type::*method)() const)
+    const T* absl_nonnull object,
+    bool (absl::internal::type_identity<T>::type::* absl_nonnull method)()
+        const)
     : eval_(&CastAndCallMethod<const T, decltype(method)>),
       arg_(reinterpret_cast<void*>(const_cast<T*>(object))) {
   StoreCallback(method);
@@ -1145,7 +1171,7 @@
 // binary; if this function is called a second time with a different function
 // pointer, the value is ignored (and will cause an assertion failure in debug
 // mode.)
-void RegisterMutexProfiler(void (*fn)(int64_t wait_cycles));
+void RegisterMutexProfiler(void (*absl_nonnull fn)(int64_t wait_cycles));
 
 // Register a hook for Mutex tracing.
 //
@@ -1159,8 +1185,9 @@
 //
 // This has the same ordering and single-use limitations as
 // RegisterMutexProfiler() above.
-void RegisterMutexTracer(void (*fn)(const char* msg, const void* obj,
-                                    int64_t wait_cycles));
+void RegisterMutexTracer(void (*absl_nonnull fn)(const char* absl_nonnull msg,
+                                                 const void* absl_nonnull obj,
+                                                 int64_t wait_cycles));
 
 // Register a hook for CondVar tracing.
 //
@@ -1174,7 +1201,8 @@
 //
 // This has the same ordering and single-use limitations as
 // RegisterMutexProfiler() above.
-void RegisterCondVarTracer(void (*fn)(const char* msg, const void* cv));
+void RegisterCondVarTracer(void (*absl_nonnull fn)(
+    const char* absl_nonnull msg, const void* absl_nonnull cv));
 
 // EnableMutexInvariantDebugging()
 //
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index bb93abc..a3eb3db 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -36,6 +36,7 @@
 #include "absl/log/check.h"
 #include "absl/log/log.h"
 #include "absl/memory/memory.h"
+#include "absl/random/random.h"
 #include "absl/synchronization/internal/create_thread_identity.h"
 #include "absl/synchronization/internal/thread_pool.h"
 #include "absl/time/clock.h"
@@ -1064,8 +1065,7 @@
 
 static void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv,
                                      int *running) {
-  std::random_device dev;
-  std::mt19937 gen(dev());
+  absl::InsecureBitGen gen;
   std::uniform_int_distribution<int> random_millis(0, 15);
   mu->ReaderLock();
   while (*running == 3) {
@@ -1357,7 +1357,7 @@
 
 // Returns true if `actual_delay` is close enough to `expected_delay` to pass
 // the timeouts/deadlines test.  Otherwise, logs warnings and returns false.
-ABSL_MUST_USE_RESULT
+[[nodiscard]]
 static bool DelayIsWithinBounds(absl::Duration expected_delay,
                                 absl::Duration actual_delay) {
   bool pass = true;
@@ -1725,7 +1725,7 @@
 TEST(Mutex, LoggingAddressReuse) {
   // Repeatedly re-create a Mutex with debug logging at the same address.
   ScopedInvariantDebugging scoped_debugging;
-  alignas(absl::Mutex) char storage[sizeof(absl::Mutex)];
+  alignas(absl::Mutex) unsigned char storage[sizeof(absl::Mutex)];
   auto invariant =
       +[](void *alive) { EXPECT_TRUE(*static_cast<bool *>(alive)); };
   constexpr size_t kIters = 10;
diff --git a/absl/synchronization/notification.cc b/absl/synchronization/notification.cc
index 165ba66..a5853ab 100644
--- a/absl/synchronization/notification.cc
+++ b/absl/synchronization/notification.cc
@@ -17,6 +17,7 @@
 #include <atomic>
 
 #include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/tracing.h"
 #include "absl/synchronization/mutex.h"
 #include "absl/time/time.h"
 
@@ -24,6 +25,7 @@
 ABSL_NAMESPACE_BEGIN
 
 void Notification::Notify() {
+  base_internal::TraceSignal(this, TraceObjectKind());
   MutexLock l(&this->mutex_);
 
 #ifndef NDEBUG
@@ -45,31 +47,37 @@
 }
 
 void Notification::WaitForNotification() const {
+  base_internal::TraceWait(this, TraceObjectKind());
   if (!HasBeenNotifiedInternal(&this->notified_yet_)) {
-    this->mutex_.LockWhen(Condition(&HasBeenNotifiedInternal,
-                                    &this->notified_yet_));
+    this->mutex_.LockWhen(
+        Condition(&HasBeenNotifiedInternal, &this->notified_yet_));
     this->mutex_.Unlock();
   }
+  base_internal::TraceContinue(this, TraceObjectKind());
 }
 
 bool Notification::WaitForNotificationWithTimeout(
     absl::Duration timeout) const {
+  base_internal::TraceWait(this, TraceObjectKind());
   bool notified = HasBeenNotifiedInternal(&this->notified_yet_);
   if (!notified) {
     notified = this->mutex_.LockWhenWithTimeout(
         Condition(&HasBeenNotifiedInternal, &this->notified_yet_), timeout);
     this->mutex_.Unlock();
   }
+  base_internal::TraceContinue(notified ? this : nullptr, TraceObjectKind());
   return notified;
 }
 
 bool Notification::WaitForNotificationWithDeadline(absl::Time deadline) const {
+  base_internal::TraceWait(this, TraceObjectKind());
   bool notified = HasBeenNotifiedInternal(&this->notified_yet_);
   if (!notified) {
     notified = this->mutex_.LockWhenWithDeadline(
         Condition(&HasBeenNotifiedInternal, &this->notified_yet_), deadline);
     this->mutex_.Unlock();
   }
+  base_internal::TraceContinue(notified ? this : nullptr, TraceObjectKind());
   return notified;
 }
 
diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h
index 8986d9a..1ceffdb 100644
--- a/absl/synchronization/notification.h
+++ b/absl/synchronization/notification.h
@@ -53,6 +53,7 @@
 #include <atomic>
 
 #include "absl/base/attributes.h"
+#include "absl/base/internal/tracing.h"
 #include "absl/synchronization/mutex.h"
 #include "absl/time/time.h"
 
@@ -74,8 +75,12 @@
   // Notification::HasBeenNotified()
   //
   // Returns the value of the notification's internal "notified" state.
-  ABSL_MUST_USE_RESULT bool HasBeenNotified() const {
-    return HasBeenNotifiedInternal(&this->notified_yet_);
+  [[nodiscard]] bool HasBeenNotified() const {
+    if (HasBeenNotifiedInternal(&this->notified_yet_)) {
+      base_internal::TraceObserved(this, TraceObjectKind());
+      return true;
+    }
+    return false;
   }
 
   // Notification::WaitForNotification()
@@ -108,6 +113,11 @@
   void Notify();
 
  private:
+  // Convenience helper to reduce verbosity at call sites.
+  static inline constexpr base_internal::ObjectKind TraceObjectKind() {
+    return base_internal::ObjectKind::kNotification;
+  }
+
   static inline bool HasBeenNotifiedInternal(
       const std::atomic<bool>* notified_yet) {
     return notified_yet->load(std::memory_order_acquire);
diff --git a/absl/synchronization/notification_test.cc b/absl/synchronization/notification_test.cc
index 49ce61a..eedad17 100644
--- a/absl/synchronization/notification_test.cc
+++ b/absl/synchronization/notification_test.cc
@@ -15,10 +15,15 @@
 #include "absl/synchronization/notification.h"
 
 #include <thread>  // NOLINT(build/c++11)
+#include <tuple>
 #include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/tracing.h"
 #include "absl/synchronization/mutex.h"
+#include "absl/time/time.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -79,7 +84,11 @@
 
   // Allow for a slight early return, to account for quality of implementation
   // issues on various platforms.
-  const absl::Duration slop = absl::Milliseconds(5);
+  absl::Duration slop = absl::Milliseconds(5);
+#ifdef _MSC_VER
+  // Avoid flakiness on MSVC.
+  slop = absl::Milliseconds(15);
+#endif
   EXPECT_LE(delay - slop, elapsed)
       << "WaitForNotificationWithTimeout returned " << delay - elapsed
       << " early (with " << slop << " slop), start time was " << start;
@@ -129,5 +138,93 @@
   BasicTests(true, &local_notification2);
 }
 
+#if ABSL_HAVE_ATTRIBUTE_WEAK
+
+namespace base_internal {
+
+namespace {
+
+using TraceRecord = std::tuple<const void*, ObjectKind>;
+
+thread_local TraceRecord tls_signal;
+thread_local TraceRecord tls_wait;
+thread_local TraceRecord tls_continue;
+thread_local TraceRecord tls_observed;
+
+}  // namespace
+
+// Strong extern "C" implementation.
+extern "C" {
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceWait)(const void* object,
+                                                   ObjectKind kind) {
+  tls_wait = {object, kind};
+}
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceContinue)(const void* object,
+                                                       ObjectKind kind) {
+  tls_continue = {object, kind};
+}
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceSignal)(const void* object,
+                                                     ObjectKind kind) {
+  tls_signal = {object, kind};
+}
+
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalTraceObserved)(const void* object,
+                                                       ObjectKind kind) {
+  tls_observed = {object, kind};
+}
+
+}  // extern "C"
+
+TEST(NotificationTest, TracesNotify) {
+  Notification n;
+  tls_signal = {};
+  n.Notify();
+  EXPECT_EQ(tls_signal, TraceRecord(&n, ObjectKind::kNotification));
+}
+
+TEST(NotificationTest, TracesWaitForNotification) {
+  Notification n;
+  n.Notify();
+  tls_wait = tls_continue = {};
+  n.WaitForNotification();
+  EXPECT_EQ(tls_wait, TraceRecord(&n, ObjectKind::kNotification));
+  EXPECT_EQ(tls_continue, TraceRecord(&n, ObjectKind::kNotification));
+}
+
+TEST(NotificationTest, TracesWaitForNotificationWithTimeout) {
+  Notification n;
+
+  tls_wait = tls_continue = {};
+  n.WaitForNotificationWithTimeout(absl::Milliseconds(1));
+  EXPECT_EQ(tls_wait, TraceRecord(&n, ObjectKind::kNotification));
+  EXPECT_EQ(tls_continue, TraceRecord(nullptr, ObjectKind::kNotification));
+
+  n.Notify();
+  tls_wait = tls_continue = {};
+  n.WaitForNotificationWithTimeout(absl::Milliseconds(1));
+  EXPECT_EQ(tls_wait, TraceRecord(&n, ObjectKind::kNotification));
+  EXPECT_EQ(tls_continue, TraceRecord(&n, ObjectKind::kNotification));
+}
+
+TEST(NotificationTest, TracesHasBeenNotified) {
+  Notification n;
+
+  tls_observed = {};
+  ASSERT_FALSE(n.HasBeenNotified());
+  EXPECT_EQ(tls_observed, TraceRecord(nullptr, ObjectKind::kUnknown));
+
+  n.Notify();
+  tls_observed = {};
+  ASSERT_TRUE(n.HasBeenNotified());
+  EXPECT_EQ(tls_observed, TraceRecord(&n, ObjectKind::kNotification));
+}
+
+}  // namespace base_internal
+
+#endif  // ABSL_HAVE_ATTRIBUTE_WEAK
+
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index 05f1f2f..ad0313c 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -57,6 +57,7 @@
         "//absl/base:raw_logging_internal",
         "//absl/numeric:int128",
         "//absl/strings",
+        "//absl/strings:string_view",
         "//absl/time/internal/cctz:civil_time",
         "//absl/time/internal/cctz:time_zone",
         "//absl/types:optional",
@@ -90,18 +91,19 @@
     ],
     copts = ABSL_TEST_COPTS,
     data = ["//absl/time/internal/cctz:zoneinfo"],
-    env = {"TZDIR": "absl/time/internal/cctz/testdata/zoneinfo"},
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":test_util",
         ":time",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/hash:hash_testing",
         "//absl/numeric:int128",
+        "//absl/random",
         "//absl/strings:str_format",
         "//absl/time/internal/cctz:time_zone",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -125,13 +127,14 @@
         ":time",
         "//absl/flags:flag",
         "//absl/flags:reflection",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
-cc_test(
+cc_binary(
     name = "time_benchmark",
+    testonly = True,
     srcs = [
         "civil_time_benchmark.cc",
         "clock_benchmark.cc",
@@ -141,7 +144,6 @@
     ],
     copts = ABSL_TEST_COPTS,
     data = ["//absl/time/internal/cctz:zoneinfo"],
-    env = {"TZDIR": "absl/time/internal/cctz/testdata/zoneinfo"},
     linkopts = ABSL_DEFAULT_LINKOPTS,
     tags = [
         "benchmark",
@@ -153,6 +155,6 @@
         "//absl/base:core_headers",
         "//absl/flags:flag",
         "//absl/hash",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt
index fe625f2..ea91ba3 100644
--- a/absl/time/CMakeLists.txt
+++ b/absl/time/CMakeLists.txt
@@ -49,7 +49,7 @@
     "internal/cctz/include/cctz/civil_time.h"
     "internal/cctz/include/cctz/civil_time_detail.h"
   SRCS
-  "internal/cctz/src/civil_time_detail.cc"
+    "internal/cctz/src/civil_time_detail.cc"
   COPTS
     ${ABSL_DEFAULT_COPTS}
 )
@@ -121,6 +121,8 @@
     absl::time
     absl::config
     absl::core_headers
+    absl::hash_testing
+    absl::random_random
     absl::strings
     absl::str_format
     absl::time_zone
diff --git a/absl/time/civil_time.cc b/absl/time/civil_time.cc
index 65df39d..1773366 100644
--- a/absl/time/civil_time.cc
+++ b/absl/time/civil_time.cc
@@ -14,6 +14,7 @@
 
 #include "absl/time/civil_time.h"
 
+#include <cerrno>
 #include <cstdlib>
 #include <ostream>
 #include <string>
diff --git a/absl/time/civil_time_test.cc b/absl/time/civil_time_test.cc
index 19292a9..6e5c35d 100644
--- a/absl/time/civil_time_test.cc
+++ b/absl/time/civil_time_test.cc
@@ -21,6 +21,7 @@
 
 #include "gtest/gtest.h"
 #include "absl/base/macros.h"
+#include "absl/hash/hash_testing.h"
 #include "absl/strings/str_format.h"
 
 namespace {
@@ -1259,4 +1260,137 @@
   }
 }
 
+TEST(CivilTime, SupportsHash) {
+  // To check that every field is used by the hash implementation, test
+  // with values that have all fields the same bar one, for each field.
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      absl::CivilYear(2017),
+      absl::CivilYear(2018),
+  }));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      absl::CivilMonth(2017, 1),
+      absl::CivilMonth(2017, 2),
+      absl::CivilMonth(2018, 1),
+      absl::CivilMonth(2018, 2),
+  }));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      absl::CivilDay(2017, 1, 1),
+      absl::CivilDay(2017, 1, 2),
+      absl::CivilDay(2017, 2, 1),
+      absl::CivilDay(2017, 2, 2),
+      absl::CivilDay(2018, 1, 1),
+      absl::CivilDay(2018, 1, 2),
+      absl::CivilDay(2018, 2, 1),
+      absl::CivilDay(2018, 2, 2),
+  }));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      absl::CivilHour(2017, 1, 1, 0),
+      absl::CivilHour(2017, 1, 1, 1),
+      absl::CivilHour(2017, 1, 2, 0),
+      absl::CivilHour(2017, 1, 2, 1),
+      absl::CivilHour(2017, 2, 1, 0),
+      absl::CivilHour(2017, 2, 1, 1),
+      absl::CivilHour(2017, 2, 2, 0),
+      absl::CivilHour(2017, 2, 2, 1),
+      absl::CivilHour(2018, 1, 1, 0),
+      absl::CivilHour(2018, 1, 1, 1),
+      absl::CivilHour(2018, 1, 2, 0),
+      absl::CivilHour(2018, 1, 2, 1),
+      absl::CivilHour(2018, 2, 1, 0),
+      absl::CivilHour(2018, 2, 1, 1),
+      absl::CivilHour(2018, 2, 2, 0),
+      absl::CivilHour(2018, 2, 2, 1),
+  }));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      absl::CivilMinute(2017, 1, 1, 0, 0), absl::CivilMinute(2017, 1, 1, 0, 1),
+      absl::CivilMinute(2017, 1, 1, 1, 0), absl::CivilMinute(2017, 1, 1, 1, 1),
+      absl::CivilMinute(2017, 1, 2, 0, 0), absl::CivilMinute(2017, 1, 2, 0, 1),
+      absl::CivilMinute(2017, 1, 2, 1, 0), absl::CivilMinute(2017, 1, 2, 1, 1),
+      absl::CivilMinute(2017, 2, 1, 0, 0), absl::CivilMinute(2017, 2, 1, 0, 1),
+      absl::CivilMinute(2017, 2, 1, 1, 0), absl::CivilMinute(2017, 2, 1, 1, 1),
+      absl::CivilMinute(2017, 2, 2, 0, 0), absl::CivilMinute(2017, 2, 2, 0, 1),
+      absl::CivilMinute(2017, 2, 2, 1, 0), absl::CivilMinute(2017, 2, 2, 1, 1),
+      absl::CivilMinute(2018, 1, 1, 0, 0), absl::CivilMinute(2018, 1, 1, 0, 1),
+      absl::CivilMinute(2018, 1, 1, 1, 0), absl::CivilMinute(2018, 1, 1, 1, 1),
+      absl::CivilMinute(2018, 1, 2, 0, 0), absl::CivilMinute(2018, 1, 2, 0, 1),
+      absl::CivilMinute(2018, 1, 2, 1, 0), absl::CivilMinute(2018, 1, 2, 1, 1),
+      absl::CivilMinute(2018, 2, 1, 0, 0), absl::CivilMinute(2018, 2, 1, 0, 1),
+      absl::CivilMinute(2018, 2, 1, 1, 0), absl::CivilMinute(2018, 2, 1, 1, 1),
+      absl::CivilMinute(2018, 2, 2, 0, 0), absl::CivilMinute(2018, 2, 2, 0, 1),
+      absl::CivilMinute(2018, 2, 2, 1, 0), absl::CivilMinute(2018, 2, 2, 1, 1),
+  }));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      absl::CivilSecond(2017, 1, 1, 0, 0, 0),
+      absl::CivilSecond(2017, 1, 1, 0, 0, 1),
+      absl::CivilSecond(2017, 1, 1, 0, 1, 0),
+      absl::CivilSecond(2017, 1, 1, 0, 1, 1),
+      absl::CivilSecond(2017, 1, 1, 1, 0, 0),
+      absl::CivilSecond(2017, 1, 1, 1, 0, 1),
+      absl::CivilSecond(2017, 1, 1, 1, 1, 0),
+      absl::CivilSecond(2017, 1, 1, 1, 1, 1),
+      absl::CivilSecond(2017, 1, 2, 0, 0, 0),
+      absl::CivilSecond(2017, 1, 2, 0, 0, 1),
+      absl::CivilSecond(2017, 1, 2, 0, 1, 0),
+      absl::CivilSecond(2017, 1, 2, 0, 1, 1),
+      absl::CivilSecond(2017, 1, 2, 1, 0, 0),
+      absl::CivilSecond(2017, 1, 2, 1, 0, 1),
+      absl::CivilSecond(2017, 1, 2, 1, 1, 0),
+      absl::CivilSecond(2017, 1, 2, 1, 1, 1),
+      absl::CivilSecond(2017, 2, 1, 0, 0, 0),
+      absl::CivilSecond(2017, 2, 1, 0, 0, 1),
+      absl::CivilSecond(2017, 2, 1, 0, 1, 0),
+      absl::CivilSecond(2017, 2, 1, 0, 1, 1),
+      absl::CivilSecond(2017, 2, 1, 1, 0, 0),
+      absl::CivilSecond(2017, 2, 1, 1, 0, 1),
+      absl::CivilSecond(2017, 2, 1, 1, 1, 0),
+      absl::CivilSecond(2017, 2, 1, 1, 1, 1),
+      absl::CivilSecond(2017, 2, 2, 0, 0, 0),
+      absl::CivilSecond(2017, 2, 2, 0, 0, 1),
+      absl::CivilSecond(2017, 2, 2, 0, 1, 0),
+      absl::CivilSecond(2017, 2, 2, 0, 1, 1),
+      absl::CivilSecond(2017, 2, 2, 1, 0, 0),
+      absl::CivilSecond(2017, 2, 2, 1, 0, 1),
+      absl::CivilSecond(2017, 2, 2, 1, 1, 0),
+      absl::CivilSecond(2017, 2, 2, 1, 1, 1),
+      absl::CivilSecond(2018, 1, 1, 0, 0, 0),
+      absl::CivilSecond(2018, 1, 1, 0, 0, 1),
+      absl::CivilSecond(2018, 1, 1, 0, 1, 0),
+      absl::CivilSecond(2018, 1, 1, 0, 1, 1),
+      absl::CivilSecond(2018, 1, 1, 1, 0, 0),
+      absl::CivilSecond(2018, 1, 1, 1, 0, 1),
+      absl::CivilSecond(2018, 1, 1, 1, 1, 0),
+      absl::CivilSecond(2018, 1, 1, 1, 1, 1),
+      absl::CivilSecond(2018, 1, 2, 0, 0, 0),
+      absl::CivilSecond(2018, 1, 2, 0, 0, 1),
+      absl::CivilSecond(2018, 1, 2, 0, 1, 0),
+      absl::CivilSecond(2018, 1, 2, 0, 1, 1),
+      absl::CivilSecond(2018, 1, 2, 1, 0, 0),
+      absl::CivilSecond(2018, 1, 2, 1, 0, 1),
+      absl::CivilSecond(2018, 1, 2, 1, 1, 0),
+      absl::CivilSecond(2018, 1, 2, 1, 1, 1),
+      absl::CivilSecond(2018, 2, 1, 0, 0, 0),
+      absl::CivilSecond(2018, 2, 1, 0, 0, 1),
+      absl::CivilSecond(2018, 2, 1, 0, 1, 0),
+      absl::CivilSecond(2018, 2, 1, 0, 1, 1),
+      absl::CivilSecond(2018, 2, 1, 1, 0, 0),
+      absl::CivilSecond(2018, 2, 1, 1, 0, 1),
+      absl::CivilSecond(2018, 2, 1, 1, 1, 0),
+      absl::CivilSecond(2018, 2, 1, 1, 1, 1),
+      absl::CivilSecond(2018, 2, 2, 0, 0, 0),
+      absl::CivilSecond(2018, 2, 2, 0, 0, 1),
+      absl::CivilSecond(2018, 2, 2, 0, 1, 0),
+      absl::CivilSecond(2018, 2, 2, 0, 1, 1),
+      absl::CivilSecond(2018, 2, 2, 1, 0, 0),
+      absl::CivilSecond(2018, 2, 2, 1, 0, 1),
+      absl::CivilSecond(2018, 2, 2, 1, 1, 0),
+      absl::CivilSecond(2018, 2, 2, 1, 1, 1),
+  }));
+}
+
 }  // namespace
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index 8d0b66f..38c4b63 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -202,7 +202,8 @@
     *d = -InfiniteDuration();
     return false;
   }
-  *d = time_internal::MakeDuration(c, time_internal::GetRepLo(*d));
+  *d = time_internal::MakeDuration(static_cast<int64_t>(c),
+                                   time_internal::GetRepLo(*d));
   return true;
 }
 
@@ -239,8 +240,8 @@
 template <template <typename> class Operation>
 inline Duration ScaleDouble(Duration d, double r) {
   Operation<double> op;
-  double hi_doub = op(time_internal::GetRepHi(d), r);
-  double lo_doub = op(time_internal::GetRepLo(d), r);
+  double hi_doub = op(static_cast<double>(time_internal::GetRepHi(d)), r);
+  double lo_doub = op(static_cast<double>(time_internal::GetRepLo(d)), r);
 
   double hi_int = 0;
   double hi_frac = std::modf(hi_doub, &hi_int);
@@ -253,12 +254,15 @@
   double lo_frac = std::modf(lo_doub, &lo_int);
 
   // Rolls lo into hi if necessary.
-  int64_t lo64 = std::round(lo_frac * kTicksPerSecond);
+  int64_t lo64 = static_cast<int64_t>(std::round(lo_frac * kTicksPerSecond));
 
   Duration ans;
   if (!SafeAddRepHi(hi_int, lo_int, &ans)) return ans;
   int64_t hi64 = time_internal::GetRepHi(ans);
-  if (!SafeAddRepHi(hi64, lo64 / kTicksPerSecond, &ans)) return ans;
+  if (!SafeAddRepHi(static_cast<double>(hi64),
+                    static_cast<double>(lo64 / kTicksPerSecond), &ans)) {
+    return ans;
+  }
   hi64 = time_internal::GetRepHi(ans);
   lo64 %= kTicksPerSecond;
   NormalizeTicks(&hi64, &lo64);
@@ -549,50 +553,6 @@
 //
 // Conversion to other duration types.
 //
-
-int64_t ToInt64Nanoseconds(Duration d) {
-  if (time_internal::GetRepHi(d) >= 0 &&
-      time_internal::GetRepHi(d) >> 33 == 0) {
-    return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) +
-           (time_internal::GetRepLo(d) / kTicksPerNanosecond);
-  }
-  return d / Nanoseconds(1);
-}
-int64_t ToInt64Microseconds(Duration d) {
-  if (time_internal::GetRepHi(d) >= 0 &&
-      time_internal::GetRepHi(d) >> 43 == 0) {
-    return (time_internal::GetRepHi(d) * 1000 * 1000) +
-           (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000));
-  }
-  return d / Microseconds(1);
-}
-int64_t ToInt64Milliseconds(Duration d) {
-  if (time_internal::GetRepHi(d) >= 0 &&
-      time_internal::GetRepHi(d) >> 53 == 0) {
-    return (time_internal::GetRepHi(d) * 1000) +
-           (time_internal::GetRepLo(d) / (kTicksPerNanosecond * 1000 * 1000));
-  }
-  return d / Milliseconds(1);
-}
-int64_t ToInt64Seconds(Duration d) {
-  int64_t hi = time_internal::GetRepHi(d);
-  if (time_internal::IsInfiniteDuration(d)) return hi;
-  if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
-  return hi;
-}
-int64_t ToInt64Minutes(Duration d) {
-  int64_t hi = time_internal::GetRepHi(d);
-  if (time_internal::IsInfiniteDuration(d)) return hi;
-  if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
-  return hi / 60;
-}
-int64_t ToInt64Hours(Duration d) {
-  int64_t hi = time_internal::GetRepHi(d);
-  if (time_internal::IsInfiniteDuration(d)) return hi;
-  if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
-  return hi / (60 * 60);
-}
-
 double ToDoubleNanoseconds(Duration d) {
   return FDivDuration(d, Nanoseconds(1));
 }
@@ -718,13 +678,12 @@
   int prec;
   double pow10;
 };
-ABSL_CONST_INIT const DisplayUnit kDisplayNano = {"ns", 2, 1e2};
-ABSL_CONST_INIT const DisplayUnit kDisplayMicro = {"us", 5, 1e5};
-ABSL_CONST_INIT const DisplayUnit kDisplayMilli = {"ms", 8, 1e8};
-ABSL_CONST_INIT const DisplayUnit kDisplaySec = {"s", 11, 1e11};
-ABSL_CONST_INIT const DisplayUnit kDisplayMin = {"m", -1, 0.0};  // prec ignored
-ABSL_CONST_INIT const DisplayUnit kDisplayHour = {"h", -1,
-                                                  0.0};  // prec ignored
+constexpr DisplayUnit kDisplayNano = {"ns", 2, 1e2};
+constexpr DisplayUnit kDisplayMicro = {"us", 5, 1e5};
+constexpr DisplayUnit kDisplayMilli = {"ms", 8, 1e8};
+constexpr DisplayUnit kDisplaySec = {"s", 11, 1e11};
+constexpr DisplayUnit kDisplayMin = {"m", -1, 0.0};   // prec ignored
+constexpr DisplayUnit kDisplayHour = {"h", -1, 0.0};  // prec ignored
 
 void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
   char buf[sizeof("2562047788015216")];  // hours in max duration
@@ -744,8 +703,9 @@
   char buf[kBufferSize];  // also large enough to hold integer part
   char* ep = buf + sizeof(buf);
   double d = 0;
-  int64_t frac_part = std::round(std::modf(n, &d) * unit.pow10);
-  int64_t int_part = d;
+  int64_t frac_part =
+      static_cast<int64_t>(std::round(std::modf(n, &d) * unit.pow10));
+  int64_t int_part = static_cast<int64_t>(d);
   if (int_part != 0 || frac_part != 0) {
     char* bp = Format64(ep, 0, int_part);  // always < 1000
     out->append(bp, static_cast<size_t>(ep - bp));
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc
index 4c801a8..1e3fe67 100644
--- a/absl/time/duration_test.cc
+++ b/absl/time/duration_test.cc
@@ -16,14 +16,19 @@
 #include <winsock2.h>  // for timeval
 #endif
 
+#include "absl/base/config.h"
+
+// For feature testing and determining which headers can be included.
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#include <version>
+#endif
+
 #include <array>
 #include <cfloat>
 #include <chrono>  // NOLINT(build/c++11)
-
-#ifdef __cpp_impl_three_way_comparison
+#ifdef __cpp_lib_three_way_comparison
 #include <compare>
-#endif  // __cpp_impl_three_way_comparison
-
+#endif  // __cpp_lib_three_way_comparison
 #include <cmath>
 #include <cstdint>
 #include <ctime>
@@ -31,9 +36,11 @@
 #include <limits>
 #include <random>
 #include <string>
+#include <type_traits>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/random/random.h"
 #include "absl/strings/str_format.h"
 #include "absl/time/time.h"
 
@@ -69,6 +76,8 @@
 }
 
 TEST(Duration, ConstExpr) {
+  static_assert(std::is_trivially_destructible<absl::Duration>::value,
+                "Duration is documented as being trivially destructible");
   constexpr absl::Duration d0 = absl::ZeroDuration();
   static_assert(d0 == absl::ZeroDuration(), "ZeroDuration()");
   constexpr absl::Duration d1 = absl::Seconds(1);
@@ -437,14 +446,14 @@
   EXPECT_LT(-inf, inf);
   EXPECT_GT(inf, -inf);
 
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
   EXPECT_EQ(inf <=> inf, std::strong_ordering::equal);
   EXPECT_EQ(-inf <=> -inf, std::strong_ordering::equal);
   EXPECT_EQ(-inf <=> inf, std::strong_ordering::less);
   EXPECT_EQ(inf <=> -inf, std::strong_ordering::greater);
   EXPECT_EQ(any_dur <=> inf, std::strong_ordering::less);
   EXPECT_EQ(any_dur <=> -inf, std::strong_ordering::greater);
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 }
 
 TEST(Duration, InfinityAddition) {
@@ -511,18 +520,18 @@
   absl::Duration almost_neg_inf = sec_min;
   EXPECT_LT(-inf, almost_neg_inf);
 
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
   EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less);
   EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater);
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
   almost_neg_inf -= -absl::Nanoseconds(1);
   EXPECT_LT(-inf, almost_neg_inf);
 
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
   EXPECT_EQ(-inf <=> almost_neg_inf, std::strong_ordering::less);
   EXPECT_EQ(almost_neg_inf <=> -inf, std::strong_ordering::greater);
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
   // For reference: IEEE 754 behavior
   const double dbl_inf = std::numeric_limits<double>::infinity();
@@ -883,7 +892,7 @@
   EXPECT_LT(neg_full_range, full_range);
   EXPECT_EQ(neg_full_range, -full_range);
 
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
   EXPECT_EQ(range_future <=> absl::InfiniteDuration(),
             std::strong_ordering::less);
   EXPECT_EQ(range_past <=> -absl::InfiniteDuration(),
@@ -896,7 +905,7 @@
             std::strong_ordering::greater);
   EXPECT_EQ(neg_full_range <=> full_range, std::strong_ordering::less);
   EXPECT_EQ(neg_full_range <=> -full_range, std::strong_ordering::equal);
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 }
 
 TEST(Duration, RelationalOperators) {
@@ -920,8 +929,7 @@
 #undef TEST_REL_OPS
 }
 
-
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
 TEST(Duration, SpaceshipOperators) {
 #define TEST_REL_OPS(UNIT)               \
@@ -939,7 +947,7 @@
 #undef TEST_REL_OPS
 }
 
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
 TEST(Duration, Addition) {
 #define TEST_ADD_OPS(UNIT)                  \
@@ -1507,9 +1515,7 @@
 }
 
 TEST(Duration, ToDoubleSecondsCheckRandom) {
-  std::random_device rd;
-  std::seed_seq seed({rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()});
-  std::mt19937_64 gen(seed);
+  absl::InsecureBitGen gen;
   // We want doubles distributed from 1/8ns up to 2^63, where
   // as many values are tested from 1ns to 2ns as from 1sec to 2sec,
   // so even distribute along a log-scale of those values, and
diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel
index 0b43bb1..da30a0f 100644
--- a/absl/time/internal/cctz/BUILD.bazel
+++ b/absl/time/internal/cctz/BUILD.bazel
@@ -12,6 +12,8 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
+load("//absl:copts/configure_copts.bzl", "ABSL_DEFAULT_COPTS", "ABSL_DEFAULT_LINKOPTS", "ABSL_TEST_COPTS")
+
 package(features = [
     "header_modules",
     "layering_check",
@@ -28,6 +30,8 @@
     hdrs = [
         "include/cctz/civil_time.h",
     ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
     textual_hdrs = ["include/cctz/civil_time_detail.h"],
     visibility = ["//visibility:public"],
     deps = ["//absl/base:config"],
@@ -57,7 +61,8 @@
         "include/cctz/time_zone.h",
         "include/cctz/zone_info_source.h",
     ],
-    linkopts = select({
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS + select({
         "@platforms//os:osx": ["-Wl,-framework,CoreFoundation"],
         "@platforms//os:ios": ["-Wl,-framework,CoreFoundation"],
         "//conditions:default": [],
@@ -84,11 +89,13 @@
     name = "civil_time_test",
     size = "small",
     srcs = ["src/civil_time_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":civil_time",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -96,8 +103,9 @@
     name = "time_zone_format_test",
     size = "small",
     srcs = ["src/time_zone_format_test.cc"],
+    copts = ABSL_TEST_COPTS,
     data = [":zoneinfo"],
-    env = {"TZDIR": "absl/time/internal/cctz/testdata/zoneinfo"},
+    linkopts = ABSL_DEFAULT_LINKOPTS,
     tags = [
         "no_test_android_arm",
         "no_test_android_arm64",
@@ -108,8 +116,8 @@
         ":civil_time",
         ":time_zone",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -118,8 +126,9 @@
     size = "small",
     timeout = "moderate",
     srcs = ["src/time_zone_lookup_test.cc"],
+    copts = ABSL_TEST_COPTS,
     data = [":zoneinfo"],
-    env = {"TZDIR": "absl/time/internal/cctz/testdata/zoneinfo"},
+    linkopts = ABSL_DEFAULT_LINKOPTS,
     tags = [
         "no_test_android_arm",
         "no_test_android_arm64",
@@ -130,8 +139,8 @@
         ":civil_time",
         ":time_zone",
         "//absl/base:config",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -146,22 +155,24 @@
         "src/time_zone_info.h",
         "src/tzfile.h",
     ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
     linkstatic = 1,
     tags = ["benchmark"],
     deps = [
         ":civil_time",
         ":time_zone",
         "//absl/base:config",
-        "@com_github_google_benchmark//:benchmark_main",
+        "@google_benchmark//:benchmark_main",
     ],
 )
 
+### examples
+
+### binaries
+
 filegroup(
     name = "zoneinfo",
     srcs = glob(["testdata/zoneinfo/**"]),
     visibility = ["//absl/time:__subpackages__"],
 )
-
-### examples
-
-### binaries
diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h
index b2b0cf6..5b232f5 100644
--- a/absl/time/internal/cctz/include/cctz/time_zone.h
+++ b/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -200,7 +200,7 @@
   // version() and description() provide additional information about the
   // time zone. The content of each of the returned strings is unspecified,
   // however, when the IANA Time Zone Database is the underlying data source
-  // the version() string will be in the familar form (e.g, "2018e") or
+  // the version() string will be in the familiar form (e.g, "2018e") or
   // empty when unavailable.
   //
   // Note: These functions are for informational or testing purposes only.
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
index 11f9ba6..ba7e149 100644
--- a/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -23,7 +23,7 @@
 #include "benchmark/benchmark.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
-#include "time_zone_impl.h"
+#include "absl/time/internal/cctz/src/time_zone_impl.h"
 
 namespace {
 
@@ -199,6 +199,7 @@
                                       "America/Ciudad_Juarez",
                                       "America/Coral_Harbour",
                                       "America/Costa_Rica",
+                                      "America/Coyhaique",
                                       "America/Creston",
                                       "America/Cuiaba",
                                       "America/Curacao",
@@ -215,7 +216,6 @@
                                       "America/Fort_Nelson",
                                       "America/Fortaleza",
                                       "America/Glace_Bay",
-                                      "America/Godthab",
                                       "America/Goose_Bay",
                                       "America/Grand_Turk",
                                       "America/Grenada",
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc
index e09654e..ed7f9cb 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -12,7 +12,7 @@
 //   See the License for the specific language governing permissions and
 //   limitations under the License.
 
-#include "time_zone_fixed.h"
+#include "absl/time/internal/cctz/src/time_zone_fixed.h"
 
 #include <algorithm>
 #include <cassert>
diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc
index e7e30a2..0e5f32f 100644
--- a/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/absl/time/internal/cctz/src/time_zone_format.cc
@@ -46,7 +46,7 @@
 #endif
 
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
-#include "time_zone_if.h"
+#include "absl/time/internal/cctz/src/time_zone_if.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/time/internal/cctz/src/time_zone_if.cc b/absl/time/internal/cctz/src/time_zone_if.cc
index 0e65cd9..09f83e8 100644
--- a/absl/time/internal/cctz/src/time_zone_if.cc
+++ b/absl/time/internal/cctz/src/time_zone_if.cc
@@ -12,11 +12,11 @@
 //   See the License for the specific language governing permissions and
 //   limitations under the License.
 
-#include "time_zone_if.h"
+#include "absl/time/internal/cctz/src/time_zone_if.h"
 
 #include "absl/base/config.h"
-#include "time_zone_info.h"
-#include "time_zone_libc.h"
+#include "absl/time/internal/cctz/src/time_zone_info.h"
+#include "absl/time/internal/cctz/src/time_zone_libc.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc
index aadbb77..5f2f49e 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.cc
+++ b/absl/time/internal/cctz/src/time_zone_impl.cc
@@ -12,7 +12,7 @@
 //   See the License for the specific language governing permissions and
 //   limitations under the License.
 
-#include "time_zone_impl.h"
+#include "absl/time/internal/cctz/src/time_zone_impl.h"
 
 #include <deque>
 #include <memory>
@@ -22,7 +22,7 @@
 #include <utility>
 
 #include "absl/base/config.h"
-#include "time_zone_fixed.h"
+#include "absl/time/internal/cctz/src/time_zone_fixed.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/time/internal/cctz/src/time_zone_impl.h b/absl/time/internal/cctz/src/time_zone_impl.h
index 8308a3b..da3aec5 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.h
+++ b/absl/time/internal/cctz/src/time_zone_impl.h
@@ -21,8 +21,8 @@
 #include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
-#include "time_zone_if.h"
-#include "time_zone_info.h"
+#include "absl/time/internal/cctz/src/time_zone_if.h"
+#include "absl/time/internal/cctz/src/time_zone_info.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc
index b7178a6..f8484c9 100644
--- a/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/absl/time/internal/cctz/src/time_zone_info.cc
@@ -30,7 +30,7 @@
 // Note that we assume the proleptic Gregorian calendar and 60-second
 // minutes throughout.
 
-#include "time_zone_info.h"
+#include "absl/time/internal/cctz/src/time_zone_info.h"
 
 #include <algorithm>
 #include <cassert>
@@ -49,8 +49,8 @@
 
 #include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
-#include "time_zone_fixed.h"
-#include "time_zone_posix.h"
+#include "absl/time/internal/cctz/src/time_zone_fixed.h"
+#include "absl/time/internal/cctz/src/time_zone_posix.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h
index 689df6f..efe2f9c 100644
--- a/absl/time/internal/cctz/src/time_zone_info.h
+++ b/absl/time/internal/cctz/src/time_zone_info.h
@@ -26,8 +26,8 @@
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 #include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
-#include "time_zone_if.h"
-#include "tzfile.h"
+#include "absl/time/internal/cctz/src/time_zone_if.h"
+#include "absl/time/internal/cctz/src/tzfile.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc
index b509402..362da1a 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -16,7 +16,7 @@
 #define _CRT_SECURE_NO_WARNINGS 1
 #endif
 
-#include "time_zone_libc.h"
+#include "absl/time/internal/cctz/src/time_zone_libc.h"
 
 #include <chrono>
 #include <ctime>
diff --git a/absl/time/internal/cctz/src/time_zone_libc.h b/absl/time/internal/cctz/src/time_zone_libc.h
index ae21073..f1ed5cd 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.h
+++ b/absl/time/internal/cctz/src/time_zone_libc.h
@@ -19,7 +19,7 @@
 #include <string>
 
 #include "absl/base/config.h"
-#include "time_zone_if.h"
+#include "absl/time/internal/cctz/src/time_zone_if.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc
index 8979174..90b2972 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup.cc
@@ -33,29 +33,38 @@
 #endif
 
 #if defined(_WIN32)
-#include <sdkddkver.h>
-// Include only when the SDK is for Windows 10 (and later), and the binary is
-// targeted for Windows XP and later.
-// Note: The Windows SDK added windows.globalization.h file for Windows 10, but
-// MinGW did not add it until NTDDI_WIN10_NI (SDK version 10.0.22621.0).
-#if ((defined(_WIN32_WINNT_WIN10) && !defined(__MINGW32__)) ||        \
-     (defined(NTDDI_WIN10_NI) && NTDDI_VERSION >= NTDDI_WIN10_NI)) && \
-    (_WIN32_WINNT >= _WIN32_WINNT_WINXP)
+// Include only when <icu.h> is available.
+// https://learn.microsoft.com/en-us/windows/win32/intl/international-components-for-unicode--icu-
+// https://devblogs.microsoft.com/oldnewthing/20210527-00/?p=105255
+#if defined(__has_include)
+#if __has_include(<icu.h>)
 #define USE_WIN32_LOCAL_TIME_ZONE
-#include <roapi.h>
-#include <tchar.h>
-#include <wchar.h>
-#include <windows.globalization.h>
 #include <windows.h>
-#endif
-#endif
+#pragma push_macro("_WIN32_WINNT")
+#pragma push_macro("NTDDI_VERSION")
+// Minimum _WIN32_WINNT and NTDDI_VERSION to use ucal_getTimeZoneIDForWindowsID
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0A00  // == _WIN32_WINNT_WIN10
+#undef NTDDI_VERSION
+#define NTDDI_VERSION 0x0A000004  // == NTDDI_WIN10_RS3
+#include <icu.h>
+#pragma pop_macro("NTDDI_VERSION")
+#pragma pop_macro("_WIN32_WINNT")
+#include <timezoneapi.h>
 
+#include <atomic>
+#endif  // __has_include(<icu.h>)
+#endif  // __has_include
+#endif  // _WIN32
+
+#include <array>
+#include <cstdint>
 #include <cstdlib>
 #include <cstring>
 #include <string>
 
-#include "time_zone_fixed.h"
-#include "time_zone_impl.h"
+#include "absl/time/internal/cctz/src/time_zone_fixed.h"
+#include "absl/time/internal/cctz/src/time_zone_impl.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -64,80 +73,78 @@
 
 namespace {
 #if defined(USE_WIN32_LOCAL_TIME_ZONE)
-// Calls the WinRT Calendar.GetTimeZone method to obtain the IANA ID of the
-// local time zone. Returns an empty vector in case of an error.
-std::string win32_local_time_zone(const HMODULE combase) {
-  std::string result;
-  const auto ro_activate_instance =
-      reinterpret_cast<decltype(&RoActivateInstance)>(
-          GetProcAddress(combase, "RoActivateInstance"));
-  if (!ro_activate_instance) {
-    return result;
-  }
-  const auto windows_create_string_reference =
-      reinterpret_cast<decltype(&WindowsCreateStringReference)>(
-          GetProcAddress(combase, "WindowsCreateStringReference"));
-  if (!windows_create_string_reference) {
-    return result;
-  }
-  const auto windows_delete_string =
-      reinterpret_cast<decltype(&WindowsDeleteString)>(
-          GetProcAddress(combase, "WindowsDeleteString"));
-  if (!windows_delete_string) {
-    return result;
-  }
-  const auto windows_get_string_raw_buffer =
-      reinterpret_cast<decltype(&WindowsGetStringRawBuffer)>(
-          GetProcAddress(combase, "WindowsGetStringRawBuffer"));
-  if (!windows_get_string_raw_buffer) {
-    return result;
+// True if we have already failed to load the API.
+static std::atomic_bool g_ucal_getTimeZoneIDForWindowsIDUnavailable;
+static std::atomic<decltype(ucal_getTimeZoneIDForWindowsID)*>
+    g_ucal_getTimeZoneIDForWindowsIDRef;
+
+std::string win32_local_time_zone() {
+  // If we have already failed to load the API, then just give up.
+  if (g_ucal_getTimeZoneIDForWindowsIDUnavailable.load()) {
+    return "";
   }
 
-  // The string returned by WindowsCreateStringReference doesn't need to be
-  // deleted.
-  HSTRING calendar_class_id;
-  HSTRING_HEADER calendar_class_id_header;
-  HRESULT hr = windows_create_string_reference(
-      RuntimeClass_Windows_Globalization_Calendar,
-      sizeof(RuntimeClass_Windows_Globalization_Calendar) / sizeof(wchar_t) - 1,
-      &calendar_class_id_header, &calendar_class_id);
-  if (FAILED(hr)) {
-    return result;
-  }
-
-  IInspectable* calendar;
-  hr = ro_activate_instance(calendar_class_id, &calendar);
-  if (FAILED(hr)) {
-    return result;
-  }
-
-  ABI::Windows::Globalization::ITimeZoneOnCalendar* time_zone;
-  hr = calendar->QueryInterface(IID_PPV_ARGS(&time_zone));
-  if (FAILED(hr)) {
-    calendar->Release();
-    return result;
-  }
-
-  HSTRING tz_hstr;
-  hr = time_zone->GetTimeZone(&tz_hstr);
-  if (SUCCEEDED(hr)) {
-    UINT32 wlen;
-    const PCWSTR tz_wstr = windows_get_string_raw_buffer(tz_hstr, &wlen);
-    if (tz_wstr) {
-      const int size =
-          WideCharToMultiByte(CP_UTF8, 0, tz_wstr, static_cast<int>(wlen),
-                              nullptr, 0, nullptr, nullptr);
-      result.resize(static_cast<size_t>(size));
-      WideCharToMultiByte(CP_UTF8, 0, tz_wstr, static_cast<int>(wlen),
-                          &result[0], size, nullptr, nullptr);
+  auto ucal_getTimeZoneIDForWindowsIDFunc =
+      g_ucal_getTimeZoneIDForWindowsIDRef.load();
+  if (ucal_getTimeZoneIDForWindowsIDFunc == nullptr) {
+    // If we have already failed to load the API, then just give up.
+    if (g_ucal_getTimeZoneIDForWindowsIDUnavailable.load()) {
+      return "";
     }
-    windows_delete_string(tz_hstr);
+
+    const HMODULE icudll =
+        ::LoadLibraryExW(L"icu.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
+
+    if (icudll == nullptr) {
+      g_ucal_getTimeZoneIDForWindowsIDUnavailable.store(true);
+      return "";
+    }
+
+    ucal_getTimeZoneIDForWindowsIDFunc =
+        reinterpret_cast<decltype(ucal_getTimeZoneIDForWindowsID)*>(
+            ::GetProcAddress(icudll, "ucal_getTimeZoneIDForWindowsID"));
+
+    if (ucal_getTimeZoneIDForWindowsIDFunc == nullptr) {
+      g_ucal_getTimeZoneIDForWindowsIDUnavailable.store(true);
+      return "";
+    }
+    // store-race is not a problem here, because ::GetProcAddress() returns the
+    // same address for the same function in the same DLL.
+    g_ucal_getTimeZoneIDForWindowsIDRef.store(
+        ucal_getTimeZoneIDForWindowsIDFunc);
+
+    // We intentionally do not call ::FreeLibrary() here to avoid frequent DLL
+    // loadings and unloading. As "icu.dll" is a system library, keeping it on
+    // memory is supposed to have no major drawback.
   }
-  time_zone->Release();
-  calendar->Release();
-  return result;
+
+  DYNAMIC_TIME_ZONE_INFORMATION info = {};
+  if (::GetDynamicTimeZoneInformation(&info) == TIME_ZONE_ID_INVALID) {
+    return "";
+  }
+
+  std::array<UChar, 128> buffer;
+  UErrorCode status = U_ZERO_ERROR;
+  const auto num_chars_in_buffer = ucal_getTimeZoneIDForWindowsIDFunc(
+      reinterpret_cast<const UChar*>(info.TimeZoneKeyName), -1, nullptr,
+      buffer.data(), static_cast<int32_t>(buffer.size()), &status);
+  if (status != U_ZERO_ERROR || num_chars_in_buffer <= 0 ||
+      num_chars_in_buffer > static_cast<int32_t>(buffer.size())) {
+    return "";
+  }
+
+  const int num_bytes_in_utf8 = ::WideCharToMultiByte(
+      CP_UTF8, 0, reinterpret_cast<const wchar_t*>(buffer.data()),
+      static_cast<int>(num_chars_in_buffer), nullptr, 0, nullptr, nullptr);
+  std::string local_time_str;
+  local_time_str.resize(static_cast<size_t>(num_bytes_in_utf8));
+  ::WideCharToMultiByte(
+       CP_UTF8, 0, reinterpret_cast<const wchar_t*>(buffer.data()),
+       static_cast<int>(num_chars_in_buffer), &local_time_str[0],
+       num_bytes_in_utf8, nullptr, nullptr);
+  return local_time_str;
 }
-#endif
+#endif  // USE_WIN32_LOCAL_TIME_ZONE
 }  // namespace
 
 std::string time_zone::name() const { return effective_impl().Name(); }
@@ -255,36 +262,9 @@
   }
 #endif
 #if defined(USE_WIN32_LOCAL_TIME_ZONE)
-  // Use the WinRT Calendar class to get the local time zone. This feature is
-  // available on Windows 10 and later. The library is dynamically linked to
-  // maintain binary compatibility with Windows XP - Windows 7. On Windows 8,
-  // The combase.dll API functions are available but the RoActivateInstance
-  // call will fail for the Calendar class.
-  std::string winrt_tz;
-  const HMODULE combase =
-      LoadLibraryEx(_T("combase.dll"), nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
-  if (combase) {
-    const auto ro_initialize = reinterpret_cast<decltype(&::RoInitialize)>(
-        GetProcAddress(combase, "RoInitialize"));
-    const auto ro_uninitialize = reinterpret_cast<decltype(&::RoUninitialize)>(
-        GetProcAddress(combase, "RoUninitialize"));
-    if (ro_initialize && ro_uninitialize) {
-      const HRESULT hr = ro_initialize(RO_INIT_MULTITHREADED);
-      // RPC_E_CHANGED_MODE means that a previous RoInitialize call specified
-      // a different concurrency model. The WinRT runtime is initialized and
-      // should work for our purpose here, but we should *not* call
-      // RoUninitialize because it's a failure.
-      if (SUCCEEDED(hr) || hr == RPC_E_CHANGED_MODE) {
-        winrt_tz = win32_local_time_zone(combase);
-        if (SUCCEEDED(hr)) {
-          ro_uninitialize();
-        }
-      }
-    }
-    FreeLibrary(combase);
-  }
-  if (!winrt_tz.empty()) {
-    zone = winrt_tz.c_str();
+  std::string win32_tz = win32_local_time_zone();
+  if (!win32_tz.empty()) {
+    zone = win32_tz.c_str();
   }
 #endif
 
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index 6f7e5cf..e1bea28 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -134,6 +134,7 @@
                                       "America/Ciudad_Juarez",
                                       "America/Coral_Harbour",
                                       "America/Costa_Rica",
+                                      "America/Coyhaique",
                                       "America/Creston",
                                       "America/Cuiaba",
                                       "America/Curacao",
@@ -150,7 +151,6 @@
                                       "America/Fort_Nelson",
                                       "America/Fortaleza",
                                       "America/Glace_Bay",
-                                      "America/Godthab",
                                       "America/Goose_Bay",
                                       "America/Grand_Turk",
                                       "America/Grenada",
@@ -1330,35 +1330,24 @@
   ExpectTime(tp, tz, 1983, 12, 31, 23, 59, 59, -5 * 3600, false, "EST");
 }
 
-TEST(TimeZoneEdgeCase, WET) {
-  // Cover some non-existent times within forward transitions.
-  const time_zone tz = LoadZone("WET");
+TEST(TimeZoneEdgeCase, EuropeLisbon) {
+  // Cover a non-existent time within a forward transition.
+  const time_zone tz = LoadZone("Europe/Lisbon");
 
-  // Before the first transition.
-  auto tp = convert(civil_second(1977, 1, 1, 0, 0, 0), tz);
-  ExpectTime(tp, tz, 1977, 1, 1, 0, 0, 0, 0, false, "WET");
-
-  // Over the first transition.
-  //     228877199 == Sun,  3 Apr 1977 00:59:59 +0000 (WET)
-  //     228877200 == Sun,  3 Apr 1977 02:00:00 +0100 (WEST)
-  tp = convert(civil_second(1977, 4, 3, 0, 59, 59), tz);
-  ExpectTime(tp, tz, 1977, 4, 3, 0, 59, 59, 0, false, "WET");
+  // Over a forward transition.
+  //     354671999 == Sat, 28 Mar 1981 23:59:59 +0000 (WET)
+  //     354672000 == Sun, 29 Mar 1981 01:00:00 +0100 (WEST)
+  auto tp = convert(civil_second(1981, 3, 28, 23, 59, 59), tz);
+  ExpectTime(tp, tz, 1981, 3, 28, 23, 59, 59, 0, false, "WET");
   tp += absl::time_internal::cctz::seconds(1);
-  ExpectTime(tp, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST");
+  ExpectTime(tp, tz, 1981, 3, 29, 1, 0, 0, 1 * 3600, true, "WEST");
 
-  // A non-existent time within the first transition.
-  time_zone::civil_lookup cl1 = tz.lookup(civil_second(1977, 4, 3, 1, 15, 0));
+  // A non-existent time within the transition.
+  time_zone::civil_lookup cl1 = tz.lookup(civil_second(1981, 3, 29, 0, 15, 0));
   EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl1.kind);
-  ExpectTime(cl1.pre, tz, 1977, 4, 3, 2, 15, 0, 1 * 3600, true, "WEST");
-  ExpectTime(cl1.trans, tz, 1977, 4, 3, 2, 0, 0, 1 * 3600, true, "WEST");
-  ExpectTime(cl1.post, tz, 1977, 4, 3, 0, 15, 0, 0 * 3600, false, "WET");
-
-  // A non-existent time within the second forward transition.
-  time_zone::civil_lookup cl2 = tz.lookup(civil_second(1978, 4, 2, 1, 15, 0));
-  EXPECT_EQ(time_zone::civil_lookup::SKIPPED, cl2.kind);
-  ExpectTime(cl2.pre, tz, 1978, 4, 2, 2, 15, 0, 1 * 3600, true, "WEST");
-  ExpectTime(cl2.trans, tz, 1978, 4, 2, 2, 0, 0, 1 * 3600, true, "WEST");
-  ExpectTime(cl2.post, tz, 1978, 4, 2, 0, 15, 0, 0 * 3600, false, "WET");
+  ExpectTime(cl1.pre, tz, 1981, 3, 29, 1, 15, 0, 1 * 3600, true, "WEST");
+  ExpectTime(cl1.trans, tz, 1981, 3, 29, 1, 0, 0, 1 * 3600, true, "WEST");
+  ExpectTime(cl1.post, tz, 1981, 3, 28, 23, 15, 0, 0 * 3600, false, "WET");
 }
 
 TEST(TimeZoneEdgeCase, FixedOffsets) {
diff --git a/absl/time/internal/cctz/src/time_zone_posix.cc b/absl/time/internal/cctz/src/time_zone_posix.cc
index 5cdd09e..efea080 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.cc
+++ b/absl/time/internal/cctz/src/time_zone_posix.cc
@@ -12,7 +12,7 @@
 //   See the License for the specific language governing permissions and
 //   limitations under the License.
 
-#include "time_zone_posix.h"
+#include "absl/time/internal/cctz/src/time_zone_posix.h"
 
 #include <cstddef>
 #include <cstring>
diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h
index 2be3bb8..6281438 100644
--- a/absl/time/internal/cctz/src/tzfile.h
+++ b/absl/time/internal/cctz/src/tzfile.h
@@ -25,7 +25,7 @@
 #define TZDEFRULES "posixrules"
 #endif /* !defined TZDEFRULES */
 
-/* See Internet RFC 8536 for more details about the following format.  */
+/* See Internet RFC 9636 for more details about the following format.  */
 
 /*
 ** Each file begins with. . .
@@ -75,14 +75,16 @@
 ** If tzh_version is '2' or greater, the above is followed by a second instance
 ** of tzhead and a second instance of the data in which each coded transition
 ** time uses 8 rather than 4 chars,
-** then a POSIX-TZ-environment-variable-style string for use in handling
+** then a POSIX.1-2017 proleptic TZ string for use in handling
 ** instants after the last transition time stored in the file
 ** (with nothing between the newlines if there is no POSIX.1-2017
 ** representation for such instants).
 **
-** If tz_version is '3' or greater, the above is extended as follows.
+** If tz_version is '3' or greater, the TZ string can be any POSIX.1-2024
+** proleptic TZ string, which means the above is extended as follows.
 ** First, the TZ string's hour offset may range from -167
-** through 167 as compared to the POSIX-required 0 through 24.
+** through 167 as compared to the range 0 through 24 required
+** by POSIX.1-2017 and earlier.
 ** Second, its DST start time may be January 1 at 00:00 and its stop
 ** time December 31 at 24:00 plus the difference between DST and
 ** standard time, indicating DST all year.
diff --git a/absl/time/internal/cctz/testdata/version b/absl/time/internal/cctz/testdata/version
index 04fe674..ef468ad 100644
--- a/absl/time/internal/cctz/testdata/version
+++ b/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@
-2024a
+2025b
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
index 651e5cf..581bb0e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion b/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
index 6225036..f056047 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
index 48faea2..882400b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun b/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
index 640b259..3110cdf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua b/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
index 5e0a54f..f65bb1c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Ciudad_Juarez b/absl/time/internal/cctz/testdata/zoneinfo/America/Ciudad_Juarez
index f636ee6..5f865ea 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Ciudad_Juarez
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Ciudad_Juarez
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Coyhaique b/absl/time/internal/cctz/testdata/zoneinfo/America/Coyhaique
new file mode 100644
index 0000000..26354e8
--- /dev/null
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Coyhaique
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada b/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
index 42087af..18d0d14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo b/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
index 5c92e29..ba7b147 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan b/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
index 97d4d36..5aa6039 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Merida b/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
index e5de113..e5c7d8c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City b/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
index 80a415c..1811234 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey b/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
index a5822e2..c1e0546 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga b/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
index f7e40c0..1dd08b1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel b/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
index 42087af..18d0d14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana b/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
index 42087af..18d0d14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
index 0a948c2..6f5d3a1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
index bb7be9f..22e705c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
index 3c3584e..145bb6f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
index 824acb0..6fd31e0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
index e6e2616..cda1c1d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
index cf965c3..21e8457 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/CET b/absl/time/internal/cctz/testdata/zoneinfo/CET
index 546748d..3197327 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/CET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/CET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT b/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
index d931558..b016880 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EET b/absl/time/internal/cctz/testdata/zoneinfo/EET
index 378919e..231bf9c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EST b/absl/time/internal/cctz/testdata/zoneinfo/EST
index 3ae9691..9154643 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT b/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
index 50c95e0..2b6c2ee 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
index f0c70b6..7e9aae7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/HST b/absl/time/internal/cctz/testdata/zoneinfo/HST
index 160a53e..40e3d49 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/HST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/HST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Iran b/absl/time/internal/cctz/testdata/zoneinfo/Iran
index 824acb0..6fd31e0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Iran
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Iran
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MET b/absl/time/internal/cctz/testdata/zoneinfo/MET
index 6f0558c..3197327 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MST b/absl/time/internal/cctz/testdata/zoneinfo/MST
index a0953d1..c2bd2f9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT b/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
index 137867c..09e54e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
index 42087af..18d0d14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
index 97d4d36..5aa6039 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
index 80a415c..1811234 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT b/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
index fde4833..aaf0778 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Portugal b/absl/time/internal/cctz/testdata/zoneinfo/Portugal
index f0c70b6..7e9aae7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Portugal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Portugal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/WET b/absl/time/internal/cctz/testdata/zoneinfo/WET
index 423c6c2..7e9aae7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/WET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/WET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
index abd9489..36535bd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
@@ -124,7 +124,8 @@
 CI,BF,GH,GM,GN,IS,ML,MR,SH,SL,SN,TG	+0519-00402	Africa/Abidjan
 CK	-2114-15946	Pacific/Rarotonga
 CL	-3327-07040	America/Santiago	most of Chile
-CL	-5309-07055	America/Punta_Arenas	Region of Magallanes
+CL	-4534-07204	America/Coyhaique	Aysén Region
+CL	-5309-07055	America/Punta_Arenas	Magallanes Region
 CL	-2709-10926	Pacific/Easter	Easter Island
 CN	+3114+12128	Asia/Shanghai	Beijing Time
 CN	+4348+08735	Asia/Urumqi	Xinjiang Time
@@ -183,7 +184,7 @@
 IT,SM,VA	+4154+01229	Europe/Rome
 JM	+175805-0764736	America/Jamaica
 JO	+3157+03556	Asia/Amman
-JP	+353916+1394441	Asia/Tokyo
+JP,AU	+353916+1394441	Asia/Tokyo	Eyre Bird Observatory
 KE,DJ,ER,ET,KM,MG,SO,TZ,UG,YT	-0117+03649	Africa/Nairobi
 KG	+4254+07436	Asia/Bishkek
 KI,MH,TV,UM,WF	+0125+17300	Pacific/Tarawa	Gilberts, Marshalls, Wake
@@ -209,8 +210,7 @@
 MH	+0905+16720	Pacific/Kwajalein	Kwajalein
 MM,CC	+1647+09610	Asia/Yangon
 MN	+4755+10653	Asia/Ulaanbaatar	most of Mongolia
-MN	+4801+09139	Asia/Hovd	Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan
-MN	+4804+11430	Asia/Choibalsan	Dornod, Sükhbaatar
+MN	+4801+09139	Asia/Hovd	Bayan-Ölgii, Hovd, Uvs
 MO	+221150+1133230	Asia/Macau
 MQ	+1436-06105	America/Martinique
 MT	+3554+01431	Europe/Malta
@@ -247,7 +247,7 @@
 PF	-2308-13457	Pacific/Gambier	Gambier Islands
 PG,AQ,FM	-0930+14710	Pacific/Port_Moresby	Papua New Guinea (most areas), Chuuk, Yap, Dumont d'Urville
 PG	-0613+15534	Pacific/Bougainville	Bougainville
-PH	+1435+12100	Asia/Manila
+PH	+143512+1205804	Asia/Manila
 PK	+2452+06703	Asia/Karachi
 PL	+5215+02100	Europe/Warsaw
 PM	+4703-05620	America/Miquelon
@@ -294,7 +294,7 @@
 SA,AQ,KW,YE	+2438+04643	Asia/Riyadh	Syowa
 SB,FM	-0932+16012	Pacific/Guadalcanal	Pohnpei
 SD	+1536+03232	Africa/Khartoum
-SG,MY	+0117+10351	Asia/Singapore	peninsular Malaysia
+SG,AQ,MY	+0117+10351	Asia/Singapore	peninsular Malaysia, Concordia
 SR	+0550-05510	America/Paramaribo
 SS	+0451+03137	Africa/Juba
 ST	+0020+00644	Africa/Sao_Tome
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab b/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab
index b6f2910..093f0a0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/zonenow.tab
@@ -5,7 +5,7 @@
 # From Paul Eggert (2023-12-18):
 # This file contains a table where each row stands for a timezone
 # where civil timestamps are predicted to agree from now on.
-# This file is like zone1970.tab (see zone1970.tab's coments),
+# This file is like zone1970.tab (see zone1970.tab's comments),
 # but with the following changes:
 #
 # 1.  Each timezone corresponds to a set of clocks that are planned
@@ -97,9 +97,6 @@
 # -04/-03 (Chile DST)
 XX	-3327-07040	America/Santiago	most of Chile
 #
-# -04/-03 (Paraguay DST)
-XX	-2516-05740	America/Asuncion	Paraguay
-#
 # -04/-03 - AST/ADT (North America DST)
 XX	+4439-06336	America/Halifax	Atlantic ("AST/ADT") - Canada; Bermuda
 #
@@ -107,7 +104,7 @@
 XX	+4734-05243	America/St_Johns	Newfoundland ("NST/NDT")
 #
 # -03
-XX	-2332-04637	America/Sao_Paulo	eastern South America
+XX	-2332-04637	America/Sao_Paulo	eastern and southern South America
 #
 # -03/-02 (North America DST)
 XX	+4703-05620	America/Miquelon	St Pierre & Miquelon
@@ -123,8 +120,6 @@
 #
 # -01/+00 (EU DST)
 XX	+3744-02540	Atlantic/Azores	Azores
-# -01/+00 (EU DST) until 2024-03-31; then -02/-01 (EU DST)
-XX	+7029-02158	America/Scoresbysund	Ittoqqortoormiit
 #
 # +00 - GMT
 XX	+0519-00402	Africa/Abidjan	far western Africa; Iceland ("GMT")
@@ -199,7 +194,7 @@
 XX	+3431+06912	Asia/Kabul	Afghanistan
 #
 # +05
-XX	+4120+06918	Asia/Tashkent	Russia; west Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives
+XX	+4120+06918	Asia/Tashkent	Russia; Kazakhstan; Tajikistan; Turkmenistan; Uzbekistan; Maldives
 #
 # +05 - PKT
 XX	+2452+06703	Asia/Karachi	Pakistan ("PKT")
@@ -215,8 +210,6 @@
 #
 # +06
 XX	+2343+09025	Asia/Dhaka	Russia; Kyrgyzstan; Bhutan; Bangladesh; Chagos
-# +06 until 2024-03-01; then +05
-XX	+4315+07657	Asia/Almaty	Kazakhstan (except western areas)
 #
 # +06:30
 XX	+1647+09610	Asia/Yangon	Myanmar; Cocos
@@ -228,7 +221,7 @@
 XX	-0610+10648	Asia/Jakarta	Indonesia ("WIB")
 #
 # +08
-XX	+0117+10351	Asia/Singapore	Russia; Brunei; Malaysia; Singapore
+XX	+0117+10351	Asia/Singapore	Russia; Brunei; Malaysia; Singapore; Concordia
 #
 # +08 - AWST
 XX	-3157+11551	Australia/Perth	Western Australia ("AWST")
@@ -240,7 +233,7 @@
 XX	+2217+11409	Asia/Hong_Kong	Hong Kong ("HKT")
 #
 # +08 - PHT
-XX	+1435+12100	Asia/Manila	Philippines ("PHT")
+XX	+143512+1205804	Asia/Manila	Philippines ("PHT")
 #
 # +08 - WITA
 XX	-0507+11924	Asia/Makassar	Indonesia ("WITA")
@@ -252,7 +245,7 @@
 XX	+5203+11328	Asia/Chita	Russia; Palau; East Timor
 #
 # +09 - JST
-XX	+353916+1394441	Asia/Tokyo	Japan ("JST")
+XX	+353916+1394441	Asia/Tokyo	Japan ("JST"); Eyre Bird Observatory
 #
 # +09 - KST
 XX	+3733+12658	Asia/Seoul	Korea ("KST")
diff --git a/absl/time/time.h b/absl/time/time.h
index f133c2d..53bca90 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -74,13 +74,19 @@
 // including 'windows.h' so we are picking the lesser of two evils here.
 struct timeval;
 #endif
+
+#include "absl/base/config.h"
+
+// For feature testing and determining which headers can be included.
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#include <version>
+#endif
+
 #include <chrono>  // NOLINT(build/c++11)
-
-#ifdef __cpp_impl_three_way_comparison
-#include <compare>
-#endif  // __cpp_impl_three_way_comparison
-
 #include <cmath>
+#ifdef __cpp_lib_three_way_comparison
+#include <compare>
+#endif  // __cpp_lib_three_way_comparison
 #include <cstdint>
 #include <ctime>
 #include <limits>
@@ -91,12 +97,16 @@
 #include <utility>
 
 #include "absl/base/attributes.h"
-#include "absl/base/config.h"
 #include "absl/base/macros.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
+#if defined(__cpp_impl_three_way_comparison) && \
+    defined(__cpp_lib_three_way_comparison)
+#define ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON 1
+#endif
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
@@ -138,7 +148,8 @@
 // the result of subtracting one `absl::Time` from another. Durations behave
 // like unit-safe integers and they support all the natural integer-like
 // arithmetic operations. Arithmetic overflows and saturates at +/- infinity.
-// `Duration` should be passed by value rather than const reference.
+// `Duration` is trivially destructible and should be passed by value rather
+// than const reference.
 //
 // Factory functions `Nanoseconds()`, `Microseconds()`, `Milliseconds()`,
 // `Seconds()`, `Minutes()`, `Hours()` and `InfiniteDuration()` allow for
@@ -313,12 +324,12 @@
 
 // Relational Operators
 
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
 ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
     Duration lhs, Duration rhs);
 
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
 ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
                                                        Duration rhs);
@@ -609,12 +620,12 @@
 //
 //   absl::Duration d = absl::Milliseconds(1500);
 //   int64_t isec = absl::ToInt64Seconds(d);  // isec == 1
-ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Nanoseconds(Duration d);
-ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Microseconds(Duration d);
-ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d);
-ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Seconds(Duration d);
-ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Minutes(Duration d);
-ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Hours(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Nanoseconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Microseconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Milliseconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Seconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Minutes(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Hours(Duration d);
 
 // ToDoubleNanoseconds()
 // ToDoubleMicroseconds()
@@ -738,8 +749,9 @@
 // are provided for naturally expressing time calculations. Instances are
 // created using `absl::Now()` and the `absl::From*()` factory functions that
 // accept the gamut of other time representations. Formatting and parsing
-// functions are provided for conversion to and from strings.  `absl::Time`
-// should be passed by value rather than const reference.
+// functions are provided for conversion to and from strings. `absl::Time` is
+// trivially destructible and should be passed by value rather than const
+// reference.
 //
 // `absl::Time` assumes there are 60 seconds in a minute, which means the
 // underlying time scales must be "smeared" to eliminate leap seconds.
@@ -853,9 +865,9 @@
   friend constexpr Time time_internal::FromUnixDuration(Duration d);
   friend constexpr Duration time_internal::ToUnixDuration(Time t);
 
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
   friend constexpr std::strong_ordering operator<=>(Time lhs, Time rhs);
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
   friend constexpr bool operator<(Time lhs, Time rhs);
   friend constexpr bool operator==(Time lhs, Time rhs);
@@ -868,14 +880,14 @@
 };
 
 // Relational Operators
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
 ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
     Time lhs, Time rhs) {
   return lhs.rep_ <=> rhs.rep_;
 }
 
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
 ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) {
   return lhs.rep_ < rhs.rep_;
@@ -1752,8 +1764,7 @@
              : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs);
 }
 
-
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
 ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
     Duration lhs, Duration rhs) {
@@ -1769,7 +1780,7 @@
              : lhs_lo <=> rhs_lo;
 }
 
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
 ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,
                                                         Duration rhs) {
@@ -1853,6 +1864,61 @@
   return time_internal::FromUnixDuration(Seconds(t));
 }
 
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Nanoseconds(Duration d) {
+  if (time_internal::GetRepHi(d) >= 0 &&
+      time_internal::GetRepHi(d) >> 33 == 0) {
+    return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) +
+           (time_internal::GetRepLo(d) / time_internal::kTicksPerNanosecond);
+  } else {
+    return d / Nanoseconds(1);
+  }
+}
+
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Microseconds(
+    Duration d) {
+  if (time_internal::GetRepHi(d) >= 0 &&
+      time_internal::GetRepHi(d) >> 43 == 0) {
+    return (time_internal::GetRepHi(d) * 1000 * 1000) +
+           (time_internal::GetRepLo(d) /
+            (time_internal::kTicksPerNanosecond * 1000));
+  } else {
+    return d / Microseconds(1);
+  }
+}
+
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Milliseconds(
+    Duration d) {
+  if (time_internal::GetRepHi(d) >= 0 &&
+      time_internal::GetRepHi(d) >> 53 == 0) {
+    return (time_internal::GetRepHi(d) * 1000) +
+           (time_internal::GetRepLo(d) /
+            (time_internal::kTicksPerNanosecond * 1000 * 1000));
+  } else {
+    return d / Milliseconds(1);
+  }
+}
+
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Seconds(Duration d) {
+  int64_t hi = time_internal::GetRepHi(d);
+  if (time_internal::IsInfiniteDuration(d)) return hi;
+  if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
+  return hi;
+}
+
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Minutes(Duration d) {
+  int64_t hi = time_internal::GetRepHi(d);
+  if (time_internal::IsInfiniteDuration(d)) return hi;
+  if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
+  return hi / 60;
+}
+
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Hours(Duration d) {
+  int64_t hi = time_internal::GetRepHi(d);
+  if (time_internal::IsInfiniteDuration(d)) return hi;
+  if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
+  return hi / (60 * 60);
+}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc
index 71f54d6..7033326 100644
--- a/absl/time/time_test.cc
+++ b/absl/time/time_test.cc
@@ -13,30 +13,35 @@
 // limitations under the License.
 
 #include "absl/time/time.h"
-
-#include <cstdint>
-#include <ios>
-
 #include "absl/time/civil_time.h"
 
 #if defined(_MSC_VER)
 #include <winsock2.h>  // for timeval
 #endif
 
+#include "absl/base/config.h"
+
+// For feature testing and determining which headers can be included.
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#include <version>
+#endif
+
 #include <chrono>  // NOLINT(build/c++11)
-
-#ifdef __cpp_impl_three_way_comparison
+#ifdef __cpp_lib_three_way_comparison
 #include <compare>
-#endif  // __cpp_impl_three_way_comparison
-
+#endif  // __cpp_lib_three_way_comparison
+#include <cstdint>
 #include <cstring>
 #include <ctime>
 #include <iomanip>
+#include <ios>
 #include <limits>
 #include <string>
+#include <type_traits>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/hash/hash_testing.h"
 #include "absl/numeric/int128.h"
 #include "absl/strings/str_format.h"
 #include "absl/time/clock.h"
@@ -86,6 +91,8 @@
 }
 
 TEST(Time, ConstExpr) {
+  static_assert(std::is_trivially_destructible<absl::Time>::value,
+                "Time is documented as being trivially destructible");
   constexpr absl::Time t0 = absl::UnixEpoch();
   static_assert(t0 == absl::UnixEpoch(), "UnixEpoch");
   constexpr absl::Time t1 = absl::InfiniteFuture();
@@ -213,7 +220,7 @@
   static_assert(t1 >= t1, "");
   static_assert(t3 >= t1, "");
 
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
   static_assert((t1 <=> t1) == std::strong_ordering::equal, "");
   static_assert((t2 <=> t2) == std::strong_ordering::equal, "");
@@ -227,7 +234,7 @@
   static_assert((t3 <=> t2) == std::strong_ordering::greater, "");
   static_assert((t3 <=> t1) == std::strong_ordering::greater, "");
 
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 }
 
 TEST(Time, Infinity) {
@@ -239,14 +246,14 @@
   static_assert(ipast < ifuture, "");
   static_assert(ifuture > ipast, "");
 
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
   static_assert((ifuture <=> ifuture) == std::strong_ordering::equal, "");
   static_assert((ipast <=> ipast) == std::strong_ordering::equal, "");
   static_assert((ipast <=> ifuture) == std::strong_ordering::less, "");
   static_assert((ifuture <=> ipast) == std::strong_ordering::greater, "");
 
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
   // Arithmetic saturates
   EXPECT_EQ(ifuture, ifuture + absl::Seconds(1));
@@ -263,14 +270,14 @@
   static_assert(t < ifuture, "");
   static_assert(t > ipast, "");
 
-#ifdef __cpp_impl_three_way_comparison
+#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
   static_assert((t <=> ifuture) == std::strong_ordering::less, "");
   static_assert((t <=> ipast) == std::strong_ordering::greater, "");
   static_assert((ipast <=> t) == std::strong_ordering::less, "");
   static_assert((ifuture <=> t) == std::strong_ordering::greater, "");
 
-#endif  // __cpp_impl_three_way_comparison
+#endif  // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
 
   EXPECT_EQ(ifuture, t + absl::InfiniteDuration());
   EXPECT_EQ(ipast, t - absl::InfiniteDuration());
@@ -1329,4 +1336,29 @@
   EXPECT_EQ(absl::StrFormat("%v", t), absl::FormatTime(t));
 }
 
+TEST(Time, SupportsHash) {
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      absl::UTCTimeZone(),
+      absl::FixedTimeZone(-8 * 60 * 60),
+      absl::UTCTimeZone(),
+  }));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      absl::Now(),
+      absl::UnixEpoch(),
+      absl::UnixEpoch() + absl::Seconds(60),
+      absl::UnixEpoch() + absl::Minutes(1),
+      absl::InfiniteFuture(),
+      absl::InfinitePast(),
+  }));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+      absl::Seconds(1),
+      absl::Seconds(60),
+      absl::Minutes(1),
+      absl::InfiniteDuration(),
+      -absl::InfiniteDuration(),
+  }));
+}
+
 }  // namespace
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index a86e2c1..0668a2e 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -37,72 +37,15 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        ":bad_any_cast",
         "//absl/base:config",
         "//absl/base:core_headers",
-        "//absl/base:fast_type_id",
-        "//absl/meta:type_traits",
         "//absl/utility",
     ],
 )
 
 cc_library(
     name = "bad_any_cast",
-    hdrs = ["bad_any_cast.h"],
-    copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":bad_any_cast_impl",
-        "//absl/base:config",
-    ],
-)
-
-cc_library(
-    name = "bad_any_cast_impl",
-    srcs = [
-        "bad_any_cast.cc",
-        "bad_any_cast.h",
-    ],
-    copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = ["//visibility:private"],
-    deps = [
-        "//absl/base:config",
-        "//absl/base:raw_logging_internal",
-    ],
-)
-
-cc_test(
-    name = "any_test",
-    size = "small",
-    srcs = [
-        "any_test.cc",
-    ],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":any",
-        "//absl/base:config",
-        "//absl/base:exception_testing",
-        "//absl/container:test_instance_tracker",
-        "//absl/log",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_test(
-    name = "any_exception_safety_test",
-    srcs = ["any_exception_safety_test.cc"],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":any",
-        "//absl/base:config",
-        "//absl/base:exception_safety_testing",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
+    deprecation = "bad_any_cast dependency is empty can be removed",
 )
 
 cc_library(
@@ -117,9 +60,11 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         "//absl/algorithm",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:nullability",
         "//absl/base:throw_delegate",
+        "//absl/hash:weakly_mixed_integer",
         "//absl/meta:type_traits",
     ],
 )
@@ -137,105 +82,45 @@
         "//absl/base:exception_testing",
         "//absl/container:fixed_array",
         "//absl/container:inlined_vector",
+        "//absl/hash",
         "//absl/hash:hash_testing",
         "//absl/meta:type_traits",
         "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
 cc_library(
     name = "optional",
-    srcs = ["internal/optional.h"],
     hdrs = ["optional.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        ":bad_optional_access",
-        "//absl/base:base_internal",
         "//absl/base:config",
-        "//absl/base:core_headers",
-        "//absl/base:nullability",
-        "//absl/memory",
-        "//absl/meta:type_traits",
         "//absl/utility",
     ],
 )
 
 cc_library(
     name = "bad_optional_access",
-    srcs = ["bad_optional_access.cc"],
-    hdrs = ["bad_optional_access.h"],
+    deprecation = "bad_optional_access dependency is empty can be removed",
+)
+
+cc_library(
+    name = "variant",
+    hdrs = ["variant.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         "//absl/base:config",
-        "//absl/base:raw_logging_internal",
+        "//absl/utility",
     ],
 )
 
 cc_library(
     name = "bad_variant_access",
-    srcs = ["bad_variant_access.cc"],
-    hdrs = ["bad_variant_access.h"],
-    copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        "//absl/base:config",
-        "//absl/base:raw_logging_internal",
-    ],
-)
-
-cc_test(
-    name = "optional_test",
-    size = "small",
-    srcs = [
-        "optional_test.cc",
-    ],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":optional",
-        "//absl/base:config",
-        "//absl/log",
-        "//absl/meta:type_traits",
-        "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_test(
-    name = "optional_exception_safety_test",
-    srcs = [
-        "optional_exception_safety_test.cc",
-    ],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":optional",
-        "//absl/base:config",
-        "//absl/base:exception_safety_testing",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_library(
-    name = "variant",
-    srcs = ["internal/variant.h"],
-    hdrs = ["variant.h"],
-    copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":bad_variant_access",
-        "//absl/base:base_internal",
-        "//absl/base:config",
-        "//absl/base:core_headers",
-        "//absl/meta:type_traits",
-        "//absl/utility",
-    ],
+    deprecation = "bad_variant_access dependency is empty can be removed",
 )
 
 cc_test(
@@ -246,47 +131,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":variant",
-        "//absl/base:config",
-        "//absl/base:core_headers",
-        "//absl/memory",
-        "//absl/meta:type_traits",
-        "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_test(
-    name = "variant_benchmark",
-    srcs = [
-        "variant_benchmark.cc",
-    ],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    tags = ["benchmark"],
-    deps = [
-        ":variant",
-        "//absl/utility",
-        "@com_github_google_benchmark//:benchmark_main",
-        "@com_google_googletest//:gtest",
-    ],
-)
-
-cc_test(
-    name = "variant_exception_safety_test",
-    size = "small",
-    srcs = [
-        "variant_exception_safety_test.cc",
-    ],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":variant",
-        "//absl/base:config",
-        "//absl/base:exception_safety_testing",
-        "//absl/memory",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
 
@@ -312,7 +158,7 @@
     deps = [
         ":compare",
         "//absl/base",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
+        "@googletest//:gtest",
+        "@googletest//:gtest_main",
     ],
 )
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index fed532f..20a7e90 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -21,90 +21,14 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::bad_any_cast
     absl::config
     absl::core_headers
-    absl::fast_type_id
-    absl::type_traits
     absl::utility
   PUBLIC
 )
 
 absl_cc_library(
   NAME
-    bad_any_cast
-  HDRS
-   "bad_any_cast.h"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  DEPS
-    absl::bad_any_cast_impl
-    absl::config
-  PUBLIC
-)
-
-# Internal-only target, do not depend on directly.
-absl_cc_library(
-  NAME
-    bad_any_cast_impl
-  SRCS
-   "bad_any_cast.h"
-   "bad_any_cast.cc"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  DEPS
-    absl::config
-    absl::raw_logging_internal
-)
-
-absl_cc_test(
-  NAME
-    any_test
-  SRCS
-    "any_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::any
-    absl::config
-    absl::exception_testing
-    absl::log
-    absl::test_instance_tracker
-    GTest::gmock_main
-)
-
-absl_cc_test(
-  NAME
-    any_test_noexceptions
-  SRCS
-    "any_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::any
-    absl::config
-    absl::exception_testing
-    absl::raw_logging_internal
-    absl::test_instance_tracker
-    GTest::gmock_main
-)
-
-absl_cc_test(
-  NAME
-    any_exception_safety_test
-  SRCS
-    "any_exception_safety_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::any
-    absl::config
-    absl::exception_safety_testing
-    GTest::gmock_main
-)
-
-absl_cc_library(
-  NAME
     span
   HDRS
     "span.h"
@@ -114,10 +38,12 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::algorithm
+    absl::config
     absl::core_headers
     absl::nullability
     absl::throw_delegate
     absl::type_traits
+    absl::weakly_mixed_integer
   PUBLIC
 )
 
@@ -135,6 +61,7 @@
     absl::core_headers
     absl::exception_testing
     absl::fixed_array
+    absl::hash
     absl::inlined_vector
     absl::hash_testing
     absl::strings
@@ -167,97 +94,23 @@
     optional
   HDRS
     "optional.h"
-  SRCS
-    "internal/optional.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::bad_optional_access
-    absl::base_internal
     absl::config
-    absl::core_headers
-    absl::memory
-    absl::nullability
-    absl::type_traits
     absl::utility
   PUBLIC
 )
 
 absl_cc_library(
   NAME
-    bad_optional_access
-  HDRS
-    "bad_optional_access.h"
-  SRCS
-    "bad_optional_access.cc"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  DEPS
-    absl::config
-    absl::raw_logging_internal
-  PUBLIC
-)
-
-absl_cc_library(
-  NAME
-    bad_variant_access
-  HDRS
-    "bad_variant_access.h"
-  SRCS
-    "bad_variant_access.cc"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  DEPS
-    absl::config
-    absl::raw_logging_internal
-  PUBLIC
-)
-
-absl_cc_test(
-  NAME
-    optional_test
-  SRCS
-    "optional_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::optional
-    absl::config
-    absl::log
-    absl::strings
-    absl::type_traits
-    GTest::gmock_main
-)
-
-absl_cc_test(
-  NAME
-    optional_exception_safety_test
-  SRCS
-    "optional_exception_safety_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::optional
-    absl::config
-    absl::exception_safety_testing
-    GTest::gmock_main
-)
-
-absl_cc_library(
-  NAME
     variant
   HDRS
     "variant.h"
-  SRCS
-    "internal/variant.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::bad_variant_access
-    absl::base_internal
     absl::config
-    absl::core_headers
-    absl::type_traits
     absl::utility
   PUBLIC
 )
@@ -271,11 +124,6 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::variant
-    absl::config
-    absl::core_headers
-    absl::memory
-    absl::type_traits
-    absl::strings
     GTest::gmock_main
 )
 
@@ -306,17 +154,26 @@
     GTest::gmock_main
 )
 
-absl_cc_test(
+# Deprecated empty library.
+# Clients should remove this dependency.
+absl_cc_library(
   NAME
-    variant_exception_safety_test
-  SRCS
-    "variant_exception_safety_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::variant
-    absl::config
-    absl::exception_safety_testing
-    absl::memory
-    GTest::gmock_main
+    bad_any_cast
+  PUBLIC
+)
+
+# Deprecated empty library.
+# Clients should remove this dependency.
+absl_cc_library(
+  NAME
+    bad_optional_access
+  PUBLIC
+)
+
+# Deprecated empty library.
+# Clients should remove this dependency.
+absl_cc_library(
+  NAME
+    bad_variant_access
+  PUBLIC
 )
diff --git a/absl/types/any.h b/absl/types/any.h
index 61f071f..c488631 100644
--- a/absl/types/any.h
+++ b/absl/types/any.h
@@ -17,50 +17,21 @@
 // any.h
 // -----------------------------------------------------------------------------
 //
-// This header file define the `absl::any` type for holding a type-safe value
-// of any type. The 'absl::any` type is useful for providing a way to hold
-// something that is, as yet, unspecified. Such unspecified types
-// traditionally are passed between API boundaries until they are later cast to
-// their "destination" types. To cast to such a destination type, use
-// `absl::any_cast()`. Note that when casting an `absl::any`, you must cast it
-// to an explicit type; implicit conversions will throw.
-//
-// Example:
-//
-//   auto a = absl::any(65);
-//   absl::any_cast<int>(a);         // 65
-//   absl::any_cast<char>(a);        // throws absl::bad_any_cast
-//   absl::any_cast<std::string>(a); // throws absl::bad_any_cast
-//
-// `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
-// and is designed to be a drop-in replacement for code compliant with C++17.
-//
-// Traditionally, the behavior of casting to a temporary unspecified type has
-// been accomplished with the `void *` paradigm, where the pointer was to some
-// other unspecified type. `absl::any` provides an "owning" version of `void *`
-// that avoids issues of pointer management.
-//
-// Note: just as in the case of `void *`, use of `absl::any` (and its C++17
-// version `std::any`) is a code smell indicating that your API might not be
-// constructed correctly. We have seen that most uses of `any` are unwarranted,
-// and `absl::any`, like `std::any`, is difficult to use properly. Before using
-// this abstraction, make sure that you should not instead be rewriting your
-// code to be more specific.
-//
-// Abseil has also released an `absl::variant` type (a C++11 compatible version
-// of the C++17 `std::variant`), which is generally preferred for use over
-// `absl::any`.
+// Historical note: Abseil once provided an implementation of `absl::any` as a
+// polyfill for `std::any` prior to C++17. Now that C++17 is required,
+// `absl::any` is an alias for `std::any`.
+
 #ifndef ABSL_TYPES_ANY_H_
 #define ABSL_TYPES_ANY_H_
 
-#include "absl/base/attributes.h"
-#include "absl/base/config.h"
-#include "absl/utility/utility.h"
-
-#ifdef ABSL_USES_STD_ANY
-
 #include <any>  // IWYU pragma: export
 
+#include "absl/base/config.h"
+
+// Include-what-you-use cleanup required for these headers.
+#include "absl/base/attributes.h"
+#include "absl/utility/utility.h"
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 using std::any;
@@ -70,450 +41,4 @@
 ABSL_NAMESPACE_END
 }  // namespace absl
 
-#else  // ABSL_USES_STD_ANY
-
-#include <algorithm>
-#include <cstddef>
-#include <initializer_list>
-#include <memory>
-#include <stdexcept>
-#include <type_traits>
-#include <typeinfo>
-#include <utility>
-
-#include "absl/base/internal/fast_type_id.h"
-#include "absl/meta/type_traits.h"
-#include "absl/types/bad_any_cast.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-class any;
-
-// swap()
-//
-// Swaps two `absl::any` values. Equivalent to `x.swap(y) where `x` and `y` are
-// `absl::any` types.
-void swap(any& x, any& y) noexcept;
-
-// make_any()
-//
-// Constructs an `absl::any` of type `T` with the given arguments.
-template <typename T, typename... Args>
-any make_any(Args&&... args);
-
-// Overload of `absl::make_any()` for constructing an `absl::any` type from an
-// initializer list.
-template <typename T, typename U, typename... Args>
-any make_any(std::initializer_list<U> il, Args&&... args);
-
-// any_cast()
-//
-// Statically casts the value of a `const absl::any` type to the given type.
-// This function will throw `absl::bad_any_cast` if the stored value type of the
-// `absl::any` does not match the cast.
-//
-// `any_cast()` can also be used to get a reference to the internal storage iff
-// a reference type is passed as its `ValueType`:
-//
-// Example:
-//
-//   absl::any my_any = std::vector<int>();
-//   absl::any_cast<std::vector<int>&>(my_any).push_back(42);
-template <typename ValueType>
-ValueType any_cast(const any& operand);
-
-// Overload of `any_cast()` to statically cast the value of a non-const
-// `absl::any` type to the given type. This function will throw
-// `absl::bad_any_cast` if the stored value type of the `absl::any` does not
-// match the cast.
-template <typename ValueType>
-ValueType any_cast(any& operand);  // NOLINT(runtime/references)
-
-// Overload of `any_cast()` to statically cast the rvalue of an `absl::any`
-// type. This function will throw `absl::bad_any_cast` if the stored value type
-// of the `absl::any` does not match the cast.
-template <typename ValueType>
-ValueType any_cast(any&& operand);
-
-// Overload of `any_cast()` to statically cast the value of a const pointer
-// `absl::any` type to the given pointer type, or `nullptr` if the stored value
-// type of the `absl::any` does not match the cast.
-template <typename ValueType>
-const ValueType* any_cast(const any* operand) noexcept;
-
-// Overload of `any_cast()` to statically cast the value of a pointer
-// `absl::any` type to the given pointer type, or `nullptr` if the stored value
-// type of the `absl::any` does not match the cast.
-template <typename ValueType>
-ValueType* any_cast(any* operand) noexcept;
-
-// -----------------------------------------------------------------------------
-// absl::any
-// -----------------------------------------------------------------------------
-//
-// An `absl::any` object provides the facility to either store an instance of a
-// type, known as the "contained object", or no value. An `absl::any` is used to
-// store values of types that are unknown at compile time. The `absl::any`
-// object, when containing a value, must contain a value type; storing a
-// reference type is neither desired nor supported.
-//
-// An `absl::any` can only store a type that is copy-constructible; move-only
-// types are not allowed within an `any` object.
-//
-// Example:
-//
-//   auto a = absl::any(65);                 // Literal, copyable
-//   auto b = absl::any(std::vector<int>()); // Default-initialized, copyable
-//   std::unique_ptr<Foo> my_foo;
-//   auto c = absl::any(std::move(my_foo));  // Error, not copy-constructible
-//
-// Note that `absl::any` makes use of decayed types (`absl::decay_t` in this
-// context) to remove const-volatile qualifiers (known as "cv qualifiers"),
-// decay functions to function pointers, etc. We essentially "decay" a given
-// type into its essential type.
-//
-// `absl::any` makes use of decayed types when determining the basic type `T` of
-// the value to store in the any's contained object. In the documentation below,
-// we explicitly denote this by using the phrase "a decayed type of `T`".
-//
-// Example:
-//
-//   const int a = 4;
-//   absl::any foo(a);  // Decay ensures we store an "int", not a "const int&".
-//
-//   void my_function() {}
-//   absl::any bar(my_function);  // Decay ensures we store a function pointer.
-//
-// `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
-// and is designed to be a drop-in replacement for code compliant with C++17.
-class any {
- private:
-  template <typename T>
-  struct IsInPlaceType;
-
- public:
-  // Constructors
-
-  // Constructs an empty `absl::any` object (`any::has_value()` will return
-  // `false`).
-  constexpr any() noexcept;
-
-  // Copy constructs an `absl::any` object with a "contained object" of the
-  // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
-  // `false`.
-  any(const any& other)
-      : obj_(other.has_value() ? other.obj_->Clone()
-                               : std::unique_ptr<ObjInterface>()) {}
-
-  // Move constructs an `absl::any` object with a "contained object" of the
-  // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
-  // `false`).
-  any(any&& other) noexcept = default;
-
-  // Constructs an `absl::any` object with a "contained object" of the decayed
-  // type of `T`, which is initialized via `std::forward<T>(value)`.
-  //
-  // This constructor will not participate in overload resolution if the
-  // decayed type of `T` is not copy-constructible.
-  template <
-      typename T, typename VT = absl::decay_t<T>,
-      absl::enable_if_t<!absl::disjunction<
-          std::is_same<any, VT>, IsInPlaceType<VT>,
-          absl::negation<std::is_copy_constructible<VT> > >::value>* = nullptr>
-  any(T&& value) : obj_(new Obj<VT>(in_place, std::forward<T>(value))) {}
-
-  // Constructs an `absl::any` object with a "contained object" of the decayed
-  // type of `T`, which is initialized via `std::forward<T>(value)`.
-  template <typename T, typename... Args, typename VT = absl::decay_t<T>,
-            absl::enable_if_t<absl::conjunction<
-                std::is_copy_constructible<VT>,
-                std::is_constructible<VT, Args...>>::value>* = nullptr>
-  explicit any(in_place_type_t<T> /*tag*/, Args&&... args)
-      : obj_(new Obj<VT>(in_place, std::forward<Args>(args)...)) {}
-
-  // Constructs an `absl::any` object with a "contained object" of the passed
-  // type `VT` as a decayed type of `T`. `VT` is initialized as if
-  // direct-non-list-initializing an object of type `VT` with the arguments
-  // `initializer_list, std::forward<Args>(args)...`.
-  template <
-      typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
-      absl::enable_if_t<
-          absl::conjunction<std::is_copy_constructible<VT>,
-                            std::is_constructible<VT, std::initializer_list<U>&,
-                                                  Args...>>::value>* = nullptr>
-  explicit any(in_place_type_t<T> /*tag*/, std::initializer_list<U> ilist,
-               Args&&... args)
-      : obj_(new Obj<VT>(in_place, ilist, std::forward<Args>(args)...)) {}
-
-  // Assignment operators
-
-  // Copy assigns an `absl::any` object with a "contained object" of the
-  // passed type.
-  any& operator=(const any& rhs) {
-    any(rhs).swap(*this);
-    return *this;
-  }
-
-  // Move assigns an `absl::any` object with a "contained object" of the
-  // passed type. `rhs` is left in a valid but otherwise unspecified state.
-  any& operator=(any&& rhs) noexcept {
-    any(std::move(rhs)).swap(*this);
-    return *this;
-  }
-
-  // Assigns an `absl::any` object with a "contained object" of the passed type.
-  template <typename T, typename VT = absl::decay_t<T>,
-            absl::enable_if_t<absl::conjunction<
-                absl::negation<std::is_same<VT, any>>,
-                std::is_copy_constructible<VT>>::value>* = nullptr>
-  any& operator=(T&& rhs) {
-    any tmp(in_place_type_t<VT>(), std::forward<T>(rhs));
-    tmp.swap(*this);
-    return *this;
-  }
-
-  // Modifiers
-
-  // any::emplace()
-  //
-  // Emplaces a value within an `absl::any` object by calling `any::reset()`,
-  // initializing the contained value as if direct-non-list-initializing an
-  // object of type `VT` with the arguments `std::forward<Args>(args)...`, and
-  // returning a reference to the new contained value.
-  //
-  // Note: If an exception is thrown during the call to `VT`'s constructor,
-  // `*this` does not contain a value, and any previously contained value has
-  // been destroyed.
-  template <
-      typename T, typename... Args, typename VT = absl::decay_t<T>,
-      absl::enable_if_t<std::is_copy_constructible<VT>::value &&
-                        std::is_constructible<VT, Args...>::value>* = nullptr>
-  VT& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    reset();  // NOTE: reset() is required here even in the world of exceptions.
-    Obj<VT>* const object_ptr =
-        new Obj<VT>(in_place, std::forward<Args>(args)...);
-    obj_ = std::unique_ptr<ObjInterface>(object_ptr);
-    return object_ptr->value;
-  }
-
-  // Overload of `any::emplace()` to emplace a value within an `absl::any`
-  // object by calling `any::reset()`, initializing the contained value as if
-  // direct-non-list-initializing an object of type `VT` with the arguments
-  // `initializer_list, std::forward<Args>(args)...`, and returning a reference
-  // to the new contained value.
-  //
-  // Note: If an exception is thrown during the call to `VT`'s constructor,
-  // `*this` does not contain a value, and any previously contained value has
-  // been destroyed. The function shall not participate in overload resolution
-  // unless `is_copy_constructible_v<VT>` is `true` and
-  // `is_constructible_v<VT, initializer_list<U>&, Args...>` is `true`.
-  template <
-      typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
-      absl::enable_if_t<std::is_copy_constructible<VT>::value &&
-                        std::is_constructible<VT, std::initializer_list<U>&,
-                                              Args...>::value>* = nullptr>
-  VT& emplace(std::initializer_list<U> ilist,
-              Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    reset();  // NOTE: reset() is required here even in the world of exceptions.
-    Obj<VT>* const object_ptr =
-        new Obj<VT>(in_place, ilist, std::forward<Args>(args)...);
-    obj_ = std::unique_ptr<ObjInterface>(object_ptr);
-    return object_ptr->value;
-  }
-
-  // any::reset()
-  //
-  // Resets the state of the `absl::any` object, destroying the contained object
-  // if present.
-  void reset() noexcept { obj_ = nullptr; }
-
-  // any::swap()
-  //
-  // Swaps the passed value and the value of this `absl::any` object.
-  void swap(any& other) noexcept { obj_.swap(other.obj_); }
-
-  // Observers
-
-  // any::has_value()
-  //
-  // Returns `true` if the `any` object has a contained value, otherwise
-  // returns `false`.
-  bool has_value() const noexcept { return obj_ != nullptr; }
-
-#ifdef ABSL_INTERNAL_HAS_RTTI
-  // Returns: typeid(T) if *this has a contained object of type T, otherwise
-  // typeid(void).
-  const std::type_info& type() const noexcept {
-    if (has_value()) {
-      return obj_->Type();
-    }
-
-    return typeid(void);
-  }
-#endif  // ABSL_INTERNAL_HAS_RTTI
-
- private:
-  // Tagged type-erased abstraction for holding a cloneable object.
-  class ObjInterface {
-   public:
-    virtual ~ObjInterface() = default;
-    virtual std::unique_ptr<ObjInterface> Clone() const = 0;
-    virtual const void* ObjTypeId() const noexcept = 0;
-#ifdef ABSL_INTERNAL_HAS_RTTI
-    virtual const std::type_info& Type() const noexcept = 0;
-#endif  // ABSL_INTERNAL_HAS_RTTI
-  };
-
-  // Hold a value of some queryable type, with an ability to Clone it.
-  template <typename T>
-  class Obj : public ObjInterface {
-   public:
-    template <typename... Args>
-    explicit Obj(in_place_t /*tag*/, Args&&... args)
-        : value(std::forward<Args>(args)...) {}
-
-    std::unique_ptr<ObjInterface> Clone() const final {
-      return std::unique_ptr<ObjInterface>(new Obj(in_place, value));
-    }
-
-    const void* ObjTypeId() const noexcept final { return IdForType<T>(); }
-
-#ifdef ABSL_INTERNAL_HAS_RTTI
-    const std::type_info& Type() const noexcept final { return typeid(T); }
-#endif  // ABSL_INTERNAL_HAS_RTTI
-
-    T value;
-  };
-
-  std::unique_ptr<ObjInterface> CloneObj() const {
-    if (!obj_) return nullptr;
-    return obj_->Clone();
-  }
-
-  template <typename T>
-  constexpr static const void* IdForType() {
-    // Note: This type dance is to make the behavior consistent with typeid.
-    using NormalizedType =
-        typename std::remove_cv<typename std::remove_reference<T>::type>::type;
-
-    return base_internal::FastTypeId<NormalizedType>();
-  }
-
-  const void* GetObjTypeId() const {
-    return obj_ ? obj_->ObjTypeId() : base_internal::FastTypeId<void>();
-  }
-
-  // `absl::any` nonmember functions //
-
-  // Description at the declaration site (top of file).
-  template <typename ValueType>
-  friend ValueType any_cast(const any& operand);
-
-  // Description at the declaration site (top of file).
-  template <typename ValueType>
-  friend ValueType any_cast(any& operand);  // NOLINT(runtime/references)
-
-  // Description at the declaration site (top of file).
-  template <typename T>
-  friend const T* any_cast(const any* operand) noexcept;
-
-  // Description at the declaration site (top of file).
-  template <typename T>
-  friend T* any_cast(any* operand) noexcept;
-
-  std::unique_ptr<ObjInterface> obj_;
-};
-
-// -----------------------------------------------------------------------------
-// Implementation Details
-// -----------------------------------------------------------------------------
-
-constexpr any::any() noexcept = default;
-
-template <typename T>
-struct any::IsInPlaceType : std::false_type {};
-
-template <typename T>
-struct any::IsInPlaceType<in_place_type_t<T>> : std::true_type {};
-
-inline void swap(any& x, any& y) noexcept { x.swap(y); }
-
-// Description at the declaration site (top of file).
-template <typename T, typename... Args>
-any make_any(Args&&... args) {
-  return any(in_place_type_t<T>(), std::forward<Args>(args)...);
-}
-
-// Description at the declaration site (top of file).
-template <typename T, typename U, typename... Args>
-any make_any(std::initializer_list<U> il, Args&&... args) {
-  return any(in_place_type_t<T>(), il, std::forward<Args>(args)...);
-}
-
-// Description at the declaration site (top of file).
-template <typename ValueType>
-ValueType any_cast(const any& operand) {
-  using U = typename std::remove_cv<
-      typename std::remove_reference<ValueType>::type>::type;
-  static_assert(std::is_constructible<ValueType, const U&>::value,
-                "Invalid ValueType");
-  auto* const result = (any_cast<U>)(&operand);
-  if (result == nullptr) {
-    any_internal::ThrowBadAnyCast();
-  }
-  return static_cast<ValueType>(*result);
-}
-
-// Description at the declaration site (top of file).
-template <typename ValueType>
-ValueType any_cast(any& operand) {  // NOLINT(runtime/references)
-  using U = typename std::remove_cv<
-      typename std::remove_reference<ValueType>::type>::type;
-  static_assert(std::is_constructible<ValueType, U&>::value,
-                "Invalid ValueType");
-  auto* result = (any_cast<U>)(&operand);
-  if (result == nullptr) {
-    any_internal::ThrowBadAnyCast();
-  }
-  return static_cast<ValueType>(*result);
-}
-
-// Description at the declaration site (top of file).
-template <typename ValueType>
-ValueType any_cast(any&& operand) {
-  using U = typename std::remove_cv<
-      typename std::remove_reference<ValueType>::type>::type;
-  static_assert(std::is_constructible<ValueType, U>::value,
-                "Invalid ValueType");
-  return static_cast<ValueType>(std::move((any_cast<U&>)(operand)));
-}
-
-// Description at the declaration site (top of file).
-template <typename T>
-const T* any_cast(const any* operand) noexcept {
-  using U =
-      typename std::remove_cv<typename std::remove_reference<T>::type>::type;
-  return operand && operand->GetObjTypeId() == any::IdForType<U>()
-             ? std::addressof(
-                   static_cast<const any::Obj<U>*>(operand->obj_.get())->value)
-             : nullptr;
-}
-
-// Description at the declaration site (top of file).
-template <typename T>
-T* any_cast(any* operand) noexcept {
-  using U =
-      typename std::remove_cv<typename std::remove_reference<T>::type>::type;
-  return operand && operand->GetObjTypeId() == any::IdForType<U>()
-             ? std::addressof(
-                   static_cast<any::Obj<U>*>(operand->obj_.get())->value)
-             : nullptr;
-}
-
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_USES_STD_ANY
-
 #endif  // ABSL_TYPES_ANY_H_
diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc
deleted file mode 100644
index 31c1140..0000000
--- a/absl/types/any_exception_safety_test.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/types/any.h"
-
-#include "absl/base/config.h"
-
-// This test is a no-op when absl::any is an alias for std::any and when
-// exceptions are not enabled.
-#if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
-
-#include <typeinfo>
-#include <vector>
-
-#include "gtest/gtest.h"
-#include "absl/base/internal/exception_safety_testing.h"
-
-using Thrower = testing::ThrowingValue<>;
-using NoThrowMoveThrower =
-    testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
-using ThrowerList = std::initializer_list<Thrower>;
-using ThrowerVec = std::vector<Thrower>;
-using ThrowingAlloc = testing::ThrowingAllocator<Thrower>;
-using ThrowingThrowerVec = std::vector<Thrower, ThrowingAlloc>;
-
-namespace {
-
-testing::AssertionResult AnyInvariants(absl::any* a) {
-  using testing::AssertionFailure;
-  using testing::AssertionSuccess;
-
-  if (a->has_value()) {
-    if (a->type() == typeid(void)) {
-      return AssertionFailure()
-             << "A non-empty any should not have type `void`";
-    }
-  } else {
-    if (a->type() != typeid(void)) {
-      return AssertionFailure()
-             << "An empty any should have type void, but has type "
-             << a->type().name();
-    }
-  }
-
-  //  Make sure that reset() changes any to a valid state.
-  a->reset();
-  if (a->has_value()) {
-    return AssertionFailure() << "A reset `any` should be valueless";
-  }
-  if (a->type() != typeid(void)) {
-    return AssertionFailure() << "A reset `any` should have type() of `void`, "
-                                 "but instead has type "
-                              << a->type().name();
-  }
-  try {
-    auto unused = absl::any_cast<Thrower>(*a);
-    static_cast<void>(unused);
-    return AssertionFailure()
-           << "A reset `any` should not be able to be any_cast";
-  } catch (const absl::bad_any_cast&) {
-  } catch (...) {
-    return AssertionFailure()
-           << "Unexpected exception thrown from absl::any_cast";
-  }
-  return AssertionSuccess();
-}
-
-testing::AssertionResult AnyIsEmpty(absl::any* a) {
-  if (!a->has_value()) {
-    return testing::AssertionSuccess();
-  }
-  return testing::AssertionFailure()
-         << "a should be empty, but instead has value "
-         << absl::any_cast<Thrower>(*a).Get();
-}
-
-TEST(AnyExceptionSafety, Ctors) {
-  Thrower val(1);
-  testing::TestThrowingCtor<absl::any>(val);
-
-  Thrower copy(val);
-  testing::TestThrowingCtor<absl::any>(copy);
-
-  testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<Thrower>(), 1);
-
-  testing::TestThrowingCtor<absl::any>(absl::in_place_type_t<ThrowerVec>(),
-                                       ThrowerList{val});
-
-  testing::TestThrowingCtor<absl::any,
-                            absl::in_place_type_t<ThrowingThrowerVec>,
-                            ThrowerList, ThrowingAlloc>(
-      absl::in_place_type_t<ThrowingThrowerVec>(), {val}, ThrowingAlloc());
-}
-
-TEST(AnyExceptionSafety, Assignment) {
-  auto original =
-      absl::any(absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor);
-  auto any_is_strong = [original](absl::any* ap) {
-    return testing::AssertionResult(ap->has_value() &&
-                                    absl::any_cast<Thrower>(original) ==
-                                        absl::any_cast<Thrower>(*ap));
-  };
-  auto any_strong_tester = testing::MakeExceptionSafetyTester()
-                               .WithInitialValue(original)
-                               .WithContracts(AnyInvariants, any_is_strong);
-
-  Thrower val(2);
-  absl::any any_val(val);
-  NoThrowMoveThrower mv_val(2);
-
-  auto assign_any = [&any_val](absl::any* ap) { *ap = any_val; };
-  auto assign_val = [&val](absl::any* ap) { *ap = val; };
-  auto move = [&val](absl::any* ap) { *ap = std::move(val); };
-  auto move_movable = [&mv_val](absl::any* ap) { *ap = std::move(mv_val); };
-
-  EXPECT_TRUE(any_strong_tester.Test(assign_any));
-  EXPECT_TRUE(any_strong_tester.Test(assign_val));
-  EXPECT_TRUE(any_strong_tester.Test(move));
-  EXPECT_TRUE(any_strong_tester.Test(move_movable));
-
-  auto empty_any_is_strong = [](absl::any* ap) {
-    return testing::AssertionResult{!ap->has_value()};
-  };
-  auto strong_empty_any_tester =
-      testing::MakeExceptionSafetyTester()
-          .WithInitialValue(absl::any{})
-          .WithContracts(AnyInvariants, empty_any_is_strong);
-
-  EXPECT_TRUE(strong_empty_any_tester.Test(assign_any));
-  EXPECT_TRUE(strong_empty_any_tester.Test(assign_val));
-  EXPECT_TRUE(strong_empty_any_tester.Test(move));
-}
-
-TEST(AnyExceptionSafety, Emplace) {
-  auto initial_val =
-      absl::any{absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor};
-  auto one_tester = testing::MakeExceptionSafetyTester()
-                        .WithInitialValue(initial_val)
-                        .WithContracts(AnyInvariants, AnyIsEmpty);
-
-  auto emp_thrower = [](absl::any* ap) { ap->emplace<Thrower>(2); };
-  auto emp_throwervec = [](absl::any* ap) {
-    std::initializer_list<Thrower> il{Thrower(2, testing::nothrow_ctor)};
-    ap->emplace<ThrowerVec>(il);
-  };
-  auto emp_movethrower = [](absl::any* ap) {
-    ap->emplace<NoThrowMoveThrower>(2);
-  };
-
-  EXPECT_TRUE(one_tester.Test(emp_thrower));
-  EXPECT_TRUE(one_tester.Test(emp_throwervec));
-  EXPECT_TRUE(one_tester.Test(emp_movethrower));
-
-  auto empty_tester = one_tester.WithInitialValue(absl::any{});
-
-  EXPECT_TRUE(empty_tester.Test(emp_thrower));
-  EXPECT_TRUE(empty_tester.Test(emp_throwervec));
-}
-
-}  // namespace
-
-#endif  // #if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/absl/types/any_test.cc b/absl/types/any_test.cc
deleted file mode 100644
index 666ea5b..0000000
--- a/absl/types/any_test.cc
+++ /dev/null
@@ -1,778 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/types/any.h"
-
-// This test is a no-op when absl::any is an alias for std::any.
-#if !defined(ABSL_USES_STD_ANY)
-
-#include <initializer_list>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/base/internal/exception_testing.h"
-#include "absl/container/internal/test_instance_tracker.h"
-#include "absl/log/log.h"
-
-namespace {
-using absl::test_internal::CopyableOnlyInstance;
-using absl::test_internal::InstanceTracker;
-
-template <typename T>
-const T& AsConst(const T& t) {
-  return t;
-}
-
-struct MoveOnly {
-  MoveOnly() = default;
-  explicit MoveOnly(int value) : value(value) {}
-  MoveOnly(MoveOnly&&) = default;
-  MoveOnly& operator=(MoveOnly&&) = default;
-
-  int value = 0;
-};
-
-struct CopyOnly {
-  CopyOnly() = default;
-  explicit CopyOnly(int value) : value(value) {}
-  CopyOnly(CopyOnly&&) = delete;
-  CopyOnly& operator=(CopyOnly&&) = delete;
-  CopyOnly(const CopyOnly&) = default;
-  CopyOnly& operator=(const CopyOnly&) = default;
-
-  int value = 0;
-};
-
-struct MoveOnlyWithListConstructor {
-  MoveOnlyWithListConstructor() = default;
-  explicit MoveOnlyWithListConstructor(std::initializer_list<int> /*ilist*/,
-                                       int value)
-      : value(value) {}
-  MoveOnlyWithListConstructor(MoveOnlyWithListConstructor&&) = default;
-  MoveOnlyWithListConstructor& operator=(MoveOnlyWithListConstructor&&) =
-      default;
-
-  int value = 0;
-};
-
-struct IntMoveOnlyCopyOnly {
-  IntMoveOnlyCopyOnly(int value, MoveOnly /*move_only*/, CopyOnly /*copy_only*/)
-      : value(value) {}
-
-  int value;
-};
-
-struct ListMoveOnlyCopyOnly {
-  ListMoveOnlyCopyOnly(std::initializer_list<int> ilist, MoveOnly /*move_only*/,
-                       CopyOnly /*copy_only*/)
-      : values(ilist) {}
-
-  std::vector<int> values;
-};
-
-using FunctionType = void();
-void FunctionToEmplace() {}
-
-using ArrayType = int[2];
-using DecayedArray = absl::decay_t<ArrayType>;
-
-TEST(AnyTest, Noexcept) {
-  static_assert(std::is_nothrow_default_constructible<absl::any>(), "");
-  static_assert(std::is_nothrow_move_constructible<absl::any>(), "");
-  static_assert(std::is_nothrow_move_assignable<absl::any>(), "");
-  static_assert(noexcept(std::declval<absl::any&>().has_value()), "");
-  static_assert(noexcept(std::declval<absl::any&>().type()), "");
-  static_assert(noexcept(absl::any_cast<int>(std::declval<absl::any*>())), "");
-  static_assert(
-      noexcept(std::declval<absl::any&>().swap(std::declval<absl::any&>())),
-      "");
-
-  using std::swap;
-  static_assert(
-      noexcept(swap(std::declval<absl::any&>(), std::declval<absl::any&>())),
-      "");
-}
-
-TEST(AnyTest, HasValue) {
-  absl::any o;
-  EXPECT_FALSE(o.has_value());
-  o.emplace<int>();
-  EXPECT_TRUE(o.has_value());
-  o.reset();
-  EXPECT_FALSE(o.has_value());
-}
-
-TEST(AnyTest, Type) {
-  absl::any o;
-  EXPECT_EQ(typeid(void), o.type());
-  o.emplace<int>(5);
-  EXPECT_EQ(typeid(int), o.type());
-  o.emplace<float>(5.f);
-  EXPECT_EQ(typeid(float), o.type());
-  o.reset();
-  EXPECT_EQ(typeid(void), o.type());
-}
-
-TEST(AnyTest, EmptyPointerCast) {
-  // pointer-to-unqualified overload
-  {
-    absl::any o;
-    EXPECT_EQ(nullptr, absl::any_cast<int>(&o));
-    o.emplace<int>();
-    EXPECT_NE(nullptr, absl::any_cast<int>(&o));
-    o.reset();
-    EXPECT_EQ(nullptr, absl::any_cast<int>(&o));
-  }
-
-  // pointer-to-const overload
-  {
-    absl::any o;
-    EXPECT_EQ(nullptr, absl::any_cast<int>(&AsConst(o)));
-    o.emplace<int>();
-    EXPECT_NE(nullptr, absl::any_cast<int>(&AsConst(o)));
-    o.reset();
-    EXPECT_EQ(nullptr, absl::any_cast<int>(&AsConst(o)));
-  }
-}
-
-TEST(AnyTest, InPlaceConstruction) {
-  const CopyOnly copy_only{};
-  absl::any o(absl::in_place_type_t<IntMoveOnlyCopyOnly>(), 5, MoveOnly(),
-              copy_only);
-  IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
-  EXPECT_EQ(5, v.value);
-}
-
-TEST(AnyTest, InPlaceConstructionVariableTemplate) {
-  const CopyOnly copy_only{};
-  absl::any o(absl::in_place_type<IntMoveOnlyCopyOnly>, 5, MoveOnly(),
-              copy_only);
-  auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
-  EXPECT_EQ(5, v.value);
-}
-
-TEST(AnyTest, InPlaceConstructionWithCV) {
-  const CopyOnly copy_only{};
-  absl::any o(absl::in_place_type_t<const volatile IntMoveOnlyCopyOnly>(), 5,
-              MoveOnly(), copy_only);
-  IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
-  EXPECT_EQ(5, v.value);
-}
-
-TEST(AnyTest, InPlaceConstructionWithCVVariableTemplate) {
-  const CopyOnly copy_only{};
-  absl::any o(absl::in_place_type<const volatile IntMoveOnlyCopyOnly>, 5,
-              MoveOnly(), copy_only);
-  auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
-  EXPECT_EQ(5, v.value);
-}
-
-TEST(AnyTest, InPlaceConstructionWithFunction) {
-  absl::any o(absl::in_place_type_t<FunctionType>(), FunctionToEmplace);
-  FunctionType*& construction_result = absl::any_cast<FunctionType*&>(o);
-  EXPECT_EQ(&FunctionToEmplace, construction_result);
-}
-
-TEST(AnyTest, InPlaceConstructionWithFunctionVariableTemplate) {
-  absl::any o(absl::in_place_type<FunctionType>, FunctionToEmplace);
-  auto& construction_result = absl::any_cast<FunctionType*&>(o);
-  EXPECT_EQ(&FunctionToEmplace, construction_result);
-}
-
-TEST(AnyTest, InPlaceConstructionWithArray) {
-  ArrayType ar = {5, 42};
-  absl::any o(absl::in_place_type_t<ArrayType>(), ar);
-  DecayedArray& construction_result = absl::any_cast<DecayedArray&>(o);
-  EXPECT_EQ(&ar[0], construction_result);
-}
-
-TEST(AnyTest, InPlaceConstructionWithArrayVariableTemplate) {
-  ArrayType ar = {5, 42};
-  absl::any o(absl::in_place_type<ArrayType>, ar);
-  auto& construction_result = absl::any_cast<DecayedArray&>(o);
-  EXPECT_EQ(&ar[0], construction_result);
-}
-
-TEST(AnyTest, InPlaceConstructionIlist) {
-  const CopyOnly copy_only{};
-  absl::any o(absl::in_place_type_t<ListMoveOnlyCopyOnly>(), {1, 2, 3, 4},
-              MoveOnly(), copy_only);
-  ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
-  std::vector<int> expected_values = {1, 2, 3, 4};
-  EXPECT_EQ(expected_values, v.values);
-}
-
-TEST(AnyTest, InPlaceConstructionIlistVariableTemplate) {
-  const CopyOnly copy_only{};
-  absl::any o(absl::in_place_type<ListMoveOnlyCopyOnly>, {1, 2, 3, 4},
-              MoveOnly(), copy_only);
-  auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
-  std::vector<int> expected_values = {1, 2, 3, 4};
-  EXPECT_EQ(expected_values, v.values);
-}
-
-TEST(AnyTest, InPlaceConstructionIlistWithCV) {
-  const CopyOnly copy_only{};
-  absl::any o(absl::in_place_type_t<const volatile ListMoveOnlyCopyOnly>(),
-              {1, 2, 3, 4}, MoveOnly(), copy_only);
-  ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
-  std::vector<int> expected_values = {1, 2, 3, 4};
-  EXPECT_EQ(expected_values, v.values);
-}
-
-TEST(AnyTest, InPlaceConstructionIlistWithCVVariableTemplate) {
-  const CopyOnly copy_only{};
-  absl::any o(absl::in_place_type<const volatile ListMoveOnlyCopyOnly>,
-              {1, 2, 3, 4}, MoveOnly(), copy_only);
-  auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
-  std::vector<int> expected_values = {1, 2, 3, 4};
-  EXPECT_EQ(expected_values, v.values);
-}
-
-TEST(AnyTest, InPlaceNoArgs) {
-  absl::any o(absl::in_place_type_t<int>{});
-  EXPECT_EQ(0, absl::any_cast<int&>(o));
-}
-
-TEST(AnyTest, InPlaceNoArgsVariableTemplate) {
-  absl::any o(absl::in_place_type<int>);
-  EXPECT_EQ(0, absl::any_cast<int&>(o));
-}
-
-template <typename Enabler, typename T, typename... Args>
-struct CanEmplaceAnyImpl : std::false_type {};
-
-template <typename T, typename... Args>
-struct CanEmplaceAnyImpl<
-    absl::void_t<decltype(
-        std::declval<absl::any&>().emplace<T>(std::declval<Args>()...))>,
-    T, Args...> : std::true_type {};
-
-template <typename T, typename... Args>
-using CanEmplaceAny = CanEmplaceAnyImpl<void, T, Args...>;
-
-TEST(AnyTest, Emplace) {
-  const CopyOnly copy_only{};
-  absl::any o;
-  EXPECT_TRUE((std::is_same<decltype(o.emplace<IntMoveOnlyCopyOnly>(
-                                5, MoveOnly(), copy_only)),
-                            IntMoveOnlyCopyOnly&>::value));
-  IntMoveOnlyCopyOnly& emplace_result =
-      o.emplace<IntMoveOnlyCopyOnly>(5, MoveOnly(), copy_only);
-  EXPECT_EQ(5, emplace_result.value);
-  IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
-  EXPECT_EQ(5, v.value);
-  EXPECT_EQ(&emplace_result, &v);
-
-  static_assert(!CanEmplaceAny<int, int, int>::value, "");
-  static_assert(!CanEmplaceAny<MoveOnly, MoveOnly>::value, "");
-}
-
-TEST(AnyTest, EmplaceWithCV) {
-  const CopyOnly copy_only{};
-  absl::any o;
-  EXPECT_TRUE(
-      (std::is_same<decltype(o.emplace<const volatile IntMoveOnlyCopyOnly>(
-                        5, MoveOnly(), copy_only)),
-                    IntMoveOnlyCopyOnly&>::value));
-  IntMoveOnlyCopyOnly& emplace_result =
-      o.emplace<const volatile IntMoveOnlyCopyOnly>(5, MoveOnly(), copy_only);
-  EXPECT_EQ(5, emplace_result.value);
-  IntMoveOnlyCopyOnly& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
-  EXPECT_EQ(5, v.value);
-  EXPECT_EQ(&emplace_result, &v);
-}
-
-TEST(AnyTest, EmplaceWithFunction) {
-  absl::any o;
-  EXPECT_TRUE(
-      (std::is_same<decltype(o.emplace<FunctionType>(FunctionToEmplace)),
-                    FunctionType*&>::value));
-  FunctionType*& emplace_result = o.emplace<FunctionType>(FunctionToEmplace);
-  EXPECT_EQ(&FunctionToEmplace, emplace_result);
-}
-
-TEST(AnyTest, EmplaceWithArray) {
-  absl::any o;
-  ArrayType ar = {5, 42};
-  EXPECT_TRUE(
-      (std::is_same<decltype(o.emplace<ArrayType>(ar)), DecayedArray&>::value));
-  DecayedArray& emplace_result = o.emplace<ArrayType>(ar);
-  EXPECT_EQ(&ar[0], emplace_result);
-}
-
-TEST(AnyTest, EmplaceIlist) {
-  const CopyOnly copy_only{};
-  absl::any o;
-  EXPECT_TRUE((std::is_same<decltype(o.emplace<ListMoveOnlyCopyOnly>(
-                                {1, 2, 3, 4}, MoveOnly(), copy_only)),
-                            ListMoveOnlyCopyOnly&>::value));
-  ListMoveOnlyCopyOnly& emplace_result =
-      o.emplace<ListMoveOnlyCopyOnly>({1, 2, 3, 4}, MoveOnly(), copy_only);
-  ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
-  EXPECT_EQ(&v, &emplace_result);
-  std::vector<int> expected_values = {1, 2, 3, 4};
-  EXPECT_EQ(expected_values, v.values);
-
-  static_assert(!CanEmplaceAny<int, std::initializer_list<int>>::value, "");
-  static_assert(!CanEmplaceAny<MoveOnlyWithListConstructor,
-                               std::initializer_list<int>, int>::value,
-                "");
-}
-
-TEST(AnyTest, EmplaceIlistWithCV) {
-  const CopyOnly copy_only{};
-  absl::any o;
-  EXPECT_TRUE(
-      (std::is_same<decltype(o.emplace<const volatile ListMoveOnlyCopyOnly>(
-                        {1, 2, 3, 4}, MoveOnly(), copy_only)),
-                    ListMoveOnlyCopyOnly&>::value));
-  ListMoveOnlyCopyOnly& emplace_result =
-      o.emplace<const volatile ListMoveOnlyCopyOnly>({1, 2, 3, 4}, MoveOnly(),
-                                                     copy_only);
-  ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
-  EXPECT_EQ(&v, &emplace_result);
-  std::vector<int> expected_values = {1, 2, 3, 4};
-  EXPECT_EQ(expected_values, v.values);
-}
-
-TEST(AnyTest, EmplaceNoArgs) {
-  absl::any o;
-  o.emplace<int>();
-  EXPECT_EQ(0, absl::any_cast<int>(o));
-}
-
-TEST(AnyTest, ConversionConstruction) {
-  {
-    absl::any o = 5;
-    EXPECT_EQ(5, absl::any_cast<int>(o));
-  }
-
-  {
-    const CopyOnly copy_only(5);
-    absl::any o = copy_only;
-    EXPECT_EQ(5, absl::any_cast<CopyOnly&>(o).value);
-  }
-
-  static_assert(!std::is_convertible<MoveOnly, absl::any>::value, "");
-}
-
-TEST(AnyTest, ConversionAssignment) {
-  {
-    absl::any o;
-    o = 5;
-    EXPECT_EQ(5, absl::any_cast<int>(o));
-  }
-
-  {
-    const CopyOnly copy_only(5);
-    absl::any o;
-    o = copy_only;
-    EXPECT_EQ(5, absl::any_cast<CopyOnly&>(o).value);
-  }
-
-  static_assert(!std::is_assignable<MoveOnly, absl::any>::value, "");
-}
-
-// Suppress MSVC warnings.
-// 4521: multiple copy constructors specified
-// We wrote multiple of them to test that the correct overloads are selected.
-#ifdef _MSC_VER
-#pragma warning( push )
-#pragma warning( disable : 4521)
-#endif
-
-// Weird type for testing, only used to make sure we "properly" perfect-forward
-// when being placed into an absl::any (use the l-value constructor if given an
-// l-value rather than use the copy constructor).
-struct WeirdConstructor42 {
-  explicit WeirdConstructor42(int value) : value(value) {}
-
-  // Copy-constructor
-  WeirdConstructor42(const WeirdConstructor42& other) : value(other.value) {}
-
-  // L-value "weird" constructor (used when given an l-value)
-  WeirdConstructor42(
-      WeirdConstructor42& /*other*/)  // NOLINT(runtime/references)
-      : value(42) {}
-
-  int value;
-};
-#ifdef _MSC_VER
-#pragma warning( pop )
-#endif
-
-TEST(AnyTest, WeirdConversionConstruction) {
-  {
-    const WeirdConstructor42 source(5);
-    absl::any o = source;  // Actual copy
-    EXPECT_EQ(5, absl::any_cast<WeirdConstructor42&>(o).value);
-  }
-
-  {
-    WeirdConstructor42 source(5);
-    absl::any o = source;  // Weird "conversion"
-    EXPECT_EQ(42, absl::any_cast<WeirdConstructor42&>(o).value);
-  }
-}
-
-TEST(AnyTest, WeirdConversionAssignment) {
-  {
-    const WeirdConstructor42 source(5);
-    absl::any o;
-    o = source;  // Actual copy
-    EXPECT_EQ(5, absl::any_cast<WeirdConstructor42&>(o).value);
-  }
-
-  {
-    WeirdConstructor42 source(5);
-    absl::any o;
-    o = source;  // Weird "conversion"
-    EXPECT_EQ(42, absl::any_cast<WeirdConstructor42&>(o).value);
-  }
-}
-
-struct Value {};
-
-TEST(AnyTest, AnyCastValue) {
-  {
-    absl::any o;
-    o.emplace<int>(5);
-    EXPECT_EQ(5, absl::any_cast<int>(o));
-    EXPECT_EQ(5, absl::any_cast<int>(AsConst(o)));
-    static_assert(
-        std::is_same<decltype(absl::any_cast<Value>(o)), Value>::value, "");
-  }
-
-  {
-    absl::any o;
-    o.emplace<int>(5);
-    EXPECT_EQ(5, absl::any_cast<const int>(o));
-    EXPECT_EQ(5, absl::any_cast<const int>(AsConst(o)));
-    static_assert(std::is_same<decltype(absl::any_cast<const Value>(o)),
-                               const Value>::value,
-                  "");
-  }
-}
-
-TEST(AnyTest, AnyCastReference) {
-  {
-    absl::any o;
-    o.emplace<int>(5);
-    EXPECT_EQ(5, absl::any_cast<int&>(o));
-    EXPECT_EQ(5, absl::any_cast<const int&>(AsConst(o)));
-    static_assert(
-        std::is_same<decltype(absl::any_cast<Value&>(o)), Value&>::value, "");
-  }
-
-  {
-    absl::any o;
-    o.emplace<int>(5);
-    EXPECT_EQ(5, absl::any_cast<const int>(o));
-    EXPECT_EQ(5, absl::any_cast<const int>(AsConst(o)));
-    static_assert(std::is_same<decltype(absl::any_cast<const Value&>(o)),
-                               const Value&>::value,
-                  "");
-  }
-
-  {
-    absl::any o;
-    o.emplace<int>(5);
-    EXPECT_EQ(5, absl::any_cast<int&&>(std::move(o)));
-    static_assert(std::is_same<decltype(absl::any_cast<Value&&>(std::move(o))),
-                               Value&&>::value,
-                  "");
-  }
-
-  {
-    absl::any o;
-    o.emplace<int>(5);
-    EXPECT_EQ(5, absl::any_cast<const int>(std::move(o)));
-    static_assert(
-        std::is_same<decltype(absl::any_cast<const Value&&>(std::move(o))),
-                     const Value&&>::value,
-        "");
-  }
-}
-
-TEST(AnyTest, AnyCastPointer) {
-  {
-    absl::any o;
-    EXPECT_EQ(nullptr, absl::any_cast<char>(&o));
-    o.emplace<int>(5);
-    EXPECT_EQ(nullptr, absl::any_cast<char>(&o));
-    o.emplace<char>('a');
-    EXPECT_EQ('a', *absl::any_cast<char>(&o));
-    static_assert(
-        std::is_same<decltype(absl::any_cast<Value>(&o)), Value*>::value, "");
-  }
-
-  {
-    absl::any o;
-    EXPECT_EQ(nullptr, absl::any_cast<const char>(&o));
-    o.emplace<int>(5);
-    EXPECT_EQ(nullptr, absl::any_cast<const char>(&o));
-    o.emplace<char>('a');
-    EXPECT_EQ('a', *absl::any_cast<const char>(&o));
-    static_assert(std::is_same<decltype(absl::any_cast<const Value>(&o)),
-                               const Value*>::value,
-                  "");
-  }
-}
-
-TEST(AnyTest, MakeAny) {
-  const CopyOnly copy_only{};
-  auto o = absl::make_any<IntMoveOnlyCopyOnly>(5, MoveOnly(), copy_only);
-  static_assert(std::is_same<decltype(o), absl::any>::value, "");
-  EXPECT_EQ(5, absl::any_cast<IntMoveOnlyCopyOnly&>(o).value);
-}
-
-TEST(AnyTest, MakeAnyIList) {
-  const CopyOnly copy_only{};
-  auto o =
-      absl::make_any<ListMoveOnlyCopyOnly>({1, 2, 3}, MoveOnly(), copy_only);
-  static_assert(std::is_same<decltype(o), absl::any>::value, "");
-  ListMoveOnlyCopyOnly& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
-  std::vector<int> expected_values = {1, 2, 3};
-  EXPECT_EQ(expected_values, v.values);
-}
-
-// Test the use of copy constructor and operator=
-TEST(AnyTest, Copy) {
-  InstanceTracker tracker_raii;
-
-  {
-    absl::any o(absl::in_place_type<CopyableOnlyInstance>, 123);
-    CopyableOnlyInstance* f1 = absl::any_cast<CopyableOnlyInstance>(&o);
-
-    absl::any o2(o);
-    const CopyableOnlyInstance* f2 = absl::any_cast<CopyableOnlyInstance>(&o2);
-    EXPECT_EQ(123, f2->value());
-    EXPECT_NE(f1, f2);
-
-    absl::any o3;
-    o3 = o2;
-    const CopyableOnlyInstance* f3 = absl::any_cast<CopyableOnlyInstance>(&o3);
-    EXPECT_EQ(123, f3->value());
-    EXPECT_NE(f2, f3);
-
-    const absl::any o4(4);
-    // copy construct from const lvalue ref.
-    absl::any o5 = o4;
-    EXPECT_EQ(4, absl::any_cast<int>(o4));
-    EXPECT_EQ(4, absl::any_cast<int>(o5));
-
-    // Copy construct from const rvalue ref.
-    absl::any o6 = std::move(o4);  // NOLINT
-    EXPECT_EQ(4, absl::any_cast<int>(o4));
-    EXPECT_EQ(4, absl::any_cast<int>(o6));
-  }
-}
-
-TEST(AnyTest, Move) {
-  InstanceTracker tracker_raii;
-
-  absl::any any1;
-  any1.emplace<CopyableOnlyInstance>(5);
-
-  // This is a copy, so copy count increases to 1.
-  absl::any any2 = any1;
-  EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any1).value());
-  EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any2).value());
-  EXPECT_EQ(1, tracker_raii.copies());
-
-  // This isn't a copy, so copy count doesn't increase.
-  absl::any any3 = std::move(any2);
-  EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any3).value());
-  EXPECT_EQ(1, tracker_raii.copies());
-
-  absl::any any4;
-  any4 = std::move(any3);
-  EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(any4).value());
-  EXPECT_EQ(1, tracker_raii.copies());
-
-  absl::any tmp4(4);
-  absl::any o4(std::move(tmp4));  // move construct
-  EXPECT_EQ(4, absl::any_cast<int>(o4));
-  o4 = *&o4;  // self assign
-  EXPECT_EQ(4, absl::any_cast<int>(o4));
-  EXPECT_TRUE(o4.has_value());
-
-  absl::any o5;
-  absl::any tmp5(5);
-  o5 = std::move(tmp5);  // move assign
-  EXPECT_EQ(5, absl::any_cast<int>(o5));
-}
-
-// Reset the ObjectOwner with an object of a different type
-TEST(AnyTest, Reset) {
-  absl::any o;
-  o.emplace<int>();
-
-  o.reset();
-  EXPECT_FALSE(o.has_value());
-
-  o.emplace<char>();
-  EXPECT_TRUE(o.has_value());
-}
-
-TEST(AnyTest, ConversionConstructionCausesOneCopy) {
-  InstanceTracker tracker_raii;
-  CopyableOnlyInstance counter(5);
-  absl::any o(counter);
-  EXPECT_EQ(5, absl::any_cast<CopyableOnlyInstance&>(o).value());
-  EXPECT_EQ(1, tracker_raii.copies());
-}
-
-//////////////////////////////////
-// Tests for Exception Behavior //
-//////////////////////////////////
-
-#if defined(ABSL_USES_STD_ANY)
-
-// If using a std `any` implementation, we can't check for a specific message.
-#define ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(...)                      \
-  ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), absl::bad_any_cast, \
-                                 "")
-
-#else
-
-// If using the absl `any` implementation, we can rely on a specific message.
-#define ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(...)                      \
-  ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), absl::bad_any_cast, \
-                                 "Bad any cast")
-
-#endif  // defined(ABSL_USES_STD_ANY)
-
-TEST(AnyTest, ThrowBadAlloc) {
-  {
-    absl::any a;
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int&>(a));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int&>(a));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int&&>(absl::any{}));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int&&>(absl::any{}));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int>(a));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int>(a));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int>(absl::any{}));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int>(absl::any{}));
-
-    // const absl::any operand
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int&>(AsConst(a)));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<int>(AsConst(a)));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const int>(AsConst(a)));
-  }
-
-  {
-    absl::any a(absl::in_place_type<int>);
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&>(a));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float&>(a));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&&>(absl::any{}));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(
-        absl::any_cast<const float&&>(absl::any{}));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float>(a));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float>(a));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float>(absl::any{}));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float>(absl::any{}));
-
-    // const absl::any operand
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float&>(AsConst(a)));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float>(AsConst(a)));
-    ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float>(AsConst(a)));
-  }
-}
-
-class BadCopy {};
-
-struct BadCopyable {
-  BadCopyable() = default;
-  BadCopyable(BadCopyable&&) = default;
-  BadCopyable(const BadCopyable&) {
-#ifdef ABSL_HAVE_EXCEPTIONS
-    throw BadCopy();
-#else
-    LOG(FATAL) << "Bad copy";
-#endif
-  }
-};
-
-#define ABSL_ANY_TEST_EXPECT_BAD_COPY(...) \
-  ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), BadCopy, "Bad copy")
-
-// Test the guarantees regarding exceptions in copy/assign.
-TEST(AnyTest, FailedCopy) {
-  {
-    const BadCopyable bad{};
-    ABSL_ANY_TEST_EXPECT_BAD_COPY(absl::any{bad});
-  }
-
-  {
-    absl::any src(absl::in_place_type<BadCopyable>);
-    ABSL_ANY_TEST_EXPECT_BAD_COPY(absl::any{src});
-  }
-
-  {
-    BadCopyable bad;
-    absl::any target;
-    ABSL_ANY_TEST_EXPECT_BAD_COPY(target = bad);
-  }
-
-  {
-    BadCopyable bad;
-    absl::any target(absl::in_place_type<BadCopyable>);
-    ABSL_ANY_TEST_EXPECT_BAD_COPY(target = bad);
-    EXPECT_TRUE(target.has_value());
-  }
-
-  {
-    absl::any src(absl::in_place_type<BadCopyable>);
-    absl::any target;
-    ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src);
-    EXPECT_FALSE(target.has_value());
-  }
-
-  {
-    absl::any src(absl::in_place_type<BadCopyable>);
-    absl::any target(absl::in_place_type<BadCopyable>);
-    ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src);
-    EXPECT_TRUE(target.has_value());
-  }
-}
-
-// Test the guarantees regarding exceptions in emplace.
-TEST(AnyTest, FailedEmplace) {
-  BadCopyable bad;
-  absl::any target;
-  ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad));
-}
-
-// GCC and Clang have a bug here.
-// Ine some cases, the exception seems to be thrown at the wrong time, and
-// target may contain a value.
-#ifdef __GNUC__
-TEST(AnyTest, DISABLED_FailedEmplaceInPlace) {
-#else
-TEST(AnyTest, FailedEmplaceInPlace) {
-#endif
-  BadCopyable bad;
-  absl::any target(absl::in_place_type<int>);
-  ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad));
-  EXPECT_FALSE(target.has_value());
-}
-
-}  // namespace
-
-#endif  // #if !defined(ABSL_USES_STD_ANY)
diff --git a/absl/types/bad_any_cast.cc b/absl/types/bad_any_cast.cc
deleted file mode 100644
index 22558b4..0000000
--- a/absl/types/bad_any_cast.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/types/bad_any_cast.h"
-
-#ifndef ABSL_USES_STD_ANY
-
-#include <cstdlib>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-bad_any_cast::~bad_any_cast() = default;
-
-const char* bad_any_cast::what() const noexcept { return "Bad any cast"; }
-
-namespace any_internal {
-
-void ThrowBadAnyCast() {
-#ifdef ABSL_HAVE_EXCEPTIONS
-  throw bad_any_cast();
-#else
-  ABSL_RAW_LOG(FATAL, "Bad any cast");
-  std::abort();
-#endif
-}
-
-}  // namespace any_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#else
-
-// https://github.com/abseil/abseil-cpp/issues/1465
-// CMake builds on Apple platforms error when libraries are empty.
-// Our CMake configuration can avoid this error on header-only libraries,
-// but since this library is conditionally empty, including a single
-// variable is an easy workaround.
-#ifdef __APPLE__
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace types_internal {
-extern const char kAvoidEmptyBadAnyCastLibraryWarning;
-const char kAvoidEmptyBadAnyCastLibraryWarning = 0;
-}  // namespace types_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-#endif  // __APPLE__
-
-#endif  // ABSL_USES_STD_ANY
diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h
deleted file mode 100644
index 114cef8..0000000
--- a/absl/types/bad_any_cast.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2018 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.
-//
-// -----------------------------------------------------------------------------
-// bad_any_cast.h
-// -----------------------------------------------------------------------------
-//
-// This header file defines the `absl::bad_any_cast` type.
-
-#ifndef ABSL_TYPES_BAD_ANY_CAST_H_
-#define ABSL_TYPES_BAD_ANY_CAST_H_
-
-#include <typeinfo>
-
-#include "absl/base/config.h"
-
-#ifdef ABSL_USES_STD_ANY
-
-#include <any>
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-using std::bad_any_cast;
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#else  // ABSL_USES_STD_ANY
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// -----------------------------------------------------------------------------
-// bad_any_cast
-// -----------------------------------------------------------------------------
-//
-// An `absl::bad_any_cast` type is an exception type that is thrown when
-// failing to successfully cast the return value of an `absl::any` object.
-//
-// Example:
-//
-//   auto a = absl::any(65);
-//   absl::any_cast<int>(a);         // 65
-//   try {
-//     absl::any_cast<char>(a);
-//   } catch(const absl::bad_any_cast& e) {
-//     std::cout << "Bad any cast: " << e.what() << '\n';
-//   }
-class bad_any_cast : public std::bad_cast {
- public:
-  ~bad_any_cast() override;
-  const char* what() const noexcept override;
-};
-
-namespace any_internal {
-
-[[noreturn]] void ThrowBadAnyCast();
-
-}  // namespace any_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_USES_STD_ANY
-
-#endif  // ABSL_TYPES_BAD_ANY_CAST_H_
diff --git a/absl/types/bad_optional_access.cc b/absl/types/bad_optional_access.cc
deleted file mode 100644
index 2552cc8..0000000
--- a/absl/types/bad_optional_access.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/types/bad_optional_access.h"
-
-#ifndef ABSL_USES_STD_OPTIONAL
-
-#include <cstdlib>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-bad_optional_access::~bad_optional_access() = default;
-
-const char* bad_optional_access::what() const noexcept {
-  return "optional has no value";
-}
-
-namespace optional_internal {
-
-void throw_bad_optional_access() {
-#ifdef ABSL_HAVE_EXCEPTIONS
-  throw bad_optional_access();
-#else
-  ABSL_RAW_LOG(FATAL, "Bad optional access");
-  abort();
-#endif
-}
-
-}  // namespace optional_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#else
-
-// https://github.com/abseil/abseil-cpp/issues/1465
-// CMake builds on Apple platforms error when libraries are empty.
-// Our CMake configuration can avoid this error on header-only libraries,
-// but since this library is conditionally empty, including a single
-// variable is an easy workaround.
-#ifdef __APPLE__
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace types_internal {
-extern const char kAvoidEmptyBadOptionalAccessLibraryWarning;
-const char kAvoidEmptyBadOptionalAccessLibraryWarning = 0;
-}  // namespace types_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-#endif  // __APPLE__
-
-#endif  // ABSL_USES_STD_OPTIONAL
diff --git a/absl/types/bad_optional_access.h b/absl/types/bad_optional_access.h
deleted file mode 100644
index 049e72a..0000000
--- a/absl/types/bad_optional_access.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2018 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.
-//
-// -----------------------------------------------------------------------------
-// bad_optional_access.h
-// -----------------------------------------------------------------------------
-//
-// This header file defines the `absl::bad_optional_access` type.
-
-#ifndef ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
-#define ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
-
-#include <stdexcept>
-
-#include "absl/base/config.h"
-
-#ifdef ABSL_USES_STD_OPTIONAL
-
-#include <optional>
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-using std::bad_optional_access;
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#else  // ABSL_USES_STD_OPTIONAL
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// -----------------------------------------------------------------------------
-// bad_optional_access
-// -----------------------------------------------------------------------------
-//
-// An `absl::bad_optional_access` type is an exception type that is thrown when
-// attempting to access an `absl::optional` object that does not contain a
-// value.
-//
-// Example:
-//
-//   absl::optional<int> o;
-//
-//   try {
-//     int n = o.value();
-//   } catch(const absl::bad_optional_access& e) {
-//     std::cout << "Bad optional access: " << e.what() << '\n';
-//   }
-class bad_optional_access : public std::exception {
- public:
-  bad_optional_access() = default;
-  ~bad_optional_access() override;
-  const char* what() const noexcept override;
-};
-
-namespace optional_internal {
-
-// throw delegator
-[[noreturn]] ABSL_DLL void throw_bad_optional_access();
-
-}  // namespace optional_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_USES_STD_OPTIONAL
-
-#endif  // ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
diff --git a/absl/types/bad_variant_access.cc b/absl/types/bad_variant_access.cc
deleted file mode 100644
index a76aa80..0000000
--- a/absl/types/bad_variant_access.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/types/bad_variant_access.h"
-
-#ifndef ABSL_USES_STD_VARIANT
-
-#include <cstdlib>
-#include <stdexcept>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-//////////////////////////
-// [variant.bad.access] //
-//////////////////////////
-
-bad_variant_access::~bad_variant_access() = default;
-
-const char* bad_variant_access::what() const noexcept {
-  return "Bad variant access";
-}
-
-namespace variant_internal {
-
-void ThrowBadVariantAccess() {
-#ifdef ABSL_HAVE_EXCEPTIONS
-  throw bad_variant_access();
-#else
-  ABSL_RAW_LOG(FATAL, "Bad variant access");
-  abort();  // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn.
-#endif
-}
-
-void Rethrow() {
-#ifdef ABSL_HAVE_EXCEPTIONS
-  throw;
-#else
-  ABSL_RAW_LOG(FATAL,
-               "Internal error in absl::variant implementation. Attempted to "
-               "rethrow an exception when building with exceptions disabled.");
-  abort();  // TODO(calabrese) Remove once RAW_LOG FATAL is noreturn.
-#endif
-}
-
-}  // namespace variant_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#else
-
-// https://github.com/abseil/abseil-cpp/issues/1465
-// CMake builds on Apple platforms error when libraries are empty.
-// Our CMake configuration can avoid this error on header-only libraries,
-// but since this library is conditionally empty, including a single
-// variable is an easy workaround.
-#ifdef __APPLE__
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace types_internal {
-extern const char kAvoidEmptyBadVariantAccessLibraryWarning;
-const char kAvoidEmptyBadVariantAccessLibraryWarning = 0;
-}  // namespace types_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-#endif  // __APPLE__
-
-#endif  // ABSL_USES_STD_VARIANT
diff --git a/absl/types/bad_variant_access.h b/absl/types/bad_variant_access.h
deleted file mode 100644
index 8ab215e..0000000
--- a/absl/types/bad_variant_access.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2018 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.
-//
-// -----------------------------------------------------------------------------
-// bad_variant_access.h
-// -----------------------------------------------------------------------------
-//
-// This header file defines the `absl::bad_variant_access` type.
-
-#ifndef ABSL_TYPES_BAD_VARIANT_ACCESS_H_
-#define ABSL_TYPES_BAD_VARIANT_ACCESS_H_
-
-#include <stdexcept>
-
-#include "absl/base/config.h"
-
-#ifdef ABSL_USES_STD_VARIANT
-
-#include <variant>
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-using std::bad_variant_access;
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#else  // ABSL_USES_STD_VARIANT
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// -----------------------------------------------------------------------------
-// bad_variant_access
-// -----------------------------------------------------------------------------
-//
-// An `absl::bad_variant_access` type is an exception type that is thrown in
-// the following cases:
-//
-//   * Calling `absl::get(absl::variant) with an index or type that does not
-//     match the currently selected alternative type
-//   * Calling `absl::visit on an `absl::variant` that is in the
-//     `variant::valueless_by_exception` state.
-//
-// Example:
-//
-//   absl::variant<int, std::string> v;
-//   v = 1;
-//   try {
-//     absl::get<std::string>(v);
-//   } catch(const absl::bad_variant_access& e) {
-//     std::cout << "Bad variant access: " << e.what() << '\n';
-//   }
-class bad_variant_access : public std::exception {
- public:
-  bad_variant_access() noexcept = default;
-  ~bad_variant_access() override;
-  const char* what() const noexcept override;
-};
-
-namespace variant_internal {
-
-[[noreturn]] ABSL_DLL void ThrowBadVariantAccess();
-[[noreturn]] ABSL_DLL void Rethrow();
-
-}  // namespace variant_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_USES_STD_VARIANT
-
-#endif  // ABSL_TYPES_BAD_VARIANT_ACCESS_H_
diff --git a/absl/types/internal/optional.h b/absl/types/internal/optional.h
deleted file mode 100644
index 5731a5b..0000000
--- a/absl/types/internal/optional.h
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright 2017 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_TYPES_INTERNAL_OPTIONAL_H_
-#define ABSL_TYPES_INTERNAL_OPTIONAL_H_
-
-#include <functional>
-#include <new>
-#include <type_traits>
-#include <utility>
-
-#include "absl/base/internal/inline_variable.h"
-#include "absl/memory/memory.h"
-#include "absl/meta/type_traits.h"
-#include "absl/utility/utility.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// Forward declaration
-template <typename T>
-class optional;
-
-namespace optional_internal {
-
-// This tag type is used as a constructor parameter type for `nullopt_t`.
-struct init_t {
-  explicit init_t() = default;
-};
-
-struct empty_struct {};
-
-// This class stores the data in optional<T>.
-// It is specialized based on whether T is trivially destructible.
-// This is the specialization for non trivially destructible type.
-template <typename T, bool unused = std::is_trivially_destructible<T>::value>
-class optional_data_dtor_base {
-  struct dummy_type {
-    static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
-    // Use an array to avoid GCC 6 placement-new warning.
-    empty_struct data[sizeof(T) / sizeof(empty_struct)];
-  };
-
- protected:
-  // Whether there is data or not.
-  bool engaged_;
-  // Data storage
-  union {
-    T data_;
-    dummy_type dummy_;
-  };
-
-  void destruct() noexcept {
-    if (engaged_) {
-      // `data_` must be initialized if `engaged_` is true.
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
-      data_.~T();
-#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
-#pragma GCC diagnostic pop
-#endif
-      engaged_ = false;
-    }
-  }
-
-  // dummy_ must be initialized for constexpr constructor.
-  constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
-
-  template <typename... Args>
-  constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
-      : engaged_(true), data_(std::forward<Args>(args)...) {}
-
-  ~optional_data_dtor_base() { destruct(); }
-};
-
-// Specialization for trivially destructible type.
-template <typename T>
-class optional_data_dtor_base<T, true> {
-  struct dummy_type {
-    static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
-    // Use array to avoid GCC 6 placement-new warning.
-    empty_struct data[sizeof(T) / sizeof(empty_struct)];
-  };
-
- protected:
-  // Whether there is data or not.
-  bool engaged_;
-  // Data storage
-  union {
-    T data_;
-    dummy_type dummy_;
-  };
-  void destruct() noexcept { engaged_ = false; }
-
-  // dummy_ must be initialized for constexpr constructor.
-  constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
-
-  template <typename... Args>
-  constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
-      : engaged_(true), data_(std::forward<Args>(args)...) {}
-};
-
-template <typename T>
-class optional_data_base : public optional_data_dtor_base<T> {
- protected:
-  using base = optional_data_dtor_base<T>;
-  using base::base;
-
-  template <typename... Args>
-  void construct(Args&&... args) {
-    // Use dummy_'s address to work around casting cv-qualified T* to void*.
-    ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);
-    this->engaged_ = true;
-  }
-
-  template <typename U>
-  void assign(U&& u) {
-    if (this->engaged_) {
-      this->data_ = std::forward<U>(u);
-    } else {
-      construct(std::forward<U>(u));
-    }
-  }
-};
-
-// TODO(absl-team): Add another class using
-// std::is_trivially_move_constructible trait when available to match
-// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that
-// have trivial move but nontrivial copy.
-// Also, we should be checking is_trivially_copyable here, which is not
-// supported now, so we use is_trivially_* traits instead.
-template <typename T,
-          bool unused = absl::is_trivially_copy_constructible<T>::value&&
-              absl::is_trivially_copy_assignable<typename std::remove_cv<
-                  T>::type>::value&& std::is_trivially_destructible<T>::value>
-class optional_data;
-
-// Trivially copyable types
-template <typename T>
-class optional_data<T, true> : public optional_data_base<T> {
- protected:
-  using optional_data_base<T>::optional_data_base;
-};
-
-template <typename T>
-class optional_data<T, false> : public optional_data_base<T> {
- protected:
-  using optional_data_base<T>::optional_data_base;
-
-  optional_data() = default;
-
-  optional_data(const optional_data& rhs) : optional_data_base<T>() {
-    if (rhs.engaged_) {
-      this->construct(rhs.data_);
-    }
-  }
-
-  optional_data(optional_data&& rhs) noexcept(
-      absl::default_allocator_is_nothrow::value ||
-      std::is_nothrow_move_constructible<T>::value)
-      : optional_data_base<T>() {
-    if (rhs.engaged_) {
-      this->construct(std::move(rhs.data_));
-    }
-  }
-
-  optional_data& operator=(const optional_data& rhs) {
-    if (rhs.engaged_) {
-      this->assign(rhs.data_);
-    } else {
-      this->destruct();
-    }
-    return *this;
-  }
-
-  optional_data& operator=(optional_data&& rhs) noexcept(
-      std::is_nothrow_move_assignable<T>::value&&
-          std::is_nothrow_move_constructible<T>::value) {
-    if (rhs.engaged_) {
-      this->assign(std::move(rhs.data_));
-    } else {
-      this->destruct();
-    }
-    return *this;
-  }
-};
-
-// Ordered by level of restriction, from low to high.
-// Copyable implies movable.
-enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
-
-// Base class for enabling/disabling copy/move constructor.
-template <copy_traits>
-class optional_ctor_base;
-
-template <>
-class optional_ctor_base<copy_traits::copyable> {
- public:
-  constexpr optional_ctor_base() = default;
-  optional_ctor_base(const optional_ctor_base&) = default;
-  optional_ctor_base(optional_ctor_base&&) = default;
-  optional_ctor_base& operator=(const optional_ctor_base&) = default;
-  optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-template <>
-class optional_ctor_base<copy_traits::movable> {
- public:
-  constexpr optional_ctor_base() = default;
-  optional_ctor_base(const optional_ctor_base&) = delete;
-  optional_ctor_base(optional_ctor_base&&) = default;
-  optional_ctor_base& operator=(const optional_ctor_base&) = default;
-  optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-template <>
-class optional_ctor_base<copy_traits::non_movable> {
- public:
-  constexpr optional_ctor_base() = default;
-  optional_ctor_base(const optional_ctor_base&) = delete;
-  optional_ctor_base(optional_ctor_base&&) = delete;
-  optional_ctor_base& operator=(const optional_ctor_base&) = default;
-  optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-// Base class for enabling/disabling copy/move assignment.
-template <copy_traits>
-class optional_assign_base;
-
-template <>
-class optional_assign_base<copy_traits::copyable> {
- public:
-  constexpr optional_assign_base() = default;
-  optional_assign_base(const optional_assign_base&) = default;
-  optional_assign_base(optional_assign_base&&) = default;
-  optional_assign_base& operator=(const optional_assign_base&) = default;
-  optional_assign_base& operator=(optional_assign_base&&) = default;
-};
-
-template <>
-class optional_assign_base<copy_traits::movable> {
- public:
-  constexpr optional_assign_base() = default;
-  optional_assign_base(const optional_assign_base&) = default;
-  optional_assign_base(optional_assign_base&&) = default;
-  optional_assign_base& operator=(const optional_assign_base&) = delete;
-  optional_assign_base& operator=(optional_assign_base&&) = default;
-};
-
-template <>
-class optional_assign_base<copy_traits::non_movable> {
- public:
-  constexpr optional_assign_base() = default;
-  optional_assign_base(const optional_assign_base&) = default;
-  optional_assign_base(optional_assign_base&&) = default;
-  optional_assign_base& operator=(const optional_assign_base&) = delete;
-  optional_assign_base& operator=(optional_assign_base&&) = delete;
-};
-
-template <typename T>
-struct ctor_copy_traits {
-  static constexpr copy_traits traits =
-      std::is_copy_constructible<T>::value
-          ? copy_traits::copyable
-          : std::is_move_constructible<T>::value ? copy_traits::movable
-                                                 : copy_traits::non_movable;
-};
-
-template <typename T>
-struct assign_copy_traits {
-  static constexpr copy_traits traits =
-      absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value
-          ? copy_traits::copyable
-          : absl::is_move_assignable<T>::value &&
-                    std::is_move_constructible<T>::value
-                ? copy_traits::movable
-                : copy_traits::non_movable;
-};
-
-// Whether T is constructible or convertible from optional<U>.
-template <typename T, typename U>
-struct is_constructible_convertible_from_optional
-    : std::integral_constant<
-          bool, std::is_constructible<T, optional<U>&>::value ||
-                    std::is_constructible<T, optional<U>&&>::value ||
-                    std::is_constructible<T, const optional<U>&>::value ||
-                    std::is_constructible<T, const optional<U>&&>::value ||
-                    std::is_convertible<optional<U>&, T>::value ||
-                    std::is_convertible<optional<U>&&, T>::value ||
-                    std::is_convertible<const optional<U>&, T>::value ||
-                    std::is_convertible<const optional<U>&&, T>::value> {};
-
-// Whether T is constructible or convertible or assignable from optional<U>.
-template <typename T, typename U>
-struct is_constructible_convertible_assignable_from_optional
-    : std::integral_constant<
-          bool, is_constructible_convertible_from_optional<T, U>::value ||
-                    std::is_assignable<T&, optional<U>&>::value ||
-                    std::is_assignable<T&, optional<U>&&>::value ||
-                    std::is_assignable<T&, const optional<U>&>::value ||
-                    std::is_assignable<T&, const optional<U>&&>::value> {};
-
-// Helper function used by [optional.relops], [optional.comp_with_t],
-// for checking whether an expression is convertible to bool.
-bool convertible_to_bool(bool);
-
-// Base class for std::hash<absl::optional<T>>:
-// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to
-// compute the hash; Otherwise, it is disabled.
-// Reference N4659 23.14.15 [unord.hash].
-template <typename T, typename = size_t>
-struct optional_hash_base {
-  optional_hash_base() = delete;
-  optional_hash_base(const optional_hash_base&) = delete;
-  optional_hash_base(optional_hash_base&&) = delete;
-  optional_hash_base& operator=(const optional_hash_base&) = delete;
-  optional_hash_base& operator=(optional_hash_base&&) = delete;
-};
-
-template <typename T>
-struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
-                                 std::declval<absl::remove_const_t<T> >()))> {
-  using argument_type = absl::optional<T>;
-  using result_type = size_t;
-  size_t operator()(const absl::optional<T>& opt) const {
-    absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>();
-    if (opt) {
-      return std::hash<absl::remove_const_t<T> >()(*opt);
-    } else {
-      return static_cast<size_t>(0x297814aaad196e6dULL);
-    }
-  }
-};
-
-}  // namespace optional_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_TYPES_INTERNAL_OPTIONAL_H_
diff --git a/absl/types/internal/span.h b/absl/types/internal/span.h
index ab89ba3..1039f61 100644
--- a/absl/types/internal/span.h
+++ b/absl/types/internal/span.h
@@ -22,6 +22,7 @@
 #include <type_traits>
 
 #include "absl/algorithm/algorithm.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/meta/type_traits.h"
 
@@ -86,13 +87,13 @@
     typename std::enable_if<!std::is_const<T>::value, int>::type;
 
 template <template <typename> class SpanT, typename T>
-bool EqualImpl(SpanT<T> a, SpanT<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool EqualImpl(SpanT<T> a, SpanT<T> b) {
   static_assert(std::is_const<T>::value, "");
   return std::equal(a.begin(), a.end(), b.begin(), b.end());
 }
 
 template <template <typename> class SpanT, typename T>
-bool LessThanImpl(SpanT<T> a, SpanT<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool LessThanImpl(SpanT<T> a, SpanT<T> b) {
   // We can't use value_type since that is remove_cv_t<T>, so we go the long way
   // around.
   static_assert(std::is_const<T>::value, "");
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
deleted file mode 100644
index 4cb15f2..0000000
--- a/absl/types/internal/variant.h
+++ /dev/null
@@ -1,1622 +0,0 @@
-// Copyright 2018 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.
-//
-// Implementation details of absl/types/variant.h, pulled into a
-// separate file to avoid cluttering the top of the API header with
-// implementation details.
-
-#ifndef ABSL_TYPES_INTERNAL_VARIANT_H_
-#define ABSL_TYPES_INTERNAL_VARIANT_H_
-
-#include <cassert>
-#include <cstddef>
-#include <cstdlib>
-#include <memory>
-#include <stdexcept>
-#include <tuple>
-#include <type_traits>
-#include <utility>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/identity.h"
-#include "absl/base/internal/inline_variable.h"
-#include "absl/base/internal/invoke.h"
-#include "absl/base/macros.h"
-#include "absl/base/optimization.h"
-#include "absl/meta/type_traits.h"
-#include "absl/types/bad_variant_access.h"
-#include "absl/utility/utility.h"
-
-#if !defined(ABSL_USES_STD_VARIANT)
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-template <class... Types>
-class variant;
-
-ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast<size_t>(-1));
-
-template <class T>
-struct variant_size;
-
-template <std::size_t I, class T>
-struct variant_alternative;
-
-namespace variant_internal {
-
-// NOTE: See specializations below for details.
-template <std::size_t I, class T>
-struct VariantAlternativeSfinae {};
-
-// Requires: I < variant_size_v<T>.
-//
-// Value: The Ith type of Types...
-template <std::size_t I, class T0, class... Tn>
-struct VariantAlternativeSfinae<I, variant<T0, Tn...>>
-    : VariantAlternativeSfinae<I - 1, variant<Tn...>> {};
-
-// Value: T0
-template <class T0, class... Ts>
-struct VariantAlternativeSfinae<0, variant<T0, Ts...>> {
-  using type = T0;
-};
-
-template <std::size_t I, class T>
-using VariantAlternativeSfinaeT = typename VariantAlternativeSfinae<I, T>::type;
-
-// NOTE: Requires T to be a reference type.
-template <class T, class U>
-struct GiveQualsTo;
-
-template <class T, class U>
-struct GiveQualsTo<T&, U> {
-  using type = U&;
-};
-
-template <class T, class U>
-struct GiveQualsTo<T&&, U> {
-  using type = U&&;
-};
-
-template <class T, class U>
-struct GiveQualsTo<const T&, U> {
-  using type = const U&;
-};
-
-template <class T, class U>
-struct GiveQualsTo<const T&&, U> {
-  using type = const U&&;
-};
-
-template <class T, class U>
-struct GiveQualsTo<volatile T&, U> {
-  using type = volatile U&;
-};
-
-template <class T, class U>
-struct GiveQualsTo<volatile T&&, U> {
-  using type = volatile U&&;
-};
-
-template <class T, class U>
-struct GiveQualsTo<volatile const T&, U> {
-  using type = volatile const U&;
-};
-
-template <class T, class U>
-struct GiveQualsTo<volatile const T&&, U> {
-  using type = volatile const U&&;
-};
-
-template <class T, class U>
-using GiveQualsToT = typename GiveQualsTo<T, U>::type;
-
-// Convenience alias, since size_t integral_constant is used a lot in this file.
-template <std::size_t I>
-using SizeT = std::integral_constant<std::size_t, I>;
-
-using NPos = SizeT<variant_npos>;
-
-template <class Variant, class T, class = void>
-struct IndexOfConstructedType {};
-
-template <std::size_t I, class Variant>
-struct VariantAccessResultImpl;
-
-template <std::size_t I, template <class...> class Variantemplate, class... T>
-struct VariantAccessResultImpl<I, Variantemplate<T...>&> {
-  using type = typename absl::variant_alternative<I, variant<T...>>::type&;
-};
-
-template <std::size_t I, template <class...> class Variantemplate, class... T>
-struct VariantAccessResultImpl<I, const Variantemplate<T...>&> {
-  using type =
-      const typename absl::variant_alternative<I, variant<T...>>::type&;
-};
-
-template <std::size_t I, template <class...> class Variantemplate, class... T>
-struct VariantAccessResultImpl<I, Variantemplate<T...>&&> {
-  using type = typename absl::variant_alternative<I, variant<T...>>::type&&;
-};
-
-template <std::size_t I, template <class...> class Variantemplate, class... T>
-struct VariantAccessResultImpl<I, const Variantemplate<T...>&&> {
-  using type =
-      const typename absl::variant_alternative<I, variant<T...>>::type&&;
-};
-
-template <std::size_t I, class Variant>
-using VariantAccessResult =
-    typename VariantAccessResultImpl<I, Variant&&>::type;
-
-// NOTE: This is used instead of std::array to reduce instantiation overhead.
-template <class T, std::size_t Size>
-struct SimpleArray {
-  static_assert(Size != 0, "");
-  T value[Size];
-};
-
-template <class T>
-struct AccessedType {
-  using type = T;
-};
-
-template <class T>
-using AccessedTypeT = typename AccessedType<T>::type;
-
-template <class T, std::size_t Size>
-struct AccessedType<SimpleArray<T, Size>> {
-  using type = AccessedTypeT<T>;
-};
-
-template <class T>
-constexpr T AccessSimpleArray(const T& value) {
-  return value;
-}
-
-template <class T, std::size_t Size, class... SizeT>
-constexpr AccessedTypeT<T> AccessSimpleArray(const SimpleArray<T, Size>& table,
-                                             std::size_t head_index,
-                                             SizeT... tail_indices) {
-  return AccessSimpleArray(table.value[head_index], tail_indices...);
-}
-
-// Note: Intentionally is an alias.
-template <class T>
-using AlwaysZero = SizeT<0>;
-
-template <class Op, class... Vs>
-struct VisitIndicesResultImpl {
-  using type = absl::result_of_t<Op(AlwaysZero<Vs>...)>;
-};
-
-template <class Op, class... Vs>
-using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type;
-
-template <class ReturnType, class FunctionObject, class EndIndices,
-          class BoundIndices>
-struct MakeVisitationMatrix;
-
-template <class ReturnType, class FunctionObject, std::size_t... Indices>
-constexpr ReturnType call_with_indices(FunctionObject&& function) {
-  static_assert(
-      std::is_same<ReturnType, decltype(std::declval<FunctionObject>()(
-                                   SizeT<Indices>()...))>::value,
-      "Not all visitation overloads have the same return type.");
-  return std::forward<FunctionObject>(function)(SizeT<Indices>()...);
-}
-
-template <class ReturnType, class FunctionObject, std::size_t... BoundIndices>
-struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
-                            index_sequence<BoundIndices...>> {
-  using ResultType = ReturnType (*)(FunctionObject&&);
-  static constexpr ResultType Run() {
-    return &call_with_indices<ReturnType, FunctionObject,
-                              (BoundIndices - 1)...>;
-  }
-};
-
-template <typename Is, std::size_t J>
-struct AppendToIndexSequence;
-
-template <typename Is, std::size_t J>
-using AppendToIndexSequenceT = typename AppendToIndexSequence<Is, J>::type;
-
-template <std::size_t... Is, std::size_t J>
-struct AppendToIndexSequence<index_sequence<Is...>, J> {
-  using type = index_sequence<Is..., J>;
-};
-
-template <class ReturnType, class FunctionObject, class EndIndices,
-          class CurrIndices, class BoundIndices>
-struct MakeVisitationMatrixImpl;
-
-template <class ReturnType, class FunctionObject, class EndIndices,
-          std::size_t... CurrIndices, class BoundIndices>
-struct MakeVisitationMatrixImpl<ReturnType, FunctionObject, EndIndices,
-                                index_sequence<CurrIndices...>, BoundIndices> {
-  using ResultType = SimpleArray<
-      typename MakeVisitationMatrix<ReturnType, FunctionObject, EndIndices,
-                                    index_sequence<>>::ResultType,
-      sizeof...(CurrIndices)>;
-
-  static constexpr ResultType Run() {
-    return {{MakeVisitationMatrix<
-        ReturnType, FunctionObject, EndIndices,
-        AppendToIndexSequenceT<BoundIndices, CurrIndices>>::Run()...}};
-  }
-};
-
-template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex,
-          std::size_t... TailEndIndices, std::size_t... BoundIndices>
-struct MakeVisitationMatrix<ReturnType, FunctionObject,
-                            index_sequence<HeadEndIndex, TailEndIndices...>,
-                            index_sequence<BoundIndices...>>
-    : MakeVisitationMatrixImpl<ReturnType, FunctionObject,
-                               index_sequence<TailEndIndices...>,
-                               absl::make_index_sequence<HeadEndIndex>,
-                               index_sequence<BoundIndices...>> {};
-
-struct UnreachableSwitchCase {
-  template <class Op>
-  [[noreturn]] static VisitIndicesResultT<Op, std::size_t> Run(
-      Op&& /*ignored*/) {
-    ABSL_UNREACHABLE();
-  }
-};
-
-template <class Op, std::size_t I>
-struct ReachableSwitchCase {
-  static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) {
-    return absl::base_internal::invoke(std::forward<Op>(op), SizeT<I>());
-  }
-};
-
-// The number 33 is just a guess at a reasonable maximum to our switch. It is
-// not based on any analysis. The reason it is a power of 2 plus 1 instead of a
-// power of 2 is because the number was picked to correspond to a power of 2
-// amount of "normal" alternatives, plus one for the possibility of the user
-// providing "monostate" in addition to the more natural alternatives.
-ABSL_INTERNAL_INLINE_CONSTEXPR(std::size_t, MaxUnrolledVisitCases, 33);
-
-// Note: The default-definition is for unreachable cases.
-template <bool IsReachable>
-struct PickCaseImpl {
-  template <class Op, std::size_t I>
-  using Apply = UnreachableSwitchCase;
-};
-
-template <>
-struct PickCaseImpl</*IsReachable =*/true> {
-  template <class Op, std::size_t I>
-  using Apply = ReachableSwitchCase<Op, I>;
-};
-
-// Note: This form of dance with template aliases is to make sure that we
-//       instantiate a number of templates proportional to the number of variant
-//       alternatives rather than a number of templates proportional to our
-//       maximum unrolled amount of visitation cases (aliases are effectively
-//       "free" whereas other template instantiations are costly).
-template <class Op, std::size_t I, std::size_t EndIndex>
-using PickCase = typename PickCaseImpl<(I < EndIndex)>::template Apply<Op, I>;
-
-template <class ReturnType>
-[[noreturn]] ReturnType TypedThrowBadVariantAccess() {
-  absl::variant_internal::ThrowBadVariantAccess();
-}
-
-// Given N variant sizes, determine the number of cases there would need to be
-// in a single switch-statement that would cover every possibility in the
-// corresponding N-ary visit operation.
-template <std::size_t... NumAlternatives>
-struct NumCasesOfSwitch;
-
-template <std::size_t HeadNumAlternatives, std::size_t... TailNumAlternatives>
-struct NumCasesOfSwitch<HeadNumAlternatives, TailNumAlternatives...> {
-  static constexpr std::size_t value =
-      (HeadNumAlternatives + 1) *
-      NumCasesOfSwitch<TailNumAlternatives...>::value;
-};
-
-template <>
-struct NumCasesOfSwitch<> {
-  static constexpr std::size_t value = 1;
-};
-
-// A switch statement optimizes better than the table of function pointers.
-template <std::size_t EndIndex>
-struct VisitIndicesSwitch {
-  static_assert(EndIndex <= MaxUnrolledVisitCases,
-                "Maximum unrolled switch size exceeded.");
-
-  template <class Op>
-  static VisitIndicesResultT<Op, std::size_t> Run(Op&& op, std::size_t i) {
-    switch (i) {
-      case 0:
-        return PickCase<Op, 0, EndIndex>::Run(std::forward<Op>(op));
-      case 1:
-        return PickCase<Op, 1, EndIndex>::Run(std::forward<Op>(op));
-      case 2:
-        return PickCase<Op, 2, EndIndex>::Run(std::forward<Op>(op));
-      case 3:
-        return PickCase<Op, 3, EndIndex>::Run(std::forward<Op>(op));
-      case 4:
-        return PickCase<Op, 4, EndIndex>::Run(std::forward<Op>(op));
-      case 5:
-        return PickCase<Op, 5, EndIndex>::Run(std::forward<Op>(op));
-      case 6:
-        return PickCase<Op, 6, EndIndex>::Run(std::forward<Op>(op));
-      case 7:
-        return PickCase<Op, 7, EndIndex>::Run(std::forward<Op>(op));
-      case 8:
-        return PickCase<Op, 8, EndIndex>::Run(std::forward<Op>(op));
-      case 9:
-        return PickCase<Op, 9, EndIndex>::Run(std::forward<Op>(op));
-      case 10:
-        return PickCase<Op, 10, EndIndex>::Run(std::forward<Op>(op));
-      case 11:
-        return PickCase<Op, 11, EndIndex>::Run(std::forward<Op>(op));
-      case 12:
-        return PickCase<Op, 12, EndIndex>::Run(std::forward<Op>(op));
-      case 13:
-        return PickCase<Op, 13, EndIndex>::Run(std::forward<Op>(op));
-      case 14:
-        return PickCase<Op, 14, EndIndex>::Run(std::forward<Op>(op));
-      case 15:
-        return PickCase<Op, 15, EndIndex>::Run(std::forward<Op>(op));
-      case 16:
-        return PickCase<Op, 16, EndIndex>::Run(std::forward<Op>(op));
-      case 17:
-        return PickCase<Op, 17, EndIndex>::Run(std::forward<Op>(op));
-      case 18:
-        return PickCase<Op, 18, EndIndex>::Run(std::forward<Op>(op));
-      case 19:
-        return PickCase<Op, 19, EndIndex>::Run(std::forward<Op>(op));
-      case 20:
-        return PickCase<Op, 20, EndIndex>::Run(std::forward<Op>(op));
-      case 21:
-        return PickCase<Op, 21, EndIndex>::Run(std::forward<Op>(op));
-      case 22:
-        return PickCase<Op, 22, EndIndex>::Run(std::forward<Op>(op));
-      case 23:
-        return PickCase<Op, 23, EndIndex>::Run(std::forward<Op>(op));
-      case 24:
-        return PickCase<Op, 24, EndIndex>::Run(std::forward<Op>(op));
-      case 25:
-        return PickCase<Op, 25, EndIndex>::Run(std::forward<Op>(op));
-      case 26:
-        return PickCase<Op, 26, EndIndex>::Run(std::forward<Op>(op));
-      case 27:
-        return PickCase<Op, 27, EndIndex>::Run(std::forward<Op>(op));
-      case 28:
-        return PickCase<Op, 28, EndIndex>::Run(std::forward<Op>(op));
-      case 29:
-        return PickCase<Op, 29, EndIndex>::Run(std::forward<Op>(op));
-      case 30:
-        return PickCase<Op, 30, EndIndex>::Run(std::forward<Op>(op));
-      case 31:
-        return PickCase<Op, 31, EndIndex>::Run(std::forward<Op>(op));
-      case 32:
-        return PickCase<Op, 32, EndIndex>::Run(std::forward<Op>(op));
-      default:
-        ABSL_ASSERT(i == variant_npos);
-        return absl::base_internal::invoke(std::forward<Op>(op), NPos());
-    }
-  }
-};
-
-template <std::size_t... EndIndices>
-struct VisitIndicesFallback {
-  template <class Op, class... SizeT>
-  static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) {
-    return AccessSimpleArray(
-        MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op,
-                             index_sequence<(EndIndices + 1)...>,
-                             index_sequence<>>::Run(),
-        (indices + 1)...)(std::forward<Op>(op));
-  }
-};
-
-// Take an N-dimensional series of indices and convert them into a single index
-// without loss of information. The purpose of this is to be able to convert an
-// N-ary visit operation into a single switch statement.
-template <std::size_t...>
-struct FlattenIndices;
-
-template <std::size_t HeadSize, std::size_t... TailSize>
-struct FlattenIndices<HeadSize, TailSize...> {
-  template <class... SizeType>
-  static constexpr std::size_t Run(std::size_t head, SizeType... tail) {
-    return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...);
-  }
-};
-
-template <>
-struct FlattenIndices<> {
-  static constexpr std::size_t Run() { return 0; }
-};
-
-// Take a single "flattened" index (flattened by FlattenIndices) and determine
-// the value of the index of one of the logically represented dimensions.
-template <std::size_t I, std::size_t IndexToGet, std::size_t HeadSize,
-          std::size_t... TailSize>
-struct UnflattenIndex {
-  static constexpr std::size_t value =
-      UnflattenIndex<I / HeadSize, IndexToGet - 1, TailSize...>::value;
-};
-
-template <std::size_t I, std::size_t HeadSize, std::size_t... TailSize>
-struct UnflattenIndex<I, 0, HeadSize, TailSize...> {
-  static constexpr std::size_t value = (I % HeadSize);
-};
-
-// The backend for converting an N-ary visit operation into a unary visit.
-template <class IndexSequence, std::size_t... EndIndices>
-struct VisitIndicesVariadicImpl;
-
-template <std::size_t... N, std::size_t... EndIndices>
-struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> {
-  // A type that can take an N-ary function object and converts it to a unary
-  // function object that takes a single, flattened index, and "unflattens" it
-  // into its individual dimensions when forwarding to the wrapped object.
-  template <class Op>
-  struct FlattenedOp {
-    template <std::size_t I>
-    VisitIndicesResultT<Op, decltype(EndIndices)...> operator()(
-        SizeT<I> /*index*/) && {
-      return base_internal::invoke(
-          std::forward<Op>(op),
-          SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value -
-                std::size_t{1}>()...);
-    }
-
-    Op&& op;
-  };
-
-  template <class Op, class... SizeType>
-  static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(Op&& op,
-                                                              SizeType... i) {
-    return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run(
-        FlattenedOp<Op>{std::forward<Op>(op)},
-        FlattenIndices<(EndIndices + std::size_t{1})...>::Run(
-            (i + std::size_t{1})...));
-  }
-};
-
-template <std::size_t... EndIndices>
-struct VisitIndicesVariadic
-    : VisitIndicesVariadicImpl<absl::make_index_sequence<sizeof...(EndIndices)>,
-                               EndIndices...> {};
-
-// This implementation will flatten N-ary visit operations into a single switch
-// statement when the number of cases would be less than our maximum specified
-// switch-statement size.
-// TODO(calabrese)
-//   Based on benchmarks, determine whether the function table approach actually
-//   does optimize better than a chain of switch statements and possibly update
-//   the implementation accordingly. Also consider increasing the maximum switch
-//   size.
-template <std::size_t... EndIndices>
-struct VisitIndices
-    : absl::conditional_t<(NumCasesOfSwitch<EndIndices...>::value <=
-                           MaxUnrolledVisitCases),
-                          VisitIndicesVariadic<EndIndices...>,
-                          VisitIndicesFallback<EndIndices...>> {};
-
-template <std::size_t EndIndex>
-struct VisitIndices<EndIndex>
-    : absl::conditional_t<(EndIndex <= MaxUnrolledVisitCases),
-                          VisitIndicesSwitch<EndIndex>,
-                          VisitIndicesFallback<EndIndex>> {};
-
-// Suppress bogus warning on MSVC: MSVC complains that the `reinterpret_cast`
-// below is returning the address of a temporary or local object.
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4172)
-#endif  // _MSC_VER
-
-// TODO(calabrese) std::launder
-// TODO(calabrese) constexpr
-// NOTE: DO NOT REMOVE the `inline` keyword as it is necessary to work around a
-// MSVC bug. See https://github.com/abseil/abseil-cpp/issues/129 for details.
-template <class Self, std::size_t I>
-inline VariantAccessResult<I, Self> AccessUnion(Self&& self, SizeT<I> /*i*/) {
-  return reinterpret_cast<VariantAccessResult<I, Self>>(self);
-}
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif  // _MSC_VER
-
-template <class T>
-void DeducedDestroy(T& self) {  // NOLINT
-  self.~T();
-}
-
-// NOTE: This type exists as a single entity for variant and its bases to
-// befriend. It contains helper functionality that manipulates the state of the
-// variant, such as the implementation of things like assignment and emplace
-// operations.
-struct VariantCoreAccess {
-  template <class VariantType>
-  static typename VariantType::Variant& Derived(VariantType& self) {  // NOLINT
-    return static_cast<typename VariantType::Variant&>(self);
-  }
-
-  template <class VariantType>
-  static const typename VariantType::Variant& Derived(
-      const VariantType& self) {  // NOLINT
-    return static_cast<const typename VariantType::Variant&>(self);
-  }
-
-  template <class VariantType>
-  static void Destroy(VariantType& self) {  // NOLINT
-    Derived(self).destroy();
-    self.index_ = absl::variant_npos;
-  }
-
-  template <class Variant>
-  static void SetIndex(Variant& self, std::size_t i) {  // NOLINT
-    self.index_ = i;
-  }
-
-  template <class Variant>
-  static void InitFrom(Variant& self, Variant&& other) {  // NOLINT
-    VisitIndices<absl::variant_size<Variant>::value>::Run(
-        InitFromVisitor<Variant, Variant&&>{&self,
-                                            std::forward<Variant>(other)},
-        other.index());
-    self.index_ = other.index();
-  }
-
-  // Access a variant alternative, assuming the index is correct.
-  template <std::size_t I, class Variant>
-  static VariantAccessResult<I, Variant> Access(Variant&& self) {
-    // This cast instead of invocation of AccessUnion with an rvalue is a
-    // workaround for msvc. Without this there is a runtime failure when dealing
-    // with rvalues.
-    // TODO(calabrese) Reduce test case and find a simpler workaround.
-    return static_cast<VariantAccessResult<I, Variant>>(
-        variant_internal::AccessUnion(self.state_, SizeT<I>()));
-  }
-
-  // Access a variant alternative, throwing if the index is incorrect.
-  template <std::size_t I, class Variant>
-  static VariantAccessResult<I, Variant> CheckedAccess(Variant&& self) {
-    if (ABSL_PREDICT_FALSE(self.index_ != I)) {
-      TypedThrowBadVariantAccess<VariantAccessResult<I, Variant>>();
-    }
-
-    return Access<I>(std::forward<Variant>(self));
-  }
-
-  // The implementation of the move-assignment operation for a variant.
-  template <class VType>
-  struct MoveAssignVisitor {
-    using DerivedType = typename VType::Variant;
-    template <std::size_t NewIndex>
-    void operator()(SizeT<NewIndex> /*new_i*/) const {
-      if (left->index_ == NewIndex) {
-        Access<NewIndex>(*left) = std::move(Access<NewIndex>(*right));
-      } else {
-        Derived(*left).template emplace<NewIndex>(
-            std::move(Access<NewIndex>(*right)));
-      }
-    }
-
-    void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
-      Destroy(*left);
-    }
-
-    VType* left;
-    VType* right;
-  };
-
-  template <class VType>
-  static MoveAssignVisitor<VType> MakeMoveAssignVisitor(VType* left,
-                                                        VType* other) {
-    return {left, other};
-  }
-
-  // The implementation of the assignment operation for a variant.
-  template <class VType>
-  struct CopyAssignVisitor {
-    using DerivedType = typename VType::Variant;
-    template <std::size_t NewIndex>
-    void operator()(SizeT<NewIndex> /*new_i*/) const {
-      using New =
-          typename absl::variant_alternative<NewIndex, DerivedType>::type;
-
-      if (left->index_ == NewIndex) {
-        Access<NewIndex>(*left) = Access<NewIndex>(*right);
-      } else if (std::is_nothrow_copy_constructible<New>::value ||
-                 !std::is_nothrow_move_constructible<New>::value) {
-        Derived(*left).template emplace<NewIndex>(Access<NewIndex>(*right));
-      } else {
-        Derived(*left) = DerivedType(Derived(*right));
-      }
-    }
-
-    void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
-      Destroy(*left);
-    }
-
-    VType* left;
-    const VType* right;
-  };
-
-  template <class VType>
-  static CopyAssignVisitor<VType> MakeCopyAssignVisitor(VType* left,
-                                                        const VType& other) {
-    return {left, &other};
-  }
-
-  // The implementation of conversion-assignment operations for variant.
-  template <class Left, class QualifiedNew>
-  struct ConversionAssignVisitor {
-    using NewIndex =
-        variant_internal::IndexOfConstructedType<Left, QualifiedNew>;
-
-    void operator()(SizeT<NewIndex::value> /*old_i*/
-    ) const {
-      Access<NewIndex::value>(*left) = std::forward<QualifiedNew>(other);
-    }
-
-    template <std::size_t OldIndex>
-    void operator()(SizeT<OldIndex> /*old_i*/
-    ) const {
-      using New =
-          typename absl::variant_alternative<NewIndex::value, Left>::type;
-      if (std::is_nothrow_constructible<New, QualifiedNew>::value ||
-          !std::is_nothrow_move_constructible<New>::value) {
-        left->template emplace<NewIndex::value>(
-            std::forward<QualifiedNew>(other));
-      } else {
-        // the standard says "equivalent to
-        // operator=(variant(std::forward<T>(t)))", but we use `emplace` here
-        // because the variant's move assignment operator could be deleted.
-        left->template emplace<NewIndex::value>(
-            New(std::forward<QualifiedNew>(other)));
-      }
-    }
-
-    Left* left;
-    QualifiedNew&& other;
-  };
-
-  template <class Left, class QualifiedNew>
-  static ConversionAssignVisitor<Left, QualifiedNew>
-  MakeConversionAssignVisitor(Left* left, QualifiedNew&& qual) {
-    return {left, std::forward<QualifiedNew>(qual)};
-  }
-
-  // Backend for operations for `emplace()` which destructs `*self` then
-  // construct a new alternative with `Args...`.
-  template <std::size_t NewIndex, class Self, class... Args>
-  static typename absl::variant_alternative<NewIndex, Self>::type& Replace(
-      Self* self, Args&&... args) {
-    Destroy(*self);
-    using New = typename absl::variant_alternative<NewIndex, Self>::type;
-    New* const result = ::new (static_cast<void*>(&self->state_))
-        New(std::forward<Args>(args)...);
-    self->index_ = NewIndex;
-    return *result;
-  }
-
-  template <class LeftVariant, class QualifiedRightVariant>
-  struct InitFromVisitor {
-    template <std::size_t NewIndex>
-    void operator()(SizeT<NewIndex> /*new_i*/) const {
-      using Alternative =
-          typename variant_alternative<NewIndex, LeftVariant>::type;
-      ::new (static_cast<void*>(&left->state_)) Alternative(
-          Access<NewIndex>(std::forward<QualifiedRightVariant>(right)));
-    }
-
-    void operator()(SizeT<absl::variant_npos> /*new_i*/) const {
-      // This space intentionally left blank.
-    }
-    LeftVariant* left;
-    QualifiedRightVariant&& right;
-  };
-};
-
-template <class Expected, class... T>
-struct IndexOfImpl;
-
-template <class Expected>
-struct IndexOfImpl<Expected> {
-  using IndexFromEnd = SizeT<0>;
-  using MatchedIndexFromEnd = IndexFromEnd;
-  using MultipleMatches = std::false_type;
-};
-
-template <class Expected, class Head, class... Tail>
-struct IndexOfImpl<Expected, Head, Tail...> : IndexOfImpl<Expected, Tail...> {
-  using IndexFromEnd =
-      SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
-};
-
-template <class Expected, class... Tail>
-struct IndexOfImpl<Expected, Expected, Tail...>
-    : IndexOfImpl<Expected, Tail...> {
-  using IndexFromEnd =
-      SizeT<IndexOfImpl<Expected, Tail...>::IndexFromEnd::value + 1>;
-  using MatchedIndexFromEnd = IndexFromEnd;
-  using MultipleMatches = std::integral_constant<
-      bool, IndexOfImpl<Expected, Tail...>::MatchedIndexFromEnd::value != 0>;
-};
-
-template <class Expected, class... Types>
-struct IndexOfMeta {
-  using Results = IndexOfImpl<Expected, Types...>;
-  static_assert(!Results::MultipleMatches::value,
-                "Attempted to access a variant by specifying a type that "
-                "matches more than one alternative.");
-  static_assert(Results::MatchedIndexFromEnd::value != 0,
-                "Attempted to access a variant by specifying a type that does "
-                "not match any alternative.");
-  using type = SizeT<sizeof...(Types) - Results::MatchedIndexFromEnd::value>;
-};
-
-template <class Expected, class... Types>
-using IndexOf = typename IndexOfMeta<Expected, Types...>::type;
-
-template <class Variant, class T, std::size_t CurrIndex>
-struct UnambiguousIndexOfImpl;
-
-// Terminating case encountered once we've checked all of the alternatives
-template <class T, std::size_t CurrIndex>
-struct UnambiguousIndexOfImpl<variant<>, T, CurrIndex> : SizeT<CurrIndex> {};
-
-// Case where T is not Head
-template <class Head, class... Tail, class T, std::size_t CurrIndex>
-struct UnambiguousIndexOfImpl<variant<Head, Tail...>, T, CurrIndex>
-    : UnambiguousIndexOfImpl<variant<Tail...>, T, CurrIndex + 1>::type {};
-
-// Case where T is Head
-template <class Head, class... Tail, std::size_t CurrIndex>
-struct UnambiguousIndexOfImpl<variant<Head, Tail...>, Head, CurrIndex>
-    : SizeT<UnambiguousIndexOfImpl<variant<Tail...>, Head, 0>::value ==
-                    sizeof...(Tail)
-                ? CurrIndex
-                : CurrIndex + sizeof...(Tail) + 1> {};
-
-template <class Variant, class T>
-struct UnambiguousIndexOf;
-
-struct NoMatch {
-  struct type {};
-};
-
-template <class... Alts, class T>
-struct UnambiguousIndexOf<variant<Alts...>, T>
-    : std::conditional<UnambiguousIndexOfImpl<variant<Alts...>, T, 0>::value !=
-                           sizeof...(Alts),
-                       UnambiguousIndexOfImpl<variant<Alts...>, T, 0>,
-                       NoMatch>::type::type {};
-
-template <class T, std::size_t /*Dummy*/>
-using UnambiguousTypeOfImpl = T;
-
-template <class Variant, class T>
-using UnambiguousTypeOfT =
-    UnambiguousTypeOfImpl<T, UnambiguousIndexOf<Variant, T>::value>;
-
-template <class H, class... T>
-class VariantStateBase;
-
-// This is an implementation of the "imaginary function" that is described in
-// [variant.ctor]
-// It is used in order to determine which alternative to construct during
-// initialization from some type T.
-template <class Variant, std::size_t I = 0>
-struct ImaginaryFun;
-
-template <std::size_t I>
-struct ImaginaryFun<variant<>, I> {
-  static void Run() = delete;
-};
-
-template <class H, class... T, std::size_t I>
-struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> {
-  using ImaginaryFun<variant<T...>, I + 1>::Run;
-
-  // NOTE: const& and && are used instead of by-value due to lack of guaranteed
-  // move elision of C++17. This may have other minor differences, but tests
-  // pass.
-  static SizeT<I> Run(const H&, SizeT<I>);
-  static SizeT<I> Run(H&&, SizeT<I>);
-};
-
-// The following metafunctions are used in constructor and assignment
-// constraints.
-template <class Self, class T>
-struct IsNeitherSelfNorInPlace : std::true_type {};
-
-template <class Self>
-struct IsNeitherSelfNorInPlace<Self, Self> : std::false_type {};
-
-template <class Self, class T>
-struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {};
-
-template <class Self, std::size_t I>
-struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {};
-
-template <class Variant, class T>
-struct IndexOfConstructedType<
-    Variant, T,
-    void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
-    : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {};
-
-template <std::size_t... Is>
-struct ContainsVariantNPos
-    : absl::negation<std::is_same<  // NOLINT
-          std::integer_sequence<bool, 0 <= Is...>,
-          std::integer_sequence<bool, Is != absl::variant_npos...>>> {};
-
-template <class Op, class... QualifiedVariants>
-using RawVisitResult =
-    absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
-
-// NOTE: The spec requires that all return-paths yield the same type and is not
-// SFINAE-friendly, so we can deduce the return type by examining the first
-// result. If it's not callable, then we get an error, but are compliant and
-// fast to compile.
-// TODO(calabrese) Possibly rewrite in a way that yields better compile errors
-// at the cost of longer compile-times.
-template <class Op, class... QualifiedVariants>
-struct VisitResultImpl {
-  using type =
-      absl::result_of_t<Op(VariantAccessResult<0, QualifiedVariants>...)>;
-};
-
-// Done in two steps intentionally so that we don't cause substitution to fail.
-template <class Op, class... QualifiedVariants>
-using VisitResult = typename VisitResultImpl<Op, QualifiedVariants...>::type;
-
-template <class Op, class... QualifiedVariants>
-struct PerformVisitation {
-  using ReturnType = VisitResult<Op, QualifiedVariants...>;
-
-  template <std::size_t... Is>
-  constexpr ReturnType operator()(SizeT<Is>... indices) const {
-    return Run(typename ContainsVariantNPos<Is...>::type{},
-               absl::index_sequence_for<QualifiedVariants...>(), indices...);
-  }
-
-  template <std::size_t... TupIs, std::size_t... Is>
-  constexpr ReturnType Run(std::false_type /*has_valueless*/,
-                           index_sequence<TupIs...>, SizeT<Is>...) const {
-    static_assert(
-        std::is_same<ReturnType,
-                     absl::result_of_t<Op(VariantAccessResult<
-                                          Is, QualifiedVariants>...)>>::value,
-        "All visitation overloads must have the same return type.");
-    return absl::base_internal::invoke(
-        std::forward<Op>(op),
-        VariantCoreAccess::Access<Is>(
-            std::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...);
-  }
-
-  template <std::size_t... TupIs, std::size_t... Is>
-  [[noreturn]] ReturnType Run(std::true_type /*has_valueless*/,
-                              index_sequence<TupIs...>, SizeT<Is>...) const {
-    absl::variant_internal::ThrowBadVariantAccess();
-  }
-
-  // TODO(calabrese) Avoid using a tuple, which causes lots of instantiations
-  // Attempts using lambda variadic captures fail on current GCC.
-  std::tuple<QualifiedVariants&&...> variant_tup;
-  Op&& op;
-};
-
-template <class... T>
-union Union;
-
-// We want to allow for variant<> to be trivial. For that, we need the default
-// constructor to be trivial, which means we can't define it ourselves.
-// Instead, we use a non-default constructor that takes NoopConstructorTag
-// that doesn't affect the triviality of the types.
-struct NoopConstructorTag {};
-
-template <std::size_t I>
-struct EmplaceTag {};
-
-template <>
-union Union<> {
-  constexpr explicit Union(NoopConstructorTag) noexcept {}
-};
-
-// Suppress bogus warning on MSVC: MSVC complains that Union<T...> has a defined
-// deleted destructor from the `std::is_destructible` check below.
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4624)
-#endif  // _MSC_VER
-
-template <class Head, class... Tail>
-union Union<Head, Tail...> {
-  using TailUnion = Union<Tail...>;
-
-  explicit constexpr Union(NoopConstructorTag /*tag*/) noexcept
-      : tail(NoopConstructorTag()) {}
-
-  template <class... P>
-  explicit constexpr Union(EmplaceTag<0>, P&&... args)
-      : head(std::forward<P>(args)...) {}
-
-  template <std::size_t I, class... P>
-  explicit constexpr Union(EmplaceTag<I>, P&&... args)
-      : tail(EmplaceTag<I - 1>{}, std::forward<P>(args)...) {}
-
-  Head head;
-  TailUnion tail;
-};
-
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif  // _MSC_VER
-
-// TODO(calabrese) Just contain a Union in this union (certain configs fail).
-template <class... T>
-union DestructibleUnionImpl;
-
-template <>
-union DestructibleUnionImpl<> {
-  constexpr explicit DestructibleUnionImpl(NoopConstructorTag) noexcept {}
-};
-
-template <class Head, class... Tail>
-union DestructibleUnionImpl<Head, Tail...> {
-  using TailUnion = DestructibleUnionImpl<Tail...>;
-
-  explicit constexpr DestructibleUnionImpl(NoopConstructorTag /*tag*/) noexcept
-      : tail(NoopConstructorTag()) {}
-
-  template <class... P>
-  explicit constexpr DestructibleUnionImpl(EmplaceTag<0>, P&&... args)
-      : head(std::forward<P>(args)...) {}
-
-  template <std::size_t I, class... P>
-  explicit constexpr DestructibleUnionImpl(EmplaceTag<I>, P&&... args)
-      : tail(EmplaceTag<I - 1>{}, std::forward<P>(args)...) {}
-
-  ~DestructibleUnionImpl() {}
-
-  Head head;
-  TailUnion tail;
-};
-
-// This union type is destructible even if one or more T are not trivially
-// destructible. In the case that all T are trivially destructible, then so is
-// this resultant type.
-template <class... T>
-using DestructibleUnion =
-    absl::conditional_t<std::is_destructible<Union<T...>>::value, Union<T...>,
-                        DestructibleUnionImpl<T...>>;
-
-// Deepest base, containing the actual union and the discriminator
-template <class H, class... T>
-class VariantStateBase {
- protected:
-  using Variant = variant<H, T...>;
-
-  template <class LazyH = H,
-            class ConstructibleH = absl::enable_if_t<
-                std::is_default_constructible<LazyH>::value, LazyH>>
-  constexpr VariantStateBase() noexcept(
-      std::is_nothrow_default_constructible<ConstructibleH>::value)
-      : state_(EmplaceTag<0>()), index_(0) {}
-
-  template <std::size_t I, class... P>
-  explicit constexpr VariantStateBase(EmplaceTag<I> tag, P&&... args)
-      : state_(tag, std::forward<P>(args)...), index_(I) {}
-
-  explicit constexpr VariantStateBase(NoopConstructorTag)
-      : state_(NoopConstructorTag()), index_(variant_npos) {}
-
-  void destroy() {}  // Does nothing (shadowed in child if non-trivial)
-
-  DestructibleUnion<H, T...> state_;
-  std::size_t index_;
-};
-
-using absl::internal::type_identity;
-
-// OverloadSet::Overload() is a unary function which is overloaded to
-// take any of the element types of the variant, by reference-to-const.
-// The return type of the overload on T is type_identity<T>, so that you
-// can statically determine which overload was called.
-//
-// Overload() is not defined, so it can only be called in unevaluated
-// contexts.
-template <typename... Ts>
-struct OverloadSet;
-
-template <typename T, typename... Ts>
-struct OverloadSet<T, Ts...> : OverloadSet<Ts...> {
-  using Base = OverloadSet<Ts...>;
-  static type_identity<T> Overload(const T&);
-  using Base::Overload;
-};
-
-template <>
-struct OverloadSet<> {
-  // For any case not handled above.
-  static void Overload(...);
-};
-
-template <class T>
-using LessThanResult = decltype(std::declval<T>() < std::declval<T>());
-
-template <class T>
-using GreaterThanResult = decltype(std::declval<T>() > std::declval<T>());
-
-template <class T>
-using LessThanOrEqualResult = decltype(std::declval<T>() <= std::declval<T>());
-
-template <class T>
-using GreaterThanOrEqualResult =
-    decltype(std::declval<T>() >= std::declval<T>());
-
-template <class T>
-using EqualResult = decltype(std::declval<T>() == std::declval<T>());
-
-template <class T>
-using NotEqualResult = decltype(std::declval<T>() != std::declval<T>());
-
-using type_traits_internal::is_detected_convertible;
-
-template <class... T>
-using RequireAllHaveEqualT = absl::enable_if_t<
-    absl::conjunction<is_detected_convertible<bool, EqualResult, T>...>::value,
-    bool>;
-
-template <class... T>
-using RequireAllHaveNotEqualT =
-    absl::enable_if_t<absl::conjunction<is_detected_convertible<
-                          bool, NotEqualResult, T>...>::value,
-                      bool>;
-
-template <class... T>
-using RequireAllHaveLessThanT =
-    absl::enable_if_t<absl::conjunction<is_detected_convertible<
-                          bool, LessThanResult, T>...>::value,
-                      bool>;
-
-template <class... T>
-using RequireAllHaveLessThanOrEqualT =
-    absl::enable_if_t<absl::conjunction<is_detected_convertible<
-                          bool, LessThanOrEqualResult, T>...>::value,
-                      bool>;
-
-template <class... T>
-using RequireAllHaveGreaterThanOrEqualT =
-    absl::enable_if_t<absl::conjunction<is_detected_convertible<
-                          bool, GreaterThanOrEqualResult, T>...>::value,
-                      bool>;
-
-template <class... T>
-using RequireAllHaveGreaterThanT =
-    absl::enable_if_t<absl::conjunction<is_detected_convertible<
-                          bool, GreaterThanResult, T>...>::value,
-                      bool>;
-
-// Helper template containing implementations details of variant that can't go
-// in the private section. For convenience, this takes the variant type as a
-// single template parameter.
-template <typename T>
-struct VariantHelper;
-
-template <typename... Ts>
-struct VariantHelper<variant<Ts...>> {
-  // Type metafunction which returns the element type selected if
-  // OverloadSet::Overload() is well-formed when called with argument type U.
-  template <typename U>
-  using BestMatch = decltype(variant_internal::OverloadSet<Ts...>::Overload(
-      std::declval<U>()));
-
-  // Type metafunction which returns true if OverloadSet::Overload() is
-  // well-formed when called with argument type U.
-  // CanAccept can't be just an alias because there is a MSVC bug on parameter
-  // pack expansion involving decltype.
-  template <typename U>
-  struct CanAccept
-      : std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
-
-  // Type metafunction which returns true if Other is an instantiation of
-  // variant, and variants's converting constructor from Other will be
-  // well-formed. We will use this to remove constructors that would be
-  // ill-formed from the overload set.
-  template <typename Other>
-  struct CanConvertFrom;
-
-  template <typename... Us>
-  struct CanConvertFrom<variant<Us...>>
-      : public absl::conjunction<CanAccept<Us>...> {};
-};
-
-// A type with nontrivial copy ctor and trivial move ctor.
-struct TrivialMoveOnly {
-  TrivialMoveOnly(TrivialMoveOnly&&) = default;
-};
-
-// Trait class to detect whether a type is trivially move constructible.
-// A union's defaulted copy/move constructor is deleted if any variant member's
-// copy/move constructor is nontrivial.
-template <typename T>
-struct IsTriviallyMoveConstructible
-    : std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
-
-// To guarantee triviality of all special-member functions that can be trivial,
-// we use a chain of conditional bases for each one.
-// The order of inheritance of bases from child to base are logically:
-//
-// variant
-// VariantCopyAssignBase
-// VariantMoveAssignBase
-// VariantCopyBase
-// VariantMoveBase
-// VariantStateBaseDestructor
-// VariantStateBase
-//
-// Note that there is a separate branch at each base that is dependent on
-// whether or not that corresponding special-member-function can be trivial in
-// the resultant variant type.
-
-template <class... T>
-class VariantStateBaseDestructorNontrivial;
-
-template <class... T>
-class VariantMoveBaseNontrivial;
-
-template <class... T>
-class VariantCopyBaseNontrivial;
-
-template <class... T>
-class VariantMoveAssignBaseNontrivial;
-
-template <class... T>
-class VariantCopyAssignBaseNontrivial;
-
-// Base that is dependent on whether or not the destructor can be trivial.
-template <class... T>
-using VariantStateBaseDestructor =
-    absl::conditional_t<std::is_destructible<Union<T...>>::value,
-                        VariantStateBase<T...>,
-                        VariantStateBaseDestructorNontrivial<T...>>;
-
-// Base that is dependent on whether or not the move-constructor can be
-// implicitly generated by the compiler (trivial or deleted).
-// Previously we were using `std::is_move_constructible<Union<T...>>` to check
-// whether all Ts have trivial move constructor, but it ran into a GCC bug:
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84866
-// So we have to use a different approach (i.e. `HasTrivialMoveConstructor`) to
-// work around the bug.
-template <class... T>
-using VariantMoveBase = absl::conditional_t<
-    absl::disjunction<
-        absl::negation<absl::conjunction<std::is_move_constructible<T>...>>,
-        absl::conjunction<IsTriviallyMoveConstructible<T>...>>::value,
-    VariantStateBaseDestructor<T...>, VariantMoveBaseNontrivial<T...>>;
-
-// Base that is dependent on whether or not the copy-constructor can be trivial.
-template <class... T>
-using VariantCopyBase = absl::conditional_t<
-    absl::disjunction<
-        absl::negation<absl::conjunction<std::is_copy_constructible<T>...>>,
-        std::is_copy_constructible<Union<T...>>>::value,
-    VariantMoveBase<T...>, VariantCopyBaseNontrivial<T...>>;
-
-// Base that is dependent on whether or not the move-assign can be trivial.
-template <class... T>
-using VariantMoveAssignBase = absl::conditional_t<
-    absl::disjunction<
-        absl::conjunction<absl::is_move_assignable<Union<T...>>,
-                          std::is_move_constructible<Union<T...>>,
-                          std::is_destructible<Union<T...>>>,
-        absl::negation<absl::conjunction<std::is_move_constructible<T>...,
-                                         // Note: We're not qualifying this with
-                                         // absl:: because it doesn't compile
-                                         // under MSVC.
-                                         is_move_assignable<T>...>>>::value,
-    VariantCopyBase<T...>, VariantMoveAssignBaseNontrivial<T...>>;
-
-// Base that is dependent on whether or not the copy-assign can be trivial.
-template <class... T>
-using VariantCopyAssignBase = absl::conditional_t<
-    absl::disjunction<
-        absl::conjunction<absl::is_copy_assignable<Union<T...>>,
-                          std::is_copy_constructible<Union<T...>>,
-                          std::is_destructible<Union<T...>>>,
-        absl::negation<absl::conjunction<std::is_copy_constructible<T>...,
-                                         // Note: We're not qualifying this with
-                                         // absl:: because it doesn't compile
-                                         // under MSVC.
-                                         is_copy_assignable<T>...>>>::value,
-    VariantMoveAssignBase<T...>, VariantCopyAssignBaseNontrivial<T...>>;
-
-template <class... T>
-using VariantBase = VariantCopyAssignBase<T...>;
-
-template <class... T>
-class VariantStateBaseDestructorNontrivial : protected VariantStateBase<T...> {
- private:
-  using Base = VariantStateBase<T...>;
-
- protected:
-  using Base::Base;
-
-  VariantStateBaseDestructorNontrivial() = default;
-  VariantStateBaseDestructorNontrivial(VariantStateBaseDestructorNontrivial&&) =
-      default;
-  VariantStateBaseDestructorNontrivial(
-      const VariantStateBaseDestructorNontrivial&) = default;
-  VariantStateBaseDestructorNontrivial& operator=(
-      VariantStateBaseDestructorNontrivial&&) = default;
-  VariantStateBaseDestructorNontrivial& operator=(
-      const VariantStateBaseDestructorNontrivial&) = default;
-
-  struct Destroyer {
-    template <std::size_t I>
-    void operator()(SizeT<I> i) const {
-      using Alternative =
-          typename absl::variant_alternative<I, variant<T...>>::type;
-      variant_internal::AccessUnion(self->state_, i).~Alternative();
-    }
-
-    void operator()(SizeT<absl::variant_npos> /*i*/) const {
-      // This space intentionally left blank
-    }
-
-    VariantStateBaseDestructorNontrivial* self;
-  };
-
-  void destroy() { VisitIndices<sizeof...(T)>::Run(Destroyer{this}, index_); }
-
-  ~VariantStateBaseDestructorNontrivial() { destroy(); }
-
- protected:
-  using Base::index_;
-  using Base::state_;
-};
-
-template <class... T>
-class VariantMoveBaseNontrivial : protected VariantStateBaseDestructor<T...> {
- private:
-  using Base = VariantStateBaseDestructor<T...>;
-
- protected:
-  using Base::Base;
-
-  struct Construct {
-    template <std::size_t I>
-    void operator()(SizeT<I> i) const {
-      using Alternative =
-          typename absl::variant_alternative<I, variant<T...>>::type;
-      ::new (static_cast<void*>(&self->state_)) Alternative(
-          variant_internal::AccessUnion(std::move(other->state_), i));
-    }
-
-    void operator()(SizeT<absl::variant_npos> /*i*/) const {}
-
-    VariantMoveBaseNontrivial* self;
-    VariantMoveBaseNontrivial* other;
-  };
-
-  VariantMoveBaseNontrivial() = default;
-  VariantMoveBaseNontrivial(VariantMoveBaseNontrivial&& other) noexcept(
-      absl::conjunction<std::is_nothrow_move_constructible<T>...>::value)
-      : Base(NoopConstructorTag()) {
-    VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
-    index_ = other.index_;
-  }
-
-  VariantMoveBaseNontrivial(VariantMoveBaseNontrivial const&) = default;
-
-  VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial&&) = default;
-  VariantMoveBaseNontrivial& operator=(VariantMoveBaseNontrivial const&) =
-      default;
-
- protected:
-  using Base::index_;
-  using Base::state_;
-};
-
-template <class... T>
-class VariantCopyBaseNontrivial : protected VariantMoveBase<T...> {
- private:
-  using Base = VariantMoveBase<T...>;
-
- protected:
-  using Base::Base;
-
-  VariantCopyBaseNontrivial() = default;
-  VariantCopyBaseNontrivial(VariantCopyBaseNontrivial&&) = default;
-
-  struct Construct {
-    template <std::size_t I>
-    void operator()(SizeT<I> i) const {
-      using Alternative =
-          typename absl::variant_alternative<I, variant<T...>>::type;
-      ::new (static_cast<void*>(&self->state_))
-          Alternative(variant_internal::AccessUnion(other->state_, i));
-    }
-
-    void operator()(SizeT<absl::variant_npos> /*i*/) const {}
-
-    VariantCopyBaseNontrivial* self;
-    const VariantCopyBaseNontrivial* other;
-  };
-
-  VariantCopyBaseNontrivial(VariantCopyBaseNontrivial const& other)
-      : Base(NoopConstructorTag()) {
-    VisitIndices<sizeof...(T)>::Run(Construct{this, &other}, other.index_);
-    index_ = other.index_;
-  }
-
-  VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial&&) = default;
-  VariantCopyBaseNontrivial& operator=(VariantCopyBaseNontrivial const&) =
-      default;
-
- protected:
-  using Base::index_;
-  using Base::state_;
-};
-
-template <class... T>
-class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> {
-  friend struct VariantCoreAccess;
-
- private:
-  using Base = VariantCopyBase<T...>;
-
- protected:
-  using Base::Base;
-
-  VariantMoveAssignBaseNontrivial() = default;
-  VariantMoveAssignBaseNontrivial(VariantMoveAssignBaseNontrivial&&) = default;
-  VariantMoveAssignBaseNontrivial(const VariantMoveAssignBaseNontrivial&) =
-      default;
-  VariantMoveAssignBaseNontrivial& operator=(
-      VariantMoveAssignBaseNontrivial const&) = default;
-
-  VariantMoveAssignBaseNontrivial&
-  operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
-      absl::conjunction<std::is_nothrow_move_constructible<T>...,
-                        std::is_nothrow_move_assignable<T>...>::value) {
-    VisitIndices<sizeof...(T)>::Run(
-        VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
-    return *this;
-  }
-
- protected:
-  using Base::index_;
-  using Base::state_;
-};
-
-template <class... T>
-class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> {
-  friend struct VariantCoreAccess;
-
- private:
-  using Base = VariantMoveAssignBase<T...>;
-
- protected:
-  using Base::Base;
-
-  VariantCopyAssignBaseNontrivial() = default;
-  VariantCopyAssignBaseNontrivial(VariantCopyAssignBaseNontrivial&&) = default;
-  VariantCopyAssignBaseNontrivial(const VariantCopyAssignBaseNontrivial&) =
-      default;
-  VariantCopyAssignBaseNontrivial& operator=(
-      VariantCopyAssignBaseNontrivial&&) = default;
-
-  VariantCopyAssignBaseNontrivial& operator=(
-      const VariantCopyAssignBaseNontrivial& other) {
-    VisitIndices<sizeof...(T)>::Run(
-        VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
-    return *this;
-  }
-
- protected:
-  using Base::index_;
-  using Base::state_;
-};
-
-////////////////////////////////////////
-// Visitors for Comparison Operations //
-////////////////////////////////////////
-
-template <class... Types>
-struct EqualsOp {
-  const variant<Types...>* v;
-  const variant<Types...>* w;
-
-  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
-    return true;
-  }
-
-  template <std::size_t I>
-  constexpr bool operator()(SizeT<I> /*v_i*/) const {
-    return VariantCoreAccess::Access<I>(*v) == VariantCoreAccess::Access<I>(*w);
-  }
-};
-
-template <class... Types>
-struct NotEqualsOp {
-  const variant<Types...>* v;
-  const variant<Types...>* w;
-
-  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
-    return false;
-  }
-
-  template <std::size_t I>
-  constexpr bool operator()(SizeT<I> /*v_i*/) const {
-    return VariantCoreAccess::Access<I>(*v) != VariantCoreAccess::Access<I>(*w);
-  }
-};
-
-template <class... Types>
-struct LessThanOp {
-  const variant<Types...>* v;
-  const variant<Types...>* w;
-
-  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
-    return false;
-  }
-
-  template <std::size_t I>
-  constexpr bool operator()(SizeT<I> /*v_i*/) const {
-    return VariantCoreAccess::Access<I>(*v) < VariantCoreAccess::Access<I>(*w);
-  }
-};
-
-template <class... Types>
-struct GreaterThanOp {
-  const variant<Types...>* v;
-  const variant<Types...>* w;
-
-  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
-    return false;
-  }
-
-  template <std::size_t I>
-  constexpr bool operator()(SizeT<I> /*v_i*/) const {
-    return VariantCoreAccess::Access<I>(*v) > VariantCoreAccess::Access<I>(*w);
-  }
-};
-
-template <class... Types>
-struct LessThanOrEqualsOp {
-  const variant<Types...>* v;
-  const variant<Types...>* w;
-
-  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
-    return true;
-  }
-
-  template <std::size_t I>
-  constexpr bool operator()(SizeT<I> /*v_i*/) const {
-    return VariantCoreAccess::Access<I>(*v) <= VariantCoreAccess::Access<I>(*w);
-  }
-};
-
-template <class... Types>
-struct GreaterThanOrEqualsOp {
-  const variant<Types...>* v;
-  const variant<Types...>* w;
-
-  constexpr bool operator()(SizeT<absl::variant_npos> /*v_i*/) const {
-    return true;
-  }
-
-  template <std::size_t I>
-  constexpr bool operator()(SizeT<I> /*v_i*/) const {
-    return VariantCoreAccess::Access<I>(*v) >= VariantCoreAccess::Access<I>(*w);
-  }
-};
-
-// Precondition: v.index() == w.index();
-template <class... Types>
-struct SwapSameIndex {
-  variant<Types...>* v;
-  variant<Types...>* w;
-  template <std::size_t I>
-  void operator()(SizeT<I>) const {
-    type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
-                               VariantCoreAccess::Access<I>(*w));
-  }
-
-  void operator()(SizeT<variant_npos>) const {}
-};
-
-// TODO(calabrese) do this from a different namespace for proper adl usage
-template <class... Types>
-struct Swap {
-  variant<Types...>* v;
-  variant<Types...>* w;
-
-  void generic_swap() const {
-    variant<Types...> tmp(std::move(*w));
-    VariantCoreAccess::Destroy(*w);
-    VariantCoreAccess::InitFrom(*w, std::move(*v));
-    VariantCoreAccess::Destroy(*v);
-    VariantCoreAccess::InitFrom(*v, std::move(tmp));
-  }
-
-  void operator()(SizeT<absl::variant_npos> /*w_i*/) const {
-    if (!v->valueless_by_exception()) {
-      generic_swap();
-    }
-  }
-
-  template <std::size_t Wi>
-  void operator()(SizeT<Wi> /*w_i*/) {
-    if (v->index() == Wi) {
-      VisitIndices<sizeof...(Types)>::Run(SwapSameIndex<Types...>{v, w}, Wi);
-    } else {
-      generic_swap();
-    }
-  }
-};
-
-template <typename Variant, typename = void, typename... Ts>
-struct VariantHashBase {
-  VariantHashBase() = delete;
-  VariantHashBase(const VariantHashBase&) = delete;
-  VariantHashBase(VariantHashBase&&) = delete;
-  VariantHashBase& operator=(const VariantHashBase&) = delete;
-  VariantHashBase& operator=(VariantHashBase&&) = delete;
-};
-
-struct VariantHashVisitor {
-  template <typename T>
-  size_t operator()(const T& t) {
-    return std::hash<T>{}(t);
-  }
-};
-
-template <typename Variant, typename... Ts>
-struct VariantHashBase<Variant,
-                       absl::enable_if_t<absl::conjunction<
-                           type_traits_internal::IsHashable<Ts>...>::value>,
-                       Ts...> {
-  using argument_type = Variant;
-  using result_type = size_t;
-  size_t operator()(const Variant& var) const {
-    type_traits_internal::AssertHashEnabled<Ts...>();
-    if (var.valueless_by_exception()) {
-      return 239799884;
-    }
-    size_t result = VisitIndices<variant_size<Variant>::value>::Run(
-        PerformVisitation<VariantHashVisitor, const Variant&>{
-            std::forward_as_tuple(var), VariantHashVisitor{}},
-        var.index());
-    // Combine the index and the hash result in order to distinguish
-    // std::variant<int, int> holding the same value as different alternative.
-    return result ^ var.index();
-  }
-};
-
-}  // namespace variant_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // !defined(ABSL_USES_STD_VARIANT)
-#endif  // ABSL_TYPES_INTERNAL_VARIANT_H_
diff --git a/absl/types/optional.h b/absl/types/optional.h
index cf7249c..65bba64 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -16,32 +16,18 @@
 // optional.h
 // -----------------------------------------------------------------------------
 //
-// This header file defines the `absl::optional` type for holding a value which
-// may or may not be present. This type is useful for providing value semantics
-// for operations that may either wish to return or hold "something-or-nothing".
-//
-// Example:
-//
-//   // A common way to signal operation failure is to provide an output
-//   // parameter and a bool return type:
-//   bool AcquireResource(const Input&, Resource * out);
-//
-//   // Providing an absl::optional return type provides a cleaner API:
-//   absl::optional<Resource> AcquireResource(const Input&);
-//
-// `absl::optional` is a C++11 compatible version of the C++17 `std::optional`
-// abstraction and is designed to be a drop-in replacement for code compliant
-// with C++17.
+// Historical note: Abseil once provided an implementation of `absl::optional`
+// as a polyfill for `std::optional` prior to C++17. Now that C++17 is required,
+// `absl::optional` is an alias for `std::optional`.
+
 #ifndef ABSL_TYPES_OPTIONAL_H_
 #define ABSL_TYPES_OPTIONAL_H_
 
-#include "absl/base/config.h"   // TODO(calabrese) IWYU removal?
+#include <optional>
+
+#include "absl/base/config.h"
 #include "absl/utility/utility.h"
 
-#ifdef ABSL_USES_STD_OPTIONAL
-
-#include <optional>  // IWYU pragma: export
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 using std::bad_optional_access;
@@ -52,728 +38,4 @@
 ABSL_NAMESPACE_END
 }  // namespace absl
 
-#else  // ABSL_USES_STD_OPTIONAL
-
-#include <cassert>
-#include <functional>
-#include <initializer_list>
-#include <type_traits>
-#include <utility>
-
-#include "absl/base/attributes.h"
-#include "absl/base/nullability.h"
-#include "absl/base/internal/inline_variable.h"
-#include "absl/meta/type_traits.h"
-#include "absl/types/bad_optional_access.h"
-#include "absl/types/internal/optional.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// nullopt_t
-//
-// Class type for `absl::nullopt` used to indicate an `absl::optional<T>` type
-// that does not contain a value.
-struct nullopt_t {
-  // It must not be default-constructible to avoid ambiguity for opt = {}.
-  explicit constexpr nullopt_t(optional_internal::init_t) noexcept {}
-};
-
-// nullopt
-//
-// A tag constant of type `absl::nullopt_t` used to indicate an empty
-// `absl::optional` in certain functions, such as construction or assignment.
-ABSL_INTERNAL_INLINE_CONSTEXPR(nullopt_t, nullopt,
-                               nullopt_t(optional_internal::init_t()));
-
-// -----------------------------------------------------------------------------
-// absl::optional
-// -----------------------------------------------------------------------------
-//
-// A value of type `absl::optional<T>` holds either a value of `T` or an
-// "empty" value.  When it holds a value of `T`, it stores it as a direct
-// sub-object, so `sizeof(optional<T>)` is approximately
-// `sizeof(T) + sizeof(bool)`.
-//
-// This implementation is based on the specification in the latest draft of the
-// C++17 `std::optional` specification as of May 2017, section 20.6.
-//
-// Differences between `absl::optional<T>` and `std::optional<T>` include:
-//
-//    * `constexpr` is not used for non-const member functions.
-//      (dependency on some differences between C++11 and C++14.)
-//    * `absl::nullopt` and `absl::in_place` are not declared `constexpr`. We
-//      need the inline variable support in C++17 for external linkage.
-//    * Throws `absl::bad_optional_access` instead of
-//      `std::bad_optional_access`.
-//    * `make_optional()` cannot be declared `constexpr` due to the absence of
-//      guaranteed copy elision.
-//    * The move constructor's `noexcept` specification is stronger, i.e. if the
-//      default allocator is non-throwing (via setting
-//      `ABSL_ALLOCATOR_NOTHROW`), it evaluates to `noexcept(true)`, because
-//      we assume
-//       a) move constructors should only throw due to allocation failure and
-//       b) if T's move constructor allocates, it uses the same allocation
-//          function as the default allocator.
-//
-template <typename T>
-class optional : private optional_internal::optional_data<T>,
-                 private optional_internal::optional_ctor_base<
-                     optional_internal::ctor_copy_traits<T>::traits>,
-                 private optional_internal::optional_assign_base<
-                     optional_internal::assign_copy_traits<T>::traits> {
-  using data_base = optional_internal::optional_data<T>;
-
- public:
-  typedef T value_type;
-
-  // Constructors
-
-  // Constructs an `optional` holding an empty value, NOT a default constructed
-  // `T`.
-  constexpr optional() noexcept = default;
-
-  // Constructs an `optional` initialized with `nullopt` to hold an empty value.
-  constexpr optional(nullopt_t) noexcept {}  // NOLINT(runtime/explicit)
-
-  // Copy constructor, standard semantics
-  optional(const optional&) = default;
-
-  // Move constructor, standard semantics
-  optional(optional&&) = default;
-
-  // Constructs a non-empty `optional` direct-initialized value of type `T` from
-  // the arguments `std::forward<Args>(args)...`  within the `optional`.
-  // (The `in_place_t` is a tag used to indicate that the contained object
-  // should be constructed in-place.)
-  template <typename InPlaceT, typename... Args,
-            absl::enable_if_t<absl::conjunction<
-                std::is_same<InPlaceT, in_place_t>,
-                std::is_constructible<T, Args&&...> >::value>* = nullptr>
-  constexpr explicit optional(InPlaceT, Args&&... args)
-      : data_base(in_place_t(), std::forward<Args>(args)...) {}
-
-  // Constructs a non-empty `optional` direct-initialized value of type `T` from
-  // the arguments of an initializer_list and `std::forward<Args>(args)...`.
-  // (The `in_place_t` is a tag used to indicate that the contained object
-  // should be constructed in-place.)
-  template <typename U, typename... Args,
-            typename = typename std::enable_if<std::is_constructible<
-                T, std::initializer_list<U>&, Args&&...>::value>::type>
-  constexpr explicit optional(in_place_t, std::initializer_list<U> il,
-                              Args&&... args)
-      : data_base(in_place_t(), il, std::forward<Args>(args)...) {}
-
-  // Value constructor (implicit)
-  template <
-      typename U = T,
-      typename std::enable_if<
-          absl::conjunction<absl::negation<std::is_same<
-                                in_place_t, typename std::decay<U>::type> >,
-                            absl::negation<std::is_same<
-                                optional<T>, typename std::decay<U>::type> >,
-                            std::is_convertible<U&&, T>,
-                            std::is_constructible<T, U&&> >::value,
-          bool>::type = false>
-  constexpr optional(U&& v) : data_base(in_place_t(), std::forward<U>(v)) {}
-
-  // Value constructor (explicit)
-  template <
-      typename U = T,
-      typename std::enable_if<
-          absl::conjunction<absl::negation<std::is_same<
-                                in_place_t, typename std::decay<U>::type> >,
-                            absl::negation<std::is_same<
-                                optional<T>, typename std::decay<U>::type> >,
-                            absl::negation<std::is_convertible<U&&, T> >,
-                            std::is_constructible<T, U&&> >::value,
-          bool>::type = false>
-  explicit constexpr optional(U&& v)
-      : data_base(in_place_t(), std::forward<U>(v)) {}
-
-  // Converting copy constructor (implicit)
-  template <typename U,
-            typename std::enable_if<
-                absl::conjunction<
-                    absl::negation<std::is_same<T, U> >,
-                    std::is_constructible<T, const U&>,
-                    absl::negation<
-                        optional_internal::
-                            is_constructible_convertible_from_optional<T, U> >,
-                    std::is_convertible<const U&, T> >::value,
-                bool>::type = false>
-  optional(const optional<U>& rhs) {
-    if (rhs) {
-      this->construct(*rhs);
-    }
-  }
-
-  // Converting copy constructor (explicit)
-  template <typename U,
-            typename std::enable_if<
-                absl::conjunction<
-                    absl::negation<std::is_same<T, U>>,
-                    std::is_constructible<T, const U&>,
-                    absl::negation<
-                        optional_internal::
-                            is_constructible_convertible_from_optional<T, U>>,
-                    absl::negation<std::is_convertible<const U&, T>>>::value,
-                bool>::type = false>
-  explicit optional(const optional<U>& rhs) {
-    if (rhs) {
-      this->construct(*rhs);
-    }
-  }
-
-  // Converting move constructor (implicit)
-  template <typename U,
-            typename std::enable_if<
-                absl::conjunction<
-                    absl::negation<std::is_same<T, U> >,
-                    std::is_constructible<T, U&&>,
-                    absl::negation<
-                        optional_internal::
-                            is_constructible_convertible_from_optional<T, U> >,
-                    std::is_convertible<U&&, T> >::value,
-                bool>::type = false>
-  optional(optional<U>&& rhs) {
-    if (rhs) {
-      this->construct(std::move(*rhs));
-    }
-  }
-
-  // Converting move constructor (explicit)
-  template <
-      typename U,
-      typename std::enable_if<
-          absl::conjunction<
-              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
-              absl::negation<
-                  optional_internal::is_constructible_convertible_from_optional<
-                      T, U>>,
-              absl::negation<std::is_convertible<U&&, T>>>::value,
-          bool>::type = false>
-  explicit optional(optional<U>&& rhs) {
-    if (rhs) {
-      this->construct(std::move(*rhs));
-    }
-  }
-
-  // Destructor. Trivial if `T` is trivially destructible.
-  ~optional() = default;
-
-  // Assignment Operators
-
-  // Assignment from `nullopt`
-  //
-  // Example:
-  //
-  //   struct S { int value; };
-  //   optional<S> opt = absl::nullopt;  // Could also use opt = { };
-  optional& operator=(nullopt_t) noexcept {
-    this->destruct();
-    return *this;
-  }
-
-  // Copy assignment operator, standard semantics
-  optional& operator=(const optional& src) = default;
-
-  // Move assignment operator, standard semantics
-  optional& operator=(optional&& src) = default;
-
-  // Value assignment operators
-  template <typename U = T,
-            int&...,  // Workaround an internal compiler error in GCC 5 to 10.
-            typename = typename std::enable_if<absl::conjunction<
-                absl::negation<
-                    std::is_same<optional<T>, typename std::decay<U>::type> >,
-                absl::negation<absl::conjunction<
-                    std::is_scalar<T>,
-                    std::is_same<T, typename std::decay<U>::type> > >,
-                std::is_constructible<T, U>,
-                std::is_assignable<T&, U> >::value>::type>
-  optional& operator=(U&& v) {
-    this->assign(std::forward<U>(v));
-    return *this;
-  }
-
-  template <
-      typename U,
-      int&...,  // Workaround an internal compiler error in GCC 5 to 10.
-      typename = typename std::enable_if<absl::conjunction<
-          absl::negation<std::is_same<T, U> >,
-          std::is_constructible<T, const U&>, std::is_assignable<T&, const U&>,
-          absl::negation<
-              optional_internal::
-                  is_constructible_convertible_assignable_from_optional<
-                      T, U> > >::value>::type>
-  optional& operator=(const optional<U>& rhs) {
-    if (rhs) {
-      this->assign(*rhs);
-    } else {
-      this->destruct();
-    }
-    return *this;
-  }
-
-  template <typename U,
-            int&...,  // Workaround an internal compiler error in GCC 5 to 10.
-            typename = typename std::enable_if<absl::conjunction<
-                absl::negation<std::is_same<T, U> >,
-                std::is_constructible<T, U>, std::is_assignable<T&, U>,
-                absl::negation<
-                    optional_internal::
-                        is_constructible_convertible_assignable_from_optional<
-                            T, U> > >::value>::type>
-  optional& operator=(optional<U>&& rhs) {
-    if (rhs) {
-      this->assign(std::move(*rhs));
-    } else {
-      this->destruct();
-    }
-    return *this;
-  }
-
-  // Modifiers
-
-  // optional::reset()
-  //
-  // Destroys the inner `T` value of an `absl::optional` if one is present.
-  ABSL_ATTRIBUTE_REINITIALIZES void reset() noexcept { this->destruct(); }
-
-  // optional::emplace()
-  //
-  // (Re)constructs the underlying `T` in-place with the given forwarded
-  // arguments.
-  //
-  // Example:
-  //
-  //   optional<Foo> opt;
-  //   opt.emplace(arg1,arg2,arg3);  // Constructs Foo(arg1,arg2,arg3)
-  //
-  // If the optional is non-empty, and the `args` refer to subobjects of the
-  // current object, then behaviour is undefined, because the current object
-  // will be destructed before the new object is constructed with `args`.
-  template <typename... Args,
-            typename = typename std::enable_if<
-                std::is_constructible<T, Args&&...>::value>::type>
-  T& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    this->destruct();
-    this->construct(std::forward<Args>(args)...);
-    return reference();
-  }
-
-  // Emplace reconstruction overload for an initializer list and the given
-  // forwarded arguments.
-  //
-  // Example:
-  //
-  //   struct Foo {
-  //     Foo(std::initializer_list<int>);
-  //   };
-  //
-  //   optional<Foo> opt;
-  //   opt.emplace({1,2,3});  // Constructs Foo({1,2,3})
-  template <typename U, typename... Args,
-            typename = typename std::enable_if<std::is_constructible<
-                T, std::initializer_list<U>&, Args&&...>::value>::type>
-  T& emplace(std::initializer_list<U> il,
-             Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    this->destruct();
-    this->construct(il, std::forward<Args>(args)...);
-    return reference();
-  }
-
-  // Swaps
-
-  // Swap, standard semantics
-  void swap(optional& rhs) noexcept(
-      std::is_nothrow_move_constructible<T>::value&&
-          type_traits_internal::IsNothrowSwappable<T>::value) {
-    if (*this) {
-      if (rhs) {
-        type_traits_internal::Swap(**this, *rhs);
-      } else {
-        rhs.construct(std::move(**this));
-        this->destruct();
-      }
-    } else {
-      if (rhs) {
-        this->construct(std::move(*rhs));
-        rhs.destruct();
-      } else {
-        // No effect (swap(disengaged, disengaged)).
-      }
-    }
-  }
-
-  // Observers
-
-  // optional::operator->()
-  //
-  // Accesses the underlying `T` value's member `m` of an `optional`. If the
-  // `optional` is empty, behavior is undefined.
-  //
-  // If you need myOpt->foo in constexpr, use (*myOpt).foo instead.
-  absl::Nonnull<const T*> operator->() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    ABSL_HARDENING_ASSERT(this->engaged_);
-    return std::addressof(this->data_);
-  }
-  absl::Nonnull<T*> operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    ABSL_HARDENING_ASSERT(this->engaged_);
-    return std::addressof(this->data_);
-  }
-
-  // optional::operator*()
-  //
-  // Accesses the underlying `T` value of an `optional`. If the `optional` is
-  // empty, behavior is undefined.
-  constexpr const T& operator*() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return ABSL_HARDENING_ASSERT(this->engaged_), reference();
-  }
-  T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    ABSL_HARDENING_ASSERT(this->engaged_);
-    return reference();
-  }
-  constexpr const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return ABSL_HARDENING_ASSERT(this->engaged_), std::move(reference());
-  }
-  T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    ABSL_HARDENING_ASSERT(this->engaged_);
-    return std::move(reference());
-  }
-
-  // optional::operator bool()
-  //
-  // Returns false if and only if the `optional` is empty.
-  //
-  //   if (opt) {
-  //     // do something with *opt or opt->;
-  //   } else {
-  //     // opt is empty.
-  //   }
-  //
-  constexpr explicit operator bool() const noexcept { return this->engaged_; }
-
-  // optional::has_value()
-  //
-  // Determines whether the `optional` contains a value. Returns `false` if and
-  // only if `*this` is empty.
-  constexpr bool has_value() const noexcept { return this->engaged_; }
-
-// Suppress bogus warning on MSVC: MSVC complains call to reference() after
-// throw_bad_optional_access() is unreachable.
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4702)
-#endif  // _MSC_VER
-  // optional::value()
-  //
-  // Returns a reference to an `optional`s underlying value. The constness
-  // and lvalue/rvalue-ness of the `optional` is preserved to the view of
-  // the `T` sub-object. Throws `absl::bad_optional_access` when the `optional`
-  // is empty.
-  constexpr const T& value() const& ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return static_cast<bool>(*this)
-               ? reference()
-               : (optional_internal::throw_bad_optional_access(), reference());
-  }
-  T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND {
-    return static_cast<bool>(*this)
-               ? reference()
-               : (optional_internal::throw_bad_optional_access(), reference());
-  }
-  T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND {  // NOLINT(build/c++11)
-    return std::move(
-        static_cast<bool>(*this)
-            ? reference()
-            : (optional_internal::throw_bad_optional_access(), reference()));
-  }
-  constexpr const T&& value()
-      const&& ABSL_ATTRIBUTE_LIFETIME_BOUND {  // NOLINT(build/c++11)
-    return std::move(
-        static_cast<bool>(*this)
-            ? reference()
-            : (optional_internal::throw_bad_optional_access(), reference()));
-  }
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif  // _MSC_VER
-
-  // optional::value_or()
-  //
-  // Returns either the value of `T` or a passed default `v` if the `optional`
-  // is empty.
-  template <typename U>
-  constexpr T value_or(U&& v) const& {
-    static_assert(std::is_copy_constructible<value_type>::value,
-                  "optional<T>::value_or: T must be copy constructible");
-    static_assert(std::is_convertible<U&&, value_type>::value,
-                  "optional<T>::value_or: U must be convertible to T");
-    return static_cast<bool>(*this) ? **this
-                                    : static_cast<T>(std::forward<U>(v));
-  }
-  template <typename U>
-  T value_or(U&& v) && {  // NOLINT(build/c++11)
-    static_assert(std::is_move_constructible<value_type>::value,
-                  "optional<T>::value_or: T must be move constructible");
-    static_assert(std::is_convertible<U&&, value_type>::value,
-                  "optional<T>::value_or: U must be convertible to T");
-    return static_cast<bool>(*this) ? std::move(**this)
-                                    : static_cast<T>(std::forward<U>(v));
-  }
-
- private:
-  // Private accessors for internal storage viewed as reference to T.
-  constexpr const T& reference() const { return this->data_; }
-  T& reference() { return this->data_; }
-
-  // T constraint checks.  You can't have an optional of nullopt_t, in_place_t
-  // or a reference.
-  static_assert(
-      !std::is_same<nullopt_t, typename std::remove_cv<T>::type>::value,
-      "optional<nullopt_t> is not allowed.");
-  static_assert(
-      !std::is_same<in_place_t, typename std::remove_cv<T>::type>::value,
-      "optional<in_place_t> is not allowed.");
-  static_assert(!std::is_reference<T>::value,
-                "optional<reference> is not allowed.");
-};
-
-// Non-member functions
-
-// swap()
-//
-// Performs a swap between two `absl::optional` objects, using standard
-// semantics.
-template <typename T, typename std::enable_if<
-                          std::is_move_constructible<T>::value &&
-                              type_traits_internal::IsSwappable<T>::value,
-                          bool>::type = false>
-void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
-  a.swap(b);
-}
-
-// make_optional()
-//
-// Creates a non-empty `optional<T>` where the type of `T` is deduced. An
-// `absl::optional` can also be explicitly instantiated with
-// `make_optional<T>(v)`.
-//
-// Note: `make_optional()` constructions may be declared `constexpr` for
-// trivially copyable types `T`. Non-trivial types require copy elision
-// support in C++17 for `make_optional` to support `constexpr` on such
-// non-trivial types.
-//
-// Example:
-//
-//   constexpr absl::optional<int> opt = absl::make_optional(1);
-//   static_assert(opt.value() == 1, "");
-template <typename T>
-constexpr optional<typename std::decay<T>::type> make_optional(T&& v) {
-  return optional<typename std::decay<T>::type>(std::forward<T>(v));
-}
-
-template <typename T, typename... Args>
-constexpr optional<T> make_optional(Args&&... args) {
-  return optional<T>(in_place_t(), std::forward<Args>(args)...);
-}
-
-template <typename T, typename U, typename... Args>
-constexpr optional<T> make_optional(std::initializer_list<U> il,
-                                    Args&&... args) {
-  return optional<T>(in_place_t(), il, std::forward<Args>(args)...);
-}
-
-// Relational operators [optional.relops]
-
-// Empty optionals are considered equal to each other and less than non-empty
-// optionals. Supports relations between optional<T> and optional<U>, between
-// optional<T> and U, and between optional<T> and nullopt.
-//
-// Note: We're careful to support T having non-bool relationals.
-
-// Requires: The expression, e.g. "*x == *y" shall be well-formed and its result
-// shall be convertible to bool.
-// The C++17 (N4606) "Returns:" statements are translated into
-// code in an obvious way here, and the original text retained as function docs.
-// Returns: If bool(x) != bool(y), false; otherwise if bool(x) == false, true;
-// otherwise *x == *y.
-template <typename T, typename U>
-constexpr auto operator==(const optional<T>& x, const optional<U>& y)
-    -> decltype(optional_internal::convertible_to_bool(*x == *y)) {
-  return static_cast<bool>(x) != static_cast<bool>(y)
-             ? false
-             : static_cast<bool>(x) == false ? true
-                                             : static_cast<bool>(*x == *y);
-}
-
-// Returns: If bool(x) != bool(y), true; otherwise, if bool(x) == false, false;
-// otherwise *x != *y.
-template <typename T, typename U>
-constexpr auto operator!=(const optional<T>& x, const optional<U>& y)
-    -> decltype(optional_internal::convertible_to_bool(*x != *y)) {
-  return static_cast<bool>(x) != static_cast<bool>(y)
-             ? true
-             : static_cast<bool>(x) == false ? false
-                                             : static_cast<bool>(*x != *y);
-}
-// Returns: If !y, false; otherwise, if !x, true; otherwise *x < *y.
-template <typename T, typename U>
-constexpr auto operator<(const optional<T>& x, const optional<U>& y)
-    -> decltype(optional_internal::convertible_to_bool(*x < *y)) {
-  return !y ? false : !x ? true : static_cast<bool>(*x < *y);
-}
-// Returns: If !x, false; otherwise, if !y, true; otherwise *x > *y.
-template <typename T, typename U>
-constexpr auto operator>(const optional<T>& x, const optional<U>& y)
-    -> decltype(optional_internal::convertible_to_bool(*x > *y)) {
-  return !x ? false : !y ? true : static_cast<bool>(*x > *y);
-}
-// Returns: If !x, true; otherwise, if !y, false; otherwise *x <= *y.
-template <typename T, typename U>
-constexpr auto operator<=(const optional<T>& x, const optional<U>& y)
-    -> decltype(optional_internal::convertible_to_bool(*x <= *y)) {
-  return !x ? true : !y ? false : static_cast<bool>(*x <= *y);
-}
-// Returns: If !y, true; otherwise, if !x, false; otherwise *x >= *y.
-template <typename T, typename U>
-constexpr auto operator>=(const optional<T>& x, const optional<U>& y)
-    -> decltype(optional_internal::convertible_to_bool(*x >= *y)) {
-  return !y ? true : !x ? false : static_cast<bool>(*x >= *y);
-}
-
-// Comparison with nullopt [optional.nullops]
-// The C++17 (N4606) "Returns:" statements are used directly here.
-template <typename T>
-constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
-  return !x;
-}
-template <typename T>
-constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
-  return !x;
-}
-template <typename T>
-constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
-  return static_cast<bool>(x);
-}
-template <typename T>
-constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
-  return static_cast<bool>(x);
-}
-template <typename T>
-constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
-  return false;
-}
-template <typename T>
-constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
-  return static_cast<bool>(x);
-}
-template <typename T>
-constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
-  return !x;
-}
-template <typename T>
-constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
-  return true;
-}
-template <typename T>
-constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
-  return static_cast<bool>(x);
-}
-template <typename T>
-constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
-  return false;
-}
-template <typename T>
-constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
-  return true;
-}
-template <typename T>
-constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
-  return !x;
-}
-
-// Comparison with T [optional.comp_with_t]
-
-// Requires: The expression, e.g. "*x == v" shall be well-formed and its result
-// shall be convertible to bool.
-// The C++17 (N4606) "Equivalent to:" statements are used directly here.
-template <typename T, typename U>
-constexpr auto operator==(const optional<T>& x, const U& v)
-    -> decltype(optional_internal::convertible_to_bool(*x == v)) {
-  return static_cast<bool>(x) ? static_cast<bool>(*x == v) : false;
-}
-template <typename T, typename U>
-constexpr auto operator==(const U& v, const optional<T>& x)
-    -> decltype(optional_internal::convertible_to_bool(v == *x)) {
-  return static_cast<bool>(x) ? static_cast<bool>(v == *x) : false;
-}
-template <typename T, typename U>
-constexpr auto operator!=(const optional<T>& x, const U& v)
-    -> decltype(optional_internal::convertible_to_bool(*x != v)) {
-  return static_cast<bool>(x) ? static_cast<bool>(*x != v) : true;
-}
-template <typename T, typename U>
-constexpr auto operator!=(const U& v, const optional<T>& x)
-    -> decltype(optional_internal::convertible_to_bool(v != *x)) {
-  return static_cast<bool>(x) ? static_cast<bool>(v != *x) : true;
-}
-template <typename T, typename U>
-constexpr auto operator<(const optional<T>& x, const U& v)
-    -> decltype(optional_internal::convertible_to_bool(*x < v)) {
-  return static_cast<bool>(x) ? static_cast<bool>(*x < v) : true;
-}
-template <typename T, typename U>
-constexpr auto operator<(const U& v, const optional<T>& x)
-    -> decltype(optional_internal::convertible_to_bool(v < *x)) {
-  return static_cast<bool>(x) ? static_cast<bool>(v < *x) : false;
-}
-template <typename T, typename U>
-constexpr auto operator<=(const optional<T>& x, const U& v)
-    -> decltype(optional_internal::convertible_to_bool(*x <= v)) {
-  return static_cast<bool>(x) ? static_cast<bool>(*x <= v) : true;
-}
-template <typename T, typename U>
-constexpr auto operator<=(const U& v, const optional<T>& x)
-    -> decltype(optional_internal::convertible_to_bool(v <= *x)) {
-  return static_cast<bool>(x) ? static_cast<bool>(v <= *x) : false;
-}
-template <typename T, typename U>
-constexpr auto operator>(const optional<T>& x, const U& v)
-    -> decltype(optional_internal::convertible_to_bool(*x > v)) {
-  return static_cast<bool>(x) ? static_cast<bool>(*x > v) : false;
-}
-template <typename T, typename U>
-constexpr auto operator>(const U& v, const optional<T>& x)
-    -> decltype(optional_internal::convertible_to_bool(v > *x)) {
-  return static_cast<bool>(x) ? static_cast<bool>(v > *x) : true;
-}
-template <typename T, typename U>
-constexpr auto operator>=(const optional<T>& x, const U& v)
-    -> decltype(optional_internal::convertible_to_bool(*x >= v)) {
-  return static_cast<bool>(x) ? static_cast<bool>(*x >= v) : false;
-}
-template <typename T, typename U>
-constexpr auto operator>=(const U& v, const optional<T>& x)
-    -> decltype(optional_internal::convertible_to_bool(v >= *x)) {
-  return static_cast<bool>(x) ? static_cast<bool>(v >= *x) : true;
-}
-
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-namespace std {
-
-// std::hash specialization for absl::optional.
-template <typename T>
-struct hash<absl::optional<T> >
-    : absl::optional_internal::optional_hash_base<T> {};
-
-}  // namespace std
-
-#undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS
-
-#endif  // ABSL_USES_STD_OPTIONAL
-
 #endif  // ABSL_TYPES_OPTIONAL_H_
diff --git a/absl/types/optional_exception_safety_test.cc b/absl/types/optional_exception_safety_test.cc
deleted file mode 100644
index 8e5fe85..0000000
--- a/absl/types/optional_exception_safety_test.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/types/optional.h"
-
-#include "absl/base/config.h"
-
-// This test is a no-op when absl::optional is an alias for std::optional and
-// when exceptions are not enabled.
-#if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)
-
-#include "gtest/gtest.h"
-#include "absl/base/internal/exception_safety_testing.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-namespace {
-
-using ::testing::AssertionFailure;
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
-using ::testing::MakeExceptionSafetyTester;
-
-using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
-using Optional = absl::optional<Thrower>;
-
-using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
-using MoveOptional = absl::optional<MoveThrower>;
-
-constexpr int kInitialInteger = 5;
-constexpr int kUpdatedInteger = 10;
-
-template <typename OptionalT>
-bool ValueThrowsBadOptionalAccess(const OptionalT& optional) try {
-  return (static_cast<void>(optional.value()), false);
-} catch (const absl::bad_optional_access&) {
-  return true;
-}
-
-template <typename OptionalT>
-AssertionResult OptionalInvariants(OptionalT* optional_ptr) {
-  // Check the current state post-throw for validity
-  auto& optional = *optional_ptr;
-
-  if (optional.has_value() && ValueThrowsBadOptionalAccess(optional)) {
-    return AssertionFailure()
-           << "Optional with value should not throw bad_optional_access when "
-              "accessing the value.";
-  }
-  if (!optional.has_value() && !ValueThrowsBadOptionalAccess(optional)) {
-    return AssertionFailure()
-           << "Optional without a value should throw bad_optional_access when "
-              "accessing the value.";
-  }
-
-  // Reset to a known state
-  optional.reset();
-
-  // Confirm that the known post-reset state is valid
-  if (optional.has_value()) {
-    return AssertionFailure()
-           << "Optional should not contain a value after being reset.";
-  }
-  if (!ValueThrowsBadOptionalAccess(optional)) {
-    return AssertionFailure() << "Optional should throw bad_optional_access "
-                                 "when accessing the value after being reset.";
-  }
-
-  return AssertionSuccess();
-}
-
-template <typename OptionalT>
-AssertionResult CheckDisengaged(OptionalT* optional_ptr) {
-  auto& optional = *optional_ptr;
-
-  if (optional.has_value()) {
-    return AssertionFailure()
-           << "Expected optional to not contain a value but a value was found.";
-  }
-
-  return AssertionSuccess();
-}
-
-template <typename OptionalT>
-AssertionResult CheckEngaged(OptionalT* optional_ptr) {
-  auto& optional = *optional_ptr;
-
-  if (!optional.has_value()) {
-    return AssertionFailure()
-           << "Expected optional to contain a value but no value was found.";
-  }
-
-  return AssertionSuccess();
-}
-
-TEST(OptionalExceptionSafety, ThrowingConstructors) {
-  auto thrower_nonempty = Optional(Thrower(kInitialInteger));
-  testing::TestThrowingCtor<Optional>(thrower_nonempty);
-
-  auto integer_nonempty = absl::optional<int>(kInitialInteger);
-  testing::TestThrowingCtor<Optional>(integer_nonempty);
-  testing::TestThrowingCtor<Optional>(std::move(integer_nonempty));  // NOLINT
-
-  testing::TestThrowingCtor<Optional>(kInitialInteger);
-  using ThrowerVec = std::vector<Thrower, testing::ThrowingAllocator<Thrower>>;
-  testing::TestThrowingCtor<absl::optional<ThrowerVec>>(
-      absl::in_place,
-      std::initializer_list<Thrower>{Thrower(), Thrower(), Thrower()},
-      testing::ThrowingAllocator<Thrower>());
-}
-
-TEST(OptionalExceptionSafety, NothrowConstructors) {
-  // This constructor is marked noexcept. If it throws, the program will
-  // terminate.
-  testing::TestThrowingCtor<MoveOptional>(MoveOptional(kUpdatedInteger));
-}
-
-TEST(OptionalExceptionSafety, Emplace) {
-  // Test the basic guarantee plus test the result of optional::has_value()
-  // is false in all cases
-  auto disengaged_test = MakeExceptionSafetyTester().WithContracts(
-      OptionalInvariants<Optional>, CheckDisengaged<Optional>);
-  auto disengaged_test_empty = disengaged_test.WithInitialValue(Optional());
-  auto disengaged_test_nonempty =
-      disengaged_test.WithInitialValue(Optional(kInitialInteger));
-
-  auto emplace_thrower_directly = [](Optional* optional_ptr) {
-    optional_ptr->emplace(kUpdatedInteger);
-  };
-  EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_directly));
-  EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_directly));
-
-  auto emplace_thrower_copy = [](Optional* optional_ptr) {
-    auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor);
-    optional_ptr->emplace(thrower);
-  };
-  EXPECT_TRUE(disengaged_test_empty.Test(emplace_thrower_copy));
-  EXPECT_TRUE(disengaged_test_nonempty.Test(emplace_thrower_copy));
-}
-
-TEST(OptionalExceptionSafety, EverythingThrowsSwap) {
-  // Test the basic guarantee plus test the result of optional::has_value()
-  // remains the same
-  auto test =
-      MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>);
-  auto disengaged_test_empty = test.WithInitialValue(Optional())
-                                   .WithContracts(CheckDisengaged<Optional>);
-  auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger))
-                                   .WithContracts(CheckEngaged<Optional>);
-
-  auto swap_empty = [](Optional* optional_ptr) {
-    auto empty = Optional();
-    optional_ptr->swap(empty);
-  };
-  EXPECT_TRUE(engaged_test_nonempty.Test(swap_empty));
-
-  auto swap_nonempty = [](Optional* optional_ptr) {
-    auto nonempty =
-        Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
-    optional_ptr->swap(nonempty);
-  };
-  EXPECT_TRUE(disengaged_test_empty.Test(swap_nonempty));
-  EXPECT_TRUE(engaged_test_nonempty.Test(swap_nonempty));
-}
-
-TEST(OptionalExceptionSafety, NoThrowMoveSwap) {
-  // Tests the nothrow guarantee for optional of T with non-throwing move
-  {
-    auto empty = MoveOptional();
-    auto nonempty = MoveOptional(kInitialInteger);
-    EXPECT_TRUE(testing::TestNothrowOp([&]() { nonempty.swap(empty); }));
-  }
-  {
-    auto nonempty = MoveOptional(kUpdatedInteger);
-    auto empty = MoveOptional();
-    EXPECT_TRUE(testing::TestNothrowOp([&]() { empty.swap(nonempty); }));
-  }
-  {
-    auto nonempty_from = MoveOptional(kUpdatedInteger);
-    auto nonempty_to = MoveOptional(kInitialInteger);
-    EXPECT_TRUE(
-        testing::TestNothrowOp([&]() { nonempty_to.swap(nonempty_from); }));
-  }
-}
-
-TEST(OptionalExceptionSafety, CopyAssign) {
-  // Test the basic guarantee plus test the result of optional::has_value()
-  // remains the same
-  auto test =
-      MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>);
-  auto disengaged_test_empty = test.WithInitialValue(Optional())
-                                   .WithContracts(CheckDisengaged<Optional>);
-  auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger))
-                                   .WithContracts(CheckEngaged<Optional>);
-
-  auto copyassign_nonempty = [](Optional* optional_ptr) {
-    auto nonempty =
-        Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
-    *optional_ptr = nonempty;
-  };
-  EXPECT_TRUE(disengaged_test_empty.Test(copyassign_nonempty));
-  EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_nonempty));
-
-  auto copyassign_thrower = [](Optional* optional_ptr) {
-    auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor);
-    *optional_ptr = thrower;
-  };
-  EXPECT_TRUE(disengaged_test_empty.Test(copyassign_thrower));
-  EXPECT_TRUE(engaged_test_nonempty.Test(copyassign_thrower));
-}
-
-TEST(OptionalExceptionSafety, MoveAssign) {
-  // Test the basic guarantee plus test the result of optional::has_value()
-  // remains the same
-  auto test =
-      MakeExceptionSafetyTester().WithContracts(OptionalInvariants<Optional>);
-  auto disengaged_test_empty = test.WithInitialValue(Optional())
-                                   .WithContracts(CheckDisengaged<Optional>);
-  auto engaged_test_nonempty = test.WithInitialValue(Optional(kInitialInteger))
-                                   .WithContracts(CheckEngaged<Optional>);
-
-  auto moveassign_empty = [](Optional* optional_ptr) {
-    auto empty = Optional();
-    *optional_ptr = std::move(empty);
-  };
-  EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_empty));
-
-  auto moveassign_nonempty = [](Optional* optional_ptr) {
-    auto nonempty =
-        Optional(absl::in_place, kUpdatedInteger, testing::nothrow_ctor);
-    *optional_ptr = std::move(nonempty);
-  };
-  EXPECT_TRUE(disengaged_test_empty.Test(moveassign_nonempty));
-  EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_nonempty));
-
-  auto moveassign_thrower = [](Optional* optional_ptr) {
-    auto thrower = Thrower(kUpdatedInteger, testing::nothrow_ctor);
-    *optional_ptr = std::move(thrower);
-  };
-  EXPECT_TRUE(disengaged_test_empty.Test(moveassign_thrower));
-  EXPECT_TRUE(engaged_test_nonempty.Test(moveassign_thrower));
-}
-
-TEST(OptionalExceptionSafety, NothrowMoveAssign) {
-  // Tests the nothrow guarantee for optional of T with non-throwing move
-  {
-    auto empty = MoveOptional();
-    auto nonempty = MoveOptional(kInitialInteger);
-    EXPECT_TRUE(testing::TestNothrowOp([&]() { nonempty = std::move(empty); }));
-  }
-  {
-    auto nonempty = MoveOptional(kInitialInteger);
-    auto empty = MoveOptional();
-    EXPECT_TRUE(testing::TestNothrowOp([&]() { empty = std::move(nonempty); }));
-  }
-  {
-    auto nonempty_from = MoveOptional(kUpdatedInteger);
-    auto nonempty_to = MoveOptional(kInitialInteger);
-    EXPECT_TRUE(testing::TestNothrowOp(
-        [&]() { nonempty_to = std::move(nonempty_from); }));
-  }
-  {
-    auto thrower = MoveThrower(kUpdatedInteger);
-    auto empty = MoveOptional();
-    EXPECT_TRUE(testing::TestNothrowOp([&]() { empty = std::move(thrower); }));
-  }
-  {
-    auto thrower = MoveThrower(kUpdatedInteger);
-    auto nonempty = MoveOptional(kInitialInteger);
-    EXPECT_TRUE(
-        testing::TestNothrowOp([&]() { nonempty = std::move(thrower); }));
-  }
-}
-
-}  // namespace
-
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // #if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc
deleted file mode 100644
index 115e20c..0000000
--- a/absl/types/optional_test.cc
+++ /dev/null
@@ -1,1615 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/types/optional.h"
-
-// This test is a no-op when absl::optional is an alias for std::optional.
-#if !defined(ABSL_USES_STD_OPTIONAL)
-
-#include <string>
-#include <type_traits>
-#include <utility>
-
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/log/log.h"
-#include "absl/meta/type_traits.h"
-#include "absl/strings/string_view.h"
-
-#if defined(__cplusplus) && __cplusplus >= 202002L
-// In C++20, volatile-qualified return types are deprecated.
-#define ABSL_VOLATILE_RETURN_TYPES_DEPRECATED 1
-#endif
-
-// The following types help test an internal compiler error in GCC5 though
-// GCC10. The case OptionalTest.InternalCompilerErrorInGcc5ToGcc10 crashes the
-// compiler without a workaround. This test case should remain at the beginning
-// of the file as the internal compiler error is sensitive to other constructs
-// in this file.
-template <class T, class...>
-using GccIceHelper1 = T;
-template <typename T>
-struct GccIceHelper2 {};
-template <typename T>
-class GccIce {
-  template <typename U,
-            typename SecondTemplateArgHasToExistForSomeReason = void,
-            typename DependentType = void,
-            typename = std::is_assignable<GccIceHelper1<T, DependentType>&, U>>
-  GccIce& operator=(GccIceHelper2<U> const&) {}
-};
-
-TEST(OptionalTest, InternalCompilerErrorInGcc5ToGcc10) {
-  GccIce<int> instantiate_ice_with_same_type_as_optional;
-  static_cast<void>(instantiate_ice_with_same_type_as_optional);
-  absl::optional<int> val1;
-  absl::optional<int> val2;
-  val1 = val2;
-}
-
-struct Hashable {};
-
-namespace std {
-template <>
-struct hash<Hashable> {
-  size_t operator()(const Hashable&) { return 0; }
-};
-}  // namespace std
-
-struct NonHashable {};
-
-namespace {
-
-std::string TypeQuals(std::string&) { return "&"; }
-std::string TypeQuals(std::string&&) { return "&&"; }
-std::string TypeQuals(const std::string&) { return "c&"; }
-std::string TypeQuals(const std::string&&) { return "c&&"; }
-
-struct StructorListener {
-  int construct0 = 0;
-  int construct1 = 0;
-  int construct2 = 0;
-  int listinit = 0;
-  int copy = 0;
-  int move = 0;
-  int copy_assign = 0;
-  int move_assign = 0;
-  int destruct = 0;
-  int volatile_copy = 0;
-  int volatile_move = 0;
-  int volatile_copy_assign = 0;
-  int volatile_move_assign = 0;
-};
-
-// Suppress MSVC warnings.
-// 4521: multiple copy constructors specified
-// 4522: multiple assignment operators specified
-// We wrote multiple of them to test that the correct overloads are selected.
-#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4521)
-#pragma warning(disable : 4522)
-#endif
-struct Listenable {
-  static StructorListener* listener;
-
-  Listenable() { ++listener->construct0; }
-  explicit Listenable(int /*unused*/) { ++listener->construct1; }
-  Listenable(int /*unused*/, int /*unused*/) { ++listener->construct2; }
-  Listenable(std::initializer_list<int> /*unused*/) { ++listener->listinit; }
-  Listenable(const Listenable& /*unused*/) { ++listener->copy; }
-  Listenable(const volatile Listenable& /*unused*/) {
-    ++listener->volatile_copy;
-  }
-  Listenable(volatile Listenable&& /*unused*/) { ++listener->volatile_move; }
-  Listenable(Listenable&& /*unused*/) { ++listener->move; }
-  Listenable& operator=(const Listenable& /*unused*/) {
-    ++listener->copy_assign;
-    return *this;
-  }
-  Listenable& operator=(Listenable&& /*unused*/) {
-    ++listener->move_assign;
-    return *this;
-  }
-  // use void return type instead of volatile T& to work around GCC warning
-  // when the assignment's returned reference is ignored.
-  void operator=(const volatile Listenable& /*unused*/) volatile {
-    ++listener->volatile_copy_assign;
-  }
-  void operator=(volatile Listenable&& /*unused*/) volatile {
-    ++listener->volatile_move_assign;
-  }
-  ~Listenable() { ++listener->destruct; }
-};
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-StructorListener* Listenable::listener = nullptr;
-
-struct ConstexprType {
-  enum CtorTypes {
-    kCtorDefault,
-    kCtorInt,
-    kCtorInitializerList,
-    kCtorConstChar
-  };
-  constexpr ConstexprType() : x(kCtorDefault) {}
-  constexpr explicit ConstexprType(int i) : x(kCtorInt) {}
-  constexpr ConstexprType(std::initializer_list<int> il)
-      : x(kCtorInitializerList) {}
-  constexpr ConstexprType(const char*)  // NOLINT(runtime/explicit)
-      : x(kCtorConstChar) {}
-  int x;
-};
-
-struct Copyable {
-  Copyable() {}
-  Copyable(const Copyable&) {}
-  Copyable& operator=(const Copyable&) { return *this; }
-};
-
-struct MoveableThrow {
-  MoveableThrow() {}
-  MoveableThrow(MoveableThrow&&) {}
-  MoveableThrow& operator=(MoveableThrow&&) { return *this; }
-};
-
-struct MoveableNoThrow {
-  MoveableNoThrow() {}
-  MoveableNoThrow(MoveableNoThrow&&) noexcept {}
-  MoveableNoThrow& operator=(MoveableNoThrow&&) noexcept { return *this; }
-};
-
-struct NonMovable {
-  NonMovable() {}
-  NonMovable(const NonMovable&) = delete;
-  NonMovable& operator=(const NonMovable&) = delete;
-  NonMovable(NonMovable&&) = delete;
-  NonMovable& operator=(NonMovable&&) = delete;
-};
-
-struct NoDefault {
-  NoDefault() = delete;
-  NoDefault(const NoDefault&) {}
-  NoDefault& operator=(const NoDefault&) { return *this; }
-};
-
-struct ConvertsFromInPlaceT {
-  ConvertsFromInPlaceT(absl::in_place_t) {}  // NOLINT
-};
-
-TEST(optionalTest, DefaultConstructor) {
-  absl::optional<int> empty;
-  EXPECT_FALSE(empty);
-  constexpr absl::optional<int> cempty;
-  static_assert(!cempty.has_value(), "");
-  EXPECT_TRUE(
-      std::is_nothrow_default_constructible<absl::optional<int>>::value);
-}
-
-TEST(optionalTest, nulloptConstructor) {
-  absl::optional<int> empty(absl::nullopt);
-  EXPECT_FALSE(empty);
-  constexpr absl::optional<int> cempty{absl::nullopt};
-  static_assert(!cempty.has_value(), "");
-  EXPECT_TRUE((std::is_nothrow_constructible<absl::optional<int>,
-                                             absl::nullopt_t>::value));
-}
-
-TEST(optionalTest, CopyConstructor) {
-  {
-    absl::optional<int> empty, opt42 = 42;
-    absl::optional<int> empty_copy(empty);
-    EXPECT_FALSE(empty_copy);
-    absl::optional<int> opt42_copy(opt42);
-    EXPECT_TRUE(opt42_copy);
-    EXPECT_EQ(42, *opt42_copy);
-  }
-  {
-    absl::optional<const int> empty, opt42 = 42;
-    absl::optional<const int> empty_copy(empty);
-    EXPECT_FALSE(empty_copy);
-    absl::optional<const int> opt42_copy(opt42);
-    EXPECT_TRUE(opt42_copy);
-    EXPECT_EQ(42, *opt42_copy);
-  }
-#if !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-  {
-    absl::optional<volatile int> empty, opt42 = 42;
-    absl::optional<volatile int> empty_copy(empty);
-    EXPECT_FALSE(empty_copy);
-    absl::optional<volatile int> opt42_copy(opt42);
-    EXPECT_TRUE(opt42_copy);
-    EXPECT_EQ(42, *opt42_copy);
-  }
-#endif
-  // test copyablility
-  EXPECT_TRUE(std::is_copy_constructible<absl::optional<int>>::value);
-  EXPECT_TRUE(std::is_copy_constructible<absl::optional<Copyable>>::value);
-  EXPECT_FALSE(
-      std::is_copy_constructible<absl::optional<MoveableThrow>>::value);
-  EXPECT_FALSE(
-      std::is_copy_constructible<absl::optional<MoveableNoThrow>>::value);
-  EXPECT_FALSE(std::is_copy_constructible<absl::optional<NonMovable>>::value);
-
-  EXPECT_FALSE(
-      absl::is_trivially_copy_constructible<absl::optional<Copyable>>::value);
-  EXPECT_TRUE(
-      absl::is_trivially_copy_constructible<absl::optional<int>>::value);
-  EXPECT_TRUE(
-      absl::is_trivially_copy_constructible<absl::optional<const int>>::value);
-#if !defined(_MSC_VER) && !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-  // See defect report "Trivial copy/move constructor for class with volatile
-  // member" at
-  // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2094
-  // A class with non-static data member of volatile-qualified type should still
-  // have a trivial copy constructor if the data member is trivial.
-  // Also a cv-qualified scalar type should be trivially copyable.
-  EXPECT_TRUE(absl::is_trivially_copy_constructible<
-              absl::optional<volatile int>>::value);
-#endif  // !defined(_MSC_VER) && !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-
-  // constexpr copy constructor for trivially copyable types
-  {
-    constexpr absl::optional<int> o1;
-    constexpr absl::optional<int> o2 = o1;
-    static_assert(!o2, "");
-  }
-  {
-    constexpr absl::optional<int> o1 = 42;
-    constexpr absl::optional<int> o2 = o1;
-    static_assert(o2, "");
-    static_assert(*o2 == 42, "");
-  }
-  {
-    struct TrivialCopyable {
-      constexpr TrivialCopyable() : x(0) {}
-      constexpr explicit TrivialCopyable(int i) : x(i) {}
-      int x;
-    };
-    constexpr absl::optional<TrivialCopyable> o1(42);
-    constexpr absl::optional<TrivialCopyable> o2 = o1;
-    static_assert(o2, "");
-    static_assert((*o2).x == 42, "");
-#ifndef ABSL_GLIBCXX_OPTIONAL_TRIVIALITY_BUG
-    EXPECT_TRUE(absl::is_trivially_copy_constructible<
-                absl::optional<TrivialCopyable>>::value);
-    EXPECT_TRUE(absl::is_trivially_copy_constructible<
-                absl::optional<const TrivialCopyable>>::value);
-#endif
-#if !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-    EXPECT_FALSE(std::is_copy_constructible<
-                 absl::optional<volatile TrivialCopyable>>::value);
-#endif  // !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-  }
-}
-
-TEST(optionalTest, MoveConstructor) {
-  absl::optional<int> empty, opt42 = 42;
-  absl::optional<int> empty_move(std::move(empty));
-  EXPECT_FALSE(empty_move);
-  absl::optional<int> opt42_move(std::move(opt42));
-  EXPECT_TRUE(opt42_move);
-  EXPECT_EQ(42, opt42_move);
-  // test movability
-  EXPECT_TRUE(std::is_move_constructible<absl::optional<int>>::value);
-  EXPECT_TRUE(std::is_move_constructible<absl::optional<Copyable>>::value);
-  EXPECT_TRUE(std::is_move_constructible<absl::optional<MoveableThrow>>::value);
-  EXPECT_TRUE(
-      std::is_move_constructible<absl::optional<MoveableNoThrow>>::value);
-  EXPECT_FALSE(std::is_move_constructible<absl::optional<NonMovable>>::value);
-  // test noexcept
-  EXPECT_TRUE(std::is_nothrow_move_constructible<absl::optional<int>>::value);
-  EXPECT_EQ(
-      absl::default_allocator_is_nothrow::value,
-      std::is_nothrow_move_constructible<absl::optional<MoveableThrow>>::value);
-  EXPECT_TRUE(std::is_nothrow_move_constructible<
-              absl::optional<MoveableNoThrow>>::value);
-}
-
-TEST(optionalTest, Destructor) {
-  struct Trivial {};
-
-  struct NonTrivial {
-    NonTrivial(const NonTrivial&) {}
-    NonTrivial& operator=(const NonTrivial&) { return *this; }
-    ~NonTrivial() {}
-  };
-
-  EXPECT_TRUE(std::is_trivially_destructible<absl::optional<int>>::value);
-  EXPECT_TRUE(std::is_trivially_destructible<absl::optional<Trivial>>::value);
-  EXPECT_FALSE(
-      std::is_trivially_destructible<absl::optional<NonTrivial>>::value);
-}
-
-TEST(optionalTest, InPlaceConstructor) {
-  constexpr absl::optional<ConstexprType> opt0{absl::in_place_t()};
-  static_assert(opt0, "");
-  static_assert((*opt0).x == ConstexprType::kCtorDefault, "");
-  constexpr absl::optional<ConstexprType> opt1{absl::in_place_t(), 1};
-  static_assert(opt1, "");
-  static_assert((*opt1).x == ConstexprType::kCtorInt, "");
-  constexpr absl::optional<ConstexprType> opt2{absl::in_place_t(), {1, 2}};
-  static_assert(opt2, "");
-  static_assert((*opt2).x == ConstexprType::kCtorInitializerList, "");
-
-  EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
-                                      absl::in_place_t>::value));
-  EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
-                                      const absl::in_place_t&>::value));
-  EXPECT_TRUE(
-      (std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
-                             absl::in_place_t, absl::in_place_t>::value));
-
-  EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
-                                      absl::in_place_t>::value));
-  EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
-                                      absl::in_place_t&&>::value));
-}
-
-// template<U=T> optional(U&&);
-TEST(optionalTest, ValueConstructor) {
-  constexpr absl::optional<int> opt0(0);
-  static_assert(opt0, "");
-  static_assert(*opt0 == 0, "");
-  EXPECT_TRUE((std::is_convertible<int, absl::optional<int>>::value));
-  // Copy initialization ( = "abc") won't work due to optional(optional&&)
-  // is not constexpr. Use list initialization instead. This invokes
-  // absl::optional<ConstexprType>::absl::optional<U>(U&&), with U = const char
-  // (&) [4], which direct-initializes the ConstexprType value held by the
-  // optional via ConstexprType::ConstexprType(const char*).
-  constexpr absl::optional<ConstexprType> opt1 = {"abc"};
-  static_assert(opt1, "");
-  static_assert(ConstexprType::kCtorConstChar == (*opt1).x, "");
-  EXPECT_TRUE(
-      (std::is_convertible<const char*, absl::optional<ConstexprType>>::value));
-  // direct initialization
-  constexpr absl::optional<ConstexprType> opt2{2};
-  static_assert(opt2, "");
-  static_assert(ConstexprType::kCtorInt == (*opt2).x, "");
-  EXPECT_FALSE(
-      (std::is_convertible<int, absl::optional<ConstexprType>>::value));
-
-  // this invokes absl::optional<int>::optional(int&&)
-  // NOTE: this has different behavior than assignment, e.g.
-  // "opt3 = {};" clears the optional rather than setting the value to 0
-  // According to C++17 standard N4659 [over.ics.list] 16.3.3.1.5, (9.2)- "if
-  // the initializer list has no elements, the implicit conversion is the
-  // identity conversion", so `optional(int&&)` should be a better match than
-  // `optional(optional&&)` which is a user-defined conversion.
-  // Note: GCC 7 has a bug with this overload selection when compiled with
-  // `-std=c++17`.
-#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 7 && \
-    __cplusplus == 201703L
-#define ABSL_GCC7_OVER_ICS_LIST_BUG 1
-#endif
-#ifndef ABSL_GCC7_OVER_ICS_LIST_BUG
-  constexpr absl::optional<int> opt3({});
-  static_assert(opt3, "");
-  static_assert(*opt3 == 0, "");
-#endif
-
-  // this invokes the move constructor with a default constructed optional
-  // because non-template function is a better match than template function.
-  absl::optional<ConstexprType> opt4({});
-  EXPECT_FALSE(opt4);
-}
-
-struct Implicit {};
-
-struct Explicit {};
-
-struct Convert {
-  Convert(const Implicit&)  // NOLINT(runtime/explicit)
-      : implicit(true), move(false) {}
-  Convert(Implicit&&)  // NOLINT(runtime/explicit)
-      : implicit(true), move(true) {}
-  explicit Convert(const Explicit&) : implicit(false), move(false) {}
-  explicit Convert(Explicit&&) : implicit(false), move(true) {}
-
-  bool implicit;
-  bool move;
-};
-
-struct ConvertFromOptional {
-  ConvertFromOptional(const Implicit&)  // NOLINT(runtime/explicit)
-      : implicit(true), move(false), from_optional(false) {}
-  ConvertFromOptional(Implicit&&)  // NOLINT(runtime/explicit)
-      : implicit(true), move(true), from_optional(false) {}
-  ConvertFromOptional(
-      const absl::optional<Implicit>&)  // NOLINT(runtime/explicit)
-      : implicit(true), move(false), from_optional(true) {}
-  ConvertFromOptional(absl::optional<Implicit>&&)  // NOLINT(runtime/explicit)
-      : implicit(true), move(true), from_optional(true) {}
-  explicit ConvertFromOptional(const Explicit&)
-      : implicit(false), move(false), from_optional(false) {}
-  explicit ConvertFromOptional(Explicit&&)
-      : implicit(false), move(true), from_optional(false) {}
-  explicit ConvertFromOptional(const absl::optional<Explicit>&)
-      : implicit(false), move(false), from_optional(true) {}
-  explicit ConvertFromOptional(absl::optional<Explicit>&&)
-      : implicit(false), move(true), from_optional(true) {}
-
-  bool implicit;
-  bool move;
-  bool from_optional;
-};
-
-TEST(optionalTest, ConvertingConstructor) {
-  absl::optional<Implicit> i_empty;
-  absl::optional<Implicit> i(absl::in_place);
-  absl::optional<Explicit> e_empty;
-  absl::optional<Explicit> e(absl::in_place);
-  {
-    // implicitly constructing absl::optional<Convert> from
-    // absl::optional<Implicit>
-    absl::optional<Convert> empty = i_empty;
-    EXPECT_FALSE(empty);
-    absl::optional<Convert> opt_copy = i;
-    EXPECT_TRUE(opt_copy);
-    EXPECT_TRUE(opt_copy->implicit);
-    EXPECT_FALSE(opt_copy->move);
-    absl::optional<Convert> opt_move = absl::optional<Implicit>(absl::in_place);
-    EXPECT_TRUE(opt_move);
-    EXPECT_TRUE(opt_move->implicit);
-    EXPECT_TRUE(opt_move->move);
-  }
-  {
-    // explicitly constructing absl::optional<Convert> from
-    // absl::optional<Explicit>
-    absl::optional<Convert> empty(e_empty);
-    EXPECT_FALSE(empty);
-    absl::optional<Convert> opt_copy(e);
-    EXPECT_TRUE(opt_copy);
-    EXPECT_FALSE(opt_copy->implicit);
-    EXPECT_FALSE(opt_copy->move);
-    EXPECT_FALSE((std::is_convertible<const absl::optional<Explicit>&,
-                                      absl::optional<Convert>>::value));
-    absl::optional<Convert> opt_move{absl::optional<Explicit>(absl::in_place)};
-    EXPECT_TRUE(opt_move);
-    EXPECT_FALSE(opt_move->implicit);
-    EXPECT_TRUE(opt_move->move);
-    EXPECT_FALSE((std::is_convertible<absl::optional<Explicit>&&,
-                                      absl::optional<Convert>>::value));
-  }
-  {
-    // implicitly constructing absl::optional<ConvertFromOptional> from
-    // absl::optional<Implicit> via
-    // ConvertFromOptional(absl::optional<Implicit>&&) check that
-    // ConvertFromOptional(Implicit&&) is NOT called
-    static_assert(
-        std::is_convertible<absl::optional<Implicit>,
-                            absl::optional<ConvertFromOptional>>::value,
-        "");
-    absl::optional<ConvertFromOptional> opt0 = i_empty;
-    EXPECT_TRUE(opt0);
-    EXPECT_TRUE(opt0->implicit);
-    EXPECT_FALSE(opt0->move);
-    EXPECT_TRUE(opt0->from_optional);
-    absl::optional<ConvertFromOptional> opt1 = absl::optional<Implicit>();
-    EXPECT_TRUE(opt1);
-    EXPECT_TRUE(opt1->implicit);
-    EXPECT_TRUE(opt1->move);
-    EXPECT_TRUE(opt1->from_optional);
-  }
-  {
-    // implicitly constructing absl::optional<ConvertFromOptional> from
-    // absl::optional<Explicit> via
-    // ConvertFromOptional(absl::optional<Explicit>&&) check that
-    // ConvertFromOptional(Explicit&&) is NOT called
-    absl::optional<ConvertFromOptional> opt0(e_empty);
-    EXPECT_TRUE(opt0);
-    EXPECT_FALSE(opt0->implicit);
-    EXPECT_FALSE(opt0->move);
-    EXPECT_TRUE(opt0->from_optional);
-    EXPECT_FALSE(
-        (std::is_convertible<const absl::optional<Explicit>&,
-                             absl::optional<ConvertFromOptional>>::value));
-    absl::optional<ConvertFromOptional> opt1{absl::optional<Explicit>()};
-    EXPECT_TRUE(opt1);
-    EXPECT_FALSE(opt1->implicit);
-    EXPECT_TRUE(opt1->move);
-    EXPECT_TRUE(opt1->from_optional);
-    EXPECT_FALSE(
-        (std::is_convertible<absl::optional<Explicit>&&,
-                             absl::optional<ConvertFromOptional>>::value));
-  }
-}
-
-TEST(optionalTest, StructorBasic) {
-  StructorListener listener;
-  Listenable::listener = &listener;
-  {
-    absl::optional<Listenable> empty;
-    EXPECT_FALSE(empty);
-    absl::optional<Listenable> opt0(absl::in_place);
-    EXPECT_TRUE(opt0);
-    absl::optional<Listenable> opt1(absl::in_place, 1);
-    EXPECT_TRUE(opt1);
-    absl::optional<Listenable> opt2(absl::in_place, 1, 2);
-    EXPECT_TRUE(opt2);
-  }
-  EXPECT_EQ(1, listener.construct0);
-  EXPECT_EQ(1, listener.construct1);
-  EXPECT_EQ(1, listener.construct2);
-  EXPECT_EQ(3, listener.destruct);
-}
-
-TEST(optionalTest, CopyMoveStructor) {
-  StructorListener listener;
-  Listenable::listener = &listener;
-  absl::optional<Listenable> original(absl::in_place);
-  EXPECT_EQ(1, listener.construct0);
-  EXPECT_EQ(0, listener.copy);
-  EXPECT_EQ(0, listener.move);
-  absl::optional<Listenable> copy(original);
-  EXPECT_EQ(1, listener.construct0);
-  EXPECT_EQ(1, listener.copy);
-  EXPECT_EQ(0, listener.move);
-  absl::optional<Listenable> move(std::move(original));
-  EXPECT_EQ(1, listener.construct0);
-  EXPECT_EQ(1, listener.copy);
-  EXPECT_EQ(1, listener.move);
-}
-
-TEST(optionalTest, ListInit) {
-  StructorListener listener;
-  Listenable::listener = &listener;
-  absl::optional<Listenable> listinit1(absl::in_place, {1});
-  absl::optional<Listenable> listinit2(absl::in_place, {1, 2});
-  EXPECT_EQ(2, listener.listinit);
-}
-
-TEST(optionalTest, AssignFromNullopt) {
-  absl::optional<int> opt(1);
-  opt = absl::nullopt;
-  EXPECT_FALSE(opt);
-
-  StructorListener listener;
-  Listenable::listener = &listener;
-  absl::optional<Listenable> opt1(absl::in_place);
-  opt1 = absl::nullopt;
-  EXPECT_FALSE(opt1);
-  EXPECT_EQ(1, listener.construct0);
-  EXPECT_EQ(1, listener.destruct);
-
-  EXPECT_TRUE((
-      std::is_nothrow_assignable<absl::optional<int>, absl::nullopt_t>::value));
-  EXPECT_TRUE((std::is_nothrow_assignable<absl::optional<Listenable>,
-                                          absl::nullopt_t>::value));
-}
-
-TEST(optionalTest, CopyAssignment) {
-  const absl::optional<int> empty, opt1 = 1, opt2 = 2;
-  absl::optional<int> empty_to_opt1, opt1_to_opt2, opt2_to_empty;
-
-  EXPECT_FALSE(empty_to_opt1);
-  empty_to_opt1 = empty;
-  EXPECT_FALSE(empty_to_opt1);
-  empty_to_opt1 = opt1;
-  EXPECT_TRUE(empty_to_opt1);
-  EXPECT_EQ(1, empty_to_opt1.value());
-
-  EXPECT_FALSE(opt1_to_opt2);
-  opt1_to_opt2 = opt1;
-  EXPECT_TRUE(opt1_to_opt2);
-  EXPECT_EQ(1, opt1_to_opt2.value());
-  opt1_to_opt2 = opt2;
-  EXPECT_TRUE(opt1_to_opt2);
-  EXPECT_EQ(2, opt1_to_opt2.value());
-
-  EXPECT_FALSE(opt2_to_empty);
-  opt2_to_empty = opt2;
-  EXPECT_TRUE(opt2_to_empty);
-  EXPECT_EQ(2, opt2_to_empty.value());
-  opt2_to_empty = empty;
-  EXPECT_FALSE(opt2_to_empty);
-
-  EXPECT_FALSE(absl::is_copy_assignable<absl::optional<const int>>::value);
-  EXPECT_TRUE(absl::is_copy_assignable<absl::optional<Copyable>>::value);
-  EXPECT_FALSE(absl::is_copy_assignable<absl::optional<MoveableThrow>>::value);
-  EXPECT_FALSE(
-      absl::is_copy_assignable<absl::optional<MoveableNoThrow>>::value);
-  EXPECT_FALSE(absl::is_copy_assignable<absl::optional<NonMovable>>::value);
-
-  EXPECT_TRUE(absl::is_trivially_copy_assignable<int>::value);
-  EXPECT_TRUE(absl::is_trivially_copy_assignable<volatile int>::value);
-
-  struct Trivial {
-    int i;
-  };
-  struct NonTrivial {
-    NonTrivial& operator=(const NonTrivial&) { return *this; }
-    int i;
-  };
-
-  EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial>::value);
-  EXPECT_FALSE(absl::is_copy_assignable<const Trivial>::value);
-  EXPECT_FALSE(absl::is_copy_assignable<volatile Trivial>::value);
-  EXPECT_TRUE(absl::is_copy_assignable<NonTrivial>::value);
-  EXPECT_FALSE(absl::is_trivially_copy_assignable<NonTrivial>::value);
-
-#if !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-  {
-    StructorListener listener;
-    Listenable::listener = &listener;
-
-    absl::optional<volatile Listenable> empty, set(absl::in_place);
-    EXPECT_EQ(1, listener.construct0);
-    absl::optional<volatile Listenable> empty_to_empty, empty_to_set,
-        set_to_empty(absl::in_place), set_to_set(absl::in_place);
-    EXPECT_EQ(3, listener.construct0);
-    empty_to_empty = empty;  // no effect
-    empty_to_set = set;      // copy construct
-    set_to_empty = empty;    // destruct
-    set_to_set = set;        // copy assign
-    EXPECT_EQ(1, listener.volatile_copy);
-    EXPECT_EQ(0, listener.volatile_move);
-    EXPECT_EQ(1, listener.destruct);
-    EXPECT_EQ(1, listener.volatile_copy_assign);
-  }
-#endif  // !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-}
-
-TEST(optionalTest, MoveAssignment) {
-  {
-    StructorListener listener;
-    Listenable::listener = &listener;
-
-    absl::optional<Listenable> empty1, empty2, set1(absl::in_place),
-        set2(absl::in_place);
-    EXPECT_EQ(2, listener.construct0);
-    absl::optional<Listenable> empty_to_empty, empty_to_set,
-        set_to_empty(absl::in_place), set_to_set(absl::in_place);
-    EXPECT_EQ(4, listener.construct0);
-    empty_to_empty = std::move(empty1);
-    empty_to_set = std::move(set1);
-    set_to_empty = std::move(empty2);
-    set_to_set = std::move(set2);
-    EXPECT_EQ(0, listener.copy);
-    EXPECT_EQ(1, listener.move);
-    EXPECT_EQ(1, listener.destruct);
-    EXPECT_EQ(1, listener.move_assign);
-  }
-#if !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-  {
-    StructorListener listener;
-    Listenable::listener = &listener;
-
-    absl::optional<volatile Listenable> empty1, empty2, set1(absl::in_place),
-        set2(absl::in_place);
-    EXPECT_EQ(2, listener.construct0);
-    absl::optional<volatile Listenable> empty_to_empty, empty_to_set,
-        set_to_empty(absl::in_place), set_to_set(absl::in_place);
-    EXPECT_EQ(4, listener.construct0);
-    empty_to_empty = std::move(empty1);  // no effect
-    empty_to_set = std::move(set1);      // move construct
-    set_to_empty = std::move(empty2);    // destruct
-    set_to_set = std::move(set2);        // move assign
-    EXPECT_EQ(0, listener.volatile_copy);
-    EXPECT_EQ(1, listener.volatile_move);
-    EXPECT_EQ(1, listener.destruct);
-    EXPECT_EQ(1, listener.volatile_move_assign);
-  }
-#endif  // !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-  EXPECT_FALSE(absl::is_move_assignable<absl::optional<const int>>::value);
-  EXPECT_TRUE(absl::is_move_assignable<absl::optional<Copyable>>::value);
-  EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableThrow>>::value);
-  EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableNoThrow>>::value);
-  EXPECT_FALSE(absl::is_move_assignable<absl::optional<NonMovable>>::value);
-
-  EXPECT_FALSE(
-      std::is_nothrow_move_assignable<absl::optional<MoveableThrow>>::value);
-  EXPECT_TRUE(
-      std::is_nothrow_move_assignable<absl::optional<MoveableNoThrow>>::value);
-}
-
-struct NoConvertToOptional {
-  // disable implicit conversion from const NoConvertToOptional&
-  // to absl::optional<NoConvertToOptional>.
-  NoConvertToOptional(const NoConvertToOptional&) = delete;
-};
-
-struct CopyConvert {
-  CopyConvert(const NoConvertToOptional&);
-  CopyConvert& operator=(const CopyConvert&) = delete;
-  CopyConvert& operator=(const NoConvertToOptional&);
-};
-
-struct CopyConvertFromOptional {
-  CopyConvertFromOptional(const NoConvertToOptional&);
-  CopyConvertFromOptional(const absl::optional<NoConvertToOptional>&);
-  CopyConvertFromOptional& operator=(const CopyConvertFromOptional&) = delete;
-  CopyConvertFromOptional& operator=(const NoConvertToOptional&);
-  CopyConvertFromOptional& operator=(
-      const absl::optional<NoConvertToOptional>&);
-};
-
-struct MoveConvert {
-  MoveConvert(NoConvertToOptional&&);
-  MoveConvert& operator=(const MoveConvert&) = delete;
-  MoveConvert& operator=(NoConvertToOptional&&);
-};
-
-struct MoveConvertFromOptional {
-  MoveConvertFromOptional(NoConvertToOptional&&);
-  MoveConvertFromOptional(absl::optional<NoConvertToOptional>&&);
-  MoveConvertFromOptional& operator=(const MoveConvertFromOptional&) = delete;
-  MoveConvertFromOptional& operator=(NoConvertToOptional&&);
-  MoveConvertFromOptional& operator=(absl::optional<NoConvertToOptional>&&);
-};
-
-// template <typename U = T> absl::optional<T>& operator=(U&& v);
-TEST(optionalTest, ValueAssignment) {
-  absl::optional<int> opt;
-  EXPECT_FALSE(opt);
-  opt = 42;
-  EXPECT_TRUE(opt);
-  EXPECT_EQ(42, opt.value());
-  opt = absl::nullopt;
-  EXPECT_FALSE(opt);
-  opt = 42;
-  EXPECT_TRUE(opt);
-  EXPECT_EQ(42, opt.value());
-  opt = 43;
-  EXPECT_TRUE(opt);
-  EXPECT_EQ(43, opt.value());
-  opt = {};  // this should clear optional
-  EXPECT_FALSE(opt);
-
-  opt = {44};
-  EXPECT_TRUE(opt);
-  EXPECT_EQ(44, opt.value());
-
-  // U = const NoConvertToOptional&
-  EXPECT_TRUE((std::is_assignable<absl::optional<CopyConvert>&,
-                                  const NoConvertToOptional&>::value));
-  // U = const absl::optional<NoConvertToOptional>&
-  EXPECT_TRUE((std::is_assignable<absl::optional<CopyConvertFromOptional>&,
-                                  const NoConvertToOptional&>::value));
-  // U = const NoConvertToOptional& triggers SFINAE because
-  // std::is_constructible_v<MoveConvert, const NoConvertToOptional&> is false
-  EXPECT_FALSE((std::is_assignable<absl::optional<MoveConvert>&,
-                                   const NoConvertToOptional&>::value));
-  // U = NoConvertToOptional
-  EXPECT_TRUE((std::is_assignable<absl::optional<MoveConvert>&,
-                                  NoConvertToOptional&&>::value));
-  // U = const NoConvertToOptional& triggers SFINAE because
-  // std::is_constructible_v<MoveConvertFromOptional, const
-  // NoConvertToOptional&> is false
-  EXPECT_FALSE((std::is_assignable<absl::optional<MoveConvertFromOptional>&,
-                                   const NoConvertToOptional&>::value));
-  // U = NoConvertToOptional
-  EXPECT_TRUE((std::is_assignable<absl::optional<MoveConvertFromOptional>&,
-                                  NoConvertToOptional&&>::value));
-  // U = const absl::optional<NoConvertToOptional>&
-  EXPECT_TRUE(
-      (std::is_assignable<absl::optional<CopyConvertFromOptional>&,
-                          const absl::optional<NoConvertToOptional>&>::value));
-  // U = absl::optional<NoConvertToOptional>
-  EXPECT_TRUE(
-      (std::is_assignable<absl::optional<MoveConvertFromOptional>&,
-                          absl::optional<NoConvertToOptional>&&>::value));
-}
-
-// template <typename U> absl::optional<T>& operator=(const absl::optional<U>&
-// rhs); template <typename U> absl::optional<T>& operator=(absl::optional<U>&&
-// rhs);
-TEST(optionalTest, ConvertingAssignment) {
-  absl::optional<int> opt_i;
-  absl::optional<char> opt_c('c');
-  opt_i = opt_c;
-  EXPECT_TRUE(opt_i);
-  EXPECT_EQ(*opt_c, *opt_i);
-  opt_i = absl::optional<char>();
-  EXPECT_FALSE(opt_i);
-  opt_i = absl::optional<char>('d');
-  EXPECT_TRUE(opt_i);
-  EXPECT_EQ('d', *opt_i);
-
-  absl::optional<std::string> opt_str;
-  absl::optional<const char*> opt_cstr("abc");
-  opt_str = opt_cstr;
-  EXPECT_TRUE(opt_str);
-  EXPECT_EQ(std::string("abc"), *opt_str);
-  opt_str = absl::optional<const char*>();
-  EXPECT_FALSE(opt_str);
-  opt_str = absl::optional<const char*>("def");
-  EXPECT_TRUE(opt_str);
-  EXPECT_EQ(std::string("def"), *opt_str);
-
-  // operator=(const absl::optional<U>&) with U = NoConvertToOptional
-  EXPECT_TRUE(
-      (std::is_assignable<absl::optional<CopyConvert>,
-                          const absl::optional<NoConvertToOptional>&>::value));
-  // operator=(const absl::optional<U>&) with U = NoConvertToOptional
-  // triggers SFINAE because
-  // std::is_constructible_v<MoveConvert, const NoConvertToOptional&> is false
-  EXPECT_FALSE(
-      (std::is_assignable<absl::optional<MoveConvert>&,
-                          const absl::optional<NoConvertToOptional>&>::value));
-  // operator=(absl::optional<U>&&) with U = NoConvertToOptional
-  EXPECT_TRUE(
-      (std::is_assignable<absl::optional<MoveConvert>&,
-                          absl::optional<NoConvertToOptional>&&>::value));
-  // operator=(const absl::optional<U>&) with U = NoConvertToOptional triggers
-  // SFINAE because std::is_constructible_v<MoveConvertFromOptional, const
-  // NoConvertToOptional&> is false. operator=(U&&) with U = const
-  // absl::optional<NoConverToOptional>& triggers SFINAE because
-  // std::is_constructible<MoveConvertFromOptional,
-  // absl::optional<NoConvertToOptional>&&> is true.
-  EXPECT_FALSE(
-      (std::is_assignable<absl::optional<MoveConvertFromOptional>&,
-                          const absl::optional<NoConvertToOptional>&>::value));
-}
-
-TEST(optionalTest, ResetAndHasValue) {
-  StructorListener listener;
-  Listenable::listener = &listener;
-  absl::optional<Listenable> opt;
-  EXPECT_FALSE(opt);
-  EXPECT_FALSE(opt.has_value());
-  opt.emplace();
-  EXPECT_TRUE(opt);
-  EXPECT_TRUE(opt.has_value());
-  opt.reset();
-  EXPECT_FALSE(opt);
-  EXPECT_FALSE(opt.has_value());
-  EXPECT_EQ(1, listener.destruct);
-  opt.reset();
-  EXPECT_FALSE(opt);
-  EXPECT_FALSE(opt.has_value());
-
-  constexpr absl::optional<int> empty;
-  static_assert(!empty.has_value(), "");
-  constexpr absl::optional<int> nonempty(1);
-  static_assert(nonempty.has_value(), "");
-}
-
-TEST(optionalTest, Emplace) {
-  StructorListener listener;
-  Listenable::listener = &listener;
-  absl::optional<Listenable> opt;
-  EXPECT_FALSE(opt);
-  opt.emplace(1);
-  EXPECT_TRUE(opt);
-  opt.emplace(1, 2);
-  EXPECT_EQ(1, listener.construct1);
-  EXPECT_EQ(1, listener.construct2);
-  EXPECT_EQ(1, listener.destruct);
-
-  absl::optional<std::string> o;
-  EXPECT_TRUE((std::is_same<std::string&, decltype(o.emplace("abc"))>::value));
-  std::string& ref = o.emplace("abc");
-  EXPECT_EQ(&ref, &o.value());
-}
-
-TEST(optionalTest, ListEmplace) {
-  StructorListener listener;
-  Listenable::listener = &listener;
-  absl::optional<Listenable> opt;
-  EXPECT_FALSE(opt);
-  opt.emplace({1});
-  EXPECT_TRUE(opt);
-  opt.emplace({1, 2});
-  EXPECT_EQ(2, listener.listinit);
-  EXPECT_EQ(1, listener.destruct);
-
-  absl::optional<Listenable> o;
-  EXPECT_TRUE((std::is_same<Listenable&, decltype(o.emplace({1}))>::value));
-  Listenable& ref = o.emplace({1});
-  EXPECT_EQ(&ref, &o.value());
-}
-
-TEST(optionalTest, Swap) {
-  absl::optional<int> opt_empty, opt1 = 1, opt2 = 2;
-  EXPECT_FALSE(opt_empty);
-  EXPECT_TRUE(opt1);
-  EXPECT_EQ(1, opt1.value());
-  EXPECT_TRUE(opt2);
-  EXPECT_EQ(2, opt2.value());
-  swap(opt_empty, opt1);
-  EXPECT_FALSE(opt1);
-  EXPECT_TRUE(opt_empty);
-  EXPECT_EQ(1, opt_empty.value());
-  EXPECT_TRUE(opt2);
-  EXPECT_EQ(2, opt2.value());
-  swap(opt_empty, opt1);
-  EXPECT_FALSE(opt_empty);
-  EXPECT_TRUE(opt1);
-  EXPECT_EQ(1, opt1.value());
-  EXPECT_TRUE(opt2);
-  EXPECT_EQ(2, opt2.value());
-  swap(opt1, opt2);
-  EXPECT_FALSE(opt_empty);
-  EXPECT_TRUE(opt1);
-  EXPECT_EQ(2, opt1.value());
-  EXPECT_TRUE(opt2);
-  EXPECT_EQ(1, opt2.value());
-
-  EXPECT_TRUE(noexcept(opt1.swap(opt2)));
-  EXPECT_TRUE(noexcept(swap(opt1, opt2)));
-}
-
-template <int v>
-struct DeletedOpAddr {
-  int value = v;
-  constexpr DeletedOpAddr() = default;
-  constexpr const DeletedOpAddr<v>* operator&() const = delete;  // NOLINT
-  DeletedOpAddr<v>* operator&() = delete;                        // NOLINT
-};
-
-// The static_assert featuring a constexpr call to operator->() is commented out
-// to document the fact that the current implementation of absl::optional<T>
-// expects such usecases to be malformed and not compile.
-TEST(optionalTest, OperatorAddr) {
-  constexpr int v = -1;
-  {  // constexpr
-    constexpr absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{});
-    static_assert(opt.has_value(), "");
-    // static_assert(opt->value == v, "");
-    static_assert((*opt).value == v, "");
-  }
-  {  // non-constexpr
-    const absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{});
-    EXPECT_TRUE(opt.has_value());
-    EXPECT_TRUE(opt->value == v);
-    EXPECT_TRUE((*opt).value == v);
-  }
-}
-
-TEST(optionalTest, PointerStuff) {
-  absl::optional<std::string> opt(absl::in_place, "foo");
-  EXPECT_EQ("foo", *opt);
-  const auto& opt_const = opt;
-  EXPECT_EQ("foo", *opt_const);
-  EXPECT_EQ(opt->size(), 3u);
-  EXPECT_EQ(opt_const->size(), 3u);
-
-  constexpr absl::optional<ConstexprType> opt1(1);
-  static_assert((*opt1).x == ConstexprType::kCtorInt, "");
-}
-
-TEST(optionalTest, Value) {
-  using O = absl::optional<std::string>;
-  using CO = const absl::optional<std::string>;
-  using OC = absl::optional<const std::string>;
-  O lvalue(absl::in_place, "lvalue");
-  CO clvalue(absl::in_place, "clvalue");
-  OC lvalue_c(absl::in_place, "lvalue_c");
-  EXPECT_EQ("lvalue", lvalue.value());
-  EXPECT_EQ("clvalue", clvalue.value());
-  EXPECT_EQ("lvalue_c", lvalue_c.value());
-  EXPECT_EQ("xvalue", O(absl::in_place, "xvalue").value());
-  EXPECT_EQ("xvalue_c", OC(absl::in_place, "xvalue_c").value());
-  EXPECT_EQ("cxvalue", CO(absl::in_place, "cxvalue").value());
-  EXPECT_EQ("&", TypeQuals(lvalue.value()));
-  EXPECT_EQ("c&", TypeQuals(clvalue.value()));
-  EXPECT_EQ("c&", TypeQuals(lvalue_c.value()));
-  EXPECT_EQ("&&", TypeQuals(O(absl::in_place, "xvalue").value()));
-  EXPECT_EQ("c&&", TypeQuals(CO(absl::in_place, "cxvalue").value()));
-  EXPECT_EQ("c&&", TypeQuals(OC(absl::in_place, "xvalue_c").value()));
-
-#if !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-  // test on volatile type
-  using OV = absl::optional<volatile int>;
-  OV lvalue_v(absl::in_place, 42);
-  EXPECT_EQ(42, lvalue_v.value());
-  EXPECT_EQ(42, OV(42).value());
-  EXPECT_TRUE((std::is_same<volatile int&, decltype(lvalue_v.value())>::value));
-  EXPECT_TRUE((std::is_same<volatile int&&, decltype(OV(42).value())>::value));
-#endif  // !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-
-  // test exception throw on value()
-  absl::optional<int> empty;
-#ifdef ABSL_HAVE_EXCEPTIONS
-  EXPECT_THROW((void)empty.value(), absl::bad_optional_access);
-#else
-  EXPECT_DEATH_IF_SUPPORTED((void)empty.value(), "Bad optional access");
-#endif
-
-  // test constexpr value()
-  constexpr absl::optional<int> o1(1);
-  static_assert(1 == o1.value(), "");  // const &
-#ifndef _MSC_VER
-  using COI = const absl::optional<int>;
-  static_assert(2 == COI(2).value(), "");  // const &&
-#endif
-}
-
-TEST(optionalTest, DerefOperator) {
-  using O = absl::optional<std::string>;
-  using CO = const absl::optional<std::string>;
-  using OC = absl::optional<const std::string>;
-  O lvalue(absl::in_place, "lvalue");
-  CO clvalue(absl::in_place, "clvalue");
-  OC lvalue_c(absl::in_place, "lvalue_c");
-  EXPECT_EQ("lvalue", *lvalue);
-  EXPECT_EQ("clvalue", *clvalue);
-  EXPECT_EQ("lvalue_c", *lvalue_c);
-  EXPECT_EQ("xvalue", *O(absl::in_place, "xvalue"));
-  EXPECT_EQ("xvalue_c", *OC(absl::in_place, "xvalue_c"));
-  EXPECT_EQ("cxvalue", *CO(absl::in_place, "cxvalue"));
-  EXPECT_EQ("&", TypeQuals(*lvalue));
-  EXPECT_EQ("c&", TypeQuals(*clvalue));
-  EXPECT_EQ("&&", TypeQuals(*O(absl::in_place, "xvalue")));
-  EXPECT_EQ("c&&", TypeQuals(*CO(absl::in_place, "cxvalue")));
-  EXPECT_EQ("c&&", TypeQuals(*OC(absl::in_place, "xvalue_c")));
-
-#if !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-  // test on volatile type
-  using OV = absl::optional<volatile int>;
-  OV lvalue_v(absl::in_place, 42);
-  EXPECT_EQ(42, *lvalue_v);
-  EXPECT_EQ(42, *OV(42));
-  EXPECT_TRUE((std::is_same<volatile int&, decltype(*lvalue_v)>::value));
-  EXPECT_TRUE((std::is_same<volatile int&&, decltype(*OV(42))>::value));
-#endif  // !defined(ABSL_VOLATILE_RETURN_TYPES_DEPRECATED)
-
-  constexpr absl::optional<int> opt1(1);
-  static_assert(*opt1 == 1, "");
-#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
-  using COI = const absl::optional<int>;
-  static_assert(*COI(2) == 2, "");
-#endif
-}
-
-TEST(optionalTest, ValueOr) {
-  absl::optional<double> opt_empty, opt_set = 1.2;
-  EXPECT_EQ(42.0, opt_empty.value_or(42));
-  EXPECT_EQ(1.2, opt_set.value_or(42));
-  EXPECT_EQ(42.0, absl::optional<double>().value_or(42));
-  EXPECT_EQ(1.2, absl::optional<double>(1.2).value_or(42));
-
-  constexpr absl::optional<double> copt_empty, copt_set = {1.2};
-  static_assert(42.0 == copt_empty.value_or(42), "");
-  static_assert(1.2 == copt_set.value_or(42), "");
-  using COD = const absl::optional<double>;
-  static_assert(42.0 == COD().value_or(42), "");
-  static_assert(1.2 == COD(1.2).value_or(42), "");
-}
-
-// make_optional cannot be constexpr until C++17
-TEST(optionalTest, make_optional) {
-  auto opt_int = absl::make_optional(42);
-  EXPECT_TRUE((std::is_same<decltype(opt_int), absl::optional<int>>::value));
-  EXPECT_EQ(42, opt_int);
-
-  StructorListener listener;
-  Listenable::listener = &listener;
-
-  absl::optional<Listenable> opt0 = absl::make_optional<Listenable>();
-  EXPECT_EQ(1, listener.construct0);
-  absl::optional<Listenable> opt1 = absl::make_optional<Listenable>(1);
-  EXPECT_EQ(1, listener.construct1);
-  absl::optional<Listenable> opt2 = absl::make_optional<Listenable>(1, 2);
-  EXPECT_EQ(1, listener.construct2);
-  absl::optional<Listenable> opt3 = absl::make_optional<Listenable>({1});
-  absl::optional<Listenable> opt4 = absl::make_optional<Listenable>({1, 2});
-  EXPECT_EQ(2, listener.listinit);
-
-  // Constexpr tests on trivially copyable types
-  // optional<T> has trivial copy/move ctors when T is trivially copyable.
-  // For nontrivial types with constexpr constructors, we need copy elision in
-  // C++17 for make_optional to be constexpr.
-  {
-    constexpr absl::optional<int> c_opt = absl::make_optional(42);
-    static_assert(c_opt.value() == 42, "");
-  }
-  {
-    struct TrivialCopyable {
-      constexpr TrivialCopyable() : x(0) {}
-      constexpr explicit TrivialCopyable(int i) : x(i) {}
-      int x;
-    };
-
-    constexpr TrivialCopyable v;
-    constexpr absl::optional<TrivialCopyable> c_opt0 = absl::make_optional(v);
-    static_assert((*c_opt0).x == 0, "");
-    constexpr absl::optional<TrivialCopyable> c_opt1 =
-        absl::make_optional<TrivialCopyable>();
-    static_assert((*c_opt1).x == 0, "");
-    constexpr absl::optional<TrivialCopyable> c_opt2 =
-        absl::make_optional<TrivialCopyable>(42);
-    static_assert((*c_opt2).x == 42, "");
-  }
-}
-
-template <typename T, typename U>
-void optionalTest_Comparisons_EXPECT_LESS(T x, U y) {
-  EXPECT_FALSE(x == y);
-  EXPECT_TRUE(x != y);
-  EXPECT_TRUE(x < y);
-  EXPECT_FALSE(x > y);
-  EXPECT_TRUE(x <= y);
-  EXPECT_FALSE(x >= y);
-}
-
-template <typename T, typename U>
-void optionalTest_Comparisons_EXPECT_SAME(T x, U y) {
-  EXPECT_TRUE(x == y);
-  EXPECT_FALSE(x != y);
-  EXPECT_FALSE(x < y);
-  EXPECT_FALSE(x > y);
-  EXPECT_TRUE(x <= y);
-  EXPECT_TRUE(x >= y);
-}
-
-template <typename T, typename U>
-void optionalTest_Comparisons_EXPECT_GREATER(T x, U y) {
-  EXPECT_FALSE(x == y);
-  EXPECT_TRUE(x != y);
-  EXPECT_FALSE(x < y);
-  EXPECT_TRUE(x > y);
-  EXPECT_FALSE(x <= y);
-  EXPECT_TRUE(x >= y);
-}
-
-template <typename T, typename U, typename V>
-void TestComparisons() {
-  absl::optional<T> ae, a2{2}, a4{4};
-  absl::optional<U> be, b2{2}, b4{4};
-  V v3 = 3;
-
-  // LHS: absl::nullopt, ae, a2, v3, a4
-  // RHS: absl::nullopt, be, b2, v3, b4
-
-  // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(absl::nullopt,absl::nullopt);
-  optionalTest_Comparisons_EXPECT_SAME(absl::nullopt, be);
-  optionalTest_Comparisons_EXPECT_LESS(absl::nullopt, b2);
-  // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(absl::nullopt,v3);
-  optionalTest_Comparisons_EXPECT_LESS(absl::nullopt, b4);
-
-  optionalTest_Comparisons_EXPECT_SAME(ae, absl::nullopt);
-  optionalTest_Comparisons_EXPECT_SAME(ae, be);
-  optionalTest_Comparisons_EXPECT_LESS(ae, b2);
-  optionalTest_Comparisons_EXPECT_LESS(ae, v3);
-  optionalTest_Comparisons_EXPECT_LESS(ae, b4);
-
-  optionalTest_Comparisons_EXPECT_GREATER(a2, absl::nullopt);
-  optionalTest_Comparisons_EXPECT_GREATER(a2, be);
-  optionalTest_Comparisons_EXPECT_SAME(a2, b2);
-  optionalTest_Comparisons_EXPECT_LESS(a2, v3);
-  optionalTest_Comparisons_EXPECT_LESS(a2, b4);
-
-  // optionalTest_Comparisons_EXPECT_NOT_TO_WORK(v3,absl::nullopt);
-  optionalTest_Comparisons_EXPECT_GREATER(v3, be);
-  optionalTest_Comparisons_EXPECT_GREATER(v3, b2);
-  optionalTest_Comparisons_EXPECT_SAME(v3, v3);
-  optionalTest_Comparisons_EXPECT_LESS(v3, b4);
-
-  optionalTest_Comparisons_EXPECT_GREATER(a4, absl::nullopt);
-  optionalTest_Comparisons_EXPECT_GREATER(a4, be);
-  optionalTest_Comparisons_EXPECT_GREATER(a4, b2);
-  optionalTest_Comparisons_EXPECT_GREATER(a4, v3);
-  optionalTest_Comparisons_EXPECT_SAME(a4, b4);
-}
-
-struct Int1 {
-  Int1() = default;
-  Int1(int i) : i(i) {}  // NOLINT(runtime/explicit)
-  int i;
-};
-
-struct Int2 {
-  Int2() = default;
-  Int2(int i) : i(i) {}  // NOLINT(runtime/explicit)
-  int i;
-};
-
-// comparison between Int1 and Int2
-constexpr bool operator==(const Int1& lhs, const Int2& rhs) {
-  return lhs.i == rhs.i;
-}
-constexpr bool operator!=(const Int1& lhs, const Int2& rhs) {
-  return !(lhs == rhs);
-}
-constexpr bool operator<(const Int1& lhs, const Int2& rhs) {
-  return lhs.i < rhs.i;
-}
-constexpr bool operator<=(const Int1& lhs, const Int2& rhs) {
-  return lhs < rhs || lhs == rhs;
-}
-constexpr bool operator>(const Int1& lhs, const Int2& rhs) {
-  return !(lhs <= rhs);
-}
-constexpr bool operator>=(const Int1& lhs, const Int2& rhs) {
-  return !(lhs < rhs);
-}
-
-TEST(optionalTest, Comparisons) {
-  TestComparisons<int, int, int>();
-  TestComparisons<const int, int, int>();
-  TestComparisons<Int1, int, int>();
-  TestComparisons<int, Int2, int>();
-  TestComparisons<Int1, Int2, int>();
-
-  // compare absl::optional<std::string> with const char*
-  absl::optional<std::string> opt_str = "abc";
-  const char* cstr = "abc";
-  EXPECT_TRUE(opt_str == cstr);
-  // compare absl::optional<std::string> with absl::optional<const char*>
-  absl::optional<const char*> opt_cstr = cstr;
-  EXPECT_TRUE(opt_str == opt_cstr);
-  // compare absl::optional<std::string> with absl::optional<absl::string_view>
-  absl::optional<absl::string_view> e1;
-  absl::optional<std::string> e2;
-  EXPECT_TRUE(e1 == e2);
-}
-
-TEST(optionalTest, SwapRegression) {
-  StructorListener listener;
-  Listenable::listener = &listener;
-
-  {
-    absl::optional<Listenable> a;
-    absl::optional<Listenable> b(absl::in_place);
-    a.swap(b);
-  }
-
-  EXPECT_EQ(1, listener.construct0);
-  EXPECT_EQ(1, listener.move);
-  EXPECT_EQ(2, listener.destruct);
-
-  {
-    absl::optional<Listenable> a(absl::in_place);
-    absl::optional<Listenable> b;
-    a.swap(b);
-  }
-
-  EXPECT_EQ(2, listener.construct0);
-  EXPECT_EQ(2, listener.move);
-  EXPECT_EQ(4, listener.destruct);
-}
-
-TEST(optionalTest, BigStringLeakCheck) {
-  constexpr size_t n = 1 << 16;
-
-  using OS = absl::optional<std::string>;
-
-  OS a;
-  OS b = absl::nullopt;
-  OS c = std::string(n, 'c');
-  std::string sd(n, 'd');
-  OS d = sd;
-  OS e(absl::in_place, n, 'e');
-  OS f;
-  f.emplace(n, 'f');
-
-  OS ca(a);
-  OS cb(b);
-  OS cc(c);
-  OS cd(d);
-  OS ce(e);
-
-  OS oa;
-  OS ob = absl::nullopt;
-  OS oc = std::string(n, 'c');
-  std::string sod(n, 'd');
-  OS od = sod;
-  OS oe(absl::in_place, n, 'e');
-  OS of;
-  of.emplace(n, 'f');
-
-  OS ma(std::move(oa));
-  OS mb(std::move(ob));
-  OS mc(std::move(oc));
-  OS md(std::move(od));
-  OS me(std::move(oe));
-  OS mf(std::move(of));
-
-  OS aa1;
-  OS ab1 = absl::nullopt;
-  OS ac1 = std::string(n, 'c');
-  std::string sad1(n, 'd');
-  OS ad1 = sad1;
-  OS ae1(absl::in_place, n, 'e');
-  OS af1;
-  af1.emplace(n, 'f');
-
-  OS aa2;
-  OS ab2 = absl::nullopt;
-  OS ac2 = std::string(n, 'c');
-  std::string sad2(n, 'd');
-  OS ad2 = sad2;
-  OS ae2(absl::in_place, n, 'e');
-  OS af2;
-  af2.emplace(n, 'f');
-
-  aa1 = af2;
-  ab1 = ae2;
-  ac1 = ad2;
-  ad1 = ac2;
-  ae1 = ab2;
-  af1 = aa2;
-
-  OS aa3;
-  OS ab3 = absl::nullopt;
-  OS ac3 = std::string(n, 'c');
-  std::string sad3(n, 'd');
-  OS ad3 = sad3;
-  OS ae3(absl::in_place, n, 'e');
-  OS af3;
-  af3.emplace(n, 'f');
-
-  aa3 = absl::nullopt;
-  ab3 = absl::nullopt;
-  ac3 = absl::nullopt;
-  ad3 = absl::nullopt;
-  ae3 = absl::nullopt;
-  af3 = absl::nullopt;
-
-  OS aa4;
-  OS ab4 = absl::nullopt;
-  OS ac4 = std::string(n, 'c');
-  std::string sad4(n, 'd');
-  OS ad4 = sad4;
-  OS ae4(absl::in_place, n, 'e');
-  OS af4;
-  af4.emplace(n, 'f');
-
-  aa4 = OS(absl::in_place, n, 'a');
-  ab4 = OS(absl::in_place, n, 'b');
-  ac4 = OS(absl::in_place, n, 'c');
-  ad4 = OS(absl::in_place, n, 'd');
-  ae4 = OS(absl::in_place, n, 'e');
-  af4 = OS(absl::in_place, n, 'f');
-
-  OS aa5;
-  OS ab5 = absl::nullopt;
-  OS ac5 = std::string(n, 'c');
-  std::string sad5(n, 'd');
-  OS ad5 = sad5;
-  OS ae5(absl::in_place, n, 'e');
-  OS af5;
-  af5.emplace(n, 'f');
-
-  std::string saa5(n, 'a');
-  std::string sab5(n, 'a');
-  std::string sac5(n, 'a');
-  std::string sad52(n, 'a');
-  std::string sae5(n, 'a');
-  std::string saf5(n, 'a');
-
-  aa5 = saa5;
-  ab5 = sab5;
-  ac5 = sac5;
-  ad5 = sad52;
-  ae5 = sae5;
-  af5 = saf5;
-
-  OS aa6;
-  OS ab6 = absl::nullopt;
-  OS ac6 = std::string(n, 'c');
-  std::string sad6(n, 'd');
-  OS ad6 = sad6;
-  OS ae6(absl::in_place, n, 'e');
-  OS af6;
-  af6.emplace(n, 'f');
-
-  aa6 = std::string(n, 'a');
-  ab6 = std::string(n, 'b');
-  ac6 = std::string(n, 'c');
-  ad6 = std::string(n, 'd');
-  ae6 = std::string(n, 'e');
-  af6 = std::string(n, 'f');
-
-  OS aa7;
-  OS ab7 = absl::nullopt;
-  OS ac7 = std::string(n, 'c');
-  std::string sad7(n, 'd');
-  OS ad7 = sad7;
-  OS ae7(absl::in_place, n, 'e');
-  OS af7;
-  af7.emplace(n, 'f');
-
-  aa7.emplace(n, 'A');
-  ab7.emplace(n, 'B');
-  ac7.emplace(n, 'C');
-  ad7.emplace(n, 'D');
-  ae7.emplace(n, 'E');
-  af7.emplace(n, 'F');
-}
-
-TEST(optionalTest, MoveAssignRegression) {
-  StructorListener listener;
-  Listenable::listener = &listener;
-
-  {
-    absl::optional<Listenable> a;
-    Listenable b;
-    a = std::move(b);
-  }
-
-  EXPECT_EQ(1, listener.construct0);
-  EXPECT_EQ(1, listener.move);
-  EXPECT_EQ(2, listener.destruct);
-}
-
-TEST(optionalTest, ValueType) {
-  EXPECT_TRUE((std::is_same<absl::optional<int>::value_type, int>::value));
-  EXPECT_TRUE((std::is_same<absl::optional<std::string>::value_type,
-                            std::string>::value));
-  EXPECT_FALSE(
-      (std::is_same<absl::optional<int>::value_type, absl::nullopt_t>::value));
-}
-
-template <typename T>
-struct is_hash_enabled_for {
-  template <typename U, typename = decltype(std::hash<U>()(std::declval<U>()))>
-  static std::true_type test(int);
-
-  template <typename U>
-  static std::false_type test(...);
-
-  static constexpr bool value = decltype(test<T>(0))::value;
-};
-
-TEST(optionalTest, Hash) {
-  std::hash<absl::optional<int>> hash;
-  std::set<size_t> hashcodes;
-  hashcodes.insert(hash(absl::nullopt));
-  for (int i = 0; i < 100; ++i) {
-    hashcodes.insert(hash(i));
-  }
-  EXPECT_GT(hashcodes.size(), 90u);
-
-  static_assert(is_hash_enabled_for<absl::optional<int>>::value, "");
-  static_assert(is_hash_enabled_for<absl::optional<Hashable>>::value, "");
-  static_assert(
-      absl::type_traits_internal::IsHashable<absl::optional<int>>::value, "");
-  static_assert(
-      absl::type_traits_internal::IsHashable<absl::optional<Hashable>>::value,
-      "");
-  absl::type_traits_internal::AssertHashEnabled<absl::optional<int>>();
-  absl::type_traits_internal::AssertHashEnabled<absl::optional<Hashable>>();
-
-#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
-  static_assert(!is_hash_enabled_for<absl::optional<NonHashable>>::value, "");
-  static_assert(!absl::type_traits_internal::IsHashable<
-                    absl::optional<NonHashable>>::value,
-                "");
-#endif
-
-  // libstdc++ std::optional is missing remove_const_t, i.e. it's using
-  // std::hash<T> rather than std::hash<std::remove_const_t<T>>.
-  // Reference: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82262
-#ifndef __GLIBCXX__
-  static_assert(is_hash_enabled_for<absl::optional<const int>>::value, "");
-  static_assert(is_hash_enabled_for<absl::optional<const Hashable>>::value, "");
-  std::hash<absl::optional<const int>> c_hash;
-  for (int i = 0; i < 100; ++i) {
-    EXPECT_EQ(hash(i), c_hash(i));
-  }
-#endif
-}
-
-struct MoveMeNoThrow {
-  MoveMeNoThrow() : x(0) {}
-  [[noreturn]] MoveMeNoThrow(const MoveMeNoThrow& other) : x(other.x) {
-    LOG(FATAL) << "Should not be called.";
-  }
-  MoveMeNoThrow(MoveMeNoThrow&& other) noexcept : x(other.x) {}
-  int x;
-};
-
-struct MoveMeThrow {
-  MoveMeThrow() : x(0) {}
-  MoveMeThrow(const MoveMeThrow& other) : x(other.x) {}
-  MoveMeThrow(MoveMeThrow&& other) : x(other.x) {}
-  int x;
-};
-
-TEST(optionalTest, NoExcept) {
-  static_assert(
-      std::is_nothrow_move_constructible<absl::optional<MoveMeNoThrow>>::value,
-      "");
-  static_assert(absl::default_allocator_is_nothrow::value ==
-                    std::is_nothrow_move_constructible<
-                        absl::optional<MoveMeThrow>>::value,
-                "");
-  std::vector<absl::optional<MoveMeNoThrow>> v;
-  for (int i = 0; i < 10; ++i) v.emplace_back();
-}
-
-struct AnyLike {
-  AnyLike(AnyLike&&) = default;
-  AnyLike(const AnyLike&) = default;
-
-  template <typename ValueType,
-            typename T = typename std::decay<ValueType>::type,
-            typename std::enable_if<
-                !absl::disjunction<
-                    std::is_same<AnyLike, T>,
-                    absl::negation<std::is_copy_constructible<T>>>::value,
-                int>::type = 0>
-  AnyLike(ValueType&&) {}  // NOLINT(runtime/explicit)
-
-  AnyLike& operator=(AnyLike&&) = default;
-  AnyLike& operator=(const AnyLike&) = default;
-
-  template <typename ValueType,
-            typename T = typename std::decay<ValueType>::type>
-  typename std::enable_if<
-      absl::conjunction<absl::negation<std::is_same<AnyLike, T>>,
-                        std::is_copy_constructible<T>>::value,
-      AnyLike&>::type
-  operator=(ValueType&& /* rhs */) {
-    return *this;
-  }
-};
-
-TEST(optionalTest, ConstructionConstraints) {
-  EXPECT_TRUE((std::is_constructible<AnyLike, absl::optional<AnyLike>>::value));
-
-  EXPECT_TRUE(
-      (std::is_constructible<AnyLike, const absl::optional<AnyLike>&>::value));
-
-  EXPECT_TRUE((std::is_constructible<absl::optional<AnyLike>, AnyLike>::value));
-  EXPECT_TRUE(
-      (std::is_constructible<absl::optional<AnyLike>, const AnyLike&>::value));
-
-  EXPECT_TRUE((std::is_convertible<absl::optional<AnyLike>, AnyLike>::value));
-
-  EXPECT_TRUE(
-      (std::is_convertible<const absl::optional<AnyLike>&, AnyLike>::value));
-
-  EXPECT_TRUE((std::is_convertible<AnyLike, absl::optional<AnyLike>>::value));
-  EXPECT_TRUE(
-      (std::is_convertible<const AnyLike&, absl::optional<AnyLike>>::value));
-
-  EXPECT_TRUE(std::is_move_constructible<absl::optional<AnyLike>>::value);
-  EXPECT_TRUE(std::is_copy_constructible<absl::optional<AnyLike>>::value);
-}
-
-TEST(optionalTest, AssignmentConstraints) {
-  EXPECT_TRUE((std::is_assignable<AnyLike&, absl::optional<AnyLike>>::value));
-  EXPECT_TRUE(
-      (std::is_assignable<AnyLike&, const absl::optional<AnyLike>&>::value));
-  EXPECT_TRUE((std::is_assignable<absl::optional<AnyLike>&, AnyLike>::value));
-  EXPECT_TRUE(
-      (std::is_assignable<absl::optional<AnyLike>&, const AnyLike&>::value));
-  EXPECT_TRUE(std::is_move_assignable<absl::optional<AnyLike>>::value);
-  EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value);
-}
-
-#if !defined(__EMSCRIPTEN__)
-struct NestedClassBug {
-  struct Inner {
-    bool dummy = false;
-  };
-  absl::optional<Inner> value;
-};
-
-TEST(optionalTest, InPlaceTSFINAEBug) {
-  NestedClassBug b;
-  ((void)b);
-  using Inner = NestedClassBug::Inner;
-
-  EXPECT_TRUE((std::is_default_constructible<Inner>::value));
-  EXPECT_TRUE((std::is_constructible<Inner>::value));
-  EXPECT_TRUE(
-      (std::is_constructible<absl::optional<Inner>, absl::in_place_t>::value));
-
-  absl::optional<Inner> o(absl::in_place);
-  EXPECT_TRUE(o.has_value());
-  o.emplace();
-  EXPECT_TRUE(o.has_value());
-}
-#endif  // !defined(__EMSCRIPTEN__)
-
-}  // namespace
-
-#endif  // #if !defined(ABSL_USES_STD_OPTIONAL)
diff --git a/absl/types/span.h b/absl/types/span.h
index a0f8027..0e46ee6 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -61,17 +61,53 @@
 #include <utility>
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/base/macros.h"
 #include "absl/base/nullability.h"
 #include "absl/base/optimization.h"
-#include "absl/base/port.h"    // TODO(strel): remove this include
+#include "absl/base/port.h"  // TODO(strel): remove this include
+#include "absl/hash/internal/weakly_mixed_integer.h"
 #include "absl/meta/type_traits.h"
 #include "absl/types/internal/span.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
+template <typename T>
+class Span;
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+// Android local modification: some security tests use "#define private public"
+// to access private implementation details. libc++'s <ranges> is currently not
+// compatible with that.
+#if !defined(private)
+
+// If std::ranges is available, mark Span as satisfying the `view` and
+// `borrowed_range` concepts, just like std::span.
+#if !defined(__has_include)
+#define __has_include(header) 0
+#endif
+#if __has_include(<version>)
+#include <version>  // NOLINT(misc-include-cleaner)
+#endif
+#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L
+#include <ranges>  // NOLINT(build/c++20)
+template <typename T>
+ // NOLINTNEXTLINE(build/c++20)
+inline constexpr bool std::ranges::enable_view<absl::Span<T>> = true;
+template <typename T>
+ // NOLINTNEXTLINE(build/c++20)
+inline constexpr bool std::ranges::enable_borrowed_range<absl::Span<T>> = true;
+#endif
+
+#endif // !defined(private)
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
 //------------------------------------------------------------------------------
 // Span
 //------------------------------------------------------------------------------
@@ -151,7 +187,7 @@
 //   int* my_array = new int[10];
 //   MyRoutine(absl::Span<const int>(my_array, 10));
 template <typename T>
-class ABSL_INTERNAL_ATTRIBUTE_VIEW Span {
+class ABSL_ATTRIBUTE_VIEW Span {
  private:
   // Used to determine whether a Span can be constructed from a container of
   // type C.
@@ -173,10 +209,11 @@
  public:
   using element_type = T;
   using value_type = absl::remove_cv_t<T>;
-  // TODO(b/316099902) - pointer should be Nullable<T*>, but this makes it hard
-  // to recognize foreach loops as safe.
-  using pointer = T*;
-  using const_pointer = const T*;
+  // TODO(b/316099902) - pointer should be absl_nullable, but this makes it hard
+  // to recognize foreach loops as safe. absl_nullability_unknown is currently
+  // used to suppress -Wnullability-completeness warnings.
+  using pointer = T* absl_nullability_unknown;
+  using const_pointer = const T* absl_nullability_unknown;
   using reference = T&;
   using const_reference = const T&;
   using iterator = pointer;
@@ -187,15 +224,18 @@
   using difference_type = ptrdiff_t;
   using absl_internal_is_view = std::true_type;
 
+  // NOLINTNEXTLINE
   static const size_type npos = ~(size_type(0));
 
   constexpr Span() noexcept : Span(nullptr, 0) {}
-  constexpr Span(pointer array, size_type length) noexcept
+  constexpr Span(pointer array ABSL_ATTRIBUTE_LIFETIME_BOUND,
+                 size_type length) noexcept
       : ptr_(array), len_(length) {}
 
   // Implicit conversion constructors
   template <size_t N>
-  constexpr Span(T (&a)[N]) noexcept  // NOLINT(runtime/explicit)
+  constexpr Span(T(  // NOLINT(google-explicit-constructor)
+      &a ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) noexcept
       : Span(a, N) {}
 
   // Explicit reference constructor for a mutable `Span<T>` type. Can be
@@ -212,9 +252,8 @@
   template <typename V, typename = EnableIfConvertibleFrom<V>,
             typename = EnableIfValueIsConst<V>,
             typename = span_internal::EnableIfNotIsView<V>>
-  constexpr Span(
-      const V& v
-          ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept  // NOLINT(runtime/explicit)
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr Span(const V& v ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
       : Span(span_internal::GetData(v), v.size()) {}
 
   // Overloads of the above two functions that are only enabled for view types.
@@ -229,7 +268,7 @@
   template <typename V, typename = EnableIfConvertibleFrom<V>,
             typename = EnableIfValueIsConst<V>,
             span_internal::EnableIfIsView<V> = 0>
-  constexpr Span(const V& v) noexcept  // NOLINT(runtime/explicit)
+  constexpr Span(const V& v) noexcept  // NOLINT(google-explicit-constructor)
       : Span(span_internal::GetData(v), v.size()) {}
 
   // Implicit constructor from an initializer list, making it possible to pass a
@@ -300,7 +339,8 @@
   //
   // Returns a reference to the i'th element of this span.
   constexpr reference operator[](size_type i) const noexcept {
-    return ABSL_HARDENING_ASSERT(i < size()), ptr_[i];
+    ABSL_HARDENING_ASSERT(i < size());
+    return ptr_[i];
   }
 
   // Span::at()
@@ -319,7 +359,8 @@
   // Returns a reference to the first element of this span. The span must not
   // be empty.
   constexpr reference front() const noexcept {
-    return ABSL_HARDENING_ASSERT(size() > 0), *data();
+    ABSL_HARDENING_ASSERT(size() > 0);
+    return *data();
   }
 
   // Span::back()
@@ -327,7 +368,8 @@
   // Returns a reference to the last element of this span. The span must not
   // be empty.
   constexpr reference back() const noexcept {
-    return ABSL_HARDENING_ASSERT(size() > 0), *(data() + size() - 1);
+    ABSL_HARDENING_ASSERT(size() > 0);
+    return *(data() + size() - 1);
   }
 
   // Span::begin()
@@ -465,7 +507,7 @@
   template <typename H>
   friend H AbslHashValue(H h, Span v) {
     return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
-                      v.size());
+                      hash_internal::WeaklyMixedInteger{v.size()});
   }
 
  private:
@@ -492,157 +534,165 @@
 
 // operator==
 template <typename T>
-bool operator==(Span<T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, Span<T> b) {
   return span_internal::EqualImpl<Span, const T>(a, b);
 }
 template <typename T>
-bool operator==(Span<const T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<const T> a,
+                                                    Span<T> b) {
   return span_internal::EqualImpl<Span, const T>(a, b);
 }
 template <typename T>
-bool operator==(Span<T> a, Span<const T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a,
+                                                    Span<const T> b) {
   return span_internal::EqualImpl<Span, const T>(a, b);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator==(const U& a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(const U& a, Span<T> b) {
   return span_internal::EqualImpl<Span, const T>(a, b);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator==(Span<T> a, const U& b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, const U& b) {
   return span_internal::EqualImpl<Span, const T>(a, b);
 }
 
 // operator!=
 template <typename T>
-bool operator!=(Span<T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, Span<T> b) {
   return !(a == b);
 }
 template <typename T>
-bool operator!=(Span<const T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<const T> a,
+                                                    Span<T> b) {
   return !(a == b);
 }
 template <typename T>
-bool operator!=(Span<T> a, Span<const T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a,
+                                                    Span<const T> b) {
   return !(a == b);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator!=(const U& a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(const U& a, Span<T> b) {
   return !(a == b);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator!=(Span<T> a, const U& b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, const U& b) {
   return !(a == b);
 }
 
 // operator<
 template <typename T>
-bool operator<(Span<T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<T> b) {
   return span_internal::LessThanImpl<Span, const T>(a, b);
 }
 template <typename T>
-bool operator<(Span<const T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<const T> a, Span<T> b) {
   return span_internal::LessThanImpl<Span, const T>(a, b);
 }
 template <typename T>
-bool operator<(Span<T> a, Span<const T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<const T> b) {
   return span_internal::LessThanImpl<Span, const T>(a, b);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator<(const U& a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(const U& a, Span<T> b) {
   return span_internal::LessThanImpl<Span, const T>(a, b);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator<(Span<T> a, const U& b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, const U& b) {
   return span_internal::LessThanImpl<Span, const T>(a, b);
 }
 
 // operator>
 template <typename T>
-bool operator>(Span<T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<T> b) {
   return b < a;
 }
 template <typename T>
-bool operator>(Span<const T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<const T> a, Span<T> b) {
   return b < a;
 }
 template <typename T>
-bool operator>(Span<T> a, Span<const T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<const T> b) {
   return b < a;
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator>(const U& a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(const U& a, Span<T> b) {
   return b < a;
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator>(Span<T> a, const U& b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, const U& b) {
   return b < a;
 }
 
 // operator<=
 template <typename T>
-bool operator<=(Span<T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, Span<T> b) {
   return !(b < a);
 }
 template <typename T>
-bool operator<=(Span<const T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<const T> a,
+                                                    Span<T> b) {
   return !(b < a);
 }
 template <typename T>
-bool operator<=(Span<T> a, Span<const T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a,
+                                                    Span<const T> b) {
   return !(b < a);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator<=(const U& a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(const U& a, Span<T> b) {
   return !(b < a);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator<=(Span<T> a, const U& b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, const U& b) {
   return !(b < a);
 }
 
 // operator>=
 template <typename T>
-bool operator>=(Span<T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, Span<T> b) {
   return !(a < b);
 }
 template <typename T>
-bool operator>=(Span<const T> a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<const T> a,
+                                                    Span<T> b) {
   return !(a < b);
 }
 template <typename T>
-bool operator>=(Span<T> a, Span<const T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a,
+                                                    Span<const T> b) {
   return !(a < b);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator>=(const U& a, Span<T> b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(const U& a, Span<T> b) {
   return !(a < b);
 }
 template <
     typename T, typename U,
     typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
-bool operator>=(Span<T> a, const U& b) {
+ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, const U& b) {
   return !(a < b);
 }
 
@@ -683,14 +733,14 @@
 //   }
 //
 template <int&... ExplicitArgumentBarrier, typename T>
-constexpr Span<T> MakeSpan(absl::Nullable<T*> ptr, size_t size) noexcept {
+constexpr Span<T> MakeSpan(T* absl_nullable ptr, size_t size) noexcept {
   return Span<T>(ptr, size);
 }
 
 template <int&... ExplicitArgumentBarrier, typename T>
-Span<T> MakeSpan(absl::Nullable<T*> begin, absl::Nullable<T*> end) noexcept {
-  return ABSL_HARDENING_ASSERT(begin <= end),
-         Span<T>(begin, static_cast<size_t>(end - begin));
+Span<T> MakeSpan(T* absl_nullable begin, T* absl_nullable end) noexcept {
+  ABSL_HARDENING_ASSERT(begin <= end);
+  return Span<T>(begin, static_cast<size_t>(end - begin));
 }
 
 template <int&... ExplicitArgumentBarrier, typename C>
@@ -729,15 +779,16 @@
 //   ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 }));
 //
 template <int&... ExplicitArgumentBarrier, typename T>
-constexpr Span<const T> MakeConstSpan(absl::Nullable<T*> ptr,
+constexpr Span<const T> MakeConstSpan(T* absl_nullable ptr,
                                       size_t size) noexcept {
   return Span<const T>(ptr, size);
 }
 
 template <int&... ExplicitArgumentBarrier, typename T>
-Span<const T> MakeConstSpan(absl::Nullable<T*> begin,
-                            absl::Nullable<T*> end) noexcept {
-  return ABSL_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin);
+Span<const T> MakeConstSpan(T* absl_nullable begin,
+                            T* absl_nullable end) noexcept {
+  ABSL_HARDENING_ASSERT(begin <= end);
+  return Span<const T>(begin, end - begin);
 }
 
 template <int&... ExplicitArgumentBarrier, typename C>
diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc
index e24144d..6700b81 100644
--- a/absl/types/span_test.cc
+++ b/absl/types/span_test.cc
@@ -30,6 +30,7 @@
 #include "absl/base/options.h"
 #include "absl/container/fixed_array.h"
 #include "absl/container/inlined_vector.h"
+#include "absl/hash/hash.h"
 #include "absl/hash/hash_testing.h"
 #include "absl/meta/type_traits.h"
 #include "absl/strings/str_cat.h"
@@ -787,9 +788,9 @@
 template <int i>
 struct ConstexprTester {};
 
-#define ABSL_TEST_CONSTEXPR(expr)                       \
-  do {                                                  \
-    ABSL_ATTRIBUTE_UNUSED ConstexprTester<(expr, 1)> t; \
+#define ABSL_TEST_CONSTEXPR(expr)                                          \
+  do {                                                                     \
+    ABSL_ATTRIBUTE_UNUSED ConstexprTester<(static_cast<void>(expr), 1)> t; \
   } while (0)
 
 struct ContainerWithConstexprMethods {
@@ -826,6 +827,41 @@
   ABSL_TEST_CONSTEXPR(span[0]);
 }
 
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+    ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+
+TEST(ConstIntSpan, ConstexprRelOpsTest) {
+  static constexpr int lhs_data[] = {1, 2, 3};
+  static constexpr int rhs_data[] = {1, 2, 3};
+
+  constexpr absl::Span<const int> lhs = absl::MakeConstSpan(lhs_data, 3);
+  constexpr absl::Span<const int> rhs = absl::MakeConstSpan(rhs_data, 3);
+
+  ABSL_TEST_CONSTEXPR(lhs_data == rhs);
+  ABSL_TEST_CONSTEXPR(lhs_data != rhs);
+  ABSL_TEST_CONSTEXPR(lhs_data < rhs);
+  ABSL_TEST_CONSTEXPR(lhs_data <= rhs);
+  ABSL_TEST_CONSTEXPR(lhs_data > rhs);
+  ABSL_TEST_CONSTEXPR(lhs_data >= rhs);
+
+  ABSL_TEST_CONSTEXPR(lhs == rhs);
+  ABSL_TEST_CONSTEXPR(lhs != rhs);
+  ABSL_TEST_CONSTEXPR(lhs < rhs);
+  ABSL_TEST_CONSTEXPR(lhs <= rhs);
+  ABSL_TEST_CONSTEXPR(lhs > rhs);
+  ABSL_TEST_CONSTEXPR(lhs >= rhs);
+
+  ABSL_TEST_CONSTEXPR(lhs == rhs_data);
+  ABSL_TEST_CONSTEXPR(lhs != rhs_data);
+  ABSL_TEST_CONSTEXPR(lhs < rhs_data);
+  ABSL_TEST_CONSTEXPR(lhs <= rhs_data);
+  ABSL_TEST_CONSTEXPR(lhs > rhs_data);
+  ABSL_TEST_CONSTEXPR(lhs >= rhs_data);
+}
+
+#endif  // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) &&
+        //  ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+
 struct BigStruct {
   char bytes[10000];
 };
@@ -850,4 +886,16 @@
        T(array + 1, 2), T(array + 2, 2)}));
 }
 
+// std::vector is implicitly convertible to absl::Span.
+// There are real life cases where clients rely on this consistency in order to
+// implement heterogeneous lookup.
+TEST(Span, HashConsistentWithVectorLike) {
+  EXPECT_EQ(absl::HashOf(absl::Span<const int>({1, 2, 3})),
+            absl::HashOf(std::vector<int>{1, 2, 3}));
+  EXPECT_EQ(absl::HashOf(absl::Span<const int>({1, 2, 3})),
+            absl::HashOf(absl::InlinedVector<int, 2>{1, 2, 3}));
+  EXPECT_EQ(absl::HashOf(absl::Span<const int>({1, 2, 3})),
+            absl::HashOf(absl::FixedArray<int>{1, 2, 3}));
+}
+
 }  // namespace
diff --git a/absl/types/variant.h b/absl/types/variant.h
index 56a7e05..6b36645 100644
--- a/absl/types/variant.h
+++ b/absl/types/variant.h
@@ -16,39 +16,18 @@
 // variant.h
 // -----------------------------------------------------------------------------
 //
-// This header file defines an `absl::variant` type for holding a type-safe
-// value of some prescribed set of types (noted as alternative types), and
-// associated functions for managing variants.
-//
-// The `absl::variant` type is a form of type-safe union. An `absl::variant`
-// should always hold a value of one of its alternative types (except in the
-// "valueless by exception state" -- see below). A default-constructed
-// `absl::variant` will hold the value of its first alternative type, provided
-// it is default-constructible.
-//
-// In exceptional cases due to error, an `absl::variant` can hold no
-// value (known as a "valueless by exception" state), though this is not the
-// norm.
-//
-// As with `absl::optional`, an `absl::variant` -- when it holds a value --
-// allocates a value of that type directly within the `variant` itself; it
-// cannot hold a reference, array, or the type `void`; it can, however, hold a
-// pointer to externally managed memory.
-//
-// `absl::variant` is a C++11 compatible version of the C++17 `std::variant`
-// abstraction and is designed to be a drop-in replacement for code compliant
-// with C++17.
+// Historical note: Abseil once provided an implementation of `absl::variant`
+// as a polyfill for `std::variant` prior to C++17. Now that C++17 is required,
+// `absl::variant` is an alias for `std::variant`.
 
 #ifndef ABSL_TYPES_VARIANT_H_
 #define ABSL_TYPES_VARIANT_H_
 
+#include <variant>
+
 #include "absl/base/config.h"
 #include "absl/utility/utility.h"
 
-#ifdef ABSL_USES_STD_VARIANT
-
-#include <variant>  // IWYU pragma: export
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 using std::bad_variant_access;
@@ -63,765 +42,8 @@
 using std::variant_size;
 using std::variant_size_v;
 using std::visit;
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#else  // ABSL_USES_STD_VARIANT
-
-#include <functional>
-#include <new>
-#include <type_traits>
-#include <utility>
-
-#include "absl/base/macros.h"
-#include "absl/base/port.h"
-#include "absl/meta/type_traits.h"
-#include "absl/types/internal/variant.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// -----------------------------------------------------------------------------
-// absl::variant
-// -----------------------------------------------------------------------------
-//
-// An `absl::variant` type is a form of type-safe union. An `absl::variant` --
-// except in exceptional cases -- always holds a value of one of its alternative
-// types.
-//
-// Example:
-//
-//   // Construct a variant that holds either an integer or a std::string and
-//   // assign it to a std::string.
-//   absl::variant<int, std::string> v = std::string("abc");
-//
-//   // A default-constructed variant will hold a value-initialized value of
-//   // the first alternative type.
-//   auto a = absl::variant<int, std::string>();   // Holds an int of value '0'.
-//
-//   // variants are assignable.
-//
-//   // copy assignment
-//   auto v1 = absl::variant<int, std::string>("abc");
-//   auto v2 = absl::variant<int, std::string>(10);
-//   v2 = v1;  // copy assign
-//
-//   // move assignment
-//   auto v1 = absl::variant<int, std::string>("abc");
-//   v1 = absl::variant<int, std::string>(10);
-//
-//   // assignment through type conversion
-//   a = 128;         // variant contains int
-//   a = "128";       // variant contains std::string
-//
-// An `absl::variant` holding a value of one of its alternative types `T` holds
-// an allocation of `T` directly within the variant itself. An `absl::variant`
-// is not allowed to allocate additional storage, such as dynamic memory, to
-// allocate the contained value. The contained value shall be allocated in a
-// region of the variant storage suitably aligned for all alternative types.
-template <typename... Ts>
-class variant;
-
-// swap()
-//
-// Swaps two `absl::variant` values. This function is equivalent to `v.swap(w)`
-// where `v` and `w` are `absl::variant` types.
-//
-// Note that this function requires all alternative types to be both swappable
-// and move-constructible, because any two variants may refer to either the same
-// type (in which case, they will be swapped) or to two different types (in
-// which case the values will need to be moved).
-//
-template <
-    typename... Ts,
-    absl::enable_if_t<
-        absl::conjunction<std::is_move_constructible<Ts>...,
-                          type_traits_internal::IsSwappable<Ts>...>::value,
-        int> = 0>
-void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
-  v.swap(w);
-}
-
-// variant_size
-//
-// Returns the number of alternative types available for a given `absl::variant`
-// type as a compile-time constant expression. As this is a class template, it
-// is not generally useful for accessing the number of alternative types of
-// any given `absl::variant` instance.
-//
-// Example:
-//
-//   auto a = absl::variant<int, std::string>;
-//   constexpr int num_types =
-//       absl::variant_size<absl::variant<int, std::string>>();
-//
-//   // You can also use the member constant `value`.
-//   constexpr int num_types =
-//       absl::variant_size<absl::variant<int, std::string>>::value;
-//
-//   // `absl::variant_size` is more valuable for use in generic code:
-//   template <typename Variant>
-//   constexpr bool IsVariantMultivalue() {
-//       return absl::variant_size<Variant>() > 1;
-//   }
-//
-// Note that the set of cv-qualified specializations of `variant_size` are
-// provided to ensure that those specializations compile (especially when passed
-// within template logic).
-template <class T>
-struct variant_size;
-
-template <class... Ts>
-struct variant_size<variant<Ts...>>
-    : std::integral_constant<std::size_t, sizeof...(Ts)> {};
-
-// Specialization of `variant_size` for const qualified variants.
-template <class T>
-struct variant_size<const T> : variant_size<T>::type {};
-
-// Specialization of `variant_size` for volatile qualified variants.
-template <class T>
-struct variant_size<volatile T> : variant_size<T>::type {};
-
-// Specialization of `variant_size` for const volatile qualified variants.
-template <class T>
-struct variant_size<const volatile T> : variant_size<T>::type {};
-
-// variant_alternative
-//
-// Returns the alternative type for a given `absl::variant` at the passed
-// index value as a compile-time constant expression. As this is a class
-// template resulting in a type, it is not useful for access of the run-time
-// value of any given `absl::variant` variable.
-//
-// Example:
-//
-//   // The type of the 0th alternative is "int".
-//   using alternative_type_0
-//     = absl::variant_alternative<0, absl::variant<int, std::string>>::type;
-//
-//   static_assert(std::is_same<alternative_type_0, int>::value, "");
-//
-//   // `absl::variant_alternative` is more valuable for use in generic code:
-//   template <typename Variant>
-//   constexpr bool IsFirstElementTrivial() {
-//       return std::is_trivial_v<variant_alternative<0, Variant>::type>;
-//   }
-//
-// Note that the set of cv-qualified specializations of `variant_alternative`
-// are provided to ensure that those specializations compile (especially when
-// passed within template logic).
-template <std::size_t I, class T>
-struct variant_alternative;
-
-template <std::size_t I, class... Types>
-struct variant_alternative<I, variant<Types...>> {
-  using type =
-      variant_internal::VariantAlternativeSfinaeT<I, variant<Types...>>;
-};
-
-// Specialization of `variant_alternative` for const qualified variants.
-template <std::size_t I, class T>
-struct variant_alternative<I, const T> {
-  using type = const typename variant_alternative<I, T>::type;
-};
-
-// Specialization of `variant_alternative` for volatile qualified variants.
-template <std::size_t I, class T>
-struct variant_alternative<I, volatile T> {
-  using type = volatile typename variant_alternative<I, T>::type;
-};
-
-// Specialization of `variant_alternative` for const volatile qualified
-// variants.
-template <std::size_t I, class T>
-struct variant_alternative<I, const volatile T> {
-  using type = const volatile typename variant_alternative<I, T>::type;
-};
-
-// Template type alias for variant_alternative<I, T>::type.
-//
-// Example:
-//
-//   using alternative_type_0
-//     = absl::variant_alternative_t<0, absl::variant<int, std::string>>;
-//   static_assert(std::is_same<alternative_type_0, int>::value, "");
-template <std::size_t I, class T>
-using variant_alternative_t = typename variant_alternative<I, T>::type;
-
-// holds_alternative()
-//
-// Checks whether the given variant currently holds a given alternative type,
-// returning `true` if so.
-//
-// Example:
-//
-//   absl::variant<int, std::string> foo = 42;
-//   if (absl::holds_alternative<int>(foo)) {
-//       std::cout << "The variant holds an integer";
-//   }
-template <class T, class... Types>
-constexpr bool holds_alternative(const variant<Types...>& v) noexcept {
-  static_assert(
-      variant_internal::UnambiguousIndexOfImpl<variant<Types...>, T,
-                                               0>::value != sizeof...(Types),
-      "The type T must occur exactly once in Types...");
-  return v.index() ==
-         variant_internal::UnambiguousIndexOf<variant<Types...>, T>::value;
-}
-
-// get()
-//
-// Returns a reference to the value currently within a given variant, using
-// either a unique alternative type amongst the variant's set of alternative
-// types, or the variant's index value. Attempting to get a variant's value
-// using a type that is not unique within the variant's set of alternative types
-// is a compile-time error. If the index of the alternative being specified is
-// different from the index of the alternative that is currently stored, throws
-// `absl::bad_variant_access`.
-//
-// Example:
-//
-//   auto a = absl::variant<int, std::string>;
-//
-//   // Get the value by type (if unique).
-//   int i = absl::get<int>(a);
-//
-//   auto b = absl::variant<int, int>;
-//
-//   // Getting the value by a type that is not unique is ill-formed.
-//   int j = absl::get<int>(b);     // Compile Error!
-//
-//   // Getting value by index not ambiguous and allowed.
-//   int k = absl::get<1>(b);
-
-// Overload for getting a variant's lvalue by type.
-template <class T, class... Types>
-constexpr T& get(variant<Types...>& v) {  // NOLINT
-  return variant_internal::VariantCoreAccess::CheckedAccess<
-      variant_internal::IndexOf<T, Types...>::value>(v);
-}
-
-// Overload for getting a variant's rvalue by type.
-template <class T, class... Types>
-constexpr T&& get(variant<Types...>&& v) {
-  return variant_internal::VariantCoreAccess::CheckedAccess<
-      variant_internal::IndexOf<T, Types...>::value>(std::move(v));
-}
-
-// Overload for getting a variant's const lvalue by type.
-template <class T, class... Types>
-constexpr const T& get(const variant<Types...>& v) {
-  return variant_internal::VariantCoreAccess::CheckedAccess<
-      variant_internal::IndexOf<T, Types...>::value>(v);
-}
-
-// Overload for getting a variant's const rvalue by type.
-template <class T, class... Types>
-constexpr const T&& get(const variant<Types...>&& v) {
-  return variant_internal::VariantCoreAccess::CheckedAccess<
-      variant_internal::IndexOf<T, Types...>::value>(std::move(v));
-}
-
-// Overload for getting a variant's lvalue by index.
-template <std::size_t I, class... Types>
-constexpr variant_alternative_t<I, variant<Types...>>& get(
-    variant<Types...>& v) {  // NOLINT
-  return variant_internal::VariantCoreAccess::CheckedAccess<I>(v);
-}
-
-// Overload for getting a variant's rvalue by index.
-template <std::size_t I, class... Types>
-constexpr variant_alternative_t<I, variant<Types...>>&& get(
-    variant<Types...>&& v) {
-  return variant_internal::VariantCoreAccess::CheckedAccess<I>(std::move(v));
-}
-
-// Overload for getting a variant's const lvalue by index.
-template <std::size_t I, class... Types>
-constexpr const variant_alternative_t<I, variant<Types...>>& get(
-    const variant<Types...>& v) {
-  return variant_internal::VariantCoreAccess::CheckedAccess<I>(v);
-}
-
-// Overload for getting a variant's const rvalue by index.
-template <std::size_t I, class... Types>
-constexpr const variant_alternative_t<I, variant<Types...>>&& get(
-    const variant<Types...>&& v) {
-  return variant_internal::VariantCoreAccess::CheckedAccess<I>(std::move(v));
-}
-
-// get_if()
-//
-// Returns a pointer to the value currently stored within a given variant, if
-// present, using either a unique alternative type amongst the variant's set of
-// alternative types, or the variant's index value. If such a value does not
-// exist, returns `nullptr`.
-//
-// As with `get`, attempting to get a variant's value using a type that is not
-// unique within the variant's set of alternative types is a compile-time error.
-
-// Overload for getting a pointer to the value stored in the given variant by
-// index.
-template <std::size_t I, class... Types>
-constexpr absl::add_pointer_t<variant_alternative_t<I, variant<Types...>>>
-get_if(variant<Types...>* v) noexcept {
-  return (v != nullptr && v->index() == I)
-             ? std::addressof(
-                   variant_internal::VariantCoreAccess::Access<I>(*v))
-             : nullptr;
-}
-
-// Overload for getting a pointer to the const value stored in the given
-// variant by index.
-template <std::size_t I, class... Types>
-constexpr absl::add_pointer_t<const variant_alternative_t<I, variant<Types...>>>
-get_if(const variant<Types...>* v) noexcept {
-  return (v != nullptr && v->index() == I)
-             ? std::addressof(
-                   variant_internal::VariantCoreAccess::Access<I>(*v))
-             : nullptr;
-}
-
-// Overload for getting a pointer to the value stored in the given variant by
-// type.
-template <class T, class... Types>
-constexpr absl::add_pointer_t<T> get_if(variant<Types...>* v) noexcept {
-  return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
-}
-
-// Overload for getting a pointer to the const value stored in the given variant
-// by type.
-template <class T, class... Types>
-constexpr absl::add_pointer_t<const T> get_if(
-    const variant<Types...>* v) noexcept {
-  return absl::get_if<variant_internal::IndexOf<T, Types...>::value>(v);
-}
-
-// visit()
-//
-// Calls a provided functor on a given set of variants. `absl::visit()` is
-// commonly used to conditionally inspect the state of a given variant (or set
-// of variants).
-//
-// The functor must return the same type when called with any of the variants'
-// alternatives.
-//
-// Example:
-//
-//   // Define a visitor functor
-//   struct GetVariant {
-//       template<typename T>
-//       void operator()(const T& i) const {
-//         std::cout << "The variant's value is: " << i;
-//       }
-//   };
-//
-//   // Declare our variant, and call `absl::visit()` on it.
-//   // Note that `GetVariant()` returns void in either case.
-//   absl::variant<int, std::string> foo = std::string("foo");
-//   GetVariant visitor;
-//   absl::visit(visitor, foo);  // Prints `The variant's value is: foo'
-template <typename Visitor, typename... Variants>
-variant_internal::VisitResult<Visitor, Variants...> visit(Visitor&& vis,
-                                                          Variants&&... vars) {
-  return variant_internal::
-      VisitIndices<variant_size<absl::decay_t<Variants> >::value...>::Run(
-          variant_internal::PerformVisitation<Visitor, Variants...>{
-              std::forward_as_tuple(std::forward<Variants>(vars)...),
-              std::forward<Visitor>(vis)},
-          vars.index()...);
-}
-
-// monostate
-//
-// The monostate class serves as a first alternative type for a variant for
-// which the first variant type is otherwise not default-constructible.
-struct monostate {};
-
-// `absl::monostate` Relational Operators
-
-constexpr bool operator<(monostate, monostate) noexcept { return false; }
-constexpr bool operator>(monostate, monostate) noexcept { return false; }
-constexpr bool operator<=(monostate, monostate) noexcept { return true; }
-constexpr bool operator>=(monostate, monostate) noexcept { return true; }
-constexpr bool operator==(monostate, monostate) noexcept { return true; }
-constexpr bool operator!=(monostate, monostate) noexcept { return false; }
-
-
-//------------------------------------------------------------------------------
-// `absl::variant` Template Definition
-//------------------------------------------------------------------------------
-template <typename T0, typename... Tn>
-class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
-  static_assert(absl::conjunction<std::is_object<T0>,
-                                  std::is_object<Tn>...>::value,
-                "Attempted to instantiate a variant containing a non-object "
-                "type.");
-  // Intentionally not qualifying `negation` with `absl::` to work around a bug
-  // in MSVC 2015 with inline namespace and variadic template.
-  static_assert(absl::conjunction<negation<std::is_array<T0> >,
-                                  negation<std::is_array<Tn> >...>::value,
-                "Attempted to instantiate a variant containing an array type.");
-  static_assert(absl::conjunction<std::is_nothrow_destructible<T0>,
-                                  std::is_nothrow_destructible<Tn>...>::value,
-                "Attempted to instantiate a variant containing a non-nothrow "
-                "destructible type.");
-
-  friend struct variant_internal::VariantCoreAccess;
-
- private:
-  using Base = variant_internal::VariantBase<T0, Tn...>;
-
- public:
-  // Constructors
-
-  // Constructs a variant holding a default-initialized value of the first
-  // alternative type.
-  constexpr variant() /*noexcept(see 111above)*/ = default;
-
-  // Copy constructor, standard semantics
-  variant(const variant& other) = default;
-
-  // Move constructor, standard semantics
-  variant(variant&& other) /*noexcept(see above)*/ = default;
-
-  // Constructs a variant of an alternative type specified by overload
-  // resolution of the provided forwarding arguments through
-  // direct-initialization.
-  //
-  // Note: If the selected constructor is a constexpr constructor, this
-  // constructor shall be a constexpr constructor.
-  //
-  // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
-  // has been voted passed the design phase in the C++ standard meeting in Mar
-  // 2018. It will be implemented and integrated into `absl::variant`.
-  template <
-      class T,
-      std::size_t I = std::enable_if<
-          variant_internal::IsNeitherSelfNorInPlace<variant,
-                                                    absl::decay_t<T> >::value,
-          variant_internal::IndexOfConstructedType<variant, T> >::type::value,
-      class Tj = absl::variant_alternative_t<I, variant>,
-      absl::enable_if_t<std::is_constructible<Tj, T>::value>* = nullptr>
-  constexpr variant(T&& t) noexcept(std::is_nothrow_constructible<Tj, T>::value)
-      : Base(variant_internal::EmplaceTag<I>(), std::forward<T>(t)) {}
-
-  // Constructs a variant of an alternative type from the arguments through
-  // direct-initialization.
-  //
-  // Note: If the selected constructor is a constexpr constructor, this
-  // constructor shall be a constexpr constructor.
-  template <class T, class... Args,
-            typename std::enable_if<std::is_constructible<
-                variant_internal::UnambiguousTypeOfT<variant, T>,
-                Args...>::value>::type* = nullptr>
-  constexpr explicit variant(in_place_type_t<T>, Args&&... args)
-      : Base(variant_internal::EmplaceTag<
-                 variant_internal::UnambiguousIndexOf<variant, T>::value>(),
-             std::forward<Args>(args)...) {}
-
-  // Constructs a variant of an alternative type from an initializer list
-  // and other arguments through direct-initialization.
-  //
-  // Note: If the selected constructor is a constexpr constructor, this
-  // constructor shall be a constexpr constructor.
-  template <class T, class U, class... Args,
-            typename std::enable_if<std::is_constructible<
-                variant_internal::UnambiguousTypeOfT<variant, T>,
-                std::initializer_list<U>&, Args...>::value>::type* = nullptr>
-  constexpr explicit variant(in_place_type_t<T>, std::initializer_list<U> il,
-                             Args&&... args)
-      : Base(variant_internal::EmplaceTag<
-                 variant_internal::UnambiguousIndexOf<variant, T>::value>(),
-             il, std::forward<Args>(args)...) {}
-
-  // Constructs a variant of an alternative type from a provided index,
-  // through value-initialization using the provided forwarded arguments.
-  template <std::size_t I, class... Args,
-            typename std::enable_if<std::is_constructible<
-                variant_internal::VariantAlternativeSfinaeT<I, variant>,
-                Args...>::value>::type* = nullptr>
-  constexpr explicit variant(in_place_index_t<I>, Args&&... args)
-      : Base(variant_internal::EmplaceTag<I>(), std::forward<Args>(args)...) {}
-
-  // Constructs a variant of an alternative type from a provided index,
-  // through value-initialization of an initializer list and the provided
-  // forwarded arguments.
-  template <std::size_t I, class U, class... Args,
-            typename std::enable_if<std::is_constructible<
-                variant_internal::VariantAlternativeSfinaeT<I, variant>,
-                std::initializer_list<U>&, Args...>::value>::type* = nullptr>
-  constexpr explicit variant(in_place_index_t<I>, std::initializer_list<U> il,
-                             Args&&... args)
-      : Base(variant_internal::EmplaceTag<I>(), il,
-             std::forward<Args>(args)...) {}
-
-  // Destructors
-
-  // Destroys the variant's currently contained value, provided that
-  // `absl::valueless_by_exception()` is false.
-  ~variant() = default;
-
-  // Assignment Operators
-
-  // Copy assignment operator
-  variant& operator=(const variant& other) = default;
-
-  // Move assignment operator
-  variant& operator=(variant&& other) /*noexcept(see above)*/ = default;
-
-  // Converting assignment operator
-  //
-  // NOTE: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0608r1.html
-  // has been voted passed the design phase in the C++ standard meeting in Mar
-  // 2018. It will be implemented and integrated into `absl::variant`.
-  template <
-      class T,
-      std::size_t I = std::enable_if<
-          !std::is_same<absl::decay_t<T>, variant>::value,
-          variant_internal::IndexOfConstructedType<variant, T>>::type::value,
-      class Tj = absl::variant_alternative_t<I, variant>,
-      typename std::enable_if<std::is_assignable<Tj&, T>::value &&
-                              std::is_constructible<Tj, T>::value>::type* =
-          nullptr>
-  variant& operator=(T&& t) noexcept(
-      std::is_nothrow_assignable<Tj&, T>::value&&
-          std::is_nothrow_constructible<Tj, T>::value) {
-    variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
-        variant_internal::VariantCoreAccess::MakeConversionAssignVisitor(
-            this, std::forward<T>(t)),
-        index());
-
-    return *this;
-  }
-
-
-  // emplace() Functions
-
-  // Constructs a value of the given alternative type T within the variant. The
-  // existing value of the variant is destroyed first (provided that
-  // `absl::valueless_by_exception()` is false). Requires that T is unambiguous
-  // in the variant.
-  //
-  // Example:
-  //
-  //   absl::variant<std::vector<int>, int, std::string> v;
-  //   v.emplace<int>(99);
-  //   v.emplace<std::string>("abc");
-  template <
-      class T, class... Args,
-      typename std::enable_if<std::is_constructible<
-          absl::variant_alternative_t<
-              variant_internal::UnambiguousIndexOf<variant, T>::value, variant>,
-          Args...>::value>::type* = nullptr>
-  T& emplace(Args&&... args) {
-    return variant_internal::VariantCoreAccess::Replace<
-        variant_internal::UnambiguousIndexOf<variant, T>::value>(
-        this, std::forward<Args>(args)...);
-  }
-
-  // Constructs a value of the given alternative type T within the variant using
-  // an initializer list. The existing value of the variant is destroyed first
-  // (provided that `absl::valueless_by_exception()` is false). Requires that T
-  // is unambiguous in the variant.
-  //
-  // Example:
-  //
-  //   absl::variant<std::vector<int>, int, std::string> v;
-  //   v.emplace<std::vector<int>>({0, 1, 2});
-  template <
-      class T, class U, class... Args,
-      typename std::enable_if<std::is_constructible<
-          absl::variant_alternative_t<
-              variant_internal::UnambiguousIndexOf<variant, T>::value, variant>,
-          std::initializer_list<U>&, Args...>::value>::type* = nullptr>
-  T& emplace(std::initializer_list<U> il, Args&&... args) {
-    return variant_internal::VariantCoreAccess::Replace<
-        variant_internal::UnambiguousIndexOf<variant, T>::value>(
-        this, il, std::forward<Args>(args)...);
-  }
-
-  // Destroys the current value of the variant (provided that
-  // `absl::valueless_by_exception()` is false) and constructs a new value at
-  // the given index.
-  //
-  // Example:
-  //
-  //   absl::variant<std::vector<int>, int, int> v;
-  //   v.emplace<1>(99);
-  //   v.emplace<2>(98);
-  //   v.emplace<int>(99);  // Won't compile. 'int' isn't a unique type.
-  template <std::size_t I, class... Args,
-            typename std::enable_if<
-                std::is_constructible<absl::variant_alternative_t<I, variant>,
-                                      Args...>::value>::type* = nullptr>
-  absl::variant_alternative_t<I, variant>& emplace(Args&&... args) {
-    return variant_internal::VariantCoreAccess::Replace<I>(
-        this, std::forward<Args>(args)...);
-  }
-
-  // Destroys the current value of the variant (provided that
-  // `absl::valueless_by_exception()` is false) and constructs a new value at
-  // the given index using an initializer list and the provided arguments.
-  //
-  // Example:
-  //
-  //   absl::variant<std::vector<int>, int, int> v;
-  //   v.emplace<0>({0, 1, 2});
-  template <std::size_t I, class U, class... Args,
-            typename std::enable_if<std::is_constructible<
-                absl::variant_alternative_t<I, variant>,
-                std::initializer_list<U>&, Args...>::value>::type* = nullptr>
-  absl::variant_alternative_t<I, variant>& emplace(std::initializer_list<U> il,
-                                                   Args&&... args) {
-    return variant_internal::VariantCoreAccess::Replace<I>(
-        this, il, std::forward<Args>(args)...);
-  }
-
-  // variant::valueless_by_exception()
-  //
-  // Returns false if and only if the variant currently holds a valid value.
-  constexpr bool valueless_by_exception() const noexcept {
-    return this->index_ == absl::variant_npos;
-  }
-
-  // variant::index()
-  //
-  // Returns the index value of the variant's currently selected alternative
-  // type.
-  constexpr std::size_t index() const noexcept { return this->index_; }
-
-  // variant::swap()
-  //
-  // Swaps the values of two variant objects.
-  //
-  void swap(variant& rhs) noexcept(
-      absl::conjunction<
-          std::is_nothrow_move_constructible<T0>,
-          std::is_nothrow_move_constructible<Tn>...,
-          type_traits_internal::IsNothrowSwappable<T0>,
-          type_traits_internal::IsNothrowSwappable<Tn>...>::value) {
-    return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
-        variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
-  }
-};
-
-// We need a valid declaration of variant<> for SFINAE and overload resolution
-// to work properly above, but we don't need a full declaration since this type
-// will never be constructed. This declaration, though incomplete, suffices.
-template <>
-class variant<>;
-
-//------------------------------------------------------------------------------
-// Relational Operators
-//------------------------------------------------------------------------------
-//
-// If neither operand is in the `variant::valueless_by_exception` state:
-//
-//   * If the index of both variants is the same, the relational operator
-//     returns the result of the corresponding relational operator for the
-//     corresponding alternative type.
-//   * If the index of both variants is not the same, the relational operator
-//     returns the result of that operation applied to the value of the left
-//     operand's index and the value of the right operand's index.
-//   * If at least one operand is in the valueless_by_exception state:
-//     - A variant in the valueless_by_exception state is only considered equal
-//       to another variant in the valueless_by_exception state.
-//     - If exactly one operand is in the valueless_by_exception state, the
-//       variant in the valueless_by_exception state is less than the variant
-//       that is not in the valueless_by_exception state.
-//
-// Note: The value 1 is added to each index in the relational comparisons such
-// that the index corresponding to the valueless_by_exception state wraps around
-// to 0 (the lowest value for the index type), and the remaining indices stay in
-// the same relative order.
-
-// Equal-to operator
-template <typename... Types>
-constexpr variant_internal::RequireAllHaveEqualT<Types...> operator==(
-    const variant<Types...>& a, const variant<Types...>& b) {
-  return (a.index() == b.index()) &&
-         variant_internal::VisitIndices<sizeof...(Types)>::Run(
-             variant_internal::EqualsOp<Types...>{&a, &b}, a.index());
-}
-
-// Not equal operator
-template <typename... Types>
-constexpr variant_internal::RequireAllHaveNotEqualT<Types...> operator!=(
-    const variant<Types...>& a, const variant<Types...>& b) {
-  return (a.index() != b.index()) ||
-         variant_internal::VisitIndices<sizeof...(Types)>::Run(
-             variant_internal::NotEqualsOp<Types...>{&a, &b}, a.index());
-}
-
-// Less-than operator
-template <typename... Types>
-constexpr variant_internal::RequireAllHaveLessThanT<Types...> operator<(
-    const variant<Types...>& a, const variant<Types...>& b) {
-  return (a.index() != b.index())
-             ? (a.index() + 1) < (b.index() + 1)
-             : variant_internal::VisitIndices<sizeof...(Types)>::Run(
-                   variant_internal::LessThanOp<Types...>{&a, &b}, a.index());
-}
-
-// Greater-than operator
-template <typename... Types>
-constexpr variant_internal::RequireAllHaveGreaterThanT<Types...> operator>(
-    const variant<Types...>& a, const variant<Types...>& b) {
-  return (a.index() != b.index())
-             ? (a.index() + 1) > (b.index() + 1)
-             : variant_internal::VisitIndices<sizeof...(Types)>::Run(
-                   variant_internal::GreaterThanOp<Types...>{&a, &b},
-                   a.index());
-}
-
-// Less-than or equal-to operator
-template <typename... Types>
-constexpr variant_internal::RequireAllHaveLessThanOrEqualT<Types...> operator<=(
-    const variant<Types...>& a, const variant<Types...>& b) {
-  return (a.index() != b.index())
-             ? (a.index() + 1) < (b.index() + 1)
-             : variant_internal::VisitIndices<sizeof...(Types)>::Run(
-                   variant_internal::LessThanOrEqualsOp<Types...>{&a, &b},
-                   a.index());
-}
-
-// Greater-than or equal-to operator
-template <typename... Types>
-constexpr variant_internal::RequireAllHaveGreaterThanOrEqualT<Types...>
-operator>=(const variant<Types...>& a, const variant<Types...>& b) {
-  return (a.index() != b.index())
-             ? (a.index() + 1) > (b.index() + 1)
-             : variant_internal::VisitIndices<sizeof...(Types)>::Run(
-                   variant_internal::GreaterThanOrEqualsOp<Types...>{&a, &b},
-                   a.index());
-}
-
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-namespace std {
-
-// hash()
-template <>  // NOLINT
-struct hash<absl::monostate> {
-  std::size_t operator()(absl::monostate) const { return 0; }
-};
-
-template <class... T>  // NOLINT
-struct hash<absl::variant<T...>>
-    : absl::variant_internal::VariantHashBase<absl::variant<T...>, void,
-                                              absl::remove_const_t<T>...> {};
-
-}  // namespace std
-
-#endif  // ABSL_USES_STD_VARIANT
 
-namespace absl {
-ABSL_NAMESPACE_BEGIN
 namespace variant_internal {
-
 // Helper visitor for converting a variant<Ts...>` into another type (mostly
 // variant) that can be constructed from any type.
 template <typename To>
@@ -831,7 +53,6 @@
     return To(std::forward<T>(v));
   }
 };
-
 }  // namespace variant_internal
 
 // ConvertVariantTo()
diff --git a/absl/types/variant_benchmark.cc b/absl/types/variant_benchmark.cc
deleted file mode 100644
index 350b175..0000000
--- a/absl/types/variant_benchmark.cc
+++ /dev/null
@@ -1,222 +0,0 @@
-// Copyright 2017 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.
-
-// Unit tests for the variant template. The 'is' and 'IsEmpty' methods
-// of variant are not explicitly tested because they are used repeatedly
-// in building other tests. All other public variant methods should have
-// explicit tests.
-
-#include "absl/types/variant.h"
-
-#include <cstddef>
-#include <cstdlib>
-#include <string>
-#include <tuple>
-
-#include "benchmark/benchmark.h"
-#include "absl/utility/utility.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace {
-
-template <std::size_t I>
-struct VariantAlternative {
-  char member;
-};
-
-template <class Indices>
-struct VariantOfAlternativesImpl;
-
-template <std::size_t... Indices>
-struct VariantOfAlternativesImpl<absl::index_sequence<Indices...>> {
-  using type = absl::variant<VariantAlternative<Indices>...>;
-};
-
-template <std::size_t NumAlternatives>
-using VariantOfAlternatives = typename VariantOfAlternativesImpl<
-    absl::make_index_sequence<NumAlternatives>>::type;
-
-struct Empty {};
-
-template <class... T>
-void Ignore(T...) noexcept {}
-
-template <class T>
-Empty DoNotOptimizeAndReturnEmpty(T&& arg) noexcept {
-  benchmark::DoNotOptimize(arg);
-  return {};
-}
-
-struct VisitorApplier {
-  struct Visitor {
-    template <class... T>
-    void operator()(T&&... args) const noexcept {
-      Ignore(DoNotOptimizeAndReturnEmpty(args)...);
-    }
-  };
-
-  template <class... Vars>
-  void operator()(const Vars&... vars) const noexcept {
-    absl::visit(Visitor(), vars...);
-  }
-};
-
-template <std::size_t NumIndices, std::size_t CurrIndex = NumIndices - 1>
-struct MakeWithIndex {
-  using Variant = VariantOfAlternatives<NumIndices>;
-
-  static Variant Run(std::size_t index) {
-    return index == CurrIndex
-               ? Variant(absl::in_place_index_t<CurrIndex>())
-               : MakeWithIndex<NumIndices, CurrIndex - 1>::Run(index);
-  }
-};
-
-template <std::size_t NumIndices>
-struct MakeWithIndex<NumIndices, 0> {
-  using Variant = VariantOfAlternatives<NumIndices>;
-
-  static Variant Run(std::size_t /*index*/) { return Variant(); }
-};
-
-template <std::size_t NumIndices, class Dimensions>
-struct MakeVariantTuple;
-
-template <class T, std::size_t /*I*/>
-using always_t = T;
-
-template <std::size_t NumIndices>
-VariantOfAlternatives<NumIndices> MakeVariant(std::size_t dimension,
-                                              std::size_t index) {
-  return dimension == 0
-             ? MakeWithIndex<NumIndices>::Run(index % NumIndices)
-             : MakeVariant<NumIndices>(dimension - 1, index / NumIndices);
-}
-
-template <std::size_t NumIndices, std::size_t... Dimensions>
-struct MakeVariantTuple<NumIndices, absl::index_sequence<Dimensions...>> {
-  using VariantTuple =
-      std::tuple<always_t<VariantOfAlternatives<NumIndices>, Dimensions>...>;
-
-  static VariantTuple Run(int index) {
-    return std::make_tuple(MakeVariant<NumIndices>(Dimensions, index)...);
-  }
-};
-
-constexpr std::size_t integral_pow(std::size_t base, std::size_t power) {
-  return power == 0 ? 1 : base * integral_pow(base, power - 1);
-}
-
-template <std::size_t End, std::size_t I = 0>
-struct VisitTestBody {
-  template <class Vars, class State>
-  static bool Run(Vars& vars, State& state) {
-    if (state.KeepRunning()) {
-      absl::apply(VisitorApplier(), vars[I]);
-      return VisitTestBody<End, I + 1>::Run(vars, state);
-    }
-    return false;
-  }
-};
-
-template <std::size_t End>
-struct VisitTestBody<End, End> {
-  template <class Vars, class State>
-  static bool Run(Vars& /*vars*/, State& /*state*/) {
-    return true;
-  }
-};
-
-// Visit operations where branch prediction is likely to give a boost.
-template <std::size_t NumIndices, std::size_t NumDimensions = 1>
-void BM_RedundantVisit(benchmark::State& state) {
-  auto vars =
-      MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>::
-          Run(static_cast<std::size_t>(state.range(0)));
-
-  for (auto _ : state) {  // NOLINT
-    benchmark::DoNotOptimize(vars);
-    absl::apply(VisitorApplier(), vars);
-  }
-}
-
-// Visit operations where branch prediction is unlikely to give a boost.
-template <std::size_t NumIndices, std::size_t NumDimensions = 1>
-void BM_Visit(benchmark::State& state) {
-  constexpr std::size_t num_possibilities =
-      integral_pow(NumIndices, NumDimensions);
-
-  using VariantTupleMaker =
-      MakeVariantTuple<NumIndices, absl::make_index_sequence<NumDimensions>>;
-  using Tuple = typename VariantTupleMaker::VariantTuple;
-
-  Tuple vars[num_possibilities];
-  for (std::size_t i = 0; i < num_possibilities; ++i)
-    vars[i] = VariantTupleMaker::Run(i);
-
-  while (VisitTestBody<num_possibilities>::Run(vars, state)) {
-  }
-}
-
-// Visitation
-//   Each visit is on a different variant with a different active alternative)
-
-// Unary visit
-BENCHMARK_TEMPLATE(BM_Visit, 1);
-BENCHMARK_TEMPLATE(BM_Visit, 2);
-BENCHMARK_TEMPLATE(BM_Visit, 3);
-BENCHMARK_TEMPLATE(BM_Visit, 4);
-BENCHMARK_TEMPLATE(BM_Visit, 5);
-BENCHMARK_TEMPLATE(BM_Visit, 6);
-BENCHMARK_TEMPLATE(BM_Visit, 7);
-BENCHMARK_TEMPLATE(BM_Visit, 8);
-BENCHMARK_TEMPLATE(BM_Visit, 16);
-BENCHMARK_TEMPLATE(BM_Visit, 32);
-BENCHMARK_TEMPLATE(BM_Visit, 64);
-
-// Binary visit
-BENCHMARK_TEMPLATE(BM_Visit, 1, 2);
-BENCHMARK_TEMPLATE(BM_Visit, 2, 2);
-BENCHMARK_TEMPLATE(BM_Visit, 3, 2);
-BENCHMARK_TEMPLATE(BM_Visit, 4, 2);
-BENCHMARK_TEMPLATE(BM_Visit, 5, 2);
-
-// Ternary visit
-BENCHMARK_TEMPLATE(BM_Visit, 1, 3);
-BENCHMARK_TEMPLATE(BM_Visit, 2, 3);
-BENCHMARK_TEMPLATE(BM_Visit, 3, 3);
-
-// Quaternary visit
-BENCHMARK_TEMPLATE(BM_Visit, 1, 4);
-BENCHMARK_TEMPLATE(BM_Visit, 2, 4);
-
-// Redundant Visitation
-//   Each visit consistently has the same alternative active
-
-// Unary visit
-BENCHMARK_TEMPLATE(BM_RedundantVisit, 1)->Arg(0);
-BENCHMARK_TEMPLATE(BM_RedundantVisit, 2)->DenseRange(0, 1);
-BENCHMARK_TEMPLATE(BM_RedundantVisit, 8)->DenseRange(0, 7);
-
-// Binary visit
-BENCHMARK_TEMPLATE(BM_RedundantVisit, 1, 2)->Arg(0);
-BENCHMARK_TEMPLATE(BM_RedundantVisit, 2, 2)
-    ->DenseRange(0, integral_pow(2, 2) - 1);
-BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2)
-    ->DenseRange(0, integral_pow(4, 2) - 1);
-
-}  // namespace
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc
deleted file mode 100644
index 439c6e1..0000000
--- a/absl/types/variant_exception_safety_test.cc
+++ /dev/null
@@ -1,532 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/types/variant.h"
-
-#include "absl/base/config.h"
-
-// This test is a no-op when absl::variant is an alias for std::variant and when
-// exceptions are not enabled.
-#if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS)
-
-#include <iostream>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/internal/exception_safety_testing.h"
-#include "absl/memory/memory.h"
-
-// See comment in absl/base/config.h
-#if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace {
-
-using ::testing::MakeExceptionSafetyTester;
-using ::testing::strong_guarantee;
-using ::testing::TestNothrowOp;
-using ::testing::TestThrowingCtor;
-
-using Thrower = testing::ThrowingValue<>;
-using CopyNothrow = testing::ThrowingValue<testing::TypeSpec::kNoThrowCopy>;
-using MoveNothrow = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
-using ThrowingAlloc = testing::ThrowingAllocator<Thrower>;
-using ThrowerVec = std::vector<Thrower, ThrowingAlloc>;
-using ThrowingVariant =
-    absl::variant<Thrower, CopyNothrow, MoveNothrow, ThrowerVec>;
-
-struct ConversionException {};
-
-template <class T>
-struct ExceptionOnConversion {
-  operator T() const {  // NOLINT
-    throw ConversionException();
-  }
-};
-
-// Forces a variant into the valueless by exception state.
-void ToValuelessByException(ThrowingVariant& v) {  // NOLINT
-  try {
-    v.emplace<Thrower>();
-    v.emplace<Thrower>(ExceptionOnConversion<Thrower>());
-  } catch (const ConversionException&) {
-    // This space intentionally left blank.
-  }
-}
-
-// Check that variant is still in a usable state after an exception is thrown.
-testing::AssertionResult VariantInvariants(ThrowingVariant* v) {
-  using testing::AssertionFailure;
-  using testing::AssertionSuccess;
-
-  // Try using the active alternative
-  if (absl::holds_alternative<Thrower>(*v)) {
-    auto& t = absl::get<Thrower>(*v);
-    t = Thrower{-100};
-    if (t.Get() != -100) {
-      return AssertionFailure() << "Thrower should be assigned -100";
-    }
-  } else if (absl::holds_alternative<ThrowerVec>(*v)) {
-    auto& tv = absl::get<ThrowerVec>(*v);
-    tv.clear();
-    tv.emplace_back(-100);
-    if (tv.size() != 1 || tv[0].Get() != -100) {
-      return AssertionFailure() << "ThrowerVec should be {Thrower{-100}}";
-    }
-  } else if (absl::holds_alternative<CopyNothrow>(*v)) {
-    auto& t = absl::get<CopyNothrow>(*v);
-    t = CopyNothrow{-100};
-    if (t.Get() != -100) {
-      return AssertionFailure() << "CopyNothrow should be assigned -100";
-    }
-  } else if (absl::holds_alternative<MoveNothrow>(*v)) {
-    auto& t = absl::get<MoveNothrow>(*v);
-    t = MoveNothrow{-100};
-    if (t.Get() != -100) {
-      return AssertionFailure() << "MoveNothrow should be assigned -100";
-    }
-  }
-
-  // Try making variant valueless_by_exception
-  if (!v->valueless_by_exception()) ToValuelessByException(*v);
-  if (!v->valueless_by_exception()) {
-    return AssertionFailure() << "Variant should be valueless_by_exception";
-  }
-  try {
-    auto unused = absl::get<Thrower>(*v);
-    static_cast<void>(unused);
-    return AssertionFailure() << "Variant should not contain Thrower";
-  } catch (const absl::bad_variant_access&) {
-  } catch (...) {
-    return AssertionFailure() << "Unexpected exception throw from absl::get";
-  }
-
-  // Try using the variant
-  v->emplace<Thrower>(100);
-  if (!absl::holds_alternative<Thrower>(*v) ||
-      absl::get<Thrower>(*v) != Thrower(100)) {
-    return AssertionFailure() << "Variant should contain Thrower(100)";
-  }
-  v->emplace<ThrowerVec>({Thrower(100)});
-  if (!absl::holds_alternative<ThrowerVec>(*v) ||
-      absl::get<ThrowerVec>(*v)[0] != Thrower(100)) {
-    return AssertionFailure()
-           << "Variant should contain ThrowerVec{Thrower(100)}";
-  }
-  return AssertionSuccess();
-}
-
-template <typename... Args>
-Thrower ExpectedThrower(Args&&... args) {
-  return Thrower(42, args...);
-}
-
-ThrowerVec ExpectedThrowerVec() { return {Thrower(100), Thrower(200)}; }
-ThrowingVariant ValuelessByException() {
-  ThrowingVariant v;
-  ToValuelessByException(v);
-  return v;
-}
-ThrowingVariant WithThrower() { return Thrower(39); }
-ThrowingVariant WithThrowerVec() {
-  return ThrowerVec{Thrower(1), Thrower(2), Thrower(3)};
-}
-ThrowingVariant WithCopyNoThrow() { return CopyNothrow(39); }
-ThrowingVariant WithMoveNoThrow() { return MoveNothrow(39); }
-
-TEST(VariantExceptionSafetyTest, DefaultConstructor) {
-  TestThrowingCtor<ThrowingVariant>();
-}
-
-TEST(VariantExceptionSafetyTest, CopyConstructor) {
-  {
-    ThrowingVariant v(ExpectedThrower());
-    TestThrowingCtor<ThrowingVariant>(v);
-  }
-  {
-    ThrowingVariant v(ExpectedThrowerVec());
-    TestThrowingCtor<ThrowingVariant>(v);
-  }
-  {
-    ThrowingVariant v(ValuelessByException());
-    TestThrowingCtor<ThrowingVariant>(v);
-  }
-}
-
-TEST(VariantExceptionSafetyTest, MoveConstructor) {
-  {
-    ThrowingVariant v(ExpectedThrower());
-    TestThrowingCtor<ThrowingVariant>(std::move(v));
-  }
-  {
-    ThrowingVariant v(ExpectedThrowerVec());
-    TestThrowingCtor<ThrowingVariant>(std::move(v));
-  }
-  {
-    ThrowingVariant v(ValuelessByException());
-    TestThrowingCtor<ThrowingVariant>(std::move(v));
-  }
-}
-
-TEST(VariantExceptionSafetyTest, ValueConstructor) {
-  TestThrowingCtor<ThrowingVariant>(ExpectedThrower());
-  TestThrowingCtor<ThrowingVariant>(ExpectedThrowerVec());
-}
-
-TEST(VariantExceptionSafetyTest, InPlaceTypeConstructor) {
-  TestThrowingCtor<ThrowingVariant>(absl::in_place_type_t<Thrower>{},
-                                    ExpectedThrower());
-  TestThrowingCtor<ThrowingVariant>(absl::in_place_type_t<ThrowerVec>{},
-                                    ExpectedThrowerVec());
-}
-
-TEST(VariantExceptionSafetyTest, InPlaceIndexConstructor) {
-  TestThrowingCtor<ThrowingVariant>(absl::in_place_index_t<0>{},
-                                    ExpectedThrower());
-  TestThrowingCtor<ThrowingVariant>(absl::in_place_index_t<3>{},
-                                    ExpectedThrowerVec());
-}
-
-TEST(VariantExceptionSafetyTest, CopyAssign) {
-  // variant& operator=(const variant& rhs);
-  // Let j be rhs.index()
-  {
-    // - neither *this nor rhs holds a value
-    const ThrowingVariant rhs = ValuelessByException();
-    ThrowingVariant lhs = ValuelessByException();
-    EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; }));
-  }
-  {
-    // - *this holds a value but rhs does not
-    const ThrowingVariant rhs = ValuelessByException();
-    ThrowingVariant lhs = WithThrower();
-    EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; }));
-  }
-  // - index() == j
-  {
-    const ThrowingVariant rhs(ExpectedThrower());
-    auto tester =
-        MakeExceptionSafetyTester()
-            .WithInitialValue(WithThrower())
-            .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; });
-    EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test());
-    EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
-  }
-  {
-    const ThrowingVariant rhs(ExpectedThrowerVec());
-    auto tester =
-        MakeExceptionSafetyTester()
-            .WithInitialValue(WithThrowerVec())
-            .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; });
-    EXPECT_TRUE(tester.WithContracts(VariantInvariants).Test());
-    EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
-  }
-  // libstdc++ std::variant has bugs on copy assignment regarding exception
-  // safety.
-#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
-  // index() != j
-  // if is_nothrow_copy_constructible_v<Tj> or
-  // !is_nothrow_move_constructible<Tj> is true, equivalent to
-  // emplace<j>(get<j>(rhs))
-  {
-    // is_nothrow_copy_constructible_v<Tj> == true
-    // should not throw because emplace() invokes Tj's copy ctor
-    // which should not throw.
-    const ThrowingVariant rhs(CopyNothrow{});
-    ThrowingVariant lhs = WithThrower();
-    EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; }));
-  }
-  {
-    // is_nothrow_copy_constructible<Tj> == false &&
-    // is_nothrow_move_constructible<Tj> == false
-    // should provide basic guarantee because emplace() invokes Tj's copy ctor
-    // which may throw.
-    const ThrowingVariant rhs(ExpectedThrower());
-    auto tester =
-        MakeExceptionSafetyTester()
-            .WithInitialValue(WithCopyNoThrow())
-            .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; });
-    EXPECT_TRUE(tester
-                    .WithContracts(VariantInvariants,
-                                   [](ThrowingVariant* lhs) {
-                                     return lhs->valueless_by_exception();
-                                   })
-                    .Test());
-    EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
-  }
-#endif  // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
-  {
-    // is_nothrow_copy_constructible_v<Tj> == false &&
-    // is_nothrow_move_constructible_v<Tj> == true
-    // should provide strong guarantee because it is equivalent to
-    // operator=(variant(rhs)) which creates a temporary then invoke the move
-    // ctor which shouldn't throw.
-    const ThrowingVariant rhs(MoveNothrow{});
-    EXPECT_TRUE(MakeExceptionSafetyTester()
-                    .WithInitialValue(WithThrower())
-                    .WithContracts(VariantInvariants, strong_guarantee)
-                    .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }));
-  }
-}
-
-TEST(VariantExceptionSafetyTest, MoveAssign) {
-  // variant& operator=(variant&& rhs);
-  // Let j be rhs.index()
-  {
-    // - neither *this nor rhs holds a value
-    ThrowingVariant rhs = ValuelessByException();
-    ThrowingVariant lhs = ValuelessByException();
-    EXPECT_TRUE(TestNothrowOp([&]() { lhs = std::move(rhs); }));
-  }
-  {
-    // - *this holds a value but rhs does not
-    ThrowingVariant rhs = ValuelessByException();
-    ThrowingVariant lhs = WithThrower();
-    EXPECT_TRUE(TestNothrowOp([&]() { lhs = std::move(rhs); }));
-  }
-  {
-    // - index() == j
-    // assign get<j>(std::move(rhs)) to the value contained in *this.
-    // If an exception is thrown during call to Tj's move assignment, the state
-    // of the contained value is as defined by the exception safety guarantee of
-    // Tj's move assignment; index() will be j.
-    ThrowingVariant rhs(ExpectedThrower());
-    size_t j = rhs.index();
-    // Since Thrower's move assignment has basic guarantee, so should variant's.
-    auto tester = MakeExceptionSafetyTester()
-                      .WithInitialValue(WithThrower())
-                      .WithOperation([&](ThrowingVariant* lhs) {
-                        auto copy = rhs;
-                        *lhs = std::move(copy);
-                      });
-    EXPECT_TRUE(tester
-                    .WithContracts(
-                        VariantInvariants,
-                        [&](ThrowingVariant* lhs) { return lhs->index() == j; })
-                    .Test());
-    EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
-  }
-  {
-    // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06.
-    // The fix is targeted for gcc-9.
-    // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7
-    // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614
-#if !(defined(ABSL_USES_STD_VARIANT) && \
-      defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
-    // - otherwise (index() != j), equivalent to
-    // emplace<j>(get<j>(std::move(rhs)))
-    // - If an exception is thrown during the call to Tj's move construction
-    // (with j being rhs.index()), the variant will hold no value.
-    ThrowingVariant rhs(CopyNothrow{});
-    EXPECT_TRUE(MakeExceptionSafetyTester()
-                    .WithInitialValue(WithThrower())
-                    .WithContracts(VariantInvariants,
-                                   [](ThrowingVariant* lhs) {
-                                     return lhs->valueless_by_exception();
-                                   })
-                    .Test([&](ThrowingVariant* lhs) {
-                      auto copy = rhs;
-                      *lhs = std::move(copy);
-                    }));
-#endif  // !(defined(ABSL_USES_STD_VARIANT) &&
-        //   defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
-  }
-}
-
-TEST(VariantExceptionSafetyTest, ValueAssign) {
-  // template<class T> variant& operator=(T&& t);
-  // Let Tj be the type that is selected by overload resolution to be assigned.
-  {
-    // If *this holds a Tj, assigns std::forward<T>(t) to the value contained in
-    // *this. If  an exception is thrown during the assignment of
-    // std::forward<T>(t) to the value contained in *this, the state of the
-    // contained value and t are as defined by the exception safety guarantee of
-    // the assignment expression; valueless_by_exception() will be false.
-    // Since Thrower's copy/move assignment has basic guarantee, so should
-    // variant's.
-    Thrower rhs = ExpectedThrower();
-    // copy assign
-    auto copy_tester =
-        MakeExceptionSafetyTester()
-            .WithInitialValue(WithThrower())
-            .WithOperation([rhs](ThrowingVariant* lhs) { *lhs = rhs; });
-    EXPECT_TRUE(copy_tester
-                    .WithContracts(VariantInvariants,
-                                   [](ThrowingVariant* lhs) {
-                                     return !lhs->valueless_by_exception();
-                                   })
-                    .Test());
-    EXPECT_FALSE(copy_tester.WithContracts(strong_guarantee).Test());
-    // move assign
-    auto move_tester = MakeExceptionSafetyTester()
-                           .WithInitialValue(WithThrower())
-                           .WithOperation([&](ThrowingVariant* lhs) {
-                             auto copy = rhs;
-                             *lhs = std::move(copy);
-                           });
-    EXPECT_TRUE(move_tester
-                    .WithContracts(VariantInvariants,
-                                   [](ThrowingVariant* lhs) {
-                                     return !lhs->valueless_by_exception();
-                                   })
-                    .Test());
-
-    EXPECT_FALSE(move_tester.WithContracts(strong_guarantee).Test());
-  }
-  // Otherwise (*this holds something else), if is_nothrow_constructible_v<Tj,
-  // T> || !is_nothrow_move_constructible_v<Tj> is true, equivalent to
-  // emplace<j>(std::forward<T>(t)).
-  // We simplify the test by letting T = `const Tj&`  or `Tj&&`, so we can reuse
-  // the CopyNothrow and MoveNothrow types.
-
-  // if is_nothrow_constructible_v<Tj, T>
-  // (i.e. is_nothrow_copy/move_constructible_v<Tj>) is true, emplace() just
-  // invokes the copy/move constructor and it should not throw.
-  {
-    const CopyNothrow rhs;
-    ThrowingVariant lhs = WithThrower();
-    EXPECT_TRUE(TestNothrowOp([&]() { lhs = rhs; }));
-  }
-  {
-    MoveNothrow rhs;
-    ThrowingVariant lhs = WithThrower();
-    EXPECT_TRUE(TestNothrowOp([&]() { lhs = std::move(rhs); }));
-  }
-  // if is_nothrow_constructible_v<Tj, T> == false &&
-  // is_nothrow_move_constructible<Tj> == false
-  // emplace() invokes the copy/move constructor which may throw so it should
-  // provide basic guarantee and variant object might not hold a value.
-  {
-    Thrower rhs = ExpectedThrower();
-    // copy
-    auto copy_tester =
-        MakeExceptionSafetyTester()
-            .WithInitialValue(WithCopyNoThrow())
-            .WithOperation([&rhs](ThrowingVariant* lhs) { *lhs = rhs; });
-    EXPECT_TRUE(copy_tester
-                    .WithContracts(VariantInvariants,
-                                   [](ThrowingVariant* lhs) {
-                                     return lhs->valueless_by_exception();
-                                   })
-                    .Test());
-    EXPECT_FALSE(copy_tester.WithContracts(strong_guarantee).Test());
-    // move
-    auto move_tester = MakeExceptionSafetyTester()
-                           .WithInitialValue(WithCopyNoThrow())
-                           .WithOperation([](ThrowingVariant* lhs) {
-                             *lhs = ExpectedThrower(testing::nothrow_ctor);
-                           });
-    EXPECT_TRUE(move_tester
-                    .WithContracts(VariantInvariants,
-                                   [](ThrowingVariant* lhs) {
-                                     return lhs->valueless_by_exception();
-                                   })
-                    .Test());
-    EXPECT_FALSE(move_tester.WithContracts(strong_guarantee).Test());
-  }
-  // Otherwise (if is_nothrow_constructible_v<Tj, T> == false &&
-  // is_nothrow_move_constructible<Tj> == true),
-  // equivalent to operator=(variant(std::forward<T>(t)))
-  // This should have strong guarantee because it creates a temporary variant
-  // and operator=(variant&&) invokes Tj's move ctor which doesn't throw.
-  // libstdc++ std::variant has bugs on conversion assignment regarding
-  // exception safety.
-#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
-  {
-    MoveNothrow rhs;
-    EXPECT_TRUE(MakeExceptionSafetyTester()
-                    .WithInitialValue(WithThrower())
-                    .WithContracts(VariantInvariants, strong_guarantee)
-                    .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }));
-  }
-#endif  // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
-}
-
-TEST(VariantExceptionSafetyTest, Emplace) {
-  // If an exception during the initialization of the contained value, the
-  // variant might not hold a value. The standard requires emplace() to provide
-  // only basic guarantee.
-  {
-    Thrower args = ExpectedThrower();
-    auto tester = MakeExceptionSafetyTester()
-                      .WithInitialValue(WithThrower())
-                      .WithOperation([&args](ThrowingVariant* v) {
-                        v->emplace<Thrower>(args);
-                      });
-    EXPECT_TRUE(tester
-                    .WithContracts(VariantInvariants,
-                                   [](ThrowingVariant* v) {
-                                     return v->valueless_by_exception();
-                                   })
-                    .Test());
-    EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
-  }
-}
-
-TEST(VariantExceptionSafetyTest, Swap) {
-  // if both are valueless_by_exception(), no effect
-  {
-    ThrowingVariant rhs = ValuelessByException();
-    ThrowingVariant lhs = ValuelessByException();
-    EXPECT_TRUE(TestNothrowOp([&]() { lhs.swap(rhs); }));
-  }
-  // if index() == rhs.index(), calls swap(get<i>(*this), get<i>(rhs))
-  // where i is index().
-  {
-    ThrowingVariant rhs = ExpectedThrower();
-    EXPECT_TRUE(MakeExceptionSafetyTester()
-                    .WithInitialValue(WithThrower())
-                    .WithContracts(VariantInvariants)
-                    .Test([&](ThrowingVariant* lhs) {
-                      auto copy = rhs;
-                      lhs->swap(copy);
-                    }));
-  }
-  // Otherwise, exchanges the value of rhs and *this. The exception safety
-  // involves variant in moved-from state which is not specified in the
-  // standard, and since swap is 3-step it's impossible for it to provide a
-  // overall strong guarantee. So, we are only checking basic guarantee here.
-  {
-    ThrowingVariant rhs = ExpectedThrower();
-    EXPECT_TRUE(MakeExceptionSafetyTester()
-                    .WithInitialValue(WithCopyNoThrow())
-                    .WithContracts(VariantInvariants)
-                    .Test([&](ThrowingVariant* lhs) {
-                      auto copy = rhs;
-                      lhs->swap(copy);
-                    }));
-  }
-  {
-    ThrowingVariant rhs = ExpectedThrower();
-    EXPECT_TRUE(MakeExceptionSafetyTester()
-                    .WithInitialValue(WithCopyNoThrow())
-                    .WithContracts(VariantInvariants)
-                    .Test([&](ThrowingVariant* lhs) {
-                      auto copy = rhs;
-                      copy.swap(*lhs);
-                    }));
-  }
-}
-
-}  // namespace
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
-
-#endif  // #if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
index 91b142c..4d7b025 100644
--- a/absl/types/variant_test.cc
+++ b/absl/types/variant_test.cc
@@ -12,2255 +12,22 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-// Unit tests for the variant template. The 'is' and 'IsEmpty' methods
-// of variant are not explicitly tested because they are used repeatedly
-// in building other tests. All other public variant methods should have
-// explicit tests.
-
 #include "absl/types/variant.h"
 
-// This test is a no-op when absl::variant is an alias for std::variant.
-#if !defined(ABSL_USES_STD_VARIANT)
-
-#include <algorithm>
-#include <cstddef>
-#include <functional>
-#include <initializer_list>
 #include <memory>
-#include <ostream>
-#include <queue>
-#include <type_traits>
-#include <unordered_set>
-#include <utility>
-#include <vector>
+#include <string>
+#include <variant>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/base/port.h"
-#include "absl/memory/memory.h"
-#include "absl/meta/type_traits.h"
-#include "absl/strings/string_view.h"
-
-#ifdef ABSL_HAVE_EXCEPTIONS
-
-#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \
-  EXPECT_THROW(expr, exception_t)
-
-#else
-
-#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \
-  EXPECT_DEATH_IF_SUPPORTED(expr, text)
-
-#endif  // ABSL_HAVE_EXCEPTIONS
-
-#define ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(...)                 \
-  ABSL_VARIANT_TEST_EXPECT_FAIL((void)(__VA_ARGS__), absl::bad_variant_access, \
-                                "Bad variant access")
-
-struct Hashable {};
-
-namespace std {
-template <>
-struct hash<Hashable> {
-  size_t operator()(const Hashable&);
-};
-}  // namespace std
-
-struct NonHashable {};
 
 namespace absl {
-ABSL_NAMESPACE_BEGIN
 namespace {
 
 using ::testing::DoubleEq;
 using ::testing::Pointee;
 using ::testing::VariantWith;
 
-struct MoveCanThrow {
-  MoveCanThrow() : v(0) {}
-  MoveCanThrow(int v) : v(v) {}  // NOLINT(runtime/explicit)
-  MoveCanThrow(const MoveCanThrow& other) : v(other.v) {}
-  MoveCanThrow& operator=(const MoveCanThrow& /*other*/) { return *this; }
-  int v;
-};
-
-bool operator==(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v == rhs.v; }
-bool operator!=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v != rhs.v; }
-bool operator<(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v < rhs.v; }
-bool operator<=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v <= rhs.v; }
-bool operator>=(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v >= rhs.v; }
-bool operator>(MoveCanThrow lhs, MoveCanThrow rhs) { return lhs.v > rhs.v; }
-
-// This helper class allows us to determine if it was swapped with std::swap()
-// or with its friend swap() function.
-struct SpecialSwap {
-  explicit SpecialSwap(int i) : i(i) {}
-  friend void swap(SpecialSwap& a, SpecialSwap& b) {
-    a.special_swap = b.special_swap = true;
-    std::swap(a.i, b.i);
-  }
-  bool operator==(SpecialSwap other) const { return i == other.i; }
-  int i;
-  bool special_swap = false;
-};
-
-struct MoveOnlyWithListConstructor {
-  MoveOnlyWithListConstructor() = default;
-  explicit MoveOnlyWithListConstructor(std::initializer_list<int> /*ilist*/,
-                                       int value)
-      : value(value) {}
-  MoveOnlyWithListConstructor(MoveOnlyWithListConstructor&&) = default;
-  MoveOnlyWithListConstructor& operator=(MoveOnlyWithListConstructor&&) =
-      default;
-
-  int value = 0;
-};
-
-#ifdef ABSL_HAVE_EXCEPTIONS
-
-struct ConversionException {};
-
-template <class T>
-struct ExceptionOnConversion {
-  operator T() const {  // NOLINT(runtime/explicit)
-    throw ConversionException();
-  }
-};
-
-// Forces a variant into the valueless by exception state.
-template <class H, class... T>
-void ToValuelessByException(absl::variant<H, T...>& v) {  // NOLINT
-  try {
-    v.template emplace<0>(ExceptionOnConversion<H>());
-  } catch (ConversionException& /*e*/) {
-    // This space intentionally left blank.
-  }
-}
-
-#endif  // ABSL_HAVE_EXCEPTIONS
-
-// An indexed sequence of distinct structures holding a single
-// value of type T
-template<typename T, size_t N>
-struct ValueHolder {
-  explicit ValueHolder(const T& x) : value(x) {}
-  typedef T value_type;
-  value_type value;
-  static const size_t kIndex = N;
-};
-template<typename T, size_t N>
-const size_t ValueHolder<T, N>::kIndex;
-
-// The following three functions make ValueHolder compatible with
-// EXPECT_EQ and EXPECT_NE
-template<typename T, size_t N>
-inline bool operator==(const ValueHolder<T, N>& left,
-                       const ValueHolder<T, N>& right) {
-  return left.value == right.value;
-}
-
-template<typename T, size_t N>
-inline bool operator!=(const ValueHolder<T, N>& left,
-                       const ValueHolder<T, N>& right) {
-  return left.value != right.value;
-}
-
-template<typename T, size_t N>
-inline std::ostream& operator<<(
-    std::ostream& stream, const ValueHolder<T, N>& object) {
-  return stream << object.value;
-}
-
-// Makes a variant holding twelve uniquely typed T wrappers.
-template<typename T>
-struct VariantFactory {
-  typedef variant<ValueHolder<T, 1>, ValueHolder<T, 2>, ValueHolder<T, 3>,
-                  ValueHolder<T, 4>>
-      Type;
-};
-
-// A typelist in 1:1 with VariantFactory, to use type driven unit tests.
-typedef ::testing::Types<ValueHolder<size_t, 1>, ValueHolder<size_t, 2>,
-                         ValueHolder<size_t, 3>,
-                         ValueHolder<size_t, 4>> VariantTypes;
-
-// Increments the provided counter pointer in the destructor
-struct IncrementInDtor {
-  explicit IncrementInDtor(int* counter) : counter(counter) {}
-  ~IncrementInDtor() { *counter += 1; }
-  int* counter;
-};
-
-struct IncrementInDtorCopyCanThrow {
-  explicit IncrementInDtorCopyCanThrow(int* counter) : counter(counter) {}
-  IncrementInDtorCopyCanThrow(IncrementInDtorCopyCanThrow&& other) noexcept =
-      default;
-  IncrementInDtorCopyCanThrow(const IncrementInDtorCopyCanThrow& other)
-      : counter(other.counter) {}
-  IncrementInDtorCopyCanThrow& operator=(
-      IncrementInDtorCopyCanThrow&&) noexcept = default;
-  IncrementInDtorCopyCanThrow& operator=(
-      IncrementInDtorCopyCanThrow const& other) {
-    counter = other.counter;
-    return *this;
-  }
-  ~IncrementInDtorCopyCanThrow() { *counter += 1; }
-  int* counter;
-};
-
-// This is defined so operator== for ValueHolder<IncrementInDtor> will
-// return true if two IncrementInDtor objects increment the same
-// counter
-inline bool operator==(const IncrementInDtor& left,
-                       const IncrementInDtor& right) {
-  return left.counter == right.counter;
-}
-
-// This is defined so EXPECT_EQ can work with IncrementInDtor
-inline std::ostream& operator<<(
-    std::ostream& stream, const IncrementInDtor& object) {
-  return stream << object.counter;
-}
-
-// A class that can be copied, but not assigned.
-class CopyNoAssign {
- public:
-  explicit CopyNoAssign(int value) : foo(value) {}
-  CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
-  int foo;
- private:
-  const CopyNoAssign& operator=(const CopyNoAssign&);
-};
-
-// A class that can neither be copied nor assigned. We provide
-// overloads for the constructor with up to four parameters so we can
-// test the overloads of variant::emplace.
-class NonCopyable {
- public:
-  NonCopyable()
-      : value(0) {}
-  explicit NonCopyable(int value1)
-      : value(value1) {}
-
-  NonCopyable(int value1, int value2)
-      : value(value1 + value2) {}
-
-  NonCopyable(int value1, int value2, int value3)
-      : value(value1 + value2 + value3) {}
-
-  NonCopyable(int value1, int value2, int value3, int value4)
-      : value(value1 + value2 + value3 + value4) {}
-  NonCopyable(const NonCopyable&) = delete;
-  NonCopyable& operator=(const NonCopyable&) = delete;
-  int value;
-};
-
-// A typed test and typed test case over the VariantTypes typelist,
-// from which we derive a number of tests that will execute for one of
-// each type.
-template <typename T>
-class VariantTypesTest : public ::testing::Test {};
-TYPED_TEST_SUITE(VariantTypesTest, VariantTypes);
-
-////////////////////
-// [variant.ctor] //
-////////////////////
-
-struct NonNoexceptDefaultConstructible {
-  NonNoexceptDefaultConstructible() {}
-  int value = 5;
-};
-
-struct NonDefaultConstructible {
-  NonDefaultConstructible() = delete;
-};
-
-TEST(VariantTest, TestDefaultConstructor) {
-  {
-    using X = variant<int>;
-    constexpr variant<int> x{};
-    ASSERT_FALSE(x.valueless_by_exception());
-    ASSERT_EQ(0u, x.index());
-    EXPECT_EQ(0, absl::get<0>(x));
-    EXPECT_TRUE(std::is_nothrow_default_constructible<X>::value);
-  }
-
-  {
-    using X = variant<NonNoexceptDefaultConstructible>;
-    X x{};
-    ASSERT_FALSE(x.valueless_by_exception());
-    ASSERT_EQ(0u, x.index());
-    EXPECT_EQ(5, absl::get<0>(x).value);
-    EXPECT_FALSE(std::is_nothrow_default_constructible<X>::value);
-  }
-
-  {
-    using X = variant<int, NonNoexceptDefaultConstructible>;
-    X x{};
-    ASSERT_FALSE(x.valueless_by_exception());
-    ASSERT_EQ(0u, x.index());
-    EXPECT_EQ(0, absl::get<0>(x));
-    EXPECT_TRUE(std::is_nothrow_default_constructible<X>::value);
-  }
-
-  {
-    using X = variant<NonNoexceptDefaultConstructible, int>;
-    X x{};
-    ASSERT_FALSE(x.valueless_by_exception());
-    ASSERT_EQ(0u, x.index());
-    EXPECT_EQ(5, absl::get<0>(x).value);
-    EXPECT_FALSE(std::is_nothrow_default_constructible<X>::value);
-  }
-  EXPECT_FALSE(
-      std::is_default_constructible<variant<NonDefaultConstructible>>::value);
-  EXPECT_FALSE((std::is_default_constructible<
-                variant<NonDefaultConstructible, int>>::value));
-  EXPECT_TRUE((std::is_default_constructible<
-               variant<int, NonDefaultConstructible>>::value));
-}
-
-// Test that for each slot, copy constructing a variant with that type
-// produces a sensible object that correctly reports its type, and
-// that copies the provided value.
-TYPED_TEST(VariantTypesTest, TestCopyCtor) {
-  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
-  using value_type1 = absl::variant_alternative_t<0, Variant>;
-  using value_type2 = absl::variant_alternative_t<1, Variant>;
-  using value_type3 = absl::variant_alternative_t<2, Variant>;
-  using value_type4 = absl::variant_alternative_t<3, Variant>;
-  const TypeParam value(TypeParam::kIndex);
-  Variant original(value);
-  Variant copied(original);
-  EXPECT_TRUE(absl::holds_alternative<value_type1>(copied) ||
-              TypeParam::kIndex != 1);
-  EXPECT_TRUE(absl::holds_alternative<value_type2>(copied) ||
-              TypeParam::kIndex != 2);
-  EXPECT_TRUE(absl::holds_alternative<value_type3>(copied) ||
-              TypeParam::kIndex != 3);
-  EXPECT_TRUE(absl::holds_alternative<value_type4>(copied) ||
-              TypeParam::kIndex != 4);
-  EXPECT_TRUE((absl::get_if<value_type1>(&original) ==
-               absl::get_if<value_type1>(&copied)) ||
-              TypeParam::kIndex == 1);
-  EXPECT_TRUE((absl::get_if<value_type2>(&original) ==
-               absl::get_if<value_type2>(&copied)) ||
-              TypeParam::kIndex == 2);
-  EXPECT_TRUE((absl::get_if<value_type3>(&original) ==
-               absl::get_if<value_type3>(&copied)) ||
-              TypeParam::kIndex == 3);
-  EXPECT_TRUE((absl::get_if<value_type4>(&original) ==
-               absl::get_if<value_type4>(&copied)) ||
-              TypeParam::kIndex == 4);
-  EXPECT_TRUE((absl::get_if<value_type1>(&original) ==
-               absl::get_if<value_type1>(&copied)) ||
-              TypeParam::kIndex == 1);
-  EXPECT_TRUE((absl::get_if<value_type2>(&original) ==
-               absl::get_if<value_type2>(&copied)) ||
-              TypeParam::kIndex == 2);
-  EXPECT_TRUE((absl::get_if<value_type3>(&original) ==
-               absl::get_if<value_type3>(&copied)) ||
-              TypeParam::kIndex == 3);
-  EXPECT_TRUE((absl::get_if<value_type4>(&original) ==
-               absl::get_if<value_type4>(&copied)) ||
-              TypeParam::kIndex == 4);
-  const TypeParam* ovalptr = absl::get_if<TypeParam>(&original);
-  const TypeParam* cvalptr = absl::get_if<TypeParam>(&copied);
-  ASSERT_TRUE(ovalptr != nullptr);
-  ASSERT_TRUE(cvalptr != nullptr);
-  EXPECT_EQ(*ovalptr, *cvalptr);
-  TypeParam* mutable_ovalptr = absl::get_if<TypeParam>(&original);
-  TypeParam* mutable_cvalptr = absl::get_if<TypeParam>(&copied);
-  ASSERT_TRUE(mutable_ovalptr != nullptr);
-  ASSERT_TRUE(mutable_cvalptr != nullptr);
-  EXPECT_EQ(*mutable_ovalptr, *mutable_cvalptr);
-}
-
-template <class>
-struct MoveOnly {
-  MoveOnly() = default;
-  explicit MoveOnly(int value) : value(value) {}
-  MoveOnly(MoveOnly&&) = default;
-  MoveOnly& operator=(MoveOnly&&) = default;
-  int value = 5;
-};
-
-TEST(VariantTest, TestMoveConstruct) {
-  using V = variant<MoveOnly<class A>, MoveOnly<class B>, MoveOnly<class C>>;
-
-  V v(in_place_index<1>, 10);
-  V v2 = std::move(v);
-  EXPECT_EQ(10, absl::get<1>(v2).value);
-}
-
-// Used internally to emulate missing triviality traits for tests.
-template <class T>
-union SingleUnion {
-  T member;
-};
-
-// NOTE: These don't work with types that can't be union members.
-//       They are just for testing.
-template <class T>
-struct is_trivially_move_constructible
-    : std::is_move_constructible<SingleUnion<T>>::type {};
-
-template <class T>
-struct is_trivially_move_assignable
-    : absl::is_move_assignable<SingleUnion<T>>::type {};
-
-TEST(VariantTest, NothrowMoveConstructible) {
-  // Verify that variant is nothrow move constructible iff its template
-  // arguments are.
-  using U = std::unique_ptr<int>;
-  struct E {
-    E(E&&) {}
-  };
-  static_assert(std::is_nothrow_move_constructible<variant<U>>::value, "");
-  static_assert(std::is_nothrow_move_constructible<variant<U, int>>::value, "");
-  static_assert(!std::is_nothrow_move_constructible<variant<U, E>>::value, "");
-}
-
-// Test that for each slot, constructing a variant with that type
-// produces a sensible object that correctly reports its type, and
-// that copies the provided value.
-TYPED_TEST(VariantTypesTest, TestValueCtor) {
-  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
-  using value_type1 = absl::variant_alternative_t<0, Variant>;
-  using value_type2 = absl::variant_alternative_t<1, Variant>;
-  using value_type3 = absl::variant_alternative_t<2, Variant>;
-  using value_type4 = absl::variant_alternative_t<3, Variant>;
-  const TypeParam value(TypeParam::kIndex);
-  Variant v(value);
-  EXPECT_TRUE(absl::holds_alternative<value_type1>(v) ||
-              TypeParam::kIndex != 1);
-  EXPECT_TRUE(absl::holds_alternative<value_type2>(v) ||
-              TypeParam::kIndex != 2);
-  EXPECT_TRUE(absl::holds_alternative<value_type3>(v) ||
-              TypeParam::kIndex != 3);
-  EXPECT_TRUE(absl::holds_alternative<value_type4>(v) ||
-              TypeParam::kIndex != 4);
-  EXPECT_TRUE(nullptr != absl::get_if<value_type1>(&v) ||
-              TypeParam::kIndex != 1);
-  EXPECT_TRUE(nullptr != absl::get_if<value_type2>(&v) ||
-              TypeParam::kIndex != 2);
-  EXPECT_TRUE(nullptr != absl::get_if<value_type3>(&v) ||
-              TypeParam::kIndex != 3);
-  EXPECT_TRUE(nullptr != absl::get_if<value_type4>(&v) ||
-              TypeParam::kIndex != 4);
-  EXPECT_TRUE(nullptr != absl::get_if<value_type1>(&v) ||
-              TypeParam::kIndex != 1);
-  EXPECT_TRUE(nullptr != absl::get_if<value_type2>(&v) ||
-              TypeParam::kIndex != 2);
-  EXPECT_TRUE(nullptr != absl::get_if<value_type3>(&v) ||
-              TypeParam::kIndex != 3);
-  EXPECT_TRUE(nullptr != absl::get_if<value_type4>(&v) ||
-              TypeParam::kIndex != 4);
-  const TypeParam* valptr = absl::get_if<TypeParam>(&v);
-  ASSERT_TRUE(nullptr != valptr);
-  EXPECT_EQ(value.value, valptr->value);
-  const TypeParam* mutable_valptr = absl::get_if<TypeParam>(&v);
-  ASSERT_TRUE(nullptr != mutable_valptr);
-  EXPECT_EQ(value.value, mutable_valptr->value);
-}
-
-TEST(VariantTest, AmbiguousValueConstructor) {
-  EXPECT_FALSE((std::is_convertible<int, absl::variant<int, int>>::value));
-  EXPECT_FALSE((std::is_constructible<absl::variant<int, int>, int>::value));
-}
-
-TEST(VariantTest, InPlaceType) {
-  using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
-
-  Var v1(in_place_type_t<int>(), 7);
-  ASSERT_TRUE(absl::holds_alternative<int>(v1));
-  EXPECT_EQ(7, absl::get<int>(v1));
-
-  Var v2(in_place_type_t<std::string>(), "ABC");
-  ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
-  EXPECT_EQ("ABC", absl::get<std::string>(v2));
-
-  Var v3(in_place_type_t<std::string>(), "ABC", 2u);
-  ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
-  EXPECT_EQ("AB", absl::get<std::string>(v3));
-
-  Var v4(in_place_type_t<NonCopyable>{});
-  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v4));
-
-  Var v5(in_place_type_t<std::vector<int>>(), {1, 2, 3});
-  ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
-  EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
-}
-
-TEST(VariantTest, InPlaceTypeVariableTemplate) {
-  using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
-
-  Var v1(in_place_type<int>, 7);
-  ASSERT_TRUE(absl::holds_alternative<int>(v1));
-  EXPECT_EQ(7, absl::get<int>(v1));
-
-  Var v2(in_place_type<std::string>, "ABC");
-  ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
-  EXPECT_EQ("ABC", absl::get<std::string>(v2));
-
-  Var v3(in_place_type<std::string>, "ABC", 2u);
-  ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
-  EXPECT_EQ("AB", absl::get<std::string>(v3));
-
-  Var v4(in_place_type<NonCopyable>);
-  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v4));
-
-  Var v5(in_place_type<std::vector<int>>, {1, 2, 3});
-  ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
-  EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
-}
-
-TEST(VariantTest, InPlaceTypeInitializerList) {
-  using Var =
-      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
-
-  Var v1(in_place_type_t<MoveOnlyWithListConstructor>(), {1, 2, 3, 4, 5}, 6);
-  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
-  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
-}
-
-TEST(VariantTest, InPlaceTypeInitializerListVariabletemplate) {
-  using Var =
-      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
-
-  Var v1(in_place_type<MoveOnlyWithListConstructor>, {1, 2, 3, 4, 5}, 6);
-  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
-  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
-}
-
-TEST(VariantTest, InPlaceIndex) {
-  using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
-
-  Var v1(in_place_index_t<0>(), 7);
-  ASSERT_TRUE(absl::holds_alternative<int>(v1));
-  EXPECT_EQ(7, absl::get<int>(v1));
-
-  Var v2(in_place_index_t<1>(), "ABC");
-  ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
-  EXPECT_EQ("ABC", absl::get<std::string>(v2));
-
-  Var v3(in_place_index_t<1>(), "ABC", 2u);
-  ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
-  EXPECT_EQ("AB", absl::get<std::string>(v3));
-
-  Var v4(in_place_index_t<2>{});
-  EXPECT_TRUE(absl::holds_alternative<NonCopyable>(v4));
-
-  // Verify that a variant with only non-copyables can still be constructed.
-  EXPECT_TRUE(absl::holds_alternative<NonCopyable>(
-      variant<NonCopyable>(in_place_index_t<0>{})));
-
-  Var v5(in_place_index_t<3>(), {1, 2, 3});
-  ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
-  EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
-}
-
-TEST(VariantTest, InPlaceIndexVariableTemplate) {
-  using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
-
-  Var v1(in_place_index<0>, 7);
-  ASSERT_TRUE(absl::holds_alternative<int>(v1));
-  EXPECT_EQ(7, absl::get<int>(v1));
-
-  Var v2(in_place_index<1>, "ABC");
-  ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
-  EXPECT_EQ("ABC", absl::get<std::string>(v2));
-
-  Var v3(in_place_index<1>, "ABC", 2u);
-  ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
-  EXPECT_EQ("AB", absl::get<std::string>(v3));
-
-  Var v4(in_place_index<2>);
-  EXPECT_TRUE(absl::holds_alternative<NonCopyable>(v4));
-
-  // Verify that a variant with only non-copyables can still be constructed.
-  EXPECT_TRUE(absl::holds_alternative<NonCopyable>(
-      variant<NonCopyable>(in_place_index<0>)));
-
-  Var v5(in_place_index<3>, {1, 2, 3});
-  ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
-  EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
-}
-
-TEST(VariantTest, InPlaceIndexInitializerList) {
-  using Var =
-      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
-
-  Var v1(in_place_index_t<3>(), {1, 2, 3, 4, 5}, 6);
-  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
-  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
-}
-
-TEST(VariantTest, InPlaceIndexInitializerListVariableTemplate) {
-  using Var =
-      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
-
-  Var v1(in_place_index<3>, {1, 2, 3, 4, 5}, 6);
-  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
-  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
-}
-
-////////////////////
-// [variant.dtor] //
-////////////////////
-
-// Make sure that the destructor destroys the contained value
-TEST(VariantTest, TestDtor) {
-  typedef VariantFactory<IncrementInDtor>::Type Variant;
-  using value_type1 = absl::variant_alternative_t<0, Variant>;
-  using value_type2 = absl::variant_alternative_t<1, Variant>;
-  using value_type3 = absl::variant_alternative_t<2, Variant>;
-  using value_type4 = absl::variant_alternative_t<3, Variant>;
-  int counter = 0;
-  IncrementInDtor counter_adjuster(&counter);
-  EXPECT_EQ(0, counter);
-
-  value_type1 value1(counter_adjuster);
-  { Variant object(value1); }
-  EXPECT_EQ(1, counter);
-
-  value_type2 value2(counter_adjuster);
-  { Variant object(value2); }
-  EXPECT_EQ(2, counter);
-
-  value_type3 value3(counter_adjuster);
-  { Variant object(value3); }
-  EXPECT_EQ(3, counter);
-
-  value_type4 value4(counter_adjuster);
-  { Variant object(value4); }
-  EXPECT_EQ(4, counter);
-}
-
-#ifdef ABSL_HAVE_EXCEPTIONS
-
-// See comment in absl/base/config.h
-#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
-TEST(VariantTest, DISABLED_TestDtorValuelessByException)
-#else
-// Test destruction when in the valueless_by_exception state.
-TEST(VariantTest, TestDtorValuelessByException)
-#endif
-{
-  int counter = 0;
-  IncrementInDtor counter_adjuster(&counter);
-
-  {
-    using Variant = VariantFactory<IncrementInDtor>::Type;
-
-    Variant v(in_place_index<0>, counter_adjuster);
-    EXPECT_EQ(0, counter);
-
-    ToValuelessByException(v);
-    ASSERT_TRUE(v.valueless_by_exception());
-    EXPECT_EQ(1, counter);
-  }
-  EXPECT_EQ(1, counter);
-}
-
-#endif  // ABSL_HAVE_EXCEPTIONS
-
-//////////////////////
-// [variant.assign] //
-//////////////////////
-
-// Test that self-assignment doesn't destroy the current value
-TEST(VariantTest, TestSelfAssignment) {
-  typedef VariantFactory<IncrementInDtor>::Type Variant;
-  int counter = 0;
-  IncrementInDtor counter_adjuster(&counter);
-  absl::variant_alternative_t<0, Variant> value(counter_adjuster);
-  Variant object(value);
-  object.operator=(object);
-  EXPECT_EQ(0, counter);
-
-  // A string long enough that it's likely to defeat any inline representation
-  // optimization.
-  const std::string long_str(128, 'a');
-
-  std::string foo = long_str;
-  foo = *&foo;
-  EXPECT_EQ(long_str, foo);
-
-  variant<int, std::string> so = long_str;
-  ASSERT_EQ(1u, so.index());
-  EXPECT_EQ(long_str, absl::get<1>(so));
-  so = *&so;
-
-  ASSERT_EQ(1u, so.index());
-  EXPECT_EQ(long_str, absl::get<1>(so));
-}
-
-// Test that assigning a variant<..., T, ...> to a variant<..., T, ...> produces
-// a variant<..., T, ...> with the correct value.
-TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValueSameTypes) {
-  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
-  const TypeParam value(TypeParam::kIndex);
-  const Variant source(value);
-  Variant target(TypeParam(value.value + 1));
-  ASSERT_TRUE(absl::holds_alternative<TypeParam>(source));
-  ASSERT_TRUE(absl::holds_alternative<TypeParam>(target));
-  ASSERT_NE(absl::get<TypeParam>(source), absl::get<TypeParam>(target));
-  target = source;
-  ASSERT_TRUE(absl::holds_alternative<TypeParam>(source));
-  ASSERT_TRUE(absl::holds_alternative<TypeParam>(target));
-  EXPECT_EQ(absl::get<TypeParam>(source), absl::get<TypeParam>(target));
-}
-
-// Test that assisnging a variant<..., T, ...> to a variant<1, ...>
-// produces a variant<..., T, ...> with the correct value.
-TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValuesVaryingSourceType) {
-  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
-  using value_type1 = absl::variant_alternative_t<0, Variant>;
-  const TypeParam value(TypeParam::kIndex);
-  const Variant source(value);
-  ASSERT_TRUE(absl::holds_alternative<TypeParam>(source));
-  Variant target(value_type1(1));
-  ASSERT_TRUE(absl::holds_alternative<value_type1>(target));
-  target = source;
-  EXPECT_TRUE(absl::holds_alternative<TypeParam>(source));
-  EXPECT_TRUE(absl::holds_alternative<TypeParam>(target));
-  EXPECT_EQ(absl::get<TypeParam>(source), absl::get<TypeParam>(target));
-}
-
-// Test that assigning a variant<1, ...> to a variant<..., T, ...>
-// produces a variant<1, ...> with the correct value.
-TYPED_TEST(VariantTypesTest, TestAssignmentCopiesValuesVaryingTargetType) {
-  typedef typename VariantFactory<typename TypeParam::value_type>::Type Variant;
-  using value_type1 = absl::variant_alternative_t<0, Variant>;
-  const Variant source(value_type1(1));
-  ASSERT_TRUE(absl::holds_alternative<value_type1>(source));
-  const TypeParam value(TypeParam::kIndex);
-  Variant target(value);
-  ASSERT_TRUE(absl::holds_alternative<TypeParam>(target));
-  target = source;
-  EXPECT_TRUE(absl::holds_alternative<value_type1>(target));
-  EXPECT_TRUE(absl::holds_alternative<value_type1>(source));
-  EXPECT_EQ(absl::get<value_type1>(source), absl::get<value_type1>(target));
-}
-
-// Test that operator=<T> works, that assigning a new value destroys
-// the old and that assigning the new value again does not redestroy
-// the old
-TEST(VariantTest, TestAssign) {
-  typedef VariantFactory<IncrementInDtor>::Type Variant;
-  using value_type1 = absl::variant_alternative_t<0, Variant>;
-  using value_type2 = absl::variant_alternative_t<1, Variant>;
-  using value_type3 = absl::variant_alternative_t<2, Variant>;
-  using value_type4 = absl::variant_alternative_t<3, Variant>;
-
-  const int kSize = 4;
-  int counter[kSize];
-  std::unique_ptr<IncrementInDtor> counter_adjustor[kSize];
-  for (int i = 0; i != kSize; i++) {
-    counter[i] = 0;
-    counter_adjustor[i] = absl::make_unique<IncrementInDtor>(&counter[i]);
-  }
-
-  value_type1 v1(*counter_adjustor[0]);
-  value_type2 v2(*counter_adjustor[1]);
-  value_type3 v3(*counter_adjustor[2]);
-  value_type4 v4(*counter_adjustor[3]);
-
-  // Test that reassignment causes destruction of old value
-  {
-    Variant object(v1);
-    object = v2;
-    object = v3;
-    object = v4;
-    object = v1;
-  }
-
-  EXPECT_EQ(2, counter[0]);
-  EXPECT_EQ(1, counter[1]);
-  EXPECT_EQ(1, counter[2]);
-  EXPECT_EQ(1, counter[3]);
-
-  std::fill(std::begin(counter), std::end(counter), 0);
-
-  // Test that self-assignment does not cause destruction of old value
-  {
-    Variant object(v1);
-    object.operator=(object);
-    EXPECT_EQ(0, counter[0]);
-  }
-  {
-    Variant object(v2);
-    object.operator=(object);
-    EXPECT_EQ(0, counter[1]);
-  }
-  {
-    Variant object(v3);
-    object.operator=(object);
-    EXPECT_EQ(0, counter[2]);
-  }
-  {
-    Variant object(v4);
-    object.operator=(object);
-    EXPECT_EQ(0, counter[3]);
-  }
-
-  EXPECT_EQ(1, counter[0]);
-  EXPECT_EQ(1, counter[1]);
-  EXPECT_EQ(1, counter[2]);
-  EXPECT_EQ(1, counter[3]);
-}
-
-// This tests that we perform a backup if the copy-assign can throw but the move
-// cannot throw.
-TEST(VariantTest, TestBackupAssign) {
-  typedef VariantFactory<IncrementInDtorCopyCanThrow>::Type Variant;
-  using value_type1 = absl::variant_alternative_t<0, Variant>;
-  using value_type2 = absl::variant_alternative_t<1, Variant>;
-  using value_type3 = absl::variant_alternative_t<2, Variant>;
-  using value_type4 = absl::variant_alternative_t<3, Variant>;
-
-  const int kSize = 4;
-  int counter[kSize];
-  std::unique_ptr<IncrementInDtorCopyCanThrow> counter_adjustor[kSize];
-  for (int i = 0; i != kSize; i++) {
-    counter[i] = 0;
-    counter_adjustor[i].reset(new IncrementInDtorCopyCanThrow(&counter[i]));
-  }
-
-  value_type1 v1(*counter_adjustor[0]);
-  value_type2 v2(*counter_adjustor[1]);
-  value_type3 v3(*counter_adjustor[2]);
-  value_type4 v4(*counter_adjustor[3]);
-
-  // Test that reassignment causes destruction of old value
-  {
-    Variant object(v1);
-    object = v2;
-    object = v3;
-    object = v4;
-    object = v1;
-  }
-
-  // libstdc++ doesn't pass this test
-#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
-  EXPECT_EQ(3, counter[0]);
-  EXPECT_EQ(2, counter[1]);
-  EXPECT_EQ(2, counter[2]);
-  EXPECT_EQ(2, counter[3]);
-#endif
-
-  std::fill(std::begin(counter), std::end(counter), 0);
-
-  // Test that self-assignment does not cause destruction of old value
-  {
-    Variant object(v1);
-    object.operator=(object);
-    EXPECT_EQ(0, counter[0]);
-  }
-  {
-    Variant object(v2);
-    object.operator=(object);
-    EXPECT_EQ(0, counter[1]);
-  }
-  {
-    Variant object(v3);
-    object.operator=(object);
-    EXPECT_EQ(0, counter[2]);
-  }
-  {
-    Variant object(v4);
-    object.operator=(object);
-    EXPECT_EQ(0, counter[3]);
-  }
-
-  EXPECT_EQ(1, counter[0]);
-  EXPECT_EQ(1, counter[1]);
-  EXPECT_EQ(1, counter[2]);
-  EXPECT_EQ(1, counter[3]);
-}
-
-///////////////////
-// [variant.mod] //
-///////////////////
-
-TEST(VariantTest, TestEmplaceBasic) {
-  using Variant = variant<int, char>;
-
-  Variant v(absl::in_place_index<0>, 0);
-
-  {
-    char& emplace_result = v.emplace<char>();
-    ASSERT_TRUE(absl::holds_alternative<char>(v));
-    EXPECT_EQ(absl::get<char>(v), 0);
-    EXPECT_EQ(&emplace_result, &absl::get<char>(v));
-  }
-
-  // Make sure that another emplace does zero-initialization
-  absl::get<char>(v) = 'a';
-  v.emplace<char>('b');
-  ASSERT_TRUE(absl::holds_alternative<char>(v));
-  EXPECT_EQ(absl::get<char>(v), 'b');
-
-  {
-    int& emplace_result = v.emplace<int>();
-    EXPECT_TRUE(absl::holds_alternative<int>(v));
-    EXPECT_EQ(absl::get<int>(v), 0);
-    EXPECT_EQ(&emplace_result, &absl::get<int>(v));
-  }
-}
-
-TEST(VariantTest, TestEmplaceInitializerList) {
-  using Var =
-      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
-
-  Var v1(absl::in_place_index<0>, 555);
-  MoveOnlyWithListConstructor& emplace_result =
-      v1.emplace<MoveOnlyWithListConstructor>({1, 2, 3, 4, 5}, 6);
-  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
-  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
-  EXPECT_EQ(&emplace_result, &absl::get<MoveOnlyWithListConstructor>(v1));
-}
-
-TEST(VariantTest, TestEmplaceIndex) {
-  using Variant = variant<int, char>;
-
-  Variant v(absl::in_place_index<0>, 555);
-
-  {
-    char& emplace_result = v.emplace<1>();
-    ASSERT_TRUE(absl::holds_alternative<char>(v));
-    EXPECT_EQ(absl::get<char>(v), 0);
-    EXPECT_EQ(&emplace_result, &absl::get<char>(v));
-  }
-
-  // Make sure that another emplace does zero-initialization
-  absl::get<char>(v) = 'a';
-  v.emplace<1>('b');
-  ASSERT_TRUE(absl::holds_alternative<char>(v));
-  EXPECT_EQ(absl::get<char>(v), 'b');
-
-  {
-    int& emplace_result = v.emplace<0>();
-    EXPECT_TRUE(absl::holds_alternative<int>(v));
-    EXPECT_EQ(absl::get<int>(v), 0);
-    EXPECT_EQ(&emplace_result, &absl::get<int>(v));
-  }
-}
-
-TEST(VariantTest, TestEmplaceIndexInitializerList) {
-  using Var =
-      variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
-
-  Var v1(absl::in_place_index<0>, 555);
-  MoveOnlyWithListConstructor& emplace_result =
-      v1.emplace<3>({1, 2, 3, 4, 5}, 6);
-  ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
-  EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
-  EXPECT_EQ(&emplace_result, &absl::get<MoveOnlyWithListConstructor>(v1));
-}
-
-//////////////////////
-// [variant.status] //
-//////////////////////
-
-TEST(VariantTest, Index) {
-  using Var = variant<int, std::string, double>;
-
-  Var v = 1;
-  EXPECT_EQ(0u, v.index());
-  v = "str";
-  EXPECT_EQ(1u, v.index());
-  v = 0.;
-  EXPECT_EQ(2u, v.index());
-
-  Var v2 = v;
-  EXPECT_EQ(2u, v2.index());
-  v2.emplace<int>(3);
-  EXPECT_EQ(0u, v2.index());
-}
-
-TEST(VariantTest, NotValuelessByException) {
-  using Var = variant<int, std::string, double>;
-
-  Var v = 1;
-  EXPECT_FALSE(v.valueless_by_exception());
-  v = "str";
-  EXPECT_FALSE(v.valueless_by_exception());
-  v = 0.;
-  EXPECT_FALSE(v.valueless_by_exception());
-
-  Var v2 = v;
-  EXPECT_FALSE(v.valueless_by_exception());
-  v2.emplace<int>(3);
-  EXPECT_FALSE(v.valueless_by_exception());
-}
-
-#ifdef ABSL_HAVE_EXCEPTIONS
-
-TEST(VariantTest, IndexValuelessByException) {
-  using Var = variant<MoveCanThrow, std::string, double>;
-
-  Var v(absl::in_place_index<0>);
-  EXPECT_EQ(0u, v.index());
-  ToValuelessByException(v);
-  EXPECT_EQ(absl::variant_npos, v.index());
-  v = "str";
-  EXPECT_EQ(1u, v.index());
-}
-
-TEST(VariantTest, ValuelessByException) {
-  using Var = variant<MoveCanThrow, std::string, double>;
-
-  Var v(absl::in_place_index<0>);
-  EXPECT_FALSE(v.valueless_by_exception());
-  ToValuelessByException(v);
-  EXPECT_TRUE(v.valueless_by_exception());
-  v = "str";
-  EXPECT_FALSE(v.valueless_by_exception());
-}
-
-#endif  // ABSL_HAVE_EXCEPTIONS
-
-////////////////////
-// [variant.swap] //
-////////////////////
-
-TEST(VariantTest, MemberSwap) {
-  SpecialSwap v1(3);
-  SpecialSwap v2(7);
-
-  variant<SpecialSwap> a = v1, b = v2;
-
-  EXPECT_THAT(a, VariantWith<SpecialSwap>(v1));
-  EXPECT_THAT(b, VariantWith<SpecialSwap>(v2));
-
-  a.swap(b);
-  EXPECT_THAT(a, VariantWith<SpecialSwap>(v2));
-  EXPECT_THAT(b, VariantWith<SpecialSwap>(v1));
-  EXPECT_TRUE(absl::get<SpecialSwap>(a).special_swap);
-
-  using V = variant<MoveCanThrow, std::string, int>;
-  int i = 33;
-  std::string s = "abc";
-  {
-    // lhs and rhs holds different alternative
-    V lhs(i), rhs(s);
-    lhs.swap(rhs);
-    EXPECT_THAT(lhs, VariantWith<std::string>(s));
-    EXPECT_THAT(rhs, VariantWith<int>(i));
-  }
-#ifdef ABSL_HAVE_EXCEPTIONS
-  V valueless(in_place_index<0>);
-  ToValuelessByException(valueless);
-  {
-    // lhs is valueless
-    V lhs(valueless), rhs(i);
-    lhs.swap(rhs);
-    EXPECT_THAT(lhs, VariantWith<int>(i));
-    EXPECT_TRUE(rhs.valueless_by_exception());
-  }
-  {
-    // rhs is valueless
-    V lhs(s), rhs(valueless);
-    lhs.swap(rhs);
-    EXPECT_THAT(rhs, VariantWith<std::string>(s));
-    EXPECT_TRUE(lhs.valueless_by_exception());
-  }
-  {
-    // both are valueless
-    V lhs(valueless), rhs(valueless);
-    lhs.swap(rhs);
-    EXPECT_TRUE(lhs.valueless_by_exception());
-    EXPECT_TRUE(rhs.valueless_by_exception());
-  }
-#endif  // ABSL_HAVE_EXCEPTIONS
-}
-
-//////////////////////
-// [variant.helper] //
-//////////////////////
-
-TEST(VariantTest, VariantSize) {
-  {
-    using Size1Variant = absl::variant<int>;
-    EXPECT_EQ(1u, absl::variant_size<Size1Variant>::value);
-    EXPECT_EQ(1u, absl::variant_size<const Size1Variant>::value);
-    EXPECT_EQ(1u, absl::variant_size<volatile Size1Variant>::value);
-    EXPECT_EQ(1u, absl::variant_size<const volatile Size1Variant>::value);
-  }
-
-  {
-    using Size3Variant = absl::variant<int, float, int>;
-    EXPECT_EQ(3u, absl::variant_size<Size3Variant>::value);
-    EXPECT_EQ(3u, absl::variant_size<const Size3Variant>::value);
-    EXPECT_EQ(3u, absl::variant_size<volatile Size3Variant>::value);
-    EXPECT_EQ(3u, absl::variant_size<const volatile Size3Variant>::value);
-  }
-}
-
-TEST(VariantTest, VariantAlternative) {
-  {
-    using V = absl::variant<float, int, const char*>;
-    EXPECT_TRUE(
-        (std::is_same<float, absl::variant_alternative_t<0, V>>::value));
-    EXPECT_TRUE((std::is_same<const float,
-                              absl::variant_alternative_t<0, const V>>::value));
-    EXPECT_TRUE(
-        (std::is_same<volatile float,
-                      absl::variant_alternative_t<0, volatile V>>::value));
-    EXPECT_TRUE((
-        std::is_same<const volatile float,
-                     absl::variant_alternative_t<0, const volatile V>>::value));
-
-    EXPECT_TRUE((std::is_same<int, absl::variant_alternative_t<1, V>>::value));
-    EXPECT_TRUE((std::is_same<const int,
-                              absl::variant_alternative_t<1, const V>>::value));
-    EXPECT_TRUE(
-        (std::is_same<volatile int,
-                      absl::variant_alternative_t<1, volatile V>>::value));
-    EXPECT_TRUE((
-        std::is_same<const volatile int,
-                     absl::variant_alternative_t<1, const volatile V>>::value));
-
-    EXPECT_TRUE(
-        (std::is_same<const char*, absl::variant_alternative_t<2, V>>::value));
-    EXPECT_TRUE((std::is_same<const char* const,
-                              absl::variant_alternative_t<2, const V>>::value));
-    EXPECT_TRUE(
-        (std::is_same<const char* volatile,
-                      absl::variant_alternative_t<2, volatile V>>::value));
-    EXPECT_TRUE((
-        std::is_same<const char* const volatile,
-                     absl::variant_alternative_t<2, const volatile V>>::value));
-  }
-
-  {
-    using V = absl::variant<float, volatile int, const char*>;
-    EXPECT_TRUE(
-        (std::is_same<float, absl::variant_alternative_t<0, V>>::value));
-    EXPECT_TRUE((std::is_same<const float,
-                              absl::variant_alternative_t<0, const V>>::value));
-    EXPECT_TRUE(
-        (std::is_same<volatile float,
-                      absl::variant_alternative_t<0, volatile V>>::value));
-    EXPECT_TRUE((
-        std::is_same<const volatile float,
-                     absl::variant_alternative_t<0, const volatile V>>::value));
-
-    EXPECT_TRUE(
-        (std::is_same<volatile int, absl::variant_alternative_t<1, V>>::value));
-    EXPECT_TRUE((std::is_same<const volatile int,
-                              absl::variant_alternative_t<1, const V>>::value));
-    EXPECT_TRUE(
-        (std::is_same<volatile int,
-                      absl::variant_alternative_t<1, volatile V>>::value));
-    EXPECT_TRUE((
-        std::is_same<const volatile int,
-                     absl::variant_alternative_t<1, const volatile V>>::value));
-
-    EXPECT_TRUE(
-        (std::is_same<const char*, absl::variant_alternative_t<2, V>>::value));
-    EXPECT_TRUE((std::is_same<const char* const,
-                              absl::variant_alternative_t<2, const V>>::value));
-    EXPECT_TRUE(
-        (std::is_same<const char* volatile,
-                      absl::variant_alternative_t<2, volatile V>>::value));
-    EXPECT_TRUE((
-        std::is_same<const char* const volatile,
-                     absl::variant_alternative_t<2, const volatile V>>::value));
-  }
-}
-
-///////////////////
-// [variant.get] //
-///////////////////
-
-TEST(VariantTest, HoldsAlternative) {
-  using Var = variant<int, std::string, double>;
-
-  Var v = 1;
-  EXPECT_TRUE(absl::holds_alternative<int>(v));
-  EXPECT_FALSE(absl::holds_alternative<std::string>(v));
-  EXPECT_FALSE(absl::holds_alternative<double>(v));
-  v = "str";
-  EXPECT_FALSE(absl::holds_alternative<int>(v));
-  EXPECT_TRUE(absl::holds_alternative<std::string>(v));
-  EXPECT_FALSE(absl::holds_alternative<double>(v));
-  v = 0.;
-  EXPECT_FALSE(absl::holds_alternative<int>(v));
-  EXPECT_FALSE(absl::holds_alternative<std::string>(v));
-  EXPECT_TRUE(absl::holds_alternative<double>(v));
-
-  Var v2 = v;
-  EXPECT_FALSE(absl::holds_alternative<int>(v2));
-  EXPECT_FALSE(absl::holds_alternative<std::string>(v2));
-  EXPECT_TRUE(absl::holds_alternative<double>(v2));
-  v2.emplace<int>(3);
-  EXPECT_TRUE(absl::holds_alternative<int>(v2));
-  EXPECT_FALSE(absl::holds_alternative<std::string>(v2));
-  EXPECT_FALSE(absl::holds_alternative<double>(v2));
-}
-
-TEST(VariantTest, GetIndex) {
-  using Var = variant<int, std::string, double, int>;
-
-  {
-    Var v(absl::in_place_index<0>, 0);
-
-    using LValueGetType = decltype(absl::get<0>(v));
-    using RValueGetType = decltype(absl::get<0>(std::move(v)));
-
-    EXPECT_TRUE((std::is_same<LValueGetType, int&>::value));
-    EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value));
-    EXPECT_EQ(absl::get<0>(v), 0);
-    EXPECT_EQ(absl::get<0>(std::move(v)), 0);
-
-    const Var& const_v = v;
-    using ConstLValueGetType = decltype(absl::get<0>(const_v));
-    using ConstRValueGetType = decltype(absl::get<0>(std::move(const_v)));
-    EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value));
-    EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value));
-    EXPECT_EQ(absl::get<0>(const_v), 0);
-    EXPECT_EQ(absl::get<0>(std::move(const_v)), 0);
-  }
-
-  {
-    Var v = std::string("Hello");
-
-    using LValueGetType = decltype(absl::get<1>(v));
-    using RValueGetType = decltype(absl::get<1>(std::move(v)));
-
-    EXPECT_TRUE((std::is_same<LValueGetType, std::string&>::value));
-    EXPECT_TRUE((std::is_same<RValueGetType, std::string&&>::value));
-    EXPECT_EQ(absl::get<1>(v), "Hello");
-    EXPECT_EQ(absl::get<1>(std::move(v)), "Hello");
-
-    const Var& const_v = v;
-    using ConstLValueGetType = decltype(absl::get<1>(const_v));
-    using ConstRValueGetType = decltype(absl::get<1>(std::move(const_v)));
-    EXPECT_TRUE((std::is_same<ConstLValueGetType, const std::string&>::value));
-    EXPECT_TRUE((std::is_same<ConstRValueGetType, const std::string&&>::value));
-    EXPECT_EQ(absl::get<1>(const_v), "Hello");
-    EXPECT_EQ(absl::get<1>(std::move(const_v)), "Hello");
-  }
-
-  {
-    Var v = 2.0;
-
-    using LValueGetType = decltype(absl::get<2>(v));
-    using RValueGetType = decltype(absl::get<2>(std::move(v)));
-
-    EXPECT_TRUE((std::is_same<LValueGetType, double&>::value));
-    EXPECT_TRUE((std::is_same<RValueGetType, double&&>::value));
-    EXPECT_EQ(absl::get<2>(v), 2.);
-    EXPECT_EQ(absl::get<2>(std::move(v)), 2.);
-
-    const Var& const_v = v;
-    using ConstLValueGetType = decltype(absl::get<2>(const_v));
-    using ConstRValueGetType = decltype(absl::get<2>(std::move(const_v)));
-    EXPECT_TRUE((std::is_same<ConstLValueGetType, const double&>::value));
-    EXPECT_TRUE((std::is_same<ConstRValueGetType, const double&&>::value));
-    EXPECT_EQ(absl::get<2>(const_v), 2.);
-    EXPECT_EQ(absl::get<2>(std::move(const_v)), 2.);
-  }
-
-  {
-    Var v(absl::in_place_index<0>, 0);
-    v.emplace<3>(1);
-
-    using LValueGetType = decltype(absl::get<3>(v));
-    using RValueGetType = decltype(absl::get<3>(std::move(v)));
-
-    EXPECT_TRUE((std::is_same<LValueGetType, int&>::value));
-    EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value));
-    EXPECT_EQ(absl::get<3>(v), 1);
-    EXPECT_EQ(absl::get<3>(std::move(v)), 1);
-
-    const Var& const_v = v;
-    using ConstLValueGetType = decltype(absl::get<3>(const_v));
-    using ConstRValueGetType = decltype(absl::get<3>(std::move(const_v)));
-    EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value));
-    EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value));
-    EXPECT_EQ(absl::get<3>(const_v), 1);
-    EXPECT_EQ(absl::get<3>(std::move(const_v)), 1);  // NOLINT
-  }
-}
-
-TEST(VariantTest, BadGetIndex) {
-  using Var = variant<int, std::string, double>;
-
-  {
-    Var v = 1;
-
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(v));
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(std::move(v)));
-
-    const Var& const_v = v;
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<1>(const_v));
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
-        absl::get<1>(std::move(const_v)));  // NOLINT
-  }
-
-  {
-    Var v = std::string("Hello");
-
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(v));
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(std::move(v)));
-
-    const Var& const_v = v;
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<0>(const_v));
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
-        absl::get<0>(std::move(const_v)));  // NOLINT
-  }
-}
-
-TEST(VariantTest, GetType) {
-  using Var = variant<int, std::string, double>;
-
-  {
-    Var v = 1;
-
-    using LValueGetType = decltype(absl::get<int>(v));
-    using RValueGetType = decltype(absl::get<int>(std::move(v)));
-
-    EXPECT_TRUE((std::is_same<LValueGetType, int&>::value));
-    EXPECT_TRUE((std::is_same<RValueGetType, int&&>::value));
-    EXPECT_EQ(absl::get<int>(v), 1);
-    EXPECT_EQ(absl::get<int>(std::move(v)), 1);
-
-    const Var& const_v = v;
-    using ConstLValueGetType = decltype(absl::get<int>(const_v));
-    using ConstRValueGetType = decltype(absl::get<int>(std::move(const_v)));
-    EXPECT_TRUE((std::is_same<ConstLValueGetType, const int&>::value));
-    EXPECT_TRUE((std::is_same<ConstRValueGetType, const int&&>::value));
-    EXPECT_EQ(absl::get<int>(const_v), 1);
-    EXPECT_EQ(absl::get<int>(std::move(const_v)), 1);
-  }
-
-  {
-    Var v = std::string("Hello");
-
-    using LValueGetType = decltype(absl::get<1>(v));
-    using RValueGetType = decltype(absl::get<1>(std::move(v)));
-
-    EXPECT_TRUE((std::is_same<LValueGetType, std::string&>::value));
-    EXPECT_TRUE((std::is_same<RValueGetType, std::string&&>::value));
-    EXPECT_EQ(absl::get<std::string>(v), "Hello");
-    EXPECT_EQ(absl::get<std::string>(std::move(v)), "Hello");
-
-    const Var& const_v = v;
-    using ConstLValueGetType = decltype(absl::get<1>(const_v));
-    using ConstRValueGetType = decltype(absl::get<1>(std::move(const_v)));
-    EXPECT_TRUE((std::is_same<ConstLValueGetType, const std::string&>::value));
-    EXPECT_TRUE((std::is_same<ConstRValueGetType, const std::string&&>::value));
-    EXPECT_EQ(absl::get<std::string>(const_v), "Hello");
-    EXPECT_EQ(absl::get<std::string>(std::move(const_v)), "Hello");
-  }
-
-  {
-    Var v = 2.0;
-
-    using LValueGetType = decltype(absl::get<2>(v));
-    using RValueGetType = decltype(absl::get<2>(std::move(v)));
-
-    EXPECT_TRUE((std::is_same<LValueGetType, double&>::value));
-    EXPECT_TRUE((std::is_same<RValueGetType, double&&>::value));
-    EXPECT_EQ(absl::get<double>(v), 2.);
-    EXPECT_EQ(absl::get<double>(std::move(v)), 2.);
-
-    const Var& const_v = v;
-    using ConstLValueGetType = decltype(absl::get<2>(const_v));
-    using ConstRValueGetType = decltype(absl::get<2>(std::move(const_v)));
-    EXPECT_TRUE((std::is_same<ConstLValueGetType, const double&>::value));
-    EXPECT_TRUE((std::is_same<ConstRValueGetType, const double&&>::value));
-    EXPECT_EQ(absl::get<double>(const_v), 2.);
-    EXPECT_EQ(absl::get<double>(std::move(const_v)), 2.);
-  }
-}
-
-TEST(VariantTest, BadGetType) {
-  using Var = variant<int, std::string, double>;
-
-  {
-    Var v = 1;
-
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<std::string>(v));
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
-        absl::get<std::string>(std::move(v)));
-
-    const Var& const_v = v;
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
-        absl::get<std::string>(const_v));
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
-        absl::get<std::string>(std::move(const_v)));  // NOLINT
-  }
-
-  {
-    Var v = std::string("Hello");
-
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(v));
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(std::move(v)));
-
-    const Var& const_v = v;
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<int>(const_v));
-    ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
-        absl::get<int>(std::move(const_v)));  // NOLINT
-  }
-}
-
-TEST(VariantTest, GetIfIndex) {
-  using Var = variant<int, std::string, double, int>;
-
-  {
-    Var v(absl::in_place_index<0>, 0);
-    EXPECT_TRUE(noexcept(absl::get_if<0>(&v)));
-
-    {
-      auto* elem = absl::get_if<0>(&v);
-      EXPECT_TRUE((std::is_same<decltype(elem), int*>::value));
-      ASSERT_NE(elem, nullptr);
-      EXPECT_EQ(*elem, 0);
-      {
-        auto* bad_elem = absl::get_if<1>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<2>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<3>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-    }
-
-    const Var& const_v = v;
-    EXPECT_TRUE(noexcept(absl::get_if<0>(&const_v)));
-
-    {
-      auto* elem = absl::get_if<0>(&const_v);
-      EXPECT_TRUE((std::is_same<decltype(elem), const int*>::value));
-      ASSERT_NE(elem, nullptr);
-      EXPECT_EQ(*elem, 0);
-      {
-        auto* bad_elem = absl::get_if<1>(&const_v);
-        EXPECT_TRUE(
-            (std::is_same<decltype(bad_elem), const std::string*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<2>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<3>(&const_v);
-        EXPECT_EQ(bad_elem, nullptr);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
-      }
-    }
-  }
-
-  {
-    Var v = std::string("Hello");
-    EXPECT_TRUE(noexcept(absl::get_if<1>(&v)));
-
-    {
-      auto* elem = absl::get_if<1>(&v);
-      EXPECT_TRUE((std::is_same<decltype(elem), std::string*>::value));
-      ASSERT_NE(elem, nullptr);
-      EXPECT_EQ(*elem, "Hello");
-      {
-        auto* bad_elem = absl::get_if<0>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<2>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<3>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-    }
-
-    const Var& const_v = v;
-    EXPECT_TRUE(noexcept(absl::get_if<1>(&const_v)));
-
-    {
-      auto* elem = absl::get_if<1>(&const_v);
-      EXPECT_TRUE((std::is_same<decltype(elem), const std::string*>::value));
-      ASSERT_NE(elem, nullptr);
-      EXPECT_EQ(*elem, "Hello");
-      {
-        auto* bad_elem = absl::get_if<0>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<2>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<3>(&const_v);
-        EXPECT_EQ(bad_elem, nullptr);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
-      }
-    }
-  }
-
-  {
-    Var v = 2.0;
-    EXPECT_TRUE(noexcept(absl::get_if<2>(&v)));
-
-    {
-      auto* elem = absl::get_if<2>(&v);
-      EXPECT_TRUE((std::is_same<decltype(elem), double*>::value));
-      ASSERT_NE(elem, nullptr);
-      EXPECT_EQ(*elem, 2.0);
-      {
-        auto* bad_elem = absl::get_if<0>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<1>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<3>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-    }
-
-    const Var& const_v = v;
-    EXPECT_TRUE(noexcept(absl::get_if<2>(&const_v)));
-
-    {
-      auto* elem = absl::get_if<2>(&const_v);
-      EXPECT_TRUE((std::is_same<decltype(elem), const double*>::value));
-      ASSERT_NE(elem, nullptr);
-      EXPECT_EQ(*elem, 2.0);
-      {
-        auto* bad_elem = absl::get_if<0>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<1>(&const_v);
-        EXPECT_TRUE(
-            (std::is_same<decltype(bad_elem), const std::string*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<3>(&const_v);
-        EXPECT_EQ(bad_elem, nullptr);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
-      }
-    }
-  }
-
-  {
-    Var v(absl::in_place_index<0>, 0);
-    v.emplace<3>(1);
-    EXPECT_TRUE(noexcept(absl::get_if<3>(&v)));
-
-    {
-      auto* elem = absl::get_if<3>(&v);
-      EXPECT_TRUE((std::is_same<decltype(elem), int*>::value));
-      ASSERT_NE(elem, nullptr);
-      EXPECT_EQ(*elem, 1);
-      {
-        auto* bad_elem = absl::get_if<0>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), int*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<1>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), std::string*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<2>(&v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), double*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-    }
-
-    const Var& const_v = v;
-    EXPECT_TRUE(noexcept(absl::get_if<3>(&const_v)));
-
-    {
-      auto* elem = absl::get_if<3>(&const_v);
-      EXPECT_TRUE((std::is_same<decltype(elem), const int*>::value));
-      ASSERT_NE(elem, nullptr);
-      EXPECT_EQ(*elem, 1);
-      {
-        auto* bad_elem = absl::get_if<0>(&const_v);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const int*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<1>(&const_v);
-        EXPECT_TRUE(
-            (std::is_same<decltype(bad_elem), const std::string*>::value));
-        EXPECT_EQ(bad_elem, nullptr);
-      }
-      {
-        auto* bad_elem = absl::get_if<2>(&const_v);
-        EXPECT_EQ(bad_elem, nullptr);
-        EXPECT_TRUE((std::is_same<decltype(bad_elem), const double*>::value));
-      }
-    }
-  }
-}
-
-//////////////////////
-// [variant.relops] //
-//////////////////////
-
-TEST(VariantTest, OperatorEquals) {
-  variant<int, std::string> a(1), b(1);
-  EXPECT_TRUE(a == b);
-  EXPECT_TRUE(b == a);
-  EXPECT_FALSE(a != b);
-  EXPECT_FALSE(b != a);
-
-  b = "str";
-  EXPECT_FALSE(a == b);
-  EXPECT_FALSE(b == a);
-  EXPECT_TRUE(a != b);
-  EXPECT_TRUE(b != a);
-
-  b = 0;
-  EXPECT_FALSE(a == b);
-  EXPECT_FALSE(b == a);
-  EXPECT_TRUE(a != b);
-  EXPECT_TRUE(b != a);
-
-  a = b = "foo";
-  EXPECT_TRUE(a == b);
-  EXPECT_TRUE(b == a);
-  EXPECT_FALSE(a != b);
-  EXPECT_FALSE(b != a);
-
-  a = "bar";
-  EXPECT_FALSE(a == b);
-  EXPECT_FALSE(b == a);
-  EXPECT_TRUE(a != b);
-  EXPECT_TRUE(b != a);
-}
-
-TEST(VariantTest, OperatorRelational) {
-  variant<int, std::string> a(1), b(1);
-  EXPECT_FALSE(a < b);
-  EXPECT_FALSE(b < a);
-  EXPECT_FALSE(a > b);
-  EXPECT_FALSE(b > a);
-  EXPECT_TRUE(a <= b);
-  EXPECT_TRUE(b <= a);
-  EXPECT_TRUE(a >= b);
-  EXPECT_TRUE(b >= a);
-
-  b = "str";
-  EXPECT_TRUE(a < b);
-  EXPECT_FALSE(b < a);
-  EXPECT_FALSE(a > b);
-  EXPECT_TRUE(b > a);
-  EXPECT_TRUE(a <= b);
-  EXPECT_FALSE(b <= a);
-  EXPECT_FALSE(a >= b);
-  EXPECT_TRUE(b >= a);
-
-  b = 0;
-  EXPECT_FALSE(a < b);
-  EXPECT_TRUE(b < a);
-  EXPECT_TRUE(a > b);
-  EXPECT_FALSE(b > a);
-  EXPECT_FALSE(a <= b);
-  EXPECT_TRUE(b <= a);
-  EXPECT_TRUE(a >= b);
-  EXPECT_FALSE(b >= a);
-
-  a = b = "foo";
-  EXPECT_FALSE(a < b);
-  EXPECT_FALSE(b < a);
-  EXPECT_FALSE(a > b);
-  EXPECT_FALSE(b > a);
-  EXPECT_TRUE(a <= b);
-  EXPECT_TRUE(b <= a);
-  EXPECT_TRUE(a >= b);
-  EXPECT_TRUE(b >= a);
-
-  a = "bar";
-  EXPECT_TRUE(a < b);
-  EXPECT_FALSE(b < a);
-  EXPECT_FALSE(a > b);
-  EXPECT_TRUE(b > a);
-  EXPECT_TRUE(a <= b);
-  EXPECT_FALSE(b <= a);
-  EXPECT_FALSE(a >= b);
-  EXPECT_TRUE(b >= a);
-}
-
-#ifdef ABSL_HAVE_EXCEPTIONS
-
-TEST(VariantTest, ValuelessOperatorEquals) {
-  variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"),
-      valueless(absl::in_place_index<0>),
-      other_valueless(absl::in_place_index<0>);
-  ToValuelessByException(valueless);
-  ToValuelessByException(other_valueless);
-
-  EXPECT_TRUE(valueless == other_valueless);
-  EXPECT_TRUE(other_valueless == valueless);
-  EXPECT_FALSE(valueless == int_v);
-  EXPECT_FALSE(valueless == string_v);
-  EXPECT_FALSE(int_v == valueless);
-  EXPECT_FALSE(string_v == valueless);
-
-  EXPECT_FALSE(valueless != other_valueless);
-  EXPECT_FALSE(other_valueless != valueless);
-  EXPECT_TRUE(valueless != int_v);
-  EXPECT_TRUE(valueless != string_v);
-  EXPECT_TRUE(int_v != valueless);
-  EXPECT_TRUE(string_v != valueless);
-}
-
-TEST(VariantTest, ValuelessOperatorRelational) {
-  variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"),
-      valueless(absl::in_place_index<0>),
-      other_valueless(absl::in_place_index<0>);
-  ToValuelessByException(valueless);
-  ToValuelessByException(other_valueless);
-
-  EXPECT_FALSE(valueless < other_valueless);
-  EXPECT_FALSE(other_valueless < valueless);
-  EXPECT_TRUE(valueless < int_v);
-  EXPECT_TRUE(valueless < string_v);
-  EXPECT_FALSE(int_v < valueless);
-  EXPECT_FALSE(string_v < valueless);
-
-  EXPECT_TRUE(valueless <= other_valueless);
-  EXPECT_TRUE(other_valueless <= valueless);
-  EXPECT_TRUE(valueless <= int_v);
-  EXPECT_TRUE(valueless <= string_v);
-  EXPECT_FALSE(int_v <= valueless);
-  EXPECT_FALSE(string_v <= valueless);
-
-  EXPECT_TRUE(valueless >= other_valueless);
-  EXPECT_TRUE(other_valueless >= valueless);
-  EXPECT_FALSE(valueless >= int_v);
-  EXPECT_FALSE(valueless >= string_v);
-  EXPECT_TRUE(int_v >= valueless);
-  EXPECT_TRUE(string_v >= valueless);
-
-  EXPECT_FALSE(valueless > other_valueless);
-  EXPECT_FALSE(other_valueless > valueless);
-  EXPECT_FALSE(valueless > int_v);
-  EXPECT_FALSE(valueless > string_v);
-  EXPECT_TRUE(int_v > valueless);
-  EXPECT_TRUE(string_v > valueless);
-}
-
-#endif
-
-/////////////////////
-// [variant.visit] //
-/////////////////////
-
-template <typename T>
-struct ConvertTo {
-  template <typename U>
-  T operator()(const U& u) const {
-    return u;
-  }
-};
-
-TEST(VariantTest, VisitSimple) {
-  variant<std::string, const char*> v = "A";
-
-  std::string str = absl::visit(ConvertTo<std::string>{}, v);
-  EXPECT_EQ("A", str);
-
-  v = std::string("B");
-
-  absl::string_view piece = absl::visit(ConvertTo<absl::string_view>{}, v);
-  EXPECT_EQ("B", piece);
-
-  struct StrLen {
-    size_t operator()(const char* s) const { return strlen(s); }
-    size_t operator()(const std::string& s) const { return s.size(); }
-  };
-
-  v = "SomeStr";
-  EXPECT_EQ(7u, absl::visit(StrLen{}, v));
-  v = std::string("VeryLargeThisTime");
-  EXPECT_EQ(17u, absl::visit(StrLen{}, v));
-}
-
-TEST(VariantTest, VisitRValue) {
-  variant<std::string> v = std::string("X");
-  struct Visitor {
-    bool operator()(const std::string&) const { return false; }
-    bool operator()(std::string&&) const { return true; }  // NOLINT
-
-    int operator()(const std::string&, const std::string&) const { return 0; }
-    int operator()(const std::string&, std::string&&) const {
-      return 1;
-    }  // NOLINT
-    int operator()(std::string&&, const std::string&) const {
-      return 2;
-    }                                                                 // NOLINT
-    int operator()(std::string&&, std::string&&) const { return 3; }  // NOLINT
-  };
-  EXPECT_FALSE(absl::visit(Visitor{}, v));
-  EXPECT_TRUE(absl::visit(Visitor{}, std::move(v)));
-
-  // Also test the variadic overload.
-  EXPECT_EQ(0, absl::visit(Visitor{}, v, v));
-  EXPECT_EQ(1, absl::visit(Visitor{}, v, std::move(v)));
-  EXPECT_EQ(2, absl::visit(Visitor{}, std::move(v), v));
-  EXPECT_EQ(3, absl::visit(Visitor{}, std::move(v), std::move(v)));
-}
-
-TEST(VariantTest, VisitRValueVisitor) {
-  variant<std::string> v = std::string("X");
-  struct Visitor {
-    bool operator()(const std::string&) const& { return false; }
-    bool operator()(const std::string&) && { return true; }
-  };
-  Visitor visitor;
-  EXPECT_FALSE(absl::visit(visitor, v));
-  EXPECT_TRUE(absl::visit(Visitor{}, v));
-}
-
-TEST(VariantTest, VisitResultTypeDifferent) {
-  variant<std::string> v = std::string("X");
-  struct LValue_LValue {};
-  struct RValue_LValue {};
-  struct LValue_RValue {};
-  struct RValue_RValue {};
-  struct Visitor {
-    LValue_LValue operator()(const std::string&) const& { return {}; }
-    RValue_LValue operator()(std::string&&) const& { return {}; }  // NOLINT
-    LValue_RValue operator()(const std::string&) && { return {}; }
-    RValue_RValue operator()(std::string&&) && { return {}; }  // NOLINT
-  } visitor;
-
-  EXPECT_TRUE(
-      (std::is_same<LValue_LValue, decltype(absl::visit(visitor, v))>::value));
-  EXPECT_TRUE(
-      (std::is_same<RValue_LValue,
-                    decltype(absl::visit(visitor, std::move(v)))>::value));
-  EXPECT_TRUE((
-      std::is_same<LValue_RValue, decltype(absl::visit(Visitor{}, v))>::value));
-  EXPECT_TRUE(
-      (std::is_same<RValue_RValue,
-                    decltype(absl::visit(Visitor{}, std::move(v)))>::value));
-}
-
-TEST(VariantTest, VisitVariadic) {
-  using A = variant<int, std::string>;
-  using B = variant<std::unique_ptr<int>, absl::string_view>;
-
-  struct Visitor {
-    std::pair<int, int> operator()(int a, std::unique_ptr<int> b) const {
-      return {a, *b};
-    }
-    std::pair<int, int> operator()(absl::string_view a,
-                                   std::unique_ptr<int> b) const {
-      return {static_cast<int>(a.size()), static_cast<int>(*b)};
-    }
-    std::pair<int, int> operator()(int a, absl::string_view b) const {
-      return {a, static_cast<int>(b.size())};
-    }
-    std::pair<int, int> operator()(absl::string_view a,
-                                   absl::string_view b) const {
-      return {static_cast<int>(a.size()), static_cast<int>(b.size())};
-    }
-  };
-
-  EXPECT_THAT(absl::visit(Visitor(), A(1), B(std::unique_ptr<int>(new int(7)))),
-              ::testing::Pair(1, 7));
-  EXPECT_THAT(absl::visit(Visitor(), A(1), B(absl::string_view("ABC"))),
-              ::testing::Pair(1, 3));
-  EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
-                          B(std::unique_ptr<int>(new int(7)))),
-              ::testing::Pair(5, 7));
-  EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
-                          B(absl::string_view("ABC"))),
-              ::testing::Pair(5, 3));
-}
-
-TEST(VariantTest, VisitNoArgs) {
-  EXPECT_EQ(5, absl::visit([] { return 5; }));
-}
-
-struct ConstFunctor {
-  int operator()(int a, int b) const { return a - b; }
-};
-
-struct MutableFunctor {
-  int operator()(int a, int b) { return a - b; }
-};
-
-struct Class {
-  int Method(int a, int b) { return a - b; }
-  int ConstMethod(int a, int b) const { return a - b; }
-
-  int member;
-};
-
-TEST(VariantTest, VisitReferenceWrapper) {
-  ConstFunctor cf;
-  MutableFunctor mf;
-  absl::variant<int> three = 3;
-  absl::variant<int> two = 2;
-
-  EXPECT_EQ(1, absl::visit(std::cref(cf), three, two));
-  EXPECT_EQ(1, absl::visit(std::ref(cf), three, two));
-  EXPECT_EQ(1, absl::visit(std::ref(mf), three, two));
-}
-
-// libstdc++ std::variant doesn't support the INVOKE semantics.
-#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
-TEST(VariantTest, VisitMemberFunction) {
-  absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>());
-  absl::variant<std::unique_ptr<const Class>> cp(
-      absl::make_unique<const Class>());
-  absl::variant<int> three = 3;
-  absl::variant<int> two = 2;
-
-  EXPECT_EQ(1, absl::visit(&Class::Method, p, three, two));
-  EXPECT_EQ(1, absl::visit(&Class::ConstMethod, p, three, two));
-  EXPECT_EQ(1, absl::visit(&Class::ConstMethod, cp, three, two));
-}
-
-TEST(VariantTest, VisitDataMember) {
-  absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>(Class{42}));
-  absl::variant<std::unique_ptr<const Class>> cp(
-      absl::make_unique<const Class>(Class{42}));
-  EXPECT_EQ(42, absl::visit(&Class::member, p));
-
-  absl::visit(&Class::member, p) = 5;
-  EXPECT_EQ(5, absl::visit(&Class::member, p));
-
-  EXPECT_EQ(42, absl::visit(&Class::member, cp));
-}
-#endif  // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
-
-/////////////////////////
-// [variant.monostate] //
-/////////////////////////
-
-TEST(VariantTest, MonostateBasic) {
-  absl::monostate mono;
-  (void)mono;
-
-  // TODO(mattcalabrese) Expose move triviality metafunctions in absl.
-  EXPECT_TRUE(absl::is_trivially_default_constructible<absl::monostate>::value);
-  EXPECT_TRUE(is_trivially_move_constructible<absl::monostate>::value);
-  EXPECT_TRUE(absl::is_trivially_copy_constructible<absl::monostate>::value);
-  EXPECT_TRUE(is_trivially_move_assignable<absl::monostate>::value);
-  EXPECT_TRUE(absl::is_trivially_copy_assignable<absl::monostate>::value);
-  EXPECT_TRUE(absl::is_trivially_destructible<absl::monostate>::value);
-}
-
-TEST(VariantTest, VariantMonostateDefaultConstruction) {
-  absl::variant<absl::monostate, NonDefaultConstructible> var;
-  EXPECT_EQ(var.index(), 0u);
-}
-
-////////////////////////////////
-// [variant.monostate.relops] //
-////////////////////////////////
-
-TEST(VariantTest, MonostateComparisons) {
-  absl::monostate lhs, rhs;
-
-  EXPECT_EQ(lhs, lhs);
-  EXPECT_EQ(lhs, rhs);
-
-  EXPECT_FALSE(lhs != lhs);
-  EXPECT_FALSE(lhs != rhs);
-  EXPECT_FALSE(lhs < lhs);
-  EXPECT_FALSE(lhs < rhs);
-  EXPECT_FALSE(lhs > lhs);
-  EXPECT_FALSE(lhs > rhs);
-
-  EXPECT_LE(lhs, lhs);
-  EXPECT_LE(lhs, rhs);
-  EXPECT_GE(lhs, lhs);
-  EXPECT_GE(lhs, rhs);
-
-  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() ==
-                       std::declval<absl::monostate>()));
-  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() !=
-                       std::declval<absl::monostate>()));
-  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() <
-                       std::declval<absl::monostate>()));
-  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() >
-                       std::declval<absl::monostate>()));
-  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() <=
-                       std::declval<absl::monostate>()));
-  EXPECT_TRUE(noexcept(std::declval<absl::monostate>() >=
-                       std::declval<absl::monostate>()));
-}
-
-///////////////////////
-// [variant.specalg] //
-///////////////////////
-
-TEST(VariantTest, NonmemberSwap) {
-  using std::swap;
-
-  SpecialSwap v1(3);
-  SpecialSwap v2(7);
-
-  variant<SpecialSwap> a = v1, b = v2;
-
-  EXPECT_THAT(a, VariantWith<SpecialSwap>(v1));
-  EXPECT_THAT(b, VariantWith<SpecialSwap>(v2));
-
-  std::swap(a, b);
-  EXPECT_THAT(a, VariantWith<SpecialSwap>(v2));
-  EXPECT_THAT(b, VariantWith<SpecialSwap>(v1));
-#ifndef ABSL_USES_STD_VARIANT
-  EXPECT_FALSE(absl::get<SpecialSwap>(a).special_swap);
-#endif
-
-  swap(a, b);
-  EXPECT_THAT(a, VariantWith<SpecialSwap>(v1));
-  EXPECT_THAT(b, VariantWith<SpecialSwap>(v2));
-  EXPECT_TRUE(absl::get<SpecialSwap>(b).special_swap);
-}
-
-//////////////////////////
-// [variant.bad.access] //
-//////////////////////////
-
-TEST(VariantTest, BadAccess) {
-  EXPECT_TRUE(noexcept(absl::bad_variant_access()));
-  absl::bad_variant_access exception_obj;
-  std::exception* base = &exception_obj;
-  (void)base;
-}
-
-////////////////////
-// [variant.hash] //
-////////////////////
-
-TEST(VariantTest, MonostateHash) {
-  absl::monostate mono, other_mono;
-  std::hash<absl::monostate> const hasher{};
-  static_assert(std::is_same<decltype(hasher(mono)), std::size_t>::value, "");
-  EXPECT_EQ(hasher(mono), hasher(other_mono));
-}
-
-TEST(VariantTest, Hash) {
-  static_assert(type_traits_internal::IsHashable<variant<int>>::value, "");
-  static_assert(type_traits_internal::IsHashable<variant<Hashable>>::value, "");
-  static_assert(type_traits_internal::IsHashable<variant<int, Hashable>>::value,
-                "");
-
-#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
-  static_assert(!type_traits_internal::IsHashable<variant<NonHashable>>::value,
-                "");
-  static_assert(
-      !type_traits_internal::IsHashable<variant<Hashable, NonHashable>>::value,
-      "");
-#endif
-
-// MSVC std::hash<std::variant> does not use the index, thus produce the same
-// result on the same value as different alternative.
-#if !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT))
-  {
-    // same value as different alternative
-    variant<int, int> v0(in_place_index<0>, 42);
-    variant<int, int> v1(in_place_index<1>, 42);
-    std::hash<variant<int, int>> hash;
-    EXPECT_NE(hash(v0), hash(v1));
-  }
-#endif  // !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT))
-
-  {
-    std::hash<variant<int>> hash;
-    std::set<size_t> hashcodes;
-    for (int i = 0; i < 100; ++i) {
-      hashcodes.insert(hash(i));
-    }
-    EXPECT_GT(hashcodes.size(), 90u);
-
-    // test const-qualified
-    static_assert(type_traits_internal::IsHashable<variant<const int>>::value,
-                  "");
-    static_assert(
-        type_traits_internal::IsHashable<variant<const Hashable>>::value, "");
-    std::hash<absl::variant<const int>> c_hash;
-    for (int i = 0; i < 100; ++i) {
-      EXPECT_EQ(hash(i), c_hash(i));
-    }
-  }
-}
-
-////////////////////////////////////////
-// Miscellaneous and deprecated tests //
-////////////////////////////////////////
-
-// Test that a set requiring a basic type conversion works correctly
-#if !defined(ABSL_USES_STD_VARIANT)
-TEST(VariantTest, TestConvertingSet) {
-  typedef variant<double> Variant;
-  Variant v(1.0);
-  const int two = 2;
-  v = two;
-  EXPECT_TRUE(absl::holds_alternative<double>(v));
-  ASSERT_TRUE(nullptr != absl::get_if<double>(&v));
-  EXPECT_DOUBLE_EQ(2, absl::get<double>(v));
-}
-#endif  // ABSL_USES_STD_VARIANT
-
-// Test that a vector of variants behaves reasonably.
-TEST(VariantTest, Container) {
-  typedef variant<int, float> Variant;
-
-  // Creation of vector should work
-  std::vector<Variant> vec;
-  vec.push_back(Variant(10));
-  vec.push_back(Variant(20.0f));
-
-  // Vector resizing should work if we supply a value for new slots
-  vec.resize(10, Variant(0));
-}
-
-// Test that a variant with a non-copyable type can be constructed and
-// manipulated to some degree.
-TEST(VariantTest, TestVariantWithNonCopyableType) {
-  typedef variant<int, NonCopyable> Variant;
-  const int kValue = 1;
-  Variant v(kValue);
-  ASSERT_TRUE(absl::holds_alternative<int>(v));
-  EXPECT_EQ(kValue, absl::get<int>(v));
-}
-
-// Test that a variant with a non-copyable type can be transformed to
-// the non-copyable type with a call to `emplace` for different numbers
-// of arguments. We do not need to test this for each of T1 ... T8
-// because `emplace` does not overload on T1 ... to T8, so if this
-// works for any one of T1 ... T8, then it works for all of them. We
-// do need to test that it works with varying numbers of parameters
-// though.
-TEST(VariantTest, TestEmplace) {
-  typedef variant<int, NonCopyable> Variant;
-  const int kValue = 1;
-  Variant v(kValue);
-  ASSERT_TRUE(absl::holds_alternative<int>(v));
-  EXPECT_EQ(kValue, absl::get<int>(v));
-
-  // emplace with zero arguments, then back to 'int'
-  v.emplace<NonCopyable>();
-  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
-  EXPECT_EQ(0, absl::get<NonCopyable>(v).value);
-  v = kValue;
-  ASSERT_TRUE(absl::holds_alternative<int>(v));
-
-  // emplace with one argument:
-  v.emplace<NonCopyable>(1);
-  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
-  EXPECT_EQ(1, absl::get<NonCopyable>(v).value);
-  v = kValue;
-  ASSERT_TRUE(absl::holds_alternative<int>(v));
-
-  // emplace with two arguments:
-  v.emplace<NonCopyable>(1, 2);
-  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
-  EXPECT_EQ(3, absl::get<NonCopyable>(v).value);
-  v = kValue;
-  ASSERT_TRUE(absl::holds_alternative<int>(v));
-
-  // emplace with three arguments
-  v.emplace<NonCopyable>(1, 2, 3);
-  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
-  EXPECT_EQ(6, absl::get<NonCopyable>(v).value);
-  v = kValue;
-  ASSERT_TRUE(absl::holds_alternative<int>(v));
-
-  // emplace with four arguments
-  v.emplace<NonCopyable>(1, 2, 3, 4);
-  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
-  EXPECT_EQ(10, absl::get<NonCopyable>(v).value);
-  v = kValue;
-  ASSERT_TRUE(absl::holds_alternative<int>(v));
-}
-
-TEST(VariantTest, TestEmplaceDestroysCurrentValue) {
-  typedef variant<int, IncrementInDtor, NonCopyable> Variant;
-  int counter = 0;
-  Variant v(0);
-  ASSERT_TRUE(absl::holds_alternative<int>(v));
-  v.emplace<IncrementInDtor>(&counter);
-  ASSERT_TRUE(absl::holds_alternative<IncrementInDtor>(v));
-  ASSERT_EQ(0, counter);
-  v.emplace<NonCopyable>();
-  ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v));
-  EXPECT_EQ(1, counter);
-}
-
-TEST(VariantTest, TestMoveSemantics) {
-  typedef variant<std::unique_ptr<int>, std::unique_ptr<std::string>> Variant;
-
-  // Construct a variant by moving from an element value.
-  Variant v(absl::WrapUnique(new int(10)));
-  EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v));
-
-  // Construct a variant by moving from another variant.
-  Variant v2(std::move(v));
-  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v2));
-  ASSERT_NE(nullptr, absl::get<std::unique_ptr<int>>(v2));
-  EXPECT_EQ(10, *absl::get<std::unique_ptr<int>>(v2));
-
-  // Moving from a variant object leaves it holding moved-from value of the
-  // same element type.
-  EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<int>>(v));
-  ASSERT_NE(nullptr, absl::get_if<std::unique_ptr<int>>(&v));
-  EXPECT_EQ(nullptr, absl::get<std::unique_ptr<int>>(v));
-
-  // Assign a variant from an element value by move.
-  v = absl::make_unique<std::string>("foo");
-  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v));
-  EXPECT_EQ("foo", *absl::get<std::unique_ptr<std::string>>(v));
-
-  // Move-assign a variant.
-  v2 = std::move(v);
-  ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v2));
-  EXPECT_EQ("foo", *absl::get<std::unique_ptr<std::string>>(v2));
-  EXPECT_TRUE(absl::holds_alternative<std::unique_ptr<std::string>>(v));
-}
-
-variant<int, std::string> PassThrough(const variant<int, std::string>& arg) {
-  return arg;
-}
-
-TEST(VariantTest, TestImplicitConversion) {
-  EXPECT_TRUE(absl::holds_alternative<int>(PassThrough(0)));
-
-  // We still need the explicit cast for std::string, because C++ won't apply
-  // two user-defined implicit conversions in a row.
-  EXPECT_TRUE(
-      absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
-}
-
 struct Convertible2;
 struct Convertible1 {
   Convertible1() {}
@@ -2281,116 +48,41 @@
 };
 
 TEST(VariantTest, TestRvalueConversion) {
-#if !defined(ABSL_USES_STD_VARIANT)
-  variant<double, std::string> var(
-      ConvertVariantTo<variant<double, std::string>>(
-          variant<std::string, int>(0)));
-  ASSERT_TRUE(absl::holds_alternative<double>(var));
-  EXPECT_EQ(0.0, absl::get<double>(var));
+  std::variant<Convertible1, Convertible2> v(
+      ConvertVariantTo<std::variant<Convertible1, Convertible2>>(
+          (std::variant<Convertible2, Convertible1>(Convertible1()))));
+  ASSERT_TRUE(absl::holds_alternative<Convertible1>(v));
 
-  var = ConvertVariantTo<variant<double, std::string>>(
-      variant<const char*, float>("foo"));
-  ASSERT_TRUE(absl::holds_alternative<std::string>(var));
-  EXPECT_EQ("foo", absl::get<std::string>(var));
-
-  variant<double> singleton(
-      ConvertVariantTo<variant<double>>(variant<int, float>(42)));
-  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
-  EXPECT_EQ(42.0, absl::get<double>(singleton));
-
-  singleton = ConvertVariantTo<variant<double>>(variant<int, float>(3.14f));
-  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
-  EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton)));
-
-  singleton = ConvertVariantTo<variant<double>>(variant<int>(0));
-  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
-  EXPECT_EQ(0.0, absl::get<double>(singleton));
-
-  variant<int32_t, uint32_t> variant2(
-      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42)));
-  ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2));
-  EXPECT_EQ(42, absl::get<int32_t>(variant2));
-
-  variant2 =
-      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42u));
-  ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
-  EXPECT_EQ(42u, absl::get<uint32_t>(variant2));
-#endif  // !ABSL_USES_STD_VARIANT
-
-  variant<Convertible1, Convertible2> variant3(
-      ConvertVariantTo<variant<Convertible1, Convertible2>>(
-          (variant<Convertible2, Convertible1>(Convertible1()))));
-  ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3));
-
-  variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(
-      variant<Convertible2, Convertible1>(Convertible2()));
-  ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3));
+  v = ConvertVariantTo<std::variant<Convertible1, Convertible2>>(
+      std::variant<Convertible2, Convertible1>(Convertible2()));
+  ASSERT_TRUE(absl::holds_alternative<Convertible2>(v));
 }
 
 TEST(VariantTest, TestLvalueConversion) {
-#if !defined(ABSL_USES_STD_VARIANT)
-  variant<std::string, int> source1 = 0;
-  variant<double, std::string> destination(
-      ConvertVariantTo<variant<double, std::string>>(source1));
-  ASSERT_TRUE(absl::holds_alternative<double>(destination));
-  EXPECT_EQ(0.0, absl::get<double>(destination));
+  std::variant<Convertible2, Convertible1> source((Convertible1()));
+  std::variant<Convertible1, Convertible2> v(
+      ConvertVariantTo<std::variant<Convertible1, Convertible2>>(source));
+  ASSERT_TRUE(absl::holds_alternative<Convertible1>(v));
 
-  variant<const char*, float> source2 = "foo";
-  destination = ConvertVariantTo<variant<double, std::string>>(source2);
-  ASSERT_TRUE(absl::holds_alternative<std::string>(destination));
-  EXPECT_EQ("foo", absl::get<std::string>(destination));
-
-  variant<int, float> source3(42);
-  variant<double> singleton(ConvertVariantTo<variant<double>>(source3));
-  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
-  EXPECT_EQ(42.0, absl::get<double>(singleton));
-
-  source3 = 3.14f;
-  singleton = ConvertVariantTo<variant<double>>(source3);
-  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
-  EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton)));
-
-  variant<int> source4(0);
-  singleton = ConvertVariantTo<variant<double>>(source4);
-  ASSERT_TRUE(absl::holds_alternative<double>(singleton));
-  EXPECT_EQ(0.0, absl::get<double>(singleton));
-
-  variant<int32_t> source5(42);
-  variant<int32_t, uint32_t> variant2(
-      ConvertVariantTo<variant<int32_t, uint32_t>>(source5));
-  ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2));
-  EXPECT_EQ(42, absl::get<int32_t>(variant2));
-
-  variant<uint32_t> source6(42u);
-  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6);
-  ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
-  EXPECT_EQ(42u, absl::get<uint32_t>(variant2));
-#endif
-
-  variant<Convertible2, Convertible1> source7((Convertible1()));
-  variant<Convertible1, Convertible2> variant3(
-      ConvertVariantTo<variant<Convertible1, Convertible2>>(source7));
-  ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3));
-
-  source7 = Convertible2();
-  variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(source7);
-  ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3));
+  source = Convertible2();
+  v = ConvertVariantTo<std::variant<Convertible1, Convertible2>>(source);
+  ASSERT_TRUE(absl::holds_alternative<Convertible2>(v));
 }
 
 TEST(VariantTest, TestMoveConversion) {
-  using Variant =
-      variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
+  using Variant = std::variant<std::unique_ptr<const int>,
+                               std::unique_ptr<const std::string>>;
   using OtherVariant =
-      variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+      std::variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
 
   Variant var(
-      ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(0)}));
+      ConvertVariantTo<Variant>(OtherVariant{std::make_unique<int>(0)}));
   ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const int>>(var));
   ASSERT_NE(absl::get<std::unique_ptr<const int>>(var), nullptr);
   EXPECT_EQ(0, *absl::get<std::unique_ptr<const int>>(var));
 
   var = ConvertVariantTo<Variant>(
-      OtherVariant(absl::make_unique<std::string>("foo")));
+      OtherVariant(std::make_unique<std::string>("foo")));
   ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const std::string>>(var));
   EXPECT_EQ("foo", *absl::get<std::unique_ptr<const std::string>>(var));
 }
@@ -2399,10 +91,10 @@
   // We use shared_ptr here because it's both copyable and movable, and
   // a moved-from shared_ptr is guaranteed to be null, so we can detect
   // whether moving or copying has occurred.
-  using Variant =
-      variant<std::shared_ptr<const int>, std::shared_ptr<const std::string>>;
+  using Variant = std::variant<std::shared_ptr<const int>,
+                               std::shared_ptr<const std::string>>;
   using OtherVariant =
-      variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
+      std::variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
 
   Variant v1(std::make_shared<const int>(0));
 
@@ -2430,289 +122,43 @@
 }
 
 TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
-#if !defined(ABSL_USES_STD_VARIANT)
-  variant<double, std::string> var(
-      ConvertVariantTo<variant<double, std::string>>(
-          variant<std::string, int>(3)));
-  EXPECT_THAT(absl::get_if<double>(&var), Pointee(3.0));
+  variant<Convertible1, Convertible2> v(
+      ConvertVariantTo<std::variant<Convertible1, Convertible2>>(
+          (std::variant<Convertible2, Convertible1>(Convertible1()))));
+  ASSERT_TRUE(absl::holds_alternative<Convertible1>(v));
 
-  var = ConvertVariantTo<variant<double, std::string>>(
-      variant<const char*, float>("foo"));
-  EXPECT_THAT(absl::get_if<std::string>(&var), Pointee(std::string("foo")));
-
-  variant<double> singleton(
-      ConvertVariantTo<variant<double>>(variant<int, float>(42)));
-  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(42.0));
-
-  singleton = ConvertVariantTo<variant<double>>(variant<int, float>(3.14f));
-  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(DoubleEq(3.14f)));
-
-  singleton = ConvertVariantTo<variant<double>>(variant<int>(3));
-  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(3.0));
-
-  variant<int32_t, uint32_t> variant2(
-      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42)));
-  EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42));
-
-  variant2 =
-      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42u));
-  EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42u));
-#endif
-
-  variant<Convertible1, Convertible2> variant3(
-      ConvertVariantTo<variant<Convertible1, Convertible2>>(
-          (variant<Convertible2, Convertible1>(Convertible1()))));
-  ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3));
-
-  variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(
-      variant<Convertible2, Convertible1>(Convertible2()));
-  ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3));
+  v = ConvertVariantTo<std::variant<Convertible1, Convertible2>>(
+      std::variant<Convertible2, Convertible1>(Convertible2()));
+  ASSERT_TRUE(absl::holds_alternative<Convertible2>(v));
 }
 
 TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
-#if !defined(ABSL_USES_STD_VARIANT)
-  variant<std::string, int> source1 = 3;
-  variant<double, std::string> destination(
-      ConvertVariantTo<variant<double, std::string>>(source1));
-  EXPECT_THAT(absl::get_if<double>(&destination), Pointee(3.0));
+  variant<Convertible2, Convertible1> source((Convertible1()));
+  variant<Convertible1, Convertible2> v(
+      ConvertVariantTo<std::variant<Convertible1, Convertible2>>(source));
+  ASSERT_TRUE(absl::holds_alternative<Convertible1>(v));
 
-  variant<const char*, float> source2 = "foo";
-  destination = ConvertVariantTo<variant<double, std::string>>(source2);
-  EXPECT_THAT(absl::get_if<std::string>(&destination),
-              Pointee(std::string("foo")));
-
-  variant<int, float> source3(42);
-  variant<double> singleton(ConvertVariantTo<variant<double>>(source3));
-  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(42.0));
-
-  source3 = 3.14f;
-  singleton = ConvertVariantTo<variant<double>>(source3);
-  EXPECT_FLOAT_EQ(3.14f, static_cast<float>(absl::get<double>(singleton)));
-  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(DoubleEq(3.14f)));
-
-  variant<int> source4(3);
-  singleton = ConvertVariantTo<variant<double>>(source4);
-  EXPECT_THAT(absl::get_if<double>(&singleton), Pointee(3.0));
-
-  variant<int32_t> source5(42);
-  variant<int32_t, uint32_t> variant2(
-      ConvertVariantTo<variant<int32_t, uint32_t>>(source5));
-  EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42));
-
-  variant<uint32_t> source6(42u);
-  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6);
-  EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42u));
-#endif  // !ABSL_USES_STD_VARIANT
-
-  variant<Convertible2, Convertible1> source7((Convertible1()));
-  variant<Convertible1, Convertible2> variant3(
-      ConvertVariantTo<variant<Convertible1, Convertible2>>(source7));
-  ASSERT_TRUE(absl::holds_alternative<Convertible1>(variant3));
-
-  source7 = Convertible2();
-  variant3 = ConvertVariantTo<variant<Convertible1, Convertible2>>(source7);
-  ASSERT_TRUE(absl::holds_alternative<Convertible2>(variant3));
+  source = Convertible2();
+  v = ConvertVariantTo<std::variant<Convertible1, Convertible2>>(source);
+  ASSERT_TRUE(absl::holds_alternative<Convertible2>(v));
 }
 
 TEST(VariantTest, TestMoveConversionViaConvertVariantTo) {
-  using Variant =
-      variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
+  using Variant = std::variant<std::unique_ptr<const int>,
+                               std::unique_ptr<const std::string>>;
   using OtherVariant =
-      variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+      std::variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
 
   Variant var(
-      ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(3)}));
+      ConvertVariantTo<Variant>(OtherVariant{std::make_unique<int>(3)}));
   EXPECT_THAT(absl::get_if<std::unique_ptr<const int>>(&var),
               Pointee(Pointee(3)));
 
   var = ConvertVariantTo<Variant>(
-      OtherVariant(absl::make_unique<std::string>("foo")));
+      OtherVariant(std::make_unique<std::string>("foo")));
   EXPECT_THAT(absl::get_if<std::unique_ptr<const std::string>>(&var),
               Pointee(Pointee(std::string("foo"))));
 }
 
-// If all alternatives are trivially copy/move constructible, variant should
-// also be trivially copy/move constructible. This is not required by the
-// standard and we know that libstdc++ variant doesn't have this feature.
-// For more details see the paper:
-// http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0602r0.html
-#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
-#define ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY 1
-#endif
-
-TEST(VariantTest, TestCopyAndMoveTypeTraits) {
-  EXPECT_TRUE(std::is_copy_constructible<variant<std::string>>::value);
-  EXPECT_TRUE(absl::is_copy_assignable<variant<std::string>>::value);
-  EXPECT_TRUE(std::is_move_constructible<variant<std::string>>::value);
-  EXPECT_TRUE(absl::is_move_assignable<variant<std::string>>::value);
-  EXPECT_TRUE(std::is_move_constructible<variant<std::unique_ptr<int>>>::value);
-  EXPECT_TRUE(absl::is_move_assignable<variant<std::unique_ptr<int>>>::value);
-  EXPECT_FALSE(
-      std::is_copy_constructible<variant<std::unique_ptr<int>>>::value);
-  EXPECT_FALSE(absl::is_copy_assignable<variant<std::unique_ptr<int>>>::value);
-
-  EXPECT_FALSE(
-      absl::is_trivially_copy_constructible<variant<std::string>>::value);
-  EXPECT_FALSE(absl::is_trivially_copy_assignable<variant<std::string>>::value);
-#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
-  EXPECT_TRUE(absl::is_trivially_copy_constructible<variant<int>>::value);
-  EXPECT_TRUE(absl::is_trivially_copy_assignable<variant<int>>::value);
-  EXPECT_TRUE(is_trivially_move_constructible<variant<int>>::value);
-  EXPECT_TRUE(is_trivially_move_assignable<variant<int>>::value);
-#endif  // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
-}
-
-TEST(VariantTest, TestVectorOfMoveonlyVariant) {
-  // Verify that variant<MoveonlyType> works correctly as a std::vector element.
-  std::vector<variant<std::unique_ptr<int>, std::string>> vec;
-  vec.push_back(absl::make_unique<int>(42));
-  vec.emplace_back("Hello");
-  vec.reserve(3);
-  auto another_vec = std::move(vec);
-  // As a sanity check, verify vector contents.
-  ASSERT_EQ(2u, another_vec.size());
-  EXPECT_EQ(42, *absl::get<std::unique_ptr<int>>(another_vec[0]));
-  EXPECT_EQ("Hello", absl::get<std::string>(another_vec[1]));
-}
-
-TEST(VariantTest, NestedVariant) {
-#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
-  static_assert(absl::is_trivially_copy_constructible<variant<int>>(), "");
-  static_assert(absl::is_trivially_copy_assignable<variant<int>>(), "");
-  static_assert(is_trivially_move_constructible<variant<int>>(), "");
-  static_assert(is_trivially_move_assignable<variant<int>>(), "");
-
-  static_assert(absl::is_trivially_copy_constructible<variant<variant<int>>>(),
-                "");
-  static_assert(absl::is_trivially_copy_assignable<variant<variant<int>>>(),
-                "");
-  static_assert(is_trivially_move_constructible<variant<variant<int>>>(), "");
-  static_assert(is_trivially_move_assignable<variant<variant<int>>>(), "");
-#endif  // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
-
-  variant<int> x(42);
-  variant<variant<int>> y(x);
-  variant<variant<int>> z(y);
-  EXPECT_TRUE(absl::holds_alternative<variant<int>>(z));
-  EXPECT_EQ(x, absl::get<variant<int>>(z));
-}
-
-struct TriviallyDestructible {
-  TriviallyDestructible(TriviallyDestructible&&) {}
-  TriviallyDestructible(const TriviallyDestructible&) {}
-  TriviallyDestructible& operator=(TriviallyDestructible&&) { return *this; }
-  TriviallyDestructible& operator=(const TriviallyDestructible&) {
-    return *this;
-  }
-};
-
-struct TriviallyMovable {
-  TriviallyMovable(TriviallyMovable&&) = default;
-  TriviallyMovable(TriviallyMovable const&) {}
-  TriviallyMovable& operator=(const TriviallyMovable&) { return *this; }
-};
-
-struct TriviallyCopyable {
-  TriviallyCopyable(const TriviallyCopyable&) = default;
-  TriviallyCopyable& operator=(const TriviallyCopyable&) { return *this; }
-};
-
-struct TriviallyMoveAssignable {
-  TriviallyMoveAssignable(TriviallyMoveAssignable&&) = default;
-  TriviallyMoveAssignable(const TriviallyMoveAssignable&) {}
-  TriviallyMoveAssignable& operator=(TriviallyMoveAssignable&&) = default;
-  TriviallyMoveAssignable& operator=(const TriviallyMoveAssignable&) {
-    return *this;
-  }
-};
-
-struct TriviallyCopyAssignable {};
-
-#if ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
-TEST(VariantTest, TestTriviality) {
-  {
-    using TrivDestVar = absl::variant<TriviallyDestructible>;
-
-    EXPECT_FALSE(is_trivially_move_constructible<TrivDestVar>::value);
-    EXPECT_FALSE(absl::is_trivially_copy_constructible<TrivDestVar>::value);
-    EXPECT_FALSE(is_trivially_move_assignable<TrivDestVar>::value);
-    EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivDestVar>::value);
-    EXPECT_TRUE(absl::is_trivially_destructible<TrivDestVar>::value);
-  }
-
-  {
-    using TrivMoveVar = absl::variant<TriviallyMovable>;
-
-    EXPECT_TRUE(is_trivially_move_constructible<TrivMoveVar>::value);
-    EXPECT_FALSE(absl::is_trivially_copy_constructible<TrivMoveVar>::value);
-    EXPECT_FALSE(is_trivially_move_assignable<TrivMoveVar>::value);
-    EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivMoveVar>::value);
-    EXPECT_TRUE(absl::is_trivially_destructible<TrivMoveVar>::value);
-  }
-
-  {
-    using TrivCopyVar = absl::variant<TriviallyCopyable>;
-
-    EXPECT_TRUE(is_trivially_move_constructible<TrivCopyVar>::value);
-    EXPECT_TRUE(absl::is_trivially_copy_constructible<TrivCopyVar>::value);
-    EXPECT_FALSE(is_trivially_move_assignable<TrivCopyVar>::value);
-    EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivCopyVar>::value);
-    EXPECT_TRUE(absl::is_trivially_destructible<TrivCopyVar>::value);
-  }
-
-  {
-    using TrivMoveAssignVar = absl::variant<TriviallyMoveAssignable>;
-
-    EXPECT_TRUE(is_trivially_move_constructible<TrivMoveAssignVar>::value);
-    EXPECT_FALSE(
-        absl::is_trivially_copy_constructible<TrivMoveAssignVar>::value);
-    EXPECT_TRUE(is_trivially_move_assignable<TrivMoveAssignVar>::value);
-    EXPECT_FALSE(absl::is_trivially_copy_assignable<TrivMoveAssignVar>::value);
-    EXPECT_TRUE(absl::is_trivially_destructible<TrivMoveAssignVar>::value);
-  }
-
-  {
-    using TrivCopyAssignVar = absl::variant<TriviallyCopyAssignable>;
-
-    EXPECT_TRUE(is_trivially_move_constructible<TrivCopyAssignVar>::value);
-    EXPECT_TRUE(
-        absl::is_trivially_copy_constructible<TrivCopyAssignVar>::value);
-    EXPECT_TRUE(is_trivially_move_assignable<TrivCopyAssignVar>::value);
-    EXPECT_TRUE(absl::is_trivially_copy_assignable<TrivCopyAssignVar>::value);
-    EXPECT_TRUE(absl::is_trivially_destructible<TrivCopyAssignVar>::value);
-  }
-}
-#endif  // ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY
-
-// To verify that absl::variant correctly use the nontrivial move ctor of its
-// member rather than use the trivial copy constructor.
-TEST(VariantTest, MoveCtorBug) {
-  // To simulate std::tuple in libstdc++.
-  struct TrivialCopyNontrivialMove {
-    TrivialCopyNontrivialMove() = default;
-    TrivialCopyNontrivialMove(const TrivialCopyNontrivialMove&) = default;
-    TrivialCopyNontrivialMove(TrivialCopyNontrivialMove&&) { called = true; }
-    bool called = false;
-  };
-  {
-    using V = absl::variant<TrivialCopyNontrivialMove, int>;
-    V v1(absl::in_place_index<0>);
-    // this should invoke the move ctor, rather than the trivial copy ctor.
-    V v2(std::move(v1));
-    EXPECT_TRUE(absl::get<0>(v2).called);
-  }
-  {
-    // this case failed to compile before our fix due to a GCC bug.
-    using V = absl::variant<int, TrivialCopyNontrivialMove>;
-    V v1(absl::in_place_index<1>);
-    // this should invoke the move ctor, rather than the trivial copy ctor.
-    V v2(std::move(v1));
-    EXPECT_TRUE(absl::get<1>(v2).called);
-  }
-}
-
 }  // namespace
-ABSL_NAMESPACE_END
 }  // namespace absl
-
-#endif  // #if !defined(ABSL_USES_STD_VARIANT)
diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel
index 1c01fc1..773f949 100644
--- a/absl/utility/BUILD.bazel
+++ b/absl/utility/BUILD.bazel
@@ -18,7 +18,6 @@
     "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
     "ABSL_DEFAULT_LINKOPTS",
-    "ABSL_TEST_COPTS",
 )
 
 package(
@@ -40,47 +39,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        "//absl/base:base_internal",
         "//absl/base:config",
         "//absl/meta:type_traits",
     ],
 )
-
-cc_test(
-    name = "utility_test",
-    srcs = ["utility_test.cc"],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":utility",
-        "//absl/base:core_headers",
-        "//absl/memory",
-        "//absl/strings",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_library(
-    name = "if_constexpr",
-    hdrs = [
-        "internal/if_constexpr.h",
-    ],
-    copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        "//absl/base:config",
-    ],
-)
-
-cc_test(
-    name = "if_constexpr_test",
-    srcs = ["internal/if_constexpr_test.cc"],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":if_constexpr",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
diff --git a/absl/utility/CMakeLists.txt b/absl/utility/CMakeLists.txt
index 27ee0de..8ac87bc 100644
--- a/absl/utility/CMakeLists.txt
+++ b/absl/utility/CMakeLists.txt
@@ -22,47 +22,7 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
-    absl::base_internal
     absl::config
     absl::type_traits
   PUBLIC
 )
-
-absl_cc_test(
-  NAME
-    utility_test
-  SRCS
-    "utility_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::utility
-    absl::core_headers
-    absl::memory
-    absl::strings
-    GTest::gmock_main
-)
-
-absl_cc_library(
-  NAME
-    if_constexpr
-  HDRS
-    "internal/if_constexpr.h"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  DEPS
-    absl::config
-  PUBLIC
-)
-
-absl_cc_test(
-  NAME
-    if_constexpr_test
-  SRCS
-    "internal/if_constexpr_test.cc"
-  COPTS
-    ${ABSL_TEST_COPTS}
-  DEPS
-    absl::if_constexpr
-    GTest::gmock_main
-)
diff --git a/absl/utility/internal/if_constexpr.h b/absl/utility/internal/if_constexpr.h
deleted file mode 100644
index 7a26311..0000000
--- a/absl/utility/internal/if_constexpr.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2023 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.
-
-// The IfConstexpr and IfConstexprElse utilities in this file are meant to be
-// used to emulate `if constexpr` in pre-C++17 mode in library implementation.
-// The motivation is to allow for avoiding complex SFINAE.
-//
-// The functions passed in must depend on the type(s) of the object(s) that
-// require SFINAE. For example:
-// template<typename T>
-// int MaybeFoo(T& t) {
-//   if constexpr (HasFoo<T>::value) return t.foo();
-//   return 0;
-// }
-//
-// can be written in pre-C++17 as:
-//
-// template<typename T>
-// int MaybeFoo(T& t) {
-//   int i = 0;
-//   absl::utility_internal::IfConstexpr<HasFoo<T>::value>(
-//       [&](const auto& fooer) { i = fooer.foo(); }, t);
-//   return i;
-// }
-
-#ifndef ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
-#define ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
-
-#include <tuple>
-#include <utility>
-
-#include "absl/base/config.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-namespace utility_internal {
-
-template <bool condition, typename TrueFunc, typename FalseFunc,
-          typename... Args>
-auto IfConstexprElse(TrueFunc&& true_func, FalseFunc&& false_func,
-                     Args&&... args) {
-  return std::get<condition>(std::forward_as_tuple(
-      std::forward<FalseFunc>(false_func), std::forward<TrueFunc>(true_func)))(
-      std::forward<Args>(args)...);
-}
-
-template <bool condition, typename Func, typename... Args>
-void IfConstexpr(Func&& func, Args&&... args) {
-  IfConstexprElse<condition>(std::forward<Func>(func), [](auto&&...){},
-                             std::forward<Args>(args)...);
-}
-
-}  // namespace utility_internal
-
-ABSL_NAMESPACE_END
-}  // namespace absl
-
-#endif  // ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
diff --git a/absl/utility/internal/if_constexpr_test.cc b/absl/utility/internal/if_constexpr_test.cc
deleted file mode 100644
index d1ee723..0000000
--- a/absl/utility/internal/if_constexpr_test.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2023 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/utility/internal/if_constexpr.h"
-
-#include <utility>
-
-#include "gtest/gtest.h"
-
-namespace {
-
-struct Empty {};
-struct HasFoo {
-  int foo() const { return 1; }
-};
-
-TEST(IfConstexpr, Basic) {
-  int i = 0;
-  absl::utility_internal::IfConstexpr<false>(
-      [&](const auto& t) { i = t.foo(); }, Empty{});
-  EXPECT_EQ(i, 0);
-
-  absl::utility_internal::IfConstexpr<false>(
-      [&](const auto& t) { i = t.foo(); }, HasFoo{});
-  EXPECT_EQ(i, 0);
-
-  absl::utility_internal::IfConstexpr<true>(
-      [&](const auto& t) { i = t.foo(); }, HasFoo{});
-  EXPECT_EQ(i, 1);
-}
-
-TEST(IfConstexprElse, Basic) {
-  EXPECT_EQ(absl::utility_internal::IfConstexprElse<false>(
-      [&](const auto& t) { return t.foo(); }, [&](const auto&) { return 2; },
-      Empty{}), 2);
-
-  EXPECT_EQ(absl::utility_internal::IfConstexprElse<false>(
-      [&](const auto& t) { return t.foo(); }, [&](const auto&) { return 2; },
-      HasFoo{}), 2);
-
-  EXPECT_EQ(absl::utility_internal::IfConstexprElse<true>(
-      [&](const auto& t) { return t.foo(); }, [&](const auto&) { return 2; },
-      HasFoo{}), 1);
-}
-
-struct HasFooRValue {
-  int foo() && { return 1; }
-};
-struct RValueFunc {
-  void operator()(HasFooRValue&& t) && { *i = std::move(t).foo(); }
-
-  int* i = nullptr;
-};
-
-TEST(IfConstexpr, RValues) {
-  int i = 0;
-  RValueFunc func = {&i};
-  absl::utility_internal::IfConstexpr<false>(
-      std::move(func), HasFooRValue{});
-  EXPECT_EQ(i, 0);
-
-  func = RValueFunc{&i};
-  absl::utility_internal::IfConstexpr<true>(
-      std::move(func), HasFooRValue{});
-  EXPECT_EQ(i, 1);
-}
-
-}  // namespace
diff --git a/absl/utility/utility.h b/absl/utility/utility.h
index ebbb49b..4637b03 100644
--- a/absl/utility/utility.h
+++ b/absl/utility/utility.h
@@ -11,25 +11,6 @@
 // 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.
-//
-// This header file contains C++14 versions of standard <utility> header
-// abstractions available within C++17, and are designed to be drop-in
-// replacement for code compliant with C++14 and C++17.
-//
-// The following abstractions are defined:
-//
-//   * apply<Functor, Tuple>         == std::apply<Functor, Tuple>
-//   * exchange<T>                   == std::exchange<T>
-//   * make_from_tuple<T>            == std::make_from_tuple<T>
-//
-// This header file also provides the tag types `in_place_t`, `in_place_type_t`,
-// and `in_place_index_t`, as well as the constant `in_place`, and
-// `constexpr` `std::move()` and `std::forward()` implementations in C++11.
-//
-// References:
-//
-//  https://en.cppreference.com/w/cpp/utility/apply
-//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
 
 #ifndef ABSL_UTILITY_UTILITY_H_
 #define ABSL_UTILITY_UTILITY_H_
@@ -40,8 +21,8 @@
 #include <utility>
 
 #include "absl/base/config.h"
-#include "absl/base/internal/inline_variable.h"
-#include "absl/base/internal/invoke.h"
+
+// TODO(b/290784225): Include what you use cleanup required.
 #include "absl/meta/type_traits.h"
 
 namespace absl {
@@ -51,179 +32,23 @@
 // abstractions for platforms that had not yet provided them. Those
 // platforms are no longer supported. New code should simply use the
 // the ones from std directly.
+using std::apply;
 using std::exchange;
 using std::forward;
+using std::in_place;
+using std::in_place_index;
+using std::in_place_index_t;
+using std::in_place_t;
+using std::in_place_type;
+using std::in_place_type_t;
 using std::index_sequence;
 using std::index_sequence_for;
 using std::integer_sequence;
+using std::make_from_tuple;
 using std::make_index_sequence;
 using std::make_integer_sequence;
 using std::move;
 
-namespace utility_internal {
-
-template <typename T>
-struct InPlaceTypeTag {
-  explicit InPlaceTypeTag() = delete;
-  InPlaceTypeTag(const InPlaceTypeTag&) = delete;
-  InPlaceTypeTag& operator=(const InPlaceTypeTag&) = delete;
-};
-
-template <size_t I>
-struct InPlaceIndexTag {
-  explicit InPlaceIndexTag() = delete;
-  InPlaceIndexTag(const InPlaceIndexTag&) = delete;
-  InPlaceIndexTag& operator=(const InPlaceIndexTag&) = delete;
-};
-
-}  // namespace utility_internal
-
-// Tag types
-
-#ifdef ABSL_USES_STD_OPTIONAL
-
-using std::in_place_t;
-using std::in_place;
-
-#else  // ABSL_USES_STD_OPTIONAL
-
-// in_place_t
-//
-// Tag type used to specify in-place construction, such as with
-// `absl::optional`, designed to be a drop-in replacement for C++17's
-// `std::in_place_t`.
-struct in_place_t {};
-
-ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {});
-
-#endif  // ABSL_USES_STD_OPTIONAL
-
-#if defined(ABSL_USES_STD_ANY) || defined(ABSL_USES_STD_VARIANT)
-using std::in_place_type;
-using std::in_place_type_t;
-#else
-
-// in_place_type_t
-//
-// Tag type used for in-place construction when the type to construct needs to
-// be specified, such as with `absl::any`, designed to be a drop-in replacement
-// for C++17's `std::in_place_type_t`.
-template <typename T>
-using in_place_type_t = void (*)(utility_internal::InPlaceTypeTag<T>);
-
-template <typename T>
-void in_place_type(utility_internal::InPlaceTypeTag<T>) {}
-#endif  // ABSL_USES_STD_ANY || ABSL_USES_STD_VARIANT
-
-#ifdef ABSL_USES_STD_VARIANT
-using std::in_place_index;
-using std::in_place_index_t;
-#else
-
-// in_place_index_t
-//
-// Tag type used for in-place construction when the type to construct needs to
-// be specified, such as with `absl::any`, designed to be a drop-in replacement
-// for C++17's `std::in_place_index_t`.
-template <size_t I>
-using in_place_index_t = void (*)(utility_internal::InPlaceIndexTag<I>);
-
-template <size_t I>
-void in_place_index(utility_internal::InPlaceIndexTag<I>) {}
-#endif  // ABSL_USES_STD_VARIANT
-
-namespace utility_internal {
-// Helper method for expanding tuple into a called method.
-template <typename Functor, typename Tuple, std::size_t... Indexes>
-auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>)
-    -> decltype(absl::base_internal::invoke(
-        absl::forward<Functor>(functor),
-        std::get<Indexes>(absl::forward<Tuple>(t))...)) {
-  return absl::base_internal::invoke(
-      absl::forward<Functor>(functor),
-      std::get<Indexes>(absl::forward<Tuple>(t))...);
-}
-
-}  // namespace utility_internal
-
-// apply
-//
-// Invokes a Callable using elements of a tuple as its arguments.
-// Each element of the tuple corresponds to an argument of the call (in order).
-// Both the Callable argument and the tuple argument are perfect-forwarded.
-// For member-function Callables, the first tuple element acts as the `this`
-// pointer. `absl::apply` is designed to be a drop-in replacement for C++17's
-// `std::apply`. Unlike C++17's `std::apply`, this is not currently `constexpr`.
-//
-// Example:
-//
-//   class Foo {
-//    public:
-//     void Bar(int);
-//   };
-//   void user_function1(int, std::string);
-//   void user_function2(std::unique_ptr<Foo>);
-//   auto user_lambda = [](int, int) {};
-//
-//   int main()
-//   {
-//       std::tuple<int, std::string> tuple1(42, "bar");
-//       // Invokes the first user function on int, std::string.
-//       absl::apply(&user_function1, tuple1);
-//
-//       std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>());
-//       // Invokes the user function that takes ownership of the unique
-//       // pointer.
-//       absl::apply(&user_function2, std::move(tuple2));
-//
-//       auto foo = absl::make_unique<Foo>();
-//       std::tuple<Foo*, int> tuple3(foo.get(), 42);
-//       // Invokes the method Bar on foo with one argument, 42.
-//       absl::apply(&Foo::Bar, tuple3);
-//
-//       std::tuple<int, int> tuple4(8, 9);
-//       // Invokes a lambda.
-//       absl::apply(user_lambda, tuple4);
-//   }
-template <typename Functor, typename Tuple>
-auto apply(Functor&& functor, Tuple&& t)
-    -> decltype(utility_internal::apply_helper(
-        absl::forward<Functor>(functor), absl::forward<Tuple>(t),
-        absl::make_index_sequence<std::tuple_size<
-            typename std::remove_reference<Tuple>::type>::value>{})) {
-  return utility_internal::apply_helper(
-      absl::forward<Functor>(functor), absl::forward<Tuple>(t),
-      absl::make_index_sequence<std::tuple_size<
-          typename std::remove_reference<Tuple>::type>::value>{});
-}
-
-namespace utility_internal {
-template <typename T, typename Tuple, size_t... I>
-T make_from_tuple_impl(Tuple&& tup, absl::index_sequence<I...>) {
-  return T(std::get<I>(std::forward<Tuple>(tup))...);
-}
-}  // namespace utility_internal
-
-// make_from_tuple
-//
-// Given the template parameter type `T` and a tuple of arguments
-// `std::tuple(arg0, arg1, ..., argN)` constructs an object of type `T` as if by
-// calling `T(arg0, arg1, ..., argN)`.
-//
-// Example:
-//
-//   std::tuple<const char*, size_t> args("hello world", 5);
-//   auto s = absl::make_from_tuple<std::string>(args);
-//   assert(s == "hello");
-//
-template <typename T, typename Tuple>
-constexpr T make_from_tuple(Tuple&& tup) {
-  return utility_internal::make_from_tuple_impl<T>(
-      std::forward<Tuple>(tup),
-      absl::make_index_sequence<
-          std::tuple_size<absl::decay_t<Tuple>>::value>{});
-}
-
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/utility/utility_test.cc b/absl/utility/utility_test.cc
deleted file mode 100644
index c540b22..0000000
--- a/absl/utility/utility_test.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright 2022 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/utility/utility.h"
-
-#include <memory>
-#include <sstream>
-#include <string>
-#include <tuple>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/attributes.h"
-#include "absl/memory/memory.h"
-#include "absl/strings/str_cat.h"
-
-namespace {
-
-using ::testing::ElementsAre;
-using ::testing::Pointee;
-using ::testing::StaticAssertTypeEq;
-
-
-int Function(int a, int b) { return a - b; }
-
-int Sink(std::unique_ptr<int> p) { return *p; }
-
-std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); }
-
-void NoOp() {}
-
-struct ConstFunctor {
-  int operator()(int a, int b) const { return a - b; }
-};
-
-struct MutableFunctor {
-  int operator()(int a, int b) { return a - b; }
-};
-
-struct EphemeralFunctor {
-  EphemeralFunctor() {}
-  EphemeralFunctor(const EphemeralFunctor&) {}
-  EphemeralFunctor(EphemeralFunctor&&) {}
-  int operator()(int a, int b) && { return a - b; }
-};
-
-struct OverloadedFunctor {
-  OverloadedFunctor() {}
-  OverloadedFunctor(const OverloadedFunctor&) {}
-  OverloadedFunctor(OverloadedFunctor&&) {}
-  template <typename... Args>
-  std::string operator()(const Args&... args) & {
-    return absl::StrCat("&", args...);
-  }
-  template <typename... Args>
-  std::string operator()(const Args&... args) const& {
-    return absl::StrCat("const&", args...);
-  }
-  template <typename... Args>
-  std::string operator()(const Args&... args) && {
-    return absl::StrCat("&&", args...);
-  }
-};
-
-struct Class {
-  int Method(int a, int b) { return a - b; }
-  int ConstMethod(int a, int b) const { return a - b; }
-
-  int member;
-};
-
-struct FlipFlop {
-  int ConstMethod() const { return member; }
-  FlipFlop operator*() const { return {-member}; }
-
-  int member;
-};
-
-TEST(ApplyTest, Function) {
-  EXPECT_EQ(1, absl::apply(Function, std::make_tuple(3, 2)));
-  EXPECT_EQ(1, absl::apply(&Function, std::make_tuple(3, 2)));
-}
-
-TEST(ApplyTest, NonCopyableArgument) {
-  EXPECT_EQ(42, absl::apply(Sink, std::make_tuple(absl::make_unique<int>(42))));
-}
-
-TEST(ApplyTest, NonCopyableResult) {
-  EXPECT_THAT(absl::apply(Factory, std::make_tuple(42)), Pointee(42));
-}
-
-TEST(ApplyTest, VoidResult) { absl::apply(NoOp, std::tuple<>()); }
-
-TEST(ApplyTest, ConstFunctor) {
-  EXPECT_EQ(1, absl::apply(ConstFunctor(), std::make_tuple(3, 2)));
-}
-
-TEST(ApplyTest, MutableFunctor) {
-  MutableFunctor f;
-  EXPECT_EQ(1, absl::apply(f, std::make_tuple(3, 2)));
-  EXPECT_EQ(1, absl::apply(MutableFunctor(), std::make_tuple(3, 2)));
-}
-TEST(ApplyTest, EphemeralFunctor) {
-  EphemeralFunctor f;
-  EXPECT_EQ(1, absl::apply(std::move(f), std::make_tuple(3, 2)));
-  EXPECT_EQ(1, absl::apply(EphemeralFunctor(), std::make_tuple(3, 2)));
-}
-TEST(ApplyTest, OverloadedFunctor) {
-  OverloadedFunctor f;
-  const OverloadedFunctor& cf = f;
-
-  EXPECT_EQ("&", absl::apply(f, std::tuple<>{}));
-  EXPECT_EQ("& 42", absl::apply(f, std::make_tuple(" 42")));
-
-  EXPECT_EQ("const&", absl::apply(cf, std::tuple<>{}));
-  EXPECT_EQ("const& 42", absl::apply(cf, std::make_tuple(" 42")));
-
-  EXPECT_EQ("&&", absl::apply(std::move(f), std::tuple<>{}));
-  OverloadedFunctor f2;
-  EXPECT_EQ("&& 42", absl::apply(std::move(f2), std::make_tuple(" 42")));
-}
-
-TEST(ApplyTest, ReferenceWrapper) {
-  ConstFunctor cf;
-  MutableFunctor mf;
-  EXPECT_EQ(1, absl::apply(std::cref(cf), std::make_tuple(3, 2)));
-  EXPECT_EQ(1, absl::apply(std::ref(cf), std::make_tuple(3, 2)));
-  EXPECT_EQ(1, absl::apply(std::ref(mf), std::make_tuple(3, 2)));
-}
-
-TEST(ApplyTest, MemberFunction) {
-  std::unique_ptr<Class> p(new Class);
-  std::unique_ptr<const Class> cp(new Class);
-  EXPECT_EQ(
-      1, absl::apply(&Class::Method,
-                     std::tuple<std::unique_ptr<Class>&, int, int>(p, 3, 2)));
-  EXPECT_EQ(1, absl::apply(&Class::Method,
-                           std::tuple<Class*, int, int>(p.get(), 3, 2)));
-  EXPECT_EQ(
-      1, absl::apply(&Class::Method, std::tuple<Class&, int, int>(*p, 3, 2)));
-
-  EXPECT_EQ(
-      1, absl::apply(&Class::ConstMethod,
-                     std::tuple<std::unique_ptr<Class>&, int, int>(p, 3, 2)));
-  EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
-                           std::tuple<Class*, int, int>(p.get(), 3, 2)));
-  EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
-                           std::tuple<Class&, int, int>(*p, 3, 2)));
-
-  EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
-                           std::tuple<std::unique_ptr<const Class>&, int, int>(
-                               cp, 3, 2)));
-  EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
-                           std::tuple<const Class*, int, int>(cp.get(), 3, 2)));
-  EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
-                           std::tuple<const Class&, int, int>(*cp, 3, 2)));
-
-  EXPECT_EQ(1, absl::apply(&Class::Method,
-                           std::make_tuple(absl::make_unique<Class>(), 3, 2)));
-  EXPECT_EQ(1, absl::apply(&Class::ConstMethod,
-                           std::make_tuple(absl::make_unique<Class>(), 3, 2)));
-  EXPECT_EQ(
-      1, absl::apply(&Class::ConstMethod,
-                     std::make_tuple(absl::make_unique<const Class>(), 3, 2)));
-}
-
-TEST(ApplyTest, DataMember) {
-  std::unique_ptr<Class> p(new Class{42});
-  std::unique_ptr<const Class> cp(new Class{42});
-  EXPECT_EQ(
-      42, absl::apply(&Class::member, std::tuple<std::unique_ptr<Class>&>(p)));
-  EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<Class&>(*p)));
-  EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<Class*>(p.get())));
-
-  absl::apply(&Class::member, std::tuple<std::unique_ptr<Class>&>(p)) = 42;
-  absl::apply(&Class::member, std::tuple<Class*>(p.get())) = 42;
-  absl::apply(&Class::member, std::tuple<Class&>(*p)) = 42;
-
-  EXPECT_EQ(42, absl::apply(&Class::member,
-                            std::tuple<std::unique_ptr<const Class>&>(cp)));
-  EXPECT_EQ(42, absl::apply(&Class::member, std::tuple<const Class&>(*cp)));
-  EXPECT_EQ(42,
-            absl::apply(&Class::member, std::tuple<const Class*>(cp.get())));
-}
-
-TEST(ApplyTest, FlipFlop) {
-  FlipFlop obj = {42};
-  // This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
-  // ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
-  EXPECT_EQ(42, absl::apply(&FlipFlop::ConstMethod, std::make_tuple(obj)));
-  EXPECT_EQ(42, absl::apply(&FlipFlop::member, std::make_tuple(obj)));
-}
-
-TEST(MakeFromTupleTest, String) {
-  EXPECT_EQ(
-      absl::make_from_tuple<std::string>(std::make_tuple("hello world", 5)),
-      "hello");
-}
-
-TEST(MakeFromTupleTest, MoveOnlyParameter) {
-  struct S {
-    S(std::unique_ptr<int> n, std::unique_ptr<int> m) : value(*n + *m) {}
-    int value = 0;
-  };
-  auto tup =
-      std::make_tuple(absl::make_unique<int>(3), absl::make_unique<int>(4));
-  auto s = absl::make_from_tuple<S>(std::move(tup));
-  EXPECT_EQ(s.value, 7);
-}
-
-TEST(MakeFromTupleTest, NoParameters) {
-  struct S {
-    S() : value(1) {}
-    int value = 2;
-  };
-  EXPECT_EQ(absl::make_from_tuple<S>(std::make_tuple()).value, 1);
-}
-
-TEST(MakeFromTupleTest, Pair) {
-  EXPECT_EQ(
-      (absl::make_from_tuple<std::pair<bool, int>>(std::make_tuple(true, 17))),
-      std::make_pair(true, 17));
-}
-
-}  // namespace
diff --git a/ci/cmake_common.sh b/ci/cmake_common.sh
index c8a5b85..484230c 100644
--- a/ci/cmake_common.sh
+++ b/ci/cmake_common.sh
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 # The commit of GoogleTest to be used in the CMake tests in this directory.
-# Keep this in sync with the commit in the WORKSPACE file.
-readonly ABSL_GOOGLETEST_VERSION="1.15.2"
+# Keep this in sync with the commit in the MODULE.bazel file.
+readonly ABSL_GOOGLETEST_VERSION="1.17.0"
 
 readonly ABSL_GOOGLETEST_DOWNLOAD_URL="https://github.com/google/googletest/releases/download/v${ABSL_GOOGLETEST_VERSION}/googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz"
diff --git a/ci/linux_arm_clang-latest_libcxx_bazel.sh b/ci/linux_arm_clang-latest_libcxx_bazel.sh
index 13f4ad1..631a8bd 100755
--- a/ci/linux_arm_clang-latest_libcxx_bazel.sh
+++ b/ci/linux_arm_clang-latest_libcxx_bazel.sh
@@ -25,7 +25,7 @@
 fi
 
 if [[ -z ${STD:-} ]]; then
-  STD="c++14 c++17 c++20"
+  STD="c++17 c++20"
 fi
 
 if [[ -z ${COMPILATION_MODE:-} ]]; then
@@ -51,12 +51,12 @@
   BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
-# Avoid depending on external sites like GitHub by checking --distdir for
-# external dependencies first.
-# https://docs.bazel.build/versions/master/guide.html#distdir
-if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
-  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
-  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+# Use Bazel Vendor mode to reduce reliance on external dependencies.
+# See https://bazel.build/external/vendor and the Dockerfile for
+# an explaination of how this works.
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}"
 fi
 
 for std in ${STD}; do
@@ -69,26 +69,25 @@
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
-        -e CC="/opt/llvm/clang/bin/clang" \
-        -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
-        -e BAZEL_LINKOPTS="-L/opt/llvm/clang/lib/aarch64-unknown-linux-gnu:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/clang/lib/aarch64-unknown-linux-gnu" \
-        -e CPLUS_INCLUDE_PATH="/opt/llvm/clang/include/aarch64-unknown-linux-gnu/c++/v1:/opt/llvm/clang/include/c++/v1" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
-        /bin/sh -c "
+        /bin/bash --login -c "
           cp -r /abseil-cpp-ro/* /abseil-cpp/
           if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then
             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\" \
-            --enable_bzlmod=true \
             --features=external_include_paths \
             --keep_going \
+            --linkopt=-stdlib=libc++ \
             --show_timestamps \
             --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
             --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh
index 3153fae..cfc5510 100755
--- a/ci/linux_clang-latest_libcxx_asan_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh
@@ -25,7 +25,7 @@
 fi
 
 if [[ -z ${STD:-} ]]; then
-  STD="c++14 c++17 c++20"
+  STD="c++17 c++20 c++23"
 fi
 
 if [[ -z ${COMPILATION_MODE:-} ]]; then
@@ -59,6 +59,9 @@
   BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
 fi
 
+# https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#available-checks
+readonly UBSAN_CHECKS="float-divide-by-zero,nullability,undefined"
+
 for std in ${STD}; do
   for compilation_mode in ${COMPILATION_MODE}; do
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
@@ -68,35 +71,35 @@
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
-        -e CC="/opt/llvm/clang/bin/clang" \
-        -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
-        -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \
-        -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
+        /bin/bash --login -c "
         /usr/local/bin/bazel test ... \
-          --compilation_mode="${compilation_mode}" \
-          --copt="${exceptions_mode}" \
-          --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \
-          --copt="-fsanitize=address" \
-          --copt="-fsanitize=float-divide-by-zero" \
-          --copt="-fsanitize=nullability" \
-          --copt="-fsanitize=undefined" \
-          --copt="-fno-sanitize-blacklist" \
+          --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\" \
+          --copt=\"-fsanitize=address\" \
+          --copt=\"-fsanitize=${UBSAN_CHECKS}\" \
+          --copt=\"-fno-sanitize-recover=${UBSAN_CHECKS}\" \
+          --copt=\"-fno-sanitize-blacklist\" \
           --copt=-Werror \
           --enable_bzlmod=true \
           --features=external_include_paths \
           --keep_going \
-          --linkopt="-fsanitize=address" \
-          --linkopt="-fsanitize-link-c++-runtime" \
+          --linkopt=\"-fsanitize=address\" \
+          --linkopt=\"-fsanitize-link-c++-runtime\" \
           --show_timestamps \
-          --test_env="ASAN_SYMBOLIZER_PATH=/opt/llvm/clang/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=\"ASAN_SYMBOLIZER_PATH=/opt/llvm/clang/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_output=errors \
-          --test_tag_filters="-benchmark,-noasan" \
-          ${BAZEL_EXTRA_ARGS:-}
+          --test_tag_filters=\"-benchmark,-noasan\" \
+          ${BAZEL_EXTRA_ARGS:-}"
     done
   done
 done
diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh
index 4f3eba4..5c51d15 100755
--- a/ci/linux_clang-latest_libcxx_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_bazel.sh
@@ -25,7 +25,7 @@
 fi
 
 if [[ -z ${STD:-} ]]; then
-  STD="c++14 c++17 c++20"
+  STD="c++17 c++20 c++23"
 fi
 
 if [[ -z ${COMPILATION_MODE:-} ]]; then
@@ -51,12 +51,12 @@
   BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
-# Avoid depending on external sites like GitHub by checking --distdir for
-# external dependencies first.
-# https://docs.bazel.build/versions/master/guide.html#distdir
-if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
-  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
-  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+# Use Bazel Vendor mode to reduce reliance on external dependencies.
+# See https://bazel.build/external/vendor and the Dockerfile for
+# an explaination of how this works.
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}"
 fi
 
 for std in ${STD}; do
@@ -69,18 +69,18 @@
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
-        -e CC="/opt/llvm/clang/bin/clang" \
-        -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
-        -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \
-        -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
-        /bin/sh -c "
+        /bin/bash --login -c "
           cp -r /abseil-cpp-ro/* /abseil-cpp/
           if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then
             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 06f4c2e..c9ea22d 100755
--- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh
@@ -25,7 +25,7 @@
 fi
 
 if [[ -z ${STD:-} ]]; then
-  STD="c++14 c++17 c++20"
+  STD="c++17 c++20 c++23"
 fi
 
 if [[ -z ${COMPILATION_MODE:-} ]]; then
@@ -51,12 +51,12 @@
   BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
-# Avoid depending on external sites like GitHub by checking --distdir for
-# external dependencies first.
-# https://docs.bazel.build/versions/master/guide.html#distdir
-if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
-  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
-  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+# Use Bazel Vendor mode to reduce reliance on external dependencies.
+# See https://bazel.build/external/vendor and the Dockerfile for
+# an explaination of how this works.
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}"
 fi
 
 for std in ${STD}; do
@@ -68,30 +68,31 @@
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
-        -e CC="/opt/llvm/clang/bin/clang" \
-        -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
-        -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib" \
-        -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx-tsan/include/c++/v1" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
+        /bin/bash --login -c "
         /usr/local/bin/bazel test ... \
-          --build_tag_filters="-notsan" \
-          --compilation_mode="${compilation_mode}" \
-          --copt="${exceptions_mode}" \
-          --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \
-          --copt="-fsanitize=thread" \
-          --copt="-fno-sanitize-blacklist" \
+          --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}\" \
+          --copt=\"-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1\" \
+          --copt=\"-fsanitize=thread\" \
+          --copt=\"-fno-sanitize-blacklist\" \
           --copt=-Werror \
           --enable_bzlmod=true \
           --features=external_include_paths \
           --keep_going \
-          --linkopt="-fsanitize=thread" \
+          --linkopt=\"-fsanitize=thread\" \
           --show_timestamps \
-          --test_env="TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \
-          --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
+          --test_env=\"TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer\" \
+          --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
           --test_output=errors \
-          --test_tag_filters="-benchmark,-notsan" \
-          ${BAZEL_EXTRA_ARGS:-}
+          --test_tag_filters=\"-benchmark,-notsan\" \
+          ${BAZEL_EXTRA_ARGS:-}"
     done
   done
 done
diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh
index d499e13..a1620e0 100755
--- a/ci/linux_clang-latest_libstdcxx_bazel.sh
+++ b/ci/linux_clang-latest_libstdcxx_bazel.sh
@@ -25,7 +25,7 @@
 fi
 
 if [[ -z ${STD:-} ]]; then
-  STD="c++14 c++17"
+  STD="c++17 c++20 c++23"
 fi
 
 if [[ -z ${COMPILATION_MODE:-} ]]; then
@@ -51,12 +51,12 @@
   BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
-# Avoid depending on external sites like GitHub by checking --distdir for
-# external dependencies first.
-# https://docs.bazel.build/versions/master/guide.html#distdir
-if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
-  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
-  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+# Use Bazel Vendor mode to reduce reliance on external dependencies.
+# See https://bazel.build/external/vendor and the Dockerfile for
+# an explaination of how this works.
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}"
 fi
 
 for std in ${STD}; do
@@ -68,28 +68,29 @@
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
-        -e CC="/opt/llvm/clang/bin/clang" \
-        -e BAZEL_CXXOPTS="-std=${std}" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
+        /bin/bash --login -c "
         /usr/local/bin/bazel test ... \
-          --compilation_mode="${compilation_mode}" \
-          --copt="--gcc-toolchain=/usr/local" \
-          --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \
-          --copt="${exceptions_mode}" \
-          --copt="-march=haswell" \
+          --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\" \
+          --copt=\"${exceptions_mode}\" \
+          --copt=\"-march=haswell\" \
           --copt=-Werror \
-          --define="absl=1" \
+          --define=\"absl=1\" \
           --enable_bzlmod=true \
           --features=external_include_paths \
           --keep_going \
-          --linkopt="--gcc-toolchain=/usr/local" \
+          --linkopt=\"--gcc-toolchain=/usr/local\" \
           --show_timestamps \
-          --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
-          --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
+          --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
+          --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
           --test_output=errors \
           --test_tag_filters=-benchmark \
-          ${BAZEL_EXTRA_ARGS:-}
+          ${BAZEL_EXTRA_ARGS:-}"
     done
   done
 done
diff --git a/ci/linux_docker_containers.sh b/ci/linux_docker_containers.sh
index fefef92..0f45471 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:20240523"
-readonly LINUX_ARM_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_arm_hybrid-latest:20231219"
-readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20240523"
-readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20240717"
+readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20250430"
+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:20250430"
+readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20250430"
diff --git a/ci/linux_gcc-floor_libstdcxx_bazel.sh b/ci/linux_gcc-floor_libstdcxx_bazel.sh
index b2d8c1d..b683b60 100755
--- a/ci/linux_gcc-floor_libstdcxx_bazel.sh
+++ b/ci/linux_gcc-floor_libstdcxx_bazel.sh
@@ -25,7 +25,7 @@
 fi
 
 if [[ -z ${STD:-} ]]; then
-  STD="c++14"
+  STD="c++17"
 fi
 
 if [[ -z ${COMPILATION_MODE:-} ]]; then
@@ -51,12 +51,12 @@
   BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
-# Avoid depending on external sites like GitHub by checking --distdir for
-# external dependencies first.
-# https://docs.bazel.build/versions/master/guide.html#distdir
-if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
-  DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
-  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+# Use Bazel Vendor mode to reduce reliance on external dependencies.
+# See https://bazel.build/external/vendor and the Dockerfile for
+# an explaination of how this works.
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}"
 fi
 
 for std in ${STD}; do
@@ -68,26 +68,25 @@
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
-        -e CC="/usr/local/bin/gcc" \
-        -e BAZEL_CXXOPTS="-std=${std}" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
+        /bin/bash --login -c "
         /usr/local/bin/bazel test ... \
-          --compilation_mode="${compilation_mode}" \
-          --copt="${exceptions_mode}" \
-          --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \
+          --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\" \
           --copt=-Werror \
-          --define="absl=1" \
-          --distdir="/bazel-distdir" \
-          --enable_bzlmod=false \
+          --define=\"absl=1\" \
           --features=external_include_paths \
           --keep_going \
           --show_timestamps \
-          --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
-          --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
+          --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
+          --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
           --test_output=errors \
           --test_tag_filters=-benchmark \
-          ${BAZEL_EXTRA_ARGS:-}
+          ${BAZEL_EXTRA_ARGS:-}"
     done
   done
 done
diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh
index 8f77346..b092c1d 100755
--- a/ci/linux_gcc-latest_libstdcxx_bazel.sh
+++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh
@@ -25,7 +25,7 @@
 fi
 
 if [[ -z ${STD:-} ]]; then
-  STD="c++14 c++17 c++20"
+  STD="c++17 c++20 c++23"
 fi
 
 if [[ -z ${COMPILATION_MODE:-} ]]; then
@@ -51,12 +51,12 @@
   BAZEL_EXTRA_ARGS="--remote_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
-# Avoid depending on external sites like GitHub by checking --distdir for
-# external dependencies first.
-# https://docs.bazel.build/versions/master/guide.html#distdir
-if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
-  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
-  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+# Use Bazel Vendor mode to reduce reliance on external dependencies.
+# See https://bazel.build/external/vendor and the Dockerfile for
+# an explaination of how this works.
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly --env=BAZEL_VENDOR_ARCHIVE=/distdir/abseil-cpp_vendor.tar.gz ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--vendor_dir=/abseil-cpp_vendor ${BAZEL_EXTRA_ARGS:-}"
 fi
 
 for std in ${STD}; do
@@ -69,16 +69,16 @@
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
-        -e CC="/usr/local/bin/gcc" \
-        -e BAZEL_CXXOPTS="-std=${std}" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
-        /bin/sh -c "
+        /bin/bash --login -c "
           cp -r /abseil-cpp-ro/* /abseil-cpp/
           if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then
             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/linux_gcc-latest_libstdcxx_cmake.sh b/ci/linux_gcc-latest_libstdcxx_cmake.sh
index 243901c..d75209b 100755
--- a/ci/linux_gcc-latest_libstdcxx_cmake.sh
+++ b/ci/linux_gcc-latest_libstdcxx_cmake.sh
@@ -23,7 +23,7 @@
 source "${ABSEIL_ROOT}/ci/cmake_common.sh"
 
 if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then
-  ABSL_CMAKE_CXX_STANDARDS="14 17 20"
+  ABSL_CMAKE_CXX_STANDARDS="17 20"
 fi
 
 if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
diff --git a/ci/linux_gcc_alpine_cmake.sh b/ci/linux_gcc_alpine_cmake.sh
index f19954f..7cf25f7 100755
--- a/ci/linux_gcc_alpine_cmake.sh
+++ b/ci/linux_gcc_alpine_cmake.sh
@@ -23,7 +23,7 @@
 source "${ABSEIL_ROOT}/ci/cmake_common.sh"
 
 if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then
-  ABSL_CMAKE_CXX_STANDARDS="14 17"
+  ABSL_CMAKE_CXX_STANDARDS="17"
 fi
 
 if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
diff --git a/ci/macos_xcode_bazel.sh b/ci/macos_xcode_bazel.sh
index bb8fb4b..b05cfac 100755
--- a/ci/macos_xcode_bazel.sh
+++ b/ci/macos_xcode_bazel.sh
@@ -19,12 +19,15 @@
 
 set -euox pipefail
 
+# Use Xcode 16.0
+sudo xcode-select -s /Applications/Xcode_16.0.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-7.0.0-darwin-x86_64"
+KOKORO_GFILE_BAZEL_BIN="bazel-8.2.1-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}
@@ -32,11 +35,10 @@
   BAZEL_BIN="bazel"
 fi
 
-# Avoid depending on external sites like GitHub by checking --distdir for
-# external dependencies first.
-# https://docs.bazel.build/versions/master/guide.html#distdir
-if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
-  BAZEL_EXTRA_ARGS="--distdir=${KOKORO_GFILE_DIR}/distdir ${BAZEL_EXTRA_ARGS:-}"
+# Use Bazel Vendor mode to reduce reliance on external dependencies.
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" ]]; then
+  tar -xf "${KOKORO_GFILE_DIR}/distdir/abseil-cpp_vendor.tar.gz" -C "${TMP}/"
+  BAZEL_EXTRA_ARGS="--vendor_dir=\"${TMP}/abseil-cpp_vendor\" ${BAZEL_EXTRA_ARGS:-}"
 fi
 
 # Print the compiler and Bazel versions.
@@ -52,10 +54,13 @@
   cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
 fi
 
+# Avoid using the system version of google-benchmark.
+brew uninstall google-benchmark
+
 ${BAZEL_BIN} test ... \
   --copt="-DGTEST_REMOVE_LEGACY_TEST_CASEAPI_=1" \
   --copt="-Werror" \
-  --cxxopt="-std=c++14" \
+  --cxxopt="-std=c++17" \
   --enable_bzlmod=true \
   --features=external_include_paths \
   --keep_going \
diff --git a/ci/macos_xcode_cmake.sh b/ci/macos_xcode_cmake.sh
index eba2fb5..6811b87 100755
--- a/ci/macos_xcode_cmake.sh
+++ b/ci/macos_xcode_cmake.sh
@@ -16,6 +16,12 @@
 
 set -euox pipefail
 
+# Use Xcode 16.0
+sudo xcode-select -s /Applications/Xcode_16.0.app/Contents/Developer
+
+export CMAKE_BUILD_PARALLEL_LEVEL=$(sysctl -n hw.ncpu)
+export CTEST_PARALLEL_LEVEL=$(sysctl -n hw.ncpu)
+
 if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(dirname ${0})/.."
 fi
@@ -53,7 +59,7 @@
         -DBUILD_SHARED_LIBS=${build_shared} \
         -DABSL_BUILD_TESTING=ON \
         -DCMAKE_BUILD_TYPE=${compilation_mode} \
-        -DCMAKE_CXX_STANDARD=14 \
+        -DCMAKE_CXX_STANDARD=17 \
         -DCMAKE_MODULE_LINKER_FLAGS="-Wl,--no-undefined" \
         -DABSL_BUILD_MONOLITHIC_SHARED_LIBS=${monolithic_shared} \
         -DABSL_GOOGLETEST_DOWNLOAD_URL="${ABSL_GOOGLETEST_DOWNLOAD_URL}"
diff --git a/ci/windows_clangcl_bazel.bat b/ci/windows_clangcl_bazel.bat
index b031c30..26fd5af 100755
--- a/ci/windows_clangcl_bazel.bat
+++ b/ci/windows_clangcl_bazel.bat
@@ -21,10 +21,18 @@
 CD %~dp0\..
 if %errorlevel% neq 0 EXIT /B 1
 
-:: Set the standard version, [c++14|c++17|c++20|c++latest]
+:: Use Bazel Vendor mode to reduce reliance on external dependencies.
+IF EXIST "%KOKORO_GFILE_DIR%\distdir\abseil-cpp_vendor.tar.gz" (
+  tar --force-local -xf "%KOKORO_GFILE_DIR%\distdir\abseil-cpp_vendor.tar.gz" -C c:\
+  SET VENDOR_FLAG=--vendor_dir=c:\abseil-cpp_vendor
+) ELSE (
+  SET VENDOR_FLAG=
+)
+
+:: Set the standard version, [c++17|c++20|c++latest]
 :: https://msdn.microsoft.com/en-us/library/mt490614.aspx
-:: The default is c++14 if not set on command line.
-IF "%STD%"=="" SET STD=c++14
+:: The default is c++17 if not set on command line.
+IF "%STD%"=="" SET STD=c++17
 
 :: Set the compilation_mode (fastbuild|opt|dbg)
 :: https://docs.bazel.build/versions/master/user-manual.html#flag--compilation_mode
@@ -39,7 +47,7 @@
 :: /google/data/rw/teams/absl/kokoro/windows.
 ::
 :: TODO(absl-team): Remove -Wno-microsoft-cast
-%KOKORO_GFILE_DIR%\bazel-7.0.0-windows-x86_64.exe ^
+%KOKORO_GFILE_DIR%\bazel-8.2.1-windows-x86_64.exe ^
   test ... ^
   --compilation_mode=%COMPILATION_MODE% ^
   --compiler=clang-cl ^
@@ -47,7 +55,6 @@
   --copt=-Wno-microsoft-cast ^
   --cxxopt=/std:%STD% ^
   --define=absl=1 ^
-  --distdir=%KOKORO_GFILE_DIR%\distdir ^
   --enable_bzlmod=true ^
   --extra_execution_platforms=//:x64_windows-clang-cl ^
   --extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl ^
@@ -55,7 +62,8 @@
   --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" ^
   --test_env=TZDIR="%CD%\absl\time\internal\cctz\testdata\zoneinfo" ^
   --test_output=errors ^
-  --test_tag_filters=-benchmark
+  --test_tag_filters=-benchmark ^
+  %VENDOR_FLAG%
 
 if %errorlevel% neq 0 EXIT /B 1
 EXIT /B 0
diff --git a/ci/windows_msvc_bazel.bat b/ci/windows_msvc_bazel.bat
index e2acf5f..bbb57b4 100755
--- a/ci/windows_msvc_bazel.bat
+++ b/ci/windows_msvc_bazel.bat
@@ -18,10 +18,18 @@
 CD %~dp0\..
 if %errorlevel% neq 0 EXIT /B 1
 
-:: Set the standard version, [c++14|c++latest]
+:: Use Bazel Vendor mode to reduce reliance on external dependencies.
+IF EXIST "%KOKORO_GFILE_DIR%\distdir\abseil-cpp_vendor.tar.gz" (
+  tar --force-local -xf "%KOKORO_GFILE_DIR%\distdir\abseil-cpp_vendor.tar.gz" -C c:\
+  SET VENDOR_FLAG=--vendor_dir=c:\abseil-cpp_vendor
+) ELSE (
+  SET VENDOR_FLAG=
+)
+
+:: Set the standard version, [c++17|c++latest]
 :: https://msdn.microsoft.com/en-us/library/mt490614.aspx
-:: The default is c++14 if not set on command line.
-IF "%STD%"=="" SET STD=c++14
+:: The default is c++17 if not set on command line.
+IF "%STD%"=="" SET STD=c++17
 
 :: Set the compilation_mode (fastbuild|opt|dbg)
 :: https://docs.bazel.build/versions/master/user-manual.html#flag--compilation_mode
@@ -34,19 +42,19 @@
 :: 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-7.0.0-windows-x86_64.exe ^
+"%KOKORO_GFILE_DIR%\bazel-8.2.1-windows-x86_64.exe" ^
   test ... ^
   --compilation_mode=%COMPILATION_MODE% ^
   --copt=/WX ^
   --copt=/std:%STD% ^
   --define=absl=1 ^
-  --distdir=%KOKORO_GFILE_DIR%\distdir ^
   --enable_bzlmod=true ^
   --keep_going ^
   --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" ^
   --test_env=TZDIR="%CD%\absl\time\internal\cctz\testdata\zoneinfo" ^
   --test_output=errors ^
-  --test_tag_filters=-benchmark
+  --test_tag_filters=-benchmark ^
+  %VENDOR_FLAG%
 
 if %errorlevel% neq 0 EXIT /B 1
 EXIT /B 0
diff --git a/ci/windows_msvc_cmake.bat b/ci/windows_msvc_cmake.bat
index c9aee78..62cdb70 100755
--- a/ci/windows_msvc_cmake.bat
+++ b/ci/windows_msvc_cmake.bat
@@ -16,7 +16,7 @@
 
 :: The version of GoogleTest to be used in the CMake tests in this directory.
 :: Keep this in sync with the version in the WORKSPACE file.
-SET ABSL_GOOGLETEST_VERSION=1.15.2
+SET ABSL_GOOGLETEST_VERSION=1.17.0
 SET ABSL_GOOGLETEST_DOWNLOAD_URL=https://github.com/google/googletest/releases/download/v%ABSL_GOOGLETEST_VERSION%/googletest-%ABSL_GOOGLETEST_VERSION%.tar.gz
 
 :: Replace '\' with '/' in Windows paths for CMake.
diff --git a/generate_bp.py b/generate_bp.py
new file mode 100755
index 0000000..6797ba4
--- /dev/null
+++ b/generate_bp.py
@@ -0,0 +1,309 @@
+#!/usr/bin/env python3
+import argparse
+import json
+import subprocess
+import sys
+import os
+
+root_libs = [
+    '//absl/algorithm:algorithm',
+    '//absl/cleanup:cleanup',
+    '//absl/container:btree',
+    '//absl/container:flat_hash_map',
+    '//absl/container:flat_hash_set',
+    '//absl/container:node_hash_map',
+    '//absl/container:node_hash_set',
+    '//absl/debugging:failure_signal_handler',
+    '//absl/flags:flag',
+    '//absl/flags:parse',
+    '//absl/functional:bind_front',
+    '//absl/log:absl_check',
+    '//absl/log:absl_log',
+    '//absl/log:check',
+    '//absl/log:die_if_null',
+    '//absl/log:initialize',
+    '//absl/log:log',
+    '//absl/log:scoped_mock_log',
+    '//absl/random:bit_gen_ref',
+    '//absl/random:random',
+    '//absl/status:statusor',
+    '//absl/strings:strings',
+    '//absl/synchronization:synchronization',
+]
+ignored_deps = set([
+    '@googletest//:gtest'
+])
+
+# Convert names like //foo/bar:baz to foo_bar_baz.
+# If the last segment of the path and the target names are the same,
+# the target name will be dropped, as per bazel convention.
+# eg: //foo/bar:bar -> foo_bar
+def bazel_name_to_bp_name(name):
+    parts = name[name.rfind('/')+1:].split(':')
+    if len(parts) == 2 and parts[0] == parts[1]:
+        name = name.removesuffix(':'+parts[1])
+    name = name[2:].replace('/', '_').replace(':', '_')
+    return name
+
+def main():
+    query = subprocess.check_output(['bazel', 'query', '--output=streamed_jsonproto', 'kind(cc_library, //...)'], text=True)
+    query = query.split('\n')
+
+    # API level 29 is required native ELF TLS support, see bionic/android-changes-for-ndk-developers.md
+    # We need it because absl/strings/internal/cordz_functions.h defines a thread_local global variable.
+    # If we compile with API lower than 29, it won't link correctly with code compiled with API >= 29
+    bp = '''
+    // This Android.bp file was autogenerated by external/absel-cpp/generate_bp.py
+    // DO NOT EDIT
+
+    package {
+        default_applicable_licenses: ["libabsl_license"],
+        default_visibility: ["//visibility:private"],
+    }
+
+    license {
+        name: "libabsl_license",
+        visibility: [":__subpackages__"],
+        license_kinds: ["SPDX-license-identifier-Apache-2.0"],
+        license_text: ["LICENSE"],
+    }
+
+    cc_defaults {
+        name: "absl_defaults",
+        host_supported: true,
+        product_available: true,
+        ramdisk_available: true,
+        recovery_available: true,
+        vendor_available: true,
+        vendor_ramdisk_available: true,
+        sdk_version: "29",
+        min_sdk_version: "apex_inherit",
+        stl: "libc++",
+        apex_available: [
+            "//apex_available:platform",
+            "//apex_available:anyapex",
+        ],
+        target: {
+            windows: {
+                enabled: true,
+                cflags: ["-Wno-unknown-pragmas"],
+            },
+        },
+    }
+
+    cc_defaults {
+        name: "absl_notls_defaults",
+        defaults_visibility: ["//external/protobuf:__subpackages__"],
+        host_supported: true,
+        ramdisk_available: true,
+        recovery_available: true,
+        vendor_ramdisk_available: true,
+        apex_available: [
+            "//apex_available:platform",
+            "com.android.runtime",
+        ],
+        cflags: ["-DANDROID_DISABLE_TLS_FOR_LINKER=1"],
+    }
+
+    cc_defaults {
+        name: "absl_test_defaults",
+        host_supported: true,
+        product_available: true,
+        vendor_available: true,
+        stl: "libc++",
+    }
+
+    cc_defaults {
+        name: "absl_notls_test_defaults",
+        host_supported: true,
+        stl: "libc++",
+        cflags: ["-DANDROID_DISABLE_TLS_FOR_LINKER=1"],
+    }
+    '''
+
+    libs_graph = {}
+    libs = {}
+    alwayslink_libs = {}
+    public_libs = {}
+
+    for q in query:
+        if not q.strip():
+            continue
+        q = json.loads(q)
+        name = q['rule']['name']
+        libs[name] = q
+        libs_graph[name] = []
+        for attr in q['rule']['attribute']:
+            if attr['name'] == 'deps':
+                libs_graph[name] = attr.get('stringListValue', [])
+            if attr['name'] == 'alwayslink':
+                if attr.get('booleanValue', False):
+                    alwayslink_libs[name] = True
+            if attr['name'] == 'visibility':
+                if "//visibility:public" in attr['stringListValue']:
+                    public_libs[name] = True
+
+    queue = [l for l in root_libs]
+    processed = set(ignored_deps)
+
+    while queue:
+        name = queue.pop()
+        if name in processed:
+            continue
+        processed.add(name)
+        lib = libs[name]
+
+        bp_mod_name = bazel_name_to_bp_name(name)
+
+        deps = []
+        srcs = []
+        hdrs = []
+        testonly = False
+        for attr in lib['rule']['attribute']:
+            if attr['name'] == 'deps':
+                deps = attr.get('stringListValue', [])
+            if attr['name'] == 'srcs':
+                srcs = attr.get('stringListValue', [])
+            if attr['name'] == 'hdrs':
+                hdrs.extend(attr.get('stringListValue', []))
+            if attr['name'] == 'textual_hdrs':
+                hdrs.extend(attr.get('stringListValue', []))
+            if attr['name'] == 'testonly':
+                testonly = attr.get('booleanValue', False)
+
+        hdrs = list(sorted(set(hdrs)))
+
+        srcs = [h[2:].replace(':', '/') for h in srcs]
+        hdrs = [h[2:].replace(':', '/') for h in hdrs]
+
+        # In bazel, you can put headers in the srcs field to mean "private" headers that are not
+        # re-exported. Soong doesn't allow .h files in srcs, or .inc files anywhere. So make this
+        # a little easier for soong by moving all headers to the actual headers property, which
+        # will cause some internal headers to be exported but at least this is still better than
+        # exporting the whole absl folder. The .inc files are also copied to the generated header
+        # directories because sometimes headers #include the .inc files.
+        hdrs.extend([h for h in srcs if h.endswith('.h') or h.endswith('.inc')])
+        srcs = [s for s in srcs if not s.endswith('.h') and not s.endswith('.inc')]
+
+        for dep in deps:
+            if dep in alwayslink_libs:
+                # We are actually using whole_static_libs for everything now, so in theory this
+                # error isn't necessary. But we want to use regular static_libs. We only use
+                # whole_static_libs because soong doesn't re-export static_lib dependencies.
+                # (b/123002125#comment3)
+                sys.exit(f'{name} depends on {dep}, which is alwayslink=1. alwayslink isn\'t supported by this script. (would need to use whole_static_libs instead of static_libs)')
+
+        generated_hdrs_attr = ""
+        if hdrs:
+            header_files_for_bp = ['"' + h + '"' for h in hdrs]
+            # We add an extra my_include_dir/ to not get duplication location errors, as both in and
+            # out are exactly the same paths
+            header_files_for_out = ['"my_include_dir/' + h + '"' for h in hdrs]
+            bp += f'''
+            genrule {{
+                name: "{bp_mod_name}_hdrs",
+                srcs: [
+                  {',\n'.join(header_files_for_bp)}
+                ],
+                out: [
+                  {',\n'.join(header_files_for_out)}
+                ],
+                export_include_dirs: ["my_include_dir"],
+                cmd: "mkdir -p $(genDir)/my_include_dir $(genDir)/temp && " +
+                  "cp --parents $(in) $(genDir)/temp && " +
+                  // delete empty folders automatically created by soong
+                  "rm -rf $(genDir)/my_include_dir/* && " +
+                  "mv $(genDir)/temp/external/abseil-cpp/absl $(genDir)/my_include_dir/ && " +
+                  "rm -rf $(genDir)/temp"
+            }}
+            '''
+            generated_hdrs_attr = f'generated_headers: ["{bp_mod_name}_hdrs"],\n'
+            generated_hdrs_attr += f'export_generated_headers: ["{bp_mod_name}_hdrs"],\n'
+
+        module_type = 'cc_library_static'
+        defaults_module = 'absl_defaults'
+        notls_defaults_module = 'absl_notls_defaults'
+        bp_deps = [bazel_name_to_bp_name(d) for d in deps if d not in ignored_deps]
+        extra_attributes = ''
+
+        # Special handling for test-only libraries.
+        if testonly:
+            module_type = 'cc_test_library'
+            defaults_module = 'absl_test_defaults'
+            notls_defaults_module = 'absl_notls_test_defaults'
+            extra_attributes = '''
+            static_libs: ["libgmock", "libgtest"],
+            shared: {
+                enabled: false,
+            },
+            '''
+
+        # Hardcode the addition of liblog to log_sink_set. log_sink_set uses a select() in bazel
+        # to add the liblog dep only on android.
+        if name == "//absl/log/internal:log_sink_set":
+            extra_attributes = '''
+            target: {
+                android: {
+                    shared_libs: ["liblog"],
+                },
+            },
+            '''
+
+        visibility_prop = ''
+        visibility_prop_notls = ''
+        if name in public_libs:
+            visibility_prop = 'visibility: ["//visibility:public"],'
+            visibility_prop_notls = 'visibility: ["//external/protobuf"],'
+
+        bp_deps_for_bp = ['"' + d + '"' for d in bp_deps]
+        src_files_for_bp = ['"' + h + '"' for h in srcs]
+        bp += f'''
+        {module_type} {{
+            name: "{bp_mod_name}",
+            defaults: ["{defaults_module}"],
+            {visibility_prop}
+            srcs: [
+                {',\n'.join(src_files_for_bp)}
+            ],
+            {generated_hdrs_attr}
+            whole_static_libs: [
+                {',\n'.join(bp_deps_for_bp)}
+            ],
+            export_static_lib_headers: [
+                {',\n'.join(bp_deps_for_bp)}
+            ],
+            {extra_attributes}
+        }}
+        '''
+
+        # We need to generate separate versions of the library with TLS disabled
+        # for use in the dynamic linker and its dependencies, which does not
+        # support ELF TLS segments when loading itself.
+        bp_notls_deps_for_bp = ['"' + d + '_notls"' for d in bp_deps]
+        bp += f'''
+        {module_type} {{
+            name: "{bp_mod_name}_notls",
+            defaults: ["{notls_defaults_module}"],
+            {visibility_prop_notls}
+            srcs: [
+                {',\n'.join(src_files_for_bp)}
+            ],
+            {generated_hdrs_attr}
+            whole_static_libs: [
+                {',\n'.join(bp_notls_deps_for_bp)}
+            ],
+            export_static_lib_headers: [
+                {',\n'.join(bp_notls_deps_for_bp)}
+            ],
+            {extra_attributes}
+        }}
+        '''
+
+        queue.extend(deps)
+
+    with open('Android.bp', 'w') as f:
+        f.write(bp)
+    subprocess.check_call(['bpfmt', '-w', 'Android.bp'])
+
+if __name__ == "__main__":
+    main()