Uprev webrtc-apm to upstream WebRTC M89

This change is created by:
1. ./script/sync-apm.sh <webrtc branch-heads/4389> .
with head commit https://webrtc-review.googlesource.com/c/src/+/205280
2. Modify modules.mk files until everything compiles
3. Re-apply commit 1a11b8a webrtc-apm: Replace deprected Json::Reader call.

BUG=b:175761810
TEST=emerge webrtc-apm and deploy
Execute 'cras_test_client -C /dev/null --effects aec' to verify
on octopus

Change-Id: Ia213c55ab76b9bbaa2e9bdf9ff343f114d6e6ba0
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/webrtc-apm/+/2671443
Reviewed-by: Hsinyu Chao <hychao@chromium.org>
Tested-by: Hsinyu Chao <hychao@chromium.org>
Commit-Queue: Hsinyu Chao <hychao@chromium.org>
diff --git a/Makefile b/Makefile
index 8771078..cc2df0e 100644
--- a/Makefile
+++ b/Makefile
@@ -24,6 +24,7 @@
 
 libwebrtc_apm_CXX_OBJECTS = \
 	libaudio_processing \
+	rnn_vad \
 	rtc_base/librtc_base \
 	common_audio/libcommon_audio \
 	system_wrappers/source/libsystem_wrappers \
@@ -35,6 +36,7 @@
 
 ifeq (${USE_SSE2},1)
 libwebrtc_apm_CXX_OBJECTS += \
+	rnn_vad_avx2 \
 	common_audio_avx2 \
 	aec3_avx2
 endif
@@ -52,6 +54,7 @@
 	common_audio/libcommon_audio.pic.a \
 	system_wrappers/source/libsystem_wrappers.pic.a \
 	modules/audio_coding/libaudio_coding.pic.a \
+	rnn_vad.pic.a \
 	rtc_base/librtc_base.pic.a \
 	libaudioproc_debug_proto.pic.a \
 	absl.pic.a \
@@ -62,7 +65,8 @@
 ifeq (${USE_SSE2},1)
 CXX_LIBRARY(libwebrtc_apm.so): LDLIBS += \
 	aec3_avx2.pic.a \
-	common_audio_avx2.pic.a
+	common_audio_avx2.pic.a \
+	rnn_vad_avx2.pic.a
 endif
 
 all: CXX_LIBRARY(libwebrtc_apm.so)
diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel
index 0b772df..6da20c4 100644
--- a/absl/BUILD.bazel
+++ b/absl/BUILD.bazel
@@ -12,19 +12,16 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
-
-load(
-    ":compiler_config_setting.bzl",
-    "create_llvm_config",
-)
 
 package(default_visibility = ["//visibility:public"])
 
 licenses(["notice"])
 
-create_llvm_config(
-    name = "llvm_compiler",
+config_setting(
+    name = "clang_compiler",
+    flag_values = {
+        "@bazel_tools//tools/cpp:compiler": "clang",
+    },
     visibility = [":__subpackages__"],
 )
 
diff --git a/absl/abseil.podspec.gen.py b/absl/abseil.podspec.gen.py
index 6aefb79..6375298 100755
--- a/absl/abseil.podspec.gen.py
+++ b/absl/abseil.podspec.gen.py
@@ -40,8 +40,8 @@
     'USE_HEADERMAP' => 'NO',
     'ALWAYS_SEARCH_USER_PATHS' => 'NO',
   }
-  s.ios.deployment_target = '7.0'
-  s.osx.deployment_target = '10.9'
+  s.ios.deployment_target = '9.0'
+  s.osx.deployment_target = '10.10'
   s.tvos.deployment_target = '9.0'
   s.watchos.deployment_target = '2.0'
 """
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index 229cd71..a3002b7 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "algorithm",
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index 2457d78..6398438 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -90,10 +90,10 @@
 // lookup of std::begin and std::end, i.e.
 //   using std::begin;
 //   using std::end;
-//   std::foo(begin(c), end(c);
+//   std::foo(begin(c), end(c));
 // becomes
 //   std::foo(container_algorithm_internal::begin(c),
-//   container_algorithm_internal::end(c));
+//            container_algorithm_internal::end(c));
 // These are meant for internal use only.
 
 template <typename C>
@@ -188,7 +188,7 @@
 // c_none_of()
 //
 // Container-based version of the <algorithm> `std::none_of()` function to
-// test if no elements in a container fulfil a condition.
+// test if no elements in a container fulfill a condition.
 template <typename C, typename Pred>
 bool c_none_of(const C& c, Pred&& pred) {
   return std::none_of(container_algorithm_internal::c_begin(c),
@@ -340,24 +340,45 @@
 // c_mismatch()
 //
 // Container-based version of the <algorithm> `std::mismatch()` function to
-// return the first element where two ordered containers differ.
+// 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) {
-  return std::mismatch(container_algorithm_internal::c_begin(c1),
-                       container_algorithm_internal::c_end(c1),
-                       container_algorithm_internal::c_begin(c2));
+  auto first1 = container_algorithm_internal::c_begin(c1);
+  auto last1 = container_algorithm_internal::c_end(c1);
+  auto first2 = container_algorithm_internal::c_begin(c2);
+  auto last2 = container_algorithm_internal::c_end(c2);
+
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+    // Negates equality because Cpp17EqualityComparable doesn't require clients
+    // to overload both `operator==` and `operator!=`.
+    if (!(*first1 == *first2)) {
+      break;
+    }
+  }
+
+  return std::make_pair(first1, first2);
 }
 
 // Overload of c_mismatch() for using a predicate evaluation other than `==` as
-// the function's test condition.
+// 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) {
-  return std::mismatch(container_algorithm_internal::c_begin(c1),
-                       container_algorithm_internal::c_end(c1),
-                       container_algorithm_internal::c_begin(c2),
-                       std::forward<BinaryPredicate>(pred));
+c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
+  auto first1 = container_algorithm_internal::c_begin(c1);
+  auto last1 = container_algorithm_internal::c_end(c1);
+  auto first2 = container_algorithm_internal::c_begin(c2);
+  auto last2 = container_algorithm_internal::c_end(c2);
+
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+    if (!pred(*first1, *first2)) {
+      break;
+    }
+  }
+
+  return std::make_pair(first1, first2);
 }
 
 // c_equal()
@@ -539,12 +560,20 @@
 // c_swap_ranges()
 //
 // Container-based version of the <algorithm> `std::swap_ranges()` function to
-// swap a container's elements with another container's elements.
+// swap a container's elements with another container's elements. Swaps the
+// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
 template <typename C1, typename C2>
 container_algorithm_internal::ContainerIter<C2> c_swap_ranges(C1& c1, C2& c2) {
-  return std::swap_ranges(container_algorithm_internal::c_begin(c1),
-                          container_algorithm_internal::c_end(c1),
-                          container_algorithm_internal::c_begin(c2));
+  auto first1 = container_algorithm_internal::c_begin(c1);
+  auto last1 = container_algorithm_internal::c_end(c1);
+  auto first2 = container_algorithm_internal::c_begin(c2);
+  auto last2 = container_algorithm_internal::c_end(c2);
+
+  using std::swap;
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+    swap(*first1, *first2);
+  }
+  return first2;
 }
 
 // c_transform()
@@ -562,16 +591,23 @@
 }
 
 // Overload of c_transform() for performing a transformation using a binary
-// predicate.
+// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,
+// where N = min(size(c1), size(c2)).
 template <typename InputSequence1, typename InputSequence2,
           typename OutputIterator, typename BinaryOp>
 OutputIterator c_transform(const InputSequence1& input1,
                            const InputSequence2& input2, OutputIterator output,
                            BinaryOp&& binary_op) {
-  return std::transform(container_algorithm_internal::c_begin(input1),
-                        container_algorithm_internal::c_end(input1),
-                        container_algorithm_internal::c_begin(input2), output,
-                        std::forward<BinaryOp>(binary_op));
+  auto first1 = container_algorithm_internal::c_begin(input1);
+  auto last1 = container_algorithm_internal::c_end(input1);
+  auto first2 = container_algorithm_internal::c_begin(input2);
+  auto last2 = container_algorithm_internal::c_end(input2);
+  for (; first1 != last1 && first2 != last2;
+       ++first1, (void)++first2, ++output) {
+    *output = binary_op(*first1, *first2);
+  }
+
+  return output;
 }
 
 // c_replace()
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 0a4abe9..605afc8 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -57,9 +57,7 @@
 };
 
 struct AccumulateCalls {
-  void operator()(int value) {
-    calls.push_back(value);
-  }
+  void operator()(int value) { calls.push_back(value); }
   std::vector<int> calls;
 };
 
@@ -68,7 +66,6 @@
 bool Equals(int v1, int v2) { return v1 == v2; }
 bool IsOdd(int x) { return x % 2 != 0; }
 
-
 TEST_F(NonMutatingTest, Distance) {
   EXPECT_EQ(container_.size(), absl::c_distance(container_));
   EXPECT_EQ(sequence_.size(), absl::c_distance(sequence_));
@@ -151,13 +148,90 @@
 }
 
 TEST_F(NonMutatingTest, Mismatch) {
-  absl::c_mismatch(container_, sequence_);
-  absl::c_mismatch(sequence_, container_);
+  // Testing necessary as absl::c_mismatch executes logic.
+  {
+    auto result = absl::c_mismatch(vector_, sequence_);
+    EXPECT_EQ(result.first, vector_.end());
+    EXPECT_EQ(result.second, sequence_.end());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_);
+    EXPECT_EQ(result.first, sequence_.end());
+    EXPECT_EQ(result.second, vector_.end());
+  }
+
+  sequence_.back() = 5;
+  {
+    auto result = absl::c_mismatch(vector_, sequence_);
+    EXPECT_EQ(result.first, std::prev(vector_.end()));
+    EXPECT_EQ(result.second, std::prev(sequence_.end()));
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_);
+    EXPECT_EQ(result.first, std::prev(sequence_.end()));
+    EXPECT_EQ(result.second, std::prev(vector_.end()));
+  }
+
+  sequence_.pop_back();
+  {
+    auto result = absl::c_mismatch(vector_, sequence_);
+    EXPECT_EQ(result.first, std::prev(vector_.end()));
+    EXPECT_EQ(result.second, sequence_.end());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_);
+    EXPECT_EQ(result.first, sequence_.end());
+    EXPECT_EQ(result.second, std::prev(vector_.end()));
+  }
+  {
+    struct NoNotEquals {
+      constexpr bool operator==(NoNotEquals) const { return true; }
+      constexpr bool operator!=(NoNotEquals) const = delete;
+    };
+    std::vector<NoNotEquals> first;
+    std::list<NoNotEquals> second;
+
+    // Check this still compiles.
+    absl::c_mismatch(first, second);
+  }
 }
 
 TEST_F(NonMutatingTest, MismatchWithPredicate) {
-  absl::c_mismatch(container_, sequence_, BinPredicate);
-  absl::c_mismatch(sequence_, container_, BinPredicate);
+  // Testing necessary as absl::c_mismatch executes logic.
+  {
+    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+    EXPECT_EQ(result.first, vector_.begin());
+    EXPECT_EQ(result.second, sequence_.begin());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+    EXPECT_EQ(result.first, sequence_.begin());
+    EXPECT_EQ(result.second, vector_.begin());
+  }
+
+  sequence_.front() = 0;
+  {
+    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+    EXPECT_EQ(result.first, vector_.begin());
+    EXPECT_EQ(result.second, sequence_.begin());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+    EXPECT_EQ(result.first, std::next(sequence_.begin()));
+    EXPECT_EQ(result.second, std::next(vector_.begin()));
+  }
+
+  sequence_.clear();
+  {
+    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+    EXPECT_EQ(result.first, vector_.begin());
+    EXPECT_EQ(result.second, sequence_.end());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+    EXPECT_EQ(result.first, sequence_.end());
+    EXPECT_EQ(result.second, vector_.begin());
+  }
 }
 
 TEST_F(NonMutatingTest, Equal) {
@@ -519,11 +593,9 @@
 TEST_F(SortingTest, NthElement) {
   std::vector<int> unsorted = {2, 4, 1, 3};
   absl::c_nth_element(unsorted, unsorted.begin() + 2);
-  EXPECT_THAT(unsorted,
-              ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
+  EXPECT_THAT(unsorted, ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
   absl::c_nth_element(unsorted, unsorted.begin() + 2, std::greater<int>());
-  EXPECT_THAT(unsorted,
-              ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
+  EXPECT_THAT(unsorted, ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
 }
 
 TEST(MutatingTest, IsPartitioned) {
@@ -676,6 +748,15 @@
   absl::c_swap_ranges(odds, evens);
   EXPECT_THAT(odds, ElementsAre(1, 3, 5));
   EXPECT_THAT(evens, ElementsAre(2, 4, 6));
+
+  odds.pop_back();
+  absl::c_swap_ranges(odds, evens);
+  EXPECT_THAT(odds, ElementsAre(2, 4));
+  EXPECT_THAT(evens, ElementsAre(1, 3, 6));
+
+  absl::c_swap_ranges(evens, odds);
+  EXPECT_THAT(odds, ElementsAre(1, 3));
+  EXPECT_THAT(evens, ElementsAre(2, 4, 6));
 }
 
 TEST_F(NonMutatingTest, Transform) {
@@ -690,6 +771,20 @@
   EXPECT_EQ(std::vector<int>({1, 5, 4}), z);
   *end = 7;
   EXPECT_EQ(std::vector<int>({1, 5, 4, 7}), z);
+
+  z.clear();
+  y.pop_back();
+  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
+  EXPECT_EQ(std::vector<int>({1, 5}), z);
+  *end = 7;
+  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
+
+  z.clear();
+  std::swap(x, y);
+  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
+  EXPECT_EQ(std::vector<int>({1, 5}), z);
+  *end = 7;
+  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
 }
 
 TEST(MutatingTest, Replace) {
@@ -755,10 +850,9 @@
 TEST(MutatingTest, StableSort) {
   std::vector<Element> test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}};
   absl::c_stable_sort(test_vector);
-  EXPECT_THAT(
-      test_vector,
-      ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
-                  IsElement(2, 0), IsElement(2, 2)));
+  EXPECT_THAT(test_vector,
+              ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
+                          IsElement(2, 0), IsElement(2, 2)));
 }
 
 TEST(MutatingTest, StableSortWithPredicate) {
@@ -766,10 +860,9 @@
   absl::c_stable_sort(test_vector, [](const Element& e1, const Element& e2) {
     return e2 < e1;
   });
-  EXPECT_THAT(
-      test_vector,
-      ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
-                  IsElement(1, 1), IsElement(1, 0)));
+  EXPECT_THAT(test_vector,
+              ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
+                          IsElement(1, 1), IsElement(1, 0)));
 }
 
 TEST(MutatingTest, ReplaceCopyIf) {
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 2c4887b..9d96abe 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "atomic_hook",
diff --git a/absl/base/BUILD.gn b/absl/base/BUILD.gn
index 16a6387..346a47d 100644
--- a/absl/base/BUILD.gn
+++ b/absl/base/BUILD.gn
@@ -6,7 +6,7 @@
 
 absl_source_set("atomic_hook") {
   public = [ "internal/atomic_hook.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -15,14 +15,14 @@
 
 absl_source_set("errno_saver") {
   public = [ "internal/errno_saver.h" ]
-  deps = [ ":config" ]
+  public_deps = [ ":config" ]
   visibility = [ "//third_party/abseil-cpp/absl/*" ]
 }
 
 absl_source_set("log_severity") {
   sources = [ "log_severity.cc" ]
   public = [ "log_severity.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -31,7 +31,7 @@
 absl_source_set("raw_logging_internal") {
   sources = [ "internal/raw_logging.cc" ]
   public = [ "internal/raw_logging.h" ]
-  deps = [
+  public_deps = [
     ":atomic_hook",
     ":config",
     ":core_headers",
@@ -86,7 +86,7 @@
     "port.h",
     "thread_annotations.h",
   ]
-  deps = [ ":config" ]
+  public_deps = [ ":config" ]
 }
 
 absl_source_set("malloc_internal") {
@@ -95,7 +95,7 @@
     "internal/direct_mmap.h",
     "internal/low_level_alloc.h",
   ]
-  deps = [
+  public_deps = [
     ":base",
     ":base_internal",
     ":config",
@@ -113,7 +113,7 @@
     "internal/invoke.h",
     "internal/scheduling_mode.h",
   ]
-  deps = [
+  public_deps = [
     ":config",
     "//third_party/abseil-cpp/absl/meta:type_traits",
   ]
@@ -144,7 +144,7 @@
   # TODO(mbonadei): The bazel file has:
   #   "-DEFAULTLIB:advapi32.lib"
   # understand if this is needed here as well.
-  deps = [
+  public_deps = [
     ":atomic_hook",
     ":base_internal",
     ":config",
@@ -160,7 +160,7 @@
 absl_source_set("throw_delegate") {
   sources = [ "internal/throw_delegate.cc" ]
   public = [ "internal/throw_delegate.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":raw_logging_internal",
   ]
@@ -170,7 +170,7 @@
 absl_source_set("exception_testing") {
   testonly = true
   public = [ "internal/exception_testing.h" ]
-  deps = [ ":config" ]
+  public_deps = [ ":config" ]
   visibility = [ "//third_party/abseil-cpp/absl/*" ]
 }
 
@@ -224,7 +224,7 @@
     "internal/endian.h",
     "internal/unaligned_access.h",
   ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -232,7 +232,7 @@
 
 absl_source_set("bits") {
   public = [ "internal/bits.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -242,7 +242,7 @@
 absl_source_set("exponential_biased") {
   sources = [ "internal/exponential_biased.cc" ]
   public = [ "internal/exponential_biased.h" ]
-  deps = [
+  public_deps = [
     ":config",
     ":core_headers",
   ]
@@ -252,7 +252,7 @@
 absl_source_set("periodic_sampler") {
   sources = [ "internal/periodic_sampler.cc" ]
   public = [ "internal/periodic_sampler.h" ]
-  deps = [
+  public_deps = [
     ":core_headers",
     ":exponential_biased",
   ]
@@ -262,8 +262,10 @@
   testonly = true
   public = [ "internal/scoped_set_env.h" ]
   sources = [ "internal/scoped_set_env.cc" ]
-  deps = [
+  public_deps = [
     ":config",
+  ]
+  deps = [
     ":raw_logging_internal",
   ]
   visibility = [ "//third_party/abseil-cpp/absl/*" ]
@@ -272,8 +274,10 @@
 absl_source_set("strerror") {
   sources = [ "internal/strerror.cc" ]
   public = [ "internal/strerror.h" ]
-  deps = [
+  public_deps = [
     ":config",
+  ]
+  deps = [
     ":core_headers",
     ":errno_saver",
   ]
@@ -282,7 +286,7 @@
 
 absl_source_set("fast_type_id") {
   public = [ "internal/fast_type_id.h" ]
-  deps = [ ":config" ]
+  public_deps = [ ":config" ]
   visibility = [ "//third_party/abseil-cpp/absl/*" ]
 }
 
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index 046fbea..f1d3cfe 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -607,6 +607,7 @@
 // When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro
 // has no effect on diagnostics. In any case this macro has no effect on runtime
 // behavior and performance of code.
+
 #ifdef ABSL_FALLTHROUGH_INTENDED
 #error "ABSL_FALLTHROUGH_INTENDED should not be defined."
 #endif
diff --git a/absl/base/casts.h b/absl/base/casts.h
index 322cc1d..83c6912 100644
--- a/absl/base/casts.h
+++ b/absl/base/casts.h
@@ -159,16 +159,19 @@
   return dest;
 }
 
-// NOTE: This overload is only picked if the requirements of bit_cast are not
-// met. It is therefore UB, but is provided temporarily as previous versions of
-// this function template were unchecked. Do not use this in new code.
+// NOTE: This overload is only picked if the requirements of bit_cast are
+// not met. It is therefore UB, but is provided temporarily as previous
+// versions of this function template were unchecked. Do not use this in
+// new code.
 template <
     typename Dest, typename Source,
     typename std::enable_if<
-        !internal_casts::is_bitcastable<Dest, Source>::value, int>::type = 0>
+        !internal_casts::is_bitcastable<Dest, Source>::value,
+        int>::type = 0>
 ABSL_DEPRECATED(
-    "absl::bit_cast type requirements were violated. Update the types being "
-    "used such that they are the same size and are both TriviallyCopyable.")
+    "absl::bit_cast type requirements were violated. Update the types "
+    "being used such that they are the same size and are both "
+    "TriviallyCopyable.")
 inline Dest bit_cast(const Source& source) {
   static_assert(sizeof(Dest) == sizeof(Source),
                 "Source and destination types should have equal sizes.");
diff --git a/absl/base/config.h b/absl/base/config.h
index b1e095d..3f7f32b 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -364,7 +364,7 @@
 #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||   \
     defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
     defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
-    defined(__ASYLO__)
+    defined(__ASYLO__) || defined(__myriad2__)
 #define ABSL_HAVE_MMAP 1
 #endif
 
@@ -474,9 +474,9 @@
   (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
    __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
   (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
-   __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 120000) || \
+   __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
   (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
-   __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 50000))
+   __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
 #define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
 #else
 #define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h
index 1911272..94488ac 100644
--- a/absl/base/dynamic_annotations.h
+++ b/absl/base/dynamic_annotations.h
@@ -80,12 +80,9 @@
 #define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1
 #if !defined(SWIG)
 #define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
-#else
-#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
 #endif
 #else
 #define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
-#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 0
 #endif
 
 // Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
@@ -268,19 +265,19 @@
 // -------------------------------------------------------------------------
 // Define IGNORE_READS_BEGIN/_END attributes.
 
-#if ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 1
+#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
 
 #define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
   __attribute((exclusive_lock_function("*")))
 #define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
   __attribute((unlock_function("*")))
 
-#else  // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED == 0
+#else  // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
 
 #define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE  // empty
 #define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE    // empty
 
-#endif  // ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED
+#endif  // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
 
 // -------------------------------------------------------------------------
 // Define IGNORE_READS_BEGIN/_END annotations.
diff --git a/absl/base/internal/exponential_biased_test.cc b/absl/base/internal/exponential_biased_test.cc
index 90a482d..075583c 100644
--- a/absl/base/internal/exponential_biased_test.cc
+++ b/absl/base/internal/exponential_biased_test.cc
@@ -185,7 +185,7 @@
   ABSL_CONST_INIT static ExponentialBiased eb_static;
   EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0));
 
-#if ABSL_HAVE_THREAD_LOCAL
+#ifdef ABSL_HAVE_THREAD_LOCAL
   thread_local ExponentialBiased eb_thread;
   EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0));
 #endif
diff --git a/absl/base/internal/strerror.cc b/absl/base/internal/strerror.cc
index af18151..d66ba12 100644
--- a/absl/base/internal/strerror.cc
+++ b/absl/base/internal/strerror.cc
@@ -14,6 +14,7 @@
 
 #include "absl/base/internal/strerror.h"
 
+#include <array>
 #include <cerrno>
 #include <cstddef>
 #include <cstdio>
@@ -21,13 +22,13 @@
 #include <string>
 #include <type_traits>
 
-#include "absl/base/attributes.h"
 #include "absl/base/internal/errno_saver.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 namespace {
+
 const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
 #if defined(_WIN32)
   int rc = strerror_s(buf, buflen, errnum);
@@ -35,15 +36,6 @@
   if (rc == 0 && strncmp(buf, "Unknown error", buflen) == 0) *buf = '\0';
   return buf;
 #else
-#if defined(__GLIBC__) || defined(__APPLE__)
-  // Use the BSD sys_errlist API provided by GNU glibc and others to
-  // avoid any need to copy the message into the local buffer first.
-  if (0 <= errnum && errnum < sys_nerr) {
-    if (const char* p = sys_errlist[errnum]) {
-      return p;
-    }
-  }
-#endif
   // The type of `ret` is platform-specific; both of these branches must compile
   // either way but only one will execute on any given platform:
   auto ret = strerror_r(errnum, buf, buflen);
@@ -57,9 +49,8 @@
   }
 #endif
 }
-}  // namespace
 
-std::string StrError(int errnum) {
+std::string StrErrorInternal(int errnum) {
   absl::base_internal::ErrnoSaver errno_saver;
   char buf[100];
   const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
@@ -70,6 +61,28 @@
   return str;
 }
 
+// kSysNerr is the number of errors from a recent glibc. `StrError()` falls back
+// to `StrErrorAdaptor()` if the value is larger than this.
+constexpr int kSysNerr = 135;
+
+std::array<std::string, kSysNerr>* NewStrErrorTable() {
+  auto* table = new std::array<std::string, kSysNerr>;
+  for (int i = 0; i < static_cast<int>(table->size()); ++i) {
+    (*table)[i] = StrErrorInternal(i);
+  }
+  return table;
+}
+
+}  // namespace
+
+std::string StrError(int errnum) {
+  static const auto* table = NewStrErrorTable();
+  if (errnum >= 0 && errnum < static_cast<int>(table->size())) {
+    return (*table)[errnum];
+  }
+  return StrErrorInternal(errnum);
+}
+
 }  // namespace base_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/strerror_benchmark.cc b/absl/base/internal/strerror_benchmark.cc
index d8ca86b..c9ab14a 100644
--- a/absl/base/internal/strerror_benchmark.cc
+++ b/absl/base/internal/strerror_benchmark.cc
@@ -20,15 +20,6 @@
 #include "benchmark/benchmark.h"
 
 namespace {
-#if defined(__GLIBC__) || defined(__APPLE__)
-void BM_SysErrList(benchmark::State& state) {
-  for (auto _ : state) {
-    benchmark::DoNotOptimize(std::string(sys_errlist[ERANGE]));
-  }
-}
-BENCHMARK(BM_SysErrList);
-#endif
-
 void BM_AbslStrError(benchmark::State& state) {
   for (auto _ : state) {
     benchmark::DoNotOptimize(absl::base_internal::StrError(ERANGE));
diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc
index 349d926..4a3b205 100644
--- a/absl/base/internal/sysinfo.cc
+++ b/absl/base/internal/sysinfo.cc
@@ -426,7 +426,7 @@
 // userspace construct) to avoid unnecessary system calls. Without this caching,
 // it can take roughly 98ns, while it takes roughly 1ns with this caching.
 pid_t GetCachedTID() {
-#if ABSL_HAVE_THREAD_LOCAL
+#ifdef ABSL_HAVE_THREAD_LOCAL
   static thread_local pid_t thread_id = GetTID();
   return thread_id;
 #else
diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc
index d63a04a..6ea010e 100644
--- a/absl/base/internal/thread_identity.cc
+++ b/absl/base/internal/thread_identity.cc
@@ -23,6 +23,7 @@
 #include <cassert>
 #include <memory>
 
+#include "absl/base/attributes.h"
 #include "absl/base/call_once.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/spinlock.h"
@@ -53,9 +54,11 @@
 // exist within a process (via dlopen() or similar), references to
 // thread_identity_ptr from each instance of the code will refer to
 // *different* instances of this ptr.
-#ifdef __GNUC__
+// Apple platforms have the visibility attribute, but issue a compile warning
+// that protected visibility is unsupported.
+#if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
 __attribute__((visibility("protected")))
-#endif  // __GNUC__
+#endif  // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
 #if ABSL_PER_THREAD_TLS
 // Prefer __thread to thread_local as benchmarks indicate it is a bit faster.
 ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr;
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index ceb109b..d2a65fd 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -32,6 +32,7 @@
 
 #include "absl/base/config.h"
 #include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/optimization.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -69,30 +70,28 @@
                          // is using this PerThreadSynch as a terminator.  Its
                          // skip field must not be filled in because the loop
                          // might then skip over the terminator.
-
-  // The wait parameters of the current wait.  waitp is null if the
-  // thread is not waiting. Transitions from null to non-null must
-  // occur before the enqueue commit point (state = kQueued in
-  // Enqueue() and CondVarEnqueue()). Transitions from non-null to
-  // null must occur after the wait is finished (state = kAvailable in
-  // Mutex::Block() and CondVar::WaitCommon()). This field may be
-  // changed only by the thread that describes this PerThreadSynch.  A
-  // special case is Fer(), which calls Enqueue() on another thread,
-  // but with an identical SynchWaitParams pointer, thus leaving the
-  // pointer unchanged.
-  SynchWaitParams *waitp;
-
-  bool suppress_fatal_errors;  // If true, try to proceed even in the face of
-                               // broken invariants.  This is used within fatal
-                               // signal handlers to improve the chances of
-                               // debug logging information being output
-                               // successfully.
-
-  intptr_t readers;     // Number of readers in mutex.
-  int priority;         // Priority of thread (updated every so often).
-
-  // When priority will next be read (cycles).
-  int64_t next_priority_read_cycles;
+  bool wake;             // This thread is to be woken from a Mutex.
+  // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
+  // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
+  //
+  // The value of "x->cond_waiter" is meaningless if "x" is not on a
+  // Mutex waiter list.
+  bool cond_waiter;
+  bool maybe_unlocking;  // Valid at head of Mutex waiter queue;
+                         // true if UnlockSlow could be searching
+                         // for a waiter to wake.  Used for an optimization
+                         // in Enqueue().  true is always a valid value.
+                         // Can be reset to false when the unlocker or any
+                         // writer releases the lock, or a reader fully
+                         // releases the lock.  It may not be set to false
+                         // by a reader that decrements the count to
+                         // non-zero. protected by mutex spinlock
+  bool suppress_fatal_errors;  // If true, try to proceed even in the face
+                               // of broken invariants.  This is used within
+                               // fatal signal handlers to improve the
+                               // chances of debug logging information being
+                               // output successfully.
+  int priority;                // Priority of thread (updated every so often).
 
   // State values:
   //   kAvailable: This PerThreadSynch is available.
@@ -111,30 +110,30 @@
   };
   std::atomic<State> state;
 
-  bool maybe_unlocking;  // Valid at head of Mutex waiter queue;
-                         // true if UnlockSlow could be searching
-                         // for a waiter to wake.  Used for an optimization
-                         // in Enqueue().  true is always a valid value.
-                         // Can be reset to false when the unlocker or any
-                         // writer releases the lock, or a reader fully releases
-                         // the lock.  It may not be set to false by a reader
-                         // that decrements the count to non-zero.
-                         // protected by mutex spinlock
+  // The wait parameters of the current wait.  waitp is null if the
+  // thread is not waiting. Transitions from null to non-null must
+  // occur before the enqueue commit point (state = kQueued in
+  // Enqueue() and CondVarEnqueue()). Transitions from non-null to
+  // null must occur after the wait is finished (state = kAvailable in
+  // Mutex::Block() and CondVar::WaitCommon()). This field may be
+  // changed only by the thread that describes this PerThreadSynch.  A
+  // special case is Fer(), which calls Enqueue() on another thread,
+  // but with an identical SynchWaitParams pointer, thus leaving the
+  // pointer unchanged.
+  SynchWaitParams* waitp;
 
-  bool wake;  // This thread is to be woken from a Mutex.
+  intptr_t readers;     // Number of readers in mutex.
 
-  // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
-  // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
-  //
-  // The value of "x->cond_waiter" is meaningless if "x" is not on a
-  // Mutex waiter list.
-  bool cond_waiter;
+  // When priority will next be read (cycles).
+  int64_t next_priority_read_cycles;
 
   // Locks held; used during deadlock detection.
   // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
   SynchLocksHeld *all_locks;
 };
 
+// The instances of this class are allocated in NewThreadIdentity() with an
+// alignment of PerThreadSynch::kAlignment.
 struct ThreadIdentity {
   // Must be the first member.  The Mutex implementation requires that
   // the PerThreadSynch object associated with each thread is
@@ -212,7 +211,9 @@
 #define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
 #elif defined(_WIN32) && !defined(__MINGW32__)
 #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
-#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
+#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
+#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
+#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) &&        \
     (__GOOGLE_GRTE_VERSION__ >= 20140228L)
 // Support for async-safe TLS was specifically added in GRTEv4.  It's not
 // present in the upstream eglibc.
diff --git a/absl/base/internal/throw_delegate.cc b/absl/base/internal/throw_delegate.cc
index c055f75..c260ff1 100644
--- a/absl/base/internal/throw_delegate.cc
+++ b/absl/base/internal/throw_delegate.cc
@@ -18,6 +18,7 @@
 #include <functional>
 #include <new>
 #include <stdexcept>
+
 #include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 
@@ -25,83 +26,186 @@
 ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
+// NOTE: The various STL exception throwing functions are placed within the
+// #ifdef blocks so the symbols aren't exposed on platforms that don't support
+// them, such as the Android NDK. For example, ANGLE fails to link when building
+// within AOSP without them, since the STL functions don't exist.
 namespace {
+#ifdef ABSL_HAVE_EXCEPTIONS
 template <typename T>
 [[noreturn]] void Throw(const T& error) {
-#ifdef ABSL_HAVE_EXCEPTIONS
   throw error;
-#else
-  ABSL_RAW_LOG(FATAL, "%s", error.what());
-  std::abort();
-#endif
 }
+#endif
 }  // namespace
 
 void ThrowStdLogicError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::logic_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdLogicError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::logic_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 void ThrowStdInvalidArgument(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::invalid_argument(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdInvalidArgument(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::invalid_argument(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdDomainError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::domain_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdDomainError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::domain_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdLengthError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::length_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdLengthError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::length_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdOutOfRange(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::out_of_range(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdOutOfRange(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::out_of_range(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdRuntimeError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::runtime_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdRuntimeError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::runtime_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdRangeError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::range_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdRangeError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::range_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdOverflowError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::overflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdOverflowError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::overflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdUnderflowError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::underflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdUnderflowError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::underflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
-void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
+void ThrowStdBadFunctionCall() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  Throw(std::bad_function_call());
+#else
+  std::abort();
+#endif
+}
 
-void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
+void ThrowStdBadAlloc() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  Throw(std::bad_alloc());
+#else
+  std::abort();
+#endif
+}
 
 }  // namespace base_internal
 ABSL_NAMESPACE_END
diff --git a/absl/base/internal/unaligned_access.h b/absl/base/internal/unaligned_access.h
index dd5250d..080c197 100644
--- a/absl/base/internal/unaligned_access.h
+++ b/absl/base/internal/unaligned_access.h
@@ -45,17 +45,7 @@
 // For all three tools, replacing an unaligned access with a tool-specific
 // callback solves the problem.
 
-// Make sure uint16_t/uint32_t/uint64_t are defined.
-#include <stdint.h>
-
-extern "C" {
-uint16_t __sanitizer_unaligned_load16(const void *p);
-uint32_t __sanitizer_unaligned_load32(const void *p);
-uint64_t __sanitizer_unaligned_load64(const void *p);
-void __sanitizer_unaligned_store16(void *p, uint16_t v);
-void __sanitizer_unaligned_store32(void *p, uint32_t v);
-void __sanitizer_unaligned_store64(void *p, uint64_t v);
-}  // extern "C"
+#include <sanitizer/common_interface_defs.h>
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc
index f1e7bbe..1545288 100644
--- a/absl/base/internal/unscaledcycleclock.cc
+++ b/absl/base/internal/unscaledcycleclock.cc
@@ -123,9 +123,7 @@
 
 #pragma intrinsic(__rdtsc)
 
-int64_t UnscaledCycleClock::Now() {
-  return __rdtsc();
-}
+int64_t UnscaledCycleClock::Now() { return __rdtsc(); }
 
 double UnscaledCycleClock::Frequency() {
   return base_internal::NominalCPUFrequency();
diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h
index 65a3b16..045f17f 100644
--- a/absl/base/log_severity.h
+++ b/absl/base/log_severity.h
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
-#define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#ifndef ABSL_BASE_LOG_SEVERITY_H_
+#define ABSL_BASE_LOG_SEVERITY_H_
 
 #include <array>
 #include <ostream>
@@ -118,4 +118,4 @@
 ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#endif  // ABSL_BASE_LOG_SEVERITY_H_
diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl
deleted file mode 100644
index 6696229..0000000
--- a/absl/compiler_config_setting.bzl
+++ /dev/null
@@ -1,38 +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.
-
-"""Creates config_setting that allows selecting based on 'compiler' value."""
-
-def create_llvm_config(name, visibility):
-    # The "do_not_use_tools_cpp_compiler_present" attribute exists to
-    # distinguish between older versions of Bazel that do not support
-    # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
-    # In the future, the only way to select on the compiler will be through
-    # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can
-    # be removed.
-    if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"):
-        native.config_setting(
-            name = name,
-            flag_values = {
-                "@bazel_tools//tools/cpp:compiler": "llvm",
-            },
-            visibility = visibility,
-        )
-    else:
-        native.config_setting(
-            name = name,
-            values = {"compiler": "llvm"},
-            visibility = visibility,
-        )
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index cca5d44..8e72ad0 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "compressed_tuple",
diff --git a/absl/container/btree_map.h b/absl/container/btree_map.h
index bb450ea..abc09b0 100644
--- a/absl/container/btree_map.h
+++ b/absl/container/btree_map.h
@@ -185,7 +185,7 @@
   // template <typename K> size_type erase(const K& key):
   //
   //   Erases the element with the matching key, if it exists, returning the
-  //   number of elements erased.
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // btree_map::insert()
@@ -325,6 +325,11 @@
   //   does not contain an element with a matching key, this function returns an
   //   empty node handle.
   //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
+  //
   // NOTE: In this context, `node_type` refers to the C++17 concept of a
   // move-only type that owns and provides access to the elements in associative
   // containers (https://en.cppreference.com/w/cpp/container/node_handle).
@@ -652,6 +657,11 @@
   //   does not contain an element with a matching key, this function returns an
   //   empty node handle.
   //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
+  //
   // NOTE: In this context, `node_type` refers to the C++17 concept of a
   // move-only type that owns and provides access to the elements in associative
   // containers (https://en.cppreference.com/w/cpp/container/node_handle).
diff --git a/absl/container/btree_set.h b/absl/container/btree_set.h
index d3e7886..21ef0a0 100644
--- a/absl/container/btree_set.h
+++ b/absl/container/btree_set.h
@@ -183,7 +183,7 @@
   // template <typename K> size_type erase(const K& key):
   //
   //   Erases the element with the matching key, if it exists, returning the
-  //   number of elements erased.
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // btree_set::insert()
diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc
index 0c5f936..9b1b643 100644
--- a/absl/container/btree_test.cc
+++ b/absl/container/btree_test.cc
@@ -55,6 +55,7 @@
 using ::testing::IsEmpty;
 using ::testing::IsNull;
 using ::testing::Pair;
+using ::testing::SizeIs;
 
 template <typename T, typename U>
 void CheckPairEquals(const T &x, const U &y) {
@@ -1182,6 +1183,103 @@
   EXPECT_EQ(1, tmap.size());
 }
 
+}  // namespace
+
+class BtreeNodePeer {
+ public:
+  // Yields the size of a leaf node with a specific number of values.
+  template <typename ValueType>
+  constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
+    return btree_node<
+        set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
+                   /*TargetNodeSize=*/256,  // This parameter isn't used here.
+                   /*Multi=*/false>>::SizeWithNValues(target_values_per_node);
+  }
+
+  // Yields the number of values in a (non-root) leaf node for this btree.
+  template <typename Btree>
+  constexpr static size_t GetNumValuesPerNode() {
+    return btree_node<typename Btree::params_type>::kNodeValues;
+  }
+
+  template <typename Btree>
+  constexpr static size_t GetMaxFieldType() {
+    return std::numeric_limits<
+        typename btree_node<typename Btree::params_type>::field_type>::max();
+  }
+
+  template <typename Btree>
+  constexpr static bool UsesLinearNodeSearch() {
+    return btree_node<typename Btree::params_type>::use_linear_search::value;
+  }
+};
+
+namespace {
+
+class BtreeMapTest : public ::testing::Test {
+ public:
+  struct Key {};
+  struct Cmp {
+    template <typename T>
+    bool operator()(T, T) const {
+      return false;
+    }
+  };
+
+  struct KeyLin {
+    using absl_btree_prefer_linear_node_search = std::true_type;
+  };
+  struct CmpLin : Cmp {
+    using absl_btree_prefer_linear_node_search = std::true_type;
+  };
+
+  struct KeyBin {
+    using absl_btree_prefer_linear_node_search = std::false_type;
+  };
+  struct CmpBin : Cmp {
+    using absl_btree_prefer_linear_node_search = std::false_type;
+  };
+
+  template <typename K, typename C>
+  static bool IsLinear() {
+    return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>();
+  }
+};
+
+TEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) {
+  // Test requesting linear search by directly exporting an alias.
+  EXPECT_FALSE((IsLinear<Key, Cmp>()));
+  EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
+  EXPECT_TRUE((IsLinear<Key, CmpLin>()));
+  EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
+}
+
+TEST_F(BtreeMapTest, LinearChoiceTree) {
+  // Cmp has precedence, and is forcing binary
+  EXPECT_FALSE((IsLinear<Key, CmpBin>()));
+  EXPECT_FALSE((IsLinear<KeyLin, CmpBin>()));
+  EXPECT_FALSE((IsLinear<KeyBin, CmpBin>()));
+  EXPECT_FALSE((IsLinear<int, CmpBin>()));
+  EXPECT_FALSE((IsLinear<std::string, CmpBin>()));
+  // Cmp has precedence, and is forcing linear
+  EXPECT_TRUE((IsLinear<Key, CmpLin>()));
+  EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
+  EXPECT_TRUE((IsLinear<KeyBin, CmpLin>()));
+  EXPECT_TRUE((IsLinear<int, CmpLin>()));
+  EXPECT_TRUE((IsLinear<std::string, CmpLin>()));
+  // Cmp has no preference, Key determines linear vs binary.
+  EXPECT_FALSE((IsLinear<Key, Cmp>()));
+  EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
+  EXPECT_FALSE((IsLinear<KeyBin, Cmp>()));
+  // arithmetic key w/ std::less or std::greater: linear
+  EXPECT_TRUE((IsLinear<int, std::less<int>>()));
+  EXPECT_TRUE((IsLinear<double, std::greater<double>>()));
+  // arithmetic key w/ custom compare: binary
+  EXPECT_FALSE((IsLinear<int, Cmp>()));
+  // non-arithmetic key: binary
+  EXPECT_FALSE((IsLinear<std::string, std::less<std::string>>()));
+}
+
 TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {
   absl::btree_map<std::string, std::unique_ptr<std::string>> m;
 
@@ -1327,34 +1425,6 @@
   EXPECT_EQ(tracker.swaps(), 0);
 }
 
-}  // namespace
-
-class BtreeNodePeer {
- public:
-  // Yields the size of a leaf node with a specific number of values.
-  template <typename ValueType>
-  constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
-    return btree_node<
-        set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
-                   /*TargetNodeSize=*/256,  // This parameter isn't used here.
-                   /*Multi=*/false>>::SizeWithNValues(target_values_per_node);
-  }
-
-  // Yields the number of values in a (non-root) leaf node for this set.
-  template <typename Set>
-  constexpr static size_t GetNumValuesPerNode() {
-    return btree_node<typename Set::params_type>::kNodeValues;
-  }
-
-  template <typename Set>
-  constexpr static size_t GetMaxFieldType() {
-    return std::numeric_limits<
-        typename btree_node<typename Set::params_type>::field_type>::max();
-  }
-};
-
-namespace {
-
 // A btree set with a specific number of values per node.
 template <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>>
 class SizedBtreeSet
@@ -2109,6 +2179,31 @@
                                Pair(4, 1), Pair(4, 4), Pair(5, 5)));
 }
 
+TEST(Btree, MergeIntoSetMovableOnly) {
+  absl::btree_set<MovableOnlyInstance> src;
+  src.insert(MovableOnlyInstance(1));
+  absl::btree_multiset<MovableOnlyInstance> dst1;
+  dst1.insert(MovableOnlyInstance(2));
+  absl::btree_set<MovableOnlyInstance> dst2;
+
+  // Test merge into multiset.
+  dst1.merge(src);
+
+  EXPECT_TRUE(src.empty());
+  // ElementsAre/ElementsAreArray don't work with move-only types.
+  ASSERT_THAT(dst1, SizeIs(2));
+  EXPECT_EQ(*dst1.begin(), MovableOnlyInstance(1));
+  EXPECT_EQ(*std::next(dst1.begin()), MovableOnlyInstance(2));
+
+  // Test merge into set.
+  dst2.merge(dst1);
+
+  EXPECT_TRUE(dst1.empty());
+  ASSERT_THAT(dst2, SizeIs(2));
+  EXPECT_EQ(*dst2.begin(), MovableOnlyInstance(1));
+  EXPECT_EQ(*std::next(dst2.begin()), MovableOnlyInstance(2));
+}
+
 struct KeyCompareToWeakOrdering {
   template <typename T>
   absl::weak_ordering operator()(const T &a, const T &b) const {
@@ -2551,6 +2646,181 @@
 }
 #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;
+
+    map["key1"] = "mapped";
+
+    auto nh = map.extract(map.begin());
+    nh.key().resize(3);
+    map.insert(std::move(nh));
+
+    EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
+  }
+  // Also for multimap.
+  {
+    absl::btree_multimap<std::string, std::string> map;
+
+    map.emplace("key1", "mapped");
+
+    auto nh = map.extract(map.begin());
+    nh.key().resize(3);
+    map.insert(std::move(nh));
+
+    EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
+  }
+}
+#endif
+
+struct MultiKey {
+  int i1;
+  int i2;
+};
+
+bool operator==(const MultiKey a, const MultiKey b) {
+  return a.i1 == b.i1 && a.i2 == b.i2;
+}
+
+// A heterogeneous comparator that has different equivalence classes for
+// different lookup types.
+struct MultiKeyComp {
+  using is_transparent = void;
+  bool operator()(const MultiKey a, const MultiKey b) const {
+    if (a.i1 != b.i1) return a.i1 < b.i1;
+    return a.i2 < b.i2;
+  }
+  bool operator()(const int a, const MultiKey b) const { return a < b.i1; }
+  bool operator()(const MultiKey a, const int b) const { return a.i1 < b; }
+};
+
+TEST(Btree, MultiKeyEqualRange) {
+  absl::btree_set<MultiKey, MultiKeyComp> set;
+
+  for (int i = 0; i < 100; ++i) {
+    for (int j = 0; j < 100; ++j) {
+      set.insert({i, j});
+    }
+  }
+
+  for (int i = 0; i < 100; ++i) {
+    auto equal_range = set.equal_range(i);
+    EXPECT_EQ(equal_range.first->i1, i);
+    EXPECT_EQ(equal_range.first->i2, 0);
+    EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) << i;
+  }
+}
+
+TEST(Btree, MultiKeyErase) {
+  absl::btree_set<MultiKey, MultiKeyComp> set = {
+      {1, 1}, {2, 1}, {2, 2}, {3, 1}};
+  EXPECT_EQ(set.erase(2), 2);
+  EXPECT_THAT(set, ElementsAre(MultiKey{1, 1}, MultiKey{3, 1}));
+}
+
+TEST(Btree, MultiKeyCount) {
+  const absl::btree_set<MultiKey, MultiKeyComp> set = {
+      {1, 1}, {2, 1}, {2, 2}, {3, 1}};
+  EXPECT_EQ(set.count(2), 2);
+}
+
+TEST(Btree, AllocConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  Set set(alloc);
+
+  set.insert({1, 2, 3});
+
+  EXPECT_THAT(set, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocInitializerListConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  Set set({1, 2, 3}, alloc);
+
+  EXPECT_THAT(set, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocRangeConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  std::vector<int> v = {1, 2, 3};
+  Set set(v.begin(), v.end(), alloc);
+
+  EXPECT_THAT(set, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocCopyConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used1 = 0;
+  Alloc alloc1(&bytes_used1);
+  Set set1(alloc1);
+
+  set1.insert({1, 2, 3});
+
+  int64_t bytes_used2 = 0;
+  Alloc alloc2(&bytes_used2);
+  Set set2(set1, alloc2);
+
+  EXPECT_THAT(set1, ElementsAre(1, 2, 3));
+  EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used1, set1.size() * sizeof(int));
+  EXPECT_EQ(bytes_used1, bytes_used2);
+}
+
+TEST(Btree, AllocMoveConstructor_SameAlloc) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  Set set1(alloc);
+
+  set1.insert({1, 2, 3});
+
+  const int64_t original_bytes_used = bytes_used;
+  EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
+
+  Set set2(std::move(set1), alloc);
+
+  EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+  EXPECT_EQ(bytes_used, original_bytes_used);
+}
+
+TEST(Btree, AllocMoveConstructor_DifferentAlloc) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used1 = 0;
+  Alloc alloc1(&bytes_used1);
+  Set set1(alloc1);
+
+  set1.insert({1, 2, 3});
+
+  const int64_t original_bytes_used = bytes_used1;
+  EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
+
+  int64_t bytes_used2 = 0;
+  Alloc alloc2(&bytes_used2);
+  Set set2(std::move(set1), alloc2);
+
+  EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+  // We didn't free these bytes allocated by `set1` yet.
+  EXPECT_EQ(bytes_used1, original_bytes_used);
+  EXPECT_EQ(bytes_used2, original_bytes_used);
+}
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index c8fe8d9..fcb3e54 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -232,8 +232,8 @@
 
   // FixedArray::at
   //
-  // Bounds-checked access.  Returns a reference to the ith element of the
-  // fiexed array, or throws std::out_of_range
+  // Bounds-checked access.  Returns a reference to the ith element of the fixed
+  // array, or throws std::out_of_range
   reference at(size_type i) {
     if (ABSL_PREDICT_FALSE(i >= size())) {
       base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index fcb70d8..74def0d 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -234,7 +234,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // flat_hash_map::insert()
@@ -383,6 +384,11 @@
   //   key value and returns a node handle owning that extracted data. If the
   //   `flat_hash_map` does not contain an element with a matching key, this
   //   function returns an empty node handle.
+  //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
   using Base::extract;
 
   // flat_hash_map::merge()
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc
index 2823c32..89ec60c 100644
--- a/absl/container/flat_hash_map_test.cc
+++ b/absl/container/flat_hash_map_test.cc
@@ -267,6 +267,21 @@
   }
 }
 
+// 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;
+
+  map["key1"] = "mapped";
+
+  auto nh = map.extract(map.begin());
+  nh.key().resize(3);
+  map.insert(std::move(nh));
+
+  EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
+}
+#endif
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index 94be6e3..81e145a 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -227,7 +227,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // flat_hash_set::insert()
diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h
index 293e577..f2fc31d 100644
--- a/absl/container/internal/btree.h
+++ b/absl/container/internal/btree.h
@@ -137,15 +137,14 @@
 };
 
 // A helper class to convert a boolean comparison into a three-way "compare-to"
-// comparison that returns a negative value to indicate less-than, zero to
-// indicate equality and a positive value to indicate greater-than. This helper
+// comparison that returns an `absl::weak_ordering`. This helper
 // class is specialized for less<std::string>, greater<std::string>,
 // less<string_view>, greater<string_view>, less<absl::Cord>, and
 // greater<absl::Cord>.
 //
 // key_compare_to_adapter is provided so that btree users
 // automatically get the more efficient compare-to code when using common
-// google string types with common comparison functors.
+// Abseil string types with common comparison functors.
 // These string-like specializations also turn on heterogeneous lookup by
 // default.
 template <typename Compare>
@@ -183,12 +182,47 @@
   using type = StringBtreeDefaultGreater;
 };
 
+// Detects an 'absl_btree_prefer_linear_node_search' member. This is
+// a protocol used as an opt-in or opt-out of linear search.
+//
+//  For example, this would be useful for key types that wrap an integer
+//  and define their own cheap operator<(). For example:
+//
+//   class K {
+//    public:
+//     using absl_btree_prefer_linear_node_search = std::true_type;
+//     ...
+//    private:
+//     friend bool operator<(K a, K b) { return a.k_ < b.k_; }
+//     int k_;
+//   };
+//
+//   btree_map<K, V> m;  // Uses linear search
+//
+// If T has the preference tag, then it has a preference.
+// Btree will use the tag's truth value.
+template <typename T, typename = void>
+struct has_linear_node_search_preference : std::false_type {};
+template <typename T, typename = void>
+struct prefers_linear_node_search : std::false_type {};
+template <typename T>
+struct has_linear_node_search_preference<
+    T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
+    : std::true_type {};
+template <typename T>
+struct prefers_linear_node_search<
+    T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
+    : T::absl_btree_prefer_linear_node_search {};
+
 template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
           bool Multi, typename SlotPolicy>
 struct common_params {
   // If Compare is a common comparator for a string-like type, then we adapt it
   // to use heterogeneous lookup and to be a key-compare-to comparator.
   using key_compare = typename key_compare_to_adapter<Compare>::type;
+  // True when key_compare has been adapted to StringBtreeDefault{Less,Greater}.
+  using is_key_compare_adapted =
+      absl::negation<std::is_same<key_compare, Compare>>;
   // A type which indicates if we have a key-compare-to functor or a plain old
   // key-compare functor.
   using is_key_compare_to = btree_is_key_compare_to<key_compare, Key>;
@@ -292,6 +326,11 @@
   }
   static const Key &key(const slot_type *s) { return slot_policy::key(s); }
   static const Key &key(slot_type *s) { return slot_policy::key(s); }
+  // For use in node handle.
+  static auto mutable_key(slot_type *s)
+      -> decltype(slot_policy::mutable_key(s)) {
+    return slot_policy::mutable_key(s);
+  }
   static mapped_type &value(value_type *value) { return value->second; }
 };
 
@@ -384,6 +423,10 @@
 // useful information.
 template <typename V>
 struct SearchResult<V, false> {
+  SearchResult() {}
+  explicit SearchResult(V value) : value(value) {}
+  SearchResult(V value, MatchKind /*match*/) : value(value) {}
+
   V value;
 
   static constexpr bool HasMatch() { return false; }
@@ -414,15 +457,22 @@
   using difference_type = typename Params::difference_type;
 
   // Btree decides whether to use linear node search as follows:
+  //   - If the comparator expresses a preference, use that.
+  //   - If the key expresses a preference, use that.
   //   - If the key is arithmetic and the comparator is std::less or
   //     std::greater, choose linear.
   //   - Otherwise, choose binary.
   // TODO(ezb): Might make sense to add condition(s) based on node-size.
   using use_linear_search = std::integral_constant<
       bool,
-                std::is_arithmetic<key_type>::value &&
-                    (std::is_same<std::less<key_type>, key_compare>::value ||
-                     std::is_same<std::greater<key_type>, key_compare>::value)>;
+      has_linear_node_search_preference<key_compare>::value
+          ? prefers_linear_node_search<key_compare>::value
+          : has_linear_node_search_preference<key_type>::value
+                ? prefers_linear_node_search<key_type>::value
+                : std::is_arithmetic<key_type>::value &&
+                      (std::is_same<std::less<key_type>, key_compare>::value ||
+                       std::is_same<std::greater<key_type>,
+                                    key_compare>::value)>;
 
   // This class is organized by gtl::Layout as if it had the following
   // structure:
@@ -665,7 +715,7 @@
       }
       ++s;
     }
-    return {s};
+    return SearchResult<int, false>{s};
   }
 
   // Returns the position of the first value whose key is not less than k using
@@ -700,7 +750,7 @@
         e = mid;
       }
     }
-    return {s};
+    return SearchResult<int, false>{s};
   }
 
   // Returns the position of the first value whose key is not less than k using
@@ -793,12 +843,6 @@
   // Deletes a node and all of its children.
   static void clear_and_delete(btree_node *node, allocator_type *alloc);
 
- public:
-  // Exposed only for tests.
-  static bool testonly_uses_linear_node_search() {
-    return use_linear_search::value;
-  }
-
  private:
   template <typename... Args>
   void value_init(const field_type i, allocator_type *alloc, Args &&... args) {
@@ -1009,6 +1053,9 @@
   using node_type = btree_node<Params>;
   using is_key_compare_to = typename Params::is_key_compare_to;
   using init_type = typename Params::init_type;
+  using field_type = typename node_type::field_type;
+  using is_multi_container = typename Params::is_multi_container;
+  using is_key_compare_adapted = typename Params::is_key_compare_adapted;
 
   // We use a static empty node for the root/leftmost/rightmost of empty btrees
   // in order to avoid branching in begin()/end().
@@ -1043,7 +1090,7 @@
 #endif
   }
 
-  enum {
+  enum : uint32_t {
     kNodeValues = node_type::kNodeValues,
     kMinNodeValues = kNodeValues / 2,
   };
@@ -1095,21 +1142,35 @@
   // before this method is called. This method is used in copy construction,
   // copy assignment, and move assignment.
   template <typename Btree>
-  void copy_or_move_values_in_order(Btree *other);
+  void copy_or_move_values_in_order(Btree &other);
 
   // Validates that various assumptions/requirements are true at compile time.
   constexpr static bool static_assert_validation();
 
  public:
-  btree(const key_compare &comp, const allocator_type &alloc);
+  btree(const key_compare &comp, const allocator_type &alloc)
+      : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
 
-  btree(const btree &other);
+  btree(const btree &other) : btree(other, other.allocator()) {}
+  btree(const btree &other, const allocator_type &alloc)
+      : btree(other.key_comp(), alloc) {
+    copy_or_move_values_in_order(other);
+  }
   btree(btree &&other) noexcept
       : root_(std::move(other.root_)),
         rightmost_(absl::exchange(other.rightmost_, EmptyNode())),
         size_(absl::exchange(other.size_, 0)) {
     other.mutable_root() = EmptyNode();
   }
+  btree(btree &&other, const allocator_type &alloc)
+      : btree(other.key_comp(), alloc) {
+    if (alloc == other.allocator()) {
+      swap(other);
+    } else {
+      // Move values from `other` one at a time when allocators are different.
+      copy_or_move_values_in_order(other);
+    }
+  }
 
   ~btree() {
     // Put static_asserts in destructor to avoid triggering them before the type
@@ -1140,11 +1201,11 @@
   // Finds the first element whose key is not less than key.
   template <typename K>
   iterator lower_bound(const K &key) {
-    return internal_end(internal_lower_bound(key));
+    return internal_end(internal_lower_bound(key).value);
   }
   template <typename K>
   const_iterator lower_bound(const K &key) const {
-    return internal_end(internal_lower_bound(key));
+    return internal_end(internal_lower_bound(key).value);
   }
 
   // Finds the first element whose key is greater than key.
@@ -1158,15 +1219,13 @@
   }
 
   // Finds the range of values which compare equal to key. The first member of
-  // the returned pair is equal to lower_bound(key). The second member pair of
-  // the pair is equal to upper_bound(key).
+  // the returned pair is equal to lower_bound(key). The second member of the
+  // pair is equal to upper_bound(key).
   template <typename K>
-  std::pair<iterator, iterator> equal_range(const K &key) {
-    return {lower_bound(key), upper_bound(key)};
-  }
+  std::pair<iterator, iterator> equal_range(const K &key);
   template <typename K>
   std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
-    return {lower_bound(key), upper_bound(key)};
+    return const_cast<btree *>(this)->equal_range(key);
   }
 
   // Inserts a value into the btree only if it does not already exist. The
@@ -1231,16 +1290,6 @@
   // to the element after the last erased element.
   std::pair<size_type, iterator> erase_range(iterator begin, iterator end);
 
-  // Erases the specified key from the btree. Returns 1 if an element was
-  // erased and 0 otherwise.
-  template <typename K>
-  size_type erase_unique(const K &key);
-
-  // Erases all of the entries matching the specified key from the
-  // btree. Returns the number of elements erased.
-  template <typename K>
-  size_type erase_multi(const K &key);
-
   // Finds the iterator corresponding to a key or returns end() if the key is
   // not present.
   template <typename K>
@@ -1252,23 +1301,6 @@
     return internal_end(internal_find(key));
   }
 
-  // Returns a count of the number of times the key appears in the btree.
-  template <typename K>
-  size_type count_unique(const K &key) const {
-    const iterator begin = internal_find(key);
-    if (begin.node == nullptr) {
-      // The key doesn't exist in the tree.
-      return 0;
-    }
-    return 1;
-  }
-  // Returns a count of the number of times the key appears in the btree.
-  template <typename K>
-  size_type count_multi(const K &key) const {
-    const auto range = equal_range(key);
-    return std::distance(range.first, range.second);
-  }
-
   // Clear the btree, deleting all of the values it contains.
   void clear();
 
@@ -1445,28 +1477,19 @@
   static IterType internal_last(IterType iter);
 
   // Returns an iterator pointing to the leaf position at which key would
-  // reside in the tree. We provide 2 versions of internal_locate. The first
-  // version uses a less-than comparator and is incapable of distinguishing when
-  // there is an exact match. The second version is for the key-compare-to
-  // specialization and distinguishes exact matches. The key-compare-to
-  // specialization allows the caller to avoid a subsequent comparison to
-  // determine if an exact match was made, which is important for keys with
-  // expensive comparison, such as strings.
+  // reside in the tree, unless there is an exact match - in which case, the
+  // result may not be on a leaf. When there's a three-way comparator, we can
+  // return whether there was an exact match. This allows the caller to avoid a
+  // subsequent comparison to determine if an exact match was made, which is
+  // important for keys with expensive comparison, such as strings.
   template <typename K>
   SearchResult<iterator, is_key_compare_to::value> internal_locate(
       const K &key) const;
 
-  template <typename K>
-  SearchResult<iterator, false> internal_locate_impl(
-      const K &key, std::false_type /* IsCompareTo */) const;
-
-  template <typename K>
-  SearchResult<iterator, true> internal_locate_impl(
-      const K &key, std::true_type /* IsCompareTo */) const;
-
   // Internal routine which implements lower_bound().
   template <typename K>
-  iterator internal_lower_bound(const K &key) const;
+  SearchResult<iterator, is_key_compare_to::value> internal_lower_bound(
+      const K &key) const;
 
   // Internal routine which implements upper_bound().
   template <typename K>
@@ -1495,13 +1518,6 @@
     return res;
   }
 
- public:
-  // Exposed only for tests.
-  static bool testonly_uses_linear_node_search() {
-    return node_type::testonly_uses_linear_node_search();
-  }
-
- private:
   // We use compressed tuple in order to save space because key_compare and
   // allocator_type are usually empty.
   absl::container_internal::CompressedTuple<key_compare, allocator_type,
@@ -1824,7 +1840,7 @@
 // btree methods
 template <typename P>
 template <typename Btree>
-void btree<P>::copy_or_move_values_in_order(Btree *other) {
+void btree<P>::copy_or_move_values_in_order(Btree &other) {
   static_assert(std::is_same<btree, Btree>::value ||
                     std::is_same<const btree, Btree>::value,
                 "Btree type must be same or const.");
@@ -1832,11 +1848,11 @@
 
   // We can avoid key comparisons because we know the order of the
   // values is the same order we'll store them in.
-  auto iter = other->begin();
-  if (iter == other->end()) return;
+  auto iter = other.begin();
+  if (iter == other.end()) return;
   insert_multi(maybe_move_from_iterator(iter));
   ++iter;
-  for (; iter != other->end(); ++iter) {
+  for (; iter != other.end(); ++iter) {
     // If the btree is not empty, we can just insert the new value at the end
     // of the tree.
     internal_emplace(end(), maybe_move_from_iterator(iter));
@@ -1875,13 +1891,40 @@
 }
 
 template <typename P>
-btree<P>::btree(const key_compare &comp, const allocator_type &alloc)
-    : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
+template <typename K>
+auto btree<P>::equal_range(const K &key) -> std::pair<iterator, iterator> {
+  const SearchResult<iterator, is_key_compare_to::value> res =
+      internal_lower_bound(key);
+  const iterator lower = internal_end(res.value);
+  if (res.HasMatch() ? !res.IsEq()
+                     : lower == end() || compare_keys(key, lower.key())) {
+    return {lower, lower};
+  }
 
-template <typename P>
-btree<P>::btree(const btree &other)
-    : btree(other.key_comp(), other.allocator()) {
-  copy_or_move_values_in_order(&other);
+  const iterator next = std::next(lower);
+  // When the comparator is heterogeneous, we can't assume that comparison with
+  // non-`key_type` will be equivalent to `key_type` comparisons so there
+  // could be multiple equivalent keys even in a unique-container. But for
+  // heterogeneous comparisons from the default string adapted comparators, we
+  // don't need to worry about this.
+  if (!is_multi_container::value &&
+      (std::is_same<K, key_type>::value || is_key_compare_adapted::value)) {
+    // The next iterator after lower must point to a key greater than `key`.
+    // Note: if this assert fails, then it may indicate that the comparator does
+    // not meet the equivalence requirements for Compare
+    // (see https://en.cppreference.com/w/cpp/named_req/Compare).
+    assert(next == end() || compare_keys(key, next.key()));
+    return {lower, next};
+  }
+  // Try once more to avoid the call to upper_bound() if there's only one
+  // equivalent key. This should prevent all calls to upper_bound() in cases of
+  // unique-containers with heterogeneous comparators in which all comparison
+  // operators have the same equivalence classes.
+  if (next == end() || compare_keys(key, next.key())) return {lower, next};
+
+  // In this case, we need to call upper_bound() to avoid worst case O(N)
+  // behavior if we were to iterate over equal keys.
+  return {lower, upper_bound(key)};
 }
 
 template <typename P>
@@ -1892,8 +1935,8 @@
     mutable_root() = rightmost_ = new_leaf_root_node(1);
   }
 
-  auto res = internal_locate(key);
-  iterator &iter = res.value;
+  SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
+  iterator iter = res.value;
 
   if (res.HasMatch()) {
     if (res.IsEq()) {
@@ -2007,7 +2050,7 @@
       *mutable_allocator() = other.allocator();
     }
 
-    copy_or_move_values_in_order(&other);
+    copy_or_move_values_in_order(other);
   }
   return *this;
 }
@@ -2037,7 +2080,7 @@
         // comparator while moving the values so we can't swap the key
         // comparators.
         *mutable_key_comp() = other.key_comp();
-        copy_or_move_values_in_order(&other);
+        copy_or_move_values_in_order(other);
       }
     }
   }
@@ -2161,31 +2204,6 @@
 }
 
 template <typename P>
-template <typename K>
-auto btree<P>::erase_unique(const K &key) -> size_type {
-  const iterator iter = internal_find(key);
-  if (iter.node == nullptr) {
-    // The key doesn't exist in the tree, return nothing done.
-    return 0;
-  }
-  erase(iter);
-  return 1;
-}
-
-template <typename P>
-template <typename K>
-auto btree<P>::erase_multi(const K &key) -> size_type {
-  const iterator begin = internal_lower_bound(key);
-  if (begin.node == nullptr) {
-    // The key doesn't exist in the tree, return nothing done.
-    return 0;
-  }
-  // Delete all of the keys between begin and upper_bound(key).
-  const iterator end = internal_end(internal_upper_bound(key));
-  return erase_range(begin, end).first;
-}
-
-template <typename P>
 void btree<P>::clear() {
   if (!empty()) {
     node_type::clear_and_delete(root(), mutable_allocator());
@@ -2243,11 +2261,11 @@
         // inserting at the end of the right node then we bias rebalancing to
         // fill up the left node.
         int to_move = (kNodeValues - left->count()) /
-                      (1 + (insert_position < kNodeValues));
+                      (1 + (insert_position < static_cast<int>(kNodeValues)));
         to_move = (std::max)(1, to_move);
 
         if (insert_position - to_move >= node->start() ||
-            left->count() + to_move < kNodeValues) {
+            left->count() + to_move < static_cast<int>(kNodeValues)) {
           left->rebalance_right_to_left(to_move, node, mutable_allocator());
 
           assert(node->max_count() - node->count() == to_move);
@@ -2271,12 +2289,12 @@
         // We bias rebalancing based on the position being inserted. If we're
         // inserting at the beginning of the left node then we bias rebalancing
         // to fill up the right node.
-        int to_move = (kNodeValues - right->count()) /
+        int to_move = (static_cast<int>(kNodeValues) - right->count()) /
                       (1 + (insert_position > node->start()));
         to_move = (std::max)(1, to_move);
 
         if (insert_position <= node->finish() - to_move ||
-            right->count() + to_move < kNodeValues) {
+            right->count() + to_move < static_cast<int>(kNodeValues)) {
           node->rebalance_left_to_right(to_move, right, mutable_allocator());
 
           if (insert_position > node->finish()) {
@@ -2339,7 +2357,7 @@
     // Try merging with our left sibling.
     node_type *left = parent->child(iter->node->position() - 1);
     assert(left->max_count() == kNodeValues);
-    if (1 + left->count() + iter->node->count() <= kNodeValues) {
+    if (1U + left->count() + iter->node->count() <= kNodeValues) {
       iter->position += 1 + left->count();
       merge_nodes(left, iter->node);
       iter->node = left;
@@ -2350,7 +2368,7 @@
     // Try merging with our right sibling.
     node_type *right = parent->child(iter->node->position() + 1);
     assert(right->max_count() == kNodeValues);
-    if (1 + iter->node->count() + right->count() <= kNodeValues) {
+    if (1U + iter->node->count() + right->count() <= kNodeValues) {
       merge_nodes(iter->node, right);
       return true;
     }
@@ -2427,7 +2445,7 @@
     --iter;
     ++iter.position;
   }
-  const int max_count = iter.node->max_count();
+  const field_type max_count = iter.node->max_count();
   allocator_type *alloc = mutable_allocator();
   if (iter.node->count() == max_count) {
     // Make room in the leaf for the new item.
@@ -2459,61 +2477,48 @@
 template <typename K>
 inline auto btree<P>::internal_locate(const K &key) const
     -> SearchResult<iterator, is_key_compare_to::value> {
-  return internal_locate_impl(key, is_key_compare_to());
-}
-
-template <typename P>
-template <typename K>
-inline auto btree<P>::internal_locate_impl(
-    const K &key, std::false_type /* IsCompareTo */) const
-    -> SearchResult<iterator, false> {
   iterator iter(const_cast<node_type *>(root()));
   for (;;) {
-    iter.position = iter.node->lower_bound(key, key_comp()).value;
-    // NOTE: we don't need to walk all the way down the tree if the keys are
-    // equal, but determining equality would require doing an extra comparison
-    // on each node on the way down, and we will need to go all the way to the
-    // leaf node in the expected case.
-    if (iter.node->leaf()) {
-      break;
-    }
-    iter.node = iter.node->child(iter.position);
-  }
-  return {iter};
-}
-
-template <typename P>
-template <typename K>
-inline auto btree<P>::internal_locate_impl(
-    const K &key, std::true_type /* IsCompareTo */) const
-    -> SearchResult<iterator, true> {
-  iterator iter(const_cast<node_type *>(root()));
-  for (;;) {
-    SearchResult<int, true> res = iter.node->lower_bound(key, key_comp());
+    SearchResult<int, is_key_compare_to::value> res =
+        iter.node->lower_bound(key, key_comp());
     iter.position = res.value;
-    if (res.match == MatchKind::kEq) {
+    if (res.IsEq()) {
       return {iter, MatchKind::kEq};
     }
+    // Note: in the non-key-compare-to case, we don't need to walk all the way
+    // down the tree if the keys are equal, but determining equality would
+    // require doing an extra comparison on each node on the way down, and we
+    // will need to go all the way to the leaf node in the expected case.
     if (iter.node->leaf()) {
       break;
     }
     iter.node = iter.node->child(iter.position);
   }
+  // Note: in the non-key-compare-to case, the key may actually be equivalent
+  // here (and the MatchKind::kNe is ignored).
   return {iter, MatchKind::kNe};
 }
 
 template <typename P>
 template <typename K>
-auto btree<P>::internal_lower_bound(const K &key) const -> iterator {
+auto btree<P>::internal_lower_bound(const K &key) const
+    -> SearchResult<iterator, is_key_compare_to::value> {
   iterator iter(const_cast<node_type *>(root()));
+  SearchResult<int, is_key_compare_to::value> res;
+  bool seen_eq = false;
   for (;;) {
-    iter.position = iter.node->lower_bound(key, key_comp()).value;
+    res = iter.node->lower_bound(key, key_comp());
+    iter.position = res.value;
+    // TODO(ezb): we should be able to terminate early on IsEq() if there can't
+    // be multiple equivalent keys in container for this lookup type.
     if (iter.node->leaf()) {
       break;
     }
+    seen_eq = seen_eq || res.IsEq();
     iter.node = iter.node->child(iter.position);
   }
-  return internal_last(iter);
+  if (res.IsEq()) return {iter, MatchKind::kEq};
+  return {internal_last(iter), seen_eq ? MatchKind::kEq : MatchKind::kNe};
 }
 
 template <typename P>
@@ -2533,7 +2538,7 @@
 template <typename P>
 template <typename K>
 auto btree<P>::internal_find(const K &key) const -> iterator {
-  auto res = internal_locate(key);
+  SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
   if (res.HasMatch()) {
     if (res.IsEq()) {
       return res.value;
diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h
index 3b2e8a9..887eda4 100644
--- a/absl/container/internal/btree_container.h
+++ b/absl/container/internal/btree_container.h
@@ -23,6 +23,7 @@
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/container/internal/btree.h"  // IWYU pragma: export
 #include "absl/container/internal/common.h"
+#include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
 
 namespace absl {
@@ -68,8 +69,21 @@
   explicit btree_container(const key_compare &comp,
                            const allocator_type &alloc = allocator_type())
       : tree_(comp, alloc) {}
-  btree_container(const btree_container &other) = default;
-  btree_container(btree_container &&other) noexcept = default;
+  explicit btree_container(const allocator_type &alloc)
+      : tree_(key_compare(), alloc) {}
+
+  btree_container(const btree_container &other)
+      : btree_container(other, absl::allocator_traits<allocator_type>::
+                                   select_on_container_copy_construction(
+                                       other.get_allocator())) {}
+  btree_container(const btree_container &other, const allocator_type &alloc)
+      : tree_(other.tree_, alloc) {}
+
+  btree_container(btree_container &&other) noexcept(
+      std::is_nothrow_move_constructible<Tree>::value) = default;
+  btree_container(btree_container &&other, const allocator_type &alloc)
+      : tree_(std::move(other.tree_), alloc) {}
+
   btree_container &operator=(const btree_container &other) = default;
   btree_container &operator=(btree_container &&other) noexcept(
       std::is_nothrow_move_assignable<Tree>::value) = default;
@@ -90,6 +104,11 @@
 
   // Lookup routines.
   template <typename K = key_type>
+  size_type count(const key_arg<K> &key) const {
+    auto equal_range = this->equal_range(key);
+    return std::distance(equal_range.first, equal_range.second);
+  }
+  template <typename K = key_type>
   iterator find(const key_arg<K> &key) {
     return tree_.find(key);
   }
@@ -138,6 +157,11 @@
   iterator erase(const_iterator first, const_iterator last) {
     return tree_.erase_range(iterator(first), iterator(last)).second;
   }
+  template <typename K = key_type>
+  size_type erase(const key_arg<K> &key) {
+    auto equal_range = this->equal_range(key);
+    return tree_.erase_range(equal_range.first, equal_range.second).first;
+  }
 
   // Extract routines.
   node_type extract(iterator position) {
@@ -151,7 +175,6 @@
     return extract(iterator(position));
   }
 
- public:
   // Utility routines.
   void clear() { tree_.clear(); }
   void swap(btree_container &other) { tree_.swap(other.tree_); }
@@ -235,7 +258,7 @@
   using super_type::super_type;
   btree_set_container() {}
 
-  // Range constructor.
+  // Range constructors.
   template <class InputIterator>
   btree_set_container(InputIterator b, InputIterator e,
                       const key_compare &comp = key_compare(),
@@ -243,18 +266,19 @@
       : super_type(comp, alloc) {
     insert(b, e);
   }
+  template <class InputIterator>
+  btree_set_container(InputIterator b, InputIterator e,
+                      const allocator_type &alloc)
+      : btree_set_container(b, e, key_compare(), alloc) {}
 
-  // Initializer list constructor.
+  // Initializer list constructors.
   btree_set_container(std::initializer_list<init_type> init,
                       const key_compare &comp = key_compare(),
                       const allocator_type &alloc = allocator_type())
       : btree_set_container(init.begin(), init.end(), comp, alloc) {}
-
-  // Lookup routines.
-  template <typename K = key_type>
-  size_type count(const key_arg<K> &key) const {
-    return this->tree_.count_unique(key);
-  }
+  btree_set_container(std::initializer_list<init_type> init,
+                      const allocator_type &alloc)
+      : btree_set_container(init.begin(), init.end(), alloc) {}
 
   // Insertion routines.
   std::pair<iterator, bool> insert(const value_type &v) {
@@ -313,14 +337,10 @@
     return res.first;
   }
 
-  // Deletion routines.
-  template <typename K = key_type>
-  size_type erase(const key_arg<K> &key) {
-    return this->tree_.erase_unique(key);
-  }
-  using super_type::erase;
-
   // Node extraction routines.
+  // TODO(ezb): when the comparator is heterogeneous and has different
+  // equivalence classes for different lookup types, we should extract the first
+  // equivalent value if there are multiple.
   template <typename K = key_type>
   node_type extract(const key_arg<K> &key) {
     auto it = this->find(key);
@@ -342,7 +362,7 @@
           int> = 0>
   void merge(btree_container<T> &src) {  // NOLINT
     for (auto src_it = src.begin(); src_it != src.end();) {
-      if (insert(std::move(*src_it)).second) {
+      if (insert(std::move(params_type::element(src_it.slot()))).second) {
         src_it = src.erase(src_it);
       } else {
         ++src_it;
@@ -369,6 +389,7 @@
 class btree_map_container : public btree_set_container<Tree> {
   using super_type = btree_set_container<Tree>;
   using params_type = typename Tree::params_type;
+  friend class BtreeNodePeer;
 
  private:
   template <class K>
@@ -533,7 +554,7 @@
   using super_type::super_type;
   btree_multiset_container() {}
 
-  // Range constructor.
+  // Range constructors.
   template <class InputIterator>
   btree_multiset_container(InputIterator b, InputIterator e,
                            const key_compare &comp = key_compare(),
@@ -541,18 +562,19 @@
       : super_type(comp, alloc) {
     insert(b, e);
   }
+  template <class InputIterator>
+  btree_multiset_container(InputIterator b, InputIterator e,
+                           const allocator_type &alloc)
+      : btree_multiset_container(b, e, key_compare(), alloc) {}
 
-  // Initializer list constructor.
+  // Initializer list constructors.
   btree_multiset_container(std::initializer_list<init_type> init,
                            const key_compare &comp = key_compare(),
                            const allocator_type &alloc = allocator_type())
       : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
-
-  // Lookup routines.
-  template <typename K = key_type>
-  size_type count(const key_arg<K> &key) const {
-    return this->tree_.count_multi(key);
-  }
+  btree_multiset_container(std::initializer_list<init_type> init,
+                           const allocator_type &alloc)
+      : btree_multiset_container(init.begin(), init.end(), alloc) {}
 
   // Insertion routines.
   iterator insert(const value_type &v) { return this->tree_.insert_multi(v); }
@@ -598,14 +620,9 @@
     return res;
   }
 
-  // Deletion routines.
-  template <typename K = key_type>
-  size_type erase(const key_arg<K> &key) {
-    return this->tree_.erase_multi(key);
-  }
-  using super_type::erase;
-
   // Node extraction routines.
+  // TODO(ezb): we are supposed to extract the first equivalent key if there are
+  // multiple, but this isn't guaranteed to extract the first one.
   template <typename K = key_type>
   node_type extract(const key_arg<K> &key) {
     auto it = this->find(key);
@@ -625,8 +642,9 @@
                            typename T::params_type::is_map_container>>::value,
           int> = 0>
   void merge(btree_container<T> &src) {  // NOLINT
-    insert(std::make_move_iterator(src.begin()),
-           std::make_move_iterator(src.end()));
+    for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) {
+      insert(std::move(params_type::element(src_it.slot())));
+    }
     src.clear();
   }
 
diff --git a/absl/container/internal/common.h b/absl/container/internal/common.h
index 8990f29..030e9d4 100644
--- a/absl/container/internal/common.h
+++ b/absl/container/internal/common.h
@@ -146,8 +146,11 @@
 
   constexpr node_handle() {}
 
-  auto key() const -> decltype(PolicyTraits::key(std::declval<slot_type*>())) {
-    return PolicyTraits::key(this->slot());
+  // When C++17 is available, we can use std::launder to provide mutable
+  // access to the key. Otherwise, we provide const access.
+  auto key() const
+      -> decltype(PolicyTraits::mutable_key(std::declval<slot_type*>())) {
+    return PolicyTraits::mutable_key(this->slot());
   }
 
   mapped_type& mapped() const {
diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h
index 02bfd03..5ebe164 100644
--- a/absl/container/internal/compressed_tuple.h
+++ b/absl/container/internal/compressed_tuple.h
@@ -257,7 +257,7 @@
 
   template <int I>
   ElemT<I>& get() & {
-    return internal_compressed_tuple::Storage<ElemT<I>, I>::get();
+    return StorageT<I>::get();
   }
 
   template <int I>
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h
index c7777a9..e67529e 100644
--- a/absl/container/internal/container_memory.h
+++ b/absl/container/internal/container_memory.h
@@ -18,6 +18,7 @@
 #include <cassert>
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <tuple>
 #include <type_traits>
 #include <utility>
@@ -56,8 +57,11 @@
   using M = AlignedType<Alignment>;
   using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
   using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
-  A mem_alloc(*alloc);
-  void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
+  // On macOS, "mem_alloc" is a #define with one argument defined in
+  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+  // with the "foo(bar)" syntax.
+  A my_mem_alloc(*alloc);
+  void* p = AT::allocate(my_mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
   assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
          "allocator does not respect alignment");
   return p;
@@ -72,8 +76,11 @@
   using M = AlignedType<Alignment>;
   using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
   using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
-  A mem_alloc(*alloc);
-  AT::deallocate(mem_alloc, static_cast<M*>(p),
+  // On macOS, "mem_alloc" is a #define with one argument defined in
+  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+  // with the "foo(bar)" syntax.
+  A my_mem_alloc(*alloc);
+  AT::deallocate(my_mem_alloc, static_cast<M*>(p),
                  (n + sizeof(M) - 1) / sizeof(M));
 }
 
@@ -352,6 +359,20 @@
     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.
+    return kMutableKeys::value ? slot->key
+                               : *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;
   }
diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc
index 75c4db6..59cc5aa 100644
--- a/absl/container/internal/hash_generator_testing.cc
+++ b/absl/container/internal/hash_generator_testing.cc
@@ -41,8 +41,10 @@
 }  // namespace
 
 std::mt19937_64* GetSharedRng() {
-  RandomDeviceSeedSeq seed_seq;
-  static auto* rng = new std::mt19937_64(seed_seq);
+  static auto* rng = [] {
+    RandomDeviceSeedSeq seed_seq;
+    return new std::mt19937_64(seed_seq);
+  }();
   return rng;
 }
 
diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h
index 3e1209c..46c97b1 100644
--- a/absl/container/internal/hash_policy_traits.h
+++ b/absl/container/internal/hash_policy_traits.h
@@ -17,6 +17,7 @@
 
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <type_traits>
 #include <utility>
 
@@ -29,15 +30,34 @@
 // Defines how slots are initialized/destroyed/moved.
 template <class Policy, class = void>
 struct hash_policy_traits {
+  // The type of the keys stored in the hashtable.
+  using key_type = typename Policy::key_type;
+
  private:
   struct ReturnKey {
-    // We return `Key` here.
+    // 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) {
+      return std::forward<Key>(k);
+    }
+
     // When Key=T&, we forward the lvalue reference.
     // When Key=T, we return by value to avoid a dangling reference.
     // eg, for string_hash_map.
     template <class Key, class... Args>
-    Key operator()(Key&& k, const Args&...) const {
-      return std::forward<Key>(k);
+    auto operator()(Key&& k, const Args&...) const
+        -> decltype(Impl(std::forward<Key>(k), 0)) {
+      return Impl(std::forward<Key>(k), 0);
     }
   };
 
@@ -52,9 +72,6 @@
   // The actual object stored in the hash table.
   using slot_type = typename Policy::slot_type;
 
-  // The type of the keys stored in the hashtable.
-  using key_type = typename Policy::key_type;
-
   // The argument type for insertions into the hashtable. This is different
   // from value_type for increased performance. See initializer_list constructor
   // and insert() member functions for more details.
@@ -156,7 +173,7 @@
   // Returns the "key" portion of the slot.
   // Used for node handle manipulation.
   template <class P = Policy>
-  static auto key(slot_type* slot)
+  static auto mutable_key(slot_type* slot)
       -> decltype(P::apply(ReturnKey(), element(slot))) {
     return P::apply(ReturnKey(), element(slot));
   }
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
index 886524f..e4484fb 100644
--- a/absl/container/internal/hashtablez_sampler.cc
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -67,6 +67,7 @@
   capacity.store(0, std::memory_order_relaxed);
   size.store(0, std::memory_order_relaxed);
   num_erases.store(0, std::memory_order_relaxed);
+  num_rehashes.store(0, std::memory_order_relaxed);
   max_probe_length.store(0, std::memory_order_relaxed);
   total_probe_length.store(0, std::memory_order_relaxed);
   hashes_bitwise_or.store(0, std::memory_order_relaxed);
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index 308119c..394348d 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -73,6 +73,7 @@
   std::atomic<size_t> capacity;
   std::atomic<size_t> size;
   std::atomic<size_t> num_erases;
+  std::atomic<size_t> num_rehashes;
   std::atomic<size_t> max_probe_length;
   std::atomic<size_t> total_probe_length;
   std::atomic<size_t> hashes_bitwise_or;
@@ -105,6 +106,11 @@
 #endif
   info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);
   info->num_erases.store(0, std::memory_order_relaxed);
+  // There is only one concurrent writer, so `load` then `store` is sufficient
+  // instead of using `fetch_add`.
+  info->num_rehashes.store(
+      1 + info->num_rehashes.load(std::memory_order_relaxed),
+      std::memory_order_relaxed);
 }
 
 inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
@@ -113,7 +119,8 @@
   info->capacity.store(capacity, std::memory_order_relaxed);
   if (size == 0) {
     // This is a clear, reset the total/num_erases too.
-    RecordRehashSlow(info, 0);
+    info->total_probe_length.store(0, std::memory_order_relaxed);
+    info->num_erases.store(0, std::memory_order_relaxed);
   }
 }
 
@@ -122,12 +129,21 @@
 
 inline void RecordEraseSlow(HashtablezInfo* info) {
   info->size.fetch_sub(1, std::memory_order_relaxed);
-  info->num_erases.fetch_add(1, std::memory_order_relaxed);
+  // There is only one concurrent writer, so `load` then `store` is sufficient
+  // instead of using `fetch_add`.
+  info->num_erases.store(
+      1 + info->num_erases.load(std::memory_order_relaxed),
+      std::memory_order_relaxed);
 }
 
 HashtablezInfo* SampleSlow(int64_t* next_sample);
 void UnsampleSlow(HashtablezInfo* info);
 
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 class HashtablezInfoHandle {
  public:
   explicit HashtablezInfoHandle() : info_(nullptr) {}
@@ -179,14 +195,27 @@
   friend class HashtablezInfoHandlePeer;
   HashtablezInfo* info_;
 };
+#else
+// Ensure that when Hashtablez is turned off at compile time, HashtablezInfo can
+// be removed by the linker, in order to reduce the binary size.
+class HashtablezInfoHandle {
+ public:
+  explicit HashtablezInfoHandle() = default;
+  explicit HashtablezInfoHandle(std::nullptr_t) {}
 
-#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
-#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set
+  inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {}
+  inline void RecordRehash(size_t /*total_probe_length*/) {}
+  inline void RecordInsert(size_t /*hash*/, size_t /*distance_from_desired*/) {}
+  inline void RecordErase() {}
+
+  friend inline void swap(HashtablezInfoHandle& /*lhs*/,
+                          HashtablezInfoHandle& /*rhs*/) {}
+};
 #endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
 #if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
-#endif  // ABSL_PER_THREAD_TLS
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
 // Returns an RAII sampling handle that manages registration and unregistation
 // with the global sampler.
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
index b4c4ff9..8d10a1e 100644
--- a/absl/container/internal/hashtablez_sampler_test.cc
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -38,6 +38,7 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 class HashtablezInfoHandlePeer {
  public:
   static bool IsSampled(const HashtablezInfoHandle& h) {
@@ -46,6 +47,13 @@
 
   static HashtablezInfo* GetInfo(HashtablezInfoHandle* h) { return h->info_; }
 };
+#else
+class HashtablezInfoHandlePeer {
+ public:
+  static bool IsSampled(const HashtablezInfoHandle&) { return false; }
+  static HashtablezInfo* GetInfo(HashtablezInfoHandle*) { return nullptr; }
+};
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
 namespace {
 using ::absl::synchronization_internal::ThreadPool;
@@ -76,6 +84,7 @@
   EXPECT_EQ(info.capacity.load(), 0);
   EXPECT_EQ(info.size.load(), 0);
   EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.num_rehashes.load(), 0);
   EXPECT_EQ(info.max_probe_length.load(), 0);
   EXPECT_EQ(info.total_probe_length.load(), 0);
   EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
@@ -95,6 +104,7 @@
   EXPECT_EQ(info.capacity.load(), 0);
   EXPECT_EQ(info.size.load(), 0);
   EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.num_rehashes.load(), 0);
   EXPECT_EQ(info.max_probe_length.load(), 0);
   EXPECT_EQ(info.total_probe_length.load(), 0);
   EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
@@ -167,9 +177,10 @@
   EXPECT_EQ(info.size.load(), 2);
   EXPECT_EQ(info.total_probe_length.load(), 3);
   EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.num_rehashes.load(), 1);
 }
 
-#if defined(ABSL_HASHTABLEZ_SAMPLE)
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 TEST(HashtablezSamplerTest, SmallSampleParameter) {
   SetHashtablezEnabled(true);
   SetHashtablezSampleParameter(100);
@@ -213,7 +224,6 @@
   }
   EXPECT_NEAR(sample_rate, 0.01, 0.005);
 }
-#endif
 
 TEST(HashtablezSamplerTest, Handle) {
   auto& sampler = HashtablezSampler::Global();
@@ -243,6 +253,8 @@
   });
   EXPECT_FALSE(found);
 }
+#endif
+
 
 TEST(HashtablezSamplerTest, Registration) {
   HashtablezSampler sampler;
diff --git a/absl/container/internal/layout_test.cc b/absl/container/internal/layout_test.cc
index 757272f..1d7158f 100644
--- a/absl/container/internal/layout_test.cc
+++ b/absl/container/internal/layout_test.cc
@@ -128,8 +128,10 @@
   {
     using L = Layout<int32_t, int32_t>;
     SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
-    SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial())::ElementTypes>();
-    SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial(0))::ElementTypes>();
+    SameType<std::tuple<int32_t, int32_t>,
+             decltype(L::Partial())::ElementTypes>();
+    SameType<std::tuple<int32_t, int32_t>,
+             decltype(L::Partial(0))::ElementTypes>();
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
@@ -368,18 +370,21 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
   }
   {
     using L = Layout<int32_t, int32_t>;
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
-    EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
     EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
+              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
     EXPECT_EQ(12,
-              Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
+              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
+    EXPECT_EQ(
+        12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
     EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
   }
@@ -387,39 +392,44 @@
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
-    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
+    EXPECT_EQ(4,
+              Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
-    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
+    EXPECT_EQ(8,
+              Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
-    EXPECT_EQ(4,
-              Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
+    EXPECT_EQ(
+        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
     EXPECT_EQ(8,
               Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
-    EXPECT_EQ(8,
-              Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
+    EXPECT_EQ(
+        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
+        0,
+        Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
     EXPECT_EQ(
-        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
+        4,
+        Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(
         8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(
@@ -428,7 +438,8 @@
         24,
         Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
     EXPECT_EQ(
-        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
+        8,
+        Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
     EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
     EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
@@ -439,75 +450,78 @@
   alignas(max_align_t) const unsigned char p[100] = {};
   {
     using L = Layout<int32_t>;
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
-    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
-    EXPECT_EQ(4,
-              Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
-    EXPECT_EQ(8,
-              Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+        0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
+        0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        4,
+        Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        8,
+        Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
+                                 L::Partial(0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         0,
         Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
+        0,
+        Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
+                                 L::Partial(1, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         8,
         Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
+        0,
+        Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
+    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
+                                 L::Partial(5, 3).Pointer<int32_t>(p))));
     EXPECT_EQ(
         24,
         Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+                                 L::Partial(0, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
+                                 L::Partial(0, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<const Int128*>(
                                  L::Partial(0, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        4,
-        Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+                                 L::Partial(1, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
+                                 L::Partial(1, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(8, Distance(p, Type<const Int128*>(
                                  L::Partial(1, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+                                 L::Partial(5, 3, 1).Pointer<int8_t>(p))));
     EXPECT_EQ(24, Distance(p, Type<const Int128*>(
                                   L::Partial(5, 3, 1).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        8,
-        Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
+    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
+                                 L::Partial(5, 3, 1).Pointer<int32_t>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
-    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
   }
 }
 
@@ -548,15 +562,18 @@
     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
     EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
-    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
+    EXPECT_EQ(4,
+              Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
-    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
+    EXPECT_EQ(8,
+              Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
@@ -568,48 +585,61 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
-    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
+    EXPECT_EQ(4,
+              Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
-    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(8,
+              Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(8,
               Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
-    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(4,
-              Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        4,
+        Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
     EXPECT_EQ(
         24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
-    EXPECT_EQ(8,
-              Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        8,
+        Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
@@ -790,67 +820,72 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
-    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+    EXPECT_EQ(0,
+              Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
   }
   {
     using L = Layout<int32_t, int32_t>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
     EXPECT_EQ(
         12,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
-    EXPECT_EQ(12,
-              Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
     EXPECT_EQ(
         0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+               p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
     EXPECT_EQ(
         0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        4,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        8,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+               p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+            p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        4,
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        8,
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p,
+            Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
@@ -864,7 +899,8 @@
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
+            p,
+            Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
         4,
         Distance(
@@ -878,7 +914,8 @@
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
+            p,
+            Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(
@@ -890,12 +927,14 @@
             p,
             Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
+        0,
+        Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
     EXPECT_EQ(
-        8, Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
+        8,
+        Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
   }
 }
 
@@ -906,98 +945,94 @@
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
+            p,
+            Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
+            p,
+            Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
+        0,
+        Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
+            p,
+            Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
             p,
-            Type<Span<const int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        4,
-        Distance(
-            p,
-            Type<Span<const int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        8,
-        Distance(
-            p,
-            Type<Span<const int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
+            Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
             p,
-            Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+            Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p))
+        Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p))
                         .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(0, 0).Slice<int32_t>(p))
+                                 .data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p))
+                        .data()));
+    EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(1, 0).Slice<int32_t>(p))
+                                 .data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))
+                        .data()));
+    EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(5, 3).Slice<int32_t>(p))
+                                 .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+                                 L::Partial(0, 0, 0).Slice<int8_t>(p))
+                                 .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(0, 0, 0).Slice<int32_t>(p))
+                                 .data()));
     EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
                                  L::Partial(0, 0, 0).Slice<Int128>(p))
                                  .data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p,
-            Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        4,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p))
-                        .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+                                 L::Partial(1, 0, 0).Slice<int8_t>(p))
+                                 .data()));
+    EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(1, 0, 0).Slice<int32_t>(p))
+                                 .data()));
     EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
                                  L::Partial(1, 0, 0).Slice<Int128>(p))
                                  .data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p,
-            Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+                                 L::Partial(5, 3, 1).Slice<int8_t>(p))
+                                 .data()));
     EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
                                   L::Partial(5, 3, 1).Slice<Int128>(p))
                                   .data()));
-    EXPECT_EQ(
-        8,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p))
-                        .data()));
+    EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(5, 3, 1).Slice<int32_t>(p))
+                                 .data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
+        Distance(p,
+                 Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(p,
                  Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        8, Distance(
-               p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
+        8,
+        Distance(
+            p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
   }
 }
 
@@ -1005,18 +1040,19 @@
   alignas(max_align_t) unsigned char p[100];
   {
     using L = Layout<int32_t>;
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
     EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
   }
   {
     using L = Layout<int32_t, int32_t>;
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
+        0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
     EXPECT_EQ(
         12,
         Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
@@ -1025,55 +1061,63 @@
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
+        0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+        0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        4, Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        8, Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+        0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
+        Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        4,
+        Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        8,
+        Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(
+               p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(
+               p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
     EXPECT_EQ(
         0, Distance(
                p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
-        4,
-        Distance(p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
+        4, Distance(
+               p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
     EXPECT_EQ(
         8, Distance(
                p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(
         24, Distance(
                 p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
     EXPECT_EQ(
-        8,
-        Distance(p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
-    EXPECT_EQ(0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
+        8, Distance(
+               p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
+    EXPECT_EQ(0,
+              Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(24,
               Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
-    EXPECT_EQ(8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
+    EXPECT_EQ(8,
+              Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
   }
 }
 
@@ -1082,66 +1126,84 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
+        0, Distance(
+               p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
+        0, Distance(
+               p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(0,
+              Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
+        0,
+        Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
+        Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        4, Distance(
-               p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
+        Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        8, Distance(
-               p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+        Distance(p,
+                 Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
+            p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p,
+                 Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(
+        4,
+        Distance(
+            p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p,
+                 Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(
+        8,
+        Distance(
+            p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p,
+            Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p,
+            Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
             p,
             Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
+        0,
+        Distance(
+            p,
+            Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         4,
         Distance(
-            p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
+            p,
+            Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
         8,
         Distance(
             p,
             Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
+        0,
+        Distance(
+            p,
+            Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(
@@ -1150,14 +1212,16 @@
     EXPECT_EQ(
         8,
         Distance(
-            p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
+            p,
+            Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
+        8,
+        Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
   }
 }
 
@@ -1256,17 +1320,17 @@
   }
   {
     const auto x = L::Partial(1, 2, 3);
-    EXPECT_THAT(
-        (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
-        Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
-              IsSameSlice(x.Slice<2>(p))));
+    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
+                    x.Slices(p))),
+                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
+                      IsSameSlice(x.Slice<2>(p))));
   }
   {
     const L x(1, 2, 3);
-    EXPECT_THAT(
-        (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
-        Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
-              IsSameSlice(x.Slice<2>(p))));
+    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
+                    x.Slices(p))),
+                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
+                      IsSameSlice(x.Slice<2>(p))));
   }
 }
 
@@ -1398,7 +1462,8 @@
               x.DebugString());
   }
   {
-    constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
+    constexpr auto x =
+        Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
         "@16" +
@@ -1406,7 +1471,8 @@
         x.DebugString());
   }
   {
-    constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
+    constexpr auto x =
+        Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
         "@16" +
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index 919ac07..2f744a6 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -27,7 +27,7 @@
 
 // Returns "random" seed.
 inline size_t RandomSeed() {
-#if ABSL_HAVE_THREAD_LOCAL
+#ifdef ABSL_HAVE_THREAD_LOCAL
   static thread_local size_t counter = 0;
   size_t value = ++counter;
 #else   // ABSL_HAVE_THREAD_LOCAL
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 48a1a8c..67364b7 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -122,6 +122,16 @@
 ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
+template <typename AllocType>
+void SwapAlloc(AllocType& lhs, AllocType& rhs,
+               std::true_type /* propagate_on_container_swap */) {
+  using std::swap;
+  swap(lhs, rhs);
+}
+template <typename AllocType>
+void SwapAlloc(AllocType& /*lhs*/, AllocType& /*rhs*/,
+               std::false_type /* propagate_on_container_swap */) {}
+
 template <size_t Width>
 class probe_seq {
  public:
@@ -169,10 +179,14 @@
 
 // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
 template <class T>
-constexpr bool IsNoThrowSwappable() {
+constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
   using std::swap;
   return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
 }
+template <class T>
+constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
+  return false;
+}
 
 template <typename T>
 int TrailingZeros(T x) {
@@ -1051,7 +1065,9 @@
   }
 
   iterator insert(const_iterator, node_type&& node) {
-    return insert(std::move(node)).first;
+    auto res = insert(std::move(node));
+    node = std::move(res.node);
+    return res.position;
   }
 
   // This overload kicks in if we can deduce the key from args. This enables us
@@ -1231,8 +1247,8 @@
 
   void swap(raw_hash_set& that) noexcept(
       IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
-      (!AllocTraits::propagate_on_container_swap::value ||
-       IsNoThrowSwappable<allocator_type>())) {
+      IsNoThrowSwappable<allocator_type>(
+          typename AllocTraits::propagate_on_container_swap{})) {
     using std::swap;
     swap(ctrl_, that.ctrl_);
     swap(slots_, that.slots_);
@@ -1242,12 +1258,8 @@
     swap(hash_ref(), that.hash_ref());
     swap(eq_ref(), that.eq_ref());
     swap(infoz_, that.infoz_);
-    if (AllocTraits::propagate_on_container_swap::value) {
-      swap(alloc_ref(), that.alloc_ref());
-    } else {
-      // If the allocators do not compare equal it is officially undefined
-      // behavior. We choose to do nothing.
-    }
+    SwapAlloc(alloc_ref(), that.alloc_ref(),
+              typename AllocTraits::propagate_on_container_swap{});
   }
 
   void rehash(size_t n) {
@@ -1317,6 +1329,7 @@
       }
       if (ABSL_PREDICT_TRUE(g.MatchEmpty())) return end();
       seq.next();
+      assert(seq.index() < capacity_ && "full table!");
     }
   }
   template <class K = key_type>
@@ -1668,8 +1681,8 @@
 #endif
         return {seq.offset(mask.LowestBitSet()), seq.index()};
       }
-      assert(seq.index() < capacity_ && "full table!");
       seq.next();
+      assert(seq.index() < capacity_ && "full table!");
     }
   }
 
@@ -1700,6 +1713,7 @@
       }
       if (ABSL_PREDICT_TRUE(g.MatchEmpty())) break;
       seq.next();
+      assert(seq.index() < capacity_ && "full table!");
     }
     return {prepare_insert(hash), true};
   }
diff --git a/absl/container/internal/raw_hash_set_allocator_test.cc b/absl/container/internal/raw_hash_set_allocator_test.cc
index 7ac4b9f..e73f53f 100644
--- a/absl/container/internal/raw_hash_set_allocator_test.cc
+++ b/absl/container/internal/raw_hash_set_allocator_test.cc
@@ -424,6 +424,81 @@
   EXPECT_EQ(0, it->num_copies());
 }
 
+// This allocator is similar to std::pmr::polymorphic_allocator.
+// Note the disabled assignment.
+template <class T>
+class PAlloc {
+  template <class>
+  friend class PAlloc;
+
+ public:
+  // types
+  using value_type = T;
+
+  // traits
+  using propagate_on_container_swap = std::false_type;
+
+  PAlloc() noexcept = default;
+  explicit PAlloc(size_t id) noexcept : id_(id) {}
+  PAlloc(const PAlloc&) noexcept = default;
+  PAlloc& operator=(const PAlloc&) noexcept = delete;
+
+  template <class U>
+  PAlloc(const PAlloc<U>& that) noexcept : id_(that.id_) {}  // NOLINT
+
+  template <class U>
+  struct rebind {
+    using other = PAlloc<U>;
+  };
+
+  constexpr PAlloc select_on_container_copy_construction() const { return {}; }
+
+  // public member functions
+  T* allocate(size_t) { return new T; }
+  void deallocate(T* p, size_t) { delete p; }
+
+  friend bool operator==(const PAlloc& a, const PAlloc& b) {
+    return a.id_ == b.id_;
+  }
+  friend bool operator!=(const PAlloc& a, const PAlloc& b) { return !(a == b); }
+
+ private:
+  size_t id_ = std::numeric_limits<size_t>::max();
+};
+
+// This doesn't compile with GCC 5.4 and 5.5 due to a bug in noexcept handing.
+#if !defined(__GNUC__) || __GNUC__ != 5 || (__GNUC_MINOR__ != 4 && \
+    __GNUC_MINOR__ != 5)
+TEST(NoPropagateOn, Swap) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(PA{2});
+  swap(t1, t2);
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+#endif
+
+TEST(NoPropagateOn, CopyConstruct) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(t1);
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA());
+}
+
+TEST(NoPropagateOn, Assignment) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(PA{2});
+  t1 = t2;
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index e327930..33d2773 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -847,7 +847,8 @@
 std::vector<int64_t> CollectBadMergeKeys(size_t N) {
   static constexpr int kGroupSize = Group::kWidth - 1;
 
-  auto topk_range = [](size_t b, size_t e, IntTable* t) -> std::vector<int64_t> {
+  auto topk_range = [](size_t b, size_t e,
+                       IntTable* t) -> std::vector<int64_t> {
     for (size_t i = b; i != e; ++i) {
       t->emplace(i);
     }
@@ -1001,8 +1002,8 @@
 // 1. Create new table and reserve it to keys.size() * 2
 // 2. Insert all keys xored with seed
 // 3. Collect ProbeStats from final table.
-ProbeStats CollectProbeStatsOnKeysXoredWithSeed(const std::vector<int64_t>& keys,
-                                                size_t num_iters) {
+ProbeStats CollectProbeStatsOnKeysXoredWithSeed(
+    const std::vector<int64_t>& keys, size_t num_iters) {
   const size_t reserve_size = keys.size() * 2;
 
   ProbeStats stats;
@@ -1710,6 +1711,26 @@
   EXPECT_FALSE(node);
 }
 
+TEST(Nodes, HintInsert) {
+  IntTable t = {1, 2, 3};
+  auto node = t.extract(1);
+  EXPECT_THAT(t, UnorderedElementsAre(2, 3));
+  auto it = t.insert(t.begin(), std::move(node));
+  EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));
+  EXPECT_EQ(*it, 1);
+  EXPECT_FALSE(node);
+
+  node = t.extract(2);
+  EXPECT_THAT(t, UnorderedElementsAre(1, 3));
+  // reinsert 2 to make the next insert fail.
+  t.insert(2);
+  EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));
+  it = t.insert(t.begin(), std::move(node));
+  EXPECT_EQ(*it, 2);
+  // The node was not emptied by the insert call.
+  EXPECT_TRUE(node);
+}
+
 IntTable MakeSimpleTable(size_t size) {
   IntTable t;
   while (t.size() < size) t.insert(t.size());
@@ -1796,7 +1817,7 @@
   EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
 }
 
-#if defined(ABSL_HASHTABLEZ_SAMPLE)
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 TEST(RawHashSamplerTest, Sample) {
   // Enable the feature even if the prod default is off.
   SetHashtablezEnabled(true);
@@ -1817,7 +1838,7 @@
   EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
               0.01, 0.005);
 }
-#endif  // ABSL_HASHTABLEZ_SAMPLER
+#endif  // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
 
 TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
   // Enable the feature even if the prod default is off.
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index 174b971..7a39f62 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -225,7 +225,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // node_hash_map::insert()
@@ -374,6 +375,11 @@
   //   key value and returns a node handle owning that extracted data. If the
   //   `node_hash_map` does not contain an element with a matching key, this
   //   function returns an empty node handle.
+  //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
   using Base::extract;
 
   // node_hash_map::merge()
diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc
index 5d74b81..8f59a1e 100644
--- a/absl/container/node_hash_map_test.cc
+++ b/absl/container/node_hash_map_test.cc
@@ -254,6 +254,21 @@
   }
 }
 
+// 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;
+
+  map["key1"] = "mapped";
+
+  auto nh = map.extract(map.begin());
+  nh.key().resize(3);
+  map.insert(std::move(nh));
+
+  EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
+}
+#endif
+
 }  // namespace
 }  // namespace container_internal
 ABSL_NAMESPACE_END
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index 56bab5c..56ce3b6 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -217,7 +217,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // node_hash_set::insert()
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake
index 97bd283..51742c9 100644
--- a/absl/copts/GENERATED_AbseilCopts.cmake
+++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -5,47 +5,6 @@
 
 list(APPEND ABSL_CLANG_CL_FLAGS
     "/W3"
-    "-Wno-c++98-compat-pedantic"
-    "-Wno-conversion"
-    "-Wno-covered-switch-default"
-    "-Wno-deprecated"
-    "-Wno-disabled-macro-expansion"
-    "-Wno-double-promotion"
-    "-Wno-comma"
-    "-Wno-extra-semi"
-    "-Wno-extra-semi-stmt"
-    "-Wno-packed"
-    "-Wno-padded"
-    "-Wno-sign-compare"
-    "-Wno-float-conversion"
-    "-Wno-float-equal"
-    "-Wno-format-nonliteral"
-    "-Wno-gcc-compat"
-    "-Wno-global-constructors"
-    "-Wno-exit-time-destructors"
-    "-Wno-non-modular-include-in-module"
-    "-Wno-old-style-cast"
-    "-Wno-range-loop-analysis"
-    "-Wno-reserved-id-macro"
-    "-Wno-shorten-64-to-32"
-    "-Wno-switch-enum"
-    "-Wno-thread-safety-negative"
-    "-Wno-unknown-warning-option"
-    "-Wno-unreachable-code"
-    "-Wno-unused-macros"
-    "-Wno-weak-vtables"
-    "-Wno-zero-as-null-pointer-constant"
-    "-Wbitfield-enum-conversion"
-    "-Wbool-conversion"
-    "-Wconstant-conversion"
-    "-Wenum-conversion"
-    "-Wint-conversion"
-    "-Wliteral-conversion"
-    "-Wnon-literal-null-conversion"
-    "-Wnull-conversion"
-    "-Wobjc-literal-conversion"
-    "-Wno-sign-conversion"
-    "-Wstring-conversion"
     "/DNOMINMAX"
     "/DWIN32_LEAN_AND_MEAN"
     "/D_CRT_SECURE_NO_WARNINGS"
@@ -78,6 +37,7 @@
     "-Wextra"
     "-Wcast-qual"
     "-Wconversion-null"
+    "-Wformat-security"
     "-Wmissing-declarations"
     "-Woverlength-strings"
     "-Wpointer-arith"
@@ -87,8 +47,6 @@
     "-Wvarargs"
     "-Wvla"
     "-Wwrite-strings"
-    "-Wno-missing-field-initializers"
-    "-Wno-sign-compare"
     "-DNOMINMAX"
 )
 
@@ -105,48 +63,36 @@
 list(APPEND ABSL_LLVM_FLAGS
     "-Wall"
     "-Wextra"
-    "-Weverything"
-    "-Wno-c++98-compat-pedantic"
-    "-Wno-conversion"
-    "-Wno-covered-switch-default"
-    "-Wno-deprecated"
-    "-Wno-disabled-macro-expansion"
-    "-Wno-double-promotion"
-    "-Wno-comma"
-    "-Wno-extra-semi"
-    "-Wno-extra-semi-stmt"
-    "-Wno-packed"
-    "-Wno-padded"
-    "-Wno-sign-compare"
-    "-Wno-float-conversion"
-    "-Wno-float-equal"
-    "-Wno-format-nonliteral"
-    "-Wno-gcc-compat"
-    "-Wno-global-constructors"
-    "-Wno-exit-time-destructors"
-    "-Wno-non-modular-include-in-module"
-    "-Wno-old-style-cast"
-    "-Wno-range-loop-analysis"
-    "-Wno-reserved-id-macro"
-    "-Wno-shorten-64-to-32"
-    "-Wno-switch-enum"
-    "-Wno-thread-safety-negative"
-    "-Wno-unknown-warning-option"
-    "-Wno-unreachable-code"
-    "-Wno-unused-macros"
-    "-Wno-weak-vtables"
-    "-Wno-zero-as-null-pointer-constant"
-    "-Wbitfield-enum-conversion"
-    "-Wbool-conversion"
-    "-Wconstant-conversion"
-    "-Wenum-conversion"
-    "-Wint-conversion"
+    "-Wcast-qual"
+    "-Wconversion"
+    "-Wfloat-overflow-conversion"
+    "-Wfloat-zero-conversion"
+    "-Wfor-loop-analysis"
+    "-Wformat-security"
+    "-Wgnu-redeclared-enum"
+    "-Winfinite-recursion"
     "-Wliteral-conversion"
-    "-Wnon-literal-null-conversion"
-    "-Wnull-conversion"
-    "-Wobjc-literal-conversion"
-    "-Wno-sign-conversion"
+    "-Wmissing-declarations"
+    "-Woverlength-strings"
+    "-Wpointer-arith"
+    "-Wself-assign"
+    "-Wshadow"
     "-Wstring-conversion"
+    "-Wtautological-overlap-compare"
+    "-Wundef"
+    "-Wuninitialized"
+    "-Wunreachable-code"
+    "-Wunused-comparison"
+    "-Wunused-local-typedefs"
+    "-Wunused-result"
+    "-Wvla"
+    "-Wwrite-strings"
+    "-Wno-float-conversion"
+    "-Wno-implicit-float-conversion"
+    "-Wno-implicit-int-float-conversion"
+    "-Wno-implicit-int-conversion"
+    "-Wno-shorten-64-to-32"
+    "-Wno-sign-conversion"
     "-DNOMINMAX"
 )
 
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl
index bcdd61e..6707488 100644
--- a/absl/copts/GENERATED_copts.bzl
+++ b/absl/copts/GENERATED_copts.bzl
@@ -6,47 +6,6 @@
 
 ABSL_CLANG_CL_FLAGS = [
     "/W3",
-    "-Wno-c++98-compat-pedantic",
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-extra-semi-stmt",
-    "-Wno-packed",
-    "-Wno-padded",
-    "-Wno-sign-compare",
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    "-Wno-gcc-compat",
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    "-Wno-zero-as-null-pointer-constant",
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
-    "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
-    "-Wstring-conversion",
     "/DNOMINMAX",
     "/DWIN32_LEAN_AND_MEAN",
     "/D_CRT_SECURE_NO_WARNINGS",
@@ -79,6 +38,7 @@
     "-Wextra",
     "-Wcast-qual",
     "-Wconversion-null",
+    "-Wformat-security",
     "-Wmissing-declarations",
     "-Woverlength-strings",
     "-Wpointer-arith",
@@ -88,8 +48,6 @@
     "-Wvarargs",
     "-Wvla",
     "-Wwrite-strings",
-    "-Wno-missing-field-initializers",
-    "-Wno-sign-compare",
     "-DNOMINMAX",
 ]
 
@@ -106,48 +64,36 @@
 ABSL_LLVM_FLAGS = [
     "-Wall",
     "-Wextra",
-    "-Weverything",
-    "-Wno-c++98-compat-pedantic",
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-extra-semi-stmt",
-    "-Wno-packed",
-    "-Wno-padded",
-    "-Wno-sign-compare",
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    "-Wno-gcc-compat",
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    "-Wno-zero-as-null-pointer-constant",
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
+    "-Wcast-qual",
+    "-Wconversion",
+    "-Wfloat-overflow-conversion",
+    "-Wfloat-zero-conversion",
+    "-Wfor-loop-analysis",
+    "-Wformat-security",
+    "-Wgnu-redeclared-enum",
+    "-Winfinite-recursion",
     "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
+    "-Wmissing-declarations",
+    "-Woverlength-strings",
+    "-Wpointer-arith",
+    "-Wself-assign",
+    "-Wshadow",
     "-Wstring-conversion",
+    "-Wtautological-overlap-compare",
+    "-Wundef",
+    "-Wuninitialized",
+    "-Wunreachable-code",
+    "-Wunused-comparison",
+    "-Wunused-local-typedefs",
+    "-Wunused-result",
+    "-Wvla",
+    "-Wwrite-strings",
+    "-Wno-float-conversion",
+    "-Wno-implicit-float-conversion",
+    "-Wno-implicit-int-float-conversion",
+    "-Wno-implicit-int-conversion",
+    "-Wno-shorten-64-to-32",
+    "-Wno-sign-conversion",
     "-DNOMINMAX",
 ]
 
diff --git a/absl/copts/configure_copts.bzl b/absl/copts/configure_copts.bzl
index ff9a5ea..4d34254 100644
--- a/absl/copts/configure_copts.bzl
+++ b/absl/copts/configure_copts.bzl
@@ -23,15 +23,13 @@
 
 ABSL_DEFAULT_COPTS = select({
     "//absl:windows": ABSL_MSVC_FLAGS,
-    "//absl:llvm_compiler": ABSL_LLVM_FLAGS,
+    "//absl:clang_compiler": ABSL_LLVM_FLAGS,
     "//conditions:default": ABSL_GCC_FLAGS,
 })
 
-# in absence of modules (--compiler=gcc or -c opt), cc_tests leak their copts
-# to their (included header) dependencies and fail to build outside absl
 ABSL_TEST_COPTS = ABSL_DEFAULT_COPTS + select({
     "//absl:windows": ABSL_MSVC_TEST_FLAGS,
-    "//absl:llvm_compiler": ABSL_LLVM_TEST_FLAGS,
+    "//absl:clang_compiler": ABSL_LLVM_TEST_FLAGS,
     "//conditions:default": ABSL_GCC_TEST_FLAGS,
 })
 
diff --git a/absl/copts/copts.py b/absl/copts/copts.py
index a3437c1..cf52981 100644
--- a/absl/copts/copts.py
+++ b/absl/copts/copts.py
@@ -16,77 +16,6 @@
     "/W3",
 ]
 
-LLVM_BIG_WARNING_FLAGS = [
-    "-Wall",
-    "-Wextra",
-    "-Weverything",
-]
-
-# Docs on single flags is preceded by a comment.
-# Docs on groups of flags is preceded by ###.
-LLVM_DISABLE_WARNINGS_FLAGS = [
-    # Abseil does not support C++98
-    "-Wno-c++98-compat-pedantic",
-    # Turns off all implicit conversion warnings. Most are re-enabled below.
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    ###
-    # Turned off as they include valid C++ code.
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-extra-semi-stmt",
-    "-Wno-packed",
-    "-Wno-padded",
-    ###
-    # Google style does not use unsigned integers, though STL containers
-    # have unsigned types.
-    "-Wno-sign-compare",
-    ###
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    # Too aggressive: warns on Clang extensions enclosed in Clang-only
-    # compilation paths.
-    "-Wno-gcc-compat",
-    ###
-    # Some internal globals are necessary. Don't do this at home.
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    ###
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    # Warns on preferred usage of non-POD types such as string_view
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    # Causes warnings on include guards
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    # Causes warnings on usage of types/compare.h comparison operators.
-    "-Wno-zero-as-null-pointer-constant",
-    ###
-    # Implicit conversion warnings turned off by -Wno-conversion
-    # which are re-enabled below.
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
-    "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
-    "-Wstring-conversion",
-]
-
 LLVM_TEST_DISABLE_WARNINGS_FLAGS = [
     "-Wno-c99-extensions",
     "-Wno-deprecated-declarations",
@@ -125,6 +54,7 @@
         "-Wextra",
         "-Wcast-qual",
         "-Wconversion-null",
+        "-Wformat-security",
         "-Wmissing-declarations",
         "-Woverlength-strings",
         "-Wpointer-arith",
@@ -134,13 +64,6 @@
         "-Wvarargs",
         "-Wvla",  # variable-length array
         "-Wwrite-strings",
-        # gcc-4.x has spurious missing field initializer warnings.
-        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750
-        # Remove when gcc-4.x is no longer supported.
-        "-Wno-missing-field-initializers",
-        # Google style does not use unsigned integers, though STL containers
-        # have unsigned types.
-        "-Wno-sign-compare",
         # Don't define min and max macros (Build on Windows using gcc)
         "-DNOMINMAX",
     ],
@@ -153,15 +76,48 @@
         "-Wno-unused-parameter",
         "-Wno-unused-private-field",
     ],
-    "ABSL_LLVM_FLAGS":
-        LLVM_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS + [
-            # Don't define min and max macros (Build on Windows using clang)
-            "-DNOMINMAX",
-        ],
+    "ABSL_LLVM_FLAGS": [
+        "-Wall",
+        "-Wextra",
+        "-Wcast-qual",
+        "-Wconversion",
+        "-Wfloat-overflow-conversion",
+        "-Wfloat-zero-conversion",
+        "-Wfor-loop-analysis",
+        "-Wformat-security",
+        "-Wgnu-redeclared-enum",
+        "-Winfinite-recursion",
+        "-Wliteral-conversion",
+        "-Wmissing-declarations",
+        "-Woverlength-strings",
+        "-Wpointer-arith",
+        "-Wself-assign",
+        "-Wshadow",
+        "-Wstring-conversion",
+        "-Wtautological-overlap-compare",
+        "-Wundef",
+        "-Wuninitialized",
+        "-Wunreachable-code",
+        "-Wunused-comparison",
+        "-Wunused-local-typedefs",
+        "-Wunused-result",
+        "-Wvla",
+        "-Wwrite-strings",
+        # Warnings that are enabled by group warning flags like -Wall that we
+        # explicitly disable.
+        "-Wno-float-conversion",
+        "-Wno-implicit-float-conversion",
+        "-Wno-implicit-int-float-conversion",
+        "-Wno-implicit-int-conversion",
+        "-Wno-shorten-64-to-32",
+        "-Wno-sign-conversion",
+        # Don't define min and max macros (Build on Windows using clang)
+        "-DNOMINMAX",
+    ],
     "ABSL_LLVM_TEST_FLAGS":
         LLVM_TEST_DISABLE_WARNINGS_FLAGS,
     "ABSL_CLANG_CL_FLAGS":
-        (MSVC_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS + MSVC_DEFINES),
+        (MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES),
     "ABSL_CLANG_CL_TEST_FLAGS":
         LLVM_TEST_DISABLE_WARNINGS_FLAGS,
     "ABSL_MSVC_FLAGS":
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index 9098ca4..cd6e454 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -26,7 +26,7 @@
     default_visibility = ["//visibility:public"],
 )
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "stacktrace",
@@ -239,7 +239,7 @@
 # These targets exists for use in tests only, explicitly configuring the
 # LEAK_SANITIZER macro. It must be linked with -fsanitize=leak for lsan.
 ABSL_LSAN_LINKOPTS = select({
-    "//absl:llvm_compiler": ["-fsanitize=leak"],
+    "//absl:clang_compiler": ["-fsanitize=leak"],
     "//conditions:default": [],
 })
 
@@ -249,7 +249,7 @@
     srcs = ["leak_check.cc"],
     hdrs = ["leak_check.h"],
     copts = select({
-        "//absl:llvm_compiler": ["-DLEAK_SANITIZER"],
+        "//absl:clang_compiler": ["-DLEAK_SANITIZER"],
         "//conditions:default": [],
     }),
     linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -276,7 +276,7 @@
     name = "leak_check_test",
     srcs = ["leak_check_test.cc"],
     copts = select({
-        "//absl:llvm_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
+        "//absl:clang_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
         "//conditions:default": [],
     }),
     linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
diff --git a/absl/debugging/internal/address_is_readable.cc b/absl/debugging/internal/address_is_readable.cc
index 6537606..329c285 100644
--- a/absl/debugging/internal/address_is_readable.cc
+++ b/absl/debugging/internal/address_is_readable.cc
@@ -68,6 +68,7 @@
 // unimplemented.
 // This is a namespace-scoped variable for correct zero-initialization.
 static std::atomic<uint64_t> pid_and_fds;  // initially 0, an invalid pid.
+
 bool AddressIsReadable(const void *addr) {
   absl::base_internal::ErrnoSaver errno_saver;
   // We test whether a byte is readable by using write().  Normally, this would
@@ -86,7 +87,7 @@
     int pid;
     int read_fd;
     int write_fd;
-    uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
+    uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
     Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
     while (current_pid != pid) {
       int p[2];
@@ -98,13 +99,13 @@
       fcntl(p[1], F_SETFD, FD_CLOEXEC);
       uint64_t new_pid_and_fds = Pack(current_pid, p[0], p[1]);
       if (pid_and_fds.compare_exchange_strong(
-              local_pid_and_fds, new_pid_and_fds, std::memory_order_relaxed,
+              local_pid_and_fds, new_pid_and_fds, std::memory_order_release,
               std::memory_order_relaxed)) {
         local_pid_and_fds = new_pid_and_fds;  // fds exposed to other threads
       } else {  // fds not exposed to other threads; we can close them.
         close(p[0]);
         close(p[1]);
-        local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
+        local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
       }
       Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
     }
@@ -124,7 +125,7 @@
       // If pid_and_fds contains the problematic file descriptors we just used,
       // this call will forget them, and the loop will try again.
       pid_and_fds.compare_exchange_strong(local_pid_and_fds, 0,
-                                          std::memory_order_relaxed,
+                                          std::memory_order_release,
                                           std::memory_order_relaxed);
     }
   } while (errno == EBADF);
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 87f13e5..46cdb67 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -1082,20 +1082,28 @@
   return false;
 }
 
-// <ctor-dtor-name> ::= C1 | C2 | C3
+// <ctor-dtor-name> ::= C1 | C2 | C3 | CI1 <base-class-type> | CI2
+// <base-class-type>
 //                  ::= D0 | D1 | D2
 // # GCC extensions: "unified" constructor/destructor.  See
-// # https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
+// #
+// https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
 //                  ::= C4 | D4
 static bool ParseCtorDtorName(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
   ParseState copy = state->parse_state;
-  if (ParseOneCharToken(state, 'C') && ParseCharClass(state, "1234")) {
-    const char *const prev_name = state->out + state->parse_state.prev_name_idx;
-    MaybeAppendWithLength(state, prev_name,
-                          state->parse_state.prev_name_length);
-    return true;
+  if (ParseOneCharToken(state, 'C')) {
+    if (ParseCharClass(state, "1234")) {
+      const char *const prev_name =
+          state->out + state->parse_state.prev_name_idx;
+      MaybeAppendWithLength(state, prev_name,
+                            state->parse_state.prev_name_length);
+      return true;
+    } else if (ParseOneCharToken(state, 'I') && ParseCharClass(state, "12") &&
+               ParseClassEnumType(state)) {
+      return true;
+    }
   }
   state->parse_state = copy;
 
@@ -1265,12 +1273,40 @@
   return false;
 }
 
-// <function-type> ::= F [Y] <bare-function-type> [O] E
+//  <exception-spec> ::= Do                # non-throwing
+//                                           exception-specification (e.g.,
+//                                           noexcept, throw())
+//                   ::= DO <expression> E # computed (instantiation-dependent)
+//                                           noexcept
+//                   ::= Dw <type>+ E      # dynamic exception specification
+//                                           with instantiation-dependent types
+static bool ParseExceptionSpec(State *state) {
+  ComplexityGuard guard(state);
+  if (guard.IsTooComplex()) return false;
+
+  if (ParseTwoCharToken(state, "Do")) return true;
+
+  ParseState copy = state->parse_state;
+  if (ParseTwoCharToken(state, "DO") && ParseExpression(state) &&
+      ParseOneCharToken(state, 'E')) {
+    return true;
+  }
+  state->parse_state = copy;
+  if (ParseTwoCharToken(state, "Dw") && OneOrMore(ParseType, state) &&
+      ParseOneCharToken(state, 'E')) {
+    return true;
+  }
+  state->parse_state = copy;
+
+  return false;
+}
+
+// <function-type> ::= [exception-spec] F [Y] <bare-function-type> [O] E
 static bool ParseFunctionType(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
   ParseState copy = state->parse_state;
-  if (ParseOneCharToken(state, 'F') &&
+  if (Optional(ParseExceptionSpec(state)) && ParseOneCharToken(state, 'F') &&
       Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) &&
       Optional(ParseOneCharToken(state, 'O')) &&
       ParseOneCharToken(state, 'E')) {
@@ -1900,7 +1936,8 @@
 bool Demangle(const char *mangled, char *out, int out_size) {
   State state;
   InitState(&state, mangled, out, out_size);
-  return ParseTopLevelMangledName(&state) && !Overflowed(&state);
+  return ParseTopLevelMangledName(&state) && !Overflowed(&state) &&
+         state.parse_state.out_cur_idx > 0;
 }
 
 }  // namespace debugging_internal
diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h
index d5cc174..90af852 100644
--- a/absl/debugging/internal/stacktrace_config.h
+++ b/absl/debugging/internal/stacktrace_config.h
@@ -44,48 +44,46 @@
     !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_generic-inl.inc"
-#else
-#define ABSL_STACKTRACE_INL_HEADER \
-  "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
 #endif
 
 #elif defined(__linux__) && !defined(__ANDROID__)
 
-#if !defined(NO_FRAME_POINTER)
-# if defined(__i386__) || defined(__x86_64__)
+#if defined(NO_FRAME_POINTER) && \
+    (defined(__i386__) || defined(__x86_64__) || defined(__aarch64__))
+// Note: The libunwind-based implementation is not available to open-source
+// users.
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_x86-inl.inc"
-# elif defined(__ppc__) || defined(__PPC__)
-#define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_powerpc-inl.inc"
-# elif defined(__aarch64__)
-#define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_aarch64-inl.inc"
-#elif defined(__arm__) && defined(__GLIBC__)
+  "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>)
 // Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_generic-inl.inc"
-# else
+#endif
+#elif defined(__i386__) || defined(__x86_64__)
 #define ABSL_STACKTRACE_INL_HEADER \
-   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-# endif
-#else  // defined(NO_FRAME_POINTER)
-# if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
+  "absl/debugging/internal/stacktrace_x86-inl.inc"
+#elif defined(__ppc__) || defined(__PPC__)
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_generic-inl.inc"
-# elif defined(__ppc__) || defined(__PPC__)
+  "absl/debugging/internal/stacktrace_powerpc-inl.inc"
+#elif defined(__aarch64__)
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_generic-inl.inc"
-# else
+  "absl/debugging/internal/stacktrace_aarch64-inl.inc"
+#elif defined(__has_include)
+#if __has_include(<execinfo.h>)
+// Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
-   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-# endif
-#endif  // NO_FRAME_POINTER
+  "absl/debugging/internal/stacktrace_generic-inl.inc"
+#endif
+#endif
 
-#else
+#endif
+
+// Fallback to the empty implementation.
+#if !defined(ABSL_STACKTRACE_INL_HEADER)
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-
 #endif
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
diff --git a/absl/debugging/internal/stacktrace_generic-inl.inc b/absl/debugging/internal/stacktrace_generic-inl.inc
index b2792a1..b94c612 100644
--- a/absl/debugging/internal/stacktrace_generic-inl.inc
+++ b/absl/debugging/internal/stacktrace_generic-inl.inc
@@ -43,17 +43,6 @@
 // glibc implementation itself will trigger malloc the first time it is called.
 // As such, we suppress usage of backtrace during this early stage of execution.
 static std::atomic<bool> disable_stacktraces(true);  // Disabled until healthy.
-// 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 = []() {
-  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
-  // to use backtrace from a signal handler if we crash somewhere later.
-  backtrace(unused_stack, 1);
-  disable_stacktraces.store(false, std::memory_order_relaxed);
-  return 0;
-}();
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
 static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
@@ -99,7 +88,7 @@
 ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 bool StackTraceWorksForTest() {
-  return true;
+  return false;
 }
 }  // namespace debugging_internal
 ABSL_NAMESPACE_END
diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h
index b3729af..4f26130 100644
--- a/absl/debugging/internal/symbolize.h
+++ b/absl/debugging/internal/symbolize.h
@@ -118,16 +118,14 @@
 //   filename != nullptr
 //
 // Returns true if the file was successfully registered.
-bool RegisterFileMappingHint(
-    const void* start, const void* end, uint64_t offset, const char* filename);
+bool RegisterFileMappingHint(const void* start, const void* end,
+                             uint64_t offset, const char* filename);
 
 // Looks up the file mapping registered by RegisterFileMappingHint for an
 // address range. If there is one, the file name is stored in *filename and
 // *start and *end are modified to reflect the registered mapping. Returns
 // whether any hint was found.
-bool GetFileMappingHint(const void** start,
-                        const void** end,
-                        uint64_t    *  offset,
+bool GetFileMappingHint(const void** start, const void** end, uint64_t* offset,
                         const char** filename);
 
 }  // namespace debugging_internal
diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc
index eec7a6e..5e4a25d 100644
--- a/absl/debugging/symbolize.cc
+++ b/absl/debugging/symbolize.cc
@@ -14,9 +14,18 @@
 
 #include "absl/debugging/symbolize.h"
 
+#ifdef _WIN32
+#include <winapifamily.h>
+#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \
+    WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+// UWP doesn't have access to win32 APIs.
+#define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32
+#endif
+#endif
+
 #if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE)
 #include "absl/debugging/symbolize_elf.inc"
-#elif defined(_WIN32)
+#elif defined(ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32)
 // The Windows Symbolizer only works if PDB files containing the debug info
 // are available to the program at runtime.
 #include "absl/debugging/symbolize_win32.inc"
diff --git a/absl/debugging/symbolize_darwin.inc b/absl/debugging/symbolize_darwin.inc
index cdadd40..443ce9e 100644
--- a/absl/debugging/symbolize_darwin.inc
+++ b/absl/debugging/symbolize_darwin.inc
@@ -77,8 +77,8 @@
 
   char tmp_buf[1024];
   if (debugging_internal::Demangle(symbol.c_str(), tmp_buf, sizeof(tmp_buf))) {
-    int len = strlen(tmp_buf);
-    if (len + 1 <= out_size) {  // +1 for '\0'
+    size_t len = strlen(tmp_buf);
+    if (len + 1 <= static_cast<size_t>(out_size)) {  // +1 for '\0'
       assert(len < sizeof(tmp_buf));
       memmove(out, tmp_buf, len + 1);
     }
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index 7c36fd1..f4d5727 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -1281,7 +1281,7 @@
     const int phnum = obj->elf_header.e_phnum;
     const int phentsize = obj->elf_header.e_phentsize;
     size_t phoff = obj->elf_header.e_phoff;
-    int num_executable_load_segments = 0;
+    size_t num_executable_load_segments = 0;
     for (int j = 0; j < phnum; j++) {
       ElfW(Phdr) phdr;
       if (!ReadFromOffsetExact(obj->fd, &phdr, sizeof(phdr), phoff)) {
@@ -1342,7 +1342,7 @@
         // Note: some binaries have multiple "rx" LOAD segments. We must
         // find the right one.
         ElfW(Phdr) *phdr = nullptr;
-        for (int j = 0; j < obj->phdr.size(); j++) {
+        for (size_t j = 0; j < obj->phdr.size(); j++) {
           ElfW(Phdr) &p = obj->phdr[j];
           if (p.p_type != PT_LOAD) {
             // We only expect PT_LOADs. This must be PT_NULL that we didn't
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 92bd4f1..2bd9478 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "path_util",
@@ -114,7 +114,6 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = ["//visibility:private"],
     deps = [
         "//absl/base:config",
         "//absl/base:fast_type_id",
@@ -179,6 +178,7 @@
         ":private_handle_accessor",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/container:flat_hash_map",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -381,6 +381,8 @@
     deps = [
         ":flag",
         ":marshalling",
+        ":parse",
+        ":reflection",
         "//absl/strings",
         "//absl/time",
         "//absl/types:optional",
@@ -464,6 +466,7 @@
         ":flag",
         ":marshalling",
         ":reflection",
+        ":usage_internal",
         "//absl/memory",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
diff --git a/absl/flags/BUILD.gn b/absl/flags/BUILD.gn
index 99c61ca..8fa0603 100644
--- a/absl/flags/BUILD.gn
+++ b/absl/flags/BUILD.gn
@@ -61,7 +61,6 @@
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:fast_type_id",
   ]
-  visibility = [ ":*" ]
 }
 
 absl_source_set("commandlineflag") {
@@ -101,6 +100,7 @@
     ":private_handle_accessor",
     "//third_party/abseil-cpp/absl/base:config",
     "//third_party/abseil-cpp/absl/base:core_headers",
+    "//third_party/abseil-cpp/absl/container:flat_hash_map",
     "//third_party/abseil-cpp/absl/strings",
     "//third_party/abseil-cpp/absl/synchronization",
   ]
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index 343774d..8855191 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -165,6 +165,7 @@
     absl::flags_config
     absl::strings
     absl::synchronization
+    absl::flat_hash_map
 )
 
 # Internal-only target, do not depend on directly.
@@ -182,6 +183,7 @@
   DEPS
     absl::base
     absl::config
+    absl::flags_commandlineflag
     absl::flags_commandlineflag_internal
     absl::flags_config
     absl::flags_marshalling
@@ -407,9 +409,10 @@
     absl::flags_commandlineflag_internal
     absl::flags
     absl::flags_reflection
+    absl::flags_usage
     absl::memory
     absl::strings
-    gtest_main
+    gmock_main
 )
 
 absl_cc_test(
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index cdac545..a9cb2b7 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -144,11 +144,17 @@
   inline bool IsOfType() const {
     return GetImpl().template IsOfType<U>();
   }
-  T Get() const { return GetImpl().Get(); }
-  void Set(const T& v) { GetImpl().Set(v); }
+  T Get() const {
+    return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl());
+  }
+  void Set(const T& v) {
+    flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v);
+  }
   void InvokeCallback() { GetImpl().InvokeCallback(); }
 
-  const CommandLineFlag& Reflect() const { return GetImpl().Reflect(); }
+  const CommandLineFlag& Reflect() const {
+    return flags_internal::FlagImplPeer::InvokeReflect(GetImpl());
+  }
 
   // The data members are logically private, but they need to be public for
   // this to be an aggregate type.
@@ -180,7 +186,7 @@
 //   std::string first_name = absl::GetFlag(FLAGS_firstname);
 template <typename T>
 ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
-  return flag.Get();
+  return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
 }
 
 // SetFlag()
@@ -192,7 +198,7 @@
 // but especially within performance-critical code.
 template <typename T>
 void SetFlag(absl::Flag<T>* flag, const T& v) {
-  flag->Set(v);
+  flags_internal::FlagImplPeer::InvokeSet(*flag, v);
 }
 
 // Overload of `SetFlag()` to allow callers to pass in a value that is
@@ -201,7 +207,7 @@
 template <typename T, typename V>
 void SetFlag(absl::Flag<T>* flag, const V& v) {
   T value(v);
-  flag->Set(value);
+  flags_internal::FlagImplPeer::InvokeSet(*flag, value);
 }
 
 // GetFlagReflectionHandle()
@@ -216,7 +222,7 @@
 
 template <typename T>
 const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
-  return f.Reflect();
+  return flags_internal::FlagImplPeer::InvokeReflect(f);
 }
 
 ABSL_NAMESPACE_END
diff --git a/absl/flags/flag_benchmark.cc b/absl/flags/flag_benchmark.cc
index 7b52c9b..9982b60 100644
--- a/absl/flags/flag_benchmark.cc
+++ b/absl/flags/flag_benchmark.cc
@@ -20,6 +20,8 @@
 
 #include "absl/flags/flag.h"
 #include "absl/flags/marshalling.h"
+#include "absl/flags/parse.h"
+#include "absl/flags/reflection.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/time.h"
 #include "absl/types/optional.h"
@@ -103,6 +105,23 @@
 
 BENCHMARKED_TYPES(FLAG_DEF)
 
+// Register thousands of flags to bloat up the size of the registry.
+// This mimics real life production binaries.
+#define DEFINE_FLAG_0(name) ABSL_FLAG(int, name, 0, "");
+#define DEFINE_FLAG_1(name) DEFINE_FLAG_0(name##0) DEFINE_FLAG_0(name##1)
+#define DEFINE_FLAG_2(name) DEFINE_FLAG_1(name##0) DEFINE_FLAG_1(name##1)
+#define DEFINE_FLAG_3(name) DEFINE_FLAG_2(name##0) DEFINE_FLAG_2(name##1)
+#define DEFINE_FLAG_4(name) DEFINE_FLAG_3(name##0) DEFINE_FLAG_3(name##1)
+#define DEFINE_FLAG_5(name) DEFINE_FLAG_4(name##0) DEFINE_FLAG_4(name##1)
+#define DEFINE_FLAG_6(name) DEFINE_FLAG_5(name##0) DEFINE_FLAG_5(name##1)
+#define DEFINE_FLAG_7(name) DEFINE_FLAG_6(name##0) DEFINE_FLAG_6(name##1)
+#define DEFINE_FLAG_8(name) DEFINE_FLAG_7(name##0) DEFINE_FLAG_7(name##1)
+#define DEFINE_FLAG_9(name) DEFINE_FLAG_8(name##0) DEFINE_FLAG_8(name##1)
+#define DEFINE_FLAG_10(name) DEFINE_FLAG_9(name##0) DEFINE_FLAG_9(name##1)
+#define DEFINE_FLAG_11(name) DEFINE_FLAG_10(name##0) DEFINE_FLAG_10(name##1)
+#define DEFINE_FLAG_12(name) DEFINE_FLAG_11(name##0) DEFINE_FLAG_11(name##1)
+DEFINE_FLAG_12(bloat_flag_);
+
 namespace {
 
 #define BM_GetFlag(T)                                            \
@@ -115,6 +134,20 @@
 
 BENCHMARKED_TYPES(BM_GetFlag)
 
+void BM_ThreadedFindCommandLineFlag(benchmark::State& state) {
+  char dummy[] = "dummy";
+  char* argv[] = {dummy};
+  // We need to ensure that flags have been parsed. That is where the registry
+  // is finalized.
+  absl::ParseCommandLine(1, argv);
+
+  for (auto s : state) {
+    benchmark::DoNotOptimize(
+        absl::FindCommandLineFlag("bloat_flag_010101010101"));
+  }
+}
+BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);
+
 }  // namespace
 
 #define InvokeGetFlag(T)                                               \
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index 89e43ad..370d8a0 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -632,20 +632,9 @@
   std::string CurrentValue() const { return impl_.CurrentValue(); }
 
  private:
-  template <typename U, bool do_register>
+  template <typename, bool>
   friend class FlagRegistrar;
-
-#if !defined(_MSC_VER) || defined(__clang__)
-  template <typename U>
-  friend U absl::GetFlag(const flags_internal::Flag<U>& flag);
-  template <typename U>
-  friend void absl::SetFlag(flags_internal::Flag<U>* flag, const U& v);
-  template <typename U, typename V>
-  friend void absl::SetFlag(flags_internal::Flag<U>* flag, const V& v);
-#else
-  template <typename U>
-  friend class absl::Flag;
-#endif
+  friend class FlagImplPeer;
 
   T Get() const {
     // See implementation notes in CommandLineFlag::Get().
@@ -668,10 +657,6 @@
     impl_.Write(&v);
   }
 
-  template <typename U>
-  friend const CommandLineFlag& absl::GetFlagReflectionHandle(
-      const absl::Flag<U>& f);
-
   // Access to the reflection.
   const CommandLineFlag& Reflect() const { return impl_; }
 
@@ -684,6 +669,25 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
+// Trampoline for friend access
+
+class FlagImplPeer {
+ public:
+  template <typename T, typename FlagType>
+  static T InvokeGet(const FlagType& flag) {
+    return flag.Get();
+  }
+  template <typename FlagType, typename T>
+  static void InvokeSet(FlagType& flag, const T& v) {
+    flag.Set(v);
+  }
+  template <typename FlagType>
+  static const CommandLineFlag& InvokeReflect(const FlagType& f) {
+    return f.Reflect();
+  }
+};
+
+///////////////////////////////////////////////////////////////////////////////
 // Implementation of Flag value specific operations routine.
 template <typename T>
 void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
index 1df2db7..a8d9eb9 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -30,9 +30,6 @@
 ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-// Executes specified visitor for each non-retired flag in the registry.
-// Requires the caller hold the registry lock.
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor);
 // Executes specified visitor for each non-retired flag in the registry. While
 // callback are executed, the registry is locked and can't be changed.
 void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
@@ -41,6 +38,8 @@
 
 bool RegisterCommandLineFlag(CommandLineFlag&);
 
+void FinalizeRegistry();
+
 //-----------------------------------------------------------------------------
 // Retired registrations:
 //
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index 0805df3..7557322 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -145,7 +145,8 @@
       }
 
       // Write the token, ending the string first if necessary/possible.
-      if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
+      if (!new_line &&
+          (line_len_ + static_cast<int>(token.size()) >= max_line_len_)) {
         EndLine();
         new_line = true;
       }
diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h
index 0c62dc4..619ccce 100644
--- a/absl/flags/internal/usage.h
+++ b/absl/flags/internal/usage.h
@@ -36,7 +36,8 @@
   kHumanReadable,
 };
 
-// Outputs the help message describing specific flag.
+// Streams the help message describing `flag` to `out`.
+// The default value for `flag` is included in the output.
 void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
               HelpFormat format = HelpFormat::kHumanReadable);
 
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index 4f4bb3d..1835a83 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -611,6 +611,11 @@
                                         OnUndefinedFlag on_undef_flag) {
   ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
 
+  // Once parsing has started we will not have more flag registrations.
+  // If we did, they would be missing during parsing, which is a problem on
+  // itself.
+  flags_internal::FinalizeRegistry();
+
   // This routine does not return anything since we abort on failure.
   CheckDefaultValuesParsingRoundtrip();
 
diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc
index e4145b3..c6bf8aa 100644
--- a/absl/flags/reflection.cc
+++ b/absl/flags/reflection.cc
@@ -17,6 +17,7 @@
 
 #include <assert.h>
 
+#include <atomic>
 #include <map>
 #include <string>
 
@@ -56,21 +57,23 @@
 
   // Returns the flag object for the specified name, or nullptr if not found.
   // Will emit a warning if a 'retired' flag is specified.
-  CommandLineFlag* FindFlagLocked(absl::string_view name);
+  CommandLineFlag* FindFlag(absl::string_view name);
 
   static FlagRegistry& GlobalRegistry();  // returns a singleton registry
 
  private:
   friend class flags_internal::FlagSaverImpl;  // reads all the flags in order
                                                // to copy them
-  friend void ForEachFlagUnlocked(
-      std::function<void(CommandLineFlag&)> visitor);
+  friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
+  friend void FinalizeRegistry();
 
-  // The map from name to flag, for FindFlagLocked().
+  // The map from name to flag, for FindFlag().
   using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
   using FlagIterator = FlagMap::iterator;
   using FlagConstIterator = FlagMap::const_iterator;
   FlagMap flags_;
+  std::vector<CommandLineFlag*> flat_flags_;
+  std::atomic<bool> finalized_flags_{false};
 
   absl::Mutex lock_;
 
@@ -79,15 +82,6 @@
   FlagRegistry& operator=(const FlagRegistry&);
 };
 
-CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
-  FlagConstIterator i = flags_.find(name);
-  if (i == flags_.end()) {
-    return nullptr;
-  }
-
-  return i->second;
-}
-
 namespace {
 
 class FlagRegistryLock {
@@ -101,8 +95,24 @@
 
 }  // namespace
 
+CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) {
+  if (finalized_flags_.load(std::memory_order_acquire)) {
+    // We could save some gcus here if we make `Name()` be non-virtual.
+    // We could move the `const char*` name to the base class.
+    auto it = std::partition_point(
+        flat_flags_.begin(), flat_flags_.end(),
+        [=](CommandLineFlag* f) { return f->Name() < name; });
+    if (it != flat_flags_.end() && (*it)->Name() == name) return *it;
+  }
+
+  FlagRegistryLock frl(*this);
+  auto it = flags_.find(name);
+  return it != flags_.end() ? it->second : nullptr;
+}
+
 void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
   FlagRegistryLock registry_lock(*this);
+
   std::pair<FlagIterator, bool> ins =
       flags_.insert(FlagMap::value_type(flag.Name(), &flag));
   if (ins.second == false) {  // means the name was already in the map
@@ -152,18 +162,15 @@
 
 // --------------------------------------------------------------------
 
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor) {
-  FlagRegistry& registry = FlagRegistry::GlobalRegistry();
-  for (FlagRegistry::FlagConstIterator i = registry.flags_.begin();
-       i != registry.flags_.end(); ++i) {
-    visitor(*i->second);
-  }
-}
-
 void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
   FlagRegistry& registry = FlagRegistry::GlobalRegistry();
+
+  if (registry.finalized_flags_.load(std::memory_order_acquire)) {
+    for (const auto& i : registry.flat_flags_) visitor(*i);
+  }
+
   FlagRegistryLock frl(registry);
-  ForEachFlagUnlocked(visitor);
+  for (const auto& i : registry.flags_) visitor(*i.second);
 }
 
 // --------------------------------------------------------------------
@@ -173,6 +180,21 @@
   return true;
 }
 
+void FinalizeRegistry() {
+  auto& registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  if (registry.finalized_flags_.load(std::memory_order_relaxed)) {
+    // Was already finalized. Ignore the second time.
+    return;
+  }
+  registry.flat_flags_.reserve(registry.flags_.size());
+  for (const auto& f : registry.flags_) {
+    registry.flat_flags_.push_back(f.second);
+  }
+  registry.flags_.clear();
+  registry.finalized_flags_.store(true, std::memory_order_release);
+}
+
 // --------------------------------------------------------------------
 
 namespace {
@@ -298,9 +320,17 @@
   if (name.empty()) return nullptr;
   flags_internal::FlagRegistry& registry =
       flags_internal::FlagRegistry::GlobalRegistry();
-  flags_internal::FlagRegistryLock frl(registry);
+  return registry.FindFlag(name);
+}
 
-  return registry.FindFlagLocked(name);
+// --------------------------------------------------------------------
+
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags() {
+  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> res;
+  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+    res.insert({flag.Name(), &flag});
+  });
+  return res;
 }
 
 ABSL_NAMESPACE_END
diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h
index 045f978..e6baf5d 100644
--- a/absl/flags/reflection.h
+++ b/absl/flags/reflection.h
@@ -26,6 +26,7 @@
 #include <string>
 
 #include "absl/base/config.h"
+#include "absl/container/flat_hash_map.h"
 #include "absl/flags/commandlineflag.h"
 #include "absl/flags/internal/commandlineflag.h"
 
@@ -40,7 +41,11 @@
 // Returns the reflection handle of an Abseil flag of the specified name, or
 // `nullptr` if not found. This function will emit a warning if the name of a
 // 'retired' flag is specified.
-CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+absl::CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+
+// Returns current state of the Flags registry in a form of mapping from flag
+// name to a flag reflection handle.
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags();
 
 //------------------------------------------------------------------------------
 // FlagSaver
@@ -59,7 +64,7 @@
 //   void MyFunc() {
 //    absl::FlagSaver fs;
 //    ...
-//    absl::SetFlag(FLAGS_myFlag, otherValue);
+//    absl::SetFlag(&FLAGS_myFlag, otherValue);
 //    ...
 //  } // scope of FlagSaver left, flags return to previous state
 //
diff --git a/absl/flags/reflection_test.cc b/absl/flags/reflection_test.cc
index 2da0a0e..1a1dcb4 100644
--- a/absl/flags/reflection_test.cc
+++ b/absl/flags/reflection_test.cc
@@ -18,7 +18,9 @@
 #include <memory>
 #include <string>
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/marshalling.h"
@@ -30,6 +32,8 @@
 ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
 ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
 
+ABSL_DECLARE_FLAG(bool, help);
+
 namespace {
 
 namespace flags = absl::flags_internal;
@@ -61,6 +65,33 @@
 
 // --------------------------------------------------------------------
 
+TEST_F(ReflectionTest, TestGetAllFlags) {
+  (void)absl::GetFlag(FLAGS_help);  // Force linking of usage flags.
+
+  auto all_flags = absl::GetAllFlags();
+  EXPECT_NE(all_flags.find("int_flag"), all_flags.end());
+  EXPECT_NE(all_flags.find("bool_retired_flag"), all_flags.end());
+  EXPECT_NE(all_flags.find("help"), all_flags.end());
+  EXPECT_EQ(all_flags.find("some_undefined_flag"), all_flags.end());
+
+  std::vector<absl::string_view> flag_names_first_attempt;
+  auto all_flags_1 = absl::GetAllFlags();
+  for (auto f : all_flags_1) {
+    flag_names_first_attempt.push_back(f.first);
+  }
+
+  std::vector<absl::string_view> flag_names_second_attempt;
+  auto all_flags_2 = absl::GetAllFlags();
+  for (auto f : all_flags_2) {
+    flag_names_second_attempt.push_back(f.first);
+  }
+
+  EXPECT_THAT(flag_names_first_attempt,
+              ::testing::UnorderedElementsAreArray(flag_names_second_attempt));
+}
+
+// --------------------------------------------------------------------
+
 struct CustomUDT {
   CustomUDT() : a(1), b(1) {}
   CustomUDT(int a_, int b_) : a(a_), b(b_) {}
diff --git a/absl/functional/BUILD.bazel b/absl/functional/BUILD.bazel
index 432546c..ebd9b99 100644
--- a/absl/functional/BUILD.bazel
+++ b/absl/functional/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "bind_front",
diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel
index 6c77f1a..5b1e2d0 100644
--- a/absl/hash/BUILD.bazel
+++ b/absl/hash/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "hash",
diff --git a/absl/hash/hash.h b/absl/hash/hash.h
index d7386f6..5de132c 100644
--- a/absl/hash/hash.h
+++ b/absl/hash/hash.h
@@ -88,7 +88,6 @@
 //  * T is an arithmetic or pointer type
 //  * T defines an overload for `AbslHashValue(H, const T&)` for an arbitrary
 //    hash state `H`.
-//  - T defines a specialization of `HASH_NAMESPACE::hash<T>`
 //  - T defines a specialization of `std::hash<T>`
 //
 // `absl::Hash` intrinsically supports the following types:
@@ -128,8 +127,6 @@
 //   * Natively supported types out of the box (see above)
 //   * Types for which an `AbslHashValue()` overload is provided (such as
 //     user-defined types). See "Adding Type Support to `absl::Hash`" below.
-//   * Types which define a `HASH_NAMESPACE::hash<T>` specialization (aka
-//     `__gnu_cxx::hash<T>` for gcc/Clang or `stdext::hash<T>` for MSVC)
 //   * Types which define a `std::hash<T>` specialization
 //
 // The fallback to legacy hash functions exists mainly for backwards
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index 39ba24a..1d2e6cf 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -82,8 +82,8 @@
 }
 
 REGISTER_TYPED_TEST_CASE_P(HashValueIntTest, BasicUsage, FastPath);
-using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
-                                uint64_t, size_t>;
+using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
+                                uint32_t, uint64_t, size_t>;
 INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueIntTest, IntTypes);
 
 enum LegacyEnum { kValue1, kValue2, kValue3 };
@@ -819,8 +819,8 @@
 }
 
 REGISTER_TYPED_TEST_CASE_P(HashIntTest, BasicUsage);
-using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
-                                uint64_t, size_t>;
+using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
+                                uint32_t, uint64_t, size_t>;
 INSTANTIATE_TYPED_TEST_CASE_P(My, HashIntTest, IntTypes);
 
 struct StructWithPadding {
diff --git a/absl/hash/internal/city.cc b/absl/hash/internal/city.cc
index e122c18..58d4bcb 100644
--- a/absl/hash/internal/city.cc
+++ b/absl/hash/internal/city.cc
@@ -253,9 +253,8 @@
 
 // Return a 16-byte hash for 48 bytes.  Quick and dirty.
 // Callers do best to use "random-looking" values for a and b.
-static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(uint64_t w, uint64_t x,
-                                                        uint64_t y, uint64_t z,
-                                                        uint64_t a, uint64_t b) {
+static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(
+    uint64_t w, uint64_t x, uint64_t y, uint64_t z, uint64_t a, uint64_t b) {
   a += w;
   b = Rotate(b + a + z, 21);
   uint64_t c = a;
@@ -266,8 +265,9 @@
 }
 
 // Return a 16-byte hash for s[0] ... s[31], a, and b.  Quick and dirty.
-static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(const char *s, uint64_t a,
-                                                        uint64_t b) {
+static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(const char *s,
+                                                            uint64_t a,
+                                                            uint64_t b) {
   return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16),
                                 Fetch64(s + 24), a, b);
 }
@@ -310,8 +310,10 @@
   uint64_t x = Fetch64(s + len - 40);
   uint64_t y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
   uint64_t z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
-  std::pair<uint64_t, uint64_t> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
-  std::pair<uint64_t, uint64_t> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
+  std::pair<uint64_t, uint64_t> v =
+      WeakHashLen32WithSeeds(s + len - 64, len, z);
+  std::pair<uint64_t, uint64_t> w =
+      WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
   x = x * k1 + Fetch64(s);
 
   // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
@@ -337,7 +339,7 @@
 }
 
 uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
-                           uint64_t seed1) {
+                             uint64_t seed1) {
   return HashLen16(CityHash64(s, len) - seed0, seed1);
 }
 
diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h
index 161c774..9c1e7a5 100644
--- a/absl/hash/internal/city.h
+++ b/absl/hash/internal/city.h
@@ -71,7 +71,7 @@
 // Hash function for a byte array.  For convenience, two seeds are also
 // hashed into the result.
 uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
-                           uint64_t seed1);
+                             uint64_t seed1);
 
 // Hash function for a byte array.  Most useful in 32-bit binaries.
 uint32_t CityHash32(const char *s, size_t len);
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 9e608f7..b0132da 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -855,7 +855,14 @@
   // On other platforms this is still going to be non-deterministic but most
   // probably per-build and not per-process.
   ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() {
+#if (!defined(__clang__) || __clang_major__ > 11) && \
+    !defined(__apple_build_version__)
+    return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&kSeed));
+#else
+    // Workaround the absence of
+    // https://github.com/llvm/llvm-project/commit/bc15bf66dcca76cc06fe71fca35b74dc4d521021.
     return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(kSeed));
+#endif
   }
   static const void* const kSeed;
 
diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel
index 2ba9d7c..d2824a0 100644
--- a/absl/memory/BUILD.bazel
+++ b/absl/memory/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "memory",
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index 513f710..2b5ff62 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -420,6 +420,9 @@
 //
 // A C++11 compatible implementation of C++17's std::allocator_traits.
 //
+#if __cplusplus >= 201703L
+using std::allocator_traits;
+#else  // __cplusplus >= 201703L
 template <typename Alloc>
 struct allocator_traits {
   using allocator_type = Alloc;
@@ -609,6 +612,7 @@
     return a;
   }
 };
+#endif  // __cplusplus >= 201703L
 
 namespace memory_internal {
 
diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc
index 0d2e13b..1990c7b 100644
--- a/absl/memory/memory_test.cc
+++ b/absl/memory/memory_test.cc
@@ -555,7 +555,7 @@
   EXPECT_CALL(mock, deallocate(&x, 7));
 
   EXPECT_EQ(&x, Traits::allocate(mock, 7));
-  Traits::allocate(mock, 7, static_cast<const void*>(&hint));
+  static_cast<void>(Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
   EXPECT_EQ(&x, Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
   Traits::deallocate(mock, &x, 7);
 
diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel
index c06d2d9..5585fcc 100644
--- a/absl/meta/BUILD.bazel
+++ b/absl/meta/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "type_traits",
diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel
index da3af4d..f808f5d 100644
--- a/absl/numeric/BUILD.bazel
+++ b/absl/numeric/BUILD.bazel
@@ -22,7 +22,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "int128",
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index 000cc45..8485e28 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -30,7 +30,7 @@
     "//absl/random:__pkg__",
 ])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "traits",
diff --git a/absl/random/internal/BUILD.gn b/absl/random/internal/BUILD.gn
index 3940946..b97592c 100644
--- a/absl/random/internal/BUILD.gn
+++ b/absl/random/internal/BUILD.gn
@@ -155,7 +155,10 @@
     "randen_traits.h",
   ]
   sources = [ "randen_round_keys.cc" ]
-  deps = [ "//third_party/abseil-cpp/absl/base:config" ]
+  deps = [
+    "//build:chromeos_buildflags",
+    "//third_party/abseil-cpp/absl/base:config",
+  ]
 }
 
 absl_source_set("randen") {
diff --git a/absl/random/internal/gaussian_distribution_gentables.cc b/absl/random/internal/gaussian_distribution_gentables.cc
index a2bf039..a95333d 100644
--- a/absl/random/internal/gaussian_distribution_gentables.cc
+++ b/absl/random/internal/gaussian_distribution_gentables.cc
@@ -111,12 +111,9 @@
          "\n"
          "#include \"absl/random/gaussian_distribution.h\"\n"
          "\n"
-         // "namespace " and "absl" are broken apart so as not to conflict with
-         // script that adds the LTS inline namespace.
-         "namespace "
-         "absl {\n"
-         "namespace "
-         "random_internal {\n"
+         "namespace absl {\n"
+         "ABSL_NAMESPACE_BEGIN\n"
+         "namespace random_internal {\n"
          "\n"
          "const gaussian_distribution_base::Tables\n"
          "    gaussian_distribution_base::zg_ = {\n";
@@ -125,10 +122,9 @@
   FormatArrayContents(os, tables_.f);
   *os << "};\n"
          "\n"
-         "}  // namespace "
-         "random_internal\n"
-         "}  // namespace "
-         "absl\n"
+         "}  // namespace random_internal\n"
+         "ABSL_NAMESPACE_END\n"
+         "}  // namespace absl\n"
          "\n"
          "// clang-format on\n"
          "// END GENERATED CODE";
diff --git a/absl/random/internal/generate_real_test.cc b/absl/random/internal/generate_real_test.cc
index aa02f0c..4bdc453 100644
--- a/absl/random/internal/generate_real_test.cc
+++ b/absl/random/internal/generate_real_test.cc
@@ -419,8 +419,8 @@
   };
 
   // Rely on RandU64ToFloat generating values from greatest to least when
-  // supplied with uint64_t values from greatest (0xfff...) to least (0x0).  Thus,
-  // this algorithm stores the previous value, and if the new value is at
+  // supplied with uint64_t values from greatest (0xfff...) to least (0x0).
+  // Thus, this algorithm stores the previous value, and if the new value is at
   // greater than or equal to the previous value, then there is a collision in
   // the generation algorithm.
   //
diff --git a/absl/random/internal/randen_detect.cc b/absl/random/internal/randen_detect.cc
index d63230c..bbe7b96 100644
--- a/absl/random/internal/randen_detect.cc
+++ b/absl/random/internal/randen_detect.cc
@@ -1,13 +1,13 @@
 // Copyright 2017 The Abseil Authors.
 //
-// Licensed under the Apache License, Version 2.0 (the"License");
+// 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,
+// 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.
diff --git a/absl/status/BUILD.bazel b/absl/status/BUILD.bazel
index d164252..189bd73 100644
--- a/absl/status/BUILD.bazel
+++ b/absl/status/BUILD.bazel
@@ -26,11 +26,12 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "status",
     srcs = [
+        "internal/status_internal.h",
         "status.cc",
         "status_payload_printer.cc",
     ],
@@ -64,3 +65,39 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "statusor",
+    srcs = [
+        "internal/statusor_internal.h",
+        "statusor.cc",
+    ],
+    hdrs = [
+        "statusor.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        ":status",
+        "//absl/base:core_headers",
+        "//absl/base:raw_logging_internal",
+        "//absl/meta:type_traits",
+        "//absl/strings",
+        "//absl/types:variant",
+        "//absl/utility",
+    ],
+)
+
+cc_test(
+    name = "statusor_test",
+    size = "small",
+    srcs = ["statusor_test.cc"],
+    deps = [
+        ":status",
+        ":statusor",
+        "//absl/base",
+        "//absl/memory",
+        "//absl/types:any",
+        "//absl/utility",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/status/BUILD.gn b/absl/status/BUILD.gn
index 38dbbfc..740fb19 100644
--- a/absl/status/BUILD.gn
+++ b/absl/status/BUILD.gn
@@ -10,6 +10,7 @@
     "status_payload_printer.h",
   ]
   sources = [
+    "internal/status_internal.h",
     "status.cc",
     "status_payload_printer.cc",
   ]
@@ -27,3 +28,23 @@
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 }
+
+absl_source_set("statusor") {
+  public = [
+    "statusor.h",
+  ]
+  sources = [
+    "internal/statusor_internal.h",
+    "statusor.cc",
+  ]
+  deps = [
+    ":status",
+    "//third_party/abseil-cpp/absl/base:core_headers",
+    "//third_party/abseil-cpp/absl/base:raw_logging_internal",
+    "//third_party/abseil-cpp/absl/meta:type_traits",
+    "//third_party/abseil-cpp/absl/strings",
+    "//third_party/abseil-cpp/absl/types:variant",
+    "//third_party/abseil-cpp/absl/utility",
+  ]
+}
+
diff --git a/absl/status/CMakeLists.txt b/absl/status/CMakeLists.txt
index c041d69..f0d798a 100644
--- a/absl/status/CMakeLists.txt
+++ b/absl/status/CMakeLists.txt
@@ -19,6 +19,7 @@
   HDRS
     "status.h"
   SRCS
+    "internal/status_internal.h"
     "status.cc"
     "status_payload_printer.h"
     "status_payload_printer.cc"
@@ -51,3 +52,37 @@
     absl::strings
     gmock_main
 )
+
+absl_cc_library(
+  NAME
+    statusor
+  HDRS
+    "statusor.h"
+  SRCS
+    "statusor.cc"
+    "internal/statusor_internal.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::status
+    absl::core_headers
+    absl::raw_logging_internal
+    absl::type_traits
+    absl::strings
+    absl::utility
+    absl::variant
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    statusor_test
+  SRCS
+   "statusor_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::status
+    absl::statusor
+    gmock_main
+)
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h
new file mode 100644
index 0000000..1f82b8e
--- /dev/null
+++ b/absl/status/internal/status_internal.h
@@ -0,0 +1,51 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
+#define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
+
+#include <string>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/cord.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+enum class StatusCode : int;
+
+namespace status_internal {
+
+// Container for status payloads.
+struct Payload {
+  std::string type_url;
+  absl::Cord payload;
+};
+
+using Payloads = absl::InlinedVector<Payload, 1>;
+
+// Reference-counted representation of Status data.
+struct StatusRep {
+  std::atomic<int32_t> ref;
+  absl::StatusCode code;
+  std::string message;
+  std::unique_ptr<status_internal::Payloads> payloads;
+};
+
+absl::StatusCode MapToLocalCode(int value);
+}  // namespace status_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
diff --git a/absl/status/internal/statusor_internal.h b/absl/status/internal/statusor_internal.h
new file mode 100644
index 0000000..7cc7625
--- /dev/null
+++ b/absl/status/internal/statusor_internal.h
@@ -0,0 +1,399 @@
+// 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.
+#ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
+#define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/meta/type_traits.h"
+#include "absl/status/status.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+template <typename T>
+class ABSL_MUST_USE_RESULT StatusOr;
+
+namespace internal_statusor {
+
+// Detects whether `U` has conversion operator to `StatusOr<T>`, i.e. `operator
+// StatusOr<T>()`.
+template <typename T, typename U, typename = void>
+struct HasConversionOperatorToStatusOr : std::false_type {};
+
+template <typename T, typename U>
+void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
+
+template <typename T, typename U>
+struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
+    : std::true_type {};
+
+// Detects whether `T` is constructible or convertible from `StatusOr<U>`.
+template <typename T, typename U>
+using IsConstructibleOrConvertibleFromStatusOr =
+    absl::disjunction<std::is_constructible<T, StatusOr<U>&>,
+                      std::is_constructible<T, const StatusOr<U>&>,
+                      std::is_constructible<T, StatusOr<U>&&>,
+                      std::is_constructible<T, const StatusOr<U>&&>,
+                      std::is_convertible<StatusOr<U>&, T>,
+                      std::is_convertible<const StatusOr<U>&, T>,
+                      std::is_convertible<StatusOr<U>&&, T>,
+                      std::is_convertible<const StatusOr<U>&&, T>>;
+
+// Detects whether `T` is constructible or convertible or assignable from
+// `StatusOr<U>`.
+template <typename T, typename U>
+using IsConstructibleOrConvertibleOrAssignableFromStatusOr =
+    absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
+                      std::is_assignable<T&, StatusOr<U>&>,
+                      std::is_assignable<T&, const StatusOr<U>&>,
+                      std::is_assignable<T&, StatusOr<U>&&>,
+                      std::is_assignable<T&, const StatusOr<U>&&>>;
+
+// Detects whether direct initializing `StatusOr<T>` from `U` is ambiguous, i.e.
+// when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`.
+template <typename T, typename U>
+struct IsDirectInitializationAmbiguous
+    : public absl::conditional_t<
+          std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                       U>::value,
+          std::false_type,
+          IsDirectInitializationAmbiguous<
+              T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+template <typename T, typename V>
+struct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>>
+    : public IsConstructibleOrConvertibleFromStatusOr<T, V> {};
+
+// Checks against the constraints of the direction initialization, i.e. when
+// `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution.
+template <typename T, typename U>
+using IsDirectInitializationValid = absl::disjunction<
+    // Short circuits if T is basically U.
+    std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+    absl::negation<absl::disjunction<
+        std::is_same<absl::StatusOr<T>,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::Status,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::in_place_t,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        IsDirectInitializationAmbiguous<T, U>>>>;
+
+// This trait detects whether `StatusOr<T>::operator=(U&&)` is ambiguous, which
+// is equivalent to whether all the following conditions are met:
+// 1. `U` is `StatusOr<V>`.
+// 2. `T` is constructible and assignable from `V`.
+// 3. `T` is constructible and assignable from `U` (i.e. `StatusOr<V>`).
+// For example, the following code is considered ambiguous:
+// (`T` is `bool`, `U` is `StatusOr<bool>`, `V` is `bool`)
+//   StatusOr<bool> s1 = true;  // s1.ok() && s1.ValueOrDie() == true
+//   StatusOr<bool> s2 = false;  // s2.ok() && s2.ValueOrDie() == false
+//   s1 = s2;  // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`?
+template <typename T, typename U>
+struct IsForwardingAssignmentAmbiguous
+    : public absl::conditional_t<
+          std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                       U>::value,
+          std::false_type,
+          IsForwardingAssignmentAmbiguous<
+              T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+template <typename T, typename U>
+struct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>>
+    : public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {};
+
+// Checks against the constraints of the forwarding assignment, i.e. whether
+// `StatusOr<T>::operator(U&&)` should participate in overload resolution.
+template <typename T, typename U>
+using IsForwardingAssignmentValid = absl::disjunction<
+    // Short circuits if T is basically U.
+    std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+    absl::negation<absl::disjunction<
+        std::is_same<absl::StatusOr<T>,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::Status,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::in_place_t,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        IsForwardingAssignmentAmbiguous<T, U>>>>;
+
+class Helper {
+ public:
+  // Move type-agnostic error handling to the .cc.
+  static void HandleInvalidStatusCtorArg(Status*);
+  static void Crash(const absl::Status& status);
+};
+
+// Construct an instance of T in `p` through placement new, passing Args... to
+// the constructor.
+// This abstraction is here mostly for the gcc performance fix.
+template <typename T, typename... Args>
+void PlacementNew(void* p, Args&&... args) {
+#if defined(__GNUC__) && !defined(__clang__)
+  // Teach gcc that 'p' cannot be null, fixing code size issues.
+  if (p == nullptr) __builtin_unreachable();
+#endif
+  new (p) T(std::forward<Args>(args)...);
+}
+
+// Helper base class to hold the data and all operations.
+// We move all this to a base class to allow mixing with the appropriate
+// TraitsBase specialization.
+template <typename T>
+class StatusOrData {
+  template <typename U>
+  friend class StatusOrData;
+
+ public:
+  StatusOrData() = delete;
+
+  StatusOrData(const StatusOrData& other) {
+    if (other.ok()) {
+      MakeValue(other.data_);
+      MakeStatus();
+    } else {
+      MakeStatus(other.status_);
+    }
+  }
+
+  StatusOrData(StatusOrData&& other) noexcept {
+    if (other.ok()) {
+      MakeValue(std::move(other.data_));
+      MakeStatus();
+    } else {
+      MakeStatus(std::move(other.status_));
+    }
+  }
+
+  template <typename U>
+  explicit StatusOrData(const StatusOrData<U>& other) {
+    if (other.ok()) {
+      MakeValue(other.data_);
+      MakeStatus();
+    } else {
+      MakeStatus(other.status_);
+    }
+  }
+
+  template <typename U>
+  explicit StatusOrData(StatusOrData<U>&& other) {
+    if (other.ok()) {
+      MakeValue(std::move(other.data_));
+      MakeStatus();
+    } else {
+      MakeStatus(std::move(other.status_));
+    }
+  }
+
+  template <typename... Args>
+  explicit StatusOrData(absl::in_place_t, Args&&... args)
+      : data_(std::forward<Args>(args)...) {
+    MakeStatus();
+  }
+
+  explicit StatusOrData(const T& value) : data_(value) {
+    MakeStatus();
+  }
+  explicit StatusOrData(T&& value) : data_(std::move(value)) {
+    MakeStatus();
+  }
+
+  template <typename U,
+            absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
+                              int> = 0>
+  explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
+    EnsureNotOk();
+  }
+
+  StatusOrData& operator=(const StatusOrData& other) {
+    if (this == &other) return *this;
+    if (other.ok())
+      Assign(other.data_);
+    else
+      AssignStatus(other.status_);
+    return *this;
+  }
+
+  StatusOrData& operator=(StatusOrData&& other) {
+    if (this == &other) return *this;
+    if (other.ok())
+      Assign(std::move(other.data_));
+    else
+      AssignStatus(std::move(other.status_));
+    return *this;
+  }
+
+  ~StatusOrData() {
+    if (ok()) {
+      status_.~Status();
+      data_.~T();
+    } else {
+      status_.~Status();
+    }
+  }
+
+  template <typename U>
+  void Assign(U&& value) {
+    if (ok()) {
+      data_ = std::forward<U>(value);
+    } else {
+      MakeValue(std::forward<U>(value));
+      status_ = OkStatus();
+    }
+  }
+
+  template <typename U>
+  void AssignStatus(U&& v) {
+    Clear();
+    status_ = static_cast<absl::Status>(std::forward<U>(v));
+    EnsureNotOk();
+  }
+
+  bool ok() const { return status_.ok(); }
+
+ protected:
+  // status_ will always be active after the constructor.
+  // We make it a union to be able to initialize exactly how we need without
+  // waste.
+  // Eg. in the copy constructor we use the default constructor of Status in
+  // the ok() path to avoid an extra Ref call.
+  union {
+    Status status_;
+  };
+
+  // data_ is active iff status_.ok()==true
+  struct Dummy {};
+  union {
+    // When T is const, we need some non-const object we can cast to void* for
+    // the placement new. dummy_ is that object.
+    Dummy dummy_;
+    T data_;
+  };
+
+  void Clear() {
+    if (ok()) data_.~T();
+  }
+
+  void EnsureOk() const {
+    if (ABSL_PREDICT_FALSE(!ok())) Helper::Crash(status_);
+  }
+
+  void EnsureNotOk() {
+    if (ABSL_PREDICT_FALSE(ok())) Helper::HandleInvalidStatusCtorArg(&status_);
+  }
+
+  // Construct the value (ie. data_) through placement new with the passed
+  // argument.
+  template <typename... Arg>
+  void MakeValue(Arg&&... arg) {
+    internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)...);
+  }
+
+  // Construct the status (ie. status_) through placement new with the passed
+  // argument.
+  template <typename... Args>
+  void MakeStatus(Args&&... args) {
+    internal_statusor::PlacementNew<Status>(&status_,
+                                            std::forward<Args>(args)...);
+  }
+};
+
+// Helper base classes to allow implicitly deleted constructors and assignment
+// operators in `StatusOr`. For example, `CopyCtorBase` will explicitly delete
+// the copy constructor when T is not copy constructible and `StatusOr` will
+// inherit that behavior implicitly.
+template <typename T, bool = std::is_copy_constructible<T>::value>
+struct CopyCtorBase {
+  CopyCtorBase() = default;
+  CopyCtorBase(const CopyCtorBase&) = default;
+  CopyCtorBase(CopyCtorBase&&) = default;
+  CopyCtorBase& operator=(const CopyCtorBase&) = default;
+  CopyCtorBase& operator=(CopyCtorBase&&) = default;
+};
+
+template <typename T>
+struct CopyCtorBase<T, false> {
+  CopyCtorBase() = default;
+  CopyCtorBase(const CopyCtorBase&) = delete;
+  CopyCtorBase(CopyCtorBase&&) = default;
+  CopyCtorBase& operator=(const CopyCtorBase&) = default;
+  CopyCtorBase& operator=(CopyCtorBase&&) = default;
+};
+
+template <typename T, bool = std::is_move_constructible<T>::value>
+struct MoveCtorBase {
+  MoveCtorBase() = default;
+  MoveCtorBase(const MoveCtorBase&) = default;
+  MoveCtorBase(MoveCtorBase&&) = default;
+  MoveCtorBase& operator=(const MoveCtorBase&) = default;
+  MoveCtorBase& operator=(MoveCtorBase&&) = default;
+};
+
+template <typename T>
+struct MoveCtorBase<T, false> {
+  MoveCtorBase() = default;
+  MoveCtorBase(const MoveCtorBase&) = default;
+  MoveCtorBase(MoveCtorBase&&) = delete;
+  MoveCtorBase& operator=(const MoveCtorBase&) = default;
+  MoveCtorBase& operator=(MoveCtorBase&&) = default;
+};
+
+template <typename T, bool = std::is_copy_constructible<T>::value&&
+                          std::is_copy_assignable<T>::value>
+struct CopyAssignBase {
+  CopyAssignBase() = default;
+  CopyAssignBase(const CopyAssignBase&) = default;
+  CopyAssignBase(CopyAssignBase&&) = default;
+  CopyAssignBase& operator=(const CopyAssignBase&) = default;
+  CopyAssignBase& operator=(CopyAssignBase&&) = default;
+};
+
+template <typename T>
+struct CopyAssignBase<T, false> {
+  CopyAssignBase() = default;
+  CopyAssignBase(const CopyAssignBase&) = default;
+  CopyAssignBase(CopyAssignBase&&) = default;
+  CopyAssignBase& operator=(const CopyAssignBase&) = delete;
+  CopyAssignBase& operator=(CopyAssignBase&&) = default;
+};
+
+template <typename T, bool = std::is_move_constructible<T>::value&&
+                          std::is_move_assignable<T>::value>
+struct MoveAssignBase {
+  MoveAssignBase() = default;
+  MoveAssignBase(const MoveAssignBase&) = default;
+  MoveAssignBase(MoveAssignBase&&) = default;
+  MoveAssignBase& operator=(const MoveAssignBase&) = default;
+  MoveAssignBase& operator=(MoveAssignBase&&) = default;
+};
+
+template <typename T>
+struct MoveAssignBase<T, false> {
+  MoveAssignBase() = default;
+  MoveAssignBase(const MoveAssignBase&) = default;
+  MoveAssignBase(MoveAssignBase&&) = default;
+  MoveAssignBase& operator=(const MoveAssignBase&) = default;
+  MoveAssignBase& operator=(MoveAssignBase&&) = delete;
+};
+
+ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status);
+
+}  // namespace internal_statusor
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
diff --git a/absl/status/status.cc b/absl/status/status.cc
index 0a65573..a27fd8b 100644
--- a/absl/status/status.cc
+++ b/absl/status/status.cc
@@ -78,7 +78,7 @@
                                  absl::string_view type_url) {
   if (payloads == nullptr) return -1;
 
-  for (int i = 0; i < payloads->size(); ++i) {
+  for (size_t i = 0; i < payloads->size(); ++i) {
     if ((*payloads)[i].type_url == type_url) return i;
   }
 
@@ -167,7 +167,7 @@
     bool in_reverse =
         payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6;
 
-    for (int index = 0; index < payloads->size(); ++index) {
+    for (size_t index = 0; index < payloads->size(); ++index) {
       const auto& elem =
           (*payloads)[in_reverse ? payloads->size() - 1 - index : index];
 
diff --git a/absl/status/status.h b/absl/status/status.h
index 4253062..c4d6fce 100644
--- a/absl/status/status.h
+++ b/absl/status/status.h
@@ -11,6 +11,43 @@
 // 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: status.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the Abseil `status` library, consisting of:
+//
+//   * An `absl::Status` class for holding error handling information
+//   * A set of canonical `absl::StatusCode` error codes, and associated
+//     utilities for generating and propagating status codes.
+//   * A set of helper functions for creating status codes and checking their
+//     values
+//
+// Within Google, `absl::Status` is the primary mechanism for gracefully
+// handling errors across API boundaries (and in particular across RPC
+// boundaries). Some of these errors may be recoverable, but others may not.
+// Most functions that can produce a recoverable error should be designed to
+// return an `absl::Status` (or `absl::StatusOr`).
+//
+// Example:
+//
+// absl::Status myFunction(absl::string_view fname, ...) {
+//   ...
+//   // encounter error
+//   if (error condition) {
+//     return absl::InvalidArgumentError("bad mode");
+//   }
+//   // else, return OK
+//   return absl::OkStatus();
+// }
+//
+// An `absl::Status` is designed to either return "OK" or one of a number of
+// different error codes, corresponding to typical error conditions.
+// In almost all cases, when using `absl::Status` you should use the canonical
+// error codes (of type `absl::StatusCode`) enumerated in this header file.
+// These canonical codes are understood across the codebase and will be
+// accepted across all API and RPC boundaries.
 #ifndef ABSL_STATUS_STATUS_H_
 #define ABSL_STATUS_STATUS_H_
 
@@ -18,78 +55,132 @@
 #include <string>
 
 #include "absl/container/inlined_vector.h"
+#include "absl/status/internal/status_internal.h"
 #include "absl/strings/cord.h"
 #include "absl/types/optional.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-// Sometimes multiple error codes may apply.  Services should return
-// the most specific error code that applies.  For example, prefer
-// `kOutOfRange` over `kFailedPrecondition` if both codes apply.
-// Similarly prefer `kNotFound` or `kAlreadyExists` over `kFailedPrecondition`.
+// absl::StatusCode
+//
+// An `absl::StatusCode` is an enumerated type indicating either no error ("OK")
+// or an error condition. In most cases, an `absl::Status` indicates a
+// recoverable error, and the purpose of signalling an error is to indicate what
+// action to take in response to that error. These error codes map to the proto
+// RPC error codes indicated in https://cloud.google.com/apis/design/errors.
+//
+// The errors listed below are the canonical errors associated with
+// `absl::Status` and are used throughout the codebase. As a result, these
+// error codes are somewhat generic.
+//
+// In general, try to return the most specific error that applies if more than
+// one error may pertain. For example, prefer `kOutOfRange` over
+// `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or
+// `kAlreadyExists` over `kFailedPrecondition`.
+//
+// Because these errors may travel RPC boundaries, these codes are tied to the
+// `google.rpc.Code` definitions within
+// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
+// The string value of these RPC codes is denoted within each enum below.
+//
+// If your error handling code requires more context, you can attach payloads
+// to your status. See `absl::Status::SetPayload()` and
+// `absl::Status::GetPayload()` below.
 enum class StatusCode : int {
-  // Not an error; returned on success
+  // StatusCode::kOk
+  //
+  // kOK (gRPC code "OK") does not indicate an error; this value is returned on
+  // success. It is typical to check for this value before proceeding on any
+  // given call across an API or RPC boundary. To check this value, use the
+  // `absl::Status::ok()` member function rather than inspecting the raw code.
   kOk = 0,
 
-  // The operation was cancelled, typically by the caller.
+  // StatusCode::kCancelled
+  //
+  // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled,
+  // typically by the caller.
   kCancelled = 1,
 
-  // Unknown error. For example, errors raised by APIs that do not return
-  // enough error information may be converted to this error.
+  // StatusCode::kUnknown
+  //
+  // kUnknown (gRPC code "UNKNOWN") indicates an unknown error occurred. In
+  // general, more specific errors should be raised, if possible. Errors raised
+  // by APIs that do not return enough error information may be converted to
+  // this error.
   kUnknown = 2,
 
-  // The client specified an invalid argument. Note that this differs
-  // from `kFailedPrecondition`. `kInvalidArgument` indicates arguments
-  // that are problematic regardless of the state of the system
-  // (such as a malformed file name).
+  // StatusCode::kInvalidArgument
+  //
+  // kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller
+  // specified an invalid argument, such a malformed filename. Note that such
+  // errors should be narrowly limited to indicate to the invalid nature of the
+  // arguments themselves. Errors with validly formed arguments that may cause
+  // errors with the state of the receiving system should be denoted with
+  // `kFailedPrecondition` instead.
   kInvalidArgument = 3,
 
-  // The deadline expired before the operation could complete. For operations
-  // that change the state of the system, this error may be returned
-  // even if the operation has completed successfully. For example, a
-  // successful response from a server could have been delayed long
-  // enough for the deadline to expire.
+  // StatusCode::kDeadlineExceeded
+  //
+  // kDeadlineExceeded (gRPC code "DEADLINE_EXCEEDED") indicates a deadline
+  // expired before the operation could complete. For operations that may change
+  // state within a system, this error may be returned even if the operation has
+  // completed successfully. For example, a successful response from a server
+  // could have been delayed long enough for the deadline to expire.
   kDeadlineExceeded = 4,
 
-  // Some requested entity (such as file or directory) was not found.
+  // StatusCode::kNotFound
   //
-  // Note to server developers: if a request is denied for an entire class
-  // of users, such as gradual feature rollout or undocumented whitelist,
-  // `kNotFound` may be used. If a request is denied for some users within
-  // a class of users, such as user-based access control, `kPermissionDenied`
-  // must be used.
+  // kNotFound (gRPC code "NOT_FOUND") indicates some requested entity (such as
+  // a file or directory) was not found.
+  //
+  // `kNotFound` is useful if a request should be denied for an entire class of
+  // users, such as during a gradual feature rollout or undocumented allow list.
+  // If, instead, a request should be denied for specific sets of users, such as
+  // through user-based access control, use `kPermissionDenied` instead.
   kNotFound = 5,
 
-  // The entity that a client attempted to create (such as file or directory)
-  // already exists.
+  // StatusCode::kAlreadyExists
+  //
+  // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates the entity that a
+  // caller attempted to create (such as file or directory) is already present.
   kAlreadyExists = 6,
 
-  // The caller does not have permission to execute the specified
-  // operation. `kPermissionDenied` must not be used for rejections
-  // caused by exhausting some resource (use `kResourceExhausted`
-  // instead for those errors). `kPermissionDenied` must not be
-  // used if the caller can not be identified (use `kUnauthenticated`
-  // instead for those errors). This error code does not imply the
-  // request is valid or the requested entity exists or satisfies
-  // other pre-conditions.
+  // StatusCode::kPermissionDenied
+  //
+  // kPermissionDenied (gRPC code "PERMISSION_DENIED") indicates that the caller
+  // does not have permission to execute the specified operation. Note that this
+  // error is different than an error due to an *un*authenticated user. This
+  // error code does not imply the request is valid or the requested entity
+  // exists or satisfies any other pre-conditions.
+  //
+  // `kPermissionDenied` must not be used for rejections caused by exhausting
+  // some resource. Instead, use `kResourceExhausted` for those errors.
+  // `kPermissionDenied` must not be used if the caller cannot be identified.
+  // Instead, use `kUnauthenticated` for those errors.
   kPermissionDenied = 7,
 
-  // Some resource has been exhausted, perhaps a per-user quota, or
-  // perhaps the entire file system is out of space.
+  // StatusCode::kResourceExhausted
+  //
+  // kResourceExhausted (gRPC code "RESOURCE_EXHAUSTED") indicates some resource
+  // has been exhausted, perhaps a per-user quota, or perhaps the entire file
+  // system is out of space.
   kResourceExhausted = 8,
 
-  // The operation was rejected because the system is not in a state
-  // required for the operation's execution. For example, the directory
-  // to be deleted is non-empty, an rmdir operation is applied to
-  // a non-directory, etc.
+  // StatusCode::kFailedPrecondition
   //
-  // A litmus test that may help a service implementer in deciding
-  // between `kFailedPrecondition`, `kAborted`, and `kUnavailable`:
+  // kFailedPrecondition (gRPC code "FAILED_PRECONDITION") indicates that the
+  // operation was rejected because the system is not in a state required for
+  // the operation's execution. For example, a directory to be deleted may be
+  // non-empty, an "rmdir" operation is applied to a non-directory, etc.
+  //
+  // Some guidelines that may help a service implementer in deciding between
+  // `kFailedPrecondition`, `kAborted`, and `kUnavailable`:
+  //
   //  (a) Use `kUnavailable` if the client can retry just the failing call.
-  //  (b) Use `kAborted` if the client should retry at a higher-level
-  //      (such as when a client-specified test-and-set fails, indicating the
-  //      client should restart a read-modify-write sequence).
+  //  (b) Use `kAborted` if the client should retry at a higher transaction
+  //      level (such as when a client-specified test-and-set fails, indicating
+  //      the client should restart a read-modify-write sequence).
   //  (c) Use `kFailedPrecondition` if the client should not retry until
   //      the system state has been explicitly fixed. For example, if an "rmdir"
   //      fails because the directory is non-empty, `kFailedPrecondition`
@@ -97,15 +188,21 @@
   //      the files are deleted from the directory.
   kFailedPrecondition = 9,
 
-  // The operation was aborted, typically due to a concurrency issue such as
-  // a sequencer check failure or transaction abort.
+  // StatusCode::kAborted
   //
-  // See litmus test above for deciding between `kFailedPrecondition`,
+  // kAborted (gRPC code "ABORTED") indicates the operation was aborted,
+  // typically due to a concurrency issue such as a sequencer check failure or a
+  // failed transaction.
+  //
+  // See the guidelines above for deciding between `kFailedPrecondition`,
   // `kAborted`, and `kUnavailable`.
   kAborted = 10,
 
-  // The operation was attempted past the valid range, such as seeking or
-  // reading past end-of-file.
+  // StatusCode::kOutOfRange
+  //
+  // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was
+  // attempted past the valid range, such as seeking or reading past an
+  // end-of-file.
   //
   // Unlike `kInvalidArgument`, this error indicates a problem that may
   // be fixed if the system state changes. For example, a 32-bit file
@@ -121,175 +218,314 @@
   // they are done.
   kOutOfRange = 11,
 
-  // The operation is not implemented or is not supported/enabled in this
-  // service.
+  // StatusCode::kUnimplemented
+  //
+  // kUnimplemented (gRPC code "UNIMPLEMENTED") indicates the operation is not
+  // implemented or supported in this service. In this case, the operation
+  // should not be re-attempted.
   kUnimplemented = 12,
 
-  // Internal errors. This means that some invariants expected by the
-  // underlying system have been broken. This error code is reserved
-  // for serious errors.
+  // StatusCode::kInternal
+  //
+  // kInternal (gRPC code "INTERNAL") indicates an internal error has occurred
+  // and some invariants expected by the underlying system have not been
+  // satisfied. This error code is reserved for serious errors.
   kInternal = 13,
 
-  // The service is currently unavailable. This is most likely a
-  // transient condition, which can be corrected by retrying with
-  // a backoff. Note that it is not always safe to retry
-  // non-idempotent operations.
+  // StatusCode::kUnavailable
   //
-  // See litmus test above for deciding between `kFailedPrecondition`,
+  // kUnavailable (gRPC code "UNAVAILABLE") indicates the service is currently
+  // unavailable and that this is most likely a transient condition. An error
+  // such as this can be corrected by retrying with a backoff scheme. Note that
+  // it is not always safe to retry non-idempotent operations.
+  //
+  // See the guidelines above for deciding between `kFailedPrecondition`,
   // `kAborted`, and `kUnavailable`.
   kUnavailable = 14,
 
-  // Unrecoverable data loss or corruption.
+  // StatusCode::kDataLoss
+  //
+  // kDataLoss (gRPC code "DATA_LOSS") indicates that unrecoverable data loss or
+  // corruption has occurred. As this error is serious, proper alerting should
+  // be attached to errors such as this.
   kDataLoss = 15,
 
-  // The request does not have valid authentication credentials for the
-  // operation.
+  // StatusCode::kUnauthenticated
+  //
+  // kUnauthenticated (gRPC code "UNAUTHENTICATED") indicates that the request
+  // does not have valid authentication credentials for the operation. Correct
+  // the authentication and try again.
   kUnauthenticated = 16,
 
-  // An extra enum entry to prevent people from writing code that
-  // fails to compile when a new code is added.
+  // StatusCode::DoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_
   //
-  // Nobody should ever reference this enumeration entry. In particular,
-  // if you write C++ code that switches on this enumeration, add a default:
-  // case instead of a case that mentions this enumeration entry.
+  // NOTE: this error code entry should not be used and you should not rely on
+  // its value, which may change.
   //
-  // Nobody should rely on the value (currently 20) listed here.  It
-  // may change in the future.
+  // The purpose of this enumerated value is to force people who handle status
+  // codes with `switch()` statements to *not* simply enumerate all possible
+  // values, but instead provide a "default:" case. Providing such a default
+  // case ensures that code will compile when new codes are added.
   kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20
 };
 
+// StatusCodeToString()
+//
 // Returns the name for the status code, or "" if it is an unknown value.
 std::string StatusCodeToString(StatusCode code);
 
+// operator<<
+//
 // Streams StatusCodeToString(code) to `os`.
 std::ostream& operator<<(std::ostream& os, StatusCode code);
 
-namespace status_internal {
-
-// Container for status payloads.
-struct Payload {
-  std::string type_url;
-  absl::Cord payload;
-};
-
-using Payloads = absl::InlinedVector<Payload, 1>;
-
-// Reference-counted representation of Status data.
-struct StatusRep {
-  std::atomic<int32_t> ref;
-  absl::StatusCode code;
-  std::string message;
-  std::unique_ptr<status_internal::Payloads> payloads;
-};
-
-absl::StatusCode MapToLocalCode(int value);
-}  // namespace status_internal
-
+// absl::Status
+//
+// The `absl::Status` class is generally used to gracefully handle errors
+// across API boundaries (and in particular across RPC boundaries). Some of
+// these errors may be recoverable, but others may not. Most
+// functions which can produce a recoverable error should be designed to return
+// either an `absl::Status` (or the similar `absl::StatusOr<T>`, which holds
+// either an object of type `T` or an error).
+//
+// API developers should construct their functions to return `absl::OkStatus()`
+// upon success, or an `absl::StatusCode` upon another type of error (e.g
+// an `absl::StatusCode::kInvalidArgument` error). The API provides convenience
+// functions to constuct each status code.
+//
+// Example:
+//
+// absl::Status myFunction(absl::string_view fname, ...) {
+//   ...
+//   // encounter error
+//   if (error condition) {
+//     // Construct an absl::StatusCode::kInvalidArgument error
+//     return absl::InvalidArgumentError("bad mode");
+//   }
+//   // else, return OK
+//   return absl::OkStatus();
+// }
+//
+// Users handling status error codes should prefer checking for an OK status
+// using the `ok()` member function. Handling multiple error codes may justify
+// use of switch statement, but only check for error codes you know how to
+// handle; do not try to exhaustively match against all canonical error codes.
+// Errors that cannot be handled should be logged and/or propagated for higher
+// levels to deal with. If you do use a switch statement, make sure that you
+// also provide a `default:` switch case, so that code does not break as other
+// canonical codes are added to the API.
+//
+// Example:
+//
+//   absl::Status result = DoSomething();
+//   if (!result.ok()) {
+//     LOG(ERROR) << result;
+//   }
+//
+//   // Provide a default if switching on multiple error codes
+//   switch (result.code()) {
+//     // The user hasn't authenticated. Ask them to reauth
+//     case absl::StatusCode::kUnauthenticated:
+//       DoReAuth();
+//       break;
+//     // The user does not have permission. Log an error.
+//     case absl::StatusCode::kPermissionDenied:
+//       LOG(ERROR) << result;
+//       break;
+//     // Propagate the error otherwise.
+//     default:
+//       return true;
+//   }
+//
+// An `absl::Status` can optionally include a payload with more information
+// about the error. Typically, this payload serves one of several purposes:
+//
+//   * It may provide more fine-grained semantic information about the error to
+//     facilitate actionable remedies.
+//   * It may provide human-readable contexual information that is more
+//     appropriate to display to an end user.
+//
+// Example:
+//
+//   absl::Status result = DoSomething();
+//   // Inform user to retry after 30 seconds
+//   // See more error details in googleapis/google/rpc/error_details.proto
+//   if (absl::IsResourceExhausted(result)) {
+//     google::rpc::RetryInfo info;
+//     info.retry_delay().seconds() = 30;
+//     // Payloads require a unique key (a URL to ensure no collisions with
+//     // other payloads), and an `absl::Cord` to hold the encoded data.
+//     absl::string_view url = "type.googleapis.com/google.rpc.RetryInfo";
+//     result.SetPayload(url, info.SerializeAsCord());
+//     return result;
+//   }
+//
 class ABSL_MUST_USE_RESULT Status final {
  public:
-  // Creates an OK status with no message or payload.
+  // Constructors
+
+  // This default constructor creates an OK status with no message or payload.
+  // Avoid this constructor and prefer explicit construction of an OK status
+  // with `absl::OkStatus()`.
   Status();
 
-  // Create a status in the canonical error space with the specified code and
-  // error message.  If `code == absl::StatusCode::kOk`, `msg` is ignored and an
-  // object identical to an OK status is constructed.
+  // Creates a status in the canonical error space with the specified
+  // `absl::StatusCode` and error message.  If `code == absl::StatusCode::kOk`,
+  // `msg` is ignored and an object identical to an OK status is constructed.
   //
-  // `msg` must be in UTF-8. The implementation may complain (e.g.,
+  // The `msg` string must be in UTF-8. The implementation may complain (e.g.,
   // by printing a warning) if it is not.
   Status(absl::StatusCode code, absl::string_view msg);
 
   Status(const Status&);
   Status& operator=(const Status& x);
 
-  // Move operations.
+  // Move operators
+
   // The moved-from state is valid but unspecified.
   Status(Status&&) noexcept;
   Status& operator=(Status&&);
 
   ~Status();
 
-  // If `this->ok()`, stores `new_status` into *this. If `!this->ok()`,
-  // preserves the current data. May, in the future, augment the current status
-  // with additional information about `new_status`.
+  // Status::Update()
   //
-  // Convenient way of keeping track of the first error encountered.
-  // Instead of:
-  //   if (overall_status.ok()) overall_status = new_status
-  // Use:
+  // Updates the existing status with `new_status` provided that `this->ok()`.
+  // If the existing status already contains a non-OK error, this update has no
+  // effect and preserves the current data. Note that this behavior may change
+  // in the future to augment a current non-ok status with additional
+  // information about `new_status`.
+  //
+  // `Update()` provides a convenient way of keeping track of the first error
+  // encountered.
+  //
+  // Example:
+  //   // Instead of "if (overall_status.ok()) overall_status = new_status"
   //   overall_status.Update(new_status);
   //
-  // Style guide exception for rvalue reference granted in CL 153567220.
   void Update(const Status& new_status);
   void Update(Status&& new_status);
 
-  // Returns true if the Status is OK.
+  // Status::ok()
+  //
+  // Returns `true` if `this->ok()`. Prefer checking for an OK status using this
+  // member function.
   ABSL_MUST_USE_RESULT bool ok() const;
 
-  // Returns the (canonical) error code.
+  // Status::code()
+  //
+  // Returns the canonical error code of type `absl::StatusCode` of this status.
   absl::StatusCode code() const;
 
-  // Returns the raw (canonical) error code which could be out of the range of
-  // the local `absl::StatusCode` enum. NOTE: This should only be called when
-  // converting to wire format. Use `code` for error handling.
+  // Status::raw_code()
+  //
+  // Returns a raw (canonical) error code corresponding to the enum value of
+  // `google.rpc.Code` definitions within
+  // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto.
+  // These values could be out of the range of canonical `absl::StatusCode`
+  // enum values.
+  //
+  // NOTE: This function should only be called when converting to an associated
+  // wire format. Use `Status::code()` for error handling.
   int raw_code() const;
 
-  // Returns the error message.  Note: prefer ToString() for debug logging.
-  // This message rarely describes the error code.  It is not unusual for the
-  // error message to be the empty string.
+  // Status::message()
+  //
+  // Returns the error message associated with this error code, if available.
+  // Note that this message rarely describes the error code.  It is not unusual
+  // for the error message to be the empty string. As a result, prefer
+  // `Status::ToString()` for debug logging.
   absl::string_view message() const;
 
   friend bool operator==(const Status&, const Status&);
   friend bool operator!=(const Status&, const Status&);
 
-  // Returns a combination of the error code name, the message and the payloads.
-  // You can expect the code name and the message to be substrings of the
-  // result, and the payloads to be printed by the registered printer extensions
-  // if they are recognized.
-  // WARNING: Do not depend on the exact format of the result of `ToString()`
-  // which is subject to change.
+  // Status::ToString()
+  //
+  // Returns a combination of the error code name, the message and any
+  // associated payload messages. This string is designed simply to be human
+  // readable and its exact format should not be load bearing. Do not depend on
+  // the exact format of the result of `ToString()` which is subject to change.
+  //
+  // The printed code name and the message are generally substrings of the
+  // result, and the payloads to be printed use the status payload printer
+  // mechanism (which is internal).
   std::string ToString() const;
 
+  // Status::IgnoreError()
+  //
   // Ignores any errors. This method does nothing except potentially suppress
   // complaints from any tools that are checking that errors are not dropped on
   // the floor.
   void IgnoreError() const;
 
-  // Swap the contents of `a` with `b`
+  // swap()
+  //
+  // Swap the contents of one status with another.
   friend void swap(Status& a, Status& b);
 
-  // Payload management APIs
+  //----------------------------------------------------------------------------
+  // Payload Management APIs
+  //----------------------------------------------------------------------------
 
-  // Type URL should be unique and follow the naming convention below:
-  // The idea of type URL comes from `google.protobuf.Any`
-  // (https://developers.google.com/protocol-buffers/docs/proto3#any). The
-  // type URL should be globally unique and follow the format of URL
-  // (https://en.wikipedia.org/wiki/URL). The default type URL for a given
-  // protobuf message type is "type.googleapis.com/packagename.messagename". For
-  // other custom wire formats, users should define the format of type URL in a
-  // similar practice so as to minimize the chance of conflict between type
-  // URLs. Users should make sure that the type URL can be mapped to a concrete
+  // A payload may be attached to a status to provide additional context to an
+  // error that may not be satisifed by an existing `absl::StatusCode`.
+  // Typically, this payload serves one of several purposes:
+  //
+  //   * It may provide more fine-grained semantic information about the error
+  //     to facilitate actionable remedies.
+  //   * It may provide human-readable contexual information that is more
+  //     appropriate to display to an end user.
+  //
+  // A payload consists of a [key,value] pair, where the key is a string
+  // referring to a unique "type URL" and the value is an object of type
+  // `absl::Cord` to hold the contextual data.
+  //
+  // The "type URL" should be unique and follow the format of a URL
+  // (https://en.wikipedia.org/wiki/URL) and, ideally, provide some
+  // documentation or schema on how to interpret its associated data. For
+  // example, the default type URL for a protobuf message type is
+  // "type.googleapis.com/packagename.messagename". Other custom wire formats
+  // should define the format of type URL in a similar practice so as to
+  // minimize the chance of conflict between type URLs.
+  // Users should ensure that the type URL can be mapped to a concrete
   // C++ type if they want to deserialize the payload and read it effectively.
+  //
+  // To attach a payload to a status object, call `Status::SetPayload()`,
+  // passing it the type URL and an `absl::Cord` of associated data. Similarly,
+  // to extract the payload from a status, call `Status::GetPayload()`. You
+  // may attach multiple payloads (with differing type URLs) to any given
+  // status object, provided that the status is currently exhibiting an error
+  // code (i.e. is not OK).
 
-  // Gets the payload based for `type_url` key, if it is present.
+  // Status::GetPayload()
+  //
+  // Gets the payload of a status given its unique `type_url` key, if present.
   absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const;
 
-  // Sets the payload for `type_url` key for a non-ok status, overwriting any
-  // existing payload for `type_url`.
+  // Status::SetPayload()
   //
-  // NOTE: Does nothing if the Status is ok.
+  // Sets the payload for a non-ok status using a `type_url` key, overwriting
+  // any existing payload for that `type_url`.
+  //
+  // NOTE: This function does nothing if the Status is ok.
   void SetPayload(absl::string_view type_url, absl::Cord payload);
 
-  // Erases the payload corresponding to the `type_url` key.  Returns true if
+  // Status::ErasePayload()
+  //
+  // Erases the payload corresponding to the `type_url` key.  Returns `true` if
   // the payload was present.
   bool ErasePayload(absl::string_view type_url);
 
-  // Iterates over the stored payloads and calls `visitor(type_key, payload)`
-  // for each one.
+  // Status::ForEachPayload()
   //
-  // NOTE: The order of calls to `visitor` is not specified and may change at
+  // Iterates over the stored payloads and calls the
+  // `visitor(type_key, payload)` callable for each one.
+  //
+  // NOTE: The order of calls to `visitor()` is not specified and may change at
   // any time.
   //
-  // NOTE: Any mutation on the same 'Status' object during visitation is
+  // NOTE: Any mutation on the same 'absl::Status' object during visitation is
   // forbidden and could result in undefined behavior.
   void ForEachPayload(
       const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
@@ -358,14 +594,93 @@
   uintptr_t rep_;
 };
 
-// Returns an OK status, equivalent to a default constructed instance.
+// OkStatus()
+//
+// Returns an OK status, equivalent to a default constructed instance. Prefer
+// usage of `absl::OkStatus()` when constructing such an OK status.
 Status OkStatus();
 
+// operator<<()
+//
 // Prints a human-readable representation of `x` to `os`.
 std::ostream& operator<<(std::ostream& os, const Status& x);
 
-// -----------------------------------------------------------------
+// IsAborted()
+// IsAlreadyExists()
+// IsCancelled()
+// IsDataLoss()
+// IsDeadlineExceeded()
+// IsFailedPrecondition()
+// IsInternal()
+// IsInvalidArgument()
+// IsNotFound()
+// IsOutOfRange()
+// IsPermissionDenied()
+// IsResourceExhausted()
+// IsUnauthenticated()
+// IsUnavailable()
+// IsUnimplemented()
+// IsUnknown()
+//
+// These convenience functions return `true` if a given status matches the
+// `absl::StatusCode` error code of its associated function.
+ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
+ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
+ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
+ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
+ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
+ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
+ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
+
+// AbortedError()
+// AlreadyExistsError()
+// CancelledError()
+// DataLossError()
+// DeadlineExceededError()
+// FailedPreconditionError()
+// InternalError()
+// InvalidArgumentError()
+// NotFoundError()
+// OutOfRangeError()
+// PermissionDeniedError()
+// ResourceExhaustedError()
+// UnauthenticatedError()
+// UnavailableError()
+// UnimplementedError()
+// UnknownError()
+//
+// These convenience functions create an `absl::Status` object with an error
+// code as indicated by the associated function name, using the error message
+// passed in `message`.
+Status AbortedError(absl::string_view message);
+Status AlreadyExistsError(absl::string_view message);
+Status CancelledError(absl::string_view message);
+Status DataLossError(absl::string_view message);
+Status DeadlineExceededError(absl::string_view message);
+Status FailedPreconditionError(absl::string_view message);
+Status InternalError(absl::string_view message);
+Status InvalidArgumentError(absl::string_view message);
+Status NotFoundError(absl::string_view message);
+Status OutOfRangeError(absl::string_view message);
+Status PermissionDeniedError(absl::string_view message);
+Status ResourceExhaustedError(absl::string_view message);
+Status UnauthenticatedError(absl::string_view message);
+Status UnavailableError(absl::string_view message);
+Status UnimplementedError(absl::string_view message);
+Status UnknownError(absl::string_view message);
+
+//------------------------------------------------------------------------------
 // Implementation details follow
+//------------------------------------------------------------------------------
 
 inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {}
 
@@ -491,50 +806,11 @@
 
 inline Status OkStatus() { return Status(); }
 
-// Each of the functions below creates a Status object with a particular error
-// code and the given message. The error code of the returned status object
-// matches the name of the function.
-Status AbortedError(absl::string_view message);
-Status AlreadyExistsError(absl::string_view message);
-Status CancelledError(absl::string_view message);
-Status DataLossError(absl::string_view message);
-Status DeadlineExceededError(absl::string_view message);
-Status FailedPreconditionError(absl::string_view message);
-Status InternalError(absl::string_view message);
-Status InvalidArgumentError(absl::string_view message);
-Status NotFoundError(absl::string_view message);
-Status OutOfRangeError(absl::string_view message);
-Status PermissionDeniedError(absl::string_view message);
-Status ResourceExhaustedError(absl::string_view message);
-Status UnauthenticatedError(absl::string_view message);
-Status UnavailableError(absl::string_view message);
-Status UnimplementedError(absl::string_view message);
-Status UnknownError(absl::string_view message);
-
 // Creates a `Status` object with the `absl::StatusCode::kCancelled` error code
 // and an empty message. It is provided only for efficiency, given that
 // message-less kCancelled errors are common in the infrastructure.
 inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }
 
-// Each of the functions below returns true if the given status matches the
-// error code implied by the function's name.
-ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
-ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
-ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
-ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
-ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
-ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
-ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
-ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
-ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
-ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
-ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
-ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
-ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
-
 ABSL_NAMESPACE_END
 }  // namespace absl
 
diff --git a/absl/status/statusor.cc b/absl/status/statusor.cc
new file mode 100644
index 0000000..b954b45
--- /dev/null
+++ b/absl/status/statusor.cc
@@ -0,0 +1,71 @@
+// 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/status/statusor.h"
+
+#include <cstdlib>
+#include <utility>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+BadStatusOrAccess::BadStatusOrAccess(absl::Status status)
+    : status_(std::move(status)) {}
+
+BadStatusOrAccess::~BadStatusOrAccess() = default;
+const char* BadStatusOrAccess::what() const noexcept {
+  return "Bad StatusOr access";
+}
+
+const absl::Status& BadStatusOrAccess::status() const { return status_; }
+
+namespace internal_statusor {
+
+void Helper::HandleInvalidStatusCtorArg(absl::Status* status) {
+  const char* kMessage =
+      "An OK status is not a valid constructor argument to StatusOr<T>";
+#ifdef NDEBUG
+  ABSL_INTERNAL_LOG(ERROR, kMessage);
+#else
+  ABSL_INTERNAL_LOG(FATAL, kMessage);
+#endif
+  // In optimized builds, we will fall back to InternalError.
+  *status = absl::InternalError(kMessage);
+}
+
+void Helper::Crash(const absl::Status& status) {
+  ABSL_INTERNAL_LOG(
+      FATAL,
+      absl::StrCat("Attempting to fetch value instead of handling error ",
+                   status.ToString()));
+}
+
+void ThrowBadStatusOrAccess(absl::Status status) {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  throw absl::BadStatusOrAccess(std::move(status));
+#else
+  ABSL_INTERNAL_LOG(
+      FATAL,
+      absl::StrCat("Attempting to fetch value instead of handling error ",
+                   status.ToString()));
+  std::abort();
+#endif
+}
+
+}  // namespace internal_statusor
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/status/statusor.h b/absl/status/statusor.h
new file mode 100644
index 0000000..469d486
--- /dev/null
+++ b/absl/status/statusor.h
@@ -0,0 +1,760 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: statusor.h
+// -----------------------------------------------------------------------------
+//
+// An `absl::StatusOr<T>` represents a union of an `absl::Status` object
+// and an object of type `T`. The `absl::StatusOr<T>` will either contain an
+// object of type `T` (indicating a successful operation), or an error (of type
+// `absl::Status`) explaining why such a value is not present.
+//
+// In general, check the success of an operation returning an
+// `absl::StatusOr<T>` like you would an `absl::Status` by using the `ok()`
+// member function.
+//
+// Example:
+//
+//   StatusOr<Foo> result = Calculation();
+//   if (result.ok()) {
+//     result->DoSomethingCool();
+//   } else {
+//     LOG(ERROR) << result.status();
+//   }
+#ifndef ABSL_STATUS_STATUSOR_H_
+#define ABSL_STATUS_STATUSOR_H_
+
+#include <exception>
+#include <initializer_list>
+#include <new>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+#include "absl/status/internal/statusor_internal.h"
+#include "absl/status/status.h"
+#include "absl/types/variant.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// BadStatusOrAccess
+//
+// This class defines the type of object to throw (if exceptions are enabled),
+// when accessing the value of an `absl::StatusOr<T>` object that does not
+// contain a value. This behavior is analogous to that of
+// `std::bad_optional_access` in the case of accessing an invalid
+// `std::optional` value.
+//
+// Example:
+//
+// try {
+//   absl::StatusOr<int> v = FetchInt();
+//   DoWork(v.value());  // Accessing value() when not "OK" may throw
+// } catch (absl::BadStatusOrAccess& ex) {
+//   LOG(ERROR) << ex.status();
+// }
+class BadStatusOrAccess : public std::exception {
+ public:
+  explicit BadStatusOrAccess(absl::Status status);
+  ~BadStatusOrAccess() override;
+
+  // BadStatusOrAccess::what()
+  //
+  // Returns the associated explanatory string of the `absl::StatusOr<T>`
+  // object's error code. This function only returns the string literal "Bad
+  // StatusOr Access" for cases when evaluating general exceptions.
+  //
+  // The pointer of this string is guaranteed to be valid until any non-const
+  // function is invoked on the exception object.
+  const char* what() const noexcept override;
+
+  // BadStatusOrAccess::status()
+  //
+  // Returns the associated `absl::Status` of the `absl::StatusOr<T>` object's
+  // error.
+  const absl::Status& status() const;
+
+ private:
+  absl::Status status_;
+};
+
+// Returned StatusOr objects may not be ignored.
+template <typename T>
+class ABSL_MUST_USE_RESULT StatusOr;
+
+// absl::StatusOr<T>
+//
+// The `absl::StatusOr<T>` class template is a union of an `absl::Status` object
+// and an object of type `T`. The `absl::StatusOr<T>` models an object that is
+// either a usable object, or an error (of type `absl::Status`) explaining why
+// such an object is not present. An `absl::StatusOr<T>` is typically the return
+// value of a function which may fail.
+//
+// An `absl::StatusOr<T>` can never hold an "OK" status (an
+// `absl::StatusCode::kOk` value); instead, the presence of an object of type
+// `T` indicates success. Instead of checking for a `kOk` value, use the
+// `absl::StatusOr<T>::ok()` member function. (It is for this reason, and code
+// readability, that using the `ok()` function is preferred for `absl::Status`
+// as well.)
+//
+// Example:
+//
+//   StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+//   if (result.ok()) {
+//     result->DoSomethingCool();
+//   } else {
+//     LOG(ERROR) << result.status();
+//   }
+//
+// Accessing the object held by an `absl::StatusOr<T>` should be performed via
+// `operator*` or `operator->`, after a call to `ok()` confirms that the
+// `absl::StatusOr<T>` holds an object of type `T`:
+//
+// Example:
+//
+//   absl::StatusOr<int> i = GetCount();
+//   if (i.ok()) {
+//     updated_total += *i
+//   }
+//
+// NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will
+// throw an exception if exceptions are enabled or terminate the process when
+// execeptions are not enabled.
+//
+// Example:
+//
+//   StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+//   const Foo& foo = result.value();    // Crash/exception if no value present
+//   foo.DoSomethingCool();
+//
+// A `absl::StatusOr<T*>` can be constructed from a null pointer like any other
+// pointer value, and the result will be that `ok()` returns `true` and
+// `value()` returns `nullptr`. Checking the value of pointer in an
+// `absl::StatusOr<T>` generally requires a bit more care, to ensure both that a
+// value is present and that value is not null:
+//
+//  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
+//  if (!result.ok()) {
+//    LOG(ERROR) << result.status();
+//  } else if (*result == nullptr) {
+//    LOG(ERROR) << "Unexpected null pointer";
+//  } else {
+//    (*result)->DoSomethingCool();
+//  }
+//
+// Example factory implementation returning StatusOr<T>:
+//
+//  StatusOr<Foo> FooFactory::MakeFoo(int arg) {
+//    if (arg <= 0) {
+//      return absl::Status(absl::StatusCode::kInvalidArgument,
+//                          "Arg must be positive");
+//    }
+//    return Foo(arg);
+//  }
+template <typename T>
+class StatusOr : private internal_statusor::StatusOrData<T>,
+                 private internal_statusor::CopyCtorBase<T>,
+                 private internal_statusor::MoveCtorBase<T>,
+                 private internal_statusor::CopyAssignBase<T>,
+                 private internal_statusor::MoveAssignBase<T> {
+  template <typename U>
+  friend class StatusOr;
+
+  typedef internal_statusor::StatusOrData<T> Base;
+
+ public:
+  // StatusOr<T>::value_type
+  //
+  // This instance data provides a generic `value_type` member for use within
+  // generic programming. This usage is analogous to that of
+  // `optional::value_type` in the case of `std::optional`.
+  typedef T value_type;
+
+  // Constructors
+
+  // Constructs a new `absl::StatusOr` with an `absl::StatusCode::kUnknown`
+  // status. This constructor is marked 'explicit' to prevent usages in return
+  // values such as 'return {};', under the misconception that
+  // `absl::StatusOr<std::vector<int>>` will be initialized with an empty
+  // vector, instead of an `absl::StatusCode::kUnknown` error code.
+  explicit StatusOr();
+
+  // `StatusOr<T>` is copy constructible if `T` is copy constructible.
+  StatusOr(const StatusOr&) = default;
+  // `StatusOr<T>` is copy assignable if `T` is copy constructible and copy
+  // assignable.
+  StatusOr& operator=(const StatusOr&) = default;
+
+  // `StatusOr<T>` is move constructible if `T` is move constructible.
+  StatusOr(StatusOr&&) = default;
+  // `StatusOr<T>` is moveAssignable if `T` is move constructible and move
+  // assignable.
+  StatusOr& operator=(StatusOr&&) = default;
+
+  // Converting Constructors
+
+  // Constructs a new `absl::StatusOr<T>` from an `absl::StatusOr<U>`, when `T`
+  // is constructible from `U`. To avoid ambiguity, these constructors are
+  // disabled if `T` is also constructible from `StatusOr<U>.`. This constructor
+  // is explicit if and only if the corresponding construction of `T` from `U`
+  // is explicit. (This constructor inherits its explicitness from the
+  // underlying constructor.)
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>,
+              std::is_constructible<T, const U&>,
+              std::is_convertible<const U&, T>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  StatusOr(const StatusOr<U>& other)  // NOLINT
+      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>,
+              std::is_constructible<T, const U&>,
+              absl::negation<std::is_convertible<const U&, T>>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  explicit StatusOr(const StatusOr<U>& other)
+      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
+
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+              std::is_convertible<U&&, T>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  StatusOr(StatusOr<U>&& other)  // NOLINT
+      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+              absl::negation<std::is_convertible<U&&, T>>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  explicit StatusOr(StatusOr<U>&& other)
+      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
+
+  // Converting Assignment Operators
+
+  // Creates an `absl::StatusOr<T>` through assignment from an
+  // `absl::StatusOr<U>` when:
+  //
+  //   * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` are OK by assigning
+  //     `U` to `T` directly.
+  //   * `absl::StatusOr<T>` is OK and `absl::StatusOr<U>` contains an error
+  //      code by destroying `absl::StatusOr<T>`'s value and assigning from
+  //      `absl::StatusOr<U>'
+  //   * `absl::StatusOr<T>` contains an error code and `absl::StatusOr<U>` is
+  //      OK by directly initializing `T` from `U`.
+  //   * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` contain an error
+  //     code by assigning the `Status` in `absl::StatusOr<U>` to
+  //     `absl::StatusOr<T>`
+  //
+  // These overloads only apply if `absl::StatusOr<T>` is constructible and
+  // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly
+  // assigned from `StatusOr<U>`.
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>,
+              std::is_constructible<T, const U&>,
+              std::is_assignable<T, const U&>,
+              absl::negation<
+                  internal_statusor::
+                      IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+                          T, U>>>::value,
+          int> = 0>
+  StatusOr& operator=(const StatusOr<U>& other) {
+    this->Assign(other);
+    return *this;
+  }
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+              std::is_assignable<T, U&&>,
+              absl::negation<
+                  internal_statusor::
+                      IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+                          T, U>>>::value,
+          int> = 0>
+  StatusOr& operator=(StatusOr<U>&& other) {
+    this->Assign(std::move(other));
+    return *this;
+  }
+
+  // Constructs a new `absl::StatusOr<T>` with a non-ok status. After calling
+  // this constructor, `this->ok()` will be `false` and calls to `value()` will
+  // crash, or produce an exception if exceptions are enabled.
+  //
+  // The constructor also takes any type `U` that is convertible to
+  // `absl::Status`. This constructor is explicit if an only if `U` is not of
+  // type `absl::Status` and the conversion from `U` to `Status` is explicit.
+  //
+  // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed.
+  // In optimized builds, passing absl::OkStatus() here will have the effect
+  // of passing absl::StatusCode::kInternal as a fallback.
+  template <
+      typename U = absl::Status,
+      absl::enable_if_t<
+          absl::conjunction<
+              std::is_convertible<U&&, absl::Status>,
+              std::is_constructible<absl::Status, U&&>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+              absl::negation<std::is_same<absl::decay_t<U>, T>>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+              absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+                  T, U&&>>>::value,
+          int> = 0>
+  StatusOr(U&& v) : Base(std::forward<U>(v)) {}
+
+  template <
+      typename U = absl::Status,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_convertible<U&&, absl::Status>>,
+              std::is_constructible<absl::Status, U&&>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+              absl::negation<std::is_same<absl::decay_t<U>, T>>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+              absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+                  T, U&&>>>::value,
+          int> = 0>
+  explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {}
+
+  template <
+      typename U = absl::Status,
+      absl::enable_if_t<
+          absl::conjunction<
+              std::is_convertible<U&&, absl::Status>,
+              std::is_constructible<absl::Status, U&&>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+              absl::negation<std::is_same<absl::decay_t<U>, T>>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+              absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+                  T, U&&>>>::value,
+          int> = 0>
+  StatusOr& operator=(U&& v) {
+    this->AssignStatus(std::forward<U>(v));
+    return *this;
+  }
+
+  // Perfect-forwarding value assignment operator.
+
+  // If `*this` contains a `T` value before the call, the contained value is
+  // assigned from `std::forward<U>(v)`; Otherwise, it is directly-initialized
+  // from `std::forward<U>(v)`.
+  // This function does not participate in overload unless:
+  // 1. `std::is_constructible_v<T, U>` is true,
+  // 2. `std::is_assignable_v<T&, U>` is true.
+  // 3. `std::is_same_v<StatusOr<T>, std::remove_cvref_t<U>>` is false.
+  // 4. Assigning `U` to `T` is not ambiguous:
+  //  If `U` is `StatusOr<V>` and `T` is constructible and assignable from
+  //  both `StatusOr<V>` and `V`, the assignment is considered bug-prone and
+  //  ambiguous thus will fail to compile. For example:
+  //    StatusOr<bool> s1 = true;  // s1.ok() && *s1 == true
+  //    StatusOr<bool> s2 = false;  // s2.ok() && *s2 == false
+  //    s1 = s2;  // ambiguous, `s1 = *s2` or `s1 = bool(s2)`?
+  template <
+      typename U = T,
+      typename = typename std::enable_if<absl::conjunction<
+          std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>,
+          absl::disjunction<
+              std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, T>,
+              absl::conjunction<
+                  absl::negation<std::is_convertible<U&&, absl::Status>>,
+                  absl::negation<internal_statusor::
+                                     HasConversionOperatorToStatusOr<T, U&&>>>>,
+          internal_statusor::IsForwardingAssignmentValid<T, U&&>>::value>::type>
+  StatusOr& operator=(U&& v) {
+    this->Assign(std::forward<U>(v));
+    return *this;
+  }
+
+  // Constructs the inner value `T` in-place using the provided args, using the
+  // `T(args...)` constructor.
+  template <typename... Args>
+  explicit StatusOr(absl::in_place_t, Args&&... args);
+  template <typename U, typename... Args>
+  explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
+                    Args&&... args);
+
+  // Constructs the inner value `T` in-place using the provided args, using the
+  // `T(U)` (direct-initialization) constructor. This constructor is only valid
+  // if `T` can be constructed from a `U`. Can accept move or copy constructors.
+  //
+  // This constructor is explicit if `U` is not convertible to `T`. To avoid
+  // ambiguity, this constuctor is disabled if `U` is a `StatusOr<J>`, where `J`
+  // is convertible to `T`.
+  template <
+      typename U = T,
+      absl::enable_if_t<
+          absl::conjunction<
+              internal_statusor::IsDirectInitializationValid<T, U&&>,
+              std::is_constructible<T, U&&>, std::is_convertible<U&&, T>,
+              absl::disjunction<
+                  std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                               T>,
+                  absl::conjunction<
+                      absl::negation<std::is_convertible<U&&, absl::Status>>,
+                      absl::negation<
+                          internal_statusor::HasConversionOperatorToStatusOr<
+                              T, U&&>>>>>::value,
+          int> = 0>
+  StatusOr(U&& u)  // NOLINT
+      : StatusOr(absl::in_place, std::forward<U>(u)) {
+  }
+
+  template <
+      typename U = T,
+      absl::enable_if_t<
+          absl::conjunction<
+              internal_statusor::IsDirectInitializationValid<T, U&&>,
+              absl::disjunction<
+                  std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                               T>,
+                  absl::conjunction<
+                      absl::negation<std::is_constructible<absl::Status, U&&>>,
+                      absl::negation<
+                          internal_statusor::HasConversionOperatorToStatusOr<
+                              T, U&&>>>>,
+              std::is_constructible<T, U&&>,
+              absl::negation<std::is_convertible<U&&, T>>>::value,
+          int> = 0>
+  explicit StatusOr(U&& u)  // NOLINT
+      : StatusOr(absl::in_place, std::forward<U>(u)) {
+  }
+
+  // StatusOr<T>::ok()
+  //
+  // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This
+  // member function is analagous to `absl::Status::ok()` and should be used
+  // similarly to check the status of return values.
+  //
+  // Example:
+  //
+  // StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+  // if (result.ok()) {
+  //    // Handle result
+  // else {
+  //    // Handle error
+  // }
+  ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); }
+
+  // StatusOr<T>::status()
+  //
+  // 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 &;
+  Status status() &&;
+
+  // StatusOr<T>::value()
+  //
+  // Returns a reference to the held value if `this->ok()`. Otherwise, throws
+  // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to
+  // terminate the process if exceptions are disabled.
+  //
+  // If you have already checked the status using `this->ok()`, you probably
+  // want to use `operator*()` or `operator->()` to access the value instead of
+  // `value`.
+  //
+  // Note: for value types that are cheap to copy, prefer simple code:
+  //
+  //   T value = statusor.value();
+  //
+  // Otherwise, if the value type is expensive to copy, but can be left
+  // in the StatusOr, simply assign to a reference:
+  //
+  //   T& value = statusor.value();  // or `const T&`
+  //
+  // Otherwise, if the value type supports an efficient move, it can be
+  // used as follows:
+  //
+  //   T value = std::move(statusor).value();
+  //
+  // The `std::move` on statusor instead of on the whole expression enables
+  // warnings about possible uses of the statusor object after the move.
+  const T& value() const&;
+  T& value() &;
+  const T&& value() const&&;
+  T&& value() &&;
+
+  // StatusOr<T>:: operator*()
+  //
+  // Returns a reference to the current value.
+  //
+  // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
+  //
+  // Use `this->ok()` to verify that there is a current value within the
+  // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a
+  // similar API that guarantees crashing or throwing an exception if there is
+  // no current value.
+  const T& operator*() const&;
+  T& operator*() &;
+  const T&& operator*() const&&;
+  T&& operator*() &&;
+
+  // StatusOr<T>::operator->()
+  //
+  // Returns a pointer to the current value.
+  //
+  // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
+  //
+  // Use `this->ok()` to verify that there is a current value.
+  const T* operator->() const;
+  T* operator->();
+
+  // StatusOr<T>::value_or()
+  //
+  // Returns the current value if `this->ok() == true`. Otherwise constructs a
+  // value using the provided `default_value`.
+  //
+  // Unlike `value`, this function returns by value, copying the current value
+  // if necessary. If the value type supports an efficient move, it can be used
+  // as follows:
+  //
+  //   T value = std::move(statusor).value_or(def);
+  //
+  // Unlike with `value`, calling `std::move()` on the result of `value_or` will
+  // still trigger a copy.
+  template <typename U>
+  T value_or(U&& default_value) const&;
+  template <typename U>
+  T value_or(U&& default_value) &&;
+
+  // StatusOr<T>::IgnoreError()
+  //
+  // Ignores any errors. This method does nothing except potentially suppress
+  // complaints from any tools that are checking that errors are not dropped on
+  // the floor.
+  void IgnoreError() const;
+
+  // StatusOr<T>::emplace()
+  //
+  // Reconstructs the inner value T in-place using the provided args, using the
+  // T(args...) constructor. Returns reference to the reconstructed `T`.
+  template <typename... Args>
+  T& emplace(Args&&... args) {
+    if (ok()) {
+      this->Clear();
+      this->MakeValue(std::forward<Args>(args)...);
+    } else {
+      this->MakeValue(std::forward<Args>(args)...);
+      this->status_ = absl::OkStatus();
+    }
+    return this->data_;
+  }
+
+  template <
+      typename U, typename... Args,
+      absl::enable_if_t<
+          std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
+          int> = 0>
+  T& emplace(std::initializer_list<U> ilist, Args&&... args) {
+    if (ok()) {
+      this->Clear();
+      this->MakeValue(ilist, std::forward<Args>(args)...);
+    } else {
+      this->MakeValue(ilist, std::forward<Args>(args)...);
+      this->status_ = absl::OkStatus();
+    }
+    return this->data_;
+  }
+
+ private:
+  using internal_statusor::StatusOrData<T>::Assign;
+  template <typename U>
+  void Assign(const absl::StatusOr<U>& other);
+  template <typename U>
+  void Assign(absl::StatusOr<U>&& other);
+};
+
+// operator==()
+//
+// This operator checks the equality of two `absl::StatusOr<T>` objects.
+template <typename T>
+bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
+  if (lhs.ok() && rhs.ok()) return *lhs == *rhs;
+  return lhs.status() == rhs.status();
+}
+
+// operator!=()
+//
+// This operator checks the inequality of two `absl::StatusOr<T>` objects.
+template <typename T>
+bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
+  return !(lhs == rhs);
+}
+
+//------------------------------------------------------------------------------
+// Implementation details for StatusOr<T>
+//------------------------------------------------------------------------------
+
+// TODO(sbenza): avoid the string here completely.
+template <typename T>
+StatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, "")) {}
+
+template <typename T>
+template <typename U>
+inline void StatusOr<T>::Assign(const StatusOr<U>& other) {
+  if (other.ok()) {
+    this->Assign(*other);
+  } else {
+    this->AssignStatus(other.status());
+  }
+}
+
+template <typename T>
+template <typename U>
+inline void StatusOr<T>::Assign(StatusOr<U>&& other) {
+  if (other.ok()) {
+    this->Assign(*std::move(other));
+  } else {
+    this->AssignStatus(std::move(other).status());
+  }
+}
+template <typename T>
+template <typename... Args>
+StatusOr<T>::StatusOr(absl::in_place_t, Args&&... args)
+    : Base(absl::in_place, std::forward<Args>(args)...) {}
+
+template <typename T>
+template <typename U, typename... Args>
+StatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
+                      Args&&... args)
+    : Base(absl::in_place, ilist, std::forward<Args>(args)...) {}
+
+template <typename T>
+const Status& StatusOr<T>::status() const & { return this->status_; }
+template <typename T>
+Status StatusOr<T>::status() && {
+  return ok() ? OkStatus() : std::move(this->status_);
+}
+
+template <typename T>
+const T& StatusOr<T>::value() const& {
+  if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
+  return this->data_;
+}
+
+template <typename T>
+T& StatusOr<T>::value() & {
+  if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
+  return this->data_;
+}
+
+template <typename T>
+const T&& StatusOr<T>::value() const&& {
+  if (!this->ok()) {
+    internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
+  }
+  return std::move(this->data_);
+}
+
+template <typename T>
+T&& StatusOr<T>::value() && {
+  if (!this->ok()) {
+    internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
+  }
+  return std::move(this->data_);
+}
+
+template <typename T>
+const T& StatusOr<T>::operator*() const& {
+  this->EnsureOk();
+  return this->data_;
+}
+
+template <typename T>
+T& StatusOr<T>::operator*() & {
+  this->EnsureOk();
+  return this->data_;
+}
+
+template <typename T>
+const T&& StatusOr<T>::operator*() const&& {
+  this->EnsureOk();
+  return std::move(this->data_);
+}
+
+template <typename T>
+T&& StatusOr<T>::operator*() && {
+  this->EnsureOk();
+  return std::move(this->data_);
+}
+
+template <typename T>
+const T* StatusOr<T>::operator->() const {
+  this->EnsureOk();
+  return &this->data_;
+}
+
+template <typename T>
+T* StatusOr<T>::operator->() {
+  this->EnsureOk();
+  return &this->data_;
+}
+
+template <typename T>
+template <typename U>
+T StatusOr<T>::value_or(U&& default_value) const& {
+  if (ok()) {
+    return this->data_;
+  }
+  return std::forward<U>(default_value);
+}
+
+template <typename T>
+template <typename U>
+T StatusOr<T>::value_or(U&& default_value) && {
+  if (ok()) {
+    return std::move(this->data_);
+  }
+  return std::forward<U>(default_value);
+}
+
+template <typename T>
+void StatusOr<T>::IgnoreError() const {
+  // no-op
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_STATUSOR_H_
diff --git a/absl/status/statusor_test.cc b/absl/status/statusor_test.cc
new file mode 100644
index 0000000..c2e8fb7
--- /dev/null
+++ b/absl/status/statusor_test.cc
@@ -0,0 +1,1811 @@
+// 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/status/statusor.h"
+
+#include <array>
+#include <initializer_list>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/casts.h"
+#include "absl/memory/memory.h"
+#include "absl/status/status.h"
+#include "absl/types/any.h"
+#include "absl/utility/utility.h"
+
+namespace {
+
+using ::testing::AllOf;
+using ::testing::AnyWith;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::Ne;
+using ::testing::Not;
+using ::testing::Pointee;
+using ::testing::VariantWith;
+
+#ifdef GTEST_HAS_STATUS_MATCHERS
+using ::testing::status::IsOk;
+using ::testing::status::IsOkAndHolds;
+#else  // GTEST_HAS_STATUS_MATCHERS
+inline const ::absl::Status& GetStatus(const ::absl::Status& status) {
+  return status;
+}
+
+template <typename T>
+inline const ::absl::Status& GetStatus(const ::absl::StatusOr<T>& status) {
+  return status.status();
+}
+
+// Monomorphic implementation of matcher IsOkAndHolds(m).  StatusOrType is a
+// reference to StatusOr<T>.
+template <typename StatusOrType>
+class IsOkAndHoldsMatcherImpl
+    : public ::testing::MatcherInterface<StatusOrType> {
+ public:
+  typedef
+      typename std::remove_reference<StatusOrType>::type::value_type value_type;
+
+  template <typename InnerMatcher>
+  explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
+      : inner_matcher_(::testing::SafeMatcherCast<const value_type&>(
+            std::forward<InnerMatcher>(inner_matcher))) {}
+
+  void DescribeTo(std::ostream* os) const override {
+    *os << "is OK and has a value that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "isn't OK or has a value that ";
+    inner_matcher_.DescribeNegationTo(os);
+  }
+
+  bool MatchAndExplain(
+      StatusOrType actual_value,
+      ::testing::MatchResultListener* result_listener) const override {
+    if (!actual_value.ok()) {
+      *result_listener << "which has status " << actual_value.status();
+      return false;
+    }
+
+    ::testing::StringMatchResultListener inner_listener;
+    const bool matches =
+        inner_matcher_.MatchAndExplain(*actual_value, &inner_listener);
+    const std::string inner_explanation = inner_listener.str();
+    if (!inner_explanation.empty()) {
+      *result_listener << "which contains value "
+                       << ::testing::PrintToString(*actual_value) << ", "
+                       << inner_explanation;
+    }
+    return matches;
+  }
+
+ private:
+  const ::testing::Matcher<const value_type&> inner_matcher_;
+};
+
+// Implements IsOkAndHolds(m) as a polymorphic matcher.
+template <typename InnerMatcher>
+class IsOkAndHoldsMatcher {
+ public:
+  explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)
+      : inner_matcher_(std::move(inner_matcher)) {}
+
+  // Converts this polymorphic matcher to a monomorphic matcher of the
+  // given type.  StatusOrType can be either StatusOr<T> or a
+  // reference to StatusOr<T>.
+  template <typename StatusOrType>
+  operator ::testing::Matcher<StatusOrType>() const {  // NOLINT
+    return ::testing::Matcher<StatusOrType>(
+        new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));
+  }
+
+ private:
+  const InnerMatcher inner_matcher_;
+};
+
+// Monomorphic implementation of matcher IsOk() for a given type T.
+// T can be Status, StatusOr<>, or a reference to either of them.
+template <typename T>
+class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> {
+ public:
+  void DescribeTo(std::ostream* os) const override { *os << "is OK"; }
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "is not OK";
+  }
+  bool MatchAndExplain(T actual_value,
+                       ::testing::MatchResultListener*) const override {
+    return GetStatus(actual_value).ok();
+  }
+};
+
+// Implements IsOk() as a polymorphic matcher.
+class IsOkMatcher {
+ public:
+  template <typename T>
+  operator ::testing::Matcher<T>() const {  // NOLINT
+    return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<T>());
+  }
+};
+
+// Macros for testing the results of functions that return absl::Status or
+// absl::StatusOr<T> (for any type T).
+#define EXPECT_OK(expression) EXPECT_THAT(expression, IsOk())
+
+// Returns a gMock matcher that matches a StatusOr<> whose status is
+// OK and whose value matches the inner matcher.
+template <typename InnerMatcher>
+IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type> IsOkAndHolds(
+    InnerMatcher&& inner_matcher) {
+  return IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>(
+      std::forward<InnerMatcher>(inner_matcher));
+}
+
+// Returns a gMock matcher that matches a Status or StatusOr<> which is OK.
+inline IsOkMatcher IsOk() { return IsOkMatcher(); }
+#endif  // GTEST_HAS_STATUS_MATCHERS
+
+struct CopyDetector {
+  CopyDetector() = default;
+  explicit CopyDetector(int xx) : x(xx) {}
+  CopyDetector(CopyDetector&& d) noexcept
+      : x(d.x), copied(false), moved(true) {}
+  CopyDetector(const CopyDetector& d) : x(d.x), copied(true), moved(false) {}
+  CopyDetector& operator=(const CopyDetector& c) {
+    x = c.x;
+    copied = true;
+    moved = false;
+    return *this;
+  }
+  CopyDetector& operator=(CopyDetector&& c) noexcept {
+    x = c.x;
+    copied = false;
+    moved = true;
+    return *this;
+  }
+  int x = 0;
+  bool copied = false;
+  bool moved = false;
+};
+
+testing::Matcher<const CopyDetector&> CopyDetectorHas(int a, bool b, bool c) {
+  return AllOf(Field(&CopyDetector::x, a), Field(&CopyDetector::moved, b),
+               Field(&CopyDetector::copied, c));
+}
+
+class Base1 {
+ public:
+  virtual ~Base1() {}
+  int pad;
+};
+
+class Base2 {
+ public:
+  virtual ~Base2() {}
+  int yetotherpad;
+};
+
+class Derived : public Base1, public Base2 {
+ public:
+  virtual ~Derived() {}
+  int evenmorepad;
+};
+
+class CopyNoAssign {
+ public:
+  explicit CopyNoAssign(int value) : foo(value) {}
+  CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
+  int foo;
+
+ private:
+  const CopyNoAssign& operator=(const CopyNoAssign&);
+};
+
+absl::StatusOr<std::unique_ptr<int>> ReturnUniquePtr() {
+  // Uses implicit constructor from T&&
+  return absl::make_unique<int>(0);
+}
+
+TEST(StatusOr, ElementType) {
+  static_assert(std::is_same<absl::StatusOr<int>::value_type, int>(), "");
+  static_assert(std::is_same<absl::StatusOr<char>::value_type, char>(), "");
+}
+
+TEST(StatusOr, TestMoveOnlyInitialization) {
+  absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
+  ASSERT_TRUE(thing.ok());
+  EXPECT_EQ(0, **thing);
+  int* previous = thing->get();
+
+  thing = ReturnUniquePtr();
+  EXPECT_TRUE(thing.ok());
+  EXPECT_EQ(0, **thing);
+  EXPECT_NE(previous, thing->get());
+}
+
+TEST(StatusOr, TestMoveOnlyValueExtraction) {
+  absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
+  ASSERT_TRUE(thing.ok());
+  std::unique_ptr<int> ptr = *std::move(thing);
+  EXPECT_EQ(0, *ptr);
+
+  thing = std::move(ptr);
+  ptr = std::move(*thing);
+  EXPECT_EQ(0, *ptr);
+}
+
+TEST(StatusOr, TestMoveOnlyInitializationFromTemporaryByValueOrDie) {
+  std::unique_ptr<int> ptr(*ReturnUniquePtr());
+  EXPECT_EQ(0, *ptr);
+}
+
+TEST(StatusOr, TestValueOrDieOverloadForConstTemporary) {
+  static_assert(
+      std::is_same<const int&&,
+                   decltype(
+                       std::declval<const absl::StatusOr<int>&&>().value())>(),
+      "value() for const temporaries should return const T&&");
+}
+
+TEST(StatusOr, TestMoveOnlyConversion) {
+  absl::StatusOr<std::unique_ptr<const int>> const_thing(ReturnUniquePtr());
+  EXPECT_TRUE(const_thing.ok());
+  EXPECT_EQ(0, **const_thing);
+
+  // Test rvalue converting assignment
+  const int* const_previous = const_thing->get();
+  const_thing = ReturnUniquePtr();
+  EXPECT_TRUE(const_thing.ok());
+  EXPECT_EQ(0, **const_thing);
+  EXPECT_NE(const_previous, const_thing->get());
+}
+
+TEST(StatusOr, TestMoveOnlyVector) {
+  // Sanity check that absl::StatusOr<MoveOnly> works in vector.
+  std::vector<absl::StatusOr<std::unique_ptr<int>>> vec;
+  vec.push_back(ReturnUniquePtr());
+  vec.resize(2);
+  auto another_vec = std::move(vec);
+  EXPECT_EQ(0, **another_vec[0]);
+  EXPECT_EQ(absl::UnknownError(""), another_vec[1].status());
+}
+
+TEST(StatusOr, TestDefaultCtor) {
+  absl::StatusOr<int> thing;
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
+}
+
+TEST(StatusOr, StatusCtorForwards) {
+  absl::Status status(absl::StatusCode::kInternal, "Some error");
+
+  EXPECT_EQ(absl::StatusOr<int>(status).status().message(), "Some error");
+  EXPECT_EQ(status.message(), "Some error");
+
+  EXPECT_EQ(absl::StatusOr<int>(std::move(status)).status().message(),
+            "Some error");
+  EXPECT_NE(status.message(), "Some error");
+}
+
+// Define `EXPECT_DEATH_OR_THROW` to test the behavior of `StatusOr::value`,
+// which either throws `BadStatusOrAccess` or `LOG(FATAL)` based on whether
+// exceptions are enabled.
+#ifdef ABSL_HAVE_EXCEPTIONS
+#define EXPECT_DEATH_OR_THROW(statement, status_)    \
+  EXPECT_THROW(                                      \
+      {                                              \
+        try {                                        \
+          statement;                                 \
+        } catch (const absl::BadStatusOrAccess& e) { \
+          EXPECT_EQ(e.status(), status_);            \
+          throw;                                     \
+        }                                            \
+      },                                             \
+      absl::BadStatusOrAccess);
+#else  // ABSL_HAVE_EXCEPTIONS
+#define EXPECT_DEATH_OR_THROW(statement, status) \
+  EXPECT_DEATH_IF_SUPPORTED(statement, status.ToString());
+#endif  // ABSL_HAVE_EXCEPTIONS
+
+TEST(StatusOrDeathTest, TestDefaultCtorValue) {
+  absl::StatusOr<int> thing;
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+  const absl::StatusOr<int> thing2;
+  EXPECT_DEATH_OR_THROW(thing2.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestValueNotOk) {
+  absl::StatusOr<int> thing(absl::CancelledError());
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+TEST(StatusOrDeathTest, TestValueNotOkConst) {
+  const absl::StatusOr<int> thing(absl::UnknownError(""));
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestPointerDefaultCtorValue) {
+  absl::StatusOr<int*> thing;
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestPointerValueNotOk) {
+  absl::StatusOr<int*> thing(absl::CancelledError());
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+TEST(StatusOrDeathTest, TestPointerValueNotOkConst) {
+  const absl::StatusOr<int*> thing(absl::CancelledError());
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(StatusOrDeathTest, TestStatusCtorStatusOk) {
+  EXPECT_DEBUG_DEATH(
+      {
+        // This will DCHECK
+        absl::StatusOr<int> thing(absl::OkStatus());
+        // In optimized mode, we are actually going to get error::INTERNAL for
+        // status here, rather than crashing, so check that.
+        EXPECT_FALSE(thing.ok());
+        EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
+      },
+      "An OK status is not a valid constructor argument");
+}
+
+TEST(StatusOrDeathTest, TestPointerStatusCtorStatusOk) {
+  EXPECT_DEBUG_DEATH(
+      {
+        absl::StatusOr<int*> thing(absl::OkStatus());
+        // In optimized mode, we are actually going to get error::INTERNAL for
+        // status here, rather than crashing, so check that.
+        EXPECT_FALSE(thing.ok());
+        EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
+      },
+      "An OK status is not a valid constructor argument");
+}
+#endif
+
+TEST(StatusOr, ValueAccessor) {
+  const int kIntValue = 110;
+  {
+    absl::StatusOr<int> status_or(kIntValue);
+    EXPECT_EQ(kIntValue, status_or.value());
+    EXPECT_EQ(kIntValue, std::move(status_or).value());
+  }
+  {
+    absl::StatusOr<CopyDetector> status_or(kIntValue);
+    EXPECT_THAT(status_or,
+                IsOkAndHolds(CopyDetectorHas(kIntValue, false, false)));
+    CopyDetector copy_detector = status_or.value();
+    EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, false, true));
+    copy_detector = std::move(status_or).value();
+    EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, true, false));
+  }
+}
+
+TEST(StatusOr, BadValueAccess) {
+  const absl::Status kError = absl::CancelledError("message");
+  absl::StatusOr<int> status_or(kError);
+  EXPECT_DEATH_OR_THROW(status_or.value(), kError);
+}
+
+TEST(StatusOr, TestStatusCtor) {
+  absl::StatusOr<int> thing(absl::CancelledError());
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
+}
+
+
+
+TEST(StatusOr, TestValueCtor) {
+  const int kI = 4;
+  const absl::StatusOr<int> thing(kI);
+  EXPECT_TRUE(thing.ok());
+  EXPECT_EQ(kI, *thing);
+}
+
+struct Foo {
+  const int x;
+  explicit Foo(int y) : x(y) {}
+};
+
+TEST(StatusOr, InPlaceConstruction) {
+  EXPECT_THAT(absl::StatusOr<Foo>(absl::in_place, 10),
+              IsOkAndHolds(Field(&Foo::x, 10)));
+}
+
+struct InPlaceHelper {
+  InPlaceHelper(std::initializer_list<int> xs, std::unique_ptr<int> yy)
+      : x(xs), y(std::move(yy)) {}
+  const std::vector<int> x;
+  std::unique_ptr<int> y;
+};
+
+TEST(StatusOr, InPlaceInitListConstruction) {
+  absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
+                                          absl::make_unique<int>(13));
+  EXPECT_THAT(status_or, IsOkAndHolds(AllOf(
+                             Field(&InPlaceHelper::x, ElementsAre(10, 11, 12)),
+                             Field(&InPlaceHelper::y, Pointee(13)))));
+}
+
+TEST(StatusOr, Emplace) {
+  absl::StatusOr<Foo> status_or_foo(10);
+  status_or_foo.emplace(20);
+  EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
+  status_or_foo = absl::InvalidArgumentError("msg");
+  EXPECT_FALSE(status_or_foo.ok());
+  EXPECT_EQ(status_or_foo.status().code(), absl::StatusCode::kInvalidArgument);
+  EXPECT_EQ(status_or_foo.status().message(), "msg");
+  status_or_foo.emplace(20);
+  EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
+}
+
+TEST(StatusOr, EmplaceInitializerList) {
+  absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
+                                          absl::make_unique<int>(13));
+  status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
+  EXPECT_THAT(status_or,
+              IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
+                                 Field(&InPlaceHelper::y, Pointee(4)))));
+  status_or = absl::InvalidArgumentError("msg");
+  EXPECT_FALSE(status_or.ok());
+  EXPECT_EQ(status_or.status().code(), absl::StatusCode::kInvalidArgument);
+  EXPECT_EQ(status_or.status().message(), "msg");
+  status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
+  EXPECT_THAT(status_or,
+              IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
+                                 Field(&InPlaceHelper::y, Pointee(4)))));
+}
+
+TEST(StatusOr, TestCopyCtorStatusOk) {
+  const int kI = 4;
+  const absl::StatusOr<int> original(kI);
+  const absl::StatusOr<int> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOk) {
+  absl::StatusOr<int> original(absl::CancelledError());
+  absl::StatusOr<int> copy(original);
+  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestCopyCtorNonAssignable) {
+  const int kI = 4;
+  CopyNoAssign value(kI);
+  absl::StatusOr<CopyNoAssign> original(value);
+  absl::StatusOr<CopyNoAssign> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(original->foo, copy->foo);
+}
+
+TEST(StatusOr, TestCopyCtorStatusOKConverting) {
+  const int kI = 4;
+  absl::StatusOr<int> original(kI);
+  absl::StatusOr<double> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_DOUBLE_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
+  absl::StatusOr<int> original(absl::CancelledError());
+  absl::StatusOr<double> copy(original);
+  EXPECT_EQ(copy.status(), original.status());
+}
+
+TEST(StatusOr, TestAssignmentStatusOk) {
+  // Copy assignmment
+  {
+    const auto p = std::make_shared<int>(17);
+    absl::StatusOr<std::shared_ptr<int>> source(p);
+
+    absl::StatusOr<std::shared_ptr<int>> target;
+    target = source;
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_EQ(p, *target);
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_EQ(p, *source);
+  }
+
+  // Move asssignment
+  {
+    const auto p = std::make_shared<int>(17);
+    absl::StatusOr<std::shared_ptr<int>> source(p);
+
+    absl::StatusOr<std::shared_ptr<int>> target;
+    target = std::move(source);
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_EQ(p, *target);
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_EQ(nullptr, *source);
+  }
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOk) {
+  // Copy assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<int> target;
+    target = source;
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(expected, source.status());
+  }
+
+  // Move assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<int> target;
+    target = std::move(source);
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
+  }
+}
+
+TEST(StatusOr, TestAssignmentStatusOKConverting) {
+  // Copy assignment
+  {
+    const int kI = 4;
+    absl::StatusOr<int> source(kI);
+
+    absl::StatusOr<double> target;
+    target = source;
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_DOUBLE_EQ(kI, *target);
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_DOUBLE_EQ(kI, *source);
+  }
+
+  // Move assignment
+  {
+    const auto p = new int(17);
+    absl::StatusOr<std::unique_ptr<int>> source(absl::WrapUnique(p));
+
+    absl::StatusOr<std::shared_ptr<int>> target;
+    target = std::move(source);
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_EQ(p, target->get());
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_EQ(nullptr, source->get());
+  }
+}
+
+struct A {
+  int x;
+};
+
+struct ImplicitConstructibleFromA {
+  int x;
+  bool moved;
+  ImplicitConstructibleFromA(const A& a)  // NOLINT
+      : x(a.x), moved(false) {}
+  ImplicitConstructibleFromA(A&& a)  // NOLINT
+      : x(a.x), moved(true) {}
+};
+
+TEST(StatusOr, ImplicitConvertingConstructor) {
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(
+          absl::StatusOr<A>(A{11})),
+      IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 11),
+                         Field(&ImplicitConstructibleFromA::moved, true))));
+  absl::StatusOr<A> a(A{12});
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(a),
+      IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 12),
+                         Field(&ImplicitConstructibleFromA::moved, false))));
+}
+
+struct ExplicitConstructibleFromA {
+  int x;
+  bool moved;
+  explicit ExplicitConstructibleFromA(const A& a) : x(a.x), moved(false) {}
+  explicit ExplicitConstructibleFromA(A&& a) : x(a.x), moved(true) {}
+};
+
+TEST(StatusOr, ExplicitConvertingConstructor) {
+  EXPECT_FALSE(
+      (std::is_convertible<const absl::StatusOr<A>&,
+                           absl::StatusOr<ExplicitConstructibleFromA>>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::StatusOr<A>&&,
+                           absl::StatusOr<ExplicitConstructibleFromA>>::value));
+  EXPECT_THAT(
+      absl::StatusOr<ExplicitConstructibleFromA>(absl::StatusOr<A>(A{11})),
+      IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 11),
+                         Field(&ExplicitConstructibleFromA::moved, true))));
+  absl::StatusOr<A> a(A{12});
+  EXPECT_THAT(
+      absl::StatusOr<ExplicitConstructibleFromA>(a),
+      IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 12),
+                         Field(&ExplicitConstructibleFromA::moved, false))));
+}
+
+struct ImplicitConstructibleFromBool {
+  ImplicitConstructibleFromBool(bool y) : x(y) {}  // NOLINT
+  bool x = false;
+};
+
+struct ConvertibleToBool {
+  explicit ConvertibleToBool(bool y) : x(y) {}
+  operator bool() const { return x; }  // NOLINT
+  bool x = false;
+};
+
+TEST(StatusOr, ImplicitBooleanConstructionWithImplicitCasts) {
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromBool>>(
+          absl::StatusOr<bool>(false)),
+      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+  EXPECT_FALSE((std::is_convertible<
+                absl::StatusOr<ConvertibleToBool>,
+                absl::StatusOr<ImplicitConstructibleFromBool>>::value));
+}
+
+TEST(StatusOr, BooleanConstructionWithImplicitCasts) {
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<bool>(false)},
+      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<bool>(absl::InvalidArgumentError(""))},
+      Not(IsOk()));
+
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<ConvertibleToBool>(ConvertibleToBool{false})},
+      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<ConvertibleToBool>(absl::InvalidArgumentError(""))},
+      Not(IsOk()));
+}
+
+TEST(StatusOr, ConstImplicitCast) {
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
+                  absl::StatusOr<const bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
+                  absl::StatusOr<const bool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
+                  absl::StatusOr<bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
+                  absl::StatusOr<bool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const std::string>>(
+                  absl::StatusOr<std::string>("foo")),
+              IsOkAndHolds("foo"));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<std::string>>(
+                  absl::StatusOr<const std::string>("foo")),
+              IsOkAndHolds("foo"));
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<std::shared_ptr<const std::string>>>(
+          absl::StatusOr<std::shared_ptr<std::string>>(
+              std::make_shared<std::string>("foo"))),
+      IsOkAndHolds(Pointee(std::string("foo"))));
+}
+
+TEST(StatusOr, ConstExplicitConstruction) {
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(false)),
+              IsOkAndHolds(false));
+}
+
+struct ExplicitConstructibleFromInt {
+  int x;
+  explicit ExplicitConstructibleFromInt(int y) : x(y) {}
+};
+
+TEST(StatusOr, ExplicitConstruction) {
+  EXPECT_THAT(absl::StatusOr<ExplicitConstructibleFromInt>(10),
+              IsOkAndHolds(Field(&ExplicitConstructibleFromInt::x, 10)));
+}
+
+TEST(StatusOr, ImplicitConstruction) {
+  // Check implicit casting works.
+  auto status_or =
+      absl::implicit_cast<absl::StatusOr<absl::variant<int, std::string>>>(10);
+  EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
+}
+
+TEST(StatusOr, ImplicitConstructionFromInitliazerList) {
+  // Note: dropping the explicit std::initializer_list<int> is not supported
+  // by absl::StatusOr or absl::optional.
+  auto status_or =
+      absl::implicit_cast<absl::StatusOr<std::vector<int>>>({{10, 20, 30}});
+  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, UniquePtrImplicitConstruction) {
+  auto status_or = absl::implicit_cast<absl::StatusOr<std::unique_ptr<Base1>>>(
+      absl::make_unique<Derived>());
+  EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
+}
+
+TEST(StatusOr, NestedStatusOrCopyAndMoveConstructorTests) {
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
+      absl::InvalidArgumentError("foo");
+  EXPECT_THAT(status_or,
+              IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::StatusOr<CopyDetector>> a = status_or;
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  absl::StatusOr<absl::StatusOr<CopyDetector>> a_err = status_error;
+  EXPECT_THAT(a_err, Not(IsOk()));
+
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
+  absl::StatusOr<absl::StatusOr<CopyDetector>> b = cref;  // NOLINT
+  EXPECT_THAT(b, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
+  absl::StatusOr<absl::StatusOr<CopyDetector>> b_err = cref_err;  // NOLINT
+  EXPECT_THAT(b_err, Not(IsOk()));
+
+  absl::StatusOr<absl::StatusOr<CopyDetector>> c = std::move(status_or);
+  EXPECT_THAT(c, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::StatusOr<CopyDetector>> c_err = std::move(status_error);
+  EXPECT_THAT(c_err, Not(IsOk()));
+}
+
+TEST(StatusOr, NestedStatusOrCopyAndMoveAssignment) {
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
+      absl::InvalidArgumentError("foo");
+  absl::StatusOr<absl::StatusOr<CopyDetector>> a;
+  a = status_or;
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  a = status_error;
+  EXPECT_THAT(a, Not(IsOk()));
+
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
+  a = cref;
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
+  a = cref_err;
+  EXPECT_THAT(a, Not(IsOk()));
+  a = std::move(status_or);
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+  a = std::move(status_error);
+  EXPECT_THAT(a, Not(IsOk()));
+}
+
+struct Copyable {
+  Copyable() {}
+  Copyable(const Copyable&) {}
+  Copyable& operator=(const Copyable&) { return *this; }
+};
+
+struct MoveOnly {
+  MoveOnly() {}
+  MoveOnly(MoveOnly&&) {}
+  MoveOnly& operator=(MoveOnly&&) { return *this; }
+};
+
+struct NonMovable {
+  NonMovable() {}
+  NonMovable(const NonMovable&) = delete;
+  NonMovable(NonMovable&&) = delete;
+  NonMovable& operator=(const NonMovable&) = delete;
+  NonMovable& operator=(NonMovable&&) = delete;
+};
+
+TEST(StatusOr, CopyAndMoveAbility) {
+  EXPECT_TRUE(std::is_copy_constructible<Copyable>::value);
+  EXPECT_TRUE(std::is_copy_assignable<Copyable>::value);
+  EXPECT_TRUE(std::is_move_constructible<Copyable>::value);
+  EXPECT_TRUE(std::is_move_assignable<Copyable>::value);
+  EXPECT_FALSE(std::is_copy_constructible<MoveOnly>::value);
+  EXPECT_FALSE(std::is_copy_assignable<MoveOnly>::value);
+  EXPECT_TRUE(std::is_move_constructible<MoveOnly>::value);
+  EXPECT_TRUE(std::is_move_assignable<MoveOnly>::value);
+  EXPECT_FALSE(std::is_copy_constructible<NonMovable>::value);
+  EXPECT_FALSE(std::is_copy_assignable<NonMovable>::value);
+  EXPECT_FALSE(std::is_move_constructible<NonMovable>::value);
+  EXPECT_FALSE(std::is_move_assignable<NonMovable>::value);
+}
+
+TEST(StatusOr, StatusOrAnyCopyAndMoveConstructorTests) {
+  absl::StatusOr<absl::any> status_or = CopyDetector(10);
+  absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
+  EXPECT_THAT(
+      status_or,
+      IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::any> a = status_or;
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  absl::StatusOr<absl::any> a_err = status_error;
+  EXPECT_THAT(a_err, Not(IsOk()));
+
+  const absl::StatusOr<absl::any>& cref = status_or;
+  // No lint for no-change copy.
+  absl::StatusOr<absl::any> b = cref;  // NOLINT
+  EXPECT_THAT(
+      b, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::any>& cref_err = status_error;
+  // No lint for no-change copy.
+  absl::StatusOr<absl::any> b_err = cref_err;  // NOLINT
+  EXPECT_THAT(b_err, Not(IsOk()));
+
+  absl::StatusOr<absl::any> c = std::move(status_or);
+  EXPECT_THAT(
+      c, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::any> c_err = std::move(status_error);
+  EXPECT_THAT(c_err, Not(IsOk()));
+}
+
+TEST(StatusOr, StatusOrAnyCopyAndMoveAssignment) {
+  absl::StatusOr<absl::any> status_or = CopyDetector(10);
+  absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
+  absl::StatusOr<absl::any> a;
+  a = status_or;
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  a = status_error;
+  EXPECT_THAT(a, Not(IsOk()));
+
+  const absl::StatusOr<absl::any>& cref = status_or;
+  a = cref;
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::any>& cref_err = status_error;
+  a = cref_err;
+  EXPECT_THAT(a, Not(IsOk()));
+  a = std::move(status_or);
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+  a = std::move(status_error);
+  EXPECT_THAT(a, Not(IsOk()));
+}
+
+TEST(StatusOr, StatusOrCopyAndMoveTestsConstructor) {
+  absl::StatusOr<CopyDetector> status_or(10);
+  ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
+  absl::StatusOr<CopyDetector> a(status_or);
+  EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  const absl::StatusOr<CopyDetector>& cref = status_or;
+  absl::StatusOr<CopyDetector> b(cref);  // NOLINT
+  EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  absl::StatusOr<CopyDetector> c(std::move(status_or));
+  EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
+}
+
+TEST(StatusOr, StatusOrCopyAndMoveTestsAssignment) {
+  absl::StatusOr<CopyDetector> status_or(10);
+  ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
+  absl::StatusOr<CopyDetector> a;
+  a = status_or;
+  EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  const absl::StatusOr<CopyDetector>& cref = status_or;
+  absl::StatusOr<CopyDetector> b;
+  b = cref;
+  EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  absl::StatusOr<CopyDetector> c;
+  c = std::move(status_or);
+  EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
+}
+
+TEST(StatusOr, AbslAnyAssignment) {
+  EXPECT_FALSE((std::is_assignable<absl::StatusOr<absl::any>,
+                                   absl::StatusOr<int>>::value));
+  absl::StatusOr<absl::any> status_or;
+  status_or = absl::InvalidArgumentError("foo");
+  EXPECT_THAT(status_or, Not(IsOk()));
+}
+
+TEST(StatusOr, ImplicitAssignment) {
+  absl::StatusOr<absl::variant<int, std::string>> status_or;
+  status_or = 10;
+  EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
+}
+
+TEST(StatusOr, SelfDirectInitAssignment) {
+  absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
+  status_or = *status_or;
+  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, ImplicitCastFromInitializerList) {
+  absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
+  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, UniquePtrImplicitAssignment) {
+  absl::StatusOr<std::unique_ptr<Base1>> status_or;
+  status_or = absl::make_unique<Derived>();
+  EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
+}
+
+TEST(StatusOr, Pointer) {
+  struct A {};
+  struct B : public A {};
+  struct C : private A {};
+
+  EXPECT_TRUE((std::is_constructible<absl::StatusOr<A*>, B*>::value));
+  EXPECT_TRUE((std::is_convertible<B*, absl::StatusOr<A*>>::value));
+  EXPECT_FALSE((std::is_constructible<absl::StatusOr<A*>, C*>::value));
+  EXPECT_FALSE((std::is_convertible<C*, absl::StatusOr<A*>>::value));
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
+  // Copy assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<double> target;
+    target = source;
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(expected, source.status());
+  }
+
+  // Move assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<double> target;
+    target = std::move(source);
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
+  }
+}
+
+TEST(StatusOr, SelfAssignment) {
+  // Copy-assignment, status OK
+  {
+    // A string long enough that it's likely to defeat any inline representation
+    // optimization.
+    const std::string long_str(128, 'a');
+
+    absl::StatusOr<std::string> so = long_str;
+    so = *&so;
+
+    ASSERT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(long_str, *so);
+  }
+
+  // Copy-assignment, error status
+  {
+    absl::StatusOr<int> so = absl::NotFoundError("taco");
+    so = *&so;
+
+    EXPECT_FALSE(so.ok());
+    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+    EXPECT_EQ(so.status().message(), "taco");
+  }
+
+  // Move-assignment with copyable type, status OK
+  {
+    absl::StatusOr<int> so = 17;
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    ASSERT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(17, *so);
+  }
+
+  // Move-assignment with copyable type, error status
+  {
+    absl::StatusOr<int> so = absl::NotFoundError("taco");
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    EXPECT_FALSE(so.ok());
+    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+    EXPECT_EQ(so.status().message(), "taco");
+  }
+
+  // Move-assignment with non-copyable type, status OK
+  {
+    const auto raw = new int(17);
+    absl::StatusOr<std::unique_ptr<int>> so = absl::WrapUnique(raw);
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    ASSERT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(raw, so->get());
+  }
+
+  // Move-assignment with non-copyable type, error status
+  {
+    absl::StatusOr<std::unique_ptr<int>> so = absl::NotFoundError("taco");
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    EXPECT_FALSE(so.ok());
+    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+    EXPECT_EQ(so.status().message(), "taco");
+  }
+}
+
+// These types form the overload sets of the constructors and the assignment
+// operators of `MockValue`. They distinguish construction from assignment,
+// lvalue from rvalue.
+struct FromConstructibleAssignableLvalue {};
+struct FromConstructibleAssignableRvalue {};
+struct FromImplicitConstructibleOnly {};
+struct FromAssignableOnly {};
+
+// This class is for testing the forwarding value assignments of `StatusOr`.
+// `from_rvalue` indicates whether the constructor or the assignment taking
+// rvalue reference is called. `from_assignment` indicates whether any
+// assignment is called.
+struct MockValue {
+  // Constructs `MockValue` from `FromConstructibleAssignableLvalue`.
+  MockValue(const FromConstructibleAssignableLvalue&)  // NOLINT
+      : from_rvalue(false), assigned(false) {}
+  // Constructs `MockValue` from `FromConstructibleAssignableRvalue`.
+  MockValue(FromConstructibleAssignableRvalue&&)  // NOLINT
+      : from_rvalue(true), assigned(false) {}
+  // Constructs `MockValue` from `FromImplicitConstructibleOnly`.
+  // `MockValue` is not assignable from `FromImplicitConstructibleOnly`.
+  MockValue(const FromImplicitConstructibleOnly&)  // NOLINT
+      : from_rvalue(false), assigned(false) {}
+  // Assigns `FromConstructibleAssignableLvalue`.
+  MockValue& operator=(const FromConstructibleAssignableLvalue&) {
+    from_rvalue = false;
+    assigned = true;
+    return *this;
+  }
+  // Assigns `FromConstructibleAssignableRvalue` (rvalue only).
+  MockValue& operator=(FromConstructibleAssignableRvalue&&) {
+    from_rvalue = true;
+    assigned = true;
+    return *this;
+  }
+  // Assigns `FromAssignableOnly`, but not constructible from
+  // `FromAssignableOnly`.
+  MockValue& operator=(const FromAssignableOnly&) {
+    from_rvalue = false;
+    assigned = true;
+    return *this;
+  }
+  bool from_rvalue;
+  bool assigned;
+};
+
+// operator=(U&&)
+TEST(StatusOr, PerfectForwardingAssignment) {
+  // U == T
+  constexpr int kValue1 = 10, kValue2 = 20;
+  absl::StatusOr<CopyDetector> status_or;
+  CopyDetector lvalue(kValue1);
+  status_or = lvalue;
+  EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue1, false, true)));
+  status_or = CopyDetector(kValue2);
+  EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue2, true, false)));
+
+  // U != T
+  EXPECT_TRUE(
+      (std::is_assignable<absl::StatusOr<MockValue>&,
+                          const FromConstructibleAssignableLvalue&>::value));
+  EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
+                                  FromConstructibleAssignableLvalue&&>::value));
+  EXPECT_FALSE(
+      (std::is_assignable<absl::StatusOr<MockValue>&,
+                          const FromConstructibleAssignableRvalue&>::value));
+  EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
+                                  FromConstructibleAssignableRvalue&&>::value));
+  EXPECT_TRUE(
+      (std::is_assignable<absl::StatusOr<MockValue>&,
+                          const FromImplicitConstructibleOnly&>::value));
+  EXPECT_FALSE((std::is_assignable<absl::StatusOr<MockValue>&,
+                                   const FromAssignableOnly&>::value));
+
+  absl::StatusOr<MockValue> from_lvalue(FromConstructibleAssignableLvalue{});
+  EXPECT_FALSE(from_lvalue->from_rvalue);
+  EXPECT_FALSE(from_lvalue->assigned);
+  from_lvalue = FromConstructibleAssignableLvalue{};
+  EXPECT_FALSE(from_lvalue->from_rvalue);
+  EXPECT_TRUE(from_lvalue->assigned);
+
+  absl::StatusOr<MockValue> from_rvalue(FromConstructibleAssignableRvalue{});
+  EXPECT_TRUE(from_rvalue->from_rvalue);
+  EXPECT_FALSE(from_rvalue->assigned);
+  from_rvalue = FromConstructibleAssignableRvalue{};
+  EXPECT_TRUE(from_rvalue->from_rvalue);
+  EXPECT_TRUE(from_rvalue->assigned);
+
+  absl::StatusOr<MockValue> from_implicit_constructible(
+      FromImplicitConstructibleOnly{});
+  EXPECT_FALSE(from_implicit_constructible->from_rvalue);
+  EXPECT_FALSE(from_implicit_constructible->assigned);
+  // construct a temporary `StatusOr` object and invoke the `StatusOr` move
+  // assignment operator.
+  from_implicit_constructible = FromImplicitConstructibleOnly{};
+  EXPECT_FALSE(from_implicit_constructible->from_rvalue);
+  EXPECT_FALSE(from_implicit_constructible->assigned);
+}
+
+TEST(StatusOr, TestStatus) {
+  absl::StatusOr<int> good(4);
+  EXPECT_TRUE(good.ok());
+  absl::StatusOr<int> bad(absl::CancelledError());
+  EXPECT_FALSE(bad.ok());
+  EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, OperatorStarRefQualifiers) {
+  static_assert(
+      std::is_same<const int&,
+                   decltype(*std::declval<const absl::StatusOr<int>&>())>(),
+      "Unexpected ref-qualifiers");
+  static_assert(
+      std::is_same<int&, decltype(*std::declval<absl::StatusOr<int>&>())>(),
+      "Unexpected ref-qualifiers");
+  static_assert(
+      std::is_same<const int&&,
+                   decltype(*std::declval<const absl::StatusOr<int>&&>())>(),
+      "Unexpected ref-qualifiers");
+  static_assert(
+      std::is_same<int&&, decltype(*std::declval<absl::StatusOr<int>&&>())>(),
+      "Unexpected ref-qualifiers");
+}
+
+TEST(StatusOr, OperatorStar) {
+  const absl::StatusOr<std::string> const_lvalue("hello");
+  EXPECT_EQ("hello", *const_lvalue);
+
+  absl::StatusOr<std::string> lvalue("hello");
+  EXPECT_EQ("hello", *lvalue);
+
+  // Note: Recall that std::move() is equivalent to a static_cast to an rvalue
+  // reference type.
+  const absl::StatusOr<std::string> const_rvalue("hello");
+  EXPECT_EQ("hello", *std::move(const_rvalue));  // NOLINT
+
+  absl::StatusOr<std::string> rvalue("hello");
+  EXPECT_EQ("hello", *std::move(rvalue));
+}
+
+TEST(StatusOr, OperatorArrowQualifiers) {
+  static_assert(
+      std::is_same<
+          const int*,
+          decltype(std::declval<const absl::StatusOr<int>&>().operator->())>(),
+      "Unexpected qualifiers");
+  static_assert(
+      std::is_same<
+          int*, decltype(std::declval<absl::StatusOr<int>&>().operator->())>(),
+      "Unexpected qualifiers");
+  static_assert(
+      std::is_same<
+          const int*,
+          decltype(std::declval<const absl::StatusOr<int>&&>().operator->())>(),
+      "Unexpected qualifiers");
+  static_assert(
+      std::is_same<
+          int*, decltype(std::declval<absl::StatusOr<int>&&>().operator->())>(),
+      "Unexpected qualifiers");
+}
+
+TEST(StatusOr, OperatorArrow) {
+  const absl::StatusOr<std::string> const_lvalue("hello");
+  EXPECT_EQ(std::string("hello"), const_lvalue->c_str());
+
+  absl::StatusOr<std::string> lvalue("hello");
+  EXPECT_EQ(std::string("hello"), lvalue->c_str());
+}
+
+TEST(StatusOr, RValueStatus) {
+  absl::StatusOr<int> so(absl::NotFoundError("taco"));
+  const absl::Status s = std::move(so).status();
+
+  EXPECT_EQ(s.code(), absl::StatusCode::kNotFound);
+  EXPECT_EQ(s.message(), "taco");
+
+  // Check that !ok() still implies !status().ok(), even after moving out of the
+  // object. See the note on the rvalue ref-qualified status method.
+  EXPECT_FALSE(so.ok());  // NOLINT
+  EXPECT_FALSE(so.status().ok());
+  EXPECT_EQ(so.status().code(), absl::StatusCode::kInternal);
+  EXPECT_EQ(so.status().message(), "Status accessed after move.");
+}
+
+TEST(StatusOr, TestValue) {
+  const int kI = 4;
+  absl::StatusOr<int> thing(kI);
+  EXPECT_EQ(kI, *thing);
+}
+
+TEST(StatusOr, TestValueConst) {
+  const int kI = 4;
+  const absl::StatusOr<int> thing(kI);
+  EXPECT_EQ(kI, *thing);
+}
+
+TEST(StatusOr, TestPointerDefaultCtor) {
+  absl::StatusOr<int*> thing;
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
+}
+
+
+
+TEST(StatusOr, TestPointerStatusCtor) {
+  absl::StatusOr<int*> thing(absl::CancelledError());
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerValueCtor) {
+  const int kI = 4;
+
+  // Construction from a non-null pointer
+  {
+    absl::StatusOr<const int*> so(&kI);
+    EXPECT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(&kI, *so);
+  }
+
+  // Construction from a null pointer constant
+  {
+    absl::StatusOr<const int*> so(nullptr);
+    EXPECT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(nullptr, *so);
+  }
+
+  // Construction from a non-literal null pointer
+  {
+    const int* const p = nullptr;
+
+    absl::StatusOr<const int*> so(p);
+    EXPECT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(nullptr, *so);
+  }
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOk) {
+  const int kI = 0;
+  absl::StatusOr<const int*> original(&kI);
+  absl::StatusOr<const int*> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
+  absl::StatusOr<int*> original(absl::CancelledError());
+  absl::StatusOr<int*> copy(original);
+  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
+  Derived derived;
+  absl::StatusOr<Derived*> original(&derived);
+  absl::StatusOr<Base2*> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(static_cast<const Base2*>(*original), *copy);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
+  absl::StatusOr<Derived*> original(absl::CancelledError());
+  absl::StatusOr<Base2*> copy(original);
+  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOk) {
+  const int kI = 0;
+  absl::StatusOr<const int*> source(&kI);
+  absl::StatusOr<const int*> target;
+  target = source;
+  EXPECT_OK(target.status());
+  EXPECT_EQ(*source, *target);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
+  absl::StatusOr<int*> source(absl::CancelledError());
+  absl::StatusOr<int*> target;
+  target = source;
+  EXPECT_EQ(target.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOKConverting) {
+  Derived derived;
+  absl::StatusOr<Derived*> source(&derived);
+  absl::StatusOr<Base2*> target;
+  target = source;
+  EXPECT_OK(target.status());
+  EXPECT_EQ(static_cast<const Base2*>(*source), *target);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
+  absl::StatusOr<Derived*> source(absl::CancelledError());
+  absl::StatusOr<Base2*> target;
+  target = source;
+  EXPECT_EQ(target.status(), source.status());
+}
+
+TEST(StatusOr, TestPointerStatus) {
+  const int kI = 0;
+  absl::StatusOr<const int*> good(&kI);
+  EXPECT_TRUE(good.ok());
+  absl::StatusOr<const int*> bad(absl::CancelledError());
+  EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerValue) {
+  const int kI = 0;
+  absl::StatusOr<const int*> thing(&kI);
+  EXPECT_EQ(&kI, *thing);
+}
+
+TEST(StatusOr, TestPointerValueConst) {
+  const int kI = 0;
+  const absl::StatusOr<const int*> thing(&kI);
+  EXPECT_EQ(&kI, *thing);
+}
+
+TEST(StatusOr, StatusOrVectorOfUniquePointerCanReserveAndResize) {
+  using EvilType = std::vector<std::unique_ptr<int>>;
+  static_assert(std::is_copy_constructible<EvilType>::value, "");
+  std::vector<::absl::StatusOr<EvilType>> v(5);
+  v.reserve(v.capacity() + 10);
+  v.resize(v.capacity() + 10);
+}
+
+TEST(StatusOr, ConstPayload) {
+  // A reduced version of a problematic type found in the wild. All of the
+  // operations below should compile.
+  absl::StatusOr<const int> a;
+
+  // Copy-construction
+  absl::StatusOr<const int> b(a);
+
+  // Copy-assignment
+  EXPECT_FALSE(std::is_copy_assignable<absl::StatusOr<const int>>::value);
+
+  // Move-construction
+  absl::StatusOr<const int> c(std::move(a));
+
+  // Move-assignment
+  EXPECT_FALSE(std::is_move_assignable<absl::StatusOr<const int>>::value);
+}
+
+TEST(StatusOr, MapToStatusOrUniquePtr) {
+  // A reduced version of a problematic type found in the wild. All of the
+  // operations below should compile.
+  using MapType = std::map<std::string, absl::StatusOr<std::unique_ptr<int>>>;
+
+  MapType a;
+
+  // Move-construction
+  MapType b(std::move(a));
+
+  // Move-assignment
+  a = std::move(b);
+}
+
+TEST(StatusOr, ValueOrOk) {
+  const absl::StatusOr<int> status_or = 0;
+  EXPECT_EQ(status_or.value_or(-1), 0);
+}
+
+TEST(StatusOr, ValueOrDefault) {
+  const absl::StatusOr<int> status_or = absl::CancelledError();
+  EXPECT_EQ(status_or.value_or(-1), -1);
+}
+
+TEST(StatusOr, MoveOnlyValueOrOk) {
+  EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0))
+                  .value_or(absl::make_unique<int>(-1)),
+              Pointee(0));
+}
+
+TEST(StatusOr, MoveOnlyValueOrDefault) {
+  EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::CancelledError())
+                  .value_or(absl::make_unique<int>(-1)),
+              Pointee(-1));
+}
+
+static absl::StatusOr<int> MakeStatus() { return 100; }
+
+TEST(StatusOr, TestIgnoreError) { MakeStatus().IgnoreError(); }
+
+TEST(StatusOr, EqualityOperator) {
+  constexpr int kNumCases = 4;
+  std::array<absl::StatusOr<int>, kNumCases> group1 = {
+      absl::StatusOr<int>(1), absl::StatusOr<int>(2),
+      absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
+      absl::StatusOr<int>(absl::InternalError("msg"))};
+  std::array<absl::StatusOr<int>, kNumCases> group2 = {
+      absl::StatusOr<int>(1), absl::StatusOr<int>(2),
+      absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
+      absl::StatusOr<int>(absl::InternalError("msg"))};
+  for (int i = 0; i < kNumCases; ++i) {
+    for (int j = 0; j < kNumCases; ++j) {
+      if (i == j) {
+        EXPECT_TRUE(group1[i] == group2[j]);
+        EXPECT_FALSE(group1[i] != group2[j]);
+      } else {
+        EXPECT_FALSE(group1[i] == group2[j]);
+        EXPECT_TRUE(group1[i] != group2[j]);
+      }
+    }
+  }
+}
+
+struct MyType {
+  bool operator==(const MyType&) const { return true; }
+};
+
+enum class ConvTraits { kNone = 0, kImplicit = 1, kExplicit = 2 };
+
+// This class has conversion operator to `StatusOr<T>` based on value of
+// `conv_traits`.
+template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
+struct StatusOrConversionBase {};
+
+template <typename T>
+struct StatusOrConversionBase<T, ConvTraits::kImplicit> {
+  operator absl::StatusOr<T>() const& {  // NOLINT
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+  operator absl::StatusOr<T>() && {  // NOLINT
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+};
+
+template <typename T>
+struct StatusOrConversionBase<T, ConvTraits::kExplicit> {
+  explicit operator absl::StatusOr<T>() const& {
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+  explicit operator absl::StatusOr<T>() && {
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+};
+
+// This class has conversion operator to `T` based on the value of
+// `conv_traits`.
+template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
+struct ConversionBase {};
+
+template <typename T>
+struct ConversionBase<T, ConvTraits::kImplicit> {
+  operator T() const& { return t; }         // NOLINT
+  operator T() && { return std::move(t); }  // NOLINT
+  T t;
+};
+
+template <typename T>
+struct ConversionBase<T, ConvTraits::kExplicit> {
+  explicit operator T() const& { return t; }
+  explicit operator T() && { return std::move(t); }
+  T t;
+};
+
+// This class has conversion operator to `absl::Status` based on the value of
+// `conv_traits`.
+template <ConvTraits conv_traits = ConvTraits::kNone>
+struct StatusConversionBase {};
+
+template <>
+struct StatusConversionBase<ConvTraits::kImplicit> {
+  operator absl::Status() const& {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+  operator absl::Status() && {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+};
+
+template <>
+struct StatusConversionBase<ConvTraits::kExplicit> {
+  explicit operator absl::Status() const& {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+  explicit operator absl::Status() && {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+};
+
+static constexpr int kConvToStatus = 1;
+static constexpr int kConvToStatusOr = 2;
+static constexpr int kConvToT = 4;
+static constexpr int kConvExplicit = 8;
+
+constexpr ConvTraits GetConvTraits(int bit, int config) {
+  return (config & bit) == 0
+             ? ConvTraits::kNone
+             : ((config & kConvExplicit) == 0 ? ConvTraits::kImplicit
+                                              : ConvTraits::kExplicit);
+}
+
+// This class conditionally has conversion operator to `absl::Status`, `T`,
+// `StatusOr<T>`, based on values of the template parameters.
+template <typename T, int config>
+struct CustomType
+    : StatusOrConversionBase<T, GetConvTraits(kConvToStatusOr, config)>,
+      ConversionBase<T, GetConvTraits(kConvToT, config)>,
+      StatusConversionBase<GetConvTraits(kConvToStatus, config)> {};
+
+struct ConvertibleToAnyStatusOr {
+  template <typename T>
+  operator absl::StatusOr<T>() const {  // NOLINT
+    return absl::InvalidArgumentError("Conversion to absl::StatusOr");
+  }
+};
+
+// Test the rank of overload resolution for `StatusOr<T>` constructor and
+// assignment, from highest to lowest:
+// 1. T/Status
+// 2. U that has conversion operator to absl::StatusOr<T>
+// 3. U that is convertible to Status
+// 4. U that is convertible to T
+TEST(StatusOr, ConstructionFromT) {
+  // Construct absl::StatusOr<T> from T when T is convertible to
+  // absl::StatusOr<T>
+  {
+    ConvertibleToAnyStatusOr v;
+    absl::StatusOr<ConvertibleToAnyStatusOr> statusor(v);
+    EXPECT_TRUE(statusor.ok());
+  }
+  {
+    ConvertibleToAnyStatusOr v;
+    absl::StatusOr<ConvertibleToAnyStatusOr> statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+  // Construct absl::StatusOr<T> from T when T is explicitly convertible to
+  // Status
+  {
+    CustomType<MyType, kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor(
+        v);
+    EXPECT_TRUE(statusor.ok());
+  }
+  {
+    CustomType<MyType, kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor =
+        v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+// Construct absl::StatusOr<T> from U when U is explicitly convertible to T
+TEST(StatusOr, ConstructionFromTypeConvertibleToT) {
+  {
+    CustomType<MyType, kConvToT | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_TRUE(statusor.ok());
+  }
+  {
+    CustomType<MyType, kConvToT> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+// Construct absl::StatusOr<T> from U when U has explicit conversion operator to
+// absl::StatusOr<T>
+TEST(StatusOr, ConstructionFromTypeWithConversionOperatorToStatusOrT) {
+  {
+    CustomType<MyType, kConvToStatusOr | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr | kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType,
+               kConvToT | kConvToStatusOr | kConvToStatus | kConvExplicit>
+        v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+}
+
+TEST(StatusOr, ConstructionFromTypeConvertibleToStatus) {
+  // Construction fails because conversion to `Status` is explicit.
+  {
+    CustomType<MyType, kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+}
+
+TEST(StatusOr, AssignmentFromT) {
+  // Assign to absl::StatusOr<T> from T when T is convertible to
+  // absl::StatusOr<T>
+  {
+    ConvertibleToAnyStatusOr v;
+    absl::StatusOr<ConvertibleToAnyStatusOr> statusor;
+    statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+  // Assign to absl::StatusOr<T> from T when T is convertible to Status
+  {
+    CustomType<MyType, kConvToStatus> v;
+    absl::StatusOr<CustomType<MyType, kConvToStatus>> statusor;
+    statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+TEST(StatusOr, AssignmentFromTypeConvertibleToT) {
+  // Assign to absl::StatusOr<T> from U when U is convertible to T
+  {
+    CustomType<MyType, kConvToT> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+TEST(StatusOr, AssignmentFromTypeWithConversionOperatortoStatusOrT) {
+  // Assign to absl::StatusOr<T> from U when U has conversion operator to
+  // absl::StatusOr<T>
+  {
+    CustomType<MyType, kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+}
+
+TEST(StatusOr, AssignmentFromTypeConvertibleToStatus) {
+  // Assign to absl::StatusOr<T> from U when U is convertible to Status
+  {
+    CustomType<MyType, kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+}
+
+}  // namespace
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index 64a13ce..30a8dd2 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -54,6 +54,7 @@
         "ascii.h",
         "charconv.h",
         "escaping.h",
+        "internal/string_constant.h",
         "match.h",
         "numbers.h",
         "str_cat.h",
@@ -223,6 +224,19 @@
 )
 
 cc_test(
+    name = "string_constant_test",
+    size = "small",
+    srcs = ["internal/string_constant_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":strings",
+        "//absl/meta:type_traits",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
     name = "string_view_benchmark",
     srcs = ["string_view_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
diff --git a/absl/strings/BUILD.gn b/absl/strings/BUILD.gn
index 327ee49..4495790 100644
--- a/absl/strings/BUILD.gn
+++ b/absl/strings/BUILD.gn
@@ -31,6 +31,7 @@
     "ascii.h",
     "charconv.h",
     "escaping.h",
+    "internal/string_constant.h",
     "match.h",
     "numbers.h",
     "str_cat.h",
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index d6c2126..2b994a7 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -21,6 +21,7 @@
     "ascii.h"
     "charconv.h"
     "escaping.h"
+    "internal/string_constant.h"
     "match.h"
     "numbers.h"
     "str_cat.h"
@@ -160,6 +161,19 @@
 
 absl_cc_test(
   NAME
+    string_constant_test
+  SRCS
+    "internal/string_constant_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::type_traits
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
     string_view_test
   SRCS
     "string_view_test.cc"
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
index 763dcc4..9efd135 100644
--- a/absl/strings/cord.cc
+++ b/absl/strings/cord.cc
@@ -50,16 +50,10 @@
 using ::absl::cord_internal::CordRepExternal;
 using ::absl::cord_internal::CordRepSubstring;
 
-// Various representations that we allow
-enum CordRepKind {
-  CONCAT        = 0,
-  EXTERNAL      = 1,
-  SUBSTRING     = 2,
-
-  // We have different tags for different sized flat arrays,
-  // starting with FLAT
-  FLAT          = 3,
-};
+using ::absl::cord_internal::CONCAT;
+using ::absl::cord_internal::EXTERNAL;
+using ::absl::cord_internal::FLAT;
+using ::absl::cord_internal::SUBSTRING;
 
 namespace cord_internal {
 
@@ -247,6 +241,7 @@
 
   absl::InlinedVector<CordRep*, kInlinedVectorSize> pending;
   while (true) {
+    assert(!rep->refcount.IsImmortal());
     if (rep->tag == CONCAT) {
       CordRepConcat* rep_concat = rep->concat();
       CordRep* right = rep_concat->right;
@@ -262,6 +257,7 @@
       }
     } else if (rep->tag == EXTERNAL) {
       CordRepExternal* rep_external = rep->external();
+      assert(rep_external->releaser_invoker != nullptr);
       rep_external->releaser_invoker(rep_external);
       rep = nullptr;
     } else if (rep->tag == SUBSTRING) {
@@ -447,48 +443,49 @@
                                       bool nullify_tail) {
   static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
 
-  cord_internal::SmallMemmove(data_, data, n, nullify_tail);
-  data_[kMaxInline] = static_cast<char>(n);
+  cord_internal::SmallMemmove(data_.as_chars, data, n, nullify_tail);
+  set_tagged_size(static_cast<char>(n));
 }
 
 inline char* Cord::InlineRep::set_data(size_t n) {
   assert(n <= kMaxInline);
-  memset(data_, 0, sizeof(data_));
-  data_[kMaxInline] = static_cast<char>(n);
-  return data_;
+  ResetToEmpty();
+  set_tagged_size(static_cast<char>(n));
+  return data_.as_chars;
 }
 
 inline CordRep* Cord::InlineRep::force_tree(size_t extra_hint) {
-  size_t len = data_[kMaxInline];
-  CordRep* result;
+  size_t len = tagged_size();
   if (len > kMaxInline) {
-    memcpy(&result, data_, sizeof(result));
-  } else {
-    result = NewFlat(len + extra_hint);
-    result->length = len;
-    memcpy(result->data, data_, len);
-    set_tree(result);
+    return data_.as_tree.rep;
   }
+
+  CordRep* result = NewFlat(len + extra_hint);
+  result->length = len;
+  static_assert(kMinFlatLength >= sizeof(data_.as_chars), "");
+  memcpy(result->data, data_.as_chars, sizeof(data_.as_chars));
+  set_tree(result);
   return result;
 }
 
 inline void Cord::InlineRep::reduce_size(size_t n) {
-  size_t tag = data_[kMaxInline];
+  size_t tag = tagged_size();
   assert(tag <= kMaxInline);
   assert(tag >= n);
   tag -= n;
-  memset(data_ + tag, 0, n);
-  data_[kMaxInline] = static_cast<char>(tag);
+  memset(data_.as_chars + tag, 0, n);
+  set_tagged_size(static_cast<char>(tag));
 }
 
 inline void Cord::InlineRep::remove_prefix(size_t n) {
-  cord_internal::SmallMemmove(data_, data_ + n, data_[kMaxInline] - n);
+  cord_internal::SmallMemmove(data_.as_chars, data_.as_chars + n,
+                              tagged_size() - n);
   reduce_size(n);
 }
 
 void Cord::InlineRep::AppendTree(CordRep* tree) {
   if (tree == nullptr) return;
-  size_t len = data_[kMaxInline];
+  size_t len = tagged_size();
   if (len == 0) {
     set_tree(tree);
   } else {
@@ -498,7 +495,7 @@
 
 void Cord::InlineRep::PrependTree(CordRep* tree) {
   assert(tree != nullptr);
-  size_t len = data_[kMaxInline];
+  size_t len = tagged_size();
   if (len == 0) {
     set_tree(tree);
   } else {
@@ -554,11 +551,11 @@
   }
 
   // Try to fit in the inline buffer if possible.
-  size_t inline_length = data_[kMaxInline];
+  size_t inline_length = tagged_size();
   if (inline_length < kMaxInline && max_length <= kMaxInline - inline_length) {
-    *region = data_ + inline_length;
+    *region = data_.as_chars + inline_length;
     *size = max_length;
-    data_[kMaxInline] = static_cast<char>(inline_length + max_length);
+    set_tagged_size(static_cast<char>(inline_length + max_length));
     return;
   }
 
@@ -582,11 +579,11 @@
   const size_t max_length = std::numeric_limits<size_t>::max();
 
   // Try to fit in the inline buffer if possible.
-  size_t inline_length = data_[kMaxInline];
+  size_t inline_length = tagged_size();
   if (inline_length < kMaxInline) {
-    *region = data_ + inline_length;
+    *region = data_.as_chars + inline_length;
     *size = kMaxInline - inline_length;
-    data_[kMaxInline] = kMaxInline;
+    set_tagged_size(kMaxInline);
     return;
   }
 
@@ -621,7 +618,7 @@
 void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
   ClearSlow();
 
-  memcpy(data_, src.data_, sizeof(data_));
+  data_ = src.data_;
   if (is_tree()) {
     Ref(tree());
   }
@@ -631,7 +628,7 @@
   if (is_tree()) {
     Unref(tree());
   }
-  memset(data_, 0, sizeof(data_));
+  ResetToEmpty();
 }
 
 // --------------------------------------------------------------------
@@ -735,11 +732,11 @@
 void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
   if (src_size == 0) return;  // memcpy(_, nullptr, 0) is undefined.
   // Try to fit in the inline buffer if possible.
-  size_t inline_length = data_[kMaxInline];
+  size_t inline_length = tagged_size();
   if (inline_length < kMaxInline && src_size <= kMaxInline - inline_length) {
     // Append new data to embedded array
-    data_[kMaxInline] = static_cast<char>(inline_length + src_size);
-    memcpy(data_ + inline_length, src_data, src_size);
+    set_tagged_size(static_cast<char>(inline_length + src_size));
+    memcpy(data_.as_chars + inline_length, src_data, src_size);
     return;
   }
 
@@ -762,7 +759,7 @@
     const size_t size2 = inline_length + src_size / 10;
     root = NewFlat(std::max<size_t>(size1, size2));
     appended = std::min(src_size, TagToLength(root->tag) - inline_length);
-    memcpy(root->data, data_, inline_length);
+    memcpy(root->data, data_.as_chars, inline_length);
     memcpy(root->data + inline_length, src_data, appended);
     root->length = inline_length + appended;
     set_tree(root);
@@ -1071,7 +1068,7 @@
   } else if (new_size <= InlineRep::kMaxInline) {
     Cord::ChunkIterator it = chunk_begin();
     it.AdvanceBytes(pos);
-    char* dest = sub_cord.contents_.data_;
+    char* dest = sub_cord.contents_.data_.as_chars;
     size_t remaining_size = new_size;
     while (remaining_size > it->size()) {
       cord_internal::SmallMemmove(dest, it->data(), it->size());
@@ -1080,7 +1077,7 @@
       ++it;
     }
     cord_internal::SmallMemmove(dest, it->data(), remaining_size);
-    sub_cord.contents_.data_[InlineRep::kMaxInline] = new_size;
+    sub_cord.contents_.set_tagged_size(new_size);
   } else {
     sub_cord.contents_.set_tree(NewSubRange(tree, pos, new_size));
   }
@@ -1269,9 +1266,9 @@
 // Helper routine. Locates the first flat chunk of the Cord without
 // initializing the iterator.
 inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
-  size_t n = data_[kMaxInline];
+  size_t n = tagged_size();
   if (n <= kMaxInline) {
-    return absl::string_view(data_, n);
+    return absl::string_view(data_.as_chars, n);
   }
 
   CordRep* node = tree();
diff --git a/absl/strings/cord.h b/absl/strings/cord.h
index b8b251b..5d5c897 100644
--- a/absl/strings/cord.h
+++ b/absl/strings/cord.h
@@ -79,6 +79,7 @@
 #include "absl/meta/type_traits.h"
 #include "absl/strings/internal/cord_internal.h"
 #include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/internal/string_constant.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
 
@@ -624,6 +625,14 @@
     return c.HashFragmented(std::move(hash_state));
   }
 
+  // Create a Cord with the contents of StringConstant<T>::value.
+  // No allocations will be done and no data will be copied.
+  // This is an INTERNAL API and subject to change or removal. This API can only
+  // be used by spelling absl::strings_internal::MakeStringConstant, which is
+  // also an internal API.
+  template <typename T>
+  explicit constexpr Cord(strings_internal::StringConstant<T>);
+
  private:
   friend class CordTestPeer;
   friend bool operator==(const Cord& lhs, const Cord& rhs);
@@ -644,19 +653,19 @@
   // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.
   class InlineRep {
    public:
-    static constexpr unsigned char kMaxInline = 15;
+    static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
     static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");
-    // Tag byte & kMaxInline means we are storing a pointer.
-    static constexpr unsigned char kTreeFlag = 1 << 4;
-    // Tag byte & kProfiledFlag means we are profiling the Cord.
-    static constexpr unsigned char kProfiledFlag = 1 << 5;
+    static constexpr unsigned char kTreeFlag = cord_internal::kTreeFlag;
+    static constexpr unsigned char kProfiledFlag = cord_internal::kProfiledFlag;
 
-    constexpr InlineRep() : data_{} {}
+    constexpr InlineRep() : data_() {}
     InlineRep(const InlineRep& src);
     InlineRep(InlineRep&& src);
     InlineRep& operator=(const InlineRep& src);
     InlineRep& operator=(InlineRep&& src) noexcept;
 
+    explicit constexpr InlineRep(cord_internal::InlineData data);
+
     void Swap(InlineRep* rhs);
     bool empty() const;
     size_t size() const;
@@ -684,16 +693,16 @@
     void GetAppendRegion(char** region, size_t* size, size_t max_length);
     void GetAppendRegion(char** region, size_t* size);
     bool IsSame(const InlineRep& other) const {
-      return memcmp(data_, other.data_, sizeof(data_)) == 0;
+      return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
     }
     int BitwiseCompare(const InlineRep& other) const {
       uint64_t x, y;
-      // Use memcpy to avoid anti-aliasing issues.
-      memcpy(&x, data_, sizeof(x));
-      memcpy(&y, other.data_, sizeof(y));
+      // Use memcpy to avoid aliasing issues.
+      memcpy(&x, &data_, sizeof(x));
+      memcpy(&y, &other.data_, sizeof(y));
       if (x == y) {
-        memcpy(&x, data_ + 8, sizeof(x));
-        memcpy(&y, other.data_ + 8, sizeof(y));
+        memcpy(&x, reinterpret_cast<const char*>(&data_) + 8, sizeof(x));
+        memcpy(&y, reinterpret_cast<const char*>(&other.data_) + 8, sizeof(y));
         if (x == y) return 0;
       }
       return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y)
@@ -706,16 +715,16 @@
       // to 15 bytes does not cause a memory allocation.
       absl::strings_internal::STLStringResizeUninitialized(dst,
                                                            sizeof(data_) - 1);
-      memcpy(&(*dst)[0], data_, sizeof(data_) - 1);
+      memcpy(&(*dst)[0], &data_, sizeof(data_) - 1);
       // erase is faster than resize because the logic for memory allocation is
       // not needed.
-      dst->erase(data_[kMaxInline]);
+      dst->erase(tagged_size());
     }
 
     // Copies the inline contents into `dst`. Assumes the cord is not empty.
     void CopyToArray(char* dst) const;
 
-    bool is_tree() const { return data_[kMaxInline] > kMaxInline; }
+    bool is_tree() const { return tagged_size() > kMaxInline; }
 
    private:
     friend class Cord;
@@ -724,10 +733,18 @@
     // Unrefs the tree, stops profiling, and zeroes the contents
     void ClearSlow();
 
-    // If the data has length <= kMaxInline, we store it in data_[0..len-1],
-    // and store the length in data_[kMaxInline].  Else we store it in a tree
-    // and store a pointer to that tree in data_[0..sizeof(CordRep*)-1].
-    alignas(absl::cord_internal::CordRep*) char data_[kMaxInline + 1];
+    void ResetToEmpty() { data_ = {}; }
+
+    // This uses reinterpret_cast instead of the union to avoid accessing the
+    // inactive union element. The tagged size is not a common prefix.
+    void set_tagged_size(char new_tag) {
+      reinterpret_cast<char*>(&data_)[kMaxInline] = new_tag;
+    }
+    char tagged_size() const {
+      return reinterpret_cast<const char*>(&data_)[kMaxInline];
+    }
+
+    cord_internal::InlineData data_;
   };
   InlineRep contents_;
 
@@ -878,13 +895,16 @@
   return cord;
 }
 
+constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
+    : data_(data) {}
+
 inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src) {
-  cord_internal::SmallMemmove(data_, src.data_, sizeof(data_));
+  data_ = src.data_;
 }
 
 inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) {
-  memcpy(data_, src.data_, sizeof(data_));
-  memset(src.data_, 0, sizeof(data_));
+  data_ = src.data_;
+  src.ResetToEmpty();
 }
 
 inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
@@ -892,7 +912,7 @@
     return *this;
   }
   if (!is_tree() && !src.is_tree()) {
-    cord_internal::SmallMemmove(data_, src.data_, sizeof(data_));
+    data_ = src.data_;
     return *this;
   }
   AssignSlow(src);
@@ -904,8 +924,8 @@
   if (is_tree()) {
     ClearSlow();
   }
-  memcpy(data_, src.data_, sizeof(data_));
-  memset(src.data_, 0, sizeof(data_));
+  data_ = src.data_;
+  src.ResetToEmpty();
   return *this;
 }
 
@@ -914,43 +934,39 @@
     return;
   }
 
-  Cord::InlineRep tmp;
-  cord_internal::SmallMemmove(tmp.data_, data_, sizeof(data_));
-  cord_internal::SmallMemmove(data_, rhs->data_, sizeof(data_));
-  cord_internal::SmallMemmove(rhs->data_, tmp.data_, sizeof(data_));
+  std::swap(data_, rhs->data_);
 }
 
 inline const char* Cord::InlineRep::data() const {
-  return is_tree() ? nullptr : data_;
+  return is_tree() ? nullptr : data_.as_chars;
 }
 
 inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const {
   if (is_tree()) {
-    absl::cord_internal::CordRep* rep;
-    memcpy(&rep, data_, sizeof(rep));
-    return rep;
+    return data_.as_tree.rep;
   } else {
     return nullptr;
   }
 }
 
-inline bool Cord::InlineRep::empty() const { return data_[kMaxInline] == 0; }
+inline bool Cord::InlineRep::empty() const { return tagged_size() == 0; }
 
 inline size_t Cord::InlineRep::size() const {
-  const char tag = data_[kMaxInline];
+  const char tag = tagged_size();
   if (tag <= kMaxInline) return tag;
   return static_cast<size_t>(tree()->length);
 }
 
 inline void Cord::InlineRep::set_tree(absl::cord_internal::CordRep* rep) {
   if (rep == nullptr) {
-    memset(data_, 0, sizeof(data_));
+    ResetToEmpty();
   } else {
     bool was_tree = is_tree();
-    memcpy(data_, &rep, sizeof(rep));
-    memset(data_ + sizeof(rep), 0, sizeof(data_) - sizeof(rep) - 1);
+    data_.as_tree = {rep, {}, tagged_size()};
     if (!was_tree) {
-      data_[kMaxInline] = kTreeFlag;
+      // If we were not a tree already, set the tag.
+      // Otherwise, leave it alone because it might have the profile bit on.
+      set_tagged_size(kTreeFlag);
     }
   }
 }
@@ -961,29 +977,36 @@
     set_tree(rep);
     return;
   }
-  memcpy(data_, &rep, sizeof(rep));
-  memset(data_ + sizeof(rep), 0, sizeof(data_) - sizeof(rep) - 1);
+  data_.as_tree = {rep, {}, tagged_size()};
 }
 
 inline absl::cord_internal::CordRep* Cord::InlineRep::clear() {
-  const char tag = data_[kMaxInline];
-  absl::cord_internal::CordRep* result = nullptr;
-  if (tag > kMaxInline) {
-    memcpy(&result, data_, sizeof(result));
-  }
-  memset(data_, 0, sizeof(data_));  // Clear the cord
+  absl::cord_internal::CordRep* result = tree();
+  ResetToEmpty();
   return result;
 }
 
 inline void Cord::InlineRep::CopyToArray(char* dst) const {
   assert(!is_tree());
-  size_t n = data_[kMaxInline];
+  size_t n = tagged_size();
   assert(n != 0);
-  cord_internal::SmallMemmove(dst, data_, n);
+  cord_internal::SmallMemmove(dst, data_.as_chars, n);
 }
 
 constexpr inline Cord::Cord() noexcept {}
 
+template <typename T>
+constexpr Cord::Cord(strings_internal::StringConstant<T>)
+    : contents_(strings_internal::StringConstant<T>::value.size() <=
+                        cord_internal::kMaxInline
+                    ? cord_internal::InlineData(
+                          strings_internal::StringConstant<T>::value)
+                    : cord_internal::InlineData(cord_internal::AsTree{
+                          &cord_internal::ConstInitExternalStorage<
+                              strings_internal::StringConstant<T>>::value,
+                          {},
+                          cord_internal::kTreeFlag})) {}
+
 inline Cord& Cord::operator=(const Cord& x) {
   contents_ = x.contents_;
   return *this;
diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc
index 4443c82..7942bfc 100644
--- a/absl/strings/cord_test.cc
+++ b/absl/strings/cord_test.cc
@@ -1,3 +1,17 @@
+// 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/strings/cord.h"
 
 #include <algorithm>
@@ -167,6 +181,8 @@
       const Cord& c, absl::FunctionRef<void(absl::string_view)> callback) {
     c.ForEachChunk(callback);
   }
+
+  static bool IsTree(const Cord& c) { return c.contents_.is_tree(); }
 };
 
 ABSL_NAMESPACE_END
@@ -1613,3 +1629,83 @@
   EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), "");
   EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), "");
 }
+
+class AfterExitCordTester {
+ public:
+  bool Set(absl::Cord* cord, absl::string_view expected) {
+    cord_ = cord;
+    expected_ = expected;
+    return true;
+  }
+
+  ~AfterExitCordTester() {
+    EXPECT_EQ(*cord_, expected_);
+  }
+ private:
+  absl::Cord* cord_;
+  absl::string_view expected_;
+};
+
+template <typename Str>
+void TestConstinitConstructor(Str) {
+  const auto expected = Str::value;
+  // Defined before `cord` to be destroyed after it.
+  static AfterExitCordTester exit_tester;  // NOLINT
+  ABSL_CONST_INIT static absl::Cord cord(Str{});  // NOLINT
+  static bool init_exit_tester = exit_tester.Set(&cord, expected);
+  (void)init_exit_tester;
+
+  EXPECT_EQ(cord, expected);
+  // Copy the object and test the copy, and the original.
+  {
+    absl::Cord copy = cord;
+    EXPECT_EQ(copy, expected);
+  }
+  // The original still works
+  EXPECT_EQ(cord, expected);
+
+  // Try making adding more structure to the tree.
+  {
+    absl::Cord copy = cord;
+    std::string expected_copy(expected);
+    for (int i = 0; i < 10; ++i) {
+      copy.Append(cord);
+      absl::StrAppend(&expected_copy, expected);
+      EXPECT_EQ(copy, expected_copy);
+    }
+  }
+
+  // Make sure we are using the right branch during constant evaluation.
+  EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16);
+
+  for (int i = 0; i < 10; ++i) {
+    // Make a few more Cords from the same global rep.
+    // This tests what happens when the refcount for it gets below 1.
+    EXPECT_EQ(expected, absl::Cord(Str{}));
+  }
+}
+
+constexpr int SimpleStrlen(const char* p) {
+  return *p ? 1 + SimpleStrlen(p + 1) : 0;
+}
+
+struct ShortView {
+  constexpr absl::string_view operator()() const {
+    return absl::string_view("SSO string", SimpleStrlen("SSO string"));
+  }
+};
+
+struct LongView {
+  constexpr absl::string_view operator()() const {
+    return absl::string_view("String that does not fit SSO.",
+                             SimpleStrlen("String that does not fit SSO."));
+  }
+};
+
+
+TEST(Cord, ConstinitConstructor) {
+  TestConstinitConstructor(
+      absl::strings_internal::MakeStringConstant(ShortView{}));
+  TestConstinitConstructor(
+      absl::strings_internal::MakeStringConstant(LongView{}));
+}
diff --git a/absl/strings/internal/charconv_bigint_test.cc b/absl/strings/internal/charconv_bigint_test.cc
index 363bcb0..a8b9945 100644
--- a/absl/strings/internal/charconv_bigint_test.cc
+++ b/absl/strings/internal/charconv_bigint_test.cc
@@ -69,6 +69,61 @@
     // And we should have fully rotated all bits off by now:
     EXPECT_EQ(a, BigUnsigned<84>(0u));
   }
+  {
+    // Bit shifting large and small numbers by large and small offsets.
+    // Intended to exercise bounds-checking corner on ShiftLeft() (directly
+    // and under asan).
+
+    // 2**(32*84)-1
+    const BigUnsigned<84> all_bits_one(
+        "1474444211396924248063325089479706787923460402125687709454567433186613"
+        "6228083464060749874845919674257665016359189106695900028098437021384227"
+        "3285029708032466536084583113729486015826557532750465299832071590813090"
+        "2011853039837649252477307070509704043541368002938784757296893793903797"
+        "8180292336310543540677175225040919704702800559606097685920595947397024"
+        "8303316808753252115729411497720357971050627997031988036134171378490368"
+        "6008000778741115399296162550786288457245180872759047016734959330367829"
+        "5235612397427686310674725251378116268607113017720538636924549612987647"
+        "5767411074510311386444547332882472126067840027882117834454260409440463"
+        "9345147252664893456053258463203120637089916304618696601333953616715125"
+        "2115882482473279040772264257431663818610405673876655957323083702713344"
+        "4201105427930770976052393421467136557055");
+    const BigUnsigned<84> zero(0u);
+    const BigUnsigned<84> one(1u);
+    // in bounds shifts
+    for (int i = 1; i < 84*32; ++i) {
+      // shifting all_bits_one to the left should result in a smaller number,
+      // since the high bits rotate off and the low bits are replaced with
+      // zeroes.
+      BigUnsigned<84> big_shifted = all_bits_one;
+      big_shifted.ShiftLeft(i);
+      EXPECT_GT(all_bits_one, big_shifted);
+      // Shifting 1 to the left should instead result in a larger number.
+      BigUnsigned<84> small_shifted = one;
+      small_shifted.ShiftLeft(i);
+      EXPECT_LT(one, small_shifted);
+    }
+    // Shifting by zero or a negative number has no effect
+    for (int no_op_shift : {0, -1, -84 * 32, std::numeric_limits<int>::min()}) {
+      BigUnsigned<84> big_shifted = all_bits_one;
+      big_shifted.ShiftLeft(no_op_shift);
+      EXPECT_EQ(all_bits_one, big_shifted);
+      BigUnsigned<84> small_shifted = one;
+      big_shifted.ShiftLeft(no_op_shift);
+      EXPECT_EQ(one, small_shifted);
+    }
+    // Shifting by an amount greater than the number of bits should result in
+    // zero.
+    for (int out_of_bounds_shift :
+         {84 * 32, 84 * 32 + 1, std::numeric_limits<int>::max()}) {
+      BigUnsigned<84> big_shifted = all_bits_one;
+      big_shifted.ShiftLeft(out_of_bounds_shift);
+      EXPECT_EQ(zero, big_shifted);
+      BigUnsigned<84> small_shifted = one;
+      small_shifted.ShiftLeft(out_of_bounds_shift);
+      EXPECT_EQ(zero, small_shifted);
+    }
+  }
 }
 
 TEST(BigUnsigned, MultiplyByUint32) {
diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc
index fd6d948..8b11868 100644
--- a/absl/strings/internal/charconv_parse.cc
+++ b/absl/strings/internal/charconv_parse.cc
@@ -246,8 +246,8 @@
 // ConsumeDigits does not protect against overflow on *out; max_digits must
 // be chosen with respect to type T to avoid the possibility of overflow.
 template <int base, typename T>
-std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits,
-                          T* out, bool* dropped_nonzero_digit) {
+int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
+                  bool* dropped_nonzero_digit) {
   if (base == 10) {
     assert(max_digits <= std::numeric_limits<T>::digits10);
   } else if (base == 16) {
@@ -282,7 +282,7 @@
     *dropped_nonzero_digit = true;
   }
   *out = accumulator;
-  return begin - original_begin;
+  return static_cast<int>(begin - original_begin);
 }
 
 // Returns true if `v` is one of the chars allowed inside parentheses following
@@ -372,7 +372,7 @@
 
   int exponent_adjustment = 0;
   bool mantissa_is_inexact = false;
-  std::size_t pre_decimal_digits = ConsumeDigits<base>(
+  int pre_decimal_digits = ConsumeDigits<base>(
       begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
   begin += pre_decimal_digits;
   int digits_left;
@@ -398,14 +398,14 @@
       while (begin < end && *begin == '0') {
         ++begin;
       }
-      std::size_t zeros_skipped = begin - begin_zeros;
+      int zeros_skipped = static_cast<int>(begin - begin_zeros);
       if (zeros_skipped >= DigitLimit<base>()) {
         // refuse to parse pathological inputs
         return result;
       }
       exponent_adjustment -= static_cast<int>(zeros_skipped);
     }
-    std::size_t post_decimal_digits = ConsumeDigits<base>(
+    int post_decimal_digits = ConsumeDigits<base>(
         begin, end, digits_left, &mantissa, &mantissa_is_inexact);
     begin += post_decimal_digits;
 
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h
index d456eef..aa91a69 100644
--- a/absl/strings/internal/cord_internal.h
+++ b/absl/strings/internal/cord_internal.h
@@ -33,14 +33,17 @@
 // Wraps std::atomic for reference counting.
 class Refcount {
  public:
-  Refcount() : count_{1} {}
-  ~Refcount() {}
+  constexpr Refcount() : count_{kRefIncrement} {}
+  struct Immortal {};
+  explicit constexpr Refcount(Immortal) : count_(kImmortalTag) {}
 
-  // Increments the reference count by 1. Imposes no memory ordering.
-  inline void Increment() { count_.fetch_add(1, std::memory_order_relaxed); }
+  // Increments the reference count. Imposes no memory ordering.
+  inline void Increment() {
+    count_.fetch_add(kRefIncrement, std::memory_order_relaxed);
+  }
 
   // Asserts that the current refcount is greater than 0. If the refcount is
-  // greater than 1, decrements the reference count by 1.
+  // greater than 1, decrements the reference count.
   //
   // Returns false if there are no references outstanding; true otherwise.
   // Inserts barriers to ensure that state written before this method returns
@@ -48,19 +51,24 @@
   // false.
   inline bool Decrement() {
     int32_t refcount = count_.load(std::memory_order_acquire);
-    assert(refcount > 0);
-    return refcount != 1 && count_.fetch_sub(1, std::memory_order_acq_rel) != 1;
+    assert(refcount > 0 || refcount & kImmortalTag);
+    return refcount != kRefIncrement &&
+           count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) !=
+               kRefIncrement;
   }
 
   // Same as Decrement but expect that refcount is greater than 1.
   inline bool DecrementExpectHighRefcount() {
-    int32_t refcount = count_.fetch_sub(1, std::memory_order_acq_rel);
-    assert(refcount > 0);
-    return refcount != 1;
+    int32_t refcount =
+        count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel);
+    assert(refcount > 0 || refcount & kImmortalTag);
+    return refcount != kRefIncrement;
   }
 
   // Returns the current reference count using acquire semantics.
-  inline int32_t Get() const { return count_.load(std::memory_order_acquire); }
+  inline int32_t Get() const {
+    return count_.load(std::memory_order_acquire) >> kImmortalShift;
+  }
 
   // Returns whether the atomic integer is 1.
   // If the reference count is used in the conventional way, a
@@ -70,9 +78,27 @@
   // performs the memory barrier needed for the owning thread
   // to act on the object, knowing that it has exclusive access to the
   // object.
-  inline bool IsOne() { return count_.load(std::memory_order_acquire) == 1; }
+  inline bool IsOne() {
+    return count_.load(std::memory_order_acquire) == kRefIncrement;
+  }
+
+  bool IsImmortal() const {
+    return (count_.load(std::memory_order_relaxed) & kImmortalTag) != 0;
+  }
 
  private:
+  // We reserve the bottom bit to tag a reference count as immortal.
+  // By making it `1` we ensure that we never reach `0` when adding/subtracting
+  // `2`, thus it never looks as if it should be destroyed.
+  // These are used for the StringConstant constructor where we do not increase
+  // the refcount at construction time (due to constinit requirements) but we
+  // will still decrease it at destruction time to avoid branching on Unref.
+  enum {
+    kImmortalShift = 1,
+    kRefIncrement = 1 << kImmortalShift,
+    kImmortalTag = kRefIncrement - 1
+  };
+
   std::atomic<int32_t> count_;
 };
 
@@ -85,7 +111,22 @@
 struct CordRepSubstring;
 struct CordRepExternal;
 
+// Various representations that we allow
+enum CordRepKind {
+  CONCAT        = 0,
+  EXTERNAL      = 1,
+  SUBSTRING     = 2,
+
+  // We have different tags for different sized flat arrays,
+  // starting with FLAT
+  FLAT          = 3,
+};
+
 struct CordRep {
+  CordRep() = default;
+  constexpr CordRep(Refcount::Immortal immortal, size_t l)
+      : length(l), refcount(immortal), tag(EXTERNAL), data{} {}
+
   // The following three fields have to be less than 32 bytes since
   // that is the smallest supported flat node size.
   size_t length;
@@ -124,6 +165,12 @@
 // External CordReps are allocated together with a type erased releaser. The
 // releaser is stored in the memory directly following the CordRepExternal.
 struct CordRepExternal : public CordRep {
+  CordRepExternal() = default;
+  explicit constexpr CordRepExternal(absl::string_view str)
+      : CordRep(Refcount::Immortal{}, str.size()),
+        base(str.data()),
+        releaser_invoker(nullptr) {}
+
   const char* base;
   // Pointer to function that knows how to call and destroy the releaser.
   ExternalReleaserInvoker releaser_invoker;
@@ -167,6 +214,56 @@
   }
 };
 
+template <typename Str>
+struct ConstInitExternalStorage {
+  ABSL_CONST_INIT static CordRepExternal value;
+};
+
+template <typename Str>
+CordRepExternal ConstInitExternalStorage<Str>::value(Str::value);
+
+enum {
+  kMaxInline = 15,
+  // Tag byte & kMaxInline means we are storing a pointer.
+  kTreeFlag = 1 << 4,
+  // Tag byte & kProfiledFlag means we are profiling the Cord.
+  kProfiledFlag = 1 << 5
+};
+
+// If the data has length <= kMaxInline, we store it in `as_chars`, and
+// store the size in `tagged_size`.
+// Else we store it in a tree and store a pointer to that tree in
+// `as_tree.rep` and store a tag in `tagged_size`.
+struct AsTree {
+  absl::cord_internal::CordRep* rep;
+  char padding[kMaxInline + 1 - sizeof(absl::cord_internal::CordRep*) - 1];
+  char tagged_size;
+};
+
+constexpr char GetOrNull(absl::string_view data, size_t pos) {
+  return pos < data.size() ? data[pos] : '\0';
+}
+
+union InlineData {
+  constexpr InlineData() : as_chars{} {}
+  explicit constexpr InlineData(AsTree tree) : as_tree(tree) {}
+  explicit constexpr InlineData(absl::string_view chars)
+      : as_chars{GetOrNull(chars, 0),  GetOrNull(chars, 1),
+                 GetOrNull(chars, 2),  GetOrNull(chars, 3),
+                 GetOrNull(chars, 4),  GetOrNull(chars, 5),
+                 GetOrNull(chars, 6),  GetOrNull(chars, 7),
+                 GetOrNull(chars, 8),  GetOrNull(chars, 9),
+                 GetOrNull(chars, 10), GetOrNull(chars, 11),
+                 GetOrNull(chars, 12), GetOrNull(chars, 13),
+                 GetOrNull(chars, 14), static_cast<char>(chars.size())} {}
+
+  AsTree as_tree;
+  char as_chars[kMaxInline + 1];
+};
+static_assert(sizeof(InlineData) == kMaxInline + 1, "");
+static_assert(sizeof(AsTree) == sizeof(InlineData), "");
+static_assert(offsetof(AsTree, tagged_size) == kMaxInline, "");
+
 }  // namespace cord_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc
index 9feb224..e28a29b 100644
--- a/absl/strings/internal/str_format/arg.cc
+++ b/absl/strings/internal/str_format/arg.cc
@@ -1,3 +1,17 @@
+// 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.
+
 //
 // POSIX spec:
 //   http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index 3dbc152..7040c86 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -1,3 +1,17 @@
+// 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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
 
diff --git a/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc
index f53fd6b..1261937 100644
--- a/absl/strings/internal/str_format/arg_test.cc
+++ b/absl/strings/internal/str_format/arg_test.cc
@@ -6,6 +6,12 @@
 //
 //      https://www.apache.org/licenses/LICENSE-2.0
 //
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #include "absl/strings/internal/str_format/arg.h"
 
 #include <ostream>
diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc
index 6980ed1..4e68b90 100644
--- a/absl/strings/internal/str_format/bind.cc
+++ b/absl/strings/internal/str_format/bind.cc
@@ -1,3 +1,17 @@
+// 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/strings/internal/str_format/bind.h"
 
 #include <cerrno>
@@ -221,7 +235,7 @@
     errno = sink.error();
     return -1;
   }
-  if (sink.count() > std::numeric_limits<int>::max()) {
+  if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {
     errno = EFBIG;
     return -1;
   }
diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h
index 585246e..267cc0e 100644
--- a/absl/strings/internal/str_format/bind.h
+++ b/absl/strings/internal/str_format/bind.h
@@ -1,3 +1,17 @@
+// 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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
 
@@ -119,10 +133,11 @@
 
 #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 
-  template <FormatConversionCharSet... C,
-            typename = typename std::enable_if<
-                AllOf(sizeof...(C) == sizeof...(Args), Contains(Args,
-                                                                C)...)>::type>
+  template <
+      FormatConversionCharSet... C,
+      typename = typename std::enable_if<sizeof...(C) == sizeof...(Args)>::type,
+      typename = typename std::enable_if<AllOf(Contains(Args,
+                                                        C)...)>::type>
   FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc)  // NOLINT
       : Base(&pc) {}
 };
diff --git a/absl/strings/internal/str_format/bind_test.cc b/absl/strings/internal/str_format/bind_test.cc
index 64790a8..1eef9c4 100644
--- a/absl/strings/internal/str_format/bind_test.cc
+++ b/absl/strings/internal/str_format/bind_test.cc
@@ -1,3 +1,17 @@
+// 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/strings/internal/str_format/bind.h"
 
 #include <string.h>
diff --git a/absl/strings/internal/str_format/checker.h b/absl/strings/internal/str_format/checker.h
index 424c51f..2a2601e 100644
--- a/absl/strings/internal/str_format/checker.h
+++ b/absl/strings/internal/str_format/checker.h
@@ -1,3 +1,17 @@
+// 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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
 
diff --git a/absl/strings/internal/str_format/checker_test.cc b/absl/strings/internal/str_format/checker_test.cc
index a76d70b..7c70f47 100644
--- a/absl/strings/internal/str_format/checker_test.cc
+++ b/absl/strings/internal/str_format/checker_test.cc
@@ -1,3 +1,17 @@
+// 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 <string>
 
 #include "gmock/gmock.h"
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index 634ee78..375db0a 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -1,3 +1,17 @@
+// 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 <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc
index cafa479..0ded0a6 100644
--- a/absl/strings/internal/str_format/float_conversion.cc
+++ b/absl/strings/internal/str_format/float_conversion.cc
@@ -1,3 +1,17 @@
+// 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/strings/internal/str_format/float_conversion.h"
 
 #include <string.h>
@@ -120,7 +134,7 @@
     assert(exp > 0);
     assert(exp <= std::numeric_limits<long double>::max_exponent);
     static_assert(
-        StackArray::kMaxCapacity >=
+        static_cast<int>(StackArray::kMaxCapacity) >=
             ChunksNeeded(std::numeric_limits<long double>::max_exponent),
         "");
 
@@ -205,7 +219,7 @@
   }
 
  private:
-  static constexpr size_t kDigitsPerChunk = 9;
+  static constexpr int kDigitsPerChunk = 9;
 
   int decimal_start_;
   int decimal_end_;
@@ -442,8 +456,10 @@
 };
 
 Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
-  if (state.conv.width() < 0 || state.conv.width() <= total_size)
+  if (state.conv.width() < 0 ||
+      static_cast<size_t>(state.conv.width()) <= total_size) {
     return {0, 0, 0};
+  }
   int missing_chars = state.conv.width() - total_size;
   if (state.conv.has_left_flag()) {
     return {0, 0, missing_chars};
@@ -685,9 +701,7 @@
   // i.e., if the nibble_index is out of range. So therefore we check for this
   // and if we are out of range we just add 0 which leaves *n unchanged, which
   // seems like the reasonable thing to do in that case.
-  *n +=
-      ((nibble_index * 4 >= sizeof(Int) * 8) ? 0
-                                             : (Int{1} << (nibble_index * 4)));
+  *n += ((nibble_index >= kNumNibbles) ? 0 : (Int{1} << (nibble_index * 4)));
   Int after = *n >> kShift;
   return (before && !after) || (nibble_index >= kNumNibbles);
 }
diff --git a/absl/strings/internal/str_format/float_conversion.h b/absl/strings/internal/str_format/float_conversion.h
index e78bc19..71100e7 100644
--- a/absl/strings/internal/str_format/float_conversion.h
+++ b/absl/strings/internal/str_format/float_conversion.h
@@ -1,3 +1,17 @@
+// 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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
 
diff --git a/absl/strings/internal/str_format/parser.cc b/absl/strings/internal/str_format/parser.cc
index cc55dfa..f308d02 100644
--- a/absl/strings/internal/str_format/parser.cc
+++ b/absl/strings/internal/str_format/parser.cc
@@ -1,3 +1,17 @@
+// 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/strings/internal/str_format/parser.h"
 
 #include <assert.h>
diff --git a/absl/strings/internal/str_format/parser.h b/absl/strings/internal/str_format/parser.h
index fffed04..6504dd3 100644
--- a/absl/strings/internal/str_format/parser.h
+++ b/absl/strings/internal/str_format/parser.h
@@ -1,3 +1,17 @@
+// 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.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
 
diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc
index 5aced98..a5fa1c7 100644
--- a/absl/strings/internal/str_format/parser_test.cc
+++ b/absl/strings/internal/str_format/parser_test.cc
@@ -1,3 +1,17 @@
+// 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/strings/internal/str_format/parser.h"
 
 #include <string.h>
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h
index 6f5bc09..7692477 100644
--- a/absl/strings/internal/str_split_internal.h
+++ b/absl/strings/internal/str_split_internal.h
@@ -66,41 +66,56 @@
 
   // Matches rvalue strings and moves their data to a member.
   ConvertibleToStringView(std::string&& s)  // NOLINT(runtime/explicit)
-      : copy_(std::move(s)), value_(copy_) {}
+      : copy_(std::move(s)), value_(copy_), self_referential_(true) {}
 
   ConvertibleToStringView(const ConvertibleToStringView& other)
-      : copy_(other.copy_),
-        value_(other.IsSelfReferential() ? copy_ : other.value_) {}
+      : value_(other.value_), self_referential_(other.self_referential_) {
+    if (other.self_referential_) {
+      new (&copy_) std::string(other.copy_);
+      value_ = copy_;
+    }
+  }
 
-  ConvertibleToStringView(ConvertibleToStringView&& other) {
-    StealMembers(std::move(other));
+  ConvertibleToStringView(ConvertibleToStringView&& other)
+      : value_(other.value_), self_referential_(other.self_referential_) {
+    if (other.self_referential_) {
+      new (&copy_) std::string(std::move(other.copy_));
+      value_ = copy_;
+    }
   }
 
   ConvertibleToStringView& operator=(ConvertibleToStringView other) {
-    StealMembers(std::move(other));
+    this->~ConvertibleToStringView();
+    new (this) ConvertibleToStringView(std::move(other));
     return *this;
   }
 
   absl::string_view value() const { return value_; }
 
- private:
-  // Returns true if ctsp's value refers to its internal copy_ member.
-  bool IsSelfReferential() const { return value_.data() == copy_.data(); }
+  ~ConvertibleToStringView() { MaybeReleaseCopy(); }
 
-  void StealMembers(ConvertibleToStringView&& other) {
-    if (other.IsSelfReferential()) {
-      copy_ = std::move(other.copy_);
-      value_ = copy_;
-      other.value_ = other.copy_;
-    } else {
-      value_ = other.value_;
+ private:
+  void MaybeReleaseCopy() {
+    if (self_referential_) {
+      // An explicit destructor call cannot be a qualified name such as
+      // std::string. The "using" declaration works around this
+      // issue by creating an unqualified name for the destructor.
+      using string_type = std::string;
+      copy_.~string_type();
     }
   }
-
+  struct Unused {  // MSVC disallows unions with only 1 member.
+  };
   // Holds the data moved from temporary std::string arguments. Declared first
   // so that 'value' can refer to 'copy_'.
-  std::string copy_;
+  union {
+    std::string copy_;
+    Unused unused_;
+  };
+
   absl::string_view value_;
+  // true if value_ refers to the internal copy_ member.
+  bool self_referential_ = false;
 };
 
 // An iterator that enumerates the parts of a string from a Splitter. The text
@@ -336,7 +351,7 @@
     Container operator()(const Splitter& splitter) const {
       Container c;
       auto it = std::inserter(c, c.end());
-      for (const auto sp : splitter) {
+      for (const auto& sp : splitter) {
         *it++ = ValueType(sp);
       }
       return c;
@@ -401,7 +416,7 @@
       Container m;
       typename Container::iterator it;
       bool insert = true;
-      for (const auto sp : splitter) {
+      for (const auto& sp : splitter) {
         if (insert) {
           it = Inserter<Container>::Insert(&m, First(sp), Second());
         } else {
diff --git a/absl/strings/internal/string_constant.h b/absl/strings/internal/string_constant.h
new file mode 100644
index 0000000..b15f1d9
--- /dev/null
+++ b/absl/strings/internal/string_constant.h
@@ -0,0 +1,70 @@
+// 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.
+
+#ifndef ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
+#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
+
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+// StringConstant<T> represents a compile time string constant.
+// It can be accessed via its `absl::string_view value` static member.
+// It is guaranteed that the `string_view` returned has constant `.data()`,
+// constant `.size()` and constant `value[i]` for all `0 <= i < .size()`
+//
+// The `T` is an opaque type. It is guaranteed that different string constants
+// will have different values of `T`. This allows users to associate the string
+// constant with other static state at compile time.
+//
+// Instances should be made using the `MakeStringConstant()` factory function
+// below.
+template <typename T>
+struct StringConstant {
+ private:
+  // Returns true if `view` points to constant data.
+  // Otherwise, it can't be constant evaluated.
+  static constexpr bool ValidateConstant(absl::string_view view) {
+    return view.empty() || 2 * view[0] != 1;
+  }
+
+ public:
+  static constexpr absl::string_view value = T{}();
+  constexpr absl::string_view operator()() const { return value; }
+
+  static_assert(ValidateConstant(value),
+                "The input string_view must point to constant data.");
+};
+
+template <typename T>
+constexpr absl::string_view StringConstant<T>::value;  // NOLINT
+
+// Factory function for `StringConstant` instances.
+// It supports callables that have a constexpr default constructor and a
+// constexpr operator().
+// It must return an `absl::string_view` or `const char*` pointing to constant
+// data. This is validated at compile time.
+template <typename T>
+constexpr StringConstant<T> MakeStringConstant(T) {
+  return {};
+}
+
+}  // namespace strings_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
diff --git a/absl/strings/internal/string_constant_test.cc b/absl/strings/internal/string_constant_test.cc
new file mode 100644
index 0000000..392833c
--- /dev/null
+++ b/absl/strings/internal/string_constant_test.cc
@@ -0,0 +1,60 @@
+// 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/strings/internal/string_constant.h"
+
+#include "absl/meta/type_traits.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+using absl::strings_internal::MakeStringConstant;
+
+struct Callable {
+  constexpr absl::string_view operator()() const {
+    return absl::string_view("Callable", 8);
+  }
+};
+
+TEST(StringConstant, Traits) {
+  constexpr auto str = MakeStringConstant(Callable{});
+  using T = decltype(str);
+
+  EXPECT_TRUE(std::is_empty<T>::value);
+  EXPECT_TRUE(std::is_trivial<T>::value);
+  EXPECT_TRUE(absl::is_trivially_default_constructible<T>::value);
+  EXPECT_TRUE(absl::is_trivially_copy_constructible<T>::value);
+  EXPECT_TRUE(absl::is_trivially_move_constructible<T>::value);
+  EXPECT_TRUE(absl::is_trivially_destructible<T>::value);
+}
+
+TEST(StringConstant, MakeFromCallable) {
+  constexpr auto str = MakeStringConstant(Callable{});
+  using T = decltype(str);
+  EXPECT_EQ(Callable{}(), T::value);
+  EXPECT_EQ(Callable{}(), str());
+}
+
+TEST(StringConstant, MakeFromStringConstant) {
+  // We want to make sure the StringConstant itself is a valid input to the
+  // factory function.
+  constexpr auto str = MakeStringConstant(Callable{});
+  constexpr auto str2 = MakeStringConstant(str);
+  using T = decltype(str2);
+  EXPECT_EQ(Callable{}(), T::value);
+  EXPECT_EQ(Callable{}(), str2());
+}
+
+}  // namespace
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index 68c26dd..3da1059 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -736,9 +736,18 @@
         X / 35, X / 36,                                                   \
   }
 
+// This kVmaxOverBase is generated with
+//  for (int base = 2; base < 37; ++base) {
+//    absl::uint128 max = std::numeric_limits<absl::uint128>::max();
+//    auto result = max / base;
+//    std::cout << "    MakeUint128(" << absl::Uint128High64(result) << "u, "
+//              << absl::Uint128Low64(result) << "u),\n";
+//  }
+// See https://godbolt.org/z/aneYsb
+//
 // uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
 // array to avoid a static initializer.
-template <>
+template<>
 const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
     0,
     0,
@@ -779,6 +788,111 @@
     MakeUint128(512409557603043100u, 8198552921648689607u),
 };
 
+// This kVmaxOverBase generated with
+//   for (int base = 2; base < 37; ++base) {
+//    absl::int128 max = std::numeric_limits<absl::int128>::max();
+//    auto result = max / base;
+//    std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
+//              << absl::Int128Low64(result) << "u),\n";
+//  }
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVmaxOverBase[] = {
+    0,
+    0,
+    MakeInt128(4611686018427387903, 18446744073709551615u),
+    MakeInt128(3074457345618258602, 12297829382473034410u),
+    MakeInt128(2305843009213693951, 18446744073709551615u),
+    MakeInt128(1844674407370955161, 11068046444225730969u),
+    MakeInt128(1537228672809129301, 6148914691236517205u),
+    MakeInt128(1317624576693539401, 2635249153387078802u),
+    MakeInt128(1152921504606846975, 18446744073709551615u),
+    MakeInt128(1024819115206086200, 16397105843297379214u),
+    MakeInt128(922337203685477580, 14757395258967641292u),
+    MakeInt128(838488366986797800, 13415813871788764811u),
+    MakeInt128(768614336404564650, 12297829382473034410u),
+    MakeInt128(709490156681136600, 11351842506898185609u),
+    MakeInt128(658812288346769700, 10540996613548315209u),
+    MakeInt128(614891469123651720, 9838263505978427528u),
+    MakeInt128(576460752303423487, 18446744073709551615u),
+    MakeInt128(542551296285575047, 9765923333140350855u),
+    MakeInt128(512409557603043100, 8198552921648689607u),
+    MakeInt128(485440633518672410, 17475862806672206794u),
+    MakeInt128(461168601842738790, 7378697629483820646u),
+    MakeInt128(439208192231179800, 7027331075698876806u),
+    MakeInt128(419244183493398900, 6707906935894382405u),
+    MakeInt128(401016175515425035, 2406097053092550210u),
+    MakeInt128(384307168202282325, 6148914691236517205u),
+    MakeInt128(368934881474191032, 5902958103587056517u),
+    MakeInt128(354745078340568300, 5675921253449092804u),
+    MakeInt128(341606371735362066, 17763531330238827482u),
+    MakeInt128(329406144173384850, 5270498306774157604u),
+    MakeInt128(318047311615681924, 7633135478776366185u),
+    MakeInt128(307445734561825860, 4919131752989213764u),
+    MakeInt128(297528130221121800, 4760450083537948804u),
+    MakeInt128(288230376151711743, 18446744073709551615u),
+    MakeInt128(279496122328932600, 4471937957262921603u),
+    MakeInt128(271275648142787523, 14106333703424951235u),
+    MakeInt128(263524915338707880, 4216398645419326083u),
+    MakeInt128(256204778801521550, 4099276460824344803u),
+};
+
+// This kVminOverBase generated with
+//  for (int base = 2; base < 37; ++base) {
+//    absl::int128 min = std::numeric_limits<absl::int128>::min();
+//    auto result = min / base;
+//    std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
+//              << absl::Int128Low64(result) << "u),\n";
+//  }
+//
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVminOverBase[] = {
+    0,
+    0,
+    MakeInt128(-4611686018427387904, 0u),
+    MakeInt128(-3074457345618258603, 6148914691236517206u),
+    MakeInt128(-2305843009213693952, 0u),
+    MakeInt128(-1844674407370955162, 7378697629483820647u),
+    MakeInt128(-1537228672809129302, 12297829382473034411u),
+    MakeInt128(-1317624576693539402, 15811494920322472814u),
+    MakeInt128(-1152921504606846976, 0u),
+    MakeInt128(-1024819115206086201, 2049638230412172402u),
+    MakeInt128(-922337203685477581, 3689348814741910324u),
+    MakeInt128(-838488366986797801, 5030930201920786805u),
+    MakeInt128(-768614336404564651, 6148914691236517206u),
+    MakeInt128(-709490156681136601, 7094901566811366007u),
+    MakeInt128(-658812288346769701, 7905747460161236407u),
+    MakeInt128(-614891469123651721, 8608480567731124088u),
+    MakeInt128(-576460752303423488, 0u),
+    MakeInt128(-542551296285575048, 8680820740569200761u),
+    MakeInt128(-512409557603043101, 10248191152060862009u),
+    MakeInt128(-485440633518672411, 970881267037344822u),
+    MakeInt128(-461168601842738791, 11068046444225730970u),
+    MakeInt128(-439208192231179801, 11419412998010674810u),
+    MakeInt128(-419244183493398901, 11738837137815169211u),
+    MakeInt128(-401016175515425036, 16040647020617001406u),
+    MakeInt128(-384307168202282326, 12297829382473034411u),
+    MakeInt128(-368934881474191033, 12543785970122495099u),
+    MakeInt128(-354745078340568301, 12770822820260458812u),
+    MakeInt128(-341606371735362067, 683212743470724134u),
+    MakeInt128(-329406144173384851, 13176245766935394012u),
+    MakeInt128(-318047311615681925, 10813608594933185431u),
+    MakeInt128(-307445734561825861, 13527612320720337852u),
+    MakeInt128(-297528130221121801, 13686293990171602812u),
+    MakeInt128(-288230376151711744, 0u),
+    MakeInt128(-279496122328932601, 13974806116446630013u),
+    MakeInt128(-271275648142787524, 4340410370284600381u),
+    MakeInt128(-263524915338707881, 14230345428290225533u),
+    MakeInt128(-256204778801521551, 14347467612885206813u),
+};
+
 template <typename IntType>
 const IntType LookupTables<IntType>::kVmaxOverBase[] =
     X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
@@ -948,6 +1062,10 @@
   return safe_int_internal<int64_t>(text, value, base);
 }
 
+bool safe_strto128_base(absl::string_view text, int128* value, int base) {
+  return safe_int_internal<absl::int128>(text, value, base);
+}
+
 bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base) {
   return safe_uint_internal<uint32_t>(text, value, base);
 }
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index d872cca..2e004b4 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -127,6 +127,8 @@
 // safe_strto?() functions for implementing SimpleAtoi()
 bool safe_strto32_base(absl::string_view text, int32_t* value, int base);
 bool safe_strto64_base(absl::string_view text, int64_t* value, int base);
+bool safe_strto128_base(absl::string_view text, absl::int128* value,
+                         int base);
 bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base);
 bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base);
 bool safe_strtou128_base(absl::string_view text, absl::uint128* value,
@@ -256,6 +258,11 @@
 }
 
 ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
+                                            absl::int128* out) {
+  return numbers_internal::safe_strto128_base(str, out, 10);
+}
+
+ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
                                             absl::uint128* out) {
   return numbers_internal::safe_strtou128_base(str, out, 10);
 }
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index c2f03b6..4ab67fb 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -251,7 +251,7 @@
 template <typename int_type, typename in_val_type>
 void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
   std::string s;
-  // uint128 can be streamed but not StrCat'd
+  // (u)int128 can be streamed but not StrCat'd.
   absl::strings_internal::OStringStream(&s) << in_value;
   int_type x = static_cast<int_type>(~exp_value);
   EXPECT_TRUE(SimpleAtoi(s, &x))
@@ -264,7 +264,9 @@
 
 template <typename int_type, typename in_val_type>
 void VerifySimpleAtoiBad(in_val_type in_value) {
-  std::string s = absl::StrCat(in_value);
+  std::string s;
+  // (u)int128 can be streamed but not StrCat'd.
+  absl::strings_internal::OStringStream(&s) << in_value;
   int_type x;
   EXPECT_FALSE(SimpleAtoi(s, &x));
   EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));
@@ -347,6 +349,31 @@
       std::numeric_limits<absl::uint128>::max(),
       std::numeric_limits<absl::uint128>::max());
 
+  // SimpleAtoi(absl::string_view, absl::int128)
+  VerifySimpleAtoiGood<absl::int128>(0, 0);
+  VerifySimpleAtoiGood<absl::int128>(42, 42);
+  VerifySimpleAtoiGood<absl::int128>(-42, -42);
+
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::min(),
+                                      std::numeric_limits<int32_t>::min());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::max(),
+                                      std::numeric_limits<int32_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint32_t>::max(),
+                                      std::numeric_limits<uint32_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::min(),
+                                      std::numeric_limits<int64_t>::min());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::max(),
+                                      std::numeric_limits<int64_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint64_t>::max(),
+                                      std::numeric_limits<uint64_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(
+      std::numeric_limits<absl::int128>::min(),
+      std::numeric_limits<absl::int128>::min());
+  VerifySimpleAtoiGood<absl::int128>(
+      std::numeric_limits<absl::int128>::max(),
+      std::numeric_limits<absl::int128>::max());
+  VerifySimpleAtoiBad<absl::int128>(std::numeric_limits<absl::uint128>::max());
+
   // Some other types
   VerifySimpleAtoiGood<int>(-42, -42);
   VerifySimpleAtoiGood<int32_t>(-42, -42);
@@ -725,6 +752,51 @@
     EXPECT_FALSE(parse_func(s, &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
+  // 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());
+  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);
+
+  for (size_t i = 0; i < kNumRandomTests; ++i) {
+    int64_t high = random_int64(rng);
+    uint64_t low = random_uint64(rng);
+    IntType value = absl::MakeInt128(high, low);
+
+    int base = random_base(rng);
+    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
+    std::string s;
+    absl::strings_internal::OStringStream(&s)
+        << std::numeric_limits<IntType>::max() << value;
+    EXPECT_FALSE(parse_func(s, &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));
+  }
+}
 
 TEST(stringtest, safe_strtou32_base) {
   for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
diff --git a/absl/strings/str_cat_benchmark.cc b/absl/strings/str_cat_benchmark.cc
index ee4ad11..02c4dbe 100644
--- a/absl/strings/str_cat_benchmark.cc
+++ b/absl/strings/str_cat_benchmark.cc
@@ -137,4 +137,51 @@
 }
 BENCHMARK(BM_DoubleToString_By_SixDigits);
 
+template <typename... Chunks>
+void BM_StrAppendImpl(benchmark::State& state, size_t total_bytes,
+                      Chunks... chunks) {
+  for (auto s : state) {
+    std::string result;
+    while (result.size() < total_bytes) {
+      absl::StrAppend(&result, chunks...);
+      benchmark::DoNotOptimize(result);
+    }
+  }
+}
+
+void BM_StrAppend(benchmark::State& state) {
+  const int total_bytes = state.range(0);
+  const int chunks_at_a_time = state.range(1);
+  const absl::string_view kChunk = "0123456789";
+
+  switch (chunks_at_a_time) {
+    case 1:
+      return BM_StrAppendImpl(state, total_bytes, kChunk);
+    case 2:
+      return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk);
+    case 4:
+      return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk,
+                              kChunk);
+    case 8:
+      return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk,
+                              kChunk, kChunk, kChunk, kChunk, kChunk);
+    default:
+      std::abort();
+  }
+}
+
+template <typename B>
+void StrAppendConfig(B* benchmark) {
+  for (int bytes : {10, 100, 1000, 10000}) {
+    for (int chunks : {1, 2, 4, 8}) {
+      // Only add the ones that divide properly. Otherwise we are over counting.
+      if (bytes % (10 * chunks) == 0) {
+        benchmark->Args({bytes, chunks});
+      }
+    }
+  }
+}
+
+BENCHMARK(BM_StrAppend)->Apply(StrAppendConfig);
+
 }  // namespace
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index d9fb25a..c60027a 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -1,3 +1,16 @@
+// 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/strings/str_format.h"
 
diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc
index b5ce68d..7f7c097 100644
--- a/absl/strings/str_split_test.cc
+++ b/absl/strings/str_split_test.cc
@@ -367,7 +367,7 @@
 TEST(Splitter, RangeIterators) {
   auto splitter = absl::StrSplit("a,b,c", ',');
   std::vector<absl::string_view> output;
-  for (const absl::string_view p : splitter) {
+  for (const absl::string_view& p : splitter) {
     output.push_back(p);
   }
   EXPECT_THAT(output, ElementsAre("a", "b", "c"));
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 8a9db8c..5260b5b 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -111,6 +111,11 @@
 // example, when splitting a string, `std::vector<absl::string_view>` is a
 // natural data type for the output.
 //
+// For another example, a Cord is a non-contiguous, potentially very
+// long string-like object.  The Cord class has an interface that iteratively
+// provides string_view objects that point to the successive pieces of a Cord
+// object.
+//
 // When constructed from a source which is NUL-terminated, the `string_view`
 // itself will not include the NUL-terminator unless a specific size (including
 // the NUL) is passed to the constructor. As a result, common idioms that work
@@ -382,6 +387,7 @@
   // Returns a "substring" of the `string_view` (at offset `pos` and length
   // `n`) as another string_view. This function throws `std::out_of_bounds` if
   // `pos > size`.
+  // Use absl::ClippedSubstr if you need a truncating substr operation.
   constexpr string_view substr(size_type pos, size_type n = npos) const {
     return ABSL_PREDICT_FALSE(pos > length_)
                ? (base_internal::ThrowStdOutOfRange(
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index 1a5c02a..cd4009a 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 # Internal data structure for efficiently detecting mutex dependency cycles
 cc_library(
@@ -73,15 +73,14 @@
         "internal/create_thread_identity.cc",
         "internal/per_thread_sem.cc",
         "internal/waiter.cc",
+        "mutex.cc",
         "notification.cc",
-    ] + select({
-        "//conditions:default": ["mutex.cc"],
-    }),
+    ],
     hdrs = [
         "barrier.h",
         "blocking_counter.h",
         "internal/create_thread_identity.h",
-        "internal/mutex_nonprod.inc",
+        "internal/futex.h",
         "internal/per_thread_sem.h",
         "internal/waiter.h",
         "mutex.h",
diff --git a/absl/synchronization/BUILD.gn b/absl/synchronization/BUILD.gn
index 37ab3f9..78f64cd 100644
--- a/absl/synchronization/BUILD.gn
+++ b/absl/synchronization/BUILD.gn
@@ -42,7 +42,7 @@
     "barrier.h",
     "blocking_counter.h",
     "internal/create_thread_identity.h",
-    "internal/mutex_nonprod.inc",
+    "internal/futex.h",
     "internal/per_thread_sem.h",
     "internal/waiter.h",
     "mutex.h",
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index e5bc52f..e633d0b 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -52,7 +52,7 @@
     "barrier.h"
     "blocking_counter.h"
     "internal/create_thread_identity.h"
-    "internal/mutex_nonprod.inc"
+    "internal/futex.h"
     "internal/per_thread_sem.h"
     "internal/waiter.h"
     "mutex.h"
diff --git a/absl/synchronization/internal/futex.h b/absl/synchronization/internal/futex.h
new file mode 100644
index 0000000..06fbd6d
--- /dev/null
+++ b/absl/synchronization/internal/futex.h
@@ -0,0 +1,154 @@
+// 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.
+#ifndef ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
+#define ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
+
+#include "absl/base/config.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#ifdef __linux__
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/optimization.h"
+#include "absl/synchronization/internal/kernel_timeout.h"
+
+#ifdef ABSL_INTERNAL_HAVE_FUTEX
+#error ABSL_INTERNAL_HAVE_FUTEX may not be set on the command line
+#elif defined(__BIONIC__)
+// Bionic supports all the futex operations we need even when some of the futex
+// definitions are missing.
+#define ABSL_INTERNAL_HAVE_FUTEX
+#elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
+// FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.
+#define ABSL_INTERNAL_HAVE_FUTEX
+#endif
+
+#ifdef ABSL_INTERNAL_HAVE_FUTEX
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace synchronization_internal {
+
+// Some Android headers are missing these definitions even though they
+// support these futex operations.
+#ifdef __BIONIC__
+#ifndef SYS_futex
+#define SYS_futex __NR_futex
+#endif
+#ifndef FUTEX_WAIT_BITSET
+#define FUTEX_WAIT_BITSET 9
+#endif
+#ifndef FUTEX_PRIVATE_FLAG
+#define FUTEX_PRIVATE_FLAG 128
+#endif
+#ifndef FUTEX_CLOCK_REALTIME
+#define FUTEX_CLOCK_REALTIME 256
+#endif
+#ifndef FUTEX_BITSET_MATCH_ANY
+#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
+#endif
+#endif
+
+#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
+#define SYS_futex_time64 __NR_futex_time64
+#endif
+
+#if defined(SYS_futex_time64) && !defined(SYS_futex)
+#define SYS_futex SYS_futex_time64
+#endif
+
+class FutexImpl {
+ public:
+  static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
+                       KernelTimeout t) {
+    int err = 0;
+    if (t.has_timeout()) {
+      // https://locklessinc.com/articles/futex_cheat_sheet/
+      // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.
+      struct timespec abs_timeout = t.MakeAbsTimespec();
+      // Atomically check that the futex value is still 0, and if it
+      // is, sleep until abs_timeout or until woken by FUTEX_WAKE.
+      err = syscall(
+          SYS_futex, reinterpret_cast<int32_t *>(v),
+          FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,
+          &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY);
+    } else {
+      // Atomically check that the futex value is still 0, and if it
+      // is, sleep until woken by FUTEX_WAKE.
+      err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                    FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr);
+    }
+    if (ABSL_PREDICT_FALSE(err != 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+
+  static int WaitBitsetAbsoluteTimeout(std::atomic<int32_t> *v, int32_t val,
+                                       int32_t bits,
+                                       const struct timespec *abstime) {
+    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                      FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG, val, abstime,
+                      nullptr, bits);
+    if (ABSL_PREDICT_FALSE(err != 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+
+  static int Wake(std::atomic<int32_t> *v, int32_t count) {
+    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                      FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
+    if (ABSL_PREDICT_FALSE(err < 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+
+  // FUTEX_WAKE_BITSET
+  static int WakeBitset(std::atomic<int32_t> *v, int32_t count, int32_t bits) {
+    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                      FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, count, nullptr,
+                      nullptr, bits);
+    if (ABSL_PREDICT_FALSE(err < 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+};
+
+class Futex : public FutexImpl {};
+
+}  // namespace synchronization_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_INTERNAL_HAVE_FUTEX
+
+#endif  // ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
diff --git a/absl/synchronization/internal/graphcycles.cc b/absl/synchronization/internal/graphcycles.cc
index 19f9aab..27fec21 100644
--- a/absl/synchronization/internal/graphcycles.cc
+++ b/absl/synchronization/internal/graphcycles.cc
@@ -37,6 +37,7 @@
 
 #include <algorithm>
 #include <array>
+#include <limits>
 #include "absl/base/internal/hide_ptr.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/spinlock.h"
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index d6ac5db..bbd4d2d 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -26,6 +26,7 @@
 #define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
 
 #include <time.h>
+
 #include <algorithm>
 #include <limits>
 
@@ -57,6 +58,10 @@
 
   bool has_timeout() const { return ns_ != 0; }
 
+  // Convert to parameter for sem_timedwait/futex/similar.  Only for approved
+  // users.  Do not call if !has_timeout.
+  struct timespec MakeAbsTimespec();
+
  private:
   // internal rep, not user visible: ns after unix epoch.
   // zero = no timeout.
@@ -82,34 +87,6 @@
     return x;
   }
 
-  // Convert to parameter for sem_timedwait/futex/similar.  Only for approved
-  // users.  Do not call if !has_timeout.
-  struct timespec MakeAbsTimespec() {
-    int64_t n = ns_;
-    static const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
-    if (n == 0) {
-      ABSL_RAW_LOG(
-          ERROR,
-          "Tried to create a timespec from a non-timeout; never do this.");
-      // But we'll try to continue sanely.  no-timeout ~= saturated timeout.
-      n = (std::numeric_limits<int64_t>::max)();
-    }
-
-    // Kernel APIs validate timespecs as being at or after the epoch,
-    // despite the kernel time type being signed.  However, no one can
-    // tell the difference between a timeout at or before the epoch (since
-    // all such timeouts have expired!)
-    if (n < 0) n = 0;
-
-    struct timespec abstime;
-    int64_t seconds = (std::min)(n / kNanosPerSecond,
-                               int64_t{(std::numeric_limits<time_t>::max)()});
-    abstime.tv_sec = static_cast<time_t>(seconds);
-    abstime.tv_nsec =
-        static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
-    return abstime;
-  }
-
 #ifdef _WIN32
   // Converts to milliseconds from now, or INFINITE when
   // !has_timeout(). For use by SleepConditionVariableSRW on
@@ -148,6 +125,30 @@
   friend class Waiter;
 };
 
+inline struct timespec KernelTimeout::MakeAbsTimespec() {
+  int64_t n = ns_;
+  static const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
+  if (n == 0) {
+    ABSL_RAW_LOG(
+        ERROR, "Tried to create a timespec from a non-timeout; never do this.");
+    // But we'll try to continue sanely.  no-timeout ~= saturated timeout.
+    n = (std::numeric_limits<int64_t>::max)();
+  }
+
+  // Kernel APIs validate timespecs as being at or after the epoch,
+  // despite the kernel time type being signed.  However, no one can
+  // tell the difference between a timeout at or before the epoch (since
+  // all such timeouts have expired!)
+  if (n < 0) n = 0;
+
+  struct timespec abstime;
+  int64_t seconds = (std::min)(n / kNanosPerSecond,
+                               int64_t{(std::numeric_limits<time_t>::max)()});
+  abstime.tv_sec = static_cast<time_t>(seconds);
+  abstime.tv_nsec = static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
+  return abstime;
+}
+
 }  // namespace synchronization_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/internal/mutex_nonprod.cc b/absl/synchronization/internal/mutex_nonprod.cc
deleted file mode 100644
index 334c3bc..0000000
--- a/absl/synchronization/internal/mutex_nonprod.cc
+++ /dev/null
@@ -1,325 +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.
-
-// Implementation of a small subset of Mutex and CondVar functionality
-// for platforms where the production implementation hasn't been fully
-// ported yet.
-
-#include "absl/synchronization/mutex.h"
-
-#if defined(_WIN32)
-#include <chrono>  // NOLINT(build/c++11)
-#else
-#include <sys/time.h>
-#include <time.h>
-#endif
-
-#include <algorithm>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/time/time.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-void SetMutexDeadlockDetectionMode(OnDeadlockCycle) {}
-void EnableMutexInvariantDebugging(bool) {}
-
-namespace synchronization_internal {
-
-namespace {
-
-// Return the current time plus the timeout.
-absl::Time DeadlineFromTimeout(absl::Duration timeout) {
-  return absl::Now() + timeout;
-}
-
-// Limit the deadline to a positive, 32-bit time_t value to accommodate
-// implementation restrictions.  This also deals with InfinitePast and
-// InfiniteFuture.
-absl::Time LimitedDeadline(absl::Time deadline) {
-  deadline = std::max(absl::FromTimeT(0), deadline);
-  deadline = std::min(deadline, absl::FromTimeT(0x7fffffff));
-  return deadline;
-}
-
-}  // namespace
-
-#if defined(_WIN32)
-
-MutexImpl::MutexImpl() {}
-
-MutexImpl::~MutexImpl() {
-  if (locked_) {
-    std_mutex_.unlock();
-  }
-}
-
-void MutexImpl::Lock() {
-  std_mutex_.lock();
-  locked_ = true;
-}
-
-bool MutexImpl::TryLock() {
-  bool locked = std_mutex_.try_lock();
-  if (locked) locked_ = true;
-  return locked;
-}
-
-void MutexImpl::Unlock() {
-  locked_ = false;
-  released_.SignalAll();
-  std_mutex_.unlock();
-}
-
-CondVarImpl::CondVarImpl() {}
-
-CondVarImpl::~CondVarImpl() {}
-
-void CondVarImpl::Signal() { std_cv_.notify_one(); }
-
-void CondVarImpl::SignalAll() { std_cv_.notify_all(); }
-
-void CondVarImpl::Wait(MutexImpl* mu) {
-  mu->released_.SignalAll();
-  std_cv_.wait(mu->std_mutex_);
-}
-
-bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
-  mu->released_.SignalAll();
-  time_t when = ToTimeT(deadline);
-  int64_t nanos = ToInt64Nanoseconds(deadline - absl::FromTimeT(when));
-  std::chrono::system_clock::time_point deadline_tp =
-      std::chrono::system_clock::from_time_t(when) +
-      std::chrono::duration_cast<std::chrono::system_clock::duration>(
-          std::chrono::nanoseconds(nanos));
-  auto deadline_since_epoch =
-      std::chrono::duration_cast<std::chrono::duration<double>>(
-          deadline_tp - std::chrono::system_clock::from_time_t(0));
-  return std_cv_.wait_until(mu->std_mutex_, deadline_tp) ==
-         std::cv_status::timeout;
-}
-
-#else  // ! _WIN32
-
-MutexImpl::MutexImpl() {
-  ABSL_RAW_CHECK(pthread_mutex_init(&pthread_mutex_, nullptr) == 0,
-                 "pthread error");
-}
-
-MutexImpl::~MutexImpl() {
-  if (locked_) {
-    ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
-  }
-  ABSL_RAW_CHECK(pthread_mutex_destroy(&pthread_mutex_) == 0, "pthread error");
-}
-
-void MutexImpl::Lock() {
-  ABSL_RAW_CHECK(pthread_mutex_lock(&pthread_mutex_) == 0, "pthread error");
-  locked_ = true;
-}
-
-bool MutexImpl::TryLock() {
-  bool locked = (0 == pthread_mutex_trylock(&pthread_mutex_));
-  if (locked) locked_ = true;
-  return locked;
-}
-
-void MutexImpl::Unlock() {
-  locked_ = false;
-  released_.SignalAll();
-  ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
-}
-
-CondVarImpl::CondVarImpl() {
-  ABSL_RAW_CHECK(pthread_cond_init(&pthread_cv_, nullptr) == 0,
-                 "pthread error");
-}
-
-CondVarImpl::~CondVarImpl() {
-  ABSL_RAW_CHECK(pthread_cond_destroy(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::Signal() {
-  ABSL_RAW_CHECK(pthread_cond_signal(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::SignalAll() {
-  ABSL_RAW_CHECK(pthread_cond_broadcast(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::Wait(MutexImpl* mu) {
-  mu->released_.SignalAll();
-  ABSL_RAW_CHECK(pthread_cond_wait(&pthread_cv_, &mu->pthread_mutex_) == 0,
-                 "pthread error");
-}
-
-bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
-  mu->released_.SignalAll();
-  struct timespec ts = ToTimespec(deadline);
-  int rc = pthread_cond_timedwait(&pthread_cv_, &mu->pthread_mutex_, &ts);
-  if (rc == ETIMEDOUT) return true;
-  ABSL_RAW_CHECK(rc == 0, "pthread error");
-  return false;
-}
-
-#endif  // ! _WIN32
-
-void MutexImpl::Await(const Condition& cond) {
-  if (cond.Eval()) return;
-  released_.SignalAll();
-  do {
-    released_.Wait(this);
-  } while (!cond.Eval());
-}
-
-bool MutexImpl::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
-  if (cond.Eval()) return true;
-  released_.SignalAll();
-  while (true) {
-    if (released_.WaitWithDeadline(this, deadline)) return false;
-    if (cond.Eval()) return true;
-  }
-}
-
-}  // namespace synchronization_internal
-
-Mutex::Mutex() {}
-
-Mutex::~Mutex() {}
-
-void Mutex::Lock() { impl()->Lock(); }
-
-void Mutex::Unlock() { impl()->Unlock(); }
-
-bool Mutex::TryLock() { return impl()->TryLock(); }
-
-void Mutex::ReaderLock() { Lock(); }
-
-void Mutex::ReaderUnlock() { Unlock(); }
-
-void Mutex::Await(const Condition& cond) { impl()->Await(cond); }
-
-void Mutex::LockWhen(const Condition& cond) {
-  Lock();
-  Await(cond);
-}
-
-bool Mutex::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
-  return impl()->AwaitWithDeadline(
-      cond, synchronization_internal::LimitedDeadline(deadline));
-}
-
-bool Mutex::AwaitWithTimeout(const Condition& cond, absl::Duration timeout) {
-  return AwaitWithDeadline(
-      cond, synchronization_internal::DeadlineFromTimeout(timeout));
-}
-
-bool Mutex::LockWhenWithDeadline(const Condition& cond, absl::Time deadline) {
-  Lock();
-  return AwaitWithDeadline(cond, deadline);
-}
-
-bool Mutex::LockWhenWithTimeout(const Condition& cond, absl::Duration timeout) {
-  return LockWhenWithDeadline(
-      cond, synchronization_internal::DeadlineFromTimeout(timeout));
-}
-
-void Mutex::ReaderLockWhen(const Condition& cond) {
-  ReaderLock();
-  Await(cond);
-}
-
-bool Mutex::ReaderLockWhenWithTimeout(const Condition& cond,
-                                      absl::Duration timeout) {
-  return LockWhenWithTimeout(cond, timeout);
-}
-bool Mutex::ReaderLockWhenWithDeadline(const Condition& cond,
-                                       absl::Time deadline) {
-  return LockWhenWithDeadline(cond, deadline);
-}
-
-void Mutex::EnableDebugLog(const char*) {}
-void Mutex::EnableInvariantDebugging(void (*)(void*), void*) {}
-void Mutex::ForgetDeadlockInfo() {}
-void Mutex::AssertHeld() const {}
-void Mutex::AssertReaderHeld() const {}
-void Mutex::AssertNotHeld() const {}
-
-CondVar::CondVar() {}
-
-CondVar::~CondVar() {}
-
-void CondVar::Signal() { impl()->Signal(); }
-
-void CondVar::SignalAll() { impl()->SignalAll(); }
-
-void CondVar::Wait(Mutex* mu) { return impl()->Wait(mu->impl()); }
-
-bool CondVar::WaitWithDeadline(Mutex* mu, absl::Time deadline) {
-  return impl()->WaitWithDeadline(
-      mu->impl(), synchronization_internal::LimitedDeadline(deadline));
-}
-
-bool CondVar::WaitWithTimeout(Mutex* mu, absl::Duration timeout) {
-  return WaitWithDeadline(mu, absl::Now() + timeout);
-}
-
-void CondVar::EnableDebugLog(const char*) {}
-
-#ifdef ABSL_HAVE_THREAD_SANITIZER
-extern "C" void __tsan_read1(void *addr);
-#else
-#define __tsan_read1(addr)  // do nothing if TSan not enabled
-#endif
-
-// A function that just returns its argument, dereferenced
-static bool Dereference(void *arg) {
-  // ThreadSanitizer does not instrument this file for memory accesses.
-  // This function dereferences a user variable that can participate
-  // in a data race, so we need to manually tell TSan about this memory access.
-  __tsan_read1(arg);
-  return *(static_cast<bool *>(arg));
-}
-
-Condition::Condition() {}   // null constructor, used for kTrue only
-const Condition Condition::kTrue;
-
-Condition::Condition(bool (*func)(void *), void *arg)
-    : eval_(&CallVoidPtrFunction),
-      function_(func),
-      method_(nullptr),
-      arg_(arg) {}
-
-bool Condition::CallVoidPtrFunction(const Condition *c) {
-  return (*c->function_)(c->arg_);
-}
-
-Condition::Condition(const bool *cond)
-    : eval_(CallVoidPtrFunction),
-      function_(Dereference),
-      method_(nullptr),
-      // const_cast is safe since Dereference does not modify arg
-      arg_(const_cast<bool *>(cond)) {}
-
-bool Condition::Eval() const {
-  // eval_ == null for kTrue
-  return (this->eval_ == nullptr) || (*this->eval_)(this);
-}
-
-void RegisterSymbolizer(bool (*)(const void*, char*, int)) {}
-
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/synchronization/internal/mutex_nonprod.inc b/absl/synchronization/internal/mutex_nonprod.inc
deleted file mode 100644
index d83bc8a..0000000
--- a/absl/synchronization/internal/mutex_nonprod.inc
+++ /dev/null
@@ -1,249 +0,0 @@
-// Do not include.  This is an implementation detail of base/mutex.h.
-//
-// Declares three classes:
-//
-// base::internal::MutexImpl - implementation helper for Mutex
-// base::internal::CondVarImpl - implementation helper for CondVar
-// base::internal::SynchronizationStorage<T> - implementation helper for
-//                                             Mutex, CondVar
-
-#include <type_traits>
-
-#if defined(_WIN32)
-#include <condition_variable>
-#include <mutex>
-#else
-#include <pthread.h>
-#endif
-
-#include "absl/base/call_once.h"
-#include "absl/time/time.h"
-
-// Declare that Mutex::ReaderLock is actually Lock().  Intended primarily
-// for tests, and even then as a last resort.
-#ifdef ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE
-#error ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE cannot be directly set
-#else
-#define ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE 1
-#endif
-
-// Declare that Mutex::EnableInvariantDebugging is not implemented.
-// Intended primarily for tests, and even then as a last resort.
-#ifdef ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED
-#error ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED cannot be directly set
-#else
-#define ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED 1
-#endif
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-class Condition;
-
-namespace synchronization_internal {
-
-class MutexImpl;
-
-// Do not use this implementation detail of CondVar. Provides most of the
-// implementation, but should not be placed directly in static storage
-// because it will not linker initialize properly. See
-// SynchronizationStorage<T> below for what we mean by linker
-// initialization.
-class CondVarImpl {
- public:
-  CondVarImpl();
-  CondVarImpl(const CondVarImpl&) = delete;
-  CondVarImpl& operator=(const CondVarImpl&) = delete;
-  ~CondVarImpl();
-
-  void Signal();
-  void SignalAll();
-  void Wait(MutexImpl* mutex);
-  bool WaitWithDeadline(MutexImpl* mutex, absl::Time deadline);
-
- private:
-#if defined(_WIN32)
-  std::condition_variable_any std_cv_;
-#else
-  pthread_cond_t pthread_cv_;
-#endif
-};
-
-// Do not use this implementation detail of Mutex. Provides most of the
-// implementation, but should not be placed directly in static storage
-// because it will not linker initialize properly. See
-// SynchronizationStorage<T> below for what we mean by linker
-// initialization.
-class MutexImpl {
- public:
-  MutexImpl();
-  MutexImpl(const MutexImpl&) = delete;
-  MutexImpl& operator=(const MutexImpl&) = delete;
-  ~MutexImpl();
-
-  void Lock();
-  bool TryLock();
-  void Unlock();
-  void Await(const Condition& cond);
-  bool AwaitWithDeadline(const Condition& cond, absl::Time deadline);
-
- private:
-  friend class CondVarImpl;
-
-#if defined(_WIN32)
-  std::mutex std_mutex_;
-#else
-  pthread_mutex_t pthread_mutex_;
-#endif
-
-  // True if the underlying mutex is locked.  If the destructor is entered
-  // while locked_, the underlying mutex is unlocked.  Mutex supports
-  // destruction while locked, but the same is undefined behavior for both
-  // pthread_mutex_t and std::mutex.
-  bool locked_ = false;
-
-  // Signaled before releasing the lock, in support of Await.
-  CondVarImpl released_;
-};
-
-// Do not use this implementation detail of CondVar and Mutex.  A storage
-// space for T that supports a LinkerInitialized constructor. T must
-// have a default constructor, which is called by the first call to
-// get(). T's destructor is never called if the LinkerInitialized
-// constructor is called.
-//
-// Objects constructed with the default constructor are constructed and
-// destructed like any other object, and should never be allocated in
-// static storage.
-//
-// Objects constructed with the LinkerInitialized constructor should
-// always be in static storage. For such objects, calls to get() are always
-// valid, except from signal handlers.
-//
-// Note that this implementation relies on undefined language behavior that
-// are known to hold for the set of supported compilers. An analysis
-// follows.
-//
-// From the C++11 standard:
-//
-// [basic.life] says an object has non-trivial initialization if it is of
-// class type and it is initialized by a constructor other than a trivial
-// default constructor.  (the LinkerInitialized constructor is
-// non-trivial)
-//
-// [basic.life] says the lifetime of an object with a non-trivial
-// constructor begins when the call to the constructor is complete.
-//
-// [basic.life] says the lifetime of an object with non-trivial destructor
-// ends when the call to the destructor begins.
-//
-// [basic.life] p5 specifies undefined behavior when accessing non-static
-// members of an instance outside its
-// lifetime. (SynchronizationStorage::get() access non-static members)
-//
-// So, LinkerInitialized object of SynchronizationStorage uses a
-// non-trivial constructor, which is called at some point during dynamic
-// initialization, and is therefore subject to order of dynamic
-// initialization bugs, where get() is called before the object's
-// constructor is, resulting in undefined behavior.
-//
-// Similarly, a LinkerInitialized SynchronizationStorage object has a
-// non-trivial destructor, and so its lifetime ends at some point during
-// destruction of objects with static storage duration [basic.start.term]
-// p4. There is a window where other exit code could call get() after this
-// occurs, resulting in undefined behavior.
-//
-// Combined, these statements imply that LinkerInitialized instances
-// of SynchronizationStorage<T> rely on undefined behavior.
-//
-// However, in practice, the implementation works on all supported
-// compilers. Specifically, we rely on:
-//
-// a) zero-initialization being sufficient to initialize
-// LinkerInitialized instances for the purposes of calling
-// get(), regardless of when the constructor is called. This is
-// because the is_dynamic_ boolean is correctly zero-initialized to
-// false.
-//
-// b) the LinkerInitialized constructor is a NOP, and immaterial to
-// even to concurrent calls to get().
-//
-// c) the destructor being a NOP for LinkerInitialized objects
-// (guaranteed by a check for !is_dynamic_), and so any concurrent and
-// subsequent calls to get() functioning as if the destructor were not
-// called, by virtue of the instances' storage remaining valid after the
-// destructor runs.
-//
-// d) That a-c apply transitively when SynchronizationStorage<T> is the
-// only member of a class allocated in static storage.
-//
-// Nothing in the language standard guarantees that a-d hold.  In practice,
-// these hold in all supported compilers.
-//
-// Future direction:
-//
-// Ideally, we would simply use std::mutex or a similar class, which when
-// allocated statically would support use immediately after static
-// initialization up until static storage is reclaimed (i.e. the properties
-// we require of all "linker initialized" instances).
-//
-// Regarding construction in static storage, std::mutex is required to
-// provide a constexpr default constructor [thread.mutex.class], which
-// ensures the instance's lifetime begins with static initialization
-// [basic.start.init], and so is immune to any problems caused by the order
-// of dynamic initialization. However, as of this writing Microsoft's
-// Visual Studio does not provide a constexpr constructor for std::mutex.
-// See
-// https://blogs.msdn.microsoft.com/vcblog/2015/06/02/constexpr-complete-for-vs-2015-rtm-c11-compiler-c17-stl/
-//
-// Regarding destruction of instances in static storage, [basic.life] does
-// say an object ends when storage in which the occupies is released, in
-// the case of non-trivial destructor. However, std::mutex is not specified
-// to have a trivial destructor.
-//
-// So, we would need a class with a constexpr default constructor and a
-// trivial destructor. Today, we can achieve neither desired property using
-// std::mutex directly.
-template <typename T>
-class SynchronizationStorage {
- public:
-  // Instances allocated on the heap or on the stack should use the default
-  // constructor.
-  SynchronizationStorage()
-      : destruct_(true), once_() {}
-
-  constexpr explicit SynchronizationStorage(absl::ConstInitType)
-      : destruct_(false), once_(), space_{{0}} {}
-
-  SynchronizationStorage(SynchronizationStorage&) = delete;
-  SynchronizationStorage& operator=(SynchronizationStorage&) = delete;
-
-  ~SynchronizationStorage() {
-    if (destruct_) {
-      get()->~T();
-    }
-  }
-
-  // Retrieve the object in storage. This is fast and thread safe, but does
-  // incur the cost of absl::call_once().
-  T* get() {
-    absl::call_once(once_, SynchronizationStorage::Construct, this);
-    return reinterpret_cast<T*>(&space_);
-  }
-
- private:
-  static void Construct(SynchronizationStorage<T>* self) {
-    new (&self->space_) T();
-  }
-
-  // When true, T's destructor is run when this is destructed.
-  const bool destruct_;
-
-  absl::once_flag once_;
-
-  // An aligned space for the T.
-  alignas(T) unsigned char space_[sizeof(T)];
-};
-
-}  // namespace synchronization_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc
index b6150b9..2123be6 100644
--- a/absl/synchronization/internal/waiter.cc
+++ b/absl/synchronization/internal/waiter.cc
@@ -48,6 +48,7 @@
 #include "absl/base/optimization.h"
 #include "absl/synchronization/internal/kernel_timeout.h"
 
+
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
@@ -66,71 +67,6 @@
 
 #if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX
 
-// Some Android headers are missing these definitions even though they
-// support these futex operations.
-#ifdef __BIONIC__
-#ifndef SYS_futex
-#define SYS_futex __NR_futex
-#endif
-#ifndef FUTEX_WAIT_BITSET
-#define FUTEX_WAIT_BITSET 9
-#endif
-#ifndef FUTEX_PRIVATE_FLAG
-#define FUTEX_PRIVATE_FLAG 128
-#endif
-#ifndef FUTEX_CLOCK_REALTIME
-#define FUTEX_CLOCK_REALTIME 256
-#endif
-#ifndef FUTEX_BITSET_MATCH_ANY
-#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
-#endif
-#endif
-
-#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
-#define SYS_futex_time64 __NR_futex_time64
-#endif
-
-#if defined(SYS_futex_time64) && !defined(SYS_futex)
-#define SYS_futex SYS_futex_time64
-#endif
-
-class Futex {
- public:
-  static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
-                       KernelTimeout t) {
-    int err = 0;
-    if (t.has_timeout()) {
-      // https://locklessinc.com/articles/futex_cheat_sheet/
-      // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.
-      struct timespec abs_timeout = t.MakeAbsTimespec();
-      // Atomically check that the futex value is still 0, and if it
-      // is, sleep until abs_timeout or until woken by FUTEX_WAKE.
-      err = syscall(
-          SYS_futex, reinterpret_cast<int32_t *>(v),
-          FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,
-          &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY);
-    } else {
-      // Atomically check that the futex value is still 0, and if it
-      // is, sleep until woken by FUTEX_WAKE.
-      err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
-                    FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr);
-    }
-    if (err != 0) {
-      err = -errno;
-    }
-    return err;
-  }
-
-  static int Wake(std::atomic<int32_t> *v, int32_t count) {
-    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
-                      FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
-    if (ABSL_PREDICT_FALSE(err < 0)) {
-      err = -errno;
-    }
-    return err;
-  }
-};
-
 Waiter::Waiter() {
   futex_.store(0, std::memory_order_relaxed);
 }
diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h
index 887f9b1..be3df18 100644
--- a/absl/synchronization/internal/waiter.h
+++ b/absl/synchronization/internal/waiter.h
@@ -36,6 +36,7 @@
 #include <cstdint>
 
 #include "absl/base/internal/thread_identity.h"
+#include "absl/synchronization/internal/futex.h"
 #include "absl/synchronization/internal/kernel_timeout.h"
 
 // May be chosen at compile time via -DABSL_FORCE_WAITER_MODE=<index>
@@ -48,12 +49,7 @@
 #define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE
 #elif defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_WIN32
-#elif defined(__BIONIC__)
-// Bionic supports all the futex operations we need even when some of the futex
-// definitions are missing.
-#define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
-#elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
-// FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.
+#elif defined(ABSL_INTERNAL_HAVE_FUTEX)
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
 #elif defined(ABSL_HAVE_SEMAPHORE_H)
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 9b7f088..9e01393 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -50,6 +50,7 @@
 #include "absl/base/internal/spinlock.h"
 #include "absl/base/internal/sysinfo.h"
 #include "absl/base/internal/thread_identity.h"
+#include "absl/base/internal/tsan_mutex_interface.h"
 #include "absl/base/port.h"
 #include "absl/debugging/stacktrace.h"
 #include "absl/debugging/symbolize.h"
@@ -88,8 +89,8 @@
 ABSL_CONST_INIT std::atomic<bool> synch_check_invariants(false);
 
 ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
-    absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
-        submit_profile_data;
+absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
+    submit_profile_data;
 ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<void (*)(
     const char *msg, const void *obj, int64_t wait_cycles)>
     mutex_tracer;
@@ -491,7 +492,7 @@
   std::atomic<intptr_t> *cv_word;
 
   int64_t contention_start_cycles;  // Time (in cycles) when this thread started
-                                  // to contend for the mutex.
+                                    // to contend for the mutex.
 };
 
 struct SynchLocksHeld {
@@ -705,7 +706,7 @@
 static constexpr bool kDebugMode = true;
 #endif
 
-#ifdef ABSL_HAVE_THREAD_SANITIZER
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
 static unsigned TsanFlags(Mutex::MuHow how) {
   return how == kShared ? __tsan_mutex_read_lock : 0;
 }
@@ -1767,7 +1768,7 @@
   // All memory accesses are ignored inside of mutex operations + for unlock
   // operation tsan considers that we've already released the mutex.
   bool res = false;
-#ifdef ABSL_HAVE_THREAD_SANITIZER
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
   const int flags = read_lock ? __tsan_mutex_read_lock : 0;
   const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
 #endif
@@ -2311,7 +2312,8 @@
     if (!cond_waiter) {
       // Sample lock contention events only if the (first) waiter was trying to
       // acquire the lock, not waiting on a condition variable or Condition.
-      int64_t wait_cycles = base_internal::CycleClock::Now() - enqueue_timestamp;
+      int64_t wait_cycles =
+          base_internal::CycleClock::Now() - enqueue_timestamp;
       mutex_tracer("slow release", this, wait_cycles);
       ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
       submit_profile_data(enqueue_timestamp);
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index 52401fe..598d1e0 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -31,22 +31,23 @@
 //
 //  MutexLock - An RAII wrapper to acquire and release a `Mutex` for exclusive/
 //              write access within the current scope.
+//
 //  ReaderMutexLock
 //            - An RAII wrapper to acquire and release a `Mutex` for shared/read
 //              access within the current scope.
 //
 //  WriterMutexLock
-//            - Alias for `MutexLock` above, designed for use in distinguishing
-//              reader and writer locks within code.
+//            - Effectively an alias for `MutexLock` above, designed for use in
+//              distinguishing reader and writer locks within code.
 //
 // In addition to simple mutex locks, this file also defines ways to perform
 // locking under certain conditions.
 //
-//  Condition   - (Preferred) Used to wait for a particular predicate that
-//                depends on state protected by the `Mutex` to become true.
-//  CondVar     - A lower-level variant of `Condition` that relies on
-//                application code to explicitly signal the `CondVar` when
-//                a condition has been met.
+//  Condition - (Preferred) Used to wait for a particular predicate that
+//              depends on state protected by the `Mutex` to become true.
+//  CondVar   - A lower-level variant of `Condition` that relies on
+//              application code to explicitly signal the `CondVar` when
+//              a condition has been met.
 //
 // See below for more information on using `Condition` or `CondVar`.
 //
@@ -72,15 +73,6 @@
 #include "absl/synchronization/internal/per_thread_sem.h"
 #include "absl/time/time.h"
 
-// Decide if we should use the non-production implementation because
-// the production implementation hasn't been fully ported yet.
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-#error ABSL_INTERNAL_USE_NONPROD_MUTEX cannot be directly set
-#elif defined(ABSL_LOW_LEVEL_ALLOC_MISSING)
-#define ABSL_INTERNAL_USE_NONPROD_MUTEX 1
-#include "absl/synchronization/internal/mutex_nonprod.inc"
-#endif
-
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
@@ -461,15 +453,6 @@
   static void InternalAttemptToUseMutexInFatalSignalHandler();
 
  private:
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-  friend class CondVar;
-
-  synchronization_internal::MutexImpl *impl() { return impl_.get(); }
-
-  synchronization_internal::SynchronizationStorage<
-      synchronization_internal::MutexImpl>
-      impl_;
-#else
   std::atomic<intptr_t> mu_;  // The Mutex state.
 
   // Post()/Wait() versus associated PerThreadSem; in class for required
@@ -504,7 +487,6 @@
   void Trans(MuHow how);  // used for CondVar->Mutex transfer
   void Fer(
       base_internal::PerThreadSynch *w);  // used for CondVar->Mutex transfer
-#endif
 
   // Catch the error of writing Mutex when intending MutexLock.
   Mutex(const volatile Mutex * /*ignored*/) {}  // NOLINT(runtime/explicit)
@@ -525,22 +507,36 @@
 // Example:
 //
 // Class Foo {
-//
+//  public:
 //   Foo::Bar* Baz() {
-//     MutexLock l(&lock_);
+//     MutexLock lock(&mu_);
 //     ...
 //     return bar;
 //   }
 //
 // private:
-//   Mutex lock_;
+//   Mutex mu_;
 // };
 class ABSL_SCOPED_LOCKABLE MutexLock {
  public:
+  // Constructors
+
+  // 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) {
     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)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    this->mu_->LockWhen(cond);
+  }
+
   MutexLock(const MutexLock &) = delete;  // NOLINT(runtime/mutex)
   MutexLock(MutexLock&&) = delete;  // NOLINT(runtime/mutex)
   MutexLock& operator=(const MutexLock&) = delete;
@@ -562,6 +558,12 @@
     mu->ReaderLock();
   }
 
+  explicit ReaderMutexLock(Mutex *mu, const Condition &cond)
+      ABSL_SHARED_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    mu->ReaderLockWhen(cond);
+  }
+
   ReaderMutexLock(const ReaderMutexLock&) = delete;
   ReaderMutexLock(ReaderMutexLock&&) = delete;
   ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
@@ -584,6 +586,12 @@
     mu->WriterLock();
   }
 
+  explicit WriterMutexLock(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    mu->WriterLockWhen(cond);
+  }
+
   WriterMutexLock(const WriterMutexLock&) = delete;
   WriterMutexLock(WriterMutexLock&&) = delete;
   WriterMutexLock& operator=(const WriterMutexLock&) = delete;
@@ -622,16 +630,26 @@
 // `noexcept`; until then this requirement cannot be enforced in the
 // type system.)
 //
-// Note: to use a `Condition`, you need only construct it and pass it within the
-// appropriate `Mutex' member function, such as `Mutex::Await()`.
+// Note: to use a `Condition`, you need only construct it and pass it to a
+// suitable `Mutex' member function, such as `Mutex::Await()`, or to the
+// constructor of one of the scope guard classes.
 //
-// Example:
+// Example using LockWhen/Unlock:
 //
 //   // assume count_ is not internal reference count
 //   int count_ ABSL_GUARDED_BY(mu_);
+//   Condition count_is_zero(+[](int *count) { return *count == 0; }, &count_);
 //
-//   mu_.LockWhen(Condition(+[](int* count) { return *count == 0; },
-//         &count_));
+//   mu_.LockWhen(count_is_zero);
+//   // ...
+//   mu_.Unlock();
+//
+// Example using a scope guard:
+//
+//   {
+//     MutexLock lock(&mu_, count_is_zero);
+//     // ...
+//   }
 //
 // When multiple threads are waiting on exactly the same condition, make sure
 // that they are constructed with the same parameters (same pointer to function
@@ -686,10 +704,10 @@
   //   };
   //   mu_.Await(Condition(&reached));
   //
-  // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReadHeld()" in the
-  // lambda as it may be called when the mutex is being unlocked from a scope
-  // holding only a reader lock, which will make the assertion not fulfilled and
-  // crash the binary.
+  // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReaderHeld()" in
+  // the lambda as it may be called when the mutex is being unlocked from a
+  // scope holding only a reader lock, which will make the assertion not
+  // fulfilled and crash the binary.
 
   // See class comment for performance advice. In particular, if there
   // might be more than one waiter for the same condition, make sure
@@ -838,17 +856,10 @@
   void EnableDebugLog(const char *name);
 
  private:
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-  synchronization_internal::CondVarImpl *impl() { return impl_.get(); }
-  synchronization_internal::SynchronizationStorage<
-      synchronization_internal::CondVarImpl>
-      impl_;
-#else
   bool WaitCommon(Mutex *mutex, synchronization_internal::KernelTimeout t);
   void Remove(base_internal::PerThreadSynch *s);
   void Wakeup(base_internal::PerThreadSynch *w);
   std::atomic<intptr_t> cv_;  // Condition variable state.
-#endif
   CondVar(const CondVar&) = delete;
   CondVar& operator=(const CondVar&) = delete;
 };
@@ -870,6 +881,15 @@
       this->mu_->Lock();
     }
   }
+
+  explicit MutexLockMaybe(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    if (this->mu_ != nullptr) {
+      this->mu_->LockWhen(cond);
+    }
+  }
+
   ~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() {
     if (this->mu_ != nullptr) { this->mu_->Unlock(); }
   }
@@ -892,6 +912,13 @@
       : mu_(mu) {
     this->mu_->Lock();
   }
+
+  explicit ReleasableMutexLock(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    this->mu_->LockWhen(cond);
+  }
+
   ~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
     if (this->mu_ != nullptr) { this->mu_->Unlock(); }
   }
@@ -906,12 +933,6 @@
   ReleasableMutexLock& operator=(ReleasableMutexLock&&) = delete;
 };
 
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-
-inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {}
-
-#else
-
 inline Mutex::Mutex() : mu_(0) {
   ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
 }
@@ -920,8 +941,6 @@
 
 inline CondVar::CondVar() : cv_(0) {}
 
-#endif  // ABSL_INTERNAL_USE_NONPROD_MUTEX
-
 // static
 template <typename T>
 bool Condition::CastAndCallMethod(const Condition *c) {
@@ -988,7 +1007,7 @@
 //
 // This has the same memory ordering concerns as RegisterMutexProfiler() above.
 void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj,
-                              int64_t wait_cycles));
+                                    int64_t wait_cycles));
 
 // TODO(gfalcon): Combine RegisterMutexProfiler() and RegisterMutexTracer()
 // into a single interface, since they are only ever called in pairs.
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index 307d0e3..058f757 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -707,6 +707,40 @@
   t.join();
 }
 
+TEST(Mutex, LockWhenGuard) {
+  absl::Mutex mu;
+  int n = 30;
+  bool done = false;
+
+  // We don't inline the lambda because the conversion is ambiguous in MSVC.
+  bool (*cond_eq_10)(int *) = [](int *p) { return *p == 10; };
+  bool (*cond_lt_10)(int *) = [](int *p) { return *p < 10; };
+
+  std::thread t1([&mu, &n, &done, cond_eq_10]() {
+    absl::ReaderMutexLock lock(&mu, absl::Condition(cond_eq_10, &n));
+    done = true;
+  });
+
+  std::thread t2[10];
+  for (std::thread &t : t2) {
+    t = std::thread([&mu, &n, cond_lt_10]() {
+      absl::WriterMutexLock lock(&mu, absl::Condition(cond_lt_10, &n));
+      ++n;
+    });
+  }
+
+  {
+    absl::MutexLock lock(&mu);
+    n = 0;
+  }
+
+  for (std::thread &t : t2) t.join();
+  t1.join();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(n, 10);
+}
+
 // --------------------------------------------------------
 // The following test requires Mutex::ReaderLock to be a real shared
 // lock, which is not the case in all builds.
@@ -1002,9 +1036,6 @@
   x.mu0.Unlock();
 }
 
-// The deadlock detector is not part of non-prod builds, so do not test it.
-#if !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
-
 TEST(Mutex, DeadlockDetector) {
   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
 
@@ -1102,7 +1133,7 @@
 // annotation-based static thread-safety analysis is not currently
 // predicate-aware and cannot tell if the two for-loops that acquire and
 // release the locks have the same predicates.
-TEST(Mutex, DeadlockDetectorStessTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+TEST(Mutex, DeadlockDetectorStressTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
   // Stress test: Here we create a large number of locks and use all of them.
   // If a deadlock detector keeps a full graph of lock acquisition order,
   // it will likely be too slow for this test to pass.
@@ -1158,7 +1189,6 @@
   c.Lock();
   c.Unlock();
 }
-#endif  // !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
 
 // --------------------------------------------------------
 // Test for timeouts/deadlines on condition waits that are specified using
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index 1d69f59..991241a 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "time",
diff --git a/absl/time/clock.cc b/absl/time/clock.cc
index e5c423c..6862e01 100644
--- a/absl/time/clock.cc
+++ b/absl/time/clock.cc
@@ -74,9 +74,7 @@
 #if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
 namespace absl {
 ABSL_NAMESPACE_BEGIN
-int64_t GetCurrentTimeNanos() {
-  return GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
-}
+int64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); }
 ABSL_NAMESPACE_END
 }  // namespace absl
 #else  // Use the cyclecounter-based implementation below.
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index 952cc09..4443109 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -356,7 +356,7 @@
 // the remainder.  If it does not saturate, the remainder remain accurate,
 // but the returned quotient will over/underflow int64_t and should not be used.
 int64_t IDivDuration(bool satq, const Duration num, const Duration den,
-                   Duration* rem) {
+                     Duration* rem) {
   int64_t q = 0;
   if (IDivFastPath(num, den, &q, rem)) {
     return q;
@@ -763,7 +763,8 @@
 //   form "72h3m0.5s". Leading zero units are omitted.  As a special
 //   case, durations less than one second format use a smaller unit
 //   (milli-, micro-, or nanoseconds) to ensure that the leading digit
-//   is non-zero.  The zero duration formats as 0, with no unit.
+//   is non-zero.
+// Unlike Go, we format the zero duration as 0, with no unit.
 std::string FormatDuration(Duration d) {
   const Duration min_duration = Seconds(kint64min);
   if (d == min_duration) {
diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel
index 7a53c81..45a9529 100644
--- a/absl/time/internal/cctz/BUILD.bazel
+++ b/absl/time/internal/cctz/BUILD.bazel
@@ -16,7 +16,7 @@
 
 package(features = ["-parse_headers"])
 
-licenses(["notice"])  # Apache License
+licenses(["notice"])
 
 filegroup(
     name = "zoneinfo",
@@ -92,6 +92,11 @@
 
 ### tests
 
+test_suite(
+    name = "all_tests",
+    visibility = ["//visibility:public"],
+)
+
 cc_test(
     name = "civil_time_test",
     size = "small",
diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
index d1b4222..8aadde5 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -416,16 +416,10 @@
 
   // Assigning arithmetic.
   CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept {
-    f_ = step(T{}, f_, n);
-    return *this;
+    return *this = *this + n;
   }
   CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
-    if (n != (std::numeric_limits<diff_t>::min)()) {
-      f_ = step(T{}, f_, -n);
-    } else {
-      f_ = step(T{}, step(T{}, f_, -(n + 1)), 1);
-    }
-    return *this;
+    return *this = *this - n;
   }
   CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; }
   CONSTEXPR_M civil_time operator++(int) noexcept {
@@ -442,13 +436,15 @@
 
   // Binary arithmetic operators.
   friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {
-    return a += n;
+    return civil_time(step(T{}, a.f_, n));
   }
   friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept {
-    return a += n;
+    return a + n;
   }
   friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept {
-    return a -= n;
+    return n != (std::numeric_limits<diff_t>::min)()
+               ? civil_time(step(T{}, a.f_, -n))
+               : civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1));
   }
   friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {
     return difference(T{}, lhs.f_, rhs.f_);
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 53641bf..9a1a8d6 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -1007,7 +1007,11 @@
     const time_zone cut = LoadZone("libc:UTC");
     const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900;
     tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut);
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+    // The BSD gmtime_r() fails on extreme positive tm_year values.
+#else
     EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, cut));
+#endif
     const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900;
     tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut);
     EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut));
diff --git a/absl/time/internal/cctz/testdata/version b/absl/time/internal/cctz/testdata/version
index 7f680ee..b4410dc 100644
--- a/absl/time/internal/cctz/testdata/version
+++ b/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@
-2020a
+2020d
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
index 697b993..9ca907b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
index ae04342..56a4dd2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
index 82ea5aa..0da1d1e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
index d3f8196..ea38c97 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
index d39016b..0263c90 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
index 850c8f0..a461dce 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun b/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
index 066fbed..772e23c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
index b1c425d..bada063 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
index 625b1ac..36b0522 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
index 8ee8cb9..3f8e44b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
index 52753c0..651e5cf 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/Africa/Maseru b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
index b1c425d..bada063 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
index b1c425d..bada063 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
index 6d68850..8377809 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
index a968845..ecbc096 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
Binary files differ
diff --git a/absl/t