Replace absl::optional with std::optional in QUICHE.

Chrome has switched to those two types being the same, so we don't have any reason to use the Abseil version anymore.

PiperOrigin-RevId: 580345251
diff --git a/quiche/balsa/balsa_headers.h b/quiche/balsa/balsa_headers.h
index 3e1823b..4e6e613 100644
--- a/quiche/balsa/balsa_headers.h
+++ b/quiche/balsa/balsa_headers.h
@@ -12,6 +12,7 @@
 #include <functional>
 #include <iterator>
 #include <memory>
+#include <optional>
 #include <ostream>
 #include <string>
 #include <utility>
@@ -23,7 +24,6 @@
 #include "absl/strings/ascii.h"
 #include "absl/strings/match.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/balsa/balsa_enums.h"
 #include "quiche/balsa/header_api.h"
 #include "quiche/balsa/standard_header_map.h"
@@ -1265,8 +1265,7 @@
 
   const BalsaHeaders* headers_;
   HeaderLines::size_type idx_;
-  mutable absl::optional<std::pair<absl::string_view, absl::string_view>>
-      value_;
+  mutable std::optional<std::pair<absl::string_view, absl::string_view>> value_;
 };
 
 // A const iterator for all the header lines.
diff --git a/quiche/common/btree_scheduler.h b/quiche/common/btree_scheduler.h
index fd07d36..0f160c8 100644
--- a/quiche/common/btree_scheduler.h
+++ b/quiche/common/btree_scheduler.h
@@ -6,12 +6,12 @@
 #define QUICHE_COMMON_BTREE_SCHEDULER_H_
 
 #include <limits>
+#include <optional>
 
 #include "absl/container/btree_map.h"
 #include "absl/container/node_hash_map.h"
 #include "absl/status/status.h"
 #include "absl/status/statusor.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_bug_tracker.h"
 #include "quiche/common/platform/api/quiche_export.h"
 
@@ -46,18 +46,18 @@
 
   // Counts the number of scheduled entries in the range [min, max].  If either
   // min or max is omitted, negative or positive infinity is assumed.
-  size_t NumScheduledInPriorityRange(absl::optional<Priority> min,
-                                     absl::optional<Priority> max) const;
+  size_t NumScheduledInPriorityRange(std::optional<Priority> min,
+                                     std::optional<Priority> max) const;
 
   // Returns true if there is a stream that would go before `id` in the
   // schedule.
   absl::StatusOr<bool> ShouldYield(Id id) const;
 
   // Returns the priority for `id`, or nullopt if stream is not registered.
-  absl::optional<Priority> GetPriorityFor(Id id) const {
+  std::optional<Priority> GetPriorityFor(Id id) const {
     auto it = streams_.find(id);
     if (it == streams_.end()) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     return it->second.priority;
   }
@@ -85,7 +85,7 @@
     Priority priority;
     // If present, the sequence number with which the stream is currently
     // scheduled.  If absent, indicates that the stream is not scheduled.
-    absl::optional<int> current_sequence_number;
+    std::optional<int> current_sequence_number;
 
     bool scheduled() const { return current_sequence_number.has_value(); }
   };
@@ -140,7 +140,7 @@
 
 template <typename Id, typename Priority>
 size_t BTreeScheduler<Id, Priority>::NumScheduledInPriorityRange(
-    absl::optional<Priority> min, absl::optional<Priority> max) const {
+    std::optional<Priority> min, std::optional<Priority> max) const {
   if (min.has_value() && max.has_value()) {
     QUICHE_DCHECK(*min <= *max);
   }
@@ -210,7 +210,7 @@
   }
 
   StreamEntry& stream = it->second;
-  absl::optional<int> sequence_number;
+  std::optional<int> sequence_number;
   if (stream.scheduled()) {
     absl::StatusOr<FullScheduleEntry> old_entry = DescheduleStream(stream);
     if (old_entry.ok()) {
@@ -256,7 +256,7 @@
   }
   auto schedule_it = schedule_.begin();
   QUICHE_DCHECK(schedule_it->second->second.scheduled());
-  schedule_it->second->second.current_sequence_number = absl::nullopt;
+  schedule_it->second->second.current_sequence_number = std::nullopt;
 
   Id result = StreamId(*schedule_it);
   schedule_.erase(schedule_it);
diff --git a/quiche/common/btree_scheduler_test.cc b/quiche/common/btree_scheduler_test.cc
index d3a806c..c26e2d0 100644
--- a/quiche/common/btree_scheduler_test.cc
+++ b/quiche/common/btree_scheduler_test.cc
@@ -4,9 +4,10 @@
 
 #include "quiche/common/btree_scheduler.h"
 
+#include <optional>
+
 #include "absl/status/status.h"
 #include "absl/status/statusor.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/common/platform/api/quiche_test.h"
 #include "quiche/common/test_tools/quiche_test_utils.h"
@@ -49,7 +50,7 @@
 
   EXPECT_THAT(scheduler.GetPriorityFor(1), Optional(100));
   EXPECT_THAT(scheduler.GetPriorityFor(3), Optional(102));
-  EXPECT_EQ(scheduler.GetPriorityFor(5), absl::nullopt);
+  EXPECT_EQ(scheduler.GetPriorityFor(5), std::nullopt);
 
   EXPECT_EQ(scheduler.NumScheduled(), 0u);
   EXPECT_FALSE(scheduler.HasScheduled());
@@ -113,7 +114,7 @@
   QUICHE_EXPECT_OK(scheduler.Register(9, 64));
 
   EXPECT_EQ(scheduler.NumScheduled(), 0u);
-  EXPECT_EQ(scheduler.NumScheduledInPriorityRange(absl::nullopt, absl::nullopt),
+  EXPECT_EQ(scheduler.NumScheduledInPriorityRange(std::nullopt, std::nullopt),
             0u);
   EXPECT_EQ(scheduler.NumScheduledInPriorityRange(-1, 1), 0u);
 
@@ -122,11 +123,11 @@
   }
 
   EXPECT_EQ(scheduler.NumScheduled(), 9u);
-  EXPECT_EQ(scheduler.NumScheduledInPriorityRange(absl::nullopt, absl::nullopt),
+  EXPECT_EQ(scheduler.NumScheduledInPriorityRange(std::nullopt, std::nullopt),
             9u);
   EXPECT_EQ(scheduler.NumScheduledInPriorityRange(0, 0), 3u);
-  EXPECT_EQ(scheduler.NumScheduledInPriorityRange(absl::nullopt, -1), 2u);
-  EXPECT_EQ(scheduler.NumScheduledInPriorityRange(1, absl::nullopt), 4u);
+  EXPECT_EQ(scheduler.NumScheduledInPriorityRange(std::nullopt, -1), 2u);
+  EXPECT_EQ(scheduler.NumScheduledInPriorityRange(1, std::nullopt), 4u);
 }
 
 TEST(BTreeSchedulerTest, Registration) {
diff --git a/quiche/common/capsule.h b/quiche/common/capsule.h
index 7220ee4..b5e1831 100644
--- a/quiche/common/capsule.h
+++ b/quiche/common/capsule.h
@@ -6,12 +6,12 @@
 #define QUICHE_COMMON_CAPSULE_H_
 
 #include <cstdint>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/status/statusor.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/variant.h"
 #include "quiche/common/platform/api/quiche_export.h"
 #include "quiche/common/platform/api/quiche_logging.h"
diff --git a/quiche/common/platform/api/quiche_file_utils.cc b/quiche/common/platform/api/quiche_file_utils.cc
index 6453ea2..d039f28 100644
--- a/quiche/common/platform/api/quiche_file_utils.cc
+++ b/quiche/common/platform/api/quiche_file_utils.cc
@@ -1,5 +1,7 @@
 #include "quiche/common/platform/api/quiche_file_utils.h"
 
+#include <optional>
+
 #include "quiche_platform_impl/quiche_file_utils_impl.h"
 
 namespace quiche {
@@ -8,7 +10,7 @@
   return JoinPathImpl(a, b);
 }
 
-absl::optional<std::string> ReadFileContents(absl::string_view file) {
+std::optional<std::string> ReadFileContents(absl::string_view file) {
   return ReadFileContentsImpl(file);
 }
 
diff --git a/quiche/common/platform/api/quiche_file_utils.h b/quiche/common/platform/api/quiche_file_utils.h
index 47723d1..be7cd9d 100644
--- a/quiche/common/platform/api/quiche_file_utils.h
+++ b/quiche/common/platform/api/quiche_file_utils.h
@@ -9,11 +9,11 @@
 #ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_
 #define QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_
 
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 
 namespace quiche {
 
@@ -22,7 +22,7 @@
 std::string JoinPath(absl::string_view a, absl::string_view b);
 
 // Reads the entire file into the memory.
-absl::optional<std::string> ReadFileContents(absl::string_view file);
+std::optional<std::string> ReadFileContents(absl::string_view file);
 
 // Lists all files and directories in the directory specified by |path|. Returns
 // true on success, false on failure.
diff --git a/quiche/common/platform/api/quiche_file_utils_test.cc b/quiche/common/platform/api/quiche_file_utils_test.cc
index 68387a4..3d7a7b8 100644
--- a/quiche/common/platform/api/quiche_file_utils_test.cc
+++ b/quiche/common/platform/api/quiche_file_utils_test.cc
@@ -1,11 +1,11 @@
 #include "quiche/common/platform/api/quiche_file_utils.h"
 
+#include <optional>
 #include <vector>
 
 #include "absl/algorithm/container.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/strip.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_test.h"
 
 namespace quiche {
@@ -18,7 +18,7 @@
 TEST(QuicheFileUtilsTest, ReadFileContents) {
   std::string path = absl::StrCat(QuicheGetCommonSourcePath(),
                                   "/platform/api/testdir/testfile");
-  absl::optional<std::string> contents = ReadFileContents(path);
+  std::optional<std::string> contents = ReadFileContents(path);
   ASSERT_TRUE(contents.has_value());
   EXPECT_EQ(*contents, "This is a test file.");
 }
@@ -27,7 +27,7 @@
   std::string path =
       absl::StrCat(QuicheGetCommonSourcePath(),
                    "/platform/api/testdir/file-that-does-not-exist");
-  absl::optional<std::string> contents = ReadFileContents(path);
+  std::optional<std::string> contents = ReadFileContents(path);
   EXPECT_FALSE(contents.has_value());
 }
 
diff --git a/quiche/common/platform/api/quiche_time_utils.h b/quiche/common/platform/api/quiche_time_utils.h
index 60226d5..c5177ec 100644
--- a/quiche/common/platform/api/quiche_time_utils.h
+++ b/quiche/common/platform/api/quiche_time_utils.h
@@ -16,7 +16,7 @@
 // instance, it will reject February 29 on non-leap years, or 25 hours in a day.
 // As a notable exception, 60 seconds is accepted to deal with potential leap
 // seconds.  If the date predates Unix epoch, nullopt will be returned.
-inline absl::optional<int64_t> QuicheUtcDateTimeToUnixSeconds(
+inline std::optional<int64_t> QuicheUtcDateTimeToUnixSeconds(
     int year, int month, int day, int hour, int minute, int second) {
   return QuicheUtcDateTimeToUnixSecondsImpl(year, month, day, hour, minute,
                                             second);
diff --git a/quiche/common/platform/api/quiche_time_utils_test.cc b/quiche/common/platform/api/quiche_time_utils_test.cc
index 5d09004..31f79ff 100644
--- a/quiche/common/platform/api/quiche_time_utils_test.cc
+++ b/quiche/common/platform/api/quiche_time_utils_test.cc
@@ -4,7 +4,8 @@
 
 #include "quiche/common/platform/api/quiche_time_utils.h"
 
-#include "absl/types/optional.h"
+#include <optional>
+
 #include "quiche/common/platform/api/quiche_test.h"
 
 namespace quiche {
@@ -19,32 +20,25 @@
             QuicheUtcDateTimeToUnixSeconds(2006, 7, 15, 12, 34, 56));
   EXPECT_EQ(1591130001, QuicheUtcDateTimeToUnixSeconds(2020, 6, 2, 20, 33, 21));
 
-  EXPECT_EQ(absl::nullopt,
-            QuicheUtcDateTimeToUnixSeconds(1970, 2, 29, 0, 0, 1));
-  EXPECT_NE(absl::nullopt,
-            QuicheUtcDateTimeToUnixSeconds(1972, 2, 29, 0, 0, 1));
+  EXPECT_EQ(std::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 2, 29, 0, 0, 1));
+  EXPECT_NE(std::nullopt, QuicheUtcDateTimeToUnixSeconds(1972, 2, 29, 0, 0, 1));
 }
 
 TEST(QuicheTimeUtilsTest, Bounds) {
-  EXPECT_EQ(absl::nullopt,
-            QuicheUtcDateTimeToUnixSeconds(1970, 1, 32, 0, 0, 1));
-  EXPECT_EQ(absl::nullopt,
-            QuicheUtcDateTimeToUnixSeconds(1970, 4, 31, 0, 0, 1));
-  EXPECT_EQ(absl::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 1, 0, 0, 0, 1));
-  EXPECT_EQ(absl::nullopt,
-            QuicheUtcDateTimeToUnixSeconds(1970, 13, 1, 0, 0, 1));
-  EXPECT_EQ(absl::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 0, 1, 0, 0, 1));
-  EXPECT_EQ(absl::nullopt,
-            QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 24, 0, 0));
-  EXPECT_EQ(absl::nullopt,
-            QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 0, 60, 0));
+  EXPECT_EQ(std::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 1, 32, 0, 0, 1));
+  EXPECT_EQ(std::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 4, 31, 0, 0, 1));
+  EXPECT_EQ(std::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 1, 0, 0, 0, 1));
+  EXPECT_EQ(std::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 13, 1, 0, 0, 1));
+  EXPECT_EQ(std::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 0, 1, 0, 0, 1));
+  EXPECT_EQ(std::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 24, 0, 0));
+  EXPECT_EQ(std::nullopt, QuicheUtcDateTimeToUnixSeconds(1970, 1, 1, 0, 60, 0));
 }
 
 TEST(QuicheTimeUtilsTest, LeapSecond) {
   EXPECT_EQ(QuicheUtcDateTimeToUnixSeconds(2015, 6, 30, 23, 59, 60),
             QuicheUtcDateTimeToUnixSeconds(2015, 7, 1, 0, 0, 0));
   EXPECT_EQ(QuicheUtcDateTimeToUnixSeconds(2015, 6, 30, 25, 59, 60),
-            absl::nullopt);
+            std::nullopt);
 }
 
 }  // namespace
diff --git a/quiche/common/platform/api/quiche_url_utils.h b/quiche/common/platform/api/quiche_url_utils.h
index 3590412..2aa7ceb 100644
--- a/quiche/common/platform/api/quiche_url_utils.h
+++ b/quiche/common/platform/api/quiche_url_utils.h
@@ -5,12 +5,12 @@
 #ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_URL_UTILS_H_
 #define QUICHE_COMMON_PLATFORM_API_QUICHE_URL_UTILS_H_
 
+#include <optional>
 #include <string>
 
 #include "absl/container/flat_hash_map.h"
 #include "absl/container/flat_hash_set.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 
 #include "quiche_platform_impl/quiche_url_utils_impl.h"
 
@@ -29,8 +29,8 @@
 }
 
 // Decodes a URL-encoded string and converts it to ASCII. If the decoded input
-// contains non-ASCII characters, decoding fails and absl::nullopt is returned.
-inline absl::optional<std::string> AsciiUrlDecode(absl::string_view input) {
+// contains non-ASCII characters, decoding fails and std::nullopt is returned.
+inline std::optional<std::string> AsciiUrlDecode(absl::string_view input) {
   return AsciiUrlDecodeImpl(input);
 }
 
diff --git a/quiche/common/platform/api/quiche_url_utils_test.cc b/quiche/common/platform/api/quiche_url_utils_test.cc
index 33a30ec..7599777 100644
--- a/quiche/common/platform/api/quiche_url_utils_test.cc
+++ b/quiche/common/platform/api/quiche_url_utils_test.cc
@@ -4,12 +4,12 @@
 
 #include "quiche/common/platform/api/quiche_url_utils.h"
 
+#include <optional>
 #include <set>
 #include <string>
 
 #include "absl/container/flat_hash_map.h"
 #include "absl/container/flat_hash_set.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_test.h"
 
 namespace quiche {
@@ -54,8 +54,8 @@
 }
 
 void ValidateUrlDecode(const std::string& input,
-                       const absl::optional<std::string>& expected_output) {
-  absl::optional<std::string> decode_result = AsciiUrlDecode(input);
+                       const std::optional<std::string>& expected_output) {
+  std::optional<std::string> decode_result = AsciiUrlDecode(input);
   if (!expected_output.has_value()) {
     EXPECT_FALSE(decode_result.has_value());
     return;
@@ -72,9 +72,7 @@
   ValidateUrlDecode("%7Bfoobar%7D", "{foobar}");
 }
 
-TEST(QuicheUrlUtilsTest, DecodeFail) {
-  ValidateUrlDecode("%FF", absl::nullopt);
-}
+TEST(QuicheUrlUtilsTest, DecodeFail) { ValidateUrlDecode("%FF", std::nullopt); }
 
 }  // namespace
 }  // namespace quiche
diff --git a/quiche/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc b/quiche/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc
index 65965b2..f727425 100644
--- a/quiche/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc
+++ b/quiche/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc
@@ -16,11 +16,11 @@
 #include <fstream>
 #include <ios>
 #include <iostream>
+#include <optional>
 
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "absl/strings/strip.h"
-#include "absl/types/optional.h"
 
 namespace quiche {
 
@@ -51,16 +51,16 @@
 }
 #endif  // defined(_WIN32)
 
-absl::optional<std::string> ReadFileContentsImpl(absl::string_view file) {
+std::optional<std::string> ReadFileContentsImpl(absl::string_view file) {
   std::ifstream input_file(std::string{file}, std::ios::binary);
   if (!input_file || !input_file.is_open()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   input_file.seekg(0, std::ios_base::end);
   auto file_size = input_file.tellg();
   if (!input_file) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   input_file.seekg(0, std::ios_base::beg);
 
@@ -68,7 +68,7 @@
   output.resize(file_size);
   input_file.read(&output[0], file_size);
   if (!input_file) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return output;
diff --git a/quiche/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.h b/quiche/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.h
index ad5ff1a..c083122 100644
--- a/quiche/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.h
+++ b/quiche/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.h
@@ -5,17 +5,17 @@
 #ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_FILE_UTILS_IMPL_H_
 #define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_FILE_UTILS_IMPL_H_
 
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 
 namespace quiche {
 
 std::string JoinPathImpl(absl::string_view a, absl::string_view b);
 
-absl::optional<std::string> ReadFileContentsImpl(absl::string_view file);
+std::optional<std::string> ReadFileContentsImpl(absl::string_view file);
 
 bool EnumerateDirectoryImpl(absl::string_view path,
                             std::vector<std::string>& directories,
diff --git a/quiche/common/platform/default/quiche_platform_impl/quiche_thread_impl.h b/quiche/common/platform/default/quiche_platform_impl/quiche_thread_impl.h
index 7b5748c..6c4e96f 100644
--- a/quiche/common/platform/default/quiche_platform_impl/quiche_thread_impl.h
+++ b/quiche/common/platform/default/quiche_platform_impl/quiche_thread_impl.h
@@ -1,10 +1,10 @@
 #ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_THREAD_IMPL_H_
 #define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_THREAD_IMPL_H_
 
+#include <optional>
 #include <string>
 #include <thread>  // NOLINT: only used outside of google3
 
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_export.h"
 
 class QUICHE_NO_EXPORT QuicheThreadImpl {
@@ -20,7 +20,7 @@
   void Join() { thread_->join(); }
 
  private:
-  absl::optional<std::thread> thread_;
+  std::optional<std::thread> thread_;
 };
 
 #endif  // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_THREAD_IMPL_H_
diff --git a/quiche/common/platform/default/quiche_platform_impl/quiche_time_utils_impl.cc b/quiche/common/platform/default/quiche_platform_impl/quiche_time_utils_impl.cc
index 71beb78..a350570 100644
--- a/quiche/common/platform/default/quiche_platform_impl/quiche_time_utils_impl.cc
+++ b/quiche/common/platform/default/quiche_platform_impl/quiche_time_utils_impl.cc
@@ -10,10 +10,10 @@
 
 // Chrome converts broken out UTC times for certificates to unix times using
 // the BoringSSL routines.
-absl::optional<int64_t> QuicheUtcDateTimeToUnixSecondsImpl(int year, int month,
-                                                           int day, int hour,
-                                                           int minute,
-                                                           int second) {
+std::optional<int64_t> QuicheUtcDateTimeToUnixSecondsImpl(int year, int month,
+                                                          int day, int hour,
+                                                          int minute,
+                                                          int second) {
   struct tm tmp_tm;
   tmp_tm.tm_year = year - 1900;
   tmp_tm.tm_mon = month - 1;
@@ -29,13 +29,13 @@
   }
   int64_t result;
   if (!OPENSSL_tm_to_posix(&tmp_tm, &result)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   // Our desired behaviour is to return the following second for a leap second
   // assuming it is a valid time.
   if (leap_second) {
     if (!OPENSSL_posix_to_tm(result + 1, &tmp_tm)) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     result++;
   }
diff --git a/quiche/common/platform/default/quiche_platform_impl/quiche_time_utils_impl.h b/quiche/common/platform/default/quiche_platform_impl/quiche_time_utils_impl.h
index 24ef40f..5106e19 100644
--- a/quiche/common/platform/default/quiche_platform_impl/quiche_time_utils_impl.h
+++ b/quiche/common/platform/default/quiche_platform_impl/quiche_time_utils_impl.h
@@ -6,15 +6,14 @@
 #define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_TIME_UTILS_IMPL_H_
 
 #include <cstdint>
-
-#include "absl/types/optional.h"
+#include <optional>
 
 namespace quiche {
 
-absl::optional<int64_t> QuicheUtcDateTimeToUnixSecondsImpl(int year, int month,
-                                                           int day, int hour,
-                                                           int minute,
-                                                           int second);
+std::optional<int64_t> QuicheUtcDateTimeToUnixSecondsImpl(int year, int month,
+                                                          int day, int hour,
+                                                          int minute,
+                                                          int second);
 
 }  // namespace quiche
 
diff --git a/quiche/common/platform/default/quiche_platform_impl/quiche_url_utils_impl.cc b/quiche/common/platform/default/quiche_platform_impl/quiche_url_utils_impl.cc
index d707145..686f631 100644
--- a/quiche/common/platform/default/quiche_platform_impl/quiche_url_utils_impl.cc
+++ b/quiche/common/platform/default/quiche_platform_impl/quiche_url_utils_impl.cc
@@ -7,6 +7,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <limits>
+#include <optional>
 #include <string>
 
 #include "quiche_platform_impl/quiche_googleurl_impl.h"
@@ -15,7 +16,6 @@
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_replace.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 
 namespace quiche {
 
@@ -57,7 +57,7 @@
   return true;
 }
 
-absl::optional<std::string> AsciiUrlDecodeImpl(absl::string_view input) {
+std::optional<std::string> AsciiUrlDecodeImpl(absl::string_view input) {
   std::string input_encoded = std::string(input);
   url::RawCanonOutputW<1024> canon_output;
   url::DecodeURLEscapeSequences(input_encoded.c_str(), input_encoded.length(),
@@ -68,7 +68,7 @@
   for (int i = 0; i < canon_output.length(); i++) {
     const uint16_t c = reinterpret_cast<uint16_t*>(canon_output.data())[i];
     if (c > std::numeric_limits<signed char>::max()) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     output += static_cast<char>(c);
   }
diff --git a/quiche/common/platform/default/quiche_platform_impl/quiche_url_utils_impl.h b/quiche/common/platform/default/quiche_platform_impl/quiche_url_utils_impl.h
index 45d87e0..7f30056 100644
--- a/quiche/common/platform/default/quiche_platform_impl/quiche_url_utils_impl.h
+++ b/quiche/common/platform/default/quiche_platform_impl/quiche_url_utils_impl.h
@@ -5,12 +5,12 @@
 #ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_URL_UTILS_IMPL_H_
 #define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_URL_UTILS_IMPL_H_
 
+#include <optional>
 #include <string>
 
 #include "absl/container/flat_hash_map.h"
 #include "absl/container/flat_hash_set.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_export.h"
 
 namespace quiche {
@@ -26,8 +26,8 @@
     absl::flat_hash_set<std::string>* vars_found = nullptr);
 
 // Decodes a URL-encoded string and converts it to ASCII. If the decoded input
-// contains non-ASCII characters, decoding fails and absl::nullopt is returned.
-QUICHE_EXPORT absl::optional<std::string> AsciiUrlDecodeImpl(
+// contains non-ASCII characters, decoding fails and std::nullopt is returned.
+QUICHE_EXPORT std::optional<std::string> AsciiUrlDecodeImpl(
     absl::string_view input);
 
 }  // namespace quiche
diff --git a/quiche/common/quiche_text_utils.cc b/quiche/common/quiche_text_utils.cc
index 5b4ee8e..23b03e8 100644
--- a/quiche/common/quiche_text_utils.cc
+++ b/quiche/common/quiche_text_utils.cc
@@ -29,11 +29,11 @@
 }
 
 // static
-absl::optional<std::string> QuicheTextUtils::Base64Decode(
+std::optional<std::string> QuicheTextUtils::Base64Decode(
     absl::string_view input) {
   std::string output;
   if (!absl::Base64Unescape(input, &output)) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return output;
 }
diff --git a/quiche/common/quiche_text_utils.h b/quiche/common/quiche_text_utils.h
index b433718..8f7d7f0 100644
--- a/quiche/common/quiche_text_utils.h
+++ b/quiche/common/quiche_text_utils.h
@@ -5,6 +5,7 @@
 #ifndef QUICHE_COMMON_QUICHE_TEXT_UTILS_H_
 #define QUICHE_COMMON_QUICHE_TEXT_UTILS_H_
 
+#include <optional>
 #include <string>
 
 #include "absl/hash/hash.h"
@@ -12,7 +13,6 @@
 #include "absl/strings/escaping.h"
 #include "absl/strings/match.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_export.h"
 
 namespace quiche {
@@ -50,7 +50,7 @@
 
   // Decodes a base64-encoded |input|.  Returns nullopt when the input is
   // invalid.
-  static absl::optional<std::string> Base64Decode(absl::string_view input);
+  static std::optional<std::string> Base64Decode(absl::string_view input);
 
   // Returns a string containing hex and ASCII representations of |binary|,
   // side-by-side in the style of hexdump. Non-printable characters will be
diff --git a/quiche/common/structured_headers.cc b/quiche/common/structured_headers.cc
index 58aec62..0762d0d 100644
--- a/quiche/common/structured_headers.cc
+++ b/quiche/common/structured_headers.cc
@@ -5,6 +5,7 @@
 #include "quiche/common/structured_headers.h"
 
 #include <cmath>
+#include <optional>
 #include <string>
 #include <utility>
 
@@ -96,14 +97,14 @@
   }
 
   // Parses a List of Lists ([SH09] 4.2.4).
-  absl::optional<ListOfLists> ReadListOfLists() {
+  std::optional<ListOfLists> ReadListOfLists() {
     QUICHE_CHECK_EQ(version_, kDraft09);
     ListOfLists result;
     while (true) {
       std::vector<Item> inner_list;
       while (true) {
-        absl::optional<Item> item(ReadBareItem());
-        if (!item) return absl::nullopt;
+        std::optional<Item> item(ReadBareItem());
+        if (!item) return std::nullopt;
         inner_list.push_back(std::move(*item));
         SkipWhitespaces();
         if (!ConsumeChar(';')) break;
@@ -118,37 +119,37 @@
   }
 
   // Parses a List ([RFC8941] 4.2.1).
-  absl::optional<List> ReadList() {
+  std::optional<List> ReadList() {
     QUICHE_CHECK_EQ(version_, kFinal);
     List members;
     while (!input_.empty()) {
-      absl::optional<ParameterizedMember> member(ReadItemOrInnerList());
-      if (!member) return absl::nullopt;
+      std::optional<ParameterizedMember> member(ReadItemOrInnerList());
+      if (!member) return std::nullopt;
       members.push_back(std::move(*member));
       SkipOWS();
       if (input_.empty()) break;
-      if (!ConsumeChar(',')) return absl::nullopt;
+      if (!ConsumeChar(',')) return std::nullopt;
       SkipOWS();
-      if (input_.empty()) return absl::nullopt;
+      if (input_.empty()) return std::nullopt;
     }
     return members;
   }
 
   // Parses an Item ([RFC8941] 4.2.3).
-  absl::optional<ParameterizedItem> ReadItem() {
-    absl::optional<Item> item = ReadBareItem();
-    if (!item) return absl::nullopt;
-    absl::optional<Parameters> parameters = ReadParameters();
-    if (!parameters) return absl::nullopt;
+  std::optional<ParameterizedItem> ReadItem() {
+    std::optional<Item> item = ReadBareItem();
+    if (!item) return std::nullopt;
+    std::optional<Parameters> parameters = ReadParameters();
+    if (!parameters) return std::nullopt;
     return ParameterizedItem(std::move(*item), std::move(*parameters));
   }
 
   // Parses a bare Item ([RFC8941] 4.2.3.1, though this is also the algorithm
   // for parsing an Item from [SH09] 4.2.7).
-  absl::optional<Item> ReadBareItem() {
+  std::optional<Item> ReadBareItem() {
     if (input_.empty()) {
       QUICHE_DVLOG(1) << "ReadBareItem: unexpected EOF";
-      return absl::nullopt;
+      return std::nullopt;
     }
     switch (input_.front()) {
       case '"':
@@ -158,52 +159,52 @@
         return ReadToken();
       case ':':
         if (version_ == kFinal) return ReadByteSequence();
-        return absl::nullopt;
+        return std::nullopt;
       case '?':
         return ReadBoolean();
       default:
         if (input_.front() == '-' || absl::ascii_isdigit(input_.front()))
           return ReadNumber();
         if (absl::ascii_isalpha(input_.front())) return ReadToken();
-        return absl::nullopt;
+        return std::nullopt;
     }
   }
 
   // Parses a Dictionary ([RFC8941] 4.2.2).
-  absl::optional<Dictionary> ReadDictionary() {
+  std::optional<Dictionary> ReadDictionary() {
     QUICHE_CHECK_EQ(version_, kFinal);
     Dictionary members;
     while (!input_.empty()) {
-      absl::optional<std::string> key(ReadKey());
-      if (!key) return absl::nullopt;
-      absl::optional<ParameterizedMember> member;
+      std::optional<std::string> key(ReadKey());
+      if (!key) return std::nullopt;
+      std::optional<ParameterizedMember> member;
       if (ConsumeChar('=')) {
         member = ReadItemOrInnerList();
-        if (!member) return absl::nullopt;
+        if (!member) return std::nullopt;
       } else {
-        absl::optional<Parameters> parameters;
+        std::optional<Parameters> parameters;
         parameters = ReadParameters();
-        if (!parameters) return absl::nullopt;
+        if (!parameters) return std::nullopt;
         member = ParameterizedMember{Item(true), std::move(*parameters)};
       }
       members[*key] = std::move(*member);
       SkipOWS();
       if (input_.empty()) break;
-      if (!ConsumeChar(',')) return absl::nullopt;
+      if (!ConsumeChar(',')) return std::nullopt;
       SkipOWS();
-      if (input_.empty()) return absl::nullopt;
+      if (input_.empty()) return std::nullopt;
     }
     return members;
   }
 
   // Parses a Parameterised List ([SH09] 4.2.5).
-  absl::optional<ParameterisedList> ReadParameterisedList() {
+  std::optional<ParameterisedList> ReadParameterisedList() {
     QUICHE_CHECK_EQ(version_, kDraft09);
     ParameterisedList items;
     while (true) {
-      absl::optional<ParameterisedIdentifier> item =
+      std::optional<ParameterisedIdentifier> item =
           ReadParameterisedIdentifier();
-      if (!item) return absl::nullopt;
+      if (!item) return std::nullopt;
       items.push_back(std::move(*item));
       SkipWhitespaces();
       if (!ConsumeChar(',')) return items;
@@ -213,10 +214,10 @@
 
  private:
   // Parses a Parameterised Identifier ([SH09] 4.2.6).
-  absl::optional<ParameterisedIdentifier> ReadParameterisedIdentifier() {
+  std::optional<ParameterisedIdentifier> ReadParameterisedIdentifier() {
     QUICHE_CHECK_EQ(version_, kDraft09);
-    absl::optional<Item> primary_identifier = ReadToken();
-    if (!primary_identifier) return absl::nullopt;
+    std::optional<Item> primary_identifier = ReadToken();
+    if (!primary_identifier) return std::nullopt;
 
     ParameterisedIdentifier::Parameters parameters;
 
@@ -224,19 +225,19 @@
     while (ConsumeChar(';')) {
       SkipWhitespaces();
 
-      absl::optional<std::string> name = ReadKey();
-      if (!name) return absl::nullopt;
+      std::optional<std::string> name = ReadKey();
+      if (!name) return std::nullopt;
 
       Item value;
       if (ConsumeChar('=')) {
         auto item = ReadBareItem();
-        if (!item) return absl::nullopt;
+        if (!item) return std::nullopt;
         value = std::move(*item);
       }
       if (!parameters.emplace(*name, value).second) {
         QUICHE_DVLOG(1) << "ReadParameterisedIdentifier: duplicated parameter: "
                         << *name;
-        return absl::nullopt;
+        return std::nullopt;
       }
       SkipWhitespaces();
     }
@@ -245,7 +246,7 @@
   }
 
   // Parses an Item or Inner List ([RFC8941] 4.2.1.1).
-  absl::optional<ParameterizedMember> ReadItemOrInnerList() {
+  std::optional<ParameterizedMember> ReadItemOrInnerList() {
     QUICHE_CHECK_EQ(version_, kFinal);
     std::vector<Item> member;
     bool member_is_inner_list = (!input_.empty() && input_.front() == '(');
@@ -253,28 +254,28 @@
       return ReadInnerList();
     } else {
       auto item = ReadItem();
-      if (!item) return absl::nullopt;
+      if (!item) return std::nullopt;
       return ParameterizedMember(std::move(item->item),
                                  std::move(item->params));
     }
   }
 
   // Parses Parameters ([RFC8941] 4.2.3.2)
-  absl::optional<Parameters> ReadParameters() {
+  std::optional<Parameters> ReadParameters() {
     Parameters parameters;
     absl::flat_hash_set<std::string> keys;
 
     while (ConsumeChar(';')) {
       SkipWhitespaces();
 
-      absl::optional<std::string> name = ReadKey();
-      if (!name) return absl::nullopt;
+      std::optional<std::string> name = ReadKey();
+      if (!name) return std::nullopt;
       bool is_duplicate_key = !keys.insert(*name).second;
 
       Item value{true};
       if (ConsumeChar('=')) {
         auto item = ReadBareItem();
-        if (!item) return absl::nullopt;
+        if (!item) return std::nullopt;
         value = std::move(*item);
       }
       if (is_duplicate_key) {
@@ -292,41 +293,41 @@
   }
 
   // Parses an Inner List ([RFC8941] 4.2.1.2).
-  absl::optional<ParameterizedMember> ReadInnerList() {
+  std::optional<ParameterizedMember> ReadInnerList() {
     QUICHE_CHECK_EQ(version_, kFinal);
-    if (!ConsumeChar('(')) return absl::nullopt;
+    if (!ConsumeChar('(')) return std::nullopt;
     std::vector<ParameterizedItem> inner_list;
     while (true) {
       SkipWhitespaces();
       if (ConsumeChar(')')) {
-        absl::optional<Parameters> parameters;
+        std::optional<Parameters> parameters;
         parameters = ReadParameters();
-        if (!parameters) return absl::nullopt;
+        if (!parameters) return std::nullopt;
         return ParameterizedMember(std::move(inner_list), true,
                                    std::move(*parameters));
       }
       auto item = ReadItem();
-      if (!item) return absl::nullopt;
+      if (!item) return std::nullopt;
       inner_list.push_back(std::move(*item));
       if (input_.empty() || (input_.front() != ' ' && input_.front() != ')'))
-        return absl::nullopt;
+        return std::nullopt;
     }
     QUICHE_NOTREACHED();
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Parses a Key ([SH09] 4.2.2, [RFC8941] 4.2.3.3).
-  absl::optional<std::string> ReadKey() {
+  std::optional<std::string> ReadKey() {
     if (version_ == kDraft09) {
       if (input_.empty() || !absl::ascii_islower(input_.front())) {
         LogParseError("ReadKey", "lcalpha");
-        return absl::nullopt;
+        return std::nullopt;
       }
     } else {
       if (input_.empty() ||
           (!absl::ascii_islower(input_.front()) && input_.front() != '*')) {
         LogParseError("ReadKey", "lcalpha | *");
-        return absl::nullopt;
+        return std::nullopt;
       }
     }
     const char* allowed_chars =
@@ -339,11 +340,11 @@
   }
 
   // Parses a Token ([SH09] 4.2.10, [RFC8941] 4.2.6).
-  absl::optional<Item> ReadToken() {
+  std::optional<Item> ReadToken() {
     if (input_.empty() ||
         !(absl::ascii_isalpha(input_.front()) || input_.front() == '*')) {
       LogParseError("ReadToken", "ALPHA");
-      return absl::nullopt;
+      return std::nullopt;
     }
     size_t len = input_.find_first_not_of(version_ == kDraft09 ? kTokenChars09
                                                                : kTokenChars);
@@ -354,7 +355,7 @@
   }
 
   // Parses a Number ([SH09] 4.2.8, [RFC8941] 4.2.4).
-  absl::optional<Item> ReadNumber() {
+  std::optional<Item> ReadNumber() {
     bool is_negative = ConsumeChar('-');
     bool is_decimal = false;
     size_t decimal_position = 0;
@@ -369,30 +370,30 @@
     }
     if (i == 0) {
       LogParseError("ReadNumber", "DIGIT");
-      return absl::nullopt;
+      return std::nullopt;
     }
     if (!is_decimal) {
       // [RFC8941] restricts the range of integers further.
       if (version_ == kFinal && i > 15) {
         LogParseError("ReadNumber", "integer too long");
-        return absl::nullopt;
+        return std::nullopt;
       }
     } else {
       if (version_ != kFinal && i > 16) {
         LogParseError("ReadNumber", "float too long");
-        return absl::nullopt;
+        return std::nullopt;
       }
       if (version_ == kFinal && decimal_position > 12) {
         LogParseError("ReadNumber", "decimal too long");
-        return absl::nullopt;
+        return std::nullopt;
       }
       if (i - decimal_position > (version_ == kFinal ? 4 : 7)) {
         LogParseError("ReadNumber", "too many digits after decimal");
-        return absl::nullopt;
+        return std::nullopt;
       }
       if (i == decimal_position) {
         LogParseError("ReadNumber", "no digits after decimal");
-        return absl::nullopt;
+        return std::nullopt;
       }
     }
     std::string output_number_string(input_.substr(0, i));
@@ -402,13 +403,13 @@
       // Convert to a 64-bit double, and return if the conversion is
       // successful.
       double f;
-      if (!absl::SimpleAtod(output_number_string, &f)) return absl::nullopt;
+      if (!absl::SimpleAtod(output_number_string, &f)) return std::nullopt;
       return Item(is_negative ? -f : f);
     } else {
       // Convert to a 64-bit signed integer, and return if the conversion is
       // successful.
       int64_t n;
-      if (!absl::SimpleAtoi(output_number_string, &n)) return absl::nullopt;
+      if (!absl::SimpleAtoi(output_number_string, &n)) return std::nullopt;
       QUICHE_CHECK(version_ != kFinal ||
                    (n <= kMaxInteger && n >= kMinInteger));
       return Item(is_negative ? -n : n);
@@ -416,35 +417,35 @@
   }
 
   // Parses a String ([SH09] 4.2.9, [RFC8941] 4.2.5).
-  absl::optional<Item> ReadString() {
+  std::optional<Item> ReadString() {
     std::string s;
     if (!ConsumeChar('"')) {
       LogParseError("ReadString", "'\"'");
-      return absl::nullopt;
+      return std::nullopt;
     }
     while (!ConsumeChar('"')) {
       size_t i = 0;
       for (; i < input_.size(); ++i) {
         if (!absl::ascii_isprint(input_[i])) {
           QUICHE_DVLOG(1) << "ReadString: non printable-ASCII character";
-          return absl::nullopt;
+          return std::nullopt;
         }
         if (input_[i] == '"' || input_[i] == '\\') break;
       }
       if (i == input_.size()) {
         QUICHE_DVLOG(1) << "ReadString: missing closing '\"'";
-        return absl::nullopt;
+        return std::nullopt;
       }
       s.append(std::string(input_.substr(0, i)));
       input_.remove_prefix(i);
       if (ConsumeChar('\\')) {
         if (input_.empty()) {
           QUICHE_DVLOG(1) << "ReadString: backslash at string end";
-          return absl::nullopt;
+          return std::nullopt;
         }
         if (input_[0] != '"' && input_[0] != '\\') {
           QUICHE_DVLOG(1) << "ReadString: invalid escape";
-          return absl::nullopt;
+          return std::nullopt;
         }
         s.push_back(input_.front());
         input_.remove_prefix(1);
@@ -454,16 +455,16 @@
   }
 
   // Parses a Byte Sequence ([SH09] 4.2.11, [RFC8941] 4.2.7).
-  absl::optional<Item> ReadByteSequence() {
+  std::optional<Item> ReadByteSequence() {
     char delimiter = (version_ == kDraft09 ? '*' : ':');
     if (!ConsumeChar(delimiter)) {
       LogParseError("ReadByteSequence", "delimiter");
-      return absl::nullopt;
+      return std::nullopt;
     }
     size_t len = input_.find(delimiter);
     if (len == absl::string_view::npos) {
       QUICHE_DVLOG(1) << "ReadByteSequence: missing closing delimiter";
-      return absl::nullopt;
+      return std::nullopt;
     }
     std::string base64(input_.substr(0, len));
     // Append the necessary padding characters.
@@ -473,7 +474,7 @@
     if (!absl::Base64Unescape(base64, &binary)) {
       QUICHE_DVLOG(1) << "ReadByteSequence: failed to decode base64: "
                       << base64;
-      return absl::nullopt;
+      return std::nullopt;
     }
     input_.remove_prefix(len);
     ConsumeChar(delimiter);
@@ -483,10 +484,10 @@
   // Parses a Boolean ([RFC8941] 4.2.8).
   // Note that this only parses ?0 and ?1 forms from SH version 10+, not the
   // previous ?F and ?T, which were not needed by any consumers of SH version 9.
-  absl::optional<Item> ReadBoolean() {
+  std::optional<Item> ReadBoolean() {
     if (!ConsumeChar('?')) {
       LogParseError("ReadBoolean", "'?'");
-      return absl::nullopt;
+      return std::nullopt;
     }
     if (ConsumeChar('1')) {
       return Item(true);
@@ -494,7 +495,7 @@
     if (ConsumeChar('0')) {
       return Item(false);
     }
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // There are several points in the specs where the handling of whitespace
@@ -839,71 +840,70 @@
   return false;
 }
 
-absl::optional<ParameterizedItem> ParseItem(absl::string_view str) {
+std::optional<ParameterizedItem> ParseItem(absl::string_view str) {
   StructuredHeaderParser parser(str, StructuredHeaderParser::kFinal);
-  absl::optional<ParameterizedItem> item = parser.ReadItem();
+  std::optional<ParameterizedItem> item = parser.ReadItem();
   if (item && parser.FinishParsing()) return item;
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<Item> ParseBareItem(absl::string_view str) {
+std::optional<Item> ParseBareItem(absl::string_view str) {
   StructuredHeaderParser parser(str, StructuredHeaderParser::kFinal);
-  absl::optional<Item> item = parser.ReadBareItem();
+  std::optional<Item> item = parser.ReadBareItem();
   if (item && parser.FinishParsing()) return item;
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<ParameterisedList> ParseParameterisedList(
-    absl::string_view str) {
+std::optional<ParameterisedList> ParseParameterisedList(absl::string_view str) {
   StructuredHeaderParser parser(str, StructuredHeaderParser::kDraft09);
-  absl::optional<ParameterisedList> param_list = parser.ReadParameterisedList();
+  std::optional<ParameterisedList> param_list = parser.ReadParameterisedList();
   if (param_list && parser.FinishParsing()) return param_list;
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<ListOfLists> ParseListOfLists(absl::string_view str) {
+std::optional<ListOfLists> ParseListOfLists(absl::string_view str) {
   StructuredHeaderParser parser(str, StructuredHeaderParser::kDraft09);
-  absl::optional<ListOfLists> list_of_lists = parser.ReadListOfLists();
+  std::optional<ListOfLists> list_of_lists = parser.ReadListOfLists();
   if (list_of_lists && parser.FinishParsing()) return list_of_lists;
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<List> ParseList(absl::string_view str) {
+std::optional<List> ParseList(absl::string_view str) {
   StructuredHeaderParser parser(str, StructuredHeaderParser::kFinal);
-  absl::optional<List> list = parser.ReadList();
+  std::optional<List> list = parser.ReadList();
   if (list && parser.FinishParsing()) return list;
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<Dictionary> ParseDictionary(absl::string_view str) {
+std::optional<Dictionary> ParseDictionary(absl::string_view str) {
   StructuredHeaderParser parser(str, StructuredHeaderParser::kFinal);
-  absl::optional<Dictionary> dictionary = parser.ReadDictionary();
+  std::optional<Dictionary> dictionary = parser.ReadDictionary();
   if (dictionary && parser.FinishParsing()) return dictionary;
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<std::string> SerializeItem(const Item& value) {
+std::optional<std::string> SerializeItem(const Item& value) {
   StructuredHeaderSerializer s;
   if (s.WriteItem(ParameterizedItem(value, {}))) return s.Output();
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<std::string> SerializeItem(const ParameterizedItem& value) {
+std::optional<std::string> SerializeItem(const ParameterizedItem& value) {
   StructuredHeaderSerializer s;
   if (s.WriteItem(value)) return s.Output();
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<std::string> SerializeList(const List& value) {
+std::optional<std::string> SerializeList(const List& value) {
   StructuredHeaderSerializer s;
   if (s.WriteList(value)) return s.Output();
-  return absl::nullopt;
+  return std::nullopt;
 }
 
-absl::optional<std::string> SerializeDictionary(const Dictionary& value) {
+std::optional<std::string> SerializeDictionary(const Dictionary& value) {
   StructuredHeaderSerializer s;
   if (s.WriteDictionary(value)) return s.Output();
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 }  // namespace structured_headers
diff --git a/quiche/common/structured_headers.h b/quiche/common/structured_headers.h
index 00bf795..af1b199 100644
--- a/quiche/common/structured_headers.h
+++ b/quiche/common/structured_headers.h
@@ -7,13 +7,13 @@
 
 #include <algorithm>
 #include <map>
+#include <optional>
 #include <string>
 #include <tuple>
 #include <utility>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/variant.h"
 #include "quiche/common/platform/api/quiche_export.h"
 #include "quiche/common/platform/api/quiche_logging.h"
@@ -276,13 +276,12 @@
 // Returns the result of parsing the header value as an Item, if it can be
 // parsed as one, or nullopt if it cannot. Note that this uses the Draft 15
 // parsing rules, and so applies tighter range limits to integers.
-QUICHE_EXPORT absl::optional<ParameterizedItem> ParseItem(
-    absl::string_view str);
+QUICHE_EXPORT std::optional<ParameterizedItem> ParseItem(absl::string_view str);
 
 // Returns the result of parsing the header value as an Item with no parameters,
 // or nullopt if it cannot. Note that this uses the Draft 15 parsing rules, and
 // so applies tighter range limits to integers.
-QUICHE_EXPORT absl::optional<Item> ParseBareItem(absl::string_view str);
+QUICHE_EXPORT std::optional<Item> ParseBareItem(absl::string_view str);
 
 // Returns the result of parsing the header value as a Parameterised List, if it
 // can be parsed as one, or nullopt if it cannot. Note that parameter keys will
@@ -290,7 +289,7 @@
 // as well as parameter values, will be returned as Items. This method uses the
 // Draft 09 parsing rules for Items, so integers have the 64-bit int range.
 // Structured-Headers Draft 09 only.
-QUICHE_EXPORT absl::optional<ParameterisedList> ParseParameterisedList(
+QUICHE_EXPORT std::optional<ParameterisedList> ParseParameterisedList(
     absl::string_view str);
 
 // Returns the result of parsing the header value as a List of Lists, if it can
@@ -298,25 +297,25 @@
 // as Items. This method uses the Draft 09 parsing rules for Items, so integers
 // have the 64-bit int range.
 // Structured-Headers Draft 09 only.
-QUICHE_EXPORT absl::optional<ListOfLists> ParseListOfLists(
+QUICHE_EXPORT std::optional<ListOfLists> ParseListOfLists(
     absl::string_view str);
 
 // Returns the result of parsing the header value as a general List, if it can
 // be parsed as one, or nullopt if it cannot.
 // Structured-Headers Draft 15 only.
-QUICHE_EXPORT absl::optional<List> ParseList(absl::string_view str);
+QUICHE_EXPORT std::optional<List> ParseList(absl::string_view str);
 
 // Returns the result of parsing the header value as a general Dictionary, if it
 // can be parsed as one, or nullopt if it cannot. Structured-Headers Draft 15
 // only.
-QUICHE_EXPORT absl::optional<Dictionary> ParseDictionary(absl::string_view str);
+QUICHE_EXPORT std::optional<Dictionary> ParseDictionary(absl::string_view str);
 
 // Serialization is implemented for Structured-Headers Draft 15 only.
-QUICHE_EXPORT absl::optional<std::string> SerializeItem(const Item& value);
-QUICHE_EXPORT absl::optional<std::string> SerializeItem(
+QUICHE_EXPORT std::optional<std::string> SerializeItem(const Item& value);
+QUICHE_EXPORT std::optional<std::string> SerializeItem(
     const ParameterizedItem& value);
-QUICHE_EXPORT absl::optional<std::string> SerializeList(const List& value);
-QUICHE_EXPORT absl::optional<std::string> SerializeDictionary(
+QUICHE_EXPORT std::optional<std::string> SerializeList(const List& value);
+QUICHE_EXPORT std::optional<std::string> SerializeDictionary(
     const Dictionary& value);
 
 }  // namespace structured_headers
diff --git a/quiche/common/structured_headers_generated_test.cc b/quiche/common/structured_headers_generated_test.cc
index 7e94e49..d9b1dc6 100644
--- a/quiche/common/structured_headers_generated_test.cc
+++ b/quiche/common/structured_headers_generated_test.cc
@@ -48,7 +48,7 @@
   const char* name;
   const char* raw;
   size_t raw_len;
-  const absl::optional<ParameterizedItem>
+  const std::optional<ParameterizedItem>
       expected;           // nullopt if parse error is expected.
   const char* canonical;  // nullptr if parse error is expected, or if canonical
                           // format is identical to raw.
@@ -69,10 +69,10 @@
      9,
      {{Item("hello", Item::kByteSequenceType), {}}},
      ":aGVsbG8=:"},
-    {"bad end delimiter", ":aGVsbG8=", 9, absl::nullopt, nullptr},
-    {"extra whitespace", ":aGVsb G8=:", 11, absl::nullopt, nullptr},
-    {"extra chars", ":aGVsbG!8=:", 11, absl::nullopt, nullptr},
-    {"suffix chars", ":aGVsbG8=!:", 11, absl::nullopt, nullptr},
+    {"bad end delimiter", ":aGVsbG8=", 9, std::nullopt, nullptr},
+    {"extra whitespace", ":aGVsb G8=:", 11, std::nullopt, nullptr},
+    {"extra chars", ":aGVsbG!8=:", 11, std::nullopt, nullptr},
+    {"suffix chars", ":aGVsbG8=!:", 11, std::nullopt, nullptr},
     {"non-zero pad bits",
      ":iZ==:",
      6,
@@ -83,19 +83,19 @@
      6,
      {{Item("\377\340!", Item::kByteSequenceType), {}}},
      nullptr},
-    {"base64url binary", ":_-Ah:", 6, absl::nullopt, nullptr},
+    {"base64url binary", ":_-Ah:", 6, std::nullopt, nullptr},
     // boolean.json
     {"basic true boolean", "?1", 2, {{Item(true), {}}}, nullptr},
     {"basic false boolean", "?0", 2, {{Item(false), {}}}, nullptr},
-    {"unknown boolean", "?Q", 2, absl::nullopt, nullptr},
-    {"whitespace boolean", "? 1", 3, absl::nullopt, nullptr},
-    {"negative zero boolean", "?-0", 3, absl::nullopt, nullptr},
-    {"T boolean", "?T", 2, absl::nullopt, nullptr},
-    {"F boolean", "?F", 2, absl::nullopt, nullptr},
-    {"t boolean", "?t", 2, absl::nullopt, nullptr},
-    {"f boolean", "?f", 2, absl::nullopt, nullptr},
-    {"spelled-out True boolean", "?True", 5, absl::nullopt, nullptr},
-    {"spelled-out False boolean", "?False", 6, absl::nullopt, nullptr},
+    {"unknown boolean", "?Q", 2, std::nullopt, nullptr},
+    {"whitespace boolean", "? 1", 3, std::nullopt, nullptr},
+    {"negative zero boolean", "?-0", 3, std::nullopt, nullptr},
+    {"T boolean", "?T", 2, std::nullopt, nullptr},
+    {"F boolean", "?F", 2, std::nullopt, nullptr},
+    {"t boolean", "?t", 2, std::nullopt, nullptr},
+    {"f boolean", "?f", 2, std::nullopt, nullptr},
+    {"spelled-out True boolean", "?True", 5, std::nullopt, nullptr},
+    {"spelled-out False boolean", "?False", 6, std::nullopt, nullptr},
     // examples.json
     {"Foo-Example",
      "2; foourl=\"https://foo.example.com/\"",
@@ -127,9 +127,9 @@
      nullptr},
     {"Example-BoolHdr", "?1", 2, {{Item(true), {}}}, nullptr},
     // item.json
-    {"empty item", "", 0, absl::nullopt, nullptr},
-    {"leading space", " \t 1", 4, absl::nullopt, nullptr},
-    {"trailing space", "1 \t ", 4, absl::nullopt, nullptr},
+    {"empty item", "", 0, std::nullopt, nullptr},
+    {"leading space", " \t 1", 4, std::nullopt, nullptr},
+    {"trailing space", "1 \t ", 4, std::nullopt, nullptr},
     {"leading and trailing space", "  1  ", 5, {{Integer(1), {}}}, "1"},
     {"leading and trailing whitespace", "     1  ", 8, {{Integer(1), {}}}, "1"},
     // number-generated.json
@@ -962,27 +962,27 @@
      16,
      {{Item(999999999999.999023), {}}},
      nullptr},
-    {"too many digit 0 decimal", "000000000000000.0", 17, absl::nullopt,
+    {"too many digit 0 decimal", "000000000000000.0", 17, std::nullopt,
      nullptr},
     {"too many fractional digits 0 decimal", "000000000000.0000", 17,
-     absl::nullopt, nullptr},
-    {"too many digit 9 decimal", "999999999999999.9", 17, absl::nullopt,
+     std::nullopt, nullptr},
+    {"too many digit 9 decimal", "999999999999999.9", 17, std::nullopt,
      nullptr},
     {"too many fractional digits 9 decimal", "999999999999.9999", 17,
-     absl::nullopt, nullptr},
+     std::nullopt, nullptr},
     // number.json
     {"basic integer", "42", 2, {{Integer(42), {}}}, nullptr},
     {"zero integer", "0", 1, {{Integer(0), {}}}, nullptr},
     {"negative zero", "-0", 2, {{Integer(0), {}}}, "0"},
-    {"double negative zero", "--0", 3, absl::nullopt, nullptr},
+    {"double negative zero", "--0", 3, std::nullopt, nullptr},
     {"negative integer", "-42", 3, {{Integer(-42), {}}}, nullptr},
     {"leading 0 integer", "042", 3, {{Integer(42), {}}}, "42"},
     {"leading 0 negative integer", "-042", 4, {{Integer(-42), {}}}, "-42"},
     {"leading 0 zero", "00", 2, {{Integer(0), {}}}, "0"},
-    {"comma", "2,3", 3, absl::nullopt, nullptr},
-    {"negative non-DIGIT first character", "-a23", 4, absl::nullopt, nullptr},
-    {"sign out of place", "4-2", 3, absl::nullopt, nullptr},
-    {"whitespace after sign", "- 42", 4, absl::nullopt, nullptr},
+    {"comma", "2,3", 3, std::nullopt, nullptr},
+    {"negative non-DIGIT first character", "-a23", 4, std::nullopt, nullptr},
+    {"sign out of place", "4-2", 3, std::nullopt, nullptr},
+    {"whitespace after sign", "- 42", 4, std::nullopt, nullptr},
     {"long integer",
      "123456789012345",
      15,
@@ -993,22 +993,22 @@
      16,
      {{Integer(-123456789012345), {}}},
      nullptr},
-    {"too long integer", "1234567890123456", 16, absl::nullopt, nullptr},
-    {"negative too long integer", "-1234567890123456", 17, absl::nullopt,
+    {"too long integer", "1234567890123456", 16, std::nullopt, nullptr},
+    {"negative too long integer", "-1234567890123456", 17, std::nullopt,
      nullptr},
     {"simple decimal", "1.23", 4, {{Item(1.230000), {}}}, nullptr},
     {"negative decimal", "-1.23", 5, {{Item(-1.230000), {}}}, nullptr},
-    {"decimal, whitespace after decimal", "1. 23", 5, absl::nullopt, nullptr},
-    {"decimal, whitespace before decimal", "1 .23", 5, absl::nullopt, nullptr},
-    {"negative decimal, whitespace after sign", "- 1.23", 6, absl::nullopt,
+    {"decimal, whitespace after decimal", "1. 23", 5, std::nullopt, nullptr},
+    {"decimal, whitespace before decimal", "1 .23", 5, std::nullopt, nullptr},
+    {"negative decimal, whitespace after sign", "- 1.23", 6, std::nullopt,
      nullptr},
     {"tricky precision decimal",
      "123456789012.1",
      14,
      {{Item(123456789012.100006), {}}},
      nullptr},
-    {"double decimal decimal", "1.5.4", 5, absl::nullopt, nullptr},
-    {"adjacent double decimal decimal", "1..4", 4, absl::nullopt, nullptr},
+    {"double decimal decimal", "1.5.4", 5, std::nullopt, nullptr},
+    {"adjacent double decimal decimal", "1..4", 4, std::nullopt, nullptr},
     {"decimal with three fractional digits",
      "1.123",
      5,
@@ -1019,50 +1019,49 @@
      6,
      {{Item(-1.123000), {}}},
      nullptr},
-    {"decimal with four fractional digits", "1.1234", 6, absl::nullopt,
+    {"decimal with four fractional digits", "1.1234", 6, std::nullopt, nullptr},
+    {"negative decimal with four fractional digits", "-1.1234", 7, std::nullopt,
      nullptr},
-    {"negative decimal with four fractional digits", "-1.1234", 7,
-     absl::nullopt, nullptr},
     {"decimal with thirteen integer digits", "1234567890123.0", 15,
-     absl::nullopt, nullptr},
+     std::nullopt, nullptr},
     {"negative decimal with thirteen integer digits", "-1234567890123.0", 16,
-     absl::nullopt, nullptr},
+     std::nullopt, nullptr},
     // string-generated.json
-    {"0x00 in string", "\" \000 \"", 5, absl::nullopt, nullptr},
-    {"0x01 in string", "\" \001 \"", 5, absl::nullopt, nullptr},
-    {"0x02 in string", "\" \002 \"", 5, absl::nullopt, nullptr},
-    {"0x03 in string", "\" \003 \"", 5, absl::nullopt, nullptr},
-    {"0x04 in string", "\" \004 \"", 5, absl::nullopt, nullptr},
-    {"0x05 in string", "\" \005 \"", 5, absl::nullopt, nullptr},
-    {"0x06 in string", "\" \006 \"", 5, absl::nullopt, nullptr},
-    {"0x07 in string", "\" \a \"", 5, absl::nullopt, nullptr},
-    {"0x08 in string", "\" \b \"", 5, absl::nullopt, nullptr},
-    {"0x09 in string", "\" \t \"", 5, absl::nullopt, nullptr},
-    {"0x0a in string", "\" \n \"", 5, absl::nullopt, nullptr},
-    {"0x0b in string", "\" \v \"", 5, absl::nullopt, nullptr},
-    {"0x0c in string", "\" \f \"", 5, absl::nullopt, nullptr},
-    {"0x0d in string", "\" \r \"", 5, absl::nullopt, nullptr},
-    {"0x0e in string", "\" \016 \"", 5, absl::nullopt, nullptr},
-    {"0x0f in string", "\" \017 \"", 5, absl::nullopt, nullptr},
-    {"0x10 in string", "\" \020 \"", 5, absl::nullopt, nullptr},
-    {"0x11 in string", "\" \021 \"", 5, absl::nullopt, nullptr},
-    {"0x12 in string", "\" \022 \"", 5, absl::nullopt, nullptr},
-    {"0x13 in string", "\" \023 \"", 5, absl::nullopt, nullptr},
-    {"0x14 in string", "\" \024 \"", 5, absl::nullopt, nullptr},
-    {"0x15 in string", "\" \025 \"", 5, absl::nullopt, nullptr},
-    {"0x16 in string", "\" \026 \"", 5, absl::nullopt, nullptr},
-    {"0x17 in string", "\" \027 \"", 5, absl::nullopt, nullptr},
-    {"0x18 in string", "\" \030 \"", 5, absl::nullopt, nullptr},
-    {"0x19 in string", "\" \031 \"", 5, absl::nullopt, nullptr},
-    {"0x1a in string", "\" \032 \"", 5, absl::nullopt, nullptr},
-    {"0x1b in string", "\" \033 \"", 5, absl::nullopt, nullptr},
-    {"0x1c in string", "\" \034 \"", 5, absl::nullopt, nullptr},
-    {"0x1d in string", "\" \035 \"", 5, absl::nullopt, nullptr},
-    {"0x1e in string", "\" \036 \"", 5, absl::nullopt, nullptr},
-    {"0x1f in string", "\" \037 \"", 5, absl::nullopt, nullptr},
+    {"0x00 in string", "\" \000 \"", 5, std::nullopt, nullptr},
+    {"0x01 in string", "\" \001 \"", 5, std::nullopt, nullptr},
+    {"0x02 in string", "\" \002 \"", 5, std::nullopt, nullptr},
+    {"0x03 in string", "\" \003 \"", 5, std::nullopt, nullptr},
+    {"0x04 in string", "\" \004 \"", 5, std::nullopt, nullptr},
+    {"0x05 in string", "\" \005 \"", 5, std::nullopt, nullptr},
+    {"0x06 in string", "\" \006 \"", 5, std::nullopt, nullptr},
+    {"0x07 in string", "\" \a \"", 5, std::nullopt, nullptr},
+    {"0x08 in string", "\" \b \"", 5, std::nullopt, nullptr},
+    {"0x09 in string", "\" \t \"", 5, std::nullopt, nullptr},
+    {"0x0a in string", "\" \n \"", 5, std::nullopt, nullptr},
+    {"0x0b in string", "\" \v \"", 5, std::nullopt, nullptr},
+    {"0x0c in string", "\" \f \"", 5, std::nullopt, nullptr},
+    {"0x0d in string", "\" \r \"", 5, std::nullopt, nullptr},
+    {"0x0e in string", "\" \016 \"", 5, std::nullopt, nullptr},
+    {"0x0f in string", "\" \017 \"", 5, std::nullopt, nullptr},
+    {"0x10 in string", "\" \020 \"", 5, std::nullopt, nullptr},
+    {"0x11 in string", "\" \021 \"", 5, std::nullopt, nullptr},
+    {"0x12 in string", "\" \022 \"", 5, std::nullopt, nullptr},
+    {"0x13 in string", "\" \023 \"", 5, std::nullopt, nullptr},
+    {"0x14 in string", "\" \024 \"", 5, std::nullopt, nullptr},
+    {"0x15 in string", "\" \025 \"", 5, std::nullopt, nullptr},
+    {"0x16 in string", "\" \026 \"", 5, std::nullopt, nullptr},
+    {"0x17 in string", "\" \027 \"", 5, std::nullopt, nullptr},
+    {"0x18 in string", "\" \030 \"", 5, std::nullopt, nullptr},
+    {"0x19 in string", "\" \031 \"", 5, std::nullopt, nullptr},
+    {"0x1a in string", "\" \032 \"", 5, std::nullopt, nullptr},
+    {"0x1b in string", "\" \033 \"", 5, std::nullopt, nullptr},
+    {"0x1c in string", "\" \034 \"", 5, std::nullopt, nullptr},
+    {"0x1d in string", "\" \035 \"", 5, std::nullopt, nullptr},
+    {"0x1e in string", "\" \036 \"", 5, std::nullopt, nullptr},
+    {"0x1f in string", "\" \037 \"", 5, std::nullopt, nullptr},
     {"0x20 in string", "\"   \"", 5, {{Item("   "), {}}}, nullptr},
     {"0x21 in string", "\" ! \"", 5, {{Item(" ! "), {}}}, nullptr},
-    {"0x22 in string", "\" \" \"", 5, absl::nullopt, nullptr},
+    {"0x22 in string", "\" \" \"", 5, std::nullopt, nullptr},
     {"0x23 in string", "\" # \"", 5, {{Item(" # "), {}}}, nullptr},
     {"0x24 in string", "\" $ \"", 5, {{Item(" $ "), {}}}, nullptr},
     {"0x25 in string", "\" % \"", 5, {{Item(" % "), {}}}, nullptr},
@@ -1120,7 +1119,7 @@
     {"0x59 in string", "\" Y \"", 5, {{Item(" Y "), {}}}, nullptr},
     {"0x5a in string", "\" Z \"", 5, {{Item(" Z "), {}}}, nullptr},
     {"0x5b in string", "\" [ \"", 5, {{Item(" [ "), {}}}, nullptr},
-    {"0x5c in string", "\" \\ \"", 5, absl::nullopt, nullptr},
+    {"0x5c in string", "\" \\ \"", 5, std::nullopt, nullptr},
     {"0x5d in string", "\" ] \"", 5, {{Item(" ] "), {}}}, nullptr},
     {"0x5e in string", "\" ^ \"", 5, {{Item(" ^ "), {}}}, nullptr},
     {"0x5f in string", "\" _ \"", 5, {{Item(" _ "), {}}}, nullptr},
@@ -1155,135 +1154,135 @@
     {"0x7c in string", "\" | \"", 5, {{Item(" | "), {}}}, nullptr},
     {"0x7d in string", "\" } \"", 5, {{Item(" } "), {}}}, nullptr},
     {"0x7e in string", "\" ~ \"", 5, {{Item(" ~ "), {}}}, nullptr},
-    {"0x7f in string", "\" \177 \"", 5, absl::nullopt, nullptr},
-    {"Escaped 0x00 in string", "\"\\\000\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x01 in string", "\"\\\001\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x02 in string", "\"\\\002\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x03 in string", "\"\\\003\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x04 in string", "\"\\\004\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x05 in string", "\"\\\005\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x06 in string", "\"\\\006\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x07 in string", "\"\\\a\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x08 in string", "\"\\\b\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x09 in string", "\"\\\t\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x0a in string", "\"\\\n\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x0b in string", "\"\\\v\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x0c in string", "\"\\\f\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x0d in string", "\"\\\r\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x0e in string", "\"\\\016\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x0f in string", "\"\\\017\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x10 in string", "\"\\\020\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x11 in string", "\"\\\021\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x12 in string", "\"\\\022\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x13 in string", "\"\\\023\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x14 in string", "\"\\\024\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x15 in string", "\"\\\025\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x16 in string", "\"\\\026\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x17 in string", "\"\\\027\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x18 in string", "\"\\\030\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x19 in string", "\"\\\031\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x1a in string", "\"\\\032\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x1b in string", "\"\\\033\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x1c in string", "\"\\\034\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x1d in string", "\"\\\035\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x1e in string", "\"\\\036\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x1f in string", "\"\\\037\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x20 in string", "\"\\ \"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x21 in string", "\"\\!\"", 4, absl::nullopt, nullptr},
+    {"0x7f in string", "\" \177 \"", 5, std::nullopt, nullptr},
+    {"Escaped 0x00 in string", "\"\\\000\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x01 in string", "\"\\\001\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x02 in string", "\"\\\002\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x03 in string", "\"\\\003\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x04 in string", "\"\\\004\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x05 in string", "\"\\\005\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x06 in string", "\"\\\006\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x07 in string", "\"\\\a\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x08 in string", "\"\\\b\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x09 in string", "\"\\\t\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x0a in string", "\"\\\n\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x0b in string", "\"\\\v\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x0c in string", "\"\\\f\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x0d in string", "\"\\\r\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x0e in string", "\"\\\016\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x0f in string", "\"\\\017\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x10 in string", "\"\\\020\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x11 in string", "\"\\\021\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x12 in string", "\"\\\022\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x13 in string", "\"\\\023\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x14 in string", "\"\\\024\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x15 in string", "\"\\\025\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x16 in string", "\"\\\026\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x17 in string", "\"\\\027\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x18 in string", "\"\\\030\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x19 in string", "\"\\\031\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x1a in string", "\"\\\032\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x1b in string", "\"\\\033\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x1c in string", "\"\\\034\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x1d in string", "\"\\\035\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x1e in string", "\"\\\036\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x1f in string", "\"\\\037\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x20 in string", "\"\\ \"", 4, std::nullopt, nullptr},
+    {"Escaped 0x21 in string", "\"\\!\"", 4, std::nullopt, nullptr},
     {"Escaped 0x22 in string", "\"\\\"\"", 4, {{Item("\""), {}}}, nullptr},
-    {"Escaped 0x23 in string", "\"\\#\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x24 in string", "\"\\$\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x25 in string", "\"\\%\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x26 in string", "\"\\&\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x27 in string", "\"\\'\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x28 in string", "\"\\(\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x29 in string", "\"\\)\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x2a in string", "\"\\*\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x2b in string", "\"\\+\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x2c in string", "\"\\,\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x2d in string", "\"\\-\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x2e in string", "\"\\.\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x2f in string", "\"\\/\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x30 in string", "\"\\0\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x31 in string", "\"\\1\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x32 in string", "\"\\2\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x33 in string", "\"\\3\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x34 in string", "\"\\4\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x35 in string", "\"\\5\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x36 in string", "\"\\6\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x37 in string", "\"\\7\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x38 in string", "\"\\8\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x39 in string", "\"\\9\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x3a in string", "\"\\:\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x3b in string", "\"\\;\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x3c in string", "\"\\<\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x3d in string", "\"\\=\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x3e in string", "\"\\>\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x3f in string", "\"\\?\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x40 in string", "\"\\@\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x41 in string", "\"\\A\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x42 in string", "\"\\B\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x43 in string", "\"\\C\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x44 in string", "\"\\D\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x45 in string", "\"\\E\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x46 in string", "\"\\F\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x47 in string", "\"\\G\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x48 in string", "\"\\H\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x49 in string", "\"\\I\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x4a in string", "\"\\J\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x4b in string", "\"\\K\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x4c in string", "\"\\L\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x4d in string", "\"\\M\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x4e in string", "\"\\N\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x4f in string", "\"\\O\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x50 in string", "\"\\P\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x51 in string", "\"\\Q\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x52 in string", "\"\\R\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x53 in string", "\"\\S\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x54 in string", "\"\\T\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x55 in string", "\"\\U\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x56 in string", "\"\\V\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x57 in string", "\"\\W\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x58 in string", "\"\\X\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x59 in string", "\"\\Y\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x5a in string", "\"\\Z\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x5b in string", "\"\\[\"", 4, absl::nullopt, nullptr},
+    {"Escaped 0x23 in string", "\"\\#\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x24 in string", "\"\\$\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x25 in string", "\"\\%\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x26 in string", "\"\\&\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x27 in string", "\"\\'\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x28 in string", "\"\\(\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x29 in string", "\"\\)\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x2a in string", "\"\\*\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x2b in string", "\"\\+\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x2c in string", "\"\\,\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x2d in string", "\"\\-\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x2e in string", "\"\\.\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x2f in string", "\"\\/\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x30 in string", "\"\\0\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x31 in string", "\"\\1\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x32 in string", "\"\\2\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x33 in string", "\"\\3\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x34 in string", "\"\\4\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x35 in string", "\"\\5\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x36 in string", "\"\\6\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x37 in string", "\"\\7\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x38 in string", "\"\\8\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x39 in string", "\"\\9\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x3a in string", "\"\\:\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x3b in string", "\"\\;\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x3c in string", "\"\\<\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x3d in string", "\"\\=\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x3e in string", "\"\\>\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x3f in string", "\"\\?\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x40 in string", "\"\\@\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x41 in string", "\"\\A\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x42 in string", "\"\\B\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x43 in string", "\"\\C\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x44 in string", "\"\\D\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x45 in string", "\"\\E\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x46 in string", "\"\\F\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x47 in string", "\"\\G\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x48 in string", "\"\\H\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x49 in string", "\"\\I\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x4a in string", "\"\\J\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x4b in string", "\"\\K\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x4c in string", "\"\\L\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x4d in string", "\"\\M\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x4e in string", "\"\\N\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x4f in string", "\"\\O\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x50 in string", "\"\\P\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x51 in string", "\"\\Q\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x52 in string", "\"\\R\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x53 in string", "\"\\S\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x54 in string", "\"\\T\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x55 in string", "\"\\U\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x56 in string", "\"\\V\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x57 in string", "\"\\W\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x58 in string", "\"\\X\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x59 in string", "\"\\Y\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x5a in string", "\"\\Z\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x5b in string", "\"\\[\"", 4, std::nullopt, nullptr},
     {"Escaped 0x5c in string", "\"\\\\\"", 4, {{Item("\\"), {}}}, nullptr},
-    {"Escaped 0x5d in string", "\"\\]\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x5e in string", "\"\\^\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x5f in string", "\"\\_\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x60 in string", "\"\\`\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x61 in string", "\"\\a\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x62 in string", "\"\\b\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x63 in string", "\"\\c\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x64 in string", "\"\\d\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x65 in string", "\"\\e\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x66 in string", "\"\\f\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x67 in string", "\"\\g\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x68 in string", "\"\\h\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x69 in string", "\"\\i\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x6a in string", "\"\\j\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x6b in string", "\"\\k\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x6c in string", "\"\\l\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x6d in string", "\"\\m\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x6e in string", "\"\\n\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x6f in string", "\"\\o\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x70 in string", "\"\\p\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x71 in string", "\"\\q\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x72 in string", "\"\\r\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x73 in string", "\"\\s\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x74 in string", "\"\\t\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x75 in string", "\"\\u\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x76 in string", "\"\\v\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x77 in string", "\"\\w\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x78 in string", "\"\\x\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x79 in string", "\"\\y\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x7a in string", "\"\\z\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x7b in string", "\"\\{\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x7c in string", "\"\\|\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x7d in string", "\"\\}\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x7e in string", "\"\\~\"", 4, absl::nullopt, nullptr},
-    {"Escaped 0x7f in string", "\"\\\177\"", 4, absl::nullopt, nullptr},
+    {"Escaped 0x5d in string", "\"\\]\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x5e in string", "\"\\^\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x5f in string", "\"\\_\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x60 in string", "\"\\`\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x61 in string", "\"\\a\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x62 in string", "\"\\b\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x63 in string", "\"\\c\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x64 in string", "\"\\d\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x65 in string", "\"\\e\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x66 in string", "\"\\f\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x67 in string", "\"\\g\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x68 in string", "\"\\h\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x69 in string", "\"\\i\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x6a in string", "\"\\j\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x6b in string", "\"\\k\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x6c in string", "\"\\l\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x6d in string", "\"\\m\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x6e in string", "\"\\n\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x6f in string", "\"\\o\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x70 in string", "\"\\p\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x71 in string", "\"\\q\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x72 in string", "\"\\r\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x73 in string", "\"\\s\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x74 in string", "\"\\t\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x75 in string", "\"\\u\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x76 in string", "\"\\v\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x77 in string", "\"\\w\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x78 in string", "\"\\x\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x79 in string", "\"\\y\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x7a in string", "\"\\z\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x7b in string", "\"\\{\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x7c in string", "\"\\|\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x7d in string", "\"\\}\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x7e in string", "\"\\~\"", 4, std::nullopt, nullptr},
+    {"Escaped 0x7f in string", "\"\\\177\"", 4, std::nullopt, nullptr},
     // string.json
     {"basic string", "\"foo bar\"", 9, {{Item("foo bar"), {}}}, nullptr},
     {"empty string", "\"\"", 2, {{Item(""), {}}}, nullptr},
@@ -1301,65 +1300,65 @@
        {}}},
      nullptr},
     {"whitespace string", "\"   \"", 5, {{Item("   "), {}}}, nullptr},
-    {"non-ascii string", "\"f\374\374\"", 5, absl::nullopt, nullptr},
-    {"tab in string", "\"\\t\"", 4, absl::nullopt, nullptr},
-    {"newline in string", "\" \\n \"", 6, absl::nullopt, nullptr},
-    {"single quoted string", "'foo'", 5, absl::nullopt, nullptr},
-    {"unbalanced string", "\"foo", 4, absl::nullopt, nullptr},
+    {"non-ascii string", "\"f\374\374\"", 5, std::nullopt, nullptr},
+    {"tab in string", "\"\\t\"", 4, std::nullopt, nullptr},
+    {"newline in string", "\" \\n \"", 6, std::nullopt, nullptr},
+    {"single quoted string", "'foo'", 5, std::nullopt, nullptr},
+    {"unbalanced string", "\"foo", 4, std::nullopt, nullptr},
     {"string quoting",
      "\"foo \\\"bar\\\" \\\\ baz\"",
      20,
      {{Item("foo \"bar\" \\ baz"), {}}},
      nullptr},
-    {"bad string quoting", "\"foo \\,\"", 8, absl::nullopt, nullptr},
-    {"ending string quote", "\"foo \\\"", 7, absl::nullopt, nullptr},
-    {"abruptly ending string quote", "\"foo \\", 6, absl::nullopt, nullptr},
+    {"bad string quoting", "\"foo \\,\"", 8, std::nullopt, nullptr},
+    {"ending string quote", "\"foo \\\"", 7, std::nullopt, nullptr},
+    {"abruptly ending string quote", "\"foo \\", 6, std::nullopt, nullptr},
     // token-generated.json
-    {"0x00 in token", "a\000a", 3, absl::nullopt, nullptr},
-    {"0x01 in token", "a\001a", 3, absl::nullopt, nullptr},
-    {"0x02 in token", "a\002a", 3, absl::nullopt, nullptr},
-    {"0x03 in token", "a\003a", 3, absl::nullopt, nullptr},
-    {"0x04 in token", "a\004a", 3, absl::nullopt, nullptr},
-    {"0x05 in token", "a\005a", 3, absl::nullopt, nullptr},
-    {"0x06 in token", "a\006a", 3, absl::nullopt, nullptr},
-    {"0x07 in token", "a\aa", 3, absl::nullopt, nullptr},
-    {"0x08 in token", "a\ba", 3, absl::nullopt, nullptr},
-    {"0x09 in token", "a\ta", 3, absl::nullopt, nullptr},
-    {"0x0a in token", "a\na", 3, absl::nullopt, nullptr},
-    {"0x0b in token", "a\va", 3, absl::nullopt, nullptr},
-    {"0x0c in token", "a\fa", 3, absl::nullopt, nullptr},
-    {"0x0d in token", "a\ra", 3, absl::nullopt, nullptr},
-    {"0x0e in token", "a\016a", 3, absl::nullopt, nullptr},
-    {"0x0f in token", "a\017a", 3, absl::nullopt, nullptr},
-    {"0x10 in token", "a\020a", 3, absl::nullopt, nullptr},
-    {"0x11 in token", "a\021a", 3, absl::nullopt, nullptr},
-    {"0x12 in token", "a\022a", 3, absl::nullopt, nullptr},
-    {"0x13 in token", "a\023a", 3, absl::nullopt, nullptr},
-    {"0x14 in token", "a\024a", 3, absl::nullopt, nullptr},
-    {"0x15 in token", "a\025a", 3, absl::nullopt, nullptr},
-    {"0x16 in token", "a\026a", 3, absl::nullopt, nullptr},
-    {"0x17 in token", "a\027a", 3, absl::nullopt, nullptr},
-    {"0x18 in token", "a\030a", 3, absl::nullopt, nullptr},
-    {"0x19 in token", "a\031a", 3, absl::nullopt, nullptr},
-    {"0x1a in token", "a\032a", 3, absl::nullopt, nullptr},
-    {"0x1b in token", "a\033a", 3, absl::nullopt, nullptr},
-    {"0x1c in token", "a\034a", 3, absl::nullopt, nullptr},
-    {"0x1d in token", "a\035a", 3, absl::nullopt, nullptr},
-    {"0x1e in token", "a\036a", 3, absl::nullopt, nullptr},
-    {"0x1f in token", "a\037a", 3, absl::nullopt, nullptr},
-    {"0x20 in token", "a a", 3, absl::nullopt, nullptr},
+    {"0x00 in token", "a\000a", 3, std::nullopt, nullptr},
+    {"0x01 in token", "a\001a", 3, std::nullopt, nullptr},
+    {"0x02 in token", "a\002a", 3, std::nullopt, nullptr},
+    {"0x03 in token", "a\003a", 3, std::nullopt, nullptr},
+    {"0x04 in token", "a\004a", 3, std::nullopt, nullptr},
+    {"0x05 in token", "a\005a", 3, std::nullopt, nullptr},
+    {"0x06 in token", "a\006a", 3, std::nullopt, nullptr},
+    {"0x07 in token", "a\aa", 3, std::nullopt, nullptr},
+    {"0x08 in token", "a\ba", 3, std::nullopt, nullptr},
+    {"0x09 in token", "a\ta", 3, std::nullopt, nullptr},
+    {"0x0a in token", "a\na", 3, std::nullopt, nullptr},
+    {"0x0b in token", "a\va", 3, std::nullopt, nullptr},
+    {"0x0c in token", "a\fa", 3, std::nullopt, nullptr},
+    {"0x0d in token", "a\ra", 3, std::nullopt, nullptr},
+    {"0x0e in token", "a\016a", 3, std::nullopt, nullptr},
+    {"0x0f in token", "a\017a", 3, std::nullopt, nullptr},
+    {"0x10 in token", "a\020a", 3, std::nullopt, nullptr},
+    {"0x11 in token", "a\021a", 3, std::nullopt, nullptr},
+    {"0x12 in token", "a\022a", 3, std::nullopt, nullptr},
+    {"0x13 in token", "a\023a", 3, std::nullopt, nullptr},
+    {"0x14 in token", "a\024a", 3, std::nullopt, nullptr},
+    {"0x15 in token", "a\025a", 3, std::nullopt, nullptr},
+    {"0x16 in token", "a\026a", 3, std::nullopt, nullptr},
+    {"0x17 in token", "a\027a", 3, std::nullopt, nullptr},
+    {"0x18 in token", "a\030a", 3, std::nullopt, nullptr},
+    {"0x19 in token", "a\031a", 3, std::nullopt, nullptr},
+    {"0x1a in token", "a\032a", 3, std::nullopt, nullptr},
+    {"0x1b in token", "a\033a", 3, std::nullopt, nullptr},
+    {"0x1c in token", "a\034a", 3, std::nullopt, nullptr},
+    {"0x1d in token", "a\035a", 3, std::nullopt, nullptr},
+    {"0x1e in token", "a\036a", 3, std::nullopt, nullptr},
+    {"0x1f in token", "a\037a", 3, std::nullopt, nullptr},
+    {"0x20 in token", "a a", 3, std::nullopt, nullptr},
     {"0x21 in token", "a!a", 3, {{Item("a!a", Item::kTokenType), {}}}, nullptr},
-    {"0x22 in token", "a\"a", 3, absl::nullopt, nullptr},
+    {"0x22 in token", "a\"a", 3, std::nullopt, nullptr},
     {"0x23 in token", "a#a", 3, {{Item("a#a", Item::kTokenType), {}}}, nullptr},
     {"0x24 in token", "a$a", 3, {{Item("a$a", Item::kTokenType), {}}}, nullptr},
     {"0x25 in token", "a%a", 3, {{Item("a%a", Item::kTokenType), {}}}, nullptr},
     {"0x26 in token", "a&a", 3, {{Item("a&a", Item::kTokenType), {}}}, nullptr},
     {"0x27 in token", "a'a", 3, {{Item("a'a", Item::kTokenType), {}}}, nullptr},
-    {"0x28 in token", "a(a", 3, absl::nullopt, nullptr},
-    {"0x29 in token", "a)a", 3, absl::nullopt, nullptr},
+    {"0x28 in token", "a(a", 3, std::nullopt, nullptr},
+    {"0x29 in token", "a)a", 3, std::nullopt, nullptr},
     {"0x2a in token", "a*a", 3, {{Item("a*a", Item::kTokenType), {}}}, nullptr},
     {"0x2b in token", "a+a", 3, {{Item("a+a", Item::kTokenType), {}}}, nullptr},
-    {"0x2c in token", "a,a", 3, absl::nullopt, nullptr},
+    {"0x2c in token", "a,a", 3, std::nullopt, nullptr},
     {"0x2d in token", "a-a", 3, {{Item("a-a", Item::kTokenType), {}}}, nullptr},
     {"0x2e in token", "a.a", 3, {{Item("a.a", Item::kTokenType), {}}}, nullptr},
     {"0x2f in token", "a/a", 3, {{Item("a/a", Item::kTokenType), {}}}, nullptr},
@@ -1379,11 +1378,11 @@
      3,
      {{Item("a", Item::kTokenType), {BooleanParam("a", true)}}},
      nullptr},
-    {"0x3c in token", "a<a", 3, absl::nullopt, nullptr},
-    {"0x3d in token", "a=a", 3, absl::nullopt, nullptr},
-    {"0x3e in token", "a>a", 3, absl::nullopt, nullptr},
-    {"0x3f in token", "a?a", 3, absl::nullopt, nullptr},
-    {"0x40 in token", "a@a", 3, absl::nullopt, nullptr},
+    {"0x3c in token", "a<a", 3, std::nullopt, nullptr},
+    {"0x3d in token", "a=a", 3, std::nullopt, nullptr},
+    {"0x3e in token", "a>a", 3, std::nullopt, nullptr},
+    {"0x3f in token", "a?a", 3, std::nullopt, nullptr},
+    {"0x40 in token", "a@a", 3, std::nullopt, nullptr},
     {"0x41 in token", "aAa", 3, {{Item("aAa", Item::kTokenType), {}}}, nullptr},
     {"0x42 in token", "aBa", 3, {{Item("aBa", Item::kTokenType), {}}}, nullptr},
     {"0x43 in token", "aCa", 3, {{Item("aCa", Item::kTokenType), {}}}, nullptr},
@@ -1410,9 +1409,9 @@
     {"0x58 in token", "aXa", 3, {{Item("aXa", Item::kTokenType), {}}}, nullptr},
     {"0x59 in token", "aYa", 3, {{Item("aYa", Item::kTokenType), {}}}, nullptr},
     {"0x5a in token", "aZa", 3, {{Item("aZa", Item::kTokenType), {}}}, nullptr},
-    {"0x5b in token", "a[a", 3, absl::nullopt, nullptr},
-    {"0x5c in token", "a\\a", 3, absl::nullopt, nullptr},
-    {"0x5d in token", "a]a", 3, absl::nullopt, nullptr},
+    {"0x5b in token", "a[a", 3, std::nullopt, nullptr},
+    {"0x5c in token", "a\\a", 3, std::nullopt, nullptr},
+    {"0x5d in token", "a]a", 3, std::nullopt, nullptr},
     {"0x5e in token", "a^a", 3, {{Item("a^a", Item::kTokenType), {}}}, nullptr},
     {"0x5f in token", "a_a", 3, {{Item("a_a", Item::kTokenType), {}}}, nullptr},
     {"0x60 in token", "a`a", 3, {{Item("a`a", Item::kTokenType), {}}}, nullptr},
@@ -1442,84 +1441,84 @@
     {"0x78 in token", "axa", 3, {{Item("axa", Item::kTokenType), {}}}, nullptr},
     {"0x79 in token", "aya", 3, {{Item("aya", Item::kTokenType), {}}}, nullptr},
     {"0x7a in token", "aza", 3, {{Item("aza", Item::kTokenType), {}}}, nullptr},
-    {"0x7b in token", "a{a", 3, absl::nullopt, nullptr},
+    {"0x7b in token", "a{a", 3, std::nullopt, nullptr},
     {"0x7c in token", "a|a", 3, {{Item("a|a", Item::kTokenType), {}}}, nullptr},
-    {"0x7d in token", "a}a", 3, absl::nullopt, nullptr},
+    {"0x7d in token", "a}a", 3, std::nullopt, nullptr},
     {"0x7e in token", "a~a", 3, {{Item("a~a", Item::kTokenType), {}}}, nullptr},
-    {"0x7f in token", "a\177a", 3, absl::nullopt, nullptr},
-    {"0x00 starting an token", "\000a", 2, absl::nullopt, nullptr},
-    {"0x01 starting an token", "\001a", 2, absl::nullopt, nullptr},
-    {"0x02 starting an token", "\002a", 2, absl::nullopt, nullptr},
-    {"0x03 starting an token", "\003a", 2, absl::nullopt, nullptr},
-    {"0x04 starting an token", "\004a", 2, absl::nullopt, nullptr},
-    {"0x05 starting an token", "\005a", 2, absl::nullopt, nullptr},
-    {"0x06 starting an token", "\006a", 2, absl::nullopt, nullptr},
-    {"0x07 starting an token", "\aa", 2, absl::nullopt, nullptr},
-    {"0x08 starting an token", "\ba", 2, absl::nullopt, nullptr},
-    {"0x09 starting an token", "\ta", 2, absl::nullopt, nullptr},
-    {"0x0a starting an token", "\na", 2, absl::nullopt, nullptr},
-    {"0x0b starting an token", "\va", 2, absl::nullopt, nullptr},
-    {"0x0c starting an token", "\fa", 2, absl::nullopt, nullptr},
-    {"0x0d starting an token", "\ra", 2, absl::nullopt, nullptr},
-    {"0x0e starting an token", "\016a", 2, absl::nullopt, nullptr},
-    {"0x0f starting an token", "\017a", 2, absl::nullopt, nullptr},
-    {"0x10 starting an token", "\020a", 2, absl::nullopt, nullptr},
-    {"0x11 starting an token", "\021a", 2, absl::nullopt, nullptr},
-    {"0x12 starting an token", "\022a", 2, absl::nullopt, nullptr},
-    {"0x13 starting an token", "\023a", 2, absl::nullopt, nullptr},
-    {"0x14 starting an token", "\024a", 2, absl::nullopt, nullptr},
-    {"0x15 starting an token", "\025a", 2, absl::nullopt, nullptr},
-    {"0x16 starting an token", "\026a", 2, absl::nullopt, nullptr},
-    {"0x17 starting an token", "\027a", 2, absl::nullopt, nullptr},
-    {"0x18 starting an token", "\030a", 2, absl::nullopt, nullptr},
-    {"0x19 starting an token", "\031a", 2, absl::nullopt, nullptr},
-    {"0x1a starting an token", "\032a", 2, absl::nullopt, nullptr},
-    {"0x1b starting an token", "\033a", 2, absl::nullopt, nullptr},
-    {"0x1c starting an token", "\034a", 2, absl::nullopt, nullptr},
-    {"0x1d starting an token", "\035a", 2, absl::nullopt, nullptr},
-    {"0x1e starting an token", "\036a", 2, absl::nullopt, nullptr},
-    {"0x1f starting an token", "\037a", 2, absl::nullopt, nullptr},
+    {"0x7f in token", "a\177a", 3, std::nullopt, nullptr},
+    {"0x00 starting an token", "\000a", 2, std::nullopt, nullptr},
+    {"0x01 starting an token", "\001a", 2, std::nullopt, nullptr},
+    {"0x02 starting an token", "\002a", 2, std::nullopt, nullptr},
+    {"0x03 starting an token", "\003a", 2, std::nullopt, nullptr},
+    {"0x04 starting an token", "\004a", 2, std::nullopt, nullptr},
+    {"0x05 starting an token", "\005a", 2, std::nullopt, nullptr},
+    {"0x06 starting an token", "\006a", 2, std::nullopt, nullptr},
+    {"0x07 starting an token", "\aa", 2, std::nullopt, nullptr},
+    {"0x08 starting an token", "\ba", 2, std::nullopt, nullptr},
+    {"0x09 starting an token", "\ta", 2, std::nullopt, nullptr},
+    {"0x0a starting an token", "\na", 2, std::nullopt, nullptr},
+    {"0x0b starting an token", "\va", 2, std::nullopt, nullptr},
+    {"0x0c starting an token", "\fa", 2, std::nullopt, nullptr},
+    {"0x0d starting an token", "\ra", 2, std::nullopt, nullptr},
+    {"0x0e starting an token", "\016a", 2, std::nullopt, nullptr},
+    {"0x0f starting an token", "\017a", 2, std::nullopt, nullptr},
+    {"0x10 starting an token", "\020a", 2, std::nullopt, nullptr},
+    {"0x11 starting an token", "\021a", 2, std::nullopt, nullptr},
+    {"0x12 starting an token", "\022a", 2, std::nullopt, nullptr},
+    {"0x13 starting an token", "\023a", 2, std::nullopt, nullptr},
+    {"0x14 starting an token", "\024a", 2, std::nullopt, nullptr},
+    {"0x15 starting an token", "\025a", 2, std::nullopt, nullptr},
+    {"0x16 starting an token", "\026a", 2, std::nullopt, nullptr},
+    {"0x17 starting an token", "\027a", 2, std::nullopt, nullptr},
+    {"0x18 starting an token", "\030a", 2, std::nullopt, nullptr},
+    {"0x19 starting an token", "\031a", 2, std::nullopt, nullptr},
+    {"0x1a starting an token", "\032a", 2, std::nullopt, nullptr},
+    {"0x1b starting an token", "\033a", 2, std::nullopt, nullptr},
+    {"0x1c starting an token", "\034a", 2, std::nullopt, nullptr},
+    {"0x1d starting an token", "\035a", 2, std::nullopt, nullptr},
+    {"0x1e starting an token", "\036a", 2, std::nullopt, nullptr},
+    {"0x1f starting an token", "\037a", 2, std::nullopt, nullptr},
     {"0x20 starting an token",
      " a",
      2,
      {{Item("a", Item::kTokenType), {}}},
      "a"},
-    {"0x21 starting an token", "!a", 2, absl::nullopt, nullptr},
-    {"0x22 starting an token", "\"a", 2, absl::nullopt, nullptr},
-    {"0x23 starting an token", "#a", 2, absl::nullopt, nullptr},
-    {"0x24 starting an token", "$a", 2, absl::nullopt, nullptr},
-    {"0x25 starting an token", "%a", 2, absl::nullopt, nullptr},
-    {"0x26 starting an token", "&a", 2, absl::nullopt, nullptr},
-    {"0x27 starting an token", "'a", 2, absl::nullopt, nullptr},
-    {"0x28 starting an token", "(a", 2, absl::nullopt, nullptr},
-    {"0x29 starting an token", ")a", 2, absl::nullopt, nullptr},
+    {"0x21 starting an token", "!a", 2, std::nullopt, nullptr},
+    {"0x22 starting an token", "\"a", 2, std::nullopt, nullptr},
+    {"0x23 starting an token", "#a", 2, std::nullopt, nullptr},
+    {"0x24 starting an token", "$a", 2, std::nullopt, nullptr},
+    {"0x25 starting an token", "%a", 2, std::nullopt, nullptr},
+    {"0x26 starting an token", "&a", 2, std::nullopt, nullptr},
+    {"0x27 starting an token", "'a", 2, std::nullopt, nullptr},
+    {"0x28 starting an token", "(a", 2, std::nullopt, nullptr},
+    {"0x29 starting an token", ")a", 2, std::nullopt, nullptr},
     {"0x2a starting an token",
      "*a",
      2,
      {{Item("*a", Item::kTokenType), {}}},
      nullptr},
-    {"0x2b starting an token", "+a", 2, absl::nullopt, nullptr},
-    {"0x2c starting an token", ",a", 2, absl::nullopt, nullptr},
-    {"0x2d starting an token", "-a", 2, absl::nullopt, nullptr},
-    {"0x2e starting an token", ".a", 2, absl::nullopt, nullptr},
-    {"0x2f starting an token", "/a", 2, absl::nullopt, nullptr},
-    {"0x30 starting an token", "0a", 2, absl::nullopt, nullptr},
-    {"0x31 starting an token", "1a", 2, absl::nullopt, nullptr},
-    {"0x32 starting an token", "2a", 2, absl::nullopt, nullptr},
-    {"0x33 starting an token", "3a", 2, absl::nullopt, nullptr},
-    {"0x34 starting an token", "4a", 2, absl::nullopt, nullptr},
-    {"0x35 starting an token", "5a", 2, absl::nullopt, nullptr},
-    {"0x36 starting an token", "6a", 2, absl::nullopt, nullptr},
-    {"0x37 starting an token", "7a", 2, absl::nullopt, nullptr},
-    {"0x38 starting an token", "8a", 2, absl::nullopt, nullptr},
-    {"0x39 starting an token", "9a", 2, absl::nullopt, nullptr},
-    {"0x3a starting an token", ":a", 2, absl::nullopt, nullptr},
-    {"0x3b starting an token", ";a", 2, absl::nullopt, nullptr},
-    {"0x3c starting an token", "<a", 2, absl::nullopt, nullptr},
-    {"0x3d starting an token", "=a", 2, absl::nullopt, nullptr},
-    {"0x3e starting an token", ">a", 2, absl::nullopt, nullptr},
-    {"0x3f starting an token", "?a", 2, absl::nullopt, nullptr},
-    {"0x40 starting an token", "@a", 2, absl::nullopt, nullptr},
+    {"0x2b starting an token", "+a", 2, std::nullopt, nullptr},
+    {"0x2c starting an token", ",a", 2, std::nullopt, nullptr},
+    {"0x2d starting an token", "-a", 2, std::nullopt, nullptr},
+    {"0x2e starting an token", ".a", 2, std::nullopt, nullptr},
+    {"0x2f starting an token", "/a", 2, std::nullopt, nullptr},
+    {"0x30 starting an token", "0a", 2, std::nullopt, nullptr},
+    {"0x31 starting an token", "1a", 2, std::nullopt, nullptr},
+    {"0x32 starting an token", "2a", 2, std::nullopt, nullptr},
+    {"0x33 starting an token", "3a", 2, std::nullopt, nullptr},
+    {"0x34 starting an token", "4a", 2, std::nullopt, nullptr},
+    {"0x35 starting an token", "5a", 2, std::nullopt, nullptr},
+    {"0x36 starting an token", "6a", 2, std::nullopt, nullptr},
+    {"0x37 starting an token", "7a", 2, std::nullopt, nullptr},
+    {"0x38 starting an token", "8a", 2, std::nullopt, nullptr},
+    {"0x39 starting an token", "9a", 2, std::nullopt, nullptr},
+    {"0x3a starting an token", ":a", 2, std::nullopt, nullptr},
+    {"0x3b starting an token", ";a", 2, std::nullopt, nullptr},
+    {"0x3c starting an token", "<a", 2, std::nullopt, nullptr},
+    {"0x3d starting an token", "=a", 2, std::nullopt, nullptr},
+    {"0x3e starting an token", ">a", 2, std::nullopt, nullptr},
+    {"0x3f starting an token", "?a", 2, std::nullopt, nullptr},
+    {"0x40 starting an token", "@a", 2, std::nullopt, nullptr},
     {"0x41 starting an token",
      "Aa",
      2,
@@ -1650,12 +1649,12 @@
      2,
      {{Item("Za", Item::kTokenType), {}}},
      nullptr},
-    {"0x5b starting an token", "[a", 2, absl::nullopt, nullptr},
-    {"0x5c starting an token", "\\a", 2, absl::nullopt, nullptr},
-    {"0x5d starting an token", "]a", 2, absl::nullopt, nullptr},
-    {"0x5e starting an token", "^a", 2, absl::nullopt, nullptr},
-    {"0x5f starting an token", "_a", 2, absl::nullopt, nullptr},
-    {"0x60 starting an token", "`a", 2, absl::nullopt, nullptr},
+    {"0x5b starting an token", "[a", 2, std::nullopt, nullptr},
+    {"0x5c starting an token", "\\a", 2, std::nullopt, nullptr},
+    {"0x5d starting an token", "]a", 2, std::nullopt, nullptr},
+    {"0x5e starting an token", "^a", 2, std::nullopt, nullptr},
+    {"0x5f starting an token", "_a", 2, std::nullopt, nullptr},
+    {"0x60 starting an token", "`a", 2, std::nullopt, nullptr},
     {"0x61 starting an token",
      "aa",
      2,
@@ -1786,11 +1785,11 @@
      2,
      {{Item("za", Item::kTokenType), {}}},
      nullptr},
-    {"0x7b starting an token", "{a", 2, absl::nullopt, nullptr},
-    {"0x7c starting an token", "|a", 2, absl::nullopt, nullptr},
-    {"0x7d starting an token", "}a", 2, absl::nullopt, nullptr},
-    {"0x7e starting an token", "~a", 2, absl::nullopt, nullptr},
-    {"0x7f starting an token", "\177a", 2, absl::nullopt, nullptr},
+    {"0x7b starting an token", "{a", 2, std::nullopt, nullptr},
+    {"0x7c starting an token", "|a", 2, std::nullopt, nullptr},
+    {"0x7d starting an token", "}a", 2, std::nullopt, nullptr},
+    {"0x7e starting an token", "~a", 2, std::nullopt, nullptr},
+    {"0x7f starting an token", "\177a", 2, std::nullopt, nullptr},
     // token.json
     {"basic token - item",
      "a_b-c.d3:f%00/*",
@@ -1813,7 +1812,7 @@
   const char* name;
   const char* raw;
   size_t raw_len;
-  const absl::optional<List> expected;  // nullopt if parse error is expected.
+  const std::optional<List> expected;  // nullopt if parse error is expected.
   const char* canonical;  // nullptr if parse error is expected, or if canonical
                           // format is identical to raw.
 } list_test_cases[] = {
@@ -1861,99 +1860,88 @@
         {Param("q", "9"), TokenParam("r", "w")}}}},
      "abc;a=1;b=2;cde_456, (ghi;jk=4 l);q=\"9\";r=w"},
     // key-generated.json
-    {"0x00 in parameterised list key", "foo; a\000a=1", 10, absl::nullopt,
+    {"0x00 in parameterised list key", "foo; a\000a=1", 10, std::nullopt,
      nullptr},
-    {"0x01 in parameterised list key", "foo; a\001a=1", 10, absl::nullopt,
+    {"0x01 in parameterised list key", "foo; a\001a=1", 10, std::nullopt,
      nullptr},
-    {"0x02 in parameterised list key", "foo; a\002a=1", 10, absl::nullopt,
+    {"0x02 in parameterised list key", "foo; a\002a=1", 10, std::nullopt,
      nullptr},
-    {"0x03 in parameterised list key", "foo; a\003a=1", 10, absl::nullopt,
+    {"0x03 in parameterised list key", "foo; a\003a=1", 10, std::nullopt,
      nullptr},
-    {"0x04 in parameterised list key", "foo; a\004a=1", 10, absl::nullopt,
+    {"0x04 in parameterised list key", "foo; a\004a=1", 10, std::nullopt,
      nullptr},
-    {"0x05 in parameterised list key", "foo; a\005a=1", 10, absl::nullopt,
+    {"0x05 in parameterised list key", "foo; a\005a=1", 10, std::nullopt,
      nullptr},
-    {"0x06 in parameterised list key", "foo; a\006a=1", 10, absl::nullopt,
+    {"0x06 in parameterised list key", "foo; a\006a=1", 10, std::nullopt,
      nullptr},
-    {"0x07 in parameterised list key", "foo; a\aa=1", 10, absl::nullopt,
+    {"0x07 in parameterised list key", "foo; a\aa=1", 10, std::nullopt,
      nullptr},
-    {"0x08 in parameterised list key", "foo; a\ba=1", 10, absl::nullopt,
+    {"0x08 in parameterised list key", "foo; a\ba=1", 10, std::nullopt,
      nullptr},
-    {"0x09 in parameterised list key", "foo; a\ta=1", 10, absl::nullopt,
+    {"0x09 in parameterised list key", "foo; a\ta=1", 10, std::nullopt,
      nullptr},
-    {"0x0a in parameterised list key", "foo; a\na=1", 10, absl::nullopt,
+    {"0x0a in parameterised list key", "foo; a\na=1", 10, std::nullopt,
      nullptr},
-    {"0x0b in parameterised list key", "foo; a\va=1", 10, absl::nullopt,
+    {"0x0b in parameterised list key", "foo; a\va=1", 10, std::nullopt,
      nullptr},
-    {"0x0c in parameterised list key", "foo; a\fa=1", 10, absl::nullopt,
+    {"0x0c in parameterised list key", "foo; a\fa=1", 10, std::nullopt,
      nullptr},
-    {"0x0d in parameterised list key", "foo; a\ra=1", 10, absl::nullopt,
+    {"0x0d in parameterised list key", "foo; a\ra=1", 10, std::nullopt,
      nullptr},
-    {"0x0e in parameterised list key", "foo; a\016a=1", 10, absl::nullopt,
+    {"0x0e in parameterised list key", "foo; a\016a=1", 10, std::nullopt,
      nullptr},
-    {"0x0f in parameterised list key", "foo; a\017a=1", 10, absl::nullopt,
+    {"0x0f in parameterised list key", "foo; a\017a=1", 10, std::nullopt,
      nullptr},
-    {"0x10 in parameterised list key", "foo; a\020a=1", 10, absl::nullopt,
+    {"0x10 in parameterised list key", "foo; a\020a=1", 10, std::nullopt,
      nullptr},
-    {"0x11 in parameterised list key", "foo; a\021a=1", 10, absl::nullopt,
+    {"0x11 in parameterised list key", "foo; a\021a=1", 10, std::nullopt,
      nullptr},
-    {"0x12 in parameterised list key", "foo; a\022a=1", 10, absl::nullopt,
+    {"0x12 in parameterised list key", "foo; a\022a=1", 10, std::nullopt,
      nullptr},
-    {"0x13 in parameterised list key", "foo; a\023a=1", 10, absl::nullopt,
+    {"0x13 in parameterised list key", "foo; a\023a=1", 10, std::nullopt,
      nullptr},
-    {"0x14 in parameterised list key", "foo; a\024a=1", 10, absl::nullopt,
+    {"0x14 in parameterised list key", "foo; a\024a=1", 10, std::nullopt,
      nullptr},
-    {"0x15 in parameterised list key", "foo; a\025a=1", 10, absl::nullopt,
+    {"0x15 in parameterised list key", "foo; a\025a=1", 10, std::nullopt,
      nullptr},
-    {"0x16 in parameterised list key", "foo; a\026a=1", 10, absl::nullopt,
+    {"0x16 in parameterised list key", "foo; a\026a=1", 10, std::nullopt,
      nullptr},
-    {"0x17 in parameterised list key", "foo; a\027a=1", 10, absl::nullopt,
+    {"0x17 in parameterised list key", "foo; a\027a=1", 10, std::nullopt,
      nullptr},
-    {"0x18 in parameterised list key", "foo; a\030a=1", 10, absl::nullopt,
+    {"0x18 in parameterised list key", "foo; a\030a=1", 10, std::nullopt,
      nullptr},
-    {"0x19 in parameterised list key", "foo; a\031a=1", 10, absl::nullopt,
+    {"0x19 in parameterised list key", "foo; a\031a=1", 10, std::nullopt,
      nullptr},
-    {"0x1a in parameterised list key", "foo; a\032a=1", 10, absl::nullopt,
+    {"0x1a in parameterised list key", "foo; a\032a=1", 10, std::nullopt,
      nullptr},
-    {"0x1b in parameterised list key", "foo; a\033a=1", 10, absl::nullopt,
+    {"0x1b in parameterised list key", "foo; a\033a=1", 10, std::nullopt,
      nullptr},
-    {"0x1c in parameterised list key", "foo; a\034a=1", 10, absl::nullopt,
+    {"0x1c in parameterised list key", "foo; a\034a=1", 10, std::nullopt,
      nullptr},
-    {"0x1d in parameterised list key", "foo; a\035a=1", 10, absl::nullopt,
+    {"0x1d in parameterised list key", "foo; a\035a=1", 10, std::nullopt,
      nullptr},
-    {"0x1e in parameterised list key", "foo; a\036a=1", 10, absl::nullopt,
+    {"0x1e in parameterised list key", "foo; a\036a=1", 10, std::nullopt,
      nullptr},
-    {"0x1f in parameterised list key", "foo; a\037a=1", 10, absl::nullopt,
+    {"0x1f in parameterised list key", "foo; a\037a=1", 10, std::nullopt,
      nullptr},
-    {"0x20 in parameterised list key", "foo; a a=1", 10, absl::nullopt,
+    {"0x20 in parameterised list key", "foo; a a=1", 10, std::nullopt, nullptr},
+    {"0x21 in parameterised list key", "foo; a!a=1", 10, std::nullopt, nullptr},
+    {"0x22 in parameterised list key", "foo; a\"a=1", 10, std::nullopt,
      nullptr},
-    {"0x21 in parameterised list key", "foo; a!a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x22 in parameterised list key", "foo; a\"a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x23 in parameterised list key", "foo; a#a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x24 in parameterised list key", "foo; a$a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x25 in parameterised list key", "foo; a%a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x26 in parameterised list key", "foo; a&a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x27 in parameterised list key", "foo; a'a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x28 in parameterised list key", "foo; a(a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x29 in parameterised list key", "foo; a)a=1", 10, absl::nullopt,
-     nullptr},
+    {"0x23 in parameterised list key", "foo; a#a=1", 10, std::nullopt, nullptr},
+    {"0x24 in parameterised list key", "foo; a$a=1", 10, std::nullopt, nullptr},
+    {"0x25 in parameterised list key", "foo; a%a=1", 10, std::nullopt, nullptr},
+    {"0x26 in parameterised list key", "foo; a&a=1", 10, std::nullopt, nullptr},
+    {"0x27 in parameterised list key", "foo; a'a=1", 10, std::nullopt, nullptr},
+    {"0x28 in parameterised list key", "foo; a(a=1", 10, std::nullopt, nullptr},
+    {"0x29 in parameterised list key", "foo; a)a=1", 10, std::nullopt, nullptr},
     {"0x2a in parameterised list key",
      "foo; a*a=1",
      10,
      {{{Item("foo", Item::kTokenType), {Param("a*a", 1)}}}},
      "foo;a*a=1"},
-    {"0x2b in parameterised list key", "foo; a+a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x2c in parameterised list key", "foo; a,a=1", 10, absl::nullopt,
-     nullptr},
+    {"0x2b in parameterised list key", "foo; a+a=1", 10, std::nullopt, nullptr},
+    {"0x2c in parameterised list key", "foo; a,a=1", 10, std::nullopt, nullptr},
     {"0x2d in parameterised list key",
      "foo; a-a=1",
      10,
@@ -1964,8 +1952,7 @@
      10,
      {{{Item("foo", Item::kTokenType), {Param("a.a", 1)}}}},
      "foo;a.a=1"},
-    {"0x2f in parameterised list key", "foo; a/a=1", 10, absl::nullopt,
-     nullptr},
+    {"0x2f in parameterised list key", "foo; a/a=1", 10, std::nullopt, nullptr},
     {"0x30 in parameterised list key",
      "foo; a0a=1",
      10,
@@ -2016,90 +2003,54 @@
      10,
      {{{Item("foo", Item::kTokenType), {Param("a9a", 1)}}}},
      "foo;a9a=1"},
-    {"0x3a in parameterised list key", "foo; a:a=1", 10, absl::nullopt,
-     nullptr},
+    {"0x3a in parameterised list key", "foo; a:a=1", 10, std::nullopt, nullptr},
     {"0x3b in parameterised list key",
      "foo; a;a=1",
      10,
      {{{Item("foo", Item::kTokenType), {Param("a", 1)}}}},
      "foo;a=1"},
-    {"0x3c in parameterised list key", "foo; a<a=1", 10, absl::nullopt,
+    {"0x3c in parameterised list key", "foo; a<a=1", 10, std::nullopt, nullptr},
+    {"0x3d in parameterised list key", "foo; a=a=1", 10, std::nullopt, nullptr},
+    {"0x3e in parameterised list key", "foo; a>a=1", 10, std::nullopt, nullptr},
+    {"0x3f in parameterised list key", "foo; a?a=1", 10, std::nullopt, nullptr},
+    {"0x40 in parameterised list key", "foo; a@a=1", 10, std::nullopt, nullptr},
+    {"0x41 in parameterised list key", "foo; aAa=1", 10, std::nullopt, nullptr},
+    {"0x42 in parameterised list key", "foo; aBa=1", 10, std::nullopt, nullptr},
+    {"0x43 in parameterised list key", "foo; aCa=1", 10, std::nullopt, nullptr},
+    {"0x44 in parameterised list key", "foo; aDa=1", 10, std::nullopt, nullptr},
+    {"0x45 in parameterised list key", "foo; aEa=1", 10, std::nullopt, nullptr},
+    {"0x46 in parameterised list key", "foo; aFa=1", 10, std::nullopt, nullptr},
+    {"0x47 in parameterised list key", "foo; aGa=1", 10, std::nullopt, nullptr},
+    {"0x48 in parameterised list key", "foo; aHa=1", 10, std::nullopt, nullptr},
+    {"0x49 in parameterised list key", "foo; aIa=1", 10, std::nullopt, nullptr},
+    {"0x4a in parameterised list key", "foo; aJa=1", 10, std::nullopt, nullptr},
+    {"0x4b in parameterised list key", "foo; aKa=1", 10, std::nullopt, nullptr},
+    {"0x4c in parameterised list key", "foo; aLa=1", 10, std::nullopt, nullptr},
+    {"0x4d in parameterised list key", "foo; aMa=1", 10, std::nullopt, nullptr},
+    {"0x4e in parameterised list key", "foo; aNa=1", 10, std::nullopt, nullptr},
+    {"0x4f in parameterised list key", "foo; aOa=1", 10, std::nullopt, nullptr},
+    {"0x50 in parameterised list key", "foo; aPa=1", 10, std::nullopt, nullptr},
+    {"0x51 in parameterised list key", "foo; aQa=1", 10, std::nullopt, nullptr},
+    {"0x52 in parameterised list key", "foo; aRa=1", 10, std::nullopt, nullptr},
+    {"0x53 in parameterised list key", "foo; aSa=1", 10, std::nullopt, nullptr},
+    {"0x54 in parameterised list key", "foo; aTa=1", 10, std::nullopt, nullptr},
+    {"0x55 in parameterised list key", "foo; aUa=1", 10, std::nullopt, nullptr},
+    {"0x56 in parameterised list key", "foo; aVa=1", 10, std::nullopt, nullptr},
+    {"0x57 in parameterised list key", "foo; aWa=1", 10, std::nullopt, nullptr},
+    {"0x58 in parameterised list key", "foo; aXa=1", 10, std::nullopt, nullptr},
+    {"0x59 in parameterised list key", "foo; aYa=1", 10, std::nullopt, nullptr},
+    {"0x5a in parameterised list key", "foo; aZa=1", 10, std::nullopt, nullptr},
+    {"0x5b in parameterised list key", "foo; a[a=1", 10, std::nullopt, nullptr},
+    {"0x5c in parameterised list key", "foo; a\\a=1", 10, std::nullopt,
      nullptr},
-    {"0x3d in parameterised list key", "foo; a=a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x3e in parameterised list key", "foo; a>a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x3f in parameterised list key", "foo; a?a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x40 in parameterised list key", "foo; a@a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x41 in parameterised list key", "foo; aAa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x42 in parameterised list key", "foo; aBa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x43 in parameterised list key", "foo; aCa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x44 in parameterised list key", "foo; aDa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x45 in parameterised list key", "foo; aEa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x46 in parameterised list key", "foo; aFa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x47 in parameterised list key", "foo; aGa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x48 in parameterised list key", "foo; aHa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x49 in parameterised list key", "foo; aIa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x4a in parameterised list key", "foo; aJa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x4b in parameterised list key", "foo; aKa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x4c in parameterised list key", "foo; aLa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x4d in parameterised list key", "foo; aMa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x4e in parameterised list key", "foo; aNa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x4f in parameterised list key", "foo; aOa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x50 in parameterised list key", "foo; aPa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x51 in parameterised list key", "foo; aQa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x52 in parameterised list key", "foo; aRa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x53 in parameterised list key", "foo; aSa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x54 in parameterised list key", "foo; aTa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x55 in parameterised list key", "foo; aUa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x56 in parameterised list key", "foo; aVa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x57 in parameterised list key", "foo; aWa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x58 in parameterised list key", "foo; aXa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x59 in parameterised list key", "foo; aYa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x5a in parameterised list key", "foo; aZa=1", 10, absl::nullopt,
-     nullptr},
-    {"0x5b in parameterised list key", "foo; a[a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x5c in parameterised list key", "foo; a\\a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x5d in parameterised list key", "foo; a]a=1", 10, absl::nullopt,
-     nullptr},
-    {"0x5e in parameterised list key", "foo; a^a=1", 10, absl::nullopt,
-     nullptr},
+    {"0x5d in parameterised list key", "foo; a]a=1", 10, std::nullopt, nullptr},
+    {"0x5e in parameterised list key", "foo; a^a=1", 10, std::nullopt, nullptr},
     {"0x5f in parameterised list key",
      "foo; a_a=1",
      10,
      {{{Item("foo", Item::kTokenType), {Param("a_a", 1)}}}},
      "foo;a_a=1"},
-    {"0x60 in parameterised list key", "foo; a`a=1", 10, absl::nullopt,
-     nullptr},
+    {"0x60 in parameterised list key", "foo; a`a=1", 10, std::nullopt, nullptr},
     {"0x61 in parameterised list key",
      "foo; aaa=1",
      10,
@@ -2230,215 +2181,211 @@
      10,
      {{{Item("foo", Item::kTokenType), {Param("aza", 1)}}}},
      "foo;aza=1"},
-    {"0x7b in parameterised list key", "foo; a{a=1", 10, absl::nullopt,
+    {"0x7b in parameterised list key", "foo; a{a=1", 10, std::nullopt, nullptr},
+    {"0x7c in parameterised list key", "foo; a|a=1", 10, std::nullopt, nullptr},
+    {"0x7d in parameterised list key", "foo; a}a=1", 10, std::nullopt, nullptr},
+    {"0x7e in parameterised list key", "foo; a~a=1", 10, std::nullopt, nullptr},
+    {"0x7f in parameterised list key", "foo; a\177a=1", 10, std::nullopt,
      nullptr},
-    {"0x7c in parameterised list key", "foo; a|a=1", 10, absl::nullopt,
+    {"0x00 starting a parameterised list key", "foo; \000a=1", 9, std::nullopt,
      nullptr},
-    {"0x7d in parameterised list key", "foo; a}a=1", 10, absl::nullopt,
+    {"0x01 starting a parameterised list key", "foo; \001a=1", 9, std::nullopt,
      nullptr},
-    {"0x7e in parameterised list key", "foo; a~a=1", 10, absl::nullopt,
+    {"0x02 starting a parameterised list key", "foo; \002a=1", 9, std::nullopt,
      nullptr},
-    {"0x7f in parameterised list key", "foo; a\177a=1", 10, absl::nullopt,
+    {"0x03 starting a parameterised list key", "foo; \003a=1", 9, std::nullopt,
      nullptr},
-    {"0x00 starting a parameterised list key", "foo; \000a=1", 9, absl::nullopt,
+    {"0x04 starting a parameterised list key", "foo; \004a=1", 9, std::nullopt,
      nullptr},
-    {"0x01 starting a parameterised list key", "foo; \001a=1", 9, absl::nullopt,
+    {"0x05 starting a parameterised list key", "foo; \005a=1", 9, std::nullopt,
      nullptr},
-    {"0x02 starting a parameterised list key", "foo; \002a=1", 9, absl::nullopt,
+    {"0x06 starting a parameterised list key", "foo; \006a=1", 9, std::nullopt,
      nullptr},
-    {"0x03 starting a parameterised list key", "foo; \003a=1", 9, absl::nullopt,
+    {"0x07 starting a parameterised list key", "foo; \aa=1", 9, std::nullopt,
      nullptr},
-    {"0x04 starting a parameterised list key", "foo; \004a=1", 9, absl::nullopt,
+    {"0x08 starting a parameterised list key", "foo; \ba=1", 9, std::nullopt,
      nullptr},
-    {"0x05 starting a parameterised list key", "foo; \005a=1", 9, absl::nullopt,
+    {"0x09 starting a parameterised list key", "foo; \ta=1", 9, std::nullopt,
      nullptr},
-    {"0x06 starting a parameterised list key", "foo; \006a=1", 9, absl::nullopt,
+    {"0x0a starting a parameterised list key", "foo; \na=1", 9, std::nullopt,
      nullptr},
-    {"0x07 starting a parameterised list key", "foo; \aa=1", 9, absl::nullopt,
+    {"0x0b starting a parameterised list key", "foo; \va=1", 9, std::nullopt,
      nullptr},
-    {"0x08 starting a parameterised list key", "foo; \ba=1", 9, absl::nullopt,
+    {"0x0c starting a parameterised list key", "foo; \fa=1", 9, std::nullopt,
      nullptr},
-    {"0x09 starting a parameterised list key", "foo; \ta=1", 9, absl::nullopt,
+    {"0x0d starting a parameterised list key", "foo; \ra=1", 9, std::nullopt,
      nullptr},
-    {"0x0a starting a parameterised list key", "foo; \na=1", 9, absl::nullopt,
+    {"0x0e starting a parameterised list key", "foo; \016a=1", 9, std::nullopt,
      nullptr},
-    {"0x0b starting a parameterised list key", "foo; \va=1", 9, absl::nullopt,
+    {"0x0f starting a parameterised list key", "foo; \017a=1", 9, std::nullopt,
      nullptr},
-    {"0x0c starting a parameterised list key", "foo; \fa=1", 9, absl::nullopt,
+    {"0x10 starting a parameterised list key", "foo; \020a=1", 9, std::nullopt,
      nullptr},
-    {"0x0d starting a parameterised list key", "foo; \ra=1", 9, absl::nullopt,
+    {"0x11 starting a parameterised list key", "foo; \021a=1", 9, std::nullopt,
      nullptr},
-    {"0x0e starting a parameterised list key", "foo; \016a=1", 9, absl::nullopt,
+    {"0x12 starting a parameterised list key", "foo; \022a=1", 9, std::nullopt,
      nullptr},
-    {"0x0f starting a parameterised list key", "foo; \017a=1", 9, absl::nullopt,
+    {"0x13 starting a parameterised list key", "foo; \023a=1", 9, std::nullopt,
      nullptr},
-    {"0x10 starting a parameterised list key", "foo; \020a=1", 9, absl::nullopt,
+    {"0x14 starting a parameterised list key", "foo; \024a=1", 9, std::nullopt,
      nullptr},
-    {"0x11 starting a parameterised list key", "foo; \021a=1", 9, absl::nullopt,
+    {"0x15 starting a parameterised list key", "foo; \025a=1", 9, std::nullopt,
      nullptr},
-    {"0x12 starting a parameterised list key", "foo; \022a=1", 9, absl::nullopt,
+    {"0x16 starting a parameterised list key", "foo; \026a=1", 9, std::nullopt,
      nullptr},
-    {"0x13 starting a parameterised list key", "foo; \023a=1", 9, absl::nullopt,
+    {"0x17 starting a parameterised list key", "foo; \027a=1", 9, std::nullopt,
      nullptr},
-    {"0x14 starting a parameterised list key", "foo; \024a=1", 9, absl::nullopt,
+    {"0x18 starting a parameterised list key", "foo; \030a=1", 9, std::nullopt,
      nullptr},
-    {"0x15 starting a parameterised list key", "foo; \025a=1", 9, absl::nullopt,
+    {"0x19 starting a parameterised list key", "foo; \031a=1", 9, std::nullopt,
      nullptr},
-    {"0x16 starting a parameterised list key", "foo; \026a=1", 9, absl::nullopt,
+    {"0x1a starting a parameterised list key", "foo; \032a=1", 9, std::nullopt,
      nullptr},
-    {"0x17 starting a parameterised list key", "foo; \027a=1", 9, absl::nullopt,
+    {"0x1b starting a parameterised list key", "foo; \033a=1", 9, std::nullopt,
      nullptr},
-    {"0x18 starting a parameterised list key", "foo; \030a=1", 9, absl::nullopt,
+    {"0x1c starting a parameterised list key", "foo; \034a=1", 9, std::nullopt,
      nullptr},
-    {"0x19 starting a parameterised list key", "foo; \031a=1", 9, absl::nullopt,
+    {"0x1d starting a parameterised list key", "foo; \035a=1", 9, std::nullopt,
      nullptr},
-    {"0x1a starting a parameterised list key", "foo; \032a=1", 9, absl::nullopt,
+    {"0x1e starting a parameterised list key", "foo; \036a=1", 9, std::nullopt,
      nullptr},
-    {"0x1b starting a parameterised list key", "foo; \033a=1", 9, absl::nullopt,
-     nullptr},
-    {"0x1c starting a parameterised list key", "foo; \034a=1", 9, absl::nullopt,
-     nullptr},
-    {"0x1d starting a parameterised list key", "foo; \035a=1", 9, absl::nullopt,
-     nullptr},
-    {"0x1e starting a parameterised list key", "foo; \036a=1", 9, absl::nullopt,
-     nullptr},
-    {"0x1f starting a parameterised list key", "foo; \037a=1", 9, absl::nullopt,
+    {"0x1f starting a parameterised list key", "foo; \037a=1", 9, std::nullopt,
      nullptr},
     {"0x20 starting a parameterised list key",
      "foo;  a=1",
      9,
      {{{Item("foo", Item::kTokenType), {Param("a", 1)}}}},
      "foo;a=1"},
-    {"0x21 starting a parameterised list key", "foo; !a=1", 9, absl::nullopt,
+    {"0x21 starting a parameterised list key", "foo; !a=1", 9, std::nullopt,
      nullptr},
-    {"0x22 starting a parameterised list key", "foo; \"a=1", 9, absl::nullopt,
+    {"0x22 starting a parameterised list key", "foo; \"a=1", 9, std::nullopt,
      nullptr},
-    {"0x23 starting a parameterised list key", "foo; #a=1", 9, absl::nullopt,
+    {"0x23 starting a parameterised list key", "foo; #a=1", 9, std::nullopt,
      nullptr},
-    {"0x24 starting a parameterised list key", "foo; $a=1", 9, absl::nullopt,
+    {"0x24 starting a parameterised list key", "foo; $a=1", 9, std::nullopt,
      nullptr},
-    {"0x25 starting a parameterised list key", "foo; %a=1", 9, absl::nullopt,
+    {"0x25 starting a parameterised list key", "foo; %a=1", 9, std::nullopt,
      nullptr},
-    {"0x26 starting a parameterised list key", "foo; &a=1", 9, absl::nullopt,
+    {"0x26 starting a parameterised list key", "foo; &a=1", 9, std::nullopt,
      nullptr},
-    {"0x27 starting a parameterised list key", "foo; 'a=1", 9, absl::nullopt,
+    {"0x27 starting a parameterised list key", "foo; 'a=1", 9, std::nullopt,
      nullptr},
-    {"0x28 starting a parameterised list key", "foo; (a=1", 9, absl::nullopt,
+    {"0x28 starting a parameterised list key", "foo; (a=1", 9, std::nullopt,
      nullptr},
-    {"0x29 starting a parameterised list key", "foo; )a=1", 9, absl::nullopt,
+    {"0x29 starting a parameterised list key", "foo; )a=1", 9, std::nullopt,
      nullptr},
     {"0x2a starting a parameterised list key",
      "foo; *a=1",
      9,
      {{{Item("foo", Item::kTokenType), {Param("*a", 1)}}}},
      "foo;*a=1"},
-    {"0x2b starting a parameterised list key", "foo; +a=1", 9, absl::nullopt,
+    {"0x2b starting a parameterised list key", "foo; +a=1", 9, std::nullopt,
      nullptr},
-    {"0x2c starting a parameterised list key", "foo; ,a=1", 9, absl::nullopt,
+    {"0x2c starting a parameterised list key", "foo; ,a=1", 9, std::nullopt,
      nullptr},
-    {"0x2d starting a parameterised list key", "foo; -a=1", 9, absl::nullopt,
+    {"0x2d starting a parameterised list key", "foo; -a=1", 9, std::nullopt,
      nullptr},
-    {"0x2e starting a parameterised list key", "foo; .a=1", 9, absl::nullopt,
+    {"0x2e starting a parameterised list key", "foo; .a=1", 9, std::nullopt,
      nullptr},
-    {"0x2f starting a parameterised list key", "foo; /a=1", 9, absl::nullopt,
+    {"0x2f starting a parameterised list key", "foo; /a=1", 9, std::nullopt,
      nullptr},
-    {"0x30 starting a parameterised list key", "foo; 0a=1", 9, absl::nullopt,
+    {"0x30 starting a parameterised list key", "foo; 0a=1", 9, std::nullopt,
      nullptr},
-    {"0x31 starting a parameterised list key", "foo; 1a=1", 9, absl::nullopt,
+    {"0x31 starting a parameterised list key", "foo; 1a=1", 9, std::nullopt,
      nullptr},
-    {"0x32 starting a parameterised list key", "foo; 2a=1", 9, absl::nullopt,
+    {"0x32 starting a parameterised list key", "foo; 2a=1", 9, std::nullopt,
      nullptr},
-    {"0x33 starting a parameterised list key", "foo; 3a=1", 9, absl::nullopt,
+    {"0x33 starting a parameterised list key", "foo; 3a=1", 9, std::nullopt,
      nullptr},
-    {"0x34 starting a parameterised list key", "foo; 4a=1", 9, absl::nullopt,
+    {"0x34 starting a parameterised list key", "foo; 4a=1", 9, std::nullopt,
      nullptr},
-    {"0x35 starting a parameterised list key", "foo; 5a=1", 9, absl::nullopt,
+    {"0x35 starting a parameterised list key", "foo; 5a=1", 9, std::nullopt,
      nullptr},
-    {"0x36 starting a parameterised list key", "foo; 6a=1", 9, absl::nullopt,
+    {"0x36 starting a parameterised list key", "foo; 6a=1", 9, std::nullopt,
      nullptr},
-    {"0x37 starting a parameterised list key", "foo; 7a=1", 9, absl::nullopt,
+    {"0x37 starting a parameterised list key", "foo; 7a=1", 9, std::nullopt,
      nullptr},
-    {"0x38 starting a parameterised list key", "foo; 8a=1", 9, absl::nullopt,
+    {"0x38 starting a parameterised list key", "foo; 8a=1", 9, std::nullopt,
      nullptr},
-    {"0x39 starting a parameterised list key", "foo; 9a=1", 9, absl::nullopt,
+    {"0x39 starting a parameterised list key", "foo; 9a=1", 9, std::nullopt,
      nullptr},
-    {"0x3a starting a parameterised list key", "foo; :a=1", 9, absl::nullopt,
+    {"0x3a starting a parameterised list key", "foo; :a=1", 9, std::nullopt,
      nullptr},
-    {"0x3b starting a parameterised list key", "foo; ;a=1", 9, absl::nullopt,
+    {"0x3b starting a parameterised list key", "foo; ;a=1", 9, std::nullopt,
      nullptr},
-    {"0x3c starting a parameterised list key", "foo; <a=1", 9, absl::nullopt,
+    {"0x3c starting a parameterised list key", "foo; <a=1", 9, std::nullopt,
      nullptr},
-    {"0x3d starting a parameterised list key", "foo; =a=1", 9, absl::nullopt,
+    {"0x3d starting a parameterised list key", "foo; =a=1", 9, std::nullopt,
      nullptr},
-    {"0x3e starting a parameterised list key", "foo; >a=1", 9, absl::nullopt,
+    {"0x3e starting a parameterised list key", "foo; >a=1", 9, std::nullopt,
      nullptr},
-    {"0x3f starting a parameterised list key", "foo; ?a=1", 9, absl::nullopt,
+    {"0x3f starting a parameterised list key", "foo; ?a=1", 9, std::nullopt,
      nullptr},
-    {"0x40 starting a parameterised list key", "foo; @a=1", 9, absl::nullopt,
+    {"0x40 starting a parameterised list key", "foo; @a=1", 9, std::nullopt,
      nullptr},
-    {"0x41 starting a parameterised list key", "foo; Aa=1", 9, absl::nullopt,
+    {"0x41 starting a parameterised list key", "foo; Aa=1", 9, std::nullopt,
      nullptr},
-    {"0x42 starting a parameterised list key", "foo; Ba=1", 9, absl::nullopt,
+    {"0x42 starting a parameterised list key", "foo; Ba=1", 9, std::nullopt,
      nullptr},
-    {"0x43 starting a parameterised list key", "foo; Ca=1", 9, absl::nullopt,
+    {"0x43 starting a parameterised list key", "foo; Ca=1", 9, std::nullopt,
      nullptr},
-    {"0x44 starting a parameterised list key", "foo; Da=1", 9, absl::nullopt,
+    {"0x44 starting a parameterised list key", "foo; Da=1", 9, std::nullopt,
      nullptr},
-    {"0x45 starting a parameterised list key", "foo; Ea=1", 9, absl::nullopt,
+    {"0x45 starting a parameterised list key", "foo; Ea=1", 9, std::nullopt,
      nullptr},
-    {"0x46 starting a parameterised list key", "foo; Fa=1", 9, absl::nullopt,
+    {"0x46 starting a parameterised list key", "foo; Fa=1", 9, std::nullopt,
      nullptr},
-    {"0x47 starting a parameterised list key", "foo; Ga=1", 9, absl::nullopt,
+    {"0x47 starting a parameterised list key", "foo; Ga=1", 9, std::nullopt,
      nullptr},
-    {"0x48 starting a parameterised list key", "foo; Ha=1", 9, absl::nullopt,
+    {"0x48 starting a parameterised list key", "foo; Ha=1", 9, std::nullopt,
      nullptr},
-    {"0x49 starting a parameterised list key", "foo; Ia=1", 9, absl::nullopt,
+    {"0x49 starting a parameterised list key", "foo; Ia=1", 9, std::nullopt,
      nullptr},
-    {"0x4a starting a parameterised list key", "foo; Ja=1", 9, absl::nullopt,
+    {"0x4a starting a parameterised list key", "foo; Ja=1", 9, std::nullopt,
      nullptr},
-    {"0x4b starting a parameterised list key", "foo; Ka=1", 9, absl::nullopt,
+    {"0x4b starting a parameterised list key", "foo; Ka=1", 9, std::nullopt,
      nullptr},
-    {"0x4c starting a parameterised list key", "foo; La=1", 9, absl::nullopt,
+    {"0x4c starting a parameterised list key", "foo; La=1", 9, std::nullopt,
      nullptr},
-    {"0x4d starting a parameterised list key", "foo; Ma=1", 9, absl::nullopt,
+    {"0x4d starting a parameterised list key", "foo; Ma=1", 9, std::nullopt,
      nullptr},
-    {"0x4e starting a parameterised list key", "foo; Na=1", 9, absl::nullopt,
+    {"0x4e starting a parameterised list key", "foo; Na=1", 9, std::nullopt,
      nullptr},
-    {"0x4f starting a parameterised list key", "foo; Oa=1", 9, absl::nullopt,
+    {"0x4f starting a parameterised list key", "foo; Oa=1", 9, std::nullopt,
      nullptr},
-    {"0x50 starting a parameterised list key", "foo; Pa=1", 9, absl::nullopt,
+    {"0x50 starting a parameterised list key", "foo; Pa=1", 9, std::nullopt,
      nullptr},
-    {"0x51 starting a parameterised list key", "foo; Qa=1", 9, absl::nullopt,
+    {"0x51 starting a parameterised list key", "foo; Qa=1", 9, std::nullopt,
      nullptr},
-    {"0x52 starting a parameterised list key", "foo; Ra=1", 9, absl::nullopt,
+    {"0x52 starting a parameterised list key", "foo; Ra=1", 9, std::nullopt,
      nullptr},
-    {"0x53 starting a parameterised list key", "foo; Sa=1", 9, absl::nullopt,
+    {"0x53 starting a parameterised list key", "foo; Sa=1", 9, std::nullopt,
      nullptr},
-    {"0x54 starting a parameterised list key", "foo; Ta=1", 9, absl::nullopt,
+    {"0x54 starting a parameterised list key", "foo; Ta=1", 9, std::nullopt,
      nullptr},
-    {"0x55 starting a parameterised list key", "foo; Ua=1", 9, absl::nullopt,
+    {"0x55 starting a parameterised list key", "foo; Ua=1", 9, std::nullopt,
      nullptr},
-    {"0x56 starting a parameterised list key", "foo; Va=1", 9, absl::nullopt,
+    {"0x56 starting a parameterised list key", "foo; Va=1", 9, std::nullopt,
      nullptr},
-    {"0x57 starting a parameterised list key", "foo; Wa=1", 9, absl::nullopt,
+    {"0x57 starting a parameterised list key", "foo; Wa=1", 9, std::nullopt,
      nullptr},
-    {"0x58 starting a parameterised list key", "foo; Xa=1", 9, absl::nullopt,
+    {"0x58 starting a parameterised list key", "foo; Xa=1", 9, std::nullopt,
      nullptr},
-    {"0x59 starting a parameterised list key", "foo; Ya=1", 9, absl::nullopt,
+    {"0x59 starting a parameterised list key", "foo; Ya=1", 9, std::nullopt,
      nullptr},
-    {"0x5a starting a parameterised list key", "foo; Za=1", 9, absl::nullopt,
+    {"0x5a starting a parameterised list key", "foo; Za=1", 9, std::nullopt,
      nullptr},
-    {"0x5b starting a parameterised list key", "foo; [a=1", 9, absl::nullopt,
+    {"0x5b starting a parameterised list key", "foo; [a=1", 9, std::nullopt,
      nullptr},
-    {"0x5c starting a parameterised list key", "foo; \\a=1", 9, absl::nullopt,
+    {"0x5c starting a parameterised list key", "foo; \\a=1", 9, std::nullopt,
      nullptr},
-    {"0x5d starting a parameterised list key", "foo; ]a=1", 9, absl::nullopt,
+    {"0x5d starting a parameterised list key", "foo; ]a=1", 9, std::nullopt,
      nullptr},
-    {"0x5e starting a parameterised list key", "foo; ^a=1", 9, absl::nullopt,
+    {"0x5e starting a parameterised list key", "foo; ^a=1", 9, std::nullopt,
      nullptr},
-    {"0x5f starting a parameterised list key", "foo; _a=1", 9, absl::nullopt,
+    {"0x5f starting a parameterised list key", "foo; _a=1", 9, std::nullopt,
      nullptr},
-    {"0x60 starting a parameterised list key", "foo; `a=1", 9, absl::nullopt,
+    {"0x60 starting a parameterised list key", "foo; `a=1", 9, std::nullopt,
      nullptr},
     {"0x61 starting a parameterised list key",
      "foo; aa=1",
@@ -2570,15 +2517,15 @@
      9,
      {{{Item("foo", Item::kTokenType), {Param("za", 1)}}}},
      "foo;za=1"},
-    {"0x7b starting a parameterised list key", "foo; {a=1", 9, absl::nullopt,
+    {"0x7b starting a parameterised list key", "foo; {a=1", 9, std::nullopt,
      nullptr},
-    {"0x7c starting a parameterised list key", "foo; |a=1", 9, absl::nullopt,
+    {"0x7c starting a parameterised list key", "foo; |a=1", 9, std::nullopt,
      nullptr},
-    {"0x7d starting a parameterised list key", "foo; }a=1", 9, absl::nullopt,
+    {"0x7d starting a parameterised list key", "foo; }a=1", 9, std::nullopt,
      nullptr},
-    {"0x7e starting a parameterised list key", "foo; ~a=1", 9, absl::nullopt,
+    {"0x7e starting a parameterised list key", "foo; ~a=1", 9, std::nullopt,
      nullptr},
-    {"0x7f starting a parameterised list key", "foo; \177a=1", 9, absl::nullopt,
+    {"0x7f starting a parameterised list key", "foo; \177a=1", 9, std::nullopt,
      nullptr},
     // list.json
     {"basic list",
@@ -2613,9 +2560,9 @@
      5,
      {{{Integer(1), {}}, {Integer(42), {}}}},
      "1, 42"},
-    {"trailing comma list", "1, 42,", 6, absl::nullopt, nullptr},
-    {"empty item list", "1,,42", 5, absl::nullopt, nullptr},
-    {"empty item list (multiple field lines)", "1, , 42", 7, absl::nullopt,
+    {"trailing comma list", "1, 42,", 6, std::nullopt, nullptr},
+    {"empty item list", "1,,42", 5, std::nullopt, nullptr},
+    {"empty item list (multiple field lines)", "1, , 42", 7, std::nullopt,
      nullptr},
     // listlist.json
     {"basic list of lists",
@@ -2646,14 +2593,14 @@
      11,
      {{{{{Integer(1), {}}, {Integer(42), {}}}, {}}}},
      "(1 42)"},
-    {"wrong whitespace list of lists", "(1\t 42)", 7, absl::nullopt, nullptr},
-    {"no trailing parenthesis list of lists", "(1 42", 5, absl::nullopt,
+    {"wrong whitespace list of lists", "(1\t 42)", 7, std::nullopt, nullptr},
+    {"no trailing parenthesis list of lists", "(1 42", 5, std::nullopt,
      nullptr},
     {"no trailing parenthesis middle list of lists", "(1 2, (42 43)", 13,
-     absl::nullopt, nullptr},
-    {"no spaces in inner-list", "(abc\"def\"?0123*dXZ3*xyz)", 24, absl::nullopt,
+     std::nullopt, nullptr},
+    {"no spaces in inner-list", "(abc\"def\"?0123*dXZ3*xyz)", 24, std::nullopt,
      nullptr},
-    {"no closing parenthesis", "(", 1, absl::nullopt, nullptr},
+    {"no closing parenthesis", "(", 1, std::nullopt, nullptr},
     // param-list.json
     {"basic parameterised list",
      "abc_123;a=1;b=2; cdef_456, ghi;q=9;r=\"+w\"",
@@ -2686,11 +2633,11 @@
        {Item("text/plain", Item::kTokenType), {DoubleParam("q", 0.500000)}}}},
      "text/html, text/plain;q=0.5"},
     {"whitespace before = parameterised list", "text/html, text/plain;q =0.5",
-     28, absl::nullopt, nullptr},
+     28, std::nullopt, nullptr},
     {"whitespace after = parameterised list", "text/html, text/plain;q= 0.5",
-     28, absl::nullopt, nullptr},
+     28, std::nullopt, nullptr},
     {"whitespace before ; parameterised list", "text/html, text/plain ;q=0.5",
-     28, absl::nullopt, nullptr},
+     28, std::nullopt, nullptr},
     {"whitespace after ; parameterised list",
      "text/html, text/plain; q=0.5",
      28,
@@ -2711,9 +2658,9 @@
        {Item("text/plain", Item::kTokenType), {DoubleParam("q", 0.500000)}}}},
      "text/html, text/plain;q=0.5"},
     {"trailing comma parameterised list", "text/html,text/plain;q=0.5,", 27,
-     absl::nullopt, nullptr},
+     std::nullopt, nullptr},
     {"empty item parameterised list", "text/html,,text/plain;q=0.5,", 28,
-     absl::nullopt, nullptr},
+     std::nullopt, nullptr},
     // param-listlist.json
     {"parameterised inner list",
      "(abc_123);a=1;b=2, cdef_456",
@@ -2757,7 +2704,7 @@
   const char* name;
   const char* raw;
   size_t raw_len;
-  const absl::optional<Dictionary>
+  const std::optional<Dictionary>
       expected;           // nullopt if parse error is expected.
   const char* canonical;  // nullptr if parse error is expected, or if canonical
                           // format is identical to raw.
@@ -2812,8 +2759,8 @@
      15,
      {Dictionary{{{"a", {Integer(1), {}}}, {"b", {Integer(2), {}}}}}},
      "a=1, b=2"},
-    {"whitespace before = dictionary", "a =1, b=2", 9, absl::nullopt, nullptr},
-    {"whitespace after = dictionary", "a=1, b= 2", 9, absl::nullopt, nullptr},
+    {"whitespace before = dictionary", "a =1, b=2", 9, std::nullopt, nullptr},
+    {"whitespace after = dictionary", "a=1, b= 2", 9, std::nullopt, nullptr},
     {"two lines dictionary",
      "a=1, b=2",
      8,
@@ -2857,16 +2804,16 @@
                   {"b", {Item(true), {Param("foo", 9)}}},
                   {"c", {Integer(3), {}}}}}},
      "a=1, b;foo=9, c=3"},
-    {"trailing comma dictionary", "a=1, b=2,", 9, absl::nullopt, nullptr},
-    {"empty item dictionary", "a=1,,b=2,", 9, absl::nullopt, nullptr},
+    {"trailing comma dictionary", "a=1, b=2,", 9, std::nullopt, nullptr},
+    {"empty item dictionary", "a=1,,b=2,", 9, std::nullopt, nullptr},
     {"duplicate key dictionary",
      "a=1,b=2,a=3",
      11,
      {Dictionary{{{"a", {Integer(3), {}}}, {"b", {Integer(2), {}}}}}},
      "a=3, b=2"},
-    {"numeric key dictionary", "a=1,1b=2,a=1", 12, absl::nullopt, nullptr},
-    {"uppercase key dictionary", "a=1,B=2,a=1", 11, absl::nullopt, nullptr},
-    {"bad key dictionary", "a=1,b!=2,a=1", 12, absl::nullopt, nullptr},
+    {"numeric key dictionary", "a=1,1b=2,a=1", 12, std::nullopt, nullptr},
+    {"uppercase key dictionary", "a=1,B=2,a=1", 11, std::nullopt, nullptr},
+    {"bad key dictionary", "a=1,b!=2,a=1", 12, std::nullopt, nullptr},
     // examples.json
     {"Example-DictHeader",
      "en=\"Applepie\", da=:w4ZibGV0w6ZydGU=:",
@@ -2913,202 +2860,202 @@
      {Dictionary{{{"foo", {Integer(1), {}}}, {"bar", {Integer(2), {}}}}}},
      "foo=1, bar=2"},
     // key-generated.json
-    {"0x00 as a single-character dictionary key", "\000=1", 3, absl::nullopt,
+    {"0x00 as a single-character dictionary key", "\000=1", 3, std::nullopt,
      nullptr},
-    {"0x01 as a single-character dictionary key", "\001=1", 3, absl::nullopt,
+    {"0x01 as a single-character dictionary key", "\001=1", 3, std::nullopt,
      nullptr},
-    {"0x02 as a single-character dictionary key", "\002=1", 3, absl::nullopt,
+    {"0x02 as a single-character dictionary key", "\002=1", 3, std::nullopt,
      nullptr},
-    {"0x03 as a single-character dictionary key", "\003=1", 3, absl::nullopt,
+    {"0x03 as a single-character dictionary key", "\003=1", 3, std::nullopt,
      nullptr},
-    {"0x04 as a single-character dictionary key", "\004=1", 3, absl::nullopt,
+    {"0x04 as a single-character dictionary key", "\004=1", 3, std::nullopt,
      nullptr},
-    {"0x05 as a single-character dictionary key", "\005=1", 3, absl::nullopt,
+    {"0x05 as a single-character dictionary key", "\005=1", 3, std::nullopt,
      nullptr},
-    {"0x06 as a single-character dictionary key", "\006=1", 3, absl::nullopt,
+    {"0x06 as a single-character dictionary key", "\006=1", 3, std::nullopt,
      nullptr},
-    {"0x07 as a single-character dictionary key", "\a=1", 3, absl::nullopt,
+    {"0x07 as a single-character dictionary key", "\a=1", 3, std::nullopt,
      nullptr},
-    {"0x08 as a single-character dictionary key", "\b=1", 3, absl::nullopt,
+    {"0x08 as a single-character dictionary key", "\b=1", 3, std::nullopt,
      nullptr},
-    {"0x09 as a single-character dictionary key", "\t=1", 3, absl::nullopt,
+    {"0x09 as a single-character dictionary key", "\t=1", 3, std::nullopt,
      nullptr},
-    {"0x0a as a single-character dictionary key", "\n=1", 3, absl::nullopt,
+    {"0x0a as a single-character dictionary key", "\n=1", 3, std::nullopt,
      nullptr},
-    {"0x0b as a single-character dictionary key", "\v=1", 3, absl::nullopt,
+    {"0x0b as a single-character dictionary key", "\v=1", 3, std::nullopt,
      nullptr},
-    {"0x0c as a single-character dictionary key", "\f=1", 3, absl::nullopt,
+    {"0x0c as a single-character dictionary key", "\f=1", 3, std::nullopt,
      nullptr},
-    {"0x0d as a single-character dictionary key", "\r=1", 3, absl::nullopt,
+    {"0x0d as a single-character dictionary key", "\r=1", 3, std::nullopt,
      nullptr},
-    {"0x0e as a single-character dictionary key", "\016=1", 3, absl::nullopt,
+    {"0x0e as a single-character dictionary key", "\016=1", 3, std::nullopt,
      nullptr},
-    {"0x0f as a single-character dictionary key", "\017=1", 3, absl::nullopt,
+    {"0x0f as a single-character dictionary key", "\017=1", 3, std::nullopt,
      nullptr},
-    {"0x10 as a single-character dictionary key", "\020=1", 3, absl::nullopt,
+    {"0x10 as a single-character dictionary key", "\020=1", 3, std::nullopt,
      nullptr},
-    {"0x11 as a single-character dictionary key", "\021=1", 3, absl::nullopt,
+    {"0x11 as a single-character dictionary key", "\021=1", 3, std::nullopt,
      nullptr},
-    {"0x12 as a single-character dictionary key", "\022=1", 3, absl::nullopt,
+    {"0x12 as a single-character dictionary key", "\022=1", 3, std::nullopt,
      nullptr},
-    {"0x13 as a single-character dictionary key", "\023=1", 3, absl::nullopt,
+    {"0x13 as a single-character dictionary key", "\023=1", 3, std::nullopt,
      nullptr},
-    {"0x14 as a single-character dictionary key", "\024=1", 3, absl::nullopt,
+    {"0x14 as a single-character dictionary key", "\024=1", 3, std::nullopt,
      nullptr},
-    {"0x15 as a single-character dictionary key", "\025=1", 3, absl::nullopt,
+    {"0x15 as a single-character dictionary key", "\025=1", 3, std::nullopt,
      nullptr},
-    {"0x16 as a single-character dictionary key", "\026=1", 3, absl::nullopt,
+    {"0x16 as a single-character dictionary key", "\026=1", 3, std::nullopt,
      nullptr},
-    {"0x17 as a single-character dictionary key", "\027=1", 3, absl::nullopt,
+    {"0x17 as a single-character dictionary key", "\027=1", 3, std::nullopt,
      nullptr},
-    {"0x18 as a single-character dictionary key", "\030=1", 3, absl::nullopt,
+    {"0x18 as a single-character dictionary key", "\030=1", 3, std::nullopt,
      nullptr},
-    {"0x19 as a single-character dictionary key", "\031=1", 3, absl::nullopt,
+    {"0x19 as a single-character dictionary key", "\031=1", 3, std::nullopt,
      nullptr},
-    {"0x1a as a single-character dictionary key", "\032=1", 3, absl::nullopt,
+    {"0x1a as a single-character dictionary key", "\032=1", 3, std::nullopt,
      nullptr},
-    {"0x1b as a single-character dictionary key", "\033=1", 3, absl::nullopt,
+    {"0x1b as a single-character dictionary key", "\033=1", 3, std::nullopt,
      nullptr},
-    {"0x1c as a single-character dictionary key", "\034=1", 3, absl::nullopt,
+    {"0x1c as a single-character dictionary key", "\034=1", 3, std::nullopt,
      nullptr},
-    {"0x1d as a single-character dictionary key", "\035=1", 3, absl::nullopt,
+    {"0x1d as a single-character dictionary key", "\035=1", 3, std::nullopt,
      nullptr},
-    {"0x1e as a single-character dictionary key", "\036=1", 3, absl::nullopt,
+    {"0x1e as a single-character dictionary key", "\036=1", 3, std::nullopt,
      nullptr},
-    {"0x1f as a single-character dictionary key", "\037=1", 3, absl::nullopt,
+    {"0x1f as a single-character dictionary key", "\037=1", 3, std::nullopt,
      nullptr},
-    {"0x20 as a single-character dictionary key", "=1", 2, absl::nullopt,
+    {"0x20 as a single-character dictionary key", "=1", 2, std::nullopt,
      nullptr},
-    {"0x21 as a single-character dictionary key", "!=1", 3, absl::nullopt,
+    {"0x21 as a single-character dictionary key", "!=1", 3, std::nullopt,
      nullptr},
-    {"0x22 as a single-character dictionary key", "\"=1", 3, absl::nullopt,
+    {"0x22 as a single-character dictionary key", "\"=1", 3, std::nullopt,
      nullptr},
-    {"0x23 as a single-character dictionary key", "#=1", 3, absl::nullopt,
+    {"0x23 as a single-character dictionary key", "#=1", 3, std::nullopt,
      nullptr},
-    {"0x24 as a single-character dictionary key", "$=1", 3, absl::nullopt,
+    {"0x24 as a single-character dictionary key", "$=1", 3, std::nullopt,
      nullptr},
-    {"0x25 as a single-character dictionary key", "%=1", 3, absl::nullopt,
+    {"0x25 as a single-character dictionary key", "%=1", 3, std::nullopt,
      nullptr},
-    {"0x26 as a single-character dictionary key", "&=1", 3, absl::nullopt,
+    {"0x26 as a single-character dictionary key", "&=1", 3, std::nullopt,
      nullptr},
-    {"0x27 as a single-character dictionary key", "'=1", 3, absl::nullopt,
+    {"0x27 as a single-character dictionary key", "'=1", 3, std::nullopt,
      nullptr},
-    {"0x28 as a single-character dictionary key", "(=1", 3, absl::nullopt,
+    {"0x28 as a single-character dictionary key", "(=1", 3, std::nullopt,
      nullptr},
-    {"0x29 as a single-character dictionary key", ")=1", 3, absl::nullopt,
+    {"0x29 as a single-character dictionary key", ")=1", 3, std::nullopt,
      nullptr},
     {"0x2a as a single-character dictionary key",
      "*=1",
      3,
      {Dictionary{{{"*", {Integer(1), {}}}}}},
      nullptr},
-    {"0x2b as a single-character dictionary key", "+=1", 3, absl::nullopt,
+    {"0x2b as a single-character dictionary key", "+=1", 3, std::nullopt,
      nullptr},
-    {"0x2c as a single-character dictionary key", ",=1", 3, absl::nullopt,
+    {"0x2c as a single-character dictionary key", ",=1", 3, std::nullopt,
      nullptr},
-    {"0x2d as a single-character dictionary key", "-=1", 3, absl::nullopt,
+    {"0x2d as a single-character dictionary key", "-=1", 3, std::nullopt,
      nullptr},
-    {"0x2e as a single-character dictionary key", ".=1", 3, absl::nullopt,
+    {"0x2e as a single-character dictionary key", ".=1", 3, std::nullopt,
      nullptr},
-    {"0x2f as a single-character dictionary key", "/=1", 3, absl::nullopt,
+    {"0x2f as a single-character dictionary key", "/=1", 3, std::nullopt,
      nullptr},
-    {"0x30 as a single-character dictionary key", "0=1", 3, absl::nullopt,
+    {"0x30 as a single-character dictionary key", "0=1", 3, std::nullopt,
      nullptr},
-    {"0x31 as a single-character dictionary key", "1=1", 3, absl::nullopt,
+    {"0x31 as a single-character dictionary key", "1=1", 3, std::nullopt,
      nullptr},
-    {"0x32 as a single-character dictionary key", "2=1", 3, absl::nullopt,
+    {"0x32 as a single-character dictionary key", "2=1", 3, std::nullopt,
      nullptr},
-    {"0x33 as a single-character dictionary key", "3=1", 3, absl::nullopt,
+    {"0x33 as a single-character dictionary key", "3=1", 3, std::nullopt,
      nullptr},
-    {"0x34 as a single-character dictionary key", "4=1", 3, absl::nullopt,
+    {"0x34 as a single-character dictionary key", "4=1", 3, std::nullopt,
      nullptr},
-    {"0x35 as a single-character dictionary key", "5=1", 3, absl::nullopt,
+    {"0x35 as a single-character dictionary key", "5=1", 3, std::nullopt,
      nullptr},
-    {"0x36 as a single-character dictionary key", "6=1", 3, absl::nullopt,
+    {"0x36 as a single-character dictionary key", "6=1", 3, std::nullopt,
      nullptr},
-    {"0x37 as a single-character dictionary key", "7=1", 3, absl::nullopt,
+    {"0x37 as a single-character dictionary key", "7=1", 3, std::nullopt,
      nullptr},
-    {"0x38 as a single-character dictionary key", "8=1", 3, absl::nullopt,
+    {"0x38 as a single-character dictionary key", "8=1", 3, std::nullopt,
      nullptr},
-    {"0x39 as a single-character dictionary key", "9=1", 3, absl::nullopt,
+    {"0x39 as a single-character dictionary key", "9=1", 3, std::nullopt,
      nullptr},
-    {"0x3a as a single-character dictionary key", ":=1", 3, absl::nullopt,
+    {"0x3a as a single-character dictionary key", ":=1", 3, std::nullopt,
      nullptr},
-    {"0x3b as a single-character dictionary key", ";=1", 3, absl::nullopt,
+    {"0x3b as a single-character dictionary key", ";=1", 3, std::nullopt,
      nullptr},
-    {"0x3c as a single-character dictionary key", "<=1", 3, absl::nullopt,
+    {"0x3c as a single-character dictionary key", "<=1", 3, std::nullopt,
      nullptr},
-    {"0x3d as a single-character dictionary key", "==1", 3, absl::nullopt,
+    {"0x3d as a single-character dictionary key", "==1", 3, std::nullopt,
      nullptr},
-    {"0x3e as a single-character dictionary key", ">=1", 3, absl::nullopt,
+    {"0x3e as a single-character dictionary key", ">=1", 3, std::nullopt,
      nullptr},
-    {"0x3f as a single-character dictionary key", "?=1", 3, absl::nullopt,
+    {"0x3f as a single-character dictionary key", "?=1", 3, std::nullopt,
      nullptr},
-    {"0x40 as a single-character dictionary key", "@=1", 3, absl::nullopt,
+    {"0x40 as a single-character dictionary key", "@=1", 3, std::nullopt,
      nullptr},
-    {"0x41 as a single-character dictionary key", "A=1", 3, absl::nullopt,
+    {"0x41 as a single-character dictionary key", "A=1", 3, std::nullopt,
      nullptr},
-    {"0x42 as a single-character dictionary key", "B=1", 3, absl::nullopt,
+    {"0x42 as a single-character dictionary key", "B=1", 3, std::nullopt,
      nullptr},
-    {"0x43 as a single-character dictionary key", "C=1", 3, absl::nullopt,
+    {"0x43 as a single-character dictionary key", "C=1", 3, std::nullopt,
      nullptr},
-    {"0x44 as a single-character dictionary key", "D=1", 3, absl::nullopt,
+    {"0x44 as a single-character dictionary key", "D=1", 3, std::nullopt,
      nullptr},
-    {"0x45 as a single-character dictionary key", "E=1", 3, absl::nullopt,
+    {"0x45 as a single-character dictionary key", "E=1", 3, std::nullopt,
      nullptr},
-    {"0x46 as a single-character dictionary key", "F=1", 3, absl::nullopt,
+    {"0x46 as a single-character dictionary key", "F=1", 3, std::nullopt,
      nullptr},
-    {"0x47 as a single-character dictionary key", "G=1", 3, absl::nullopt,
+    {"0x47 as a single-character dictionary key", "G=1", 3, std::nullopt,
      nullptr},
-    {"0x48 as a single-character dictionary key", "H=1", 3, absl::nullopt,
+    {"0x48 as a single-character dictionary key", "H=1", 3, std::nullopt,
      nullptr},
-    {"0x49 as a single-character dictionary key", "I=1", 3, absl::nullopt,
+    {"0x49 as a single-character dictionary key", "I=1", 3, std::nullopt,
      nullptr},
-    {"0x4a as a single-character dictionary key", "J=1", 3, absl::nullopt,
+    {"0x4a as a single-character dictionary key", "J=1", 3, std::nullopt,
      nullptr},
-    {"0x4b as a single-character dictionary key", "K=1", 3, absl::nullopt,
+    {"0x4b as a single-character dictionary key", "K=1", 3, std::nullopt,
      nullptr},
-    {"0x4c as a single-character dictionary key", "L=1", 3, absl::nullopt,
+    {"0x4c as a single-character dictionary key", "L=1", 3, std::nullopt,
      nullptr},
-    {"0x4d as a single-character dictionary key", "M=1", 3, absl::nullopt,
+    {"0x4d as a single-character dictionary key", "M=1", 3, std::nullopt,
      nullptr},
-    {"0x4e as a single-character dictionary key", "N=1", 3, absl::nullopt,
+    {"0x4e as a single-character dictionary key", "N=1", 3, std::nullopt,
      nullptr},
-    {"0x4f as a single-character dictionary key", "O=1", 3, absl::nullopt,
+    {"0x4f as a single-character dictionary key", "O=1", 3, std::nullopt,
      nullptr},
-    {"0x50 as a single-character dictionary key", "P=1", 3, absl::nullopt,
+    {"0x50 as a single-character dictionary key", "P=1", 3, std::nullopt,
      nullptr},
-    {"0x51 as a single-character dictionary key", "Q=1", 3, absl::nullopt,
+    {"0x51 as a single-character dictionary key", "Q=1", 3, std::nullopt,
      nullptr},
-    {"0x52 as a single-character dictionary key", "R=1", 3, absl::nullopt,
+    {"0x52 as a single-character dictionary key", "R=1", 3, std::nullopt,
      nullptr},
-    {"0x53 as a single-character dictionary key", "S=1", 3, absl::nullopt,
+    {"0x53 as a single-character dictionary key", "S=1", 3, std::nullopt,
      nullptr},
-    {"0x54 as a single-character dictionary key", "T=1", 3, absl::nullopt,
+    {"0x54 as a single-character dictionary key", "T=1", 3, std::nullopt,
      nullptr},
-    {"0x55 as a single-character dictionary key", "U=1", 3, absl::nullopt,
+    {"0x55 as a single-character dictionary key", "U=1", 3, std::nullopt,
      nullptr},
-    {"0x56 as a single-character dictionary key", "V=1", 3, absl::nullopt,
+    {"0x56 as a single-character dictionary key", "V=1", 3, std::nullopt,
      nullptr},
-    {"0x57 as a single-character dictionary key", "W=1", 3, absl::nullopt,
+    {"0x57 as a single-character dictionary key", "W=1", 3, std::nullopt,
      nullptr},
-    {"0x58 as a single-character dictionary key", "X=1", 3, absl::nullopt,
+    {"0x58 as a single-character dictionary key", "X=1", 3, std::nullopt,
      nullptr},
-    {"0x59 as a single-character dictionary key", "Y=1", 3, absl::nullopt,
+    {"0x59 as a single-character dictionary key", "Y=1", 3, std::nullopt,
      nullptr},
-    {"0x5a as a single-character dictionary key", "Z=1", 3, absl::nullopt,
+    {"0x5a as a single-character dictionary key", "Z=1", 3, std::nullopt,
      nullptr},
-    {"0x5b as a single-character dictionary key", "[=1", 3, absl::nullopt,
+    {"0x5b as a single-character dictionary key", "[=1", 3, std::nullopt,
      nullptr},
-    {"0x5c as a single-character dictionary key", "\\=1", 3, absl::nullopt,
+    {"0x5c as a single-character dictionary key", "\\=1", 3, std::nullopt,
      nullptr},
-    {"0x5d as a single-character dictionary key", "]=1", 3, absl::nullopt,
+    {"0x5d as a single-character dictionary key", "]=1", 3, std::nullopt,
      nullptr},
-    {"0x5e as a single-character dictionary key", "^=1", 3, absl::nullopt,
+    {"0x5e as a single-character dictionary key", "^=1", 3, std::nullopt,
      nullptr},
-    {"0x5f as a single-character dictionary key", "_=1", 3, absl::nullopt,
+    {"0x5f as a single-character dictionary key", "_=1", 3, std::nullopt,
      nullptr},
-    {"0x60 as a single-character dictionary key", "`=1", 3, absl::nullopt,
+    {"0x60 as a single-character dictionary key", "`=1", 3, std::nullopt,
      nullptr},
     {"0x61 as a single-character dictionary key",
      "a=1",
@@ -3240,64 +3187,64 @@
      3,
      {Dictionary{{{"z", {Integer(1), {}}}}}},
      nullptr},
-    {"0x7b as a single-character dictionary key", "{=1", 3, absl::nullopt,
+    {"0x7b as a single-character dictionary key", "{=1", 3, std::nullopt,
      nullptr},
-    {"0x7c as a single-character dictionary key", "|=1", 3, absl::nullopt,
+    {"0x7c as a single-character dictionary key", "|=1", 3, std::nullopt,
      nullptr},
-    {"0x7d as a single-character dictionary key", "}=1", 3, absl::nullopt,
+    {"0x7d as a single-character dictionary key", "}=1", 3, std::nullopt,
      nullptr},
-    {"0x7e as a single-character dictionary key", "~=1", 3, absl::nullopt,
+    {"0x7e as a single-character dictionary key", "~=1", 3, std::nullopt,
      nullptr},
-    {"0x7f as a single-character dictionary key", "\177=1", 3, absl::nullopt,
+    {"0x7f as a single-character dictionary key", "\177=1", 3, std::nullopt,
      nullptr},
-    {"0x00 in dictionary key", "a\000a=1", 5, absl::nullopt, nullptr},
-    {"0x01 in dictionary key", "a\001a=1", 5, absl::nullopt, nullptr},
-    {"0x02 in dictionary key", "a\002a=1", 5, absl::nullopt, nullptr},
-    {"0x03 in dictionary key", "a\003a=1", 5, absl::nullopt, nullptr},
-    {"0x04 in dictionary key", "a\004a=1", 5, absl::nullopt, nullptr},
-    {"0x05 in dictionary key", "a\005a=1", 5, absl::nullopt, nullptr},
-    {"0x06 in dictionary key", "a\006a=1", 5, absl::nullopt, nullptr},
-    {"0x07 in dictionary key", "a\aa=1", 5, absl::nullopt, nullptr},
-    {"0x08 in dictionary key", "a\ba=1", 5, absl::nullopt, nullptr},
-    {"0x09 in dictionary key", "a\ta=1", 5, absl::nullopt, nullptr},
-    {"0x0a in dictionary key", "a\na=1", 5, absl::nullopt, nullptr},
-    {"0x0b in dictionary key", "a\va=1", 5, absl::nullopt, nullptr},
-    {"0x0c in dictionary key", "a\fa=1", 5, absl::nullopt, nullptr},
-    {"0x0d in dictionary key", "a\ra=1", 5, absl::nullopt, nullptr},
-    {"0x0e in dictionary key", "a\016a=1", 5, absl::nullopt, nullptr},
-    {"0x0f in dictionary key", "a\017a=1", 5, absl::nullopt, nullptr},
-    {"0x10 in dictionary key", "a\020a=1", 5, absl::nullopt, nullptr},
-    {"0x11 in dictionary key", "a\021a=1", 5, absl::nullopt, nullptr},
-    {"0x12 in dictionary key", "a\022a=1", 5, absl::nullopt, nullptr},
-    {"0x13 in dictionary key", "a\023a=1", 5, absl::nullopt, nullptr},
-    {"0x14 in dictionary key", "a\024a=1", 5, absl::nullopt, nullptr},
-    {"0x15 in dictionary key", "a\025a=1", 5, absl::nullopt, nullptr},
-    {"0x16 in dictionary key", "a\026a=1", 5, absl::nullopt, nullptr},
-    {"0x17 in dictionary key", "a\027a=1", 5, absl::nullopt, nullptr},
-    {"0x18 in dictionary key", "a\030a=1", 5, absl::nullopt, nullptr},
-    {"0x19 in dictionary key", "a\031a=1", 5, absl::nullopt, nullptr},
-    {"0x1a in dictionary key", "a\032a=1", 5, absl::nullopt, nullptr},
-    {"0x1b in dictionary key", "a\033a=1", 5, absl::nullopt, nullptr},
-    {"0x1c in dictionary key", "a\034a=1", 5, absl::nullopt, nullptr},
-    {"0x1d in dictionary key", "a\035a=1", 5, absl::nullopt, nullptr},
-    {"0x1e in dictionary key", "a\036a=1", 5, absl::nullopt, nullptr},
-    {"0x1f in dictionary key", "a\037a=1", 5, absl::nullopt, nullptr},
-    {"0x20 in dictionary key", "a a=1", 5, absl::nullopt, nullptr},
-    {"0x21 in dictionary key", "a!a=1", 5, absl::nullopt, nullptr},
-    {"0x22 in dictionary key", "a\"a=1", 5, absl::nullopt, nullptr},
-    {"0x23 in dictionary key", "a#a=1", 5, absl::nullopt, nullptr},
-    {"0x24 in dictionary key", "a$a=1", 5, absl::nullopt, nullptr},
-    {"0x25 in dictionary key", "a%a=1", 5, absl::nullopt, nullptr},
-    {"0x26 in dictionary key", "a&a=1", 5, absl::nullopt, nullptr},
-    {"0x27 in dictionary key", "a'a=1", 5, absl::nullopt, nullptr},
-    {"0x28 in dictionary key", "a(a=1", 5, absl::nullopt, nullptr},
-    {"0x29 in dictionary key", "a)a=1", 5, absl::nullopt, nullptr},
+    {"0x00 in dictionary key", "a\000a=1", 5, std::nullopt, nullptr},
+    {"0x01 in dictionary key", "a\001a=1", 5, std::nullopt, nullptr},
+    {"0x02 in dictionary key", "a\002a=1", 5, std::nullopt, nullptr},
+    {"0x03 in dictionary key", "a\003a=1", 5, std::nullopt, nullptr},
+    {"0x04 in dictionary key", "a\004a=1", 5, std::nullopt, nullptr},
+    {"0x05 in dictionary key", "a\005a=1", 5, std::nullopt, nullptr},
+    {"0x06 in dictionary key", "a\006a=1", 5, std::nullopt, nullptr},
+    {"0x07 in dictionary key", "a\aa=1", 5, std::nullopt, nullptr},
+    {"0x08 in dictionary key", "a\ba=1", 5, std::nullopt, nullptr},
+    {"0x09 in dictionary key", "a\ta=1", 5, std::nullopt, nullptr},
+    {"0x0a in dictionary key", "a\na=1", 5, std::nullopt, nullptr},
+    {"0x0b in dictionary key", "a\va=1", 5, std::nullopt, nullptr},
+    {"0x0c in dictionary key", "a\fa=1", 5, std::nullopt, nullptr},
+    {"0x0d in dictionary key", "a\ra=1", 5, std::nullopt, nullptr},
+    {"0x0e in dictionary key", "a\016a=1", 5, std::nullopt, nullptr},
+    {"0x0f in dictionary key", "a\017a=1", 5, std::nullopt, nullptr},
+    {"0x10 in dictionary key", "a\020a=1", 5, std::nullopt, nullptr},
+    {"0x11 in dictionary key", "a\021a=1", 5, std::nullopt, nullptr},
+    {"0x12 in dictionary key", "a\022a=1", 5, std::nullopt, nullptr},
+    {"0x13 in dictionary key", "a\023a=1", 5, std::nullopt, nullptr},
+    {"0x14 in dictionary key", "a\024a=1", 5, std::nullopt, nullptr},
+    {"0x15 in dictionary key", "a\025a=1", 5, std::nullopt, nullptr},
+    {"0x16 in dictionary key", "a\026a=1", 5, std::nullopt, nullptr},
+    {"0x17 in dictionary key", "a\027a=1", 5, std::nullopt, nullptr},
+    {"0x18 in dictionary key", "a\030a=1", 5, std::nullopt, nullptr},
+    {"0x19 in dictionary key", "a\031a=1", 5, std::nullopt, nullptr},
+    {"0x1a in dictionary key", "a\032a=1", 5, std::nullopt, nullptr},
+    {"0x1b in dictionary key", "a\033a=1", 5, std::nullopt, nullptr},
+    {"0x1c in dictionary key", "a\034a=1", 5, std::nullopt, nullptr},
+    {"0x1d in dictionary key", "a\035a=1", 5, std::nullopt, nullptr},
+    {"0x1e in dictionary key", "a\036a=1", 5, std::nullopt, nullptr},
+    {"0x1f in dictionary key", "a\037a=1", 5, std::nullopt, nullptr},
+    {"0x20 in dictionary key", "a a=1", 5, std::nullopt, nullptr},
+    {"0x21 in dictionary key", "a!a=1", 5, std::nullopt, nullptr},
+    {"0x22 in dictionary key", "a\"a=1", 5, std::nullopt, nullptr},
+    {"0x23 in dictionary key", "a#a=1", 5, std::nullopt, nullptr},
+    {"0x24 in dictionary key", "a$a=1", 5, std::nullopt, nullptr},
+    {"0x25 in dictionary key", "a%a=1", 5, std::nullopt, nullptr},
+    {"0x26 in dictionary key", "a&a=1", 5, std::nullopt, nullptr},
+    {"0x27 in dictionary key", "a'a=1", 5, std::nullopt, nullptr},
+    {"0x28 in dictionary key", "a(a=1", 5, std::nullopt, nullptr},
+    {"0x29 in dictionary key", "a)a=1", 5, std::nullopt, nullptr},
     {"0x2a in dictionary key",
      "a*a=1",
      5,
      {Dictionary{{{"a*a", {Integer(1), {}}}}}},
      nullptr},
-    {"0x2b in dictionary key", "a+a=1", 5, absl::nullopt, nullptr},
+    {"0x2b in dictionary key", "a+a=1", 5, std::nullopt, nullptr},
     {"0x2c in dictionary key",
      "a,a=1",
      5,
@@ -3313,7 +3260,7 @@
      5,
      {Dictionary{{{"a.a", {Integer(1), {}}}}}},
      nullptr},
-    {"0x2f in dictionary key", "a/a=1", 5, absl::nullopt, nullptr},
+    {"0x2f in dictionary key", "a/a=1", 5, std::nullopt, nullptr},
     {"0x30 in dictionary key",
      "a0a=1",
      5,
@@ -3364,53 +3311,53 @@
      5,
      {Dictionary{{{"a9a", {Integer(1), {}}}}}},
      nullptr},
-    {"0x3a in dictionary key", "a:a=1", 5, absl::nullopt, nullptr},
+    {"0x3a in dictionary key", "a:a=1", 5, std::nullopt, nullptr},
     {"0x3b in dictionary key",
      "a;a=1",
      5,
      {Dictionary{{{"a", {Item(true), {Param("a", 1)}}}}}},
      nullptr},
-    {"0x3c in dictionary key", "a<a=1", 5, absl::nullopt, nullptr},
-    {"0x3d in dictionary key", "a=a=1", 5, absl::nullopt, nullptr},
-    {"0x3e in dictionary key", "a>a=1", 5, absl::nullopt, nullptr},
-    {"0x3f in dictionary key", "a?a=1", 5, absl::nullopt, nullptr},
-    {"0x40 in dictionary key", "a@a=1", 5, absl::nullopt, nullptr},
-    {"0x41 in dictionary key", "aAa=1", 5, absl::nullopt, nullptr},
-    {"0x42 in dictionary key", "aBa=1", 5, absl::nullopt, nullptr},
-    {"0x43 in dictionary key", "aCa=1", 5, absl::nullopt, nullptr},
-    {"0x44 in dictionary key", "aDa=1", 5, absl::nullopt, nullptr},
-    {"0x45 in dictionary key", "aEa=1", 5, absl::nullopt, nullptr},
-    {"0x46 in dictionary key", "aFa=1", 5, absl::nullopt, nullptr},
-    {"0x47 in dictionary key", "aGa=1", 5, absl::nullopt, nullptr},
-    {"0x48 in dictionary key", "aHa=1", 5, absl::nullopt, nullptr},
-    {"0x49 in dictionary key", "aIa=1", 5, absl::nullopt, nullptr},
-    {"0x4a in dictionary key", "aJa=1", 5, absl::nullopt, nullptr},
-    {"0x4b in dictionary key", "aKa=1", 5, absl::nullopt, nullptr},
-    {"0x4c in dictionary key", "aLa=1", 5, absl::nullopt, nullptr},
-    {"0x4d in dictionary key", "aMa=1", 5, absl::nullopt, nullptr},
-    {"0x4e in dictionary key", "aNa=1", 5, absl::nullopt, nullptr},
-    {"0x4f in dictionary key", "aOa=1", 5, absl::nullopt, nullptr},
-    {"0x50 in dictionary key", "aPa=1", 5, absl::nullopt, nullptr},
-    {"0x51 in dictionary key", "aQa=1", 5, absl::nullopt, nullptr},
-    {"0x52 in dictionary key", "aRa=1", 5, absl::nullopt, nullptr},
-    {"0x53 in dictionary key", "aSa=1", 5, absl::nullopt, nullptr},
-    {"0x54 in dictionary key", "aTa=1", 5, absl::nullopt, nullptr},
-    {"0x55 in dictionary key", "aUa=1", 5, absl::nullopt, nullptr},
-    {"0x56 in dictionary key", "aVa=1", 5, absl::nullopt, nullptr},
-    {"0x57 in dictionary key", "aWa=1", 5, absl::nullopt, nullptr},
-    {"0x58 in dictionary key", "aXa=1", 5, absl::nullopt, nullptr},
-    {"0x59 in dictionary key", "aYa=1", 5, absl::nullopt, nullptr},
-    {"0x5a in dictionary key", "aZa=1", 5, absl::nullopt, nullptr},
-    {"0x5b in dictionary key", "a[a=1", 5, absl::nullopt, nullptr},
-    {"0x5c in dictionary key", "a\\a=1", 5, absl::nullopt, nullptr},
-    {"0x5d in dictionary key", "a]a=1", 5, absl::nullopt, nullptr},
-    {"0x5e in dictionary key", "a^a=1", 5, absl::nullopt, nullptr},
+    {"0x3c in dictionary key", "a<a=1", 5, std::nullopt, nullptr},
+    {"0x3d in dictionary key", "a=a=1", 5, std::nullopt, nullptr},
+    {"0x3e in dictionary key", "a>a=1", 5, std::nullopt, nullptr},
+    {"0x3f in dictionary key", "a?a=1", 5, std::nullopt, nullptr},
+    {"0x40 in dictionary key", "a@a=1", 5, std::nullopt, nullptr},
+    {"0x41 in dictionary key", "aAa=1", 5, std::nullopt, nullptr},
+    {"0x42 in dictionary key", "aBa=1", 5, std::nullopt, nullptr},
+    {"0x43 in dictionary key", "aCa=1", 5, std::nullopt, nullptr},
+    {"0x44 in dictionary key", "aDa=1", 5, std::nullopt, nullptr},
+    {"0x45 in dictionary key", "aEa=1", 5, std::nullopt, nullptr},
+    {"0x46 in dictionary key", "aFa=1", 5, std::nullopt, nullptr},
+    {"0x47 in dictionary key", "aGa=1", 5, std::nullopt, nullptr},
+    {"0x48 in dictionary key", "aHa=1", 5, std::nullopt, nullptr},
+    {"0x49 in dictionary key", "aIa=1", 5, std::nullopt, nullptr},
+    {"0x4a in dictionary key", "aJa=1", 5, std::nullopt, nullptr},
+    {"0x4b in dictionary key", "aKa=1", 5, std::nullopt, nullptr},
+    {"0x4c in dictionary key", "aLa=1", 5, std::nullopt, nullptr},
+    {"0x4d in dictionary key", "aMa=1", 5, std::nullopt, nullptr},
+    {"0x4e in dictionary key", "aNa=1", 5, std::nullopt, nullptr},
+    {"0x4f in dictionary key", "aOa=1", 5, std::nullopt, nullptr},
+    {"0x50 in dictionary key", "aPa=1", 5, std::nullopt, nullptr},
+    {"0x51 in dictionary key", "aQa=1", 5, std::nullopt, nullptr},
+    {"0x52 in dictionary key", "aRa=1", 5, std::nullopt, nullptr},
+    {"0x53 in dictionary key", "aSa=1", 5, std::nullopt, nullptr},
+    {"0x54 in dictionary key", "aTa=1", 5, std::nullopt, nullptr},
+    {"0x55 in dictionary key", "aUa=1", 5, std::nullopt, nullptr},
+    {"0x56 in dictionary key", "aVa=1", 5, std::nullopt, nullptr},
+    {"0x57 in dictionary key", "aWa=1", 5, std::nullopt, nullptr},
+    {"0x58 in dictionary key", "aXa=1", 5, std::nullopt, nullptr},
+    {"0x59 in dictionary key", "aYa=1", 5, std::nullopt, nullptr},
+    {"0x5a in dictionary key", "aZa=1", 5, std::nullopt, nullptr},
+    {"0x5b in dictionary key", "a[a=1", 5, std::nullopt, nullptr},
+    {"0x5c in dictionary key", "a\\a=1", 5, std::nullopt, nullptr},
+    {"0x5d in dictionary key", "a]a=1", 5, std::nullopt, nullptr},
+    {"0x5e in dictionary key", "a^a=1", 5, std::nullopt, nullptr},
     {"0x5f in dictionary key",
      "a_a=1",
      5,
      {Dictionary{{{"a_a", {Integer(1), {}}}}}},
      nullptr},
-    {"0x60 in dictionary key", "a`a=1", 5, absl::nullopt, nullptr},
+    {"0x60 in dictionary key", "a`a=1", 5, std::nullopt, nullptr},
     {"0x61 in dictionary key",
      "aaa=1",
      5,
@@ -3541,116 +3488,116 @@
      5,
      {Dictionary{{{"aza", {Integer(1), {}}}}}},
      nullptr},
-    {"0x7b in dictionary key", "a{a=1", 5, absl::nullopt, nullptr},
-    {"0x7c in dictionary key", "a|a=1", 5, absl::nullopt, nullptr},
-    {"0x7d in dictionary key", "a}a=1", 5, absl::nullopt, nullptr},
-    {"0x7e in dictionary key", "a~a=1", 5, absl::nullopt, nullptr},
-    {"0x7f in dictionary key", "a\177a=1", 5, absl::nullopt, nullptr},
-    {"0x00 starting an dictionary key", "\000a=1", 4, absl::nullopt, nullptr},
-    {"0x01 starting an dictionary key", "\001a=1", 4, absl::nullopt, nullptr},
-    {"0x02 starting an dictionary key", "\002a=1", 4, absl::nullopt, nullptr},
-    {"0x03 starting an dictionary key", "\003a=1", 4, absl::nullopt, nullptr},
-    {"0x04 starting an dictionary key", "\004a=1", 4, absl::nullopt, nullptr},
-    {"0x05 starting an dictionary key", "\005a=1", 4, absl::nullopt, nullptr},
-    {"0x06 starting an dictionary key", "\006a=1", 4, absl::nullopt, nullptr},
-    {"0x07 starting an dictionary key", "\aa=1", 4, absl::nullopt, nullptr},
-    {"0x08 starting an dictionary key", "\ba=1", 4, absl::nullopt, nullptr},
-    {"0x09 starting an dictionary key", "\ta=1", 4, absl::nullopt, nullptr},
-    {"0x0a starting an dictionary key", "\na=1", 4, absl::nullopt, nullptr},
-    {"0x0b starting an dictionary key", "\va=1", 4, absl::nullopt, nullptr},
-    {"0x0c starting an dictionary key", "\fa=1", 4, absl::nullopt, nullptr},
-    {"0x0d starting an dictionary key", "\ra=1", 4, absl::nullopt, nullptr},
-    {"0x0e starting an dictionary key", "\016a=1", 4, absl::nullopt, nullptr},
-    {"0x0f starting an dictionary key", "\017a=1", 4, absl::nullopt, nullptr},
-    {"0x10 starting an dictionary key", "\020a=1", 4, absl::nullopt, nullptr},
-    {"0x11 starting an dictionary key", "\021a=1", 4, absl::nullopt, nullptr},
-    {"0x12 starting an dictionary key", "\022a=1", 4, absl::nullopt, nullptr},
-    {"0x13 starting an dictionary key", "\023a=1", 4, absl::nullopt, nullptr},
-    {"0x14 starting an dictionary key", "\024a=1", 4, absl::nullopt, nullptr},
-    {"0x15 starting an dictionary key", "\025a=1", 4, absl::nullopt, nullptr},
-    {"0x16 starting an dictionary key", "\026a=1", 4, absl::nullopt, nullptr},
-    {"0x17 starting an dictionary key", "\027a=1", 4, absl::nullopt, nullptr},
-    {"0x18 starting an dictionary key", "\030a=1", 4, absl::nullopt, nullptr},
-    {"0x19 starting an dictionary key", "\031a=1", 4, absl::nullopt, nullptr},
-    {"0x1a starting an dictionary key", "\032a=1", 4, absl::nullopt, nullptr},
-    {"0x1b starting an dictionary key", "\033a=1", 4, absl::nullopt, nullptr},
-    {"0x1c starting an dictionary key", "\034a=1", 4, absl::nullopt, nullptr},
-    {"0x1d starting an dictionary key", "\035a=1", 4, absl::nullopt, nullptr},
-    {"0x1e starting an dictionary key", "\036a=1", 4, absl::nullopt, nullptr},
-    {"0x1f starting an dictionary key", "\037a=1", 4, absl::nullopt, nullptr},
+    {"0x7b in dictionary key", "a{a=1", 5, std::nullopt, nullptr},
+    {"0x7c in dictionary key", "a|a=1", 5, std::nullopt, nullptr},
+    {"0x7d in dictionary key", "a}a=1", 5, std::nullopt, nullptr},
+    {"0x7e in dictionary key", "a~a=1", 5, std::nullopt, nullptr},
+    {"0x7f in dictionary key", "a\177a=1", 5, std::nullopt, nullptr},
+    {"0x00 starting an dictionary key", "\000a=1", 4, std::nullopt, nullptr},
+    {"0x01 starting an dictionary key", "\001a=1", 4, std::nullopt, nullptr},
+    {"0x02 starting an dictionary key", "\002a=1", 4, std::nullopt, nullptr},
+    {"0x03 starting an dictionary key", "\003a=1", 4, std::nullopt, nullptr},
+    {"0x04 starting an dictionary key", "\004a=1", 4, std::nullopt, nullptr},
+    {"0x05 starting an dictionary key", "\005a=1", 4, std::nullopt, nullptr},
+    {"0x06 starting an dictionary key", "\006a=1", 4, std::nullopt, nullptr},
+    {"0x07 starting an dictionary key", "\aa=1", 4, std::nullopt, nullptr},
+    {"0x08 starting an dictionary key", "\ba=1", 4, std::nullopt, nullptr},
+    {"0x09 starting an dictionary key", "\ta=1", 4, std::nullopt, nullptr},
+    {"0x0a starting an dictionary key", "\na=1", 4, std::nullopt, nullptr},
+    {"0x0b starting an dictionary key", "\va=1", 4, std::nullopt, nullptr},
+    {"0x0c starting an dictionary key", "\fa=1", 4, std::nullopt, nullptr},
+    {"0x0d starting an dictionary key", "\ra=1", 4, std::nullopt, nullptr},
+    {"0x0e starting an dictionary key", "\016a=1", 4, std::nullopt, nullptr},
+    {"0x0f starting an dictionary key", "\017a=1", 4, std::nullopt, nullptr},
+    {"0x10 starting an dictionary key", "\020a=1", 4, std::nullopt, nullptr},
+    {"0x11 starting an dictionary key", "\021a=1", 4, std::nullopt, nullptr},
+    {"0x12 starting an dictionary key", "\022a=1", 4, std::nullopt, nullptr},
+    {"0x13 starting an dictionary key", "\023a=1", 4, std::nullopt, nullptr},
+    {"0x14 starting an dictionary key", "\024a=1", 4, std::nullopt, nullptr},
+    {"0x15 starting an dictionary key", "\025a=1", 4, std::nullopt, nullptr},
+    {"0x16 starting an dictionary key", "\026a=1", 4, std::nullopt, nullptr},
+    {"0x17 starting an dictionary key", "\027a=1", 4, std::nullopt, nullptr},
+    {"0x18 starting an dictionary key", "\030a=1", 4, std::nullopt, nullptr},
+    {"0x19 starting an dictionary key", "\031a=1", 4, std::nullopt, nullptr},
+    {"0x1a starting an dictionary key", "\032a=1", 4, std::nullopt, nullptr},
+    {"0x1b starting an dictionary key", "\033a=1", 4, std::nullopt, nullptr},
+    {"0x1c starting an dictionary key", "\034a=1", 4, std::nullopt, nullptr},
+    {"0x1d starting an dictionary key", "\035a=1", 4, std::nullopt, nullptr},
+    {"0x1e starting an dictionary key", "\036a=1", 4, std::nullopt, nullptr},
+    {"0x1f starting an dictionary key", "\037a=1", 4, std::nullopt, nullptr},
     {"0x20 starting an dictionary key",
      " a=1",
      4,
      {Dictionary{{{"a", {Integer(1), {}}}}}},
      "a=1"},
-    {"0x21 starting an dictionary key", "!a=1", 4, absl::nullopt, nullptr},
-    {"0x22 starting an dictionary key", "\"a=1", 4, absl::nullopt, nullptr},
-    {"0x23 starting an dictionary key", "#a=1", 4, absl::nullopt, nullptr},
-    {"0x24 starting an dictionary key", "$a=1", 4, absl::nullopt, nullptr},
-    {"0x25 starting an dictionary key", "%a=1", 4, absl::nullopt, nullptr},
-    {"0x26 starting an dictionary key", "&a=1", 4, absl::nullopt, nullptr},
-    {"0x27 starting an dictionary key", "'a=1", 4, absl::nullopt, nullptr},
-    {"0x28 starting an dictionary key", "(a=1", 4, absl::nullopt, nullptr},
-    {"0x29 starting an dictionary key", ")a=1", 4, absl::nullopt, nullptr},
+    {"0x21 starting an dictionary key", "!a=1", 4, std::nullopt, nullptr},
+    {"0x22 starting an dictionary key", "\"a=1", 4, std::nullopt, nullptr},
+    {"0x23 starting an dictionary key", "#a=1", 4, std::nullopt, nullptr},
+    {"0x24 starting an dictionary key", "$a=1", 4, std::nullopt, nullptr},
+    {"0x25 starting an dictionary key", "%a=1", 4, std::nullopt, nullptr},
+    {"0x26 starting an dictionary key", "&a=1", 4, std::nullopt, nullptr},
+    {"0x27 starting an dictionary key", "'a=1", 4, std::nullopt, nullptr},
+    {"0x28 starting an dictionary key", "(a=1", 4, std::nullopt, nullptr},
+    {"0x29 starting an dictionary key", ")a=1", 4, std::nullopt, nullptr},
     {"0x2a starting an dictionary key",
      "*a=1",
      4,
      {Dictionary{{{"*a", {Integer(1), {}}}}}},
      nullptr},
-    {"0x2b starting an dictionary key", "+a=1", 4, absl::nullopt, nullptr},
-    {"0x2c starting an dictionary key", ",a=1", 4, absl::nullopt, nullptr},
-    {"0x2d starting an dictionary key", "-a=1", 4, absl::nullopt, nullptr},
-    {"0x2e starting an dictionary key", ".a=1", 4, absl::nullopt, nullptr},
-    {"0x2f starting an dictionary key", "/a=1", 4, absl::nullopt, nullptr},
-    {"0x30 starting an dictionary key", "0a=1", 4, absl::nullopt, nullptr},
-    {"0x31 starting an dictionary key", "1a=1", 4, absl::nullopt, nullptr},
-    {"0x32 starting an dictionary key", "2a=1", 4, absl::nullopt, nullptr},
-    {"0x33 starting an dictionary key", "3a=1", 4, absl::nullopt, nullptr},
-    {"0x34 starting an dictionary key", "4a=1", 4, absl::nullopt, nullptr},
-    {"0x35 starting an dictionary key", "5a=1", 4, absl::nullopt, nullptr},
-    {"0x36 starting an dictionary key", "6a=1", 4, absl::nullopt, nullptr},
-    {"0x37 starting an dictionary key", "7a=1", 4, absl::nullopt, nullptr},
-    {"0x38 starting an dictionary key", "8a=1", 4, absl::nullopt, nullptr},
-    {"0x39 starting an dictionary key", "9a=1", 4, absl::nullopt, nullptr},
-    {"0x3a starting an dictionary key", ":a=1", 4, absl::nullopt, nullptr},
-    {"0x3b starting an dictionary key", ";a=1", 4, absl::nullopt, nullptr},
-    {"0x3c starting an dictionary key", "<a=1", 4, absl::nullopt, nullptr},
-    {"0x3d starting an dictionary key", "=a=1", 4, absl::nullopt, nullptr},
-    {"0x3e starting an dictionary key", ">a=1", 4, absl::nullopt, nullptr},
-    {"0x3f starting an dictionary key", "?a=1", 4, absl::nullopt, nullptr},
-    {"0x40 starting an dictionary key", "@a=1", 4, absl::nullopt, nullptr},
-    {"0x41 starting an dictionary key", "Aa=1", 4, absl::nullopt, nullptr},
-    {"0x42 starting an dictionary key", "Ba=1", 4, absl::nullopt, nullptr},
-    {"0x43 starting an dictionary key", "Ca=1", 4, absl::nullopt, nullptr},
-    {"0x44 starting an dictionary key", "Da=1", 4, absl::nullopt, nullptr},
-    {"0x45 starting an dictionary key", "Ea=1", 4, absl::nullopt, nullptr},
-    {"0x46 starting an dictionary key", "Fa=1", 4, absl::nullopt, nullptr},
-    {"0x47 starting an dictionary key", "Ga=1", 4, absl::nullopt, nullptr},
-    {"0x48 starting an dictionary key", "Ha=1", 4, absl::nullopt, nullptr},
-    {"0x49 starting an dictionary key", "Ia=1", 4, absl::nullopt, nullptr},
-    {"0x4a starting an dictionary key", "Ja=1", 4, absl::nullopt, nullptr},
-    {"0x4b starting an dictionary key", "Ka=1", 4, absl::nullopt, nullptr},
-    {"0x4c starting an dictionary key", "La=1", 4, absl::nullopt, nullptr},
-    {"0x4d starting an dictionary key", "Ma=1", 4, absl::nullopt, nullptr},
-    {"0x4e starting an dictionary key", "Na=1", 4, absl::nullopt, nullptr},
-    {"0x4f starting an dictionary key", "Oa=1", 4, absl::nullopt, nullptr},
-    {"0x50 starting an dictionary key", "Pa=1", 4, absl::nullopt, nullptr},
-    {"0x51 starting an dictionary key", "Qa=1", 4, absl::nullopt, nullptr},
-    {"0x52 starting an dictionary key", "Ra=1", 4, absl::nullopt, nullptr},
-    {"0x53 starting an dictionary key", "Sa=1", 4, absl::nullopt, nullptr},
-    {"0x54 starting an dictionary key", "Ta=1", 4, absl::nullopt, nullptr},
-    {"0x55 starting an dictionary key", "Ua=1", 4, absl::nullopt, nullptr},
-    {"0x56 starting an dictionary key", "Va=1", 4, absl::nullopt, nullptr},
-    {"0x57 starting an dictionary key", "Wa=1", 4, absl::nullopt, nullptr},
-    {"0x58 starting an dictionary key", "Xa=1", 4, absl::nullopt, nullptr},
-    {"0x59 starting an dictionary key", "Ya=1", 4, absl::nullopt, nullptr},
-    {"0x5a starting an dictionary key", "Za=1", 4, absl::nullopt, nullptr},
-    {"0x5b starting an dictionary key", "[a=1", 4, absl::nullopt, nullptr},
-    {"0x5c starting an dictionary key", "\\a=1", 4, absl::nullopt, nullptr},
-    {"0x5d starting an dictionary key", "]a=1", 4, absl::nullopt, nullptr},
-    {"0x5e starting an dictionary key", "^a=1", 4, absl::nullopt, nullptr},
-    {"0x5f starting an dictionary key", "_a=1", 4, absl::nullopt, nullptr},
-    {"0x60 starting an dictionary key", "`a=1", 4, absl::nullopt, nullptr},
+    {"0x2b starting an dictionary key", "+a=1", 4, std::nullopt, nullptr},
+    {"0x2c starting an dictionary key", ",a=1", 4, std::nullopt, nullptr},
+    {"0x2d starting an dictionary key", "-a=1", 4, std::nullopt, nullptr},
+    {"0x2e starting an dictionary key", ".a=1", 4, std::nullopt, nullptr},
+    {"0x2f starting an dictionary key", "/a=1", 4, std::nullopt, nullptr},
+    {"0x30 starting an dictionary key", "0a=1", 4, std::nullopt, nullptr},
+    {"0x31 starting an dictionary key", "1a=1", 4, std::nullopt, nullptr},
+    {"0x32 starting an dictionary key", "2a=1", 4, std::nullopt, nullptr},
+    {"0x33 starting an dictionary key", "3a=1", 4, std::nullopt, nullptr},
+    {"0x34 starting an dictionary key", "4a=1", 4, std::nullopt, nullptr},
+    {"0x35 starting an dictionary key", "5a=1", 4, std::nullopt, nullptr},
+    {"0x36 starting an dictionary key", "6a=1", 4, std::nullopt, nullptr},
+    {"0x37 starting an dictionary key", "7a=1", 4, std::nullopt, nullptr},
+    {"0x38 starting an dictionary key", "8a=1", 4, std::nullopt, nullptr},
+    {"0x39 starting an dictionary key", "9a=1", 4, std::nullopt, nullptr},
+    {"0x3a starting an dictionary key", ":a=1", 4, std::nullopt, nullptr},
+    {"0x3b starting an dictionary key", ";a=1", 4, std::nullopt, nullptr},
+    {"0x3c starting an dictionary key", "<a=1", 4, std::nullopt, nullptr},
+    {"0x3d starting an dictionary key", "=a=1", 4, std::nullopt, nullptr},
+    {"0x3e starting an dictionary key", ">a=1", 4, std::nullopt, nullptr},
+    {"0x3f starting an dictionary key", "?a=1", 4, std::nullopt, nullptr},
+    {"0x40 starting an dictionary key", "@a=1", 4, std::nullopt, nullptr},
+    {"0x41 starting an dictionary key", "Aa=1", 4, std::nullopt, nullptr},
+    {"0x42 starting an dictionary key", "Ba=1", 4, std::nullopt, nullptr},
+    {"0x43 starting an dictionary key", "Ca=1", 4, std::nullopt, nullptr},
+    {"0x44 starting an dictionary key", "Da=1", 4, std::nullopt, nullptr},
+    {"0x45 starting an dictionary key", "Ea=1", 4, std::nullopt, nullptr},
+    {"0x46 starting an dictionary key", "Fa=1", 4, std::nullopt, nullptr},
+    {"0x47 starting an dictionary key", "Ga=1", 4, std::nullopt, nullptr},
+    {"0x48 starting an dictionary key", "Ha=1", 4, std::nullopt, nullptr},
+    {"0x49 starting an dictionary key", "Ia=1", 4, std::nullopt, nullptr},
+    {"0x4a starting an dictionary key", "Ja=1", 4, std::nullopt, nullptr},
+    {"0x4b starting an dictionary key", "Ka=1", 4, std::nullopt, nullptr},
+    {"0x4c starting an dictionary key", "La=1", 4, std::nullopt, nullptr},
+    {"0x4d starting an dictionary key", "Ma=1", 4, std::nullopt, nullptr},
+    {"0x4e starting an dictionary key", "Na=1", 4, std::nullopt, nullptr},
+    {"0x4f starting an dictionary key", "Oa=1", 4, std::nullopt, nullptr},
+    {"0x50 starting an dictionary key", "Pa=1", 4, std::nullopt, nullptr},
+    {"0x51 starting an dictionary key", "Qa=1", 4, std::nullopt, nullptr},
+    {"0x52 starting an dictionary key", "Ra=1", 4, std::nullopt, nullptr},
+    {"0x53 starting an dictionary key", "Sa=1", 4, std::nullopt, nullptr},
+    {"0x54 starting an dictionary key", "Ta=1", 4, std::nullopt, nullptr},
+    {"0x55 starting an dictionary key", "Ua=1", 4, std::nullopt, nullptr},
+    {"0x56 starting an dictionary key", "Va=1", 4, std::nullopt, nullptr},
+    {"0x57 starting an dictionary key", "Wa=1", 4, std::nullopt, nullptr},
+    {"0x58 starting an dictionary key", "Xa=1", 4, std::nullopt, nullptr},
+    {"0x59 starting an dictionary key", "Ya=1", 4, std::nullopt, nullptr},
+    {"0x5a starting an dictionary key", "Za=1", 4, std::nullopt, nullptr},
+    {"0x5b starting an dictionary key", "[a=1", 4, std::nullopt, nullptr},
+    {"0x5c starting an dictionary key", "\\a=1", 4, std::nullopt, nullptr},
+    {"0x5d starting an dictionary key", "]a=1", 4, std::nullopt, nullptr},
+    {"0x5e starting an dictionary key", "^a=1", 4, std::nullopt, nullptr},
+    {"0x5f starting an dictionary key", "_a=1", 4, std::nullopt, nullptr},
+    {"0x60 starting an dictionary key", "`a=1", 4, std::nullopt, nullptr},
     {"0x61 starting an dictionary key",
      "aa=1",
      4,
@@ -3781,11 +3728,11 @@
      4,
      {Dictionary{{{"za", {Integer(1), {}}}}}},
      nullptr},
-    {"0x7b starting an dictionary key", "{a=1", 4, absl::nullopt, nullptr},
-    {"0x7c starting an dictionary key", "|a=1", 4, absl::nullopt, nullptr},
-    {"0x7d starting an dictionary key", "}a=1", 4, absl::nullopt, nullptr},
-    {"0x7e starting an dictionary key", "~a=1", 4, absl::nullopt, nullptr},
-    {"0x7f starting an dictionary key", "\177a=1", 4, absl::nullopt, nullptr},
+    {"0x7b starting an dictionary key", "{a=1", 4, std::nullopt, nullptr},
+    {"0x7c starting an dictionary key", "|a=1", 4, std::nullopt, nullptr},
+    {"0x7d starting an dictionary key", "}a=1", 4, std::nullopt, nullptr},
+    {"0x7e starting an dictionary key", "~a=1", 4, std::nullopt, nullptr},
+    {"0x7f starting an dictionary key", "\177a=1", 4, std::nullopt, nullptr},
     // param-dict.json
     {"basic parameterised dict",
      "abc=123;a=1;b=2, def=456, ghi=789;q=9;r=\"+w\"",
@@ -3825,11 +3772,11 @@
      {Dictionary{{{"a", {Item("b", Item::kTokenType), {Param("c", 1)}}},
                   {"d", {Item("e", Item::kTokenType), {Param("f", 2)}}}}}},
      "a=b;c=1, d=e;f=2"},
-    {"whitespace before = parameterised dict", "a=b;q =0.5", 10, absl::nullopt,
+    {"whitespace before = parameterised dict", "a=b;q =0.5", 10, std::nullopt,
      nullptr},
-    {"whitespace after = parameterised dict", "a=b;q= 0.5", 10, absl::nullopt,
+    {"whitespace after = parameterised dict", "a=b;q= 0.5", 10, std::nullopt,
      nullptr},
-    {"whitespace before ; parameterised dict", "a=b ;q=0.5", 10, absl::nullopt,
+    {"whitespace before ; parameterised dict", "a=b ;q=0.5", 10, std::nullopt,
      nullptr},
     {"whitespace after ; parameterised dict",
      "a=b; q=0.5",
@@ -3851,9 +3798,9 @@
      {Dictionary{{{"a", {Item("b", Item::kTokenType), {Param("c", 1)}}},
                   {"d", {Item("e", Item::kTokenType), {Param("f", 2)}}}}}},
      "a=b;c=1, d=e;f=2"},
-    {"trailing comma parameterised list", "a=b; q=1.0,", 11, absl::nullopt,
+    {"trailing comma parameterised list", "a=b; q=1.0,", 11, std::nullopt,
      nullptr},
-    {"empty item parameterised list", "a=b; q=1.0,,c=d", 15, absl::nullopt,
+    {"empty item parameterised list", "a=b; q=1.0,,c=d", 15, std::nullopt,
      nullptr},
 };
 
@@ -3864,7 +3811,7 @@
     if (c.raw) {
       SCOPED_TRACE(c.name);
       std::string raw{c.raw, c.raw_len};
-      absl::optional<ParameterizedItem> result = ParseItem(raw);
+      std::optional<ParameterizedItem> result = ParseItem(raw);
       EXPECT_EQ(result, c.expected);
     }
   }
@@ -3875,7 +3822,7 @@
     if (c.raw) {
       SCOPED_TRACE(c.name);
       std::string raw{c.raw, c.raw_len};
-      absl::optional<List> result = ParseList(raw);
+      std::optional<List> result = ParseList(raw);
       EXPECT_EQ(result, c.expected);
     }
   }
@@ -3886,7 +3833,7 @@
     if (c.raw) {
       SCOPED_TRACE(c.name);
       std::string raw{c.raw, c.raw_len};
-      absl::optional<Dictionary> result = ParseDictionary(raw);
+      std::optional<Dictionary> result = ParseDictionary(raw);
       EXPECT_EQ(result, c.expected);
     }
   }
@@ -3896,7 +3843,7 @@
   for (const auto& c : parameterized_item_test_cases) {
     SCOPED_TRACE(c.name);
     if (c.expected) {
-      absl::optional<std::string> result = SerializeItem(*c.expected);
+      std::optional<std::string> result = SerializeItem(*c.expected);
       if (c.raw || c.canonical) {
         EXPECT_TRUE(result.has_value());
         EXPECT_EQ(result.value(),
@@ -3912,7 +3859,7 @@
   for (const auto& c : list_test_cases) {
     SCOPED_TRACE(c.name);
     if (c.expected) {
-      absl::optional<std::string> result = SerializeList(*c.expected);
+      std::optional<std::string> result = SerializeList(*c.expected);
       if (c.raw || c.canonical) {
         EXPECT_TRUE(result.has_value());
         EXPECT_EQ(result.value(),
@@ -3928,7 +3875,7 @@
   for (const auto& c : dictionary_test_cases) {
     SCOPED_TRACE(c.name);
     if (c.expected) {
-      absl::optional<std::string> result = SerializeDictionary(*c.expected);
+      std::optional<std::string> result = SerializeDictionary(*c.expected);
       if (c.raw || c.canonical) {
         EXPECT_TRUE(result.has_value());
         EXPECT_EQ(result.value(),
diff --git a/quiche/common/structured_headers_test.cc b/quiche/common/structured_headers_test.cc
index 73a7ab3..988a660 100644
--- a/quiche/common/structured_headers_test.cc
+++ b/quiche/common/structured_headers_test.cc
@@ -7,6 +7,7 @@
 #include <math.h>
 
 #include <limits>
+#include <optional>
 #include <string>
 
 #include "quiche/common/platform/api/quiche_test.h"
@@ -57,12 +58,12 @@
 const struct ItemTestCase {
   const char* name;
   const char* raw;
-  const absl::optional<Item> expected;  // nullopt if parse error is expected.
+  const std::optional<Item> expected;  // nullopt if parse error is expected.
   const char* canonical;  // nullptr if parse error is expected, or if canonical
                           // format is identical to raw.
 } item_test_cases[] = {
     // Token
-    {"bad token - item", "abc$@%!", absl::nullopt, nullptr},
+    {"bad token - item", "abc$@%!", std::nullopt, nullptr},
     {"leading whitespace", " foo", Token("foo"), "foo"},
     {"trailing whitespace", "foo ", Token("foo"), "foo"},
     {"leading asterisk", "*foo", Token("*foo"), nullptr},
@@ -70,19 +71,19 @@
     {"long integer", "999999999999999", Integer(999999999999999L), nullptr},
     {"long negative integer", "-999999999999999", Integer(-999999999999999L),
      nullptr},
-    {"too long integer", "1000000000000000", absl::nullopt, nullptr},
-    {"negative too long integer", "-1000000000000000", absl::nullopt, nullptr},
+    {"too long integer", "1000000000000000", std::nullopt, nullptr},
+    {"negative too long integer", "-1000000000000000", std::nullopt, nullptr},
     {"integral decimal", "1.0", Item(1.0), nullptr},
     // String
     {"basic string", "\"foo\"", Item("foo"), nullptr},
-    {"non-ascii string", "\"f\xC3\xBC\xC3\xBC\"", absl::nullopt, nullptr},
+    {"non-ascii string", "\"f\xC3\xBC\xC3\xBC\"", std::nullopt, nullptr},
     // Additional tests
     {"valid quoting containing \\n", "\"\\\\n\"", Item("\\n"), nullptr},
     {"valid quoting containing \\t", "\"\\\\t\"", Item("\\t"), nullptr},
     {"valid quoting containing \\x", "\"\\\\x61\"", Item("\\x61"), nullptr},
-    {"c-style hex escape in string", "\"\\x61\"", absl::nullopt, nullptr},
+    {"c-style hex escape in string", "\"\\x61\"", std::nullopt, nullptr},
     {"valid quoting containing \\u", "\"\\\\u0061\"", Item("\\u0061"), nullptr},
-    {"c-style unicode escape in string", "\"\\u0061\"", absl::nullopt, nullptr},
+    {"c-style unicode escape in string", "\"\\u0061\"", std::nullopt, nullptr},
 };
 
 const ItemTestCase sh09_item_test_cases[] = {
@@ -91,8 +92,8 @@
      nullptr},
     {"large negative integer", "-9223372036854775807",
      Integer(-9223372036854775807L), nullptr},
-    {"too large integer", "9223372036854775808", absl::nullopt, nullptr},
-    {"too large negative integer", "-9223372036854775808", absl::nullopt,
+    {"too large integer", "9223372036854775808", std::nullopt, nullptr},
+    {"too large negative integer", "-9223372036854775808", std::nullopt,
      nullptr},
     // Byte Sequence
     {"basic binary", "*aGVsbG8=*", Item("hello", Item::kByteSequenceType),
@@ -100,23 +101,23 @@
     {"empty binary", "**", Item("", Item::kByteSequenceType), nullptr},
     {"bad paddding", "*aGVsbG8*", Item("hello", Item::kByteSequenceType),
      "*aGVsbG8=*"},
-    {"bad end delimiter", "*aGVsbG8=", absl::nullopt, nullptr},
-    {"extra whitespace", "*aGVsb G8=*", absl::nullopt, nullptr},
-    {"extra chars", "*aGVsbG!8=*", absl::nullopt, nullptr},
-    {"suffix chars", "*aGVsbG8=!*", absl::nullopt, nullptr},
+    {"bad end delimiter", "*aGVsbG8=", std::nullopt, nullptr},
+    {"extra whitespace", "*aGVsb G8=*", std::nullopt, nullptr},
+    {"extra chars", "*aGVsbG!8=*", std::nullopt, nullptr},
+    {"suffix chars", "*aGVsbG8=!*", std::nullopt, nullptr},
     {"non-zero pad bits", "*iZ==*", Item("\x89", Item::kByteSequenceType),
      "*iQ==*"},
     {"non-ASCII binary", "*/+Ah*", Item("\xFF\xE0!", Item::kByteSequenceType),
      nullptr},
-    {"base64url binary", "*_-Ah*", absl::nullopt, nullptr},
-    {"token with leading asterisk", "*foo", absl::nullopt, nullptr},
+    {"base64url binary", "*_-Ah*", std::nullopt, nullptr},
+    {"token with leading asterisk", "*foo", std::nullopt, nullptr},
 };
 
 // For Structured Headers Draft 15
 const struct ParameterizedItemTestCase {
   const char* name;
   const char* raw;
-  const absl::optional<ParameterizedItem>
+  const std::optional<ParameterizedItem>
       expected;           // nullopt if parse error is expected.
   const char* canonical;  // nullptr if parse error is expected, or if canonical
                           // format is identical to raw.
@@ -147,11 +148,11 @@
      {{Token("text/html"), {Param("a", 1L)}}},
      "text/html;a=1"},
     {"whitespace before = parameterised item", "text/html, text/plain;q =0.5",
-     absl::nullopt, nullptr},
+     std::nullopt, nullptr},
     {"whitespace after = parameterised item", "text/html, text/plain;q= 0.5",
-     absl::nullopt, nullptr},
+     std::nullopt, nullptr},
     {"whitespace before ; parameterised item", "text/html, text/plain ;q=0.5",
-     absl::nullopt, nullptr},
+     std::nullopt, nullptr},
     {"whitespace after ; parameterised item",
      "text/plain; q=0.5",
      {{Token("text/plain"), {DoubleParam("q", 0.5)}}},
@@ -167,7 +168,7 @@
 const struct ListTestCase {
   const char* name;
   const char* raw;
-  const absl::optional<List> expected;  // nullopt if parse error is expected.
+  const std::optional<List> expected;  // nullopt if parse error is expected.
   const char* canonical;  // nullptr if parse error is expected, or if canonical
                           // format is identical to raw.
 } list_test_cases[] = {
@@ -214,7 +215,7 @@
        {{{Integer(42L), {}}, {Integer(43L), {}}}, {BooleanParam("b", true)}}}},
      nullptr},
     {"extra whitespace before semicolon in parameters on inner list member",
-     "(a;b ;c b)", absl::nullopt, nullptr},
+     "(a;b ;c b)", std::nullopt, nullptr},
     {"extra whitespace between parameters on inner list member",
      "(a;b; c b)",
      {{{{{Token("a"), {BooleanParam("b", true), BooleanParam("c", true)}},
@@ -222,7 +223,7 @@
         {}}}},
      "(a;b;c b)"},
     {"extra whitespace before semicolon in parameters on inner list",
-     "(a b);c ;d, (e)", absl::nullopt, nullptr},
+     "(a b);c ;d, (e)", std::nullopt, nullptr},
     {"extra whitespace between parameters on inner list",
      "(a b);c; d, (e)",
      {{{{{Token("a"), {}}, {Token("b"), {}}},
@@ -235,7 +236,7 @@
 const struct DictionaryTestCase {
   const char* name;
   const char* raw;
-  const absl::optional<Dictionary>
+  const std::optional<Dictionary>
       expected;           // nullopt if parse error is expected.
   const char* canonical;  // nullptr if parse error is expected, or if canonical
                           // format is identical to raw.
@@ -281,7 +282,7 @@
 TEST(StructuredHeaderTest, ParseBareItem) {
   for (const auto& c : item_test_cases) {
     SCOPED_TRACE(c.name);
-    absl::optional<Item> result = ParseBareItem(c.raw);
+    std::optional<Item> result = ParseBareItem(c.raw);
     EXPECT_EQ(result, c.expected);
   }
 }
@@ -290,7 +291,7 @@
 TEST(StructuredHeaderTest, ParseItem) {
   for (const auto& c : parameterized_item_test_cases) {
     SCOPED_TRACE(c.name);
-    absl::optional<ParameterizedItem> result = ParseItem(c.raw);
+    std::optional<ParameterizedItem> result = ParseItem(c.raw);
     EXPECT_EQ(result, c.expected);
   }
 }
@@ -302,7 +303,7 @@
 TEST(StructuredHeaderTest, ParseSH09Item) {
   for (const auto& c : sh09_item_test_cases) {
     SCOPED_TRACE(c.name);
-    absl::optional<ListOfLists> result = ParseListOfLists(c.raw);
+    std::optional<ListOfLists> result = ParseListOfLists(c.raw);
     if (c.expected.has_value()) {
       EXPECT_TRUE(result.has_value());
       EXPECT_EQ(result->size(), 1UL);
@@ -320,7 +321,7 @@
 TEST(StructuredHeaderTest, SH09HighPrecisionFloats) {
   // These values are exactly representable in binary floating point, so no
   // accuracy issues are expected in this test.
-  absl::optional<ListOfLists> result =
+  std::optional<ListOfLists> result =
       ParseListOfLists("1.03125;-1.03125;12345678901234.5;-12345678901234.5");
   ASSERT_TRUE(result.has_value());
   EXPECT_EQ(*result,
@@ -365,7 +366,7 @@
   };
   for (const auto& c : cases) {
     SCOPED_TRACE(c.name);
-    absl::optional<ListOfLists> result = ParseListOfLists(c.raw);
+    std::optional<ListOfLists> result = ParseListOfLists(c.raw);
     if (!c.expected.empty()) {
       EXPECT_TRUE(result.has_value());
       EXPECT_EQ(*result, c.expected);
@@ -417,7 +418,7 @@
   };
   for (const auto& c : cases) {
     SCOPED_TRACE(c.name);
-    absl::optional<ParameterisedList> result = ParseParameterisedList(c.raw);
+    std::optional<ParameterisedList> result = ParseParameterisedList(c.raw);
     if (c.expected.empty()) {
       EXPECT_FALSE(result.has_value());
       continue;
@@ -436,7 +437,7 @@
 TEST(StructuredHeaderTest, ParseList) {
   for (const auto& c : list_test_cases) {
     SCOPED_TRACE(c.name);
-    absl::optional<List> result = ParseList(c.raw);
+    std::optional<List> result = ParseList(c.raw);
     EXPECT_EQ(result, c.expected);
   }
 }
@@ -445,7 +446,7 @@
 TEST(StructuredHeaderTest, ParseDictionary) {
   for (const auto& c : dictionary_test_cases) {
     SCOPED_TRACE(c.name);
-    absl::optional<Dictionary> result = ParseDictionary(c.raw);
+    std::optional<Dictionary> result = ParseDictionary(c.raw);
     EXPECT_EQ(result, c.expected);
   }
 }
@@ -456,7 +457,7 @@
   for (const auto& c : item_test_cases) {
     SCOPED_TRACE(c.name);
     if (c.expected) {
-      absl::optional<std::string> result = SerializeItem(*c.expected);
+      std::optional<std::string> result = SerializeItem(*c.expected);
       EXPECT_TRUE(result.has_value());
       EXPECT_EQ(result.value(), std::string(c.canonical ? c.canonical : c.raw));
     }
@@ -467,7 +468,7 @@
   for (const auto& c : parameterized_item_test_cases) {
     SCOPED_TRACE(c.name);
     if (c.expected) {
-      absl::optional<std::string> result = SerializeItem(*c.expected);
+      std::optional<std::string> result = SerializeItem(*c.expected);
       EXPECT_TRUE(result.has_value());
       EXPECT_EQ(result.value(), std::string(c.canonical ? c.canonical : c.raw));
     }
@@ -504,7 +505,7 @@
   };
   for (const auto& bad_token : bad_tokens) {
     SCOPED_TRACE(bad_token.name);
-    absl::optional<std::string> serialization =
+    std::optional<std::string> serialization =
         SerializeItem(Token(bad_token.value));
     EXPECT_FALSE(serialization.has_value()) << *serialization;
   }
@@ -536,7 +537,7 @@
   };
   for (const auto& bad_key : bad_keys) {
     SCOPED_TRACE(bad_key.name);
-    absl::optional<std::string> serialization =
+    std::optional<std::string> serialization =
         SerializeItem(ParameterizedItem("a", {{bad_key.value, "a"}}));
     EXPECT_FALSE(serialization.has_value()) << *serialization;
   }
@@ -557,7 +558,7 @@
   };
   for (const auto& bad_string : bad_strings) {
     SCOPED_TRACE(bad_string.name);
-    absl::optional<std::string> serialization =
+    std::optional<std::string> serialization =
         SerializeItem(Item(bad_string.value));
     EXPECT_FALSE(serialization.has_value()) << *serialization;
   }
@@ -616,7 +617,7 @@
   };
   for (const auto& test_case : float_test_cases) {
     SCOPED_TRACE(test_case.name);
-    absl::optional<std::string> serialization =
+    std::optional<std::string> serialization =
         SerializeItem(Item(test_case.value));
     EXPECT_TRUE(serialization.has_value());
     EXPECT_EQ(*serialization, test_case.canonical);
@@ -627,7 +628,7 @@
   for (const auto& c : list_test_cases) {
     SCOPED_TRACE(c.name);
     if (c.expected) {
-      absl::optional<std::string> result = SerializeList(*c.expected);
+      std::optional<std::string> result = SerializeList(*c.expected);
       EXPECT_TRUE(result.has_value());
       EXPECT_EQ(result.value(), std::string(c.canonical ? c.canonical : c.raw));
     }
@@ -654,7 +655,7 @@
   };
   for (const auto& bad_list : bad_lists) {
     SCOPED_TRACE(bad_list.name);
-    absl::optional<std::string> serialization = SerializeList(bad_list.value);
+    std::optional<std::string> serialization = SerializeList(bad_list.value);
     EXPECT_FALSE(serialization.has_value()) << *serialization;
   }
 }
@@ -663,7 +664,7 @@
   for (const auto& c : dictionary_test_cases) {
     SCOPED_TRACE(c.name);
     if (c.expected) {
-      absl::optional<std::string> result = SerializeDictionary(*c.expected);
+      std::optional<std::string> result = SerializeDictionary(*c.expected);
       EXPECT_TRUE(result.has_value());
       EXPECT_EQ(result.value(), std::string(c.canonical ? c.canonical : c.raw));
     }
@@ -752,7 +753,7 @@
   };
   for (const auto& bad_dictionary : bad_dictionaries) {
     SCOPED_TRACE(bad_dictionary.name);
-    absl::optional<std::string> serialization =
+    std::optional<std::string> serialization =
         SerializeDictionary(bad_dictionary.value);
     EXPECT_FALSE(serialization.has_value()) << *serialization;
   }
diff --git a/quiche/common/wire_serialization.h b/quiche/common/wire_serialization.h
index 4cb482b..81e0760 100644
--- a/quiche/common/wire_serialization.h
+++ b/quiche/common/wire_serialization.h
@@ -64,7 +64,6 @@
 #include "absl/status/status.h"
 #include "absl/status/statusor.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_logging.h"
 #include "quiche/common/quiche_buffer_allocator.h"
 #include "quiche/common/quiche_data_writer.h"
@@ -232,17 +231,17 @@
 // Represents varint62-prefixed strings.
 using WireStringWithVarInt62Length = WireStringWithLengthPrefix<WireVarInt62>;
 
-// Allows absl::optional to be used with this API. For instance, if the spec
+// Allows std::optional to be used with this API. For instance, if the spec
 // defines
 //   [Context ID (i)]
-// and the value is stored as absl::optional<uint64> context_id, this can be
+// and the value is stored as std::optional<uint64> context_id, this can be
 // recorded as
 //   WireOptional<WireVarInt62>(context_id)
 // When optional is absent, nothing is written onto the wire.
 template <typename WireType, typename InnerType = typename WireType::DataType>
 class QUICHE_EXPORT WireOptional {
  public:
-  using DataType = absl::optional<InnerType>;
+  using DataType = std::optional<InnerType>;
   using Status = SerializeIntoWriterStatus<WireType>;
 
   explicit WireOptional(DataType value) { value_ = value; }
diff --git a/quiche/common/wire_serialization_test.cc b/quiche/common/wire_serialization_test.cc
index 9abdda9..6c8267f 100644
--- a/quiche/common/wire_serialization_test.cc
+++ b/quiche/common/wire_serialization_test.cc
@@ -5,12 +5,12 @@
 #include "quiche/common/wire_serialization.h"
 
 #include <limits>
+#include <optional>
 
 #include "absl/status/status.h"
 #include "absl/status/statusor.h"
 #include "absl/strings/escaping.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_expect_bug.h"
 #include "quiche/common/platform/api/quiche_test.h"
 #include "quiche/common/quiche_buffer_allocator.h"
@@ -101,16 +101,16 @@
 }
 
 TEST(SerializationTest, SerializeOptionalValues) {
-  absl::optional<uint8_t> has_no_value;
-  absl::optional<uint8_t> has_value = 0x42;
+  std::optional<uint8_t> has_no_value;
+  std::optional<uint8_t> has_value = 0x42;
   ExpectEncodingHex("optional without value", "00", WireUint8(0),
                     WireOptional<WireUint8>(has_no_value));
   ExpectEncodingHex("optional with value", "0142", WireUint8(1),
                     WireOptional<WireUint8>(has_value));
   ExpectEncodingHex("empty data", "", WireOptional<WireUint8>(has_no_value));
 
-  absl::optional<std::string> has_no_string;
-  absl::optional<std::string> has_string = "\x42";
+  std::optional<std::string> has_no_string;
+  std::optional<std::string> has_string = "\x42";
   ExpectEncodingHex("optional no string", "",
                     WireOptional<WireStringWithVarInt62Length>(has_no_string));
   ExpectEncodingHex("optional string", "0142",
diff --git a/quiche/http2/adapter/header_validator.h b/quiche/http2/adapter/header_validator.h
index f1c8497..ef55948 100644
--- a/quiche/http2/adapter/header_validator.h
+++ b/quiche/http2/adapter/header_validator.h
@@ -2,11 +2,11 @@
 #define QUICHE_HTTP2_ADAPTER_HEADER_VALIDATOR_H_
 
 #include <bitset>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/http2/adapter/header_validator_base.h"
 #include "quiche/common/platform/api/quiche_export.h"
 
diff --git a/quiche/http2/adapter/header_validator_base.h b/quiche/http2/adapter/header_validator_base.h
index 703d319..416c3aa 100644
--- a/quiche/http2/adapter/header_validator_base.h
+++ b/quiche/http2/adapter/header_validator_base.h
@@ -1,11 +1,12 @@
 #ifndef QUICHE_HTTP2_ADAPTER_HEADER_VALIDATOR_BASE_H_
 #define QUICHE_HTTP2_ADAPTER_HEADER_VALIDATOR_BASE_H_
 
+#include <cstddef>
 #include <cstdint>
+#include <optional>
 #include <string>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_export.h"
 
 namespace http2 {
@@ -31,7 +32,7 @@
 
   virtual void StartHeaderBlock() {
     status_.clear();
-    content_length_ = absl::nullopt;
+    content_length_ = std::nullopt;
   }
 
   enum HeaderStatus {
@@ -49,7 +50,7 @@
   // For responses, returns the value of the ":status" header, if present.
   absl::string_view status_header() const { return status_; }
 
-  absl::optional<size_t> content_length() const { return content_length_; }
+  std::optional<size_t> content_length() const { return content_length_; }
 
   void SetMaxFieldSize(uint32_t field_size) { max_field_size_ = field_size; }
   void SetObsTextOption(ObsTextOption option) { obs_text_option_ = option; }
@@ -69,8 +70,8 @@
 
  protected:
   std::string status_;
-  absl::optional<size_t> max_field_size_;
-  absl::optional<size_t> content_length_;
+  std::optional<size_t> max_field_size_;
+  std::optional<size_t> content_length_;
   ObsTextOption obs_text_option_ = ObsTextOption::kDisallow;
   bool allow_extended_connect_ = false;
   bool validate_path_ = false;
diff --git a/quiche/http2/adapter/header_validator_test.cc b/quiche/http2/adapter/header_validator_test.cc
index f465528..e3a4c68 100644
--- a/quiche/http2/adapter/header_validator_test.cc
+++ b/quiche/http2/adapter/header_validator_test.cc
@@ -1,10 +1,10 @@
 #include "quiche/http2/adapter/header_validator.h"
 
+#include <optional>
 #include <utility>
 #include <vector>
 
 #include "absl/strings/str_cat.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_test.h"
 
 namespace http2 {
@@ -721,13 +721,13 @@
   HeaderValidator v;
 
   v.StartHeaderBlock();
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(HeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("content-length", "41"));
   EXPECT_THAT(v.content_length(), Optional(41));
 
   v.StartHeaderBlock();
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(HeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("content-length", "42"));
   EXPECT_THAT(v.content_length(), Optional(42));
@@ -737,16 +737,16 @@
   HeaderValidator v;
 
   v.StartHeaderBlock();
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
             v.ValidateSingleHeader("content-length", ""));
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
             v.ValidateSingleHeader("content-length", "nan"));
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(HeaderValidator::HEADER_FIELD_INVALID,
             v.ValidateSingleHeader("content-length", "-42"));
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   // End on a positive note.
   EXPECT_EQ(HeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("content-length", "42"));
@@ -815,7 +815,7 @@
 TEST(HeaderValidatorTest, MixedCaseContentLength) {
   HeaderValidator v;
   v.SetAllowUppercaseInHeaderNames();
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(HeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("Content-Length", "42"));
   EXPECT_THAT(v.content_length(), Optional(42));
diff --git a/quiche/http2/adapter/http2_adapter.h b/quiche/http2/adapter/http2_adapter.h
index fb9df13..0ab0a72 100644
--- a/quiche/http2/adapter/http2_adapter.h
+++ b/quiche/http2/adapter/http2_adapter.h
@@ -4,7 +4,6 @@
 #include <cstdint>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/http2/adapter/data_source.h"
 #include "quiche/http2/adapter/http2_protocol.h"
diff --git a/quiche/http2/adapter/noop_header_validator_test.cc b/quiche/http2/adapter/noop_header_validator_test.cc
index 6340c60..65cc763 100644
--- a/quiche/http2/adapter/noop_header_validator_test.cc
+++ b/quiche/http2/adapter/noop_header_validator_test.cc
@@ -1,10 +1,10 @@
 #include "quiche/http2/adapter/noop_header_validator.h"
 
+#include <optional>
 #include <utility>
 #include <vector>
 
 #include "absl/strings/str_cat.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_test.h"
 
 namespace http2 {
@@ -457,35 +457,35 @@
   NoopHeaderValidator v;
 
   v.StartHeaderBlock();
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(NoopHeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("content-length", "41"));
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
 
   v.StartHeaderBlock();
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(NoopHeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("content-length", "42"));
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
 }
 
 TEST(NoopHeaderValidatorTest, InvalidContentLength) {
   NoopHeaderValidator v;
 
   v.StartHeaderBlock();
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(NoopHeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("content-length", ""));
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(NoopHeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("content-length", "nan"));
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(NoopHeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("content-length", "-42"));
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
   EXPECT_EQ(NoopHeaderValidator::HEADER_OK,
             v.ValidateSingleHeader("content-length", "42"));
-  EXPECT_EQ(v.content_length(), absl::nullopt);
+  EXPECT_EQ(v.content_length(), std::nullopt);
 }
 
 TEST(NoopHeaderValidatorTest, TeHeader) {
diff --git a/quiche/http2/adapter/oghttp2_session.cc b/quiche/http2/adapter/oghttp2_session.cc
index fdf308e..d91d9dc 100644
--- a/quiche/http2/adapter/oghttp2_session.cc
+++ b/quiche/http2/adapter/oghttp2_session.cc
@@ -2,6 +2,7 @@
 
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <utility>
 #include <vector>
 
@@ -739,7 +740,7 @@
       if (is_settings_ack && encoder_header_table_capacity_when_acking_) {
         framer_.UpdateHeaderEncoderTableSize(
             *encoder_header_table_capacity_when_acking_);
-        encoder_header_table_capacity_when_acking_ = absl::nullopt;
+        encoder_header_table_capacity_when_acking_ = std::nullopt;
       } else if (!is_settings_ack) {
         sent_non_ack_settings_ = true;
       }
@@ -1855,7 +1856,7 @@
 }
 
 HeaderType OgHttp2Session::NextHeaderType(
-    absl::optional<HeaderType> current_type) {
+    std::optional<HeaderType> current_type) {
   if (IsServerSession()) {
     if (!current_type) {
       return HeaderType::REQUEST;
diff --git a/quiche/http2/adapter/oghttp2_session.h b/quiche/http2/adapter/oghttp2_session.h
index 96b50e9..16e4db4 100644
--- a/quiche/http2/adapter/oghttp2_session.h
+++ b/quiche/http2/adapter/oghttp2_session.h
@@ -5,10 +5,10 @@
 #include <limits>
 #include <list>
 #include <memory>
+#include <optional>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/variant.h"
 #include "quiche/http2/adapter/data_source.h"
 #include "quiche/http2/adapter/event_forwarder.h"
@@ -47,14 +47,14 @@
     // The perspective of this session.
     Perspective perspective = Perspective::kClient;
     // The maximum HPACK table size to use.
-    absl::optional<size_t> max_hpack_encoding_table_capacity = absl::nullopt;
+    std::optional<size_t> max_hpack_encoding_table_capacity;
     // The maximum number of decoded header bytes that a stream can receive.
-    absl::optional<uint32_t> max_header_list_bytes = absl::nullopt;
+    std::optional<uint32_t> max_header_list_bytes = std::nullopt;
     // The maximum size of an individual header field, including name and value.
-    absl::optional<uint32_t> max_header_field_size = absl::nullopt;
+    std::optional<uint32_t> max_header_field_size = std::nullopt;
     // The assumed initial value of the remote endpoint's max concurrent streams
     // setting.
-    absl::optional<uint32_t> remote_max_concurrent_streams = absl::nullopt;
+    std::optional<uint32_t> remote_max_concurrent_streams = std::nullopt;
     // Whether to automatically send PING acks when receiving a PING.
     bool auto_ping_ack = true;
     // Whether (as server) to send a RST_STREAM NO_ERROR when sending a fin on
@@ -245,8 +245,8 @@
     std::unique_ptr<spdy::Http2HeaderBlock> trailers;
     void* user_data = nullptr;
     int32_t send_window;
-    absl::optional<HeaderType> received_header_type;
-    absl::optional<size_t> remaining_content_length;
+    std::optional<HeaderType> received_header_type;
+    std::optional<size_t> remaining_content_length;
     bool half_closed_local = false;
     bool half_closed_remote = false;
     // Indicates that `outbound_body` temporarily cannot produce data.
@@ -286,7 +286,7 @@
                     type_ == HeaderType::RESPONSE_100);
       return validator_->status_header();
     }
-    absl::optional<size_t> content_length() const {
+    std::optional<size_t> content_length() const {
       return validator_->content_length();
     }
     void SetAllowExtendedConnect() { validator_->SetAllowExtendedConnect(); }
@@ -410,7 +410,7 @@
   void CloseStream(Http2StreamId stream_id, Http2ErrorCode error_code);
 
   // Calculates the next expected header type for a stream in a given state.
-  HeaderType NextHeaderType(absl::optional<HeaderType> current_type);
+  HeaderType NextHeaderType(std::optional<HeaderType> current_type);
 
   // Returns true if the session can create a new stream.
   bool CanCreateStream() const;
@@ -542,7 +542,7 @@
   // acking SETTINGS from the peer. Only contains a value if the peer advertises
   // a larger table capacity than currently used; a smaller value can safely be
   // applied immediately upon receipt.
-  absl::optional<uint32_t> encoder_header_table_capacity_when_acking_;
+  std::optional<uint32_t> encoder_header_table_capacity_when_acking_;
 
   uint8_t current_frame_type_ = 0;
 
diff --git a/quiche/http2/adapter/test_frame_sequence.cc b/quiche/http2/adapter/test_frame_sequence.cc
index d73f036..fab4083 100644
--- a/quiche/http2/adapter/test_frame_sequence.cc
+++ b/quiche/http2/adapter/test_frame_sequence.cc
@@ -1,6 +1,7 @@
 #include "quiche/http2/adapter/test_frame_sequence.h"
 
 #include <memory>
+#include <optional>
 
 #include "quiche/http2/adapter/http2_util.h"
 #include "quiche/http2/adapter/oghttp2_util.h"
@@ -33,7 +34,7 @@
 
 TestFrameSequence& TestFrameSequence::Data(Http2StreamId stream_id,
                                            absl::string_view payload, bool fin,
-                                           absl::optional<int> padding_length) {
+                                           std::optional<int> padding_length) {
   auto data = std::make_unique<spdy::SpdyDataIR>(stream_id, payload);
   data->set_fin(fin);
   if (padding_length) {
diff --git a/quiche/http2/adapter/test_frame_sequence.h b/quiche/http2/adapter/test_frame_sequence.h
index 953aed1..47f8199 100644
--- a/quiche/http2/adapter/test_frame_sequence.h
+++ b/quiche/http2/adapter/test_frame_sequence.h
@@ -28,7 +28,7 @@
       absl::Span<const Http2Setting> settings = {});
   TestFrameSequence& Data(Http2StreamId stream_id, absl::string_view payload,
                           bool fin = false,
-                          absl::optional<int> padding_length = absl::nullopt);
+                          std::optional<int> padding_length = std::nullopt);
   TestFrameSequence& RstStream(Http2StreamId stream_id, Http2ErrorCode error);
   TestFrameSequence& Settings(absl::Span<const Http2Setting> settings);
   TestFrameSequence& SettingsAck();
diff --git a/quiche/http2/adapter/test_utils.cc b/quiche/http2/adapter/test_utils.cc
index f85d5a3..2cdd560 100644
--- a/quiche/http2/adapter/test_utils.cc
+++ b/quiche/http2/adapter/test_utils.cc
@@ -1,11 +1,13 @@
 #include "quiche/http2/adapter/test_utils.h"
 
+#include <optional>
 #include <ostream>
 
 #include "absl/strings/str_format.h"
 #include "quiche/http2/adapter/http2_visitor_interface.h"
 #include "quiche/common/quiche_data_reader.h"
 #include "quiche/spdy/core/hpack/hpack_encoder.h"
+#include "quiche/spdy/core/spdy_protocol.h"
 
 namespace http2 {
 namespace adapter {
@@ -104,7 +106,7 @@
 namespace {
 
 using TypeAndOptionalLength =
-    std::pair<spdy::SpdyFrameType, absl::optional<size_t>>;
+    std::pair<spdy::SpdyFrameType, std::optional<size_t>>;
 
 std::ostream& operator<<(
     std::ostream& os,
@@ -152,7 +154,7 @@
   }
 
   bool MatchAndExplainOneFrame(spdy::SpdyFrameType expected_type,
-                               absl::optional<size_t> expected_length,
+                               std::optional<size_t> expected_length,
                                quiche::QuicheDataReader* reader,
                                testing::MatchResultListener* listener) const {
     uint32_t payload_length;
@@ -203,18 +205,18 @@
 }  // namespace
 
 testing::Matcher<absl::string_view> EqualsFrames(
-    std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>>
+    std::vector<std::pair<spdy::SpdyFrameType, std::optional<size_t>>>
         types_and_lengths) {
   return MakeMatcher(new SpdyControlFrameMatcher(std::move(types_and_lengths)));
 }
 
 testing::Matcher<absl::string_view> EqualsFrames(
     std::vector<spdy::SpdyFrameType> types) {
-  std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>>
+  std::vector<std::pair<spdy::SpdyFrameType, std::optional<size_t>>>
       types_and_lengths;
   types_and_lengths.reserve(types.size());
   for (spdy::SpdyFrameType type : types) {
-    types_and_lengths.push_back({type, absl::nullopt});
+    types_and_lengths.push_back({type, std::nullopt});
   }
   return MakeMatcher(new SpdyControlFrameMatcher(std::move(types_and_lengths)));
 }
diff --git a/quiche/http2/adapter/test_utils.h b/quiche/http2/adapter/test_utils.h
index cd1aa8a..ceda74f 100644
--- a/quiche/http2/adapter/test_utils.h
+++ b/quiche/http2/adapter/test_utils.h
@@ -125,7 +125,7 @@
 
 // Requires that frames match both types and lengths.
 testing::Matcher<absl::string_view> EqualsFrames(
-    std::vector<std::pair<spdy::SpdyFrameType, absl::optional<size_t>>>
+    std::vector<std::pair<spdy::SpdyFrameType, std::optional<size_t>>>
         types_and_lengths);
 
 // Requires that frames match the specified types.
diff --git a/quiche/http2/adapter/test_utils_test.cc b/quiche/http2/adapter/test_utils_test.cc
index 0ea44dc..9abeead 100644
--- a/quiche/http2/adapter/test_utils_test.cc
+++ b/quiche/http2/adapter/test_utils_test.cc
@@ -1,5 +1,7 @@
 #include "quiche/http2/adapter/test_utils.h"
 
+#include <optional>
+
 #include "quiche/common/platform/api/quiche_test.h"
 #include "quiche/spdy/core/spdy_framer.h"
 
@@ -35,12 +37,12 @@
 
   spdy::SpdyRstStreamIR rst_stream{7, spdy::ERROR_CODE_REFUSED_STREAM};
   EXPECT_THAT(framer.SerializeFrame(rst_stream),
-              EqualsFrames({{spdy::SpdyFrameType::RST_STREAM, absl::nullopt}}));
+              EqualsFrames({{spdy::SpdyFrameType::RST_STREAM, std::nullopt}}));
 
   spdy::SpdyGoAwayIR goaway{13, spdy::ERROR_CODE_ENHANCE_YOUR_CALM,
                             "Consider taking some deep breaths."};
   EXPECT_THAT(framer.SerializeFrame(goaway),
-              EqualsFrames({{spdy::SpdyFrameType::GOAWAY, absl::nullopt}}));
+              EqualsFrames({{spdy::SpdyFrameType::GOAWAY, std::nullopt}}));
 
   spdy::Http2HeaderBlock block;
   block[":method"] = "GET";
@@ -48,7 +50,7 @@
   block[":authority"] = "example.com";
   spdy::SpdyHeadersIR headers{17, std::move(block)};
   EXPECT_THAT(framer.SerializeFrame(headers),
-              EqualsFrames({{spdy::SpdyFrameType::HEADERS, absl::nullopt}}));
+              EqualsFrames({{spdy::SpdyFrameType::HEADERS, std::nullopt}}));
 }
 
 TEST(EqualsFrames, MultipleFrames) {
@@ -75,17 +77,17 @@
                    absl::string_view(framer.SerializeFrame(headers)));
   absl::string_view frame_sequence_view = frame_sequence;
   EXPECT_THAT(frame_sequence,
-              EqualsFrames({{spdy::SpdyFrameType::PING, absl::nullopt},
-                            {spdy::SpdyFrameType::WINDOW_UPDATE, absl::nullopt},
+              EqualsFrames({{spdy::SpdyFrameType::PING, std::nullopt},
+                            {spdy::SpdyFrameType::WINDOW_UPDATE, std::nullopt},
                             {spdy::SpdyFrameType::DATA, 25},
-                            {spdy::SpdyFrameType::RST_STREAM, absl::nullopt},
+                            {spdy::SpdyFrameType::RST_STREAM, std::nullopt},
                             {spdy::SpdyFrameType::GOAWAY, 42},
                             {spdy::SpdyFrameType::HEADERS, 19}}));
   EXPECT_THAT(frame_sequence_view,
-              EqualsFrames({{spdy::SpdyFrameType::PING, absl::nullopt},
-                            {spdy::SpdyFrameType::WINDOW_UPDATE, absl::nullopt},
+              EqualsFrames({{spdy::SpdyFrameType::PING, std::nullopt},
+                            {spdy::SpdyFrameType::WINDOW_UPDATE, std::nullopt},
                             {spdy::SpdyFrameType::DATA, 25},
-                            {spdy::SpdyFrameType::RST_STREAM, absl::nullopt},
+                            {spdy::SpdyFrameType::RST_STREAM, std::nullopt},
                             {spdy::SpdyFrameType::GOAWAY, 42},
                             {spdy::SpdyFrameType::HEADERS, 19}}));
   EXPECT_THAT(
diff --git a/quiche/http2/core/priority_write_scheduler.h b/quiche/http2/core/priority_write_scheduler.h
index d63a316..0e33111 100644
--- a/quiche/http2/core/priority_write_scheduler.h
+++ b/quiche/http2/core/priority_write_scheduler.h
@@ -9,6 +9,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <string>
 #include <tuple>
 #include <utility>
@@ -17,7 +18,6 @@
 #include "absl/container/flat_hash_map.h"
 #include "absl/strings/str_cat.h"
 #include "absl/time/time.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_bug_tracker.h"
 #include "quiche/common/platform/api/quiche_export.h"
 #include "quiche/common/platform/api/quiche_logging.h"
@@ -171,14 +171,14 @@
   // event.
   //
   // Preconditions: `stream_id` should be registered.
-  absl::optional<absl::Time> GetLatestEventWithPriority(
+  std::optional<absl::Time> GetLatestEventWithPriority(
       StreamIdType stream_id) const {
     auto it = stream_infos_.find(stream_id);
     if (it == stream_infos_.end()) {
       QUICHE_BUG(spdy_bug_19_5) << "Stream " << stream_id << " not registered";
-      return absl::nullopt;
+      return std::nullopt;
     }
-    absl::optional<absl::Time> last_event_time;
+    std::optional<absl::Time> last_event_time;
     const StreamInfo* const stream_info = it->second.get();
     for (int p = kHighestPriority;
          p < PriorityTypeToInt()(stream_info->priority); ++p) {
@@ -347,7 +347,7 @@
     // IDs of streams that are ready to write.
     ReadyList ready_list;
     // Time of latest write event for stream of this priority.
-    absl::optional<absl::Time> last_event_time;
+    std::optional<absl::Time> last_event_time;
   };
 
   // Use std::unique_ptr, because absl::flat_hash_map does not have pointer
diff --git a/quiche/http2/test_tools/frame_parts.cc b/quiche/http2/test_tools/frame_parts.cc
index 4792e27..824c864 100644
--- a/quiche/http2/test_tools/frame_parts.cc
+++ b/quiche/http2/test_tools/frame_parts.cc
@@ -4,6 +4,7 @@
 
 #include "quiche/http2/test_tools/frame_parts.h"
 
+#include <optional>
 #include <type_traits>
 
 #include "absl/strings/escaping.h"
@@ -534,7 +535,7 @@
 
 AssertionResult FrameParts::AppendString(absl::string_view source,
                                          std::string* target,
-                                         absl::optional<size_t>* opt_length) {
+                                         std::optional<size_t>* opt_length) {
   target->append(source.data(), source.size());
   if (opt_length != nullptr) {
     HTTP2_VERIFY_TRUE(*opt_length) << "Length is not set yet\n" << *this;
diff --git a/quiche/http2/test_tools/frame_parts.h b/quiche/http2/test_tools/frame_parts.h
index d116228..9ae5185 100644
--- a/quiche/http2/test_tools/frame_parts.h
+++ b/quiche/http2/test_tools/frame_parts.h
@@ -13,11 +13,11 @@
 #include <stddef.h>
 
 #include <cstdint>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/http2/decoder/http2_frame_decoder_listener.h"
 #include "quiche/http2/http2_constants.h"
 #include "quiche/http2/http2_structures.h"
@@ -118,74 +118,74 @@
 
   const Http2FrameHeader& GetFrameHeader() const { return frame_header_; }
 
-  absl::optional<Http2PriorityFields> GetOptPriority() const {
+  std::optional<Http2PriorityFields> GetOptPriority() const {
     return opt_priority_;
   }
-  absl::optional<Http2ErrorCode> GetOptRstStreamErrorCode() const {
+  std::optional<Http2ErrorCode> GetOptRstStreamErrorCode() const {
     return opt_rst_stream_error_code_;
   }
-  absl::optional<Http2PushPromiseFields> GetOptPushPromise() const {
+  std::optional<Http2PushPromiseFields> GetOptPushPromise() const {
     return opt_push_promise_;
   }
-  absl::optional<Http2PingFields> GetOptPing() const { return opt_ping_; }
-  absl::optional<Http2GoAwayFields> GetOptGoaway() const { return opt_goaway_; }
-  absl::optional<size_t> GetOptPadLength() const { return opt_pad_length_; }
-  absl::optional<size_t> GetOptPayloadLength() const {
+  std::optional<Http2PingFields> GetOptPing() const { return opt_ping_; }
+  std::optional<Http2GoAwayFields> GetOptGoaway() const { return opt_goaway_; }
+  std::optional<size_t> GetOptPadLength() const { return opt_pad_length_; }
+  std::optional<size_t> GetOptPayloadLength() const {
     return opt_payload_length_;
   }
-  absl::optional<size_t> GetOptMissingLength() const {
+  std::optional<size_t> GetOptMissingLength() const {
     return opt_missing_length_;
   }
-  absl::optional<size_t> GetOptAltsvcOriginLength() const {
+  std::optional<size_t> GetOptAltsvcOriginLength() const {
     return opt_altsvc_origin_length_;
   }
-  absl::optional<size_t> GetOptAltsvcValueLength() const {
+  std::optional<size_t> GetOptAltsvcValueLength() const {
     return opt_altsvc_value_length_;
   }
-  absl::optional<size_t> GetOptWindowUpdateIncrement() const {
+  std::optional<size_t> GetOptWindowUpdateIncrement() const {
     return opt_window_update_increment_;
   }
   bool GetHasFrameSizeError() const { return has_frame_size_error_; }
 
-  void SetOptPriority(absl::optional<Http2PriorityFields> opt_priority) {
+  void SetOptPriority(std::optional<Http2PriorityFields> opt_priority) {
     opt_priority_ = opt_priority;
   }
   void SetOptRstStreamErrorCode(
-      absl::optional<Http2ErrorCode> opt_rst_stream_error_code) {
+      std::optional<Http2ErrorCode> opt_rst_stream_error_code) {
     opt_rst_stream_error_code_ = opt_rst_stream_error_code;
   }
   void SetOptPushPromise(
-      absl::optional<Http2PushPromiseFields> opt_push_promise) {
+      std::optional<Http2PushPromiseFields> opt_push_promise) {
     opt_push_promise_ = opt_push_promise;
   }
-  void SetOptPing(absl::optional<Http2PingFields> opt_ping) {
+  void SetOptPing(std::optional<Http2PingFields> opt_ping) {
     opt_ping_ = opt_ping;
   }
-  void SetOptGoaway(absl::optional<Http2GoAwayFields> opt_goaway) {
+  void SetOptGoaway(std::optional<Http2GoAwayFields> opt_goaway) {
     opt_goaway_ = opt_goaway;
   }
-  void SetOptPadLength(absl::optional<size_t> opt_pad_length) {
+  void SetOptPadLength(std::optional<size_t> opt_pad_length) {
     opt_pad_length_ = opt_pad_length;
   }
-  void SetOptPayloadLength(absl::optional<size_t> opt_payload_length) {
+  void SetOptPayloadLength(std::optional<size_t> opt_payload_length) {
     opt_payload_length_ = opt_payload_length;
   }
-  void SetOptMissingLength(absl::optional<size_t> opt_missing_length) {
+  void SetOptMissingLength(std::optional<size_t> opt_missing_length) {
     opt_missing_length_ = opt_missing_length;
   }
   void SetOptAltsvcOriginLength(
-      absl::optional<size_t> opt_altsvc_origin_length) {
+      std::optional<size_t> opt_altsvc_origin_length) {
     opt_altsvc_origin_length_ = opt_altsvc_origin_length;
   }
-  void SetOptAltsvcValueLength(absl::optional<size_t> opt_altsvc_value_length) {
+  void SetOptAltsvcValueLength(std::optional<size_t> opt_altsvc_value_length) {
     opt_altsvc_value_length_ = opt_altsvc_value_length;
   }
   void SetOptWindowUpdateIncrement(
-      absl::optional<size_t> opt_window_update_increment) {
+      std::optional<size_t> opt_window_update_increment) {
     opt_window_update_increment_ = opt_window_update_increment;
   }
   void SetOptPriorityUpdate(
-      absl::optional<Http2PriorityUpdateFields> priority_update) {
+      std::optional<Http2PriorityUpdateFields> priority_update) {
     opt_priority_update_ = priority_update;
   }
 
@@ -216,7 +216,7 @@
   // called), and that target is not longer than opt_length->value().
   ::testing::AssertionResult AppendString(absl::string_view source,
                                           std::string* target,
-                                          absl::optional<size_t>* opt_length);
+                                          std::optional<size_t>* opt_length);
 
   const Http2FrameHeader frame_header_;
 
@@ -225,20 +225,20 @@
   std::string altsvc_origin_;
   std::string altsvc_value_;
 
-  absl::optional<Http2PriorityFields> opt_priority_;
-  absl::optional<Http2ErrorCode> opt_rst_stream_error_code_;
-  absl::optional<Http2PushPromiseFields> opt_push_promise_;
-  absl::optional<Http2PingFields> opt_ping_;
-  absl::optional<Http2GoAwayFields> opt_goaway_;
-  absl::optional<Http2PriorityUpdateFields> opt_priority_update_;
+  std::optional<Http2PriorityFields> opt_priority_;
+  std::optional<Http2ErrorCode> opt_rst_stream_error_code_;
+  std::optional<Http2PushPromiseFields> opt_push_promise_;
+  std::optional<Http2PingFields> opt_ping_;
+  std::optional<Http2GoAwayFields> opt_goaway_;
+  std::optional<Http2PriorityUpdateFields> opt_priority_update_;
 
-  absl::optional<size_t> opt_pad_length_;
-  absl::optional<size_t> opt_payload_length_;
-  absl::optional<size_t> opt_missing_length_;
-  absl::optional<size_t> opt_altsvc_origin_length_;
-  absl::optional<size_t> opt_altsvc_value_length_;
+  std::optional<size_t> opt_pad_length_;
+  std::optional<size_t> opt_payload_length_;
+  std::optional<size_t> opt_missing_length_;
+  std::optional<size_t> opt_altsvc_origin_length_;
+  std::optional<size_t> opt_altsvc_value_length_;
 
-  absl::optional<size_t> opt_window_update_increment_;
+  std::optional<size_t> opt_window_update_increment_;
 
   bool has_frame_size_error_ = false;
 
diff --git a/quiche/oblivious_http/buffers/oblivious_http_request.cc b/quiche/oblivious_http/buffers/oblivious_http_request.cc
index fec5c8f..eaf3c33 100644
--- a/quiche/oblivious_http/buffers/oblivious_http_request.cc
+++ b/quiche/oblivious_http/buffers/oblivious_http_request.cc
@@ -4,6 +4,7 @@
 #include <stdint.h>
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 
@@ -12,7 +13,6 @@
 #include "absl/status/statusor.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "openssl/hpke.h"
 #include "quiche/common/platform/api/quiche_bug_tracker.h"
 #include "quiche/common/platform/api/quiche_logging.h"
diff --git a/quiche/oblivious_http/buffers/oblivious_http_request.h b/quiche/oblivious_http/buffers/oblivious_http_request.h
index 0678ff5..cf27c41 100644
--- a/quiche/oblivious_http/buffers/oblivious_http_request.h
+++ b/quiche/oblivious_http/buffers/oblivious_http_request.h
@@ -2,11 +2,11 @@
 #define QUICHE_OBLIVIOUS_HTTP_BUFFERS_OBLIVIOUS_HTTP_REQUEST_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 
 #include "absl/status/statusor.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "openssl/hpke.h"
 #include "quiche/oblivious_http/common/oblivious_http_header_key_config.h"
 
@@ -115,7 +115,7 @@
       absl::string_view seed, absl::string_view request_label);
 
   // This field will be empty after calling `ReleaseContext()`.
-  absl::optional<Context> oblivious_http_request_context_;
+  std::optional<Context> oblivious_http_request_context_;
   ObliviousHttpHeaderKeyConfig key_config_;
   std::string request_ciphertext_;
   std::string request_plaintext_;
diff --git a/quiche/quic/core/batch_writer/quic_batch_writer_base.h b/quiche/quic/core/batch_writer/quic_batch_writer_base.h
index 69cefba..34c801a 100644
--- a/quiche/quic/core/batch_writer/quic_batch_writer_base.h
+++ b/quiche/quic/core/batch_writer/quic_batch_writer_base.h
@@ -39,7 +39,7 @@
 
   void SetWritable() final { write_blocked_ = false; }
 
-  absl::optional<int> MessageTooBigErrorCode() const override {
+  std::optional<int> MessageTooBigErrorCode() const override {
     return EMSGSIZE;
   }
 
diff --git a/quiche/quic/core/chlo_extractor.cc b/quiche/quic/core/chlo_extractor.cc
index a663432..ae4d6e3 100644
--- a/quiche/quic/core/chlo_extractor.cc
+++ b/quiche/quic/core/chlo_extractor.cc
@@ -57,7 +57,7 @@
   bool OnAckTimestamp(QuicPacketNumber packet_number,
                       QuicTime timestamp) override;
   bool OnAckFrameEnd(QuicPacketNumber start,
-                     const absl::optional<QuicEcnCounts>& ecn_counts) override;
+                     const std::optional<QuicEcnCounts>& ecn_counts) override;
   bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
   bool OnPingFrame(const QuicPingFrame& frame) override;
   bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override;
@@ -219,7 +219,7 @@
 
 bool ChloFramerVisitor::OnAckFrameEnd(
     QuicPacketNumber /*start*/,
-    const absl::optional<QuicEcnCounts>& /*ecn_counts*/) {
+    const std::optional<QuicEcnCounts>& /*ecn_counts*/) {
   return true;
 }
 
diff --git a/quiche/quic/core/congestion_control/bbr2_simulator_test.cc b/quiche/quic/core/congestion_control/bbr2_simulator_test.cc
index 4a14fc7..9eadce2 100644
--- a/quiche/quic/core/congestion_control/bbr2_simulator_test.cc
+++ b/quiche/quic/core/congestion_control/bbr2_simulator_test.cc
@@ -3,11 +3,11 @@
 // found in the LICENSE file.
 
 #include <memory>
+#include <optional>
 #include <sstream>
 #include <utility>
 
 #include "absl/strings/str_cat.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/congestion_control/bbr2_misc.h"
 #include "quiche/quic/core/congestion_control/bbr2_sender.h"
 #include "quiche/quic/core/congestion_control/bbr_sender.h"
@@ -90,7 +90,7 @@
   // Network switch queue capacity, in number of BDPs.
   float switch_queue_capacity_in_bdp = 2;
 
-  absl::optional<TrafficPolicerParams> sender_policer_params;
+  std::optional<TrafficPolicerParams> sender_policer_params;
 
   QuicBandwidth BottleneckBandwidth() const {
     return std::min(local_link.bandwidth, test_link.bandwidth);
diff --git a/quiche/quic/core/congestion_control/general_loss_algorithm_test.cc b/quiche/quic/core/congestion_control/general_loss_algorithm_test.cc
index 8fa22e0..4ec8a52 100644
--- a/quiche/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/quiche/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -62,15 +62,14 @@
                     const AckedPacketVector& packets_acked,
                     const std::vector<uint64_t>& losses_expected) {
     return VerifyLosses(largest_newly_acked, packets_acked, losses_expected,
-                        absl::nullopt, absl::nullopt);
+                        std::nullopt, std::nullopt);
   }
 
   void VerifyLosses(
       uint64_t largest_newly_acked, const AckedPacketVector& packets_acked,
       const std::vector<uint64_t>& losses_expected,
-      absl::optional<QuicPacketCount> max_sequence_reordering_expected,
-      absl::optional<QuicPacketCount>
-          num_borderline_time_reorderings_expected) {
+      std::optional<QuicPacketCount> max_sequence_reordering_expected,
+      std::optional<QuicPacketCount> num_borderline_time_reorderings_expected) {
     unacked_packets_.MaybeUpdateLargestAckedOfPacketNumberSpace(
         APPLICATION_DATA, QuicPacketNumber(largest_newly_acked));
     LostPacketVector lost_packets;
diff --git a/quiche/quic/core/congestion_control/uber_loss_algorithm.h b/quiche/quic/core/congestion_control/uber_loss_algorithm.h
index 19e3d9c..8b316cc 100644
--- a/quiche/quic/core/congestion_control/uber_loss_algorithm.h
+++ b/quiche/quic/core/congestion_control/uber_loss_algorithm.h
@@ -5,7 +5,8 @@
 #ifndef QUICHE_QUIC_CORE_CONGESTION_CONTROL_UBER_LOSS_ALGORITHM_H_
 #define QUICHE_QUIC_CORE_CONGESTION_CONTROL_UBER_LOSS_ALGORITHM_H_
 
-#include "absl/types/optional.h"
+#include <optional>
+
 #include "quiche/quic/core/congestion_control/general_loss_algorithm.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/platform/api/quic_flags.h"
@@ -20,8 +21,8 @@
 
 struct QUICHE_EXPORT LossDetectionParameters {
   // See GeneralLossAlgorithm for the meaning of reordering_(shift|threshold).
-  absl::optional<int> reordering_shift;
-  absl::optional<QuicPacketCount> reordering_threshold;
+  std::optional<int> reordering_shift;
+  std::optional<QuicPacketCount> reordering_threshold;
 };
 
 class QUICHE_EXPORT LossDetectionTunerInterface {
diff --git a/quiche/quic/core/congestion_control/uber_loss_algorithm_test.cc b/quiche/quic/core/congestion_control/uber_loss_algorithm_test.cc
index f840847..e2ada18 100644
--- a/quiche/quic/core/congestion_control/uber_loss_algorithm_test.cc
+++ b/quiche/quic/core/congestion_control/uber_loss_algorithm_test.cc
@@ -5,9 +5,9 @@
 #include "quiche/quic/core/congestion_control/uber_loss_algorithm.h"
 
 #include <memory>
+#include <optional>
 #include <utility>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/congestion_control/rtt_stats.h"
 #include "quiche/quic/core/crypto/crypto_protocol.h"
 #include "quiche/quic/core/quic_types.h"
@@ -69,13 +69,13 @@
                     const AckedPacketVector& packets_acked,
                     const std::vector<uint64_t>& losses_expected) {
     return VerifyLosses(largest_newly_acked, packets_acked, losses_expected,
-                        absl::nullopt);
+                        std::nullopt);
   }
 
   void VerifyLosses(
       uint64_t largest_newly_acked, const AckedPacketVector& packets_acked,
       const std::vector<uint64_t>& losses_expected,
-      absl::optional<QuicPacketCount> max_sequence_reordering_expected) {
+      std::optional<QuicPacketCount> max_sequence_reordering_expected) {
     LostPacketVector lost_packets;
     LossDetectionInterface::DetectionStats stats = loss_algorithm_.DetectLosses(
         *unacked_packets_, clock_.Now(), rtt_stats_,
diff --git a/quiche/quic/core/connection_id_generator.h b/quiche/quic/core/connection_id_generator.h
index 3e46a9e..33ecedc 100644
--- a/quiche/quic/core/connection_id_generator.h
+++ b/quiche/quic/core/connection_id_generator.h
@@ -17,11 +17,11 @@
   // Generate a new connection ID for a given connection ID. Returns the new
   // connection ID. If it cannot be generated for some reason, returns
   // empty.
-  virtual absl::optional<QuicConnectionId> GenerateNextConnectionId(
+  virtual std::optional<QuicConnectionId> GenerateNextConnectionId(
       const QuicConnectionId& original) = 0;
   // Consider the client-generated server connection ID in the quic handshake
   // and consider replacing it. Returns empty if not replaced.
-  virtual absl::optional<QuicConnectionId> MaybeReplaceConnectionId(
+  virtual std::optional<QuicConnectionId> MaybeReplaceConnectionId(
       const QuicConnectionId& original, const ParsedQuicVersion& version) = 0;
   // Returns the length of a connection ID generated by this generator with the
   // specified first byte.
diff --git a/quiche/quic/core/crypto/certificate_util_test.cc b/quiche/quic/core/crypto/certificate_util_test.cc
index 4c98d7c..06d5c4f 100644
--- a/quiche/quic/core/crypto/certificate_util_test.cc
+++ b/quiche/quic/core/crypto/certificate_util_test.cc
@@ -35,7 +35,7 @@
   ASSERT_NE(cert_view, nullptr);
   EXPECT_EQ(cert_view->public_key_type(), PublicKeyType::kP256);
 
-  absl::optional<std::string> subject = cert_view->GetHumanReadableSubject();
+  std::optional<std::string> subject = cert_view->GetHumanReadableSubject();
   ASSERT_TRUE(subject.has_value());
   EXPECT_EQ(*subject, options.subject);
 
diff --git a/quiche/quic/core/crypto/certificate_view.cc b/quiche/quic/core/crypto/certificate_view.cc
index 456d94b..5e83ae7 100644
--- a/quiche/quic/core/crypto/certificate_view.cc
+++ b/quiche/quic/core/crypto/certificate_view.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <string>
 
 #include "absl/strings/escaping.h"
@@ -14,7 +15,6 @@
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_join.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "openssl/base.h"
 #include "openssl/bytestring.h"
 #include "openssl/digest.h"
@@ -137,12 +137,12 @@
 
 }  // namespace
 
-absl::optional<std::string> X509NameAttributeToString(CBS input) {
+std::optional<std::string> X509NameAttributeToString(CBS input) {
   CBS name, value;
   unsigned value_tag;
   if (!CBS_get_asn1(&input, &name, CBS_ASN1_OBJECT) ||
       !CBS_get_any_asn1(&input, &value, &value_tag) || CBS_len(&input) != 0) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   // Note that this does not process encoding of |input| in any way.  This works
   // fine for the most cases.
@@ -153,17 +153,17 @@
 namespace {
 
 template <unsigned inner_tag, char separator,
-          absl::optional<std::string> (*parser)(CBS)>
-absl::optional<std::string> ParseAndJoin(CBS input) {
+          std::optional<std::string> (*parser)(CBS)>
+std::optional<std::string> ParseAndJoin(CBS input) {
   std::vector<std::string> pieces;
   while (CBS_len(&input) != 0) {
     CBS attribute;
     if (!CBS_get_asn1(&input, &attribute, inner_tag)) {
-      return absl::nullopt;
+      return std::nullopt;
     }
-    absl::optional<std::string> formatted = parser(attribute);
+    std::optional<std::string> formatted = parser(attribute);
     if (!formatted.has_value()) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     pieces.push_back(*formatted);
   }
@@ -171,11 +171,11 @@
   return absl::StrJoin(pieces, std::string({separator}));
 }
 
-absl::optional<std::string> RelativeDistinguishedNameToString(CBS input) {
+std::optional<std::string> RelativeDistinguishedNameToString(CBS input) {
   return ParseAndJoin<CBS_ASN1_SEQUENCE, '+', X509NameAttributeToString>(input);
 }
 
-absl::optional<std::string> DistinguishedNameToString(CBS input) {
+std::optional<std::string> DistinguishedNameToString(CBS input) {
   return ParseAndJoin<CBS_ASN1_SET, ',', RelativeDistinguishedNameToString>(
       input);
 }
@@ -198,11 +198,11 @@
   return "";
 }
 
-absl::optional<quic::QuicWallTime> ParseDerTime(unsigned tag,
-                                                absl::string_view payload) {
+std::optional<quic::QuicWallTime> ParseDerTime(unsigned tag,
+                                               absl::string_view payload) {
   if (tag != CBS_ASN1_GENERALIZEDTIME && tag != CBS_ASN1_UTCTIME) {
     QUIC_DLOG(WARNING) << "Invalid tag supplied for a DER timestamp";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   const size_t year_length = tag == CBS_ASN1_GENERALIZEDTIME ? 4 : 2;
@@ -214,7 +214,7 @@
       !reader.ReadDecimal64(2, &second) ||
       reader.ReadRemainingPayload() != "Z") {
     QUIC_DLOG(WARNING) << "Failed to parse the DER timestamp";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   if (tag == CBS_ASN1_UTCTIME) {
@@ -222,11 +222,11 @@
     year += (year >= 50) ? 1900 : 2000;
   }
 
-  const absl::optional<int64_t> unix_time =
+  const std::optional<int64_t> unix_time =
       quiche::QuicheUtcDateTimeToUnixSeconds(year, month, day, hour, minute,
                                              second);
   if (!unix_time.has_value() || *unix_time < 0) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return QuicWallTime::FromUNIXSeconds(*unix_time);
 }
@@ -256,7 +256,7 @@
 
     // Handle END lines.
     if (pending_message && line == expected_end) {
-      absl::optional<std::string> data =
+      std::optional<std::string> data =
           QuicheTextUtils::Base64Decode(encoded_message_contents);
       if (data.has_value()) {
         result.status = PemReadResult::kOk;
@@ -361,9 +361,9 @@
     QUIC_DLOG(WARNING) << "Failed to extract the validity dates";
     return nullptr;
   }
-  absl::optional<QuicWallTime> not_before_parsed =
+  std::optional<QuicWallTime> not_before_parsed =
       ParseDerTime(not_before_tag, CbsToStringPiece(not_before));
-  absl::optional<QuicWallTime> not_after_parsed =
+  std::optional<QuicWallTime> not_after_parsed =
       ParseDerTime(not_after_tag, CbsToStringPiece(not_after));
   if (!not_before_parsed.has_value() || !not_after_parsed.has_value()) {
     QUIC_DLOG(WARNING) << "Failed to parse validity dates";
@@ -545,7 +545,7 @@
       data.size());
 }
 
-absl::optional<std::string> CertificateView::GetHumanReadableSubject() const {
+std::optional<std::string> CertificateView::GetHumanReadableSubject() const {
   CBS input = StringPieceToCbs(subject_der_);
   return DistinguishedNameToString(input);
 }
diff --git a/quiche/quic/core/crypto/certificate_view.h b/quiche/quic/core/crypto/certificate_view.h
index 4a190a0..1229ad7 100644
--- a/quiche/quic/core/crypto/certificate_view.h
+++ b/quiche/quic/core/crypto/certificate_view.h
@@ -7,10 +7,10 @@
 
 #include <istream>
 #include <memory>
+#include <optional>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "openssl/base.h"
 #include "openssl/bytestring.h"
 #include "openssl/evp.h"
@@ -79,7 +79,7 @@
 
   // Returns a human-readable representation of the Subject field.  The format
   // is similar to RFC 2253, but does not match it exactly.
-  absl::optional<std::string> GetHumanReadableSubject() const;
+  std::optional<std::string> GetHumanReadableSubject() const;
 
   // |signature_algorithm| is a TLS signature algorithm ID.
   bool VerifySignature(absl::string_view data, absl::string_view signature,
@@ -143,11 +143,11 @@
 };
 
 // Parses a DER-encoded X.509 NameAttribute.  Exposed primarily for testing.
-QUICHE_EXPORT absl::optional<std::string> X509NameAttributeToString(CBS input);
+QUICHE_EXPORT std::optional<std::string> X509NameAttributeToString(CBS input);
 
 // Parses a DER time based on the specified ASN.1 tag.  Exposed primarily for
 // testing.
-QUICHE_EXPORT absl::optional<quic::QuicWallTime> ParseDerTime(
+QUICHE_EXPORT std::optional<quic::QuicWallTime> ParseDerTime(
     unsigned tag, absl::string_view payload);
 
 }  // namespace quic
diff --git a/quiche/quic/core/crypto/certificate_view_test.cc b/quiche/quic/core/crypto/certificate_view_test.cc
index d142ae4..d6b3b39 100644
--- a/quiche/quic/core/crypto/certificate_view_test.cc
+++ b/quiche/quic/core/crypto/certificate_view_test.cc
@@ -157,27 +157,27 @@
               Optional(QuicWallTime::FromUNIXSeconds(24)));
   EXPECT_TRUE(ParseDerTime(CBS_ASN1_UTCTIME, "200101000024Z").has_value());
 
-  EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, ""), absl::nullopt);
+  EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, ""), std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "19700101000024.001Z"),
-            absl::nullopt);
+            std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "19700101000024Q"),
-            absl::nullopt);
+            std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "19700101000024-0500"),
-            absl::nullopt);
+            std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "700101000024ZZ"),
-            absl::nullopt);
+            std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "19700101000024.00Z"),
-            absl::nullopt);
+            std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "19700101000024.Z"),
-            absl::nullopt);
+            std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "197O0101000024Z"),
-            absl::nullopt);
+            std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "19700101000024.0O1Z"),
-            absl::nullopt);
+            std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "-9700101000024Z"),
-            absl::nullopt);
+            std::nullopt);
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "1970-101000024Z"),
-            absl::nullopt);
+            std::nullopt);
 
   EXPECT_TRUE(ParseDerTime(CBS_ASN1_UTCTIME, "490101000024Z").has_value());
   // This should parse as 1950, which predates UNIX epoch.
@@ -186,7 +186,7 @@
   EXPECT_THAT(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "19700101230000Z"),
               Optional(QuicWallTime::FromUNIXSeconds(23 * 3600)));
   EXPECT_EQ(ParseDerTime(CBS_ASN1_GENERALIZEDTIME, "19700101240000Z"),
-            absl::nullopt);
+            std::nullopt);
 }
 
 TEST(CertificateViewTest, NameAttribute) {
diff --git a/quiche/quic/core/crypto/crypto_utils.cc b/quiche/quic/core/crypto/crypto_utils.cc
index 1ac33da..1e6b04b 100644
--- a/quiche/quic/core/crypto/crypto_utils.cc
+++ b/quiche/quic/core/crypto/crypto_utils.cc
@@ -790,7 +790,7 @@
 }
 
 // static
-absl::optional<std::string> CryptoUtils::GenerateProofPayloadToBeSigned(
+std::optional<std::string> CryptoUtils::GenerateProofPayloadToBeSigned(
     absl::string_view chlo_hash, absl::string_view server_config) {
   size_t payload_size = sizeof(kProofSignatureLabel) + sizeof(uint32_t) +
                         chlo_hash.size() + server_config.size();
@@ -804,7 +804,7 @@
                  payload_writer.WriteStringPiece(chlo_hash) &&
                  payload_writer.WriteStringPiece(server_config);
   if (!success) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return payload;
 }
diff --git a/quiche/quic/core/crypto/crypto_utils.h b/quiche/quic/core/crypto/crypto_utils.h
index 12822aa..41823fe 100644
--- a/quiche/quic/core/crypto/crypto_utils.h
+++ b/quiche/quic/core/crypto/crypto_utils.h
@@ -250,7 +250,7 @@
 
   // Computes the contents of a binary message that is signed inside QUIC Crypto
   // protocol using the certificate key.
-  static absl::optional<std::string> GenerateProofPayloadToBeSigned(
+  static std::optional<std::string> GenerateProofPayloadToBeSigned(
       absl::string_view chlo_hash, absl::string_view server_config);
 };
 
diff --git a/quiche/quic/core/crypto/proof_source.h b/quiche/quic/core/crypto/proof_source.h
index 01907c1..b963034 100644
--- a/quiche/quic/core/crypto/proof_source.h
+++ b/quiche/quic/core/crypto/proof_source.h
@@ -320,9 +320,9 @@
       const QuicConnectionId& original_connection_id,
       absl::string_view ssl_capabilities, const std::string& hostname,
       absl::string_view client_hello, const std::string& alpn,
-      absl::optional<std::string> alps,
+      std::optional<std::string> alps,
       const std::vector<uint8_t>& quic_transport_params,
-      const absl::optional<std::vector<uint8_t>>& early_data_context,
+      const std::optional<std::vector<uint8_t>>& early_data_context,
       const QuicSSLConfig& ssl_config) = 0;
 
   // Starts a compute signature operation. If the operation is not cancelled
diff --git a/quiche/quic/core/crypto/proof_source_x509.cc b/quiche/quic/core/crypto/proof_source_x509.cc
index a86c78b..c14722b 100644
--- a/quiche/quic/core/crypto/proof_source_x509.cc
+++ b/quiche/quic/core/crypto/proof_source_x509.cc
@@ -5,10 +5,10 @@
 #include "quiche/quic/core/crypto/proof_source_x509.h"
 
 #include <memory>
+#include <optional>
 
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "openssl/ssl.h"
 #include "quiche/quic/core/crypto/certificate_view.h"
 #include "quiche/quic/core/crypto/crypto_protocol.h"
@@ -54,7 +54,7 @@
     return;
   }
 
-  absl::optional<std::string> payload =
+  std::optional<std::string> payload =
       CryptoUtils::GenerateProofPayloadToBeSigned(chlo_hash, server_config);
   if (!payload.has_value()) {
     callback->Run(/*ok=*/false, nullptr, proof, nullptr);
diff --git a/quiche/quic/core/crypto/quic_crypto_client_config.h b/quiche/quic/core/crypto/quic_crypto_client_config.h
index 30cddcc..35433f3 100644
--- a/quiche/quic/core/crypto/quic_crypto_client_config.h
+++ b/quiche/quic/core/crypto/quic_crypto_client_config.h
@@ -380,7 +380,7 @@
     tls_signature_algorithms_ = std::move(signature_algorithms);
   }
 
-  const absl::optional<std::string>& tls_signature_algorithms() const {
+  const std::optional<std::string>& tls_signature_algorithms() const {
     return tls_signature_algorithms_;
   }
 
@@ -459,7 +459,7 @@
 
   // If set, configure the client to use the specified signature algorithms, via
   // SSL_set1_sigalgs_list. TLS only.
-  absl::optional<std::string> tls_signature_algorithms_;
+  std::optional<std::string> tls_signature_algorithms_;
 
   // In QUIC, technically, client hello should be fully padded.
   // However, fully padding on slow network connection (e.g. 50kbps) can add
diff --git a/quiche/quic/core/crypto/quic_crypto_server_config.cc b/quiche/quic/core/crypto/quic_crypto_server_config.cc
index 2599f5b..69275dc 100644
--- a/quiche/quic/core/crypto/quic_crypto_server_config.cc
+++ b/quiche/quic/core/crypto/quic_crypto_server_config.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <cstdlib>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 
@@ -14,7 +15,6 @@
 #include "absl/strings/escaping.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "openssl/sha.h"
 #include "openssl/ssl.h"
 #include "quiche/quic/core/crypto/aes_128_gcm_12_decrypter.h"
@@ -1536,7 +1536,7 @@
           std::unique_ptr<CertificateView> view =
               CertificateView::ParseSingleCertificate(certs[0]);
           if (view != nullptr) {
-            absl::optional<std::string> maybe_ca_subject =
+            std::optional<std::string> maybe_ca_subject =
                 view->GetHumanReadableSubject();
             if (maybe_ca_subject.has_value()) {
               ca_subject = *maybe_ca_subject;
diff --git a/quiche/quic/core/crypto/transport_parameters.h b/quiche/quic/core/crypto/transport_parameters.h
index ff57add..496de82 100644
--- a/quiche/quic/core/crypto/transport_parameters.h
+++ b/quiche/quic/core/crypto/transport_parameters.h
@@ -6,11 +6,11 @@
 #define QUICHE_QUIC_CORE_CRYPTO_TRANSPORT_PARAMETERS_H_
 
 #include <memory>
+#include <optional>
 #include <vector>
 
 #include "absl/container/flat_hash_map.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_connection_id.h"
 #include "quiche/quic/core/quic_data_reader.h"
 #include "quiche/quic/core/quic_data_writer.h"
@@ -176,15 +176,15 @@
   Perspective perspective;
 
   // Google QUIC downgrade prevention mechanism sent over QUIC+TLS.
-  absl::optional<LegacyVersionInformation> legacy_version_information;
+  std::optional<LegacyVersionInformation> legacy_version_information;
 
   // IETF downgrade prevention and compatible version negotiation, see
   // draft-ietf-quic-version-negotiation.
-  absl::optional<VersionInformation> version_information;
+  std::optional<VersionInformation> version_information;
 
   // The value of the Destination Connection ID field from the first
   // Initial packet sent by the client.
-  absl::optional<QuicConnectionId> original_destination_connection_id;
+  std::optional<QuicConnectionId> original_destination_connection_id;
 
   // Maximum idle timeout expressed in milliseconds.
   IntegerParameter max_idle_timeout_ms;
@@ -238,11 +238,11 @@
 
   // The value that the endpoint included in the Source Connection ID field of
   // the first Initial packet it sent.
-  absl::optional<QuicConnectionId> initial_source_connection_id;
+  std::optional<QuicConnectionId> initial_source_connection_id;
 
   // The value that the server included in the Source Connection ID field of a
   // Retry packet it sent.
-  absl::optional<QuicConnectionId> retry_source_connection_id;
+  std::optional<QuicConnectionId> retry_source_connection_id;
 
   // Indicates support for the DATAGRAM frame and the maximum frame size that
   // the sender accepts. See draft-ietf-quic-datagram.
@@ -253,10 +253,10 @@
   IntegerParameter initial_round_trip_time_us;
 
   // Google internal handshake message.
-  absl::optional<std::string> google_handshake_message;
+  std::optional<std::string> google_handshake_message;
 
   // Google-specific connection options.
-  absl::optional<QuicTagVector> google_connection_options;
+  std::optional<QuicTagVector> google_connection_options;
 
   // Validates whether transport parameters are valid according to
   // the specification. If the transport parameters are not valid, this method
diff --git a/quiche/quic/core/crypto/transport_parameters_test.cc b/quiche/quic/core/crypto/transport_parameters_test.cc
index 6b782c4..59f2188 100644
--- a/quiche/quic/core/crypto/transport_parameters_test.cc
+++ b/quiche/quic/core/crypto/transport_parameters_test.cc
@@ -242,7 +242,7 @@
   // Test comparison on connection IDs.
   orig_params.initial_source_connection_id =
       CreateFakeInitialSourceConnectionId();
-  new_params.initial_source_connection_id = absl::nullopt;
+  new_params.initial_source_connection_id = std::nullopt;
   EXPECT_NE(orig_params, new_params);
   EXPECT_FALSE(orig_params == new_params);
   EXPECT_TRUE(orig_params != new_params);
diff --git a/quiche/quic/core/deterministic_connection_id_generator.cc b/quiche/quic/core/deterministic_connection_id_generator.cc
index 619ede6..4a22b63 100644
--- a/quiche/quic/core/deterministic_connection_id_generator.cc
+++ b/quiche/quic/core/deterministic_connection_id_generator.cc
@@ -20,7 +20,7 @@
   }
 }
 
-absl::optional<QuicConnectionId>
+std::optional<QuicConnectionId>
 DeterministicConnectionIdGenerator::GenerateNextConnectionId(
     const QuicConnectionId& original) {
   if (expected_connection_id_length_ == 0) {
@@ -50,19 +50,19 @@
                           expected_connection_id_length_);
 }
 
-absl::optional<QuicConnectionId>
+std::optional<QuicConnectionId>
 DeterministicConnectionIdGenerator::MaybeReplaceConnectionId(
     const QuicConnectionId& original, const ParsedQuicVersion& version) {
   if (original.length() == expected_connection_id_length_) {
-    return absl::optional<QuicConnectionId>();
+    return std::optional<QuicConnectionId>();
   }
   QUICHE_DCHECK(version.AllowsVariableLengthConnectionIds());
-  absl::optional<QuicConnectionId> new_connection_id =
+  std::optional<QuicConnectionId> new_connection_id =
       GenerateNextConnectionId(original);
   // Verify that ReplaceShortServerConnectionId is deterministic.
   if (!new_connection_id.has_value()) {
     QUIC_BUG(unset_next_connection_id);
-    return absl::nullopt;
+    return std::nullopt;
   }
   QUICHE_DCHECK_EQ(
       *new_connection_id,
diff --git a/quiche/quic/core/deterministic_connection_id_generator.h b/quiche/quic/core/deterministic_connection_id_generator.h
index fbb9900..fc8f8e4 100644
--- a/quiche/quic/core/deterministic_connection_id_generator.h
+++ b/quiche/quic/core/deterministic_connection_id_generator.h
@@ -20,11 +20,11 @@
   DeterministicConnectionIdGenerator(uint8_t expected_connection_id_length);
 
   // Hashes |original| to create a new connection ID.
-  absl::optional<QuicConnectionId> GenerateNextConnectionId(
+  std::optional<QuicConnectionId> GenerateNextConnectionId(
       const QuicConnectionId& original) override;
   // Replace the connection ID if and only if |original| is not of the expected
   // length.
-  absl::optional<QuicConnectionId> MaybeReplaceConnectionId(
+  std::optional<QuicConnectionId> MaybeReplaceConnectionId(
       const QuicConnectionId& original,
       const ParsedQuicVersion& version) override;
   uint8_t ConnectionIdLength(uint8_t /*first_byte*/) const override {
diff --git a/quiche/quic/core/deterministic_connection_id_generator_test.cc b/quiche/quic/core/deterministic_connection_id_generator_test.cc
index 6c3ee21..a24b3dc 100644
--- a/quiche/quic/core/deterministic_connection_id_generator_test.cc
+++ b/quiche/quic/core/deterministic_connection_id_generator_test.cc
@@ -74,7 +74,7 @@
   const char connection_id_bytes[255] = {};
   for (uint8_t i = 0; i < sizeof(connection_id_bytes) - 1; ++i) {
     QuicConnectionId connection_id(connection_id_bytes, i);
-    absl::optional<QuicConnectionId> replacement_connection_id =
+    std::optional<QuicConnectionId> replacement_connection_id =
         generator_.GenerateNextConnectionId(connection_id);
     ASSERT_TRUE(replacement_connection_id.has_value());
     EXPECT_EQ(connection_id_length_, replacement_connection_id->length());
@@ -85,14 +85,14 @@
   // Make sure all these test connection IDs have different replacements.
   for (uint64_t i = 0; i < 256; ++i) {
     QuicConnectionId connection_id_i = TestConnectionId(i);
-    absl::optional<QuicConnectionId> new_i =
+    std::optional<QuicConnectionId> new_i =
         generator_.GenerateNextConnectionId(connection_id_i);
     ASSERT_TRUE(new_i.has_value());
     EXPECT_NE(connection_id_i, *new_i);
     for (uint64_t j = i + 1; j <= 256; ++j) {
       QuicConnectionId connection_id_j = TestConnectionId(j);
       EXPECT_NE(connection_id_i, connection_id_j);
-      absl::optional<QuicConnectionId> new_j =
+      std::optional<QuicConnectionId> new_j =
           generator_.GenerateNextConnectionId(connection_id_j);
       ASSERT_TRUE(new_j.has_value());
       EXPECT_NE(*new_i, *new_j);
@@ -107,7 +107,7 @@
                                       0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14};
   for (int i = 0; i < kQuicMaxConnectionIdWithLengthPrefixLength; i++) {
     QuicConnectionId input = QuicConnectionId(connection_id_input, i);
-    absl::optional<QuicConnectionId> output =
+    std::optional<QuicConnectionId> output =
         generator_.MaybeReplaceConnectionId(input, version_);
     if (i == connection_id_length_) {
       EXPECT_FALSE(output.has_value());
diff --git a/quiche/quic/core/frames/quic_ack_frame.h b/quiche/quic/core/frames/quic_ack_frame.h
index d0b8424..bafc755 100644
--- a/quiche/quic/core/frames/quic_ack_frame.h
+++ b/quiche/quic/core/frames/quic_ack_frame.h
@@ -116,7 +116,7 @@
   PacketNumberQueue packets;
 
   // ECN counters.
-  absl::optional<QuicEcnCounts> ecn_counters;
+  std::optional<QuicEcnCounts> ecn_counters;
 };
 
 // The highest acked packet number we've observed from the peer. If no packets
diff --git a/quiche/quic/core/http/end_to_end_test.cc b/quiche/quic/core/http/end_to_end_test.cc
index 961214b..06200ff 100644
--- a/quiche/quic/core/http/end_to_end_test.cc
+++ b/quiche/quic/core/http/end_to_end_test.cc
@@ -921,7 +921,7 @@
   // Default is true.
   bool connect_to_server_on_initialize_;
   QuicSocketAddress server_address_;
-  absl::optional<QuicSocketAddress> server_listening_address_;
+  std::optional<QuicSocketAddress> server_listening_address_;
   std::string server_hostname_;
   QuicTestBackend memory_cache_backend_;
   std::unique_ptr<ServerThread> server_thread_;
@@ -4172,7 +4172,7 @@
     QuicVersionLabel version_label;
     ParsedQuicVersion parsed_version = ParsedQuicVersion::Unsupported();
     QuicConnectionId destination_connection_id, source_connection_id;
-    absl::optional<absl::string_view> retry_token;
+    std::optional<absl::string_view> retry_token;
     std::string detailed_error;
     if (QuicFramer::ParsePublicHeaderDispatcher(
             QuicEncryptedPacket(buffer, buf_len),
diff --git a/quiche/quic/core/http/quic_receive_control_stream.cc b/quiche/quic/core/http/quic_receive_control_stream.cc
index 4be1536..6a57d5f 100644
--- a/quiche/quic/core/http/quic_receive_control_stream.cc
+++ b/quiche/quic/core/http/quic_receive_control_stream.cc
@@ -4,12 +4,12 @@
 
 #include "quiche/quic/core/http/quic_receive_control_stream.h"
 
+#include <optional>
 #include <utility>
 
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/http/http_constants.h"
 #include "quiche/quic/core/http/http_decoder.h"
 #include "quiche/quic/core/http/quic_spdy_session.h"
@@ -137,7 +137,7 @@
     spdy_session()->debug_visitor()->OnPriorityUpdateFrameReceived(frame);
   }
 
-  absl::optional<HttpStreamPriority> priority =
+  std::optional<HttpStreamPriority> priority =
       ParsePriorityFieldValue(frame.priority_field_value);
 
   if (!priority.has_value()) {
diff --git a/quiche/quic/core/http/quic_send_control_stream_test.cc b/quiche/quic/core/http/quic_send_control_stream_test.cc
index 9698a37..e83e46d 100644
--- a/quiche/quic/core/http/quic_send_control_stream_test.cc
+++ b/quiche/quic/core/http/quic_send_control_stream_test.cc
@@ -206,7 +206,7 @@
       [&writer, this](QuicStreamId /*id*/, size_t write_length,
                       QuicStreamOffset offset, StreamSendingState /*state*/,
                       TransmissionType /*type*/,
-                      absl::optional<EncryptionLevel> /*level*/) {
+                      std::optional<EncryptionLevel> /*level*/) {
         send_control_stream_->WriteStreamData(offset, write_length, &writer);
         return QuicConsumedData(/* bytes_consumed = */ write_length,
                                 /* fin_consumed = */ false);
diff --git a/quiche/quic/core/http/quic_server_session_base.cc b/quiche/quic/core/http/quic_server_session_base.cc
index 5816eb3..5248024 100644
--- a/quiche/quic/core/http/quic_server_session_base.cc
+++ b/quiche/quic/core/http/quic_server_session_base.cc
@@ -190,7 +190,7 @@
       bandwidth_estimate_sent_to_client_ = new_bandwidth_estimate;
     }
   } else {
-    absl::optional<CachedNetworkParameters> cached_network_params =
+    std::optional<CachedNetworkParameters> cached_network_params =
         GenerateCachedNetworkParameters();
 
     if (cached_network_params.has_value()) {
@@ -311,7 +311,7 @@
   return ssl_config;
 }
 
-absl::optional<CachedNetworkParameters>
+std::optional<CachedNetworkParameters>
 QuicServerSessionBase::GenerateCachedNetworkParameters() const {
   const QuicSentPacketManager& sent_packet_manager =
       connection()->sent_packet_manager();
diff --git a/quiche/quic/core/http/quic_server_session_base.h b/quiche/quic/core/http/quic_server_session_base.h
index 113f754..9892356 100644
--- a/quiche/quic/core/http/quic_server_session_base.h
+++ b/quiche/quic/core/http/quic_server_session_base.h
@@ -78,7 +78,7 @@
 
   const QuicCryptoServerStreamBase* GetCryptoStream() const override;
 
-  absl::optional<CachedNetworkParameters> GenerateCachedNetworkParameters()
+  std::optional<CachedNetworkParameters> GenerateCachedNetworkParameters()
       const override;
 
   // If an outgoing stream can be created, return true.
diff --git a/quiche/quic/core/http/quic_spdy_session.cc b/quiche/quic/core/http/quic_spdy_session.cc
index 0580fca..b78a6cc 100644
--- a/quiche/quic/core/http/quic_spdy_session.cc
+++ b/quiche/quic/core/http/quic_spdy_session.cc
@@ -8,6 +8,7 @@
 #include <cstdint>
 #include <limits>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 
@@ -16,7 +17,6 @@
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/http/http_constants.h"
 #include "quiche/quic/core/http/http_decoder.h"
 #include "quiche/quic/core/http/http_frames.h"
@@ -158,13 +158,13 @@
   }
   bool OnUnknownFrameEnd() override { return true; }
 
-  const absl::optional<std::string>& error_detail() const {
+  const std::optional<std::string>& error_detail() const {
     return error_detail_;
   }
 
  private:
   QuicSpdySession* const session_;
-  absl::optional<std::string> error_detail_;
+  std::optional<std::string> error_detail_;
 
   // True if SETTINGS frame has been received via ALPS.
   bool settings_frame_received_via_alps_ = false;
@@ -993,8 +993,8 @@
   return true;
 }
 
-absl::optional<std::string> QuicSpdySession::OnAlpsData(
-    const uint8_t* alps_data, size_t alps_length) {
+std::optional<std::string> QuicSpdySession::OnAlpsData(const uint8_t* alps_data,
+                                                       size_t alps_length) {
   AlpsFrameDecoder alps_frame_decoder(this);
   HttpDecoder decoder(&alps_frame_decoder);
   decoder.ProcessInput(reinterpret_cast<const char*>(alps_data), alps_length);
@@ -1010,7 +1010,7 @@
     return "incomplete HTTP/3 frame";
   }
 
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 void QuicSpdySession::OnAcceptChFrameReceivedViaAlps(
@@ -1060,7 +1060,7 @@
 
 bool QuicSpdySession::ValidateWebTransportSettingsConsistency() {
   // Only apply the following checks to draft-07 or later.
-  absl::optional<WebTransportHttp3Version> version =
+  std::optional<WebTransportHttp3Version> version =
       NegotiatedWebTransportVersion();
   if (!version.has_value() || *version == WebTransportHttp3Version::kDraft02) {
     return true;
@@ -1092,7 +1092,7 @@
   return true;
 }
 
-absl::optional<std::string> QuicSpdySession::OnSettingsFrameViaAlps(
+std::optional<std::string> QuicSpdySession::OnSettingsFrameViaAlps(
     const SettingsFrame& frame) {
   QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
 
@@ -1107,7 +1107,7 @@
       return "error parsing setting";
     }
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 bool QuicSpdySession::VerifySettingIsZeroOrOne(uint64_t id, uint64_t value) {
@@ -1756,10 +1756,10 @@
          NegotiatedWebTransportVersion().has_value() && allow_extended_connect_;
 }
 
-absl::optional<WebTransportHttp3Version>
+std::optional<WebTransportHttp3Version>
 QuicSpdySession::SupportedWebTransportVersion() {
   if (!SupportsWebTransport()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return NegotiatedWebTransportVersion();
 }
@@ -1887,12 +1887,12 @@
 }
 
 void QuicSpdySession::OnDatagramProcessed(
-    absl::optional<MessageStatus> /*status*/) {
+    std::optional<MessageStatus> /*status*/) {
   // TODO(b/184598230): make this work with multiple datagram flows.
 }
 
 void QuicSpdySession::DatagramObserver::OnDatagramProcessed(
-    absl::optional<MessageStatus> status) {
+    std::optional<MessageStatus> status) {
   session_->OnDatagramProcessed(status);
 }
 
diff --git a/quiche/quic/core/http/quic_spdy_session.h b/quiche/quic/core/http/quic_spdy_session.h
index c295569..290b640 100644
--- a/quiche/quic/core/http/quic_spdy_session.h
+++ b/quiche/quic/core/http/quic_spdy_session.h
@@ -9,12 +9,12 @@
 #include <cstdint>
 #include <list>
 #include <memory>
+#include <optional>
 #include <string>
 
 #include "absl/container/flat_hash_map.h"
 #include "absl/container/flat_hash_set.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/http/http_frames.h"
 #include "quiche/quic/core/http/quic_header_list.h"
 #include "quiche/quic/core/http/quic_headers_stream.h"
@@ -259,8 +259,7 @@
   // Called when an HTTP/3 SETTINGS frame is received via ALPS.
   // Returns an error message if an error has occurred, or nullopt otherwise.
   // May or may not close the connection on error.
-  absl::optional<std::string> OnSettingsFrameViaAlps(
-      const SettingsFrame& frame);
+  std::optional<std::string> OnSettingsFrameViaAlps(const SettingsFrame& frame);
 
   // Called when a setting is parsed from a SETTINGS frame received on the
   // control stream or from cached application state.
@@ -339,7 +338,7 @@
   // received or sent.
   bool goaway_received() const;
   bool goaway_sent() const;
-  absl::optional<uint64_t> last_received_http3_goaway_id() {
+  std::optional<uint64_t> last_received_http3_goaway_id() {
     return last_received_http3_goaway_id_;
   }
 
@@ -373,8 +372,8 @@
   // Decode SETTINGS from |cached_state| and apply it to the session.
   bool ResumeApplicationState(ApplicationState* cached_state) override;
 
-  absl::optional<std::string> OnAlpsData(const uint8_t* alps_data,
-                                         size_t alps_length) override;
+  std::optional<std::string> OnAlpsData(const uint8_t* alps_data,
+                                        size_t alps_length) override;
 
   // Called when ACCEPT_CH frame is parsed out of data received in TLS ALPS
   // extension.
@@ -401,7 +400,7 @@
 
   // If SupportsWebTransport() is true, returns the version of WebTransport
   // currently in use (which is the highest version supported by both peers).
-  absl::optional<WebTransportHttp3Version> SupportedWebTransportVersion();
+  std::optional<WebTransportHttp3Version> SupportedWebTransportVersion();
 
   // Indicates whether both the peer and us support HTTP/3 Datagrams.
   bool SupportsH3Datagram() const;
@@ -537,7 +536,7 @@
   void MaybeBundleOpportunistically() override;
 
   // Called whenever a datagram is dequeued or dropped from datagram_queue().
-  virtual void OnDatagramProcessed(absl::optional<MessageStatus> status);
+  virtual void OnDatagramProcessed(std::optional<MessageStatus> status);
 
   // Returns which version of the HTTP/3 datagram extension we should advertise
   // in settings and accept remote settings for.
@@ -562,7 +561,7 @@
   class QUICHE_EXPORT DatagramObserver : public QuicDatagramQueue::Observer {
    public:
     explicit DatagramObserver(QuicSpdySession* session) : session_(session) {}
-    void OnDatagramProcessed(absl::optional<MessageStatus> status) override;
+    void OnDatagramProcessed(std::optional<MessageStatus> status) override;
 
    private:
     QuicSpdySession* session_;  // not owned
@@ -591,7 +590,7 @@
   bool VerifySettingIsZeroOrOne(uint64_t id, uint64_t value);
 
   // Computes the highest WebTransport version supported by both peers.
-  absl::optional<WebTransportHttp3Version> NegotiatedWebTransportVersion()
+  std::optional<WebTransportHttp3Version> NegotiatedWebTransportVersion()
       const {
     return (LocallySupportedWebTransportVersions() &
             peer_web_transport_versions_)
@@ -668,10 +667,10 @@
 
   // The identifier in the most recently received GOAWAY frame.  Unset if no
   // GOAWAY frame has been received yet.
-  absl::optional<uint64_t> last_received_http3_goaway_id_;
+  std::optional<uint64_t> last_received_http3_goaway_id_;
   // The identifier in the most recently sent GOAWAY frame.  Unset if no GOAWAY
   // frame has been sent yet.
-  absl::optional<uint64_t> last_sent_http3_goaway_id_;
+  std::optional<uint64_t> last_sent_http3_goaway_id_;
 
   // Whether both this endpoint and our peer support HTTP datagrams and which
   // draft is in use for this session.
diff --git a/quiche/quic/core/http/quic_spdy_session_test.cc b/quiche/quic/core/http/quic_spdy_session_test.cc
index ef7b072..a8c8c0a 100644
--- a/quiche/quic/core/http/quic_spdy_session_test.cc
+++ b/quiche/quic/core/http/quic_spdy_session_test.cc
@@ -3603,7 +3603,7 @@
   ReceiveWebTransportSettings(
       WebTransportHttp3VersionSet({WebTransportHttp3Version::kDraft02}));
   EXPECT_FALSE(session_.SupportsWebTransport());
-  EXPECT_EQ(session_.SupportedWebTransportVersion(), absl::nullopt);
+  EXPECT_EQ(session_.SupportedWebTransportVersion(), std::nullopt);
 }
 
 TEST_P(QuicSpdySessionTestClient, WebTransportSettingSetToZero) {
diff --git a/quiche/quic/core/http/quic_spdy_stream.cc b/quiche/quic/core/http/quic_spdy_stream.cc
index 6f40159..40ecc03 100644
--- a/quiche/quic/core/http/quic_spdy_stream.cc
+++ b/quiche/quic/core/http/quic_spdy_stream.cc
@@ -6,6 +6,7 @@
 
 #include <limits>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 
@@ -13,7 +14,6 @@
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/http2/http2_constants.h"
 #include "quiche/quic/core/http/http_constants.h"
 #include "quiche/quic/core/http/http_decoder.h"
@@ -1117,7 +1117,7 @@
   QuicStreamOffset offset = sequencer()->NumBytesConsumed();
   sequencer()->MarkConsumed(header_length);
 
-  absl::optional<WebTransportHttp3Version> version =
+  std::optional<WebTransportHttp3Version> version =
       spdy_session_->SupportedWebTransportVersion();
   QUICHE_DCHECK(version.has_value());
   if (version == WebTransportHttp3Version::kDraft02) {
diff --git a/quiche/quic/core/http/spdy_utils.cc b/quiche/quic/core/http/spdy_utils.cc
index 873d39c..7df35ef 100644
--- a/quiche/quic/core/http/spdy_utils.cc
+++ b/quiche/quic/core/http/spdy_utils.cc
@@ -5,6 +5,7 @@
 #include "quiche/quic/core/http/spdy_utils.h"
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -12,7 +13,6 @@
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_versions.h"
 #include "quiche/quic/platform/api/quic_flag_utils.h"
 #include "quiche/quic/platform/api/quic_flags.h"
diff --git a/quiche/quic/core/http/spdy_utils.h b/quiche/quic/core/http/spdy_utils.h
index ff93b69..0b0b854 100644
--- a/quiche/quic/core/http/spdy_utils.h
+++ b/quiche/quic/core/http/spdy_utils.h
@@ -7,9 +7,9 @@
 
 #include <cstddef>
 #include <cstdint>
+#include <optional>
 #include <string>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/http/http_constants.h"
 #include "quiche/quic/core/http/quic_header_list.h"
 #include "quiche/quic/core/quic_packets.h"
diff --git a/quiche/quic/core/http/web_transport_http3.cc b/quiche/quic/core/http/web_transport_http3.cc
index 31a1a35..d1f477d 100644
--- a/quiche/quic/core/http/web_transport_http3.cc
+++ b/quiche/quic/core/http/web_transport_http3.cc
@@ -6,10 +6,10 @@
 
 #include <limits>
 #include <memory>
+#include <optional>
 
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/http/quic_spdy_session.h"
 #include "quiche/quic/core/http/quic_spdy_stream.h"
 #include "quiche/quic/core/quic_data_reader.h"
@@ -436,16 +436,16 @@
 constexpr WebTransportStreamError kDefaultWebTransportError = 0;
 }  // namespace
 
-absl::optional<WebTransportStreamError> Http3ErrorToWebTransport(
+std::optional<WebTransportStreamError> Http3ErrorToWebTransport(
     uint64_t http3_error_code) {
   // Ensure the code is within the valid range.
   if (http3_error_code < kWebTransportMappedErrorCodeFirst ||
       http3_error_code > kWebTransportMappedErrorCodeLast) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   // Exclude GREASE codepoints.
   if ((http3_error_code - 0x21) % 0x1f == 0) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   uint64_t shifted = http3_error_code - kWebTransportMappedErrorCodeFirst;
@@ -457,7 +457,7 @@
 
 WebTransportStreamError Http3ErrorToWebTransportOrDefault(
     uint64_t http3_error_code) {
-  absl::optional<WebTransportStreamError> result =
+  std::optional<WebTransportStreamError> result =
       Http3ErrorToWebTransport(http3_error_code);
   return result.has_value() ? *result : kDefaultWebTransportError;
 }
diff --git a/quiche/quic/core/http/web_transport_http3.h b/quiche/quic/core/http/web_transport_http3.h
index 14b4a1c..4f3815b 100644
--- a/quiche/quic/core/http/web_transport_http3.h
+++ b/quiche/quic/core/http/web_transport_http3.h
@@ -6,11 +6,11 @@
 #define QUICHE_QUIC_CORE_HTTP_WEB_TRANSPORT_HTTP3_H_
 
 #include <memory>
+#include <optional>
 
 #include "absl/base/attributes.h"
 #include "absl/container/flat_hash_set.h"
 #include "absl/time/time.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/http/quic_spdy_session.h"
 #include "quiche/quic/core/http/web_transport_stream_adapter.h"
 #include "quiche/quic/core/quic_error_codes.h"
@@ -174,7 +174,7 @@
  private:
   QuicSpdySession* session_;
   WebTransportStreamAdapter adapter_;
-  absl::optional<WebTransportSessionId> session_id_;
+  std::optional<WebTransportSessionId> session_id_;
   bool needs_to_send_preamble_;
 
   bool ReadSessionId();
@@ -184,7 +184,7 @@
 
 // Remaps HTTP/3 error code into a WebTransport error code.  Returns nullopt if
 // the provided code is outside of valid range.
-QUICHE_EXPORT absl::optional<WebTransportStreamError> Http3ErrorToWebTransport(
+QUICHE_EXPORT std::optional<WebTransportStreamError> Http3ErrorToWebTransport(
     uint64_t http3_error_code);
 
 // Same as above, but returns default error value (zero) when none could be
diff --git a/quiche/quic/core/http/web_transport_http3_test.cc b/quiche/quic/core/http/web_transport_http3_test.cc
index be8cfdd..87289f1 100644
--- a/quiche/quic/core/http/web_transport_http3_test.cc
+++ b/quiche/quic/core/http/web_transport_http3_test.cc
@@ -6,8 +6,8 @@
 
 #include <cstdint>
 #include <limits>
+#include <optional>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/platform/api/quic_test.h"
 
 namespace quic {
@@ -33,25 +33,25 @@
 
   EXPECT_THAT(Http3ErrorToWebTransport(0x52e4a40fa8f7), Optional(0x1cu));
   EXPECT_THAT(Http3ErrorToWebTransport(0x52e4a40fa8f8), Optional(0x1du));
-  EXPECT_THAT(Http3ErrorToWebTransport(0x52e4a40fa8f9), absl::nullopt);
+  EXPECT_THAT(Http3ErrorToWebTransport(0x52e4a40fa8f9), std::nullopt);
   EXPECT_THAT(Http3ErrorToWebTransport(0x52e4a40fa8fa), Optional(0x1eu));
 
-  EXPECT_EQ(Http3ErrorToWebTransport(0), absl::nullopt);
+  EXPECT_EQ(Http3ErrorToWebTransport(0), std::nullopt);
   EXPECT_EQ(Http3ErrorToWebTransport(std::numeric_limits<uint64_t>::max()),
-            absl::nullopt);
+            std::nullopt);
 }
 
 TEST(WebTransportHttp3Test, ErrorCodeRoundTrip) {
   for (int error = 0; error <= 65536; error++) {
     uint64_t http_error = WebTransportErrorToHttp3(error);
-    absl::optional<WebTransportStreamError> mapped_back =
+    std::optional<WebTransportStreamError> mapped_back =
         quic::Http3ErrorToWebTransport(http_error);
     ASSERT_THAT(mapped_back, Optional(error));
   }
   for (int64_t error = 0; error < std::numeric_limits<uint32_t>::max();
        error += 65537) {
     uint64_t http_error = WebTransportErrorToHttp3(error);
-    absl::optional<WebTransportStreamError> mapped_back =
+    std::optional<WebTransportStreamError> mapped_back =
         quic::Http3ErrorToWebTransport(http_error);
     ASSERT_THAT(mapped_back, Optional(error));
   }
diff --git a/quiche/quic/core/io/event_loop_connecting_client_socket.h b/quiche/quic/core/io/event_loop_connecting_client_socket.h
index 16d4a57..a4fb9e9 100644
--- a/quiche/quic/core/io/event_loop_connecting_client_socket.h
+++ b/quiche/quic/core/io/event_loop_connecting_client_socket.h
@@ -5,11 +5,11 @@
 #ifndef QUICHE_QUIC_CORE_IO_EVENT_LOOP_CONNECTING_CLIENT_SOCKET_H_
 #define QUICHE_QUIC_CORE_IO_EVENT_LOOP_CONNECTING_CLIENT_SOCKET_H_
 
+#include <optional>
 #include <string>
 
 #include "absl/status/status.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/variant.h"
 #include "quiche/quic/core/connecting_client_socket.h"
 #include "quiche/quic/core/io/quic_event_loop.h"
@@ -90,7 +90,7 @@
   ConnectStatus connect_status_ = ConnectStatus::kNotConnected;
 
   // Only set while receive in progress or pending, otherwise nullopt.
-  absl::optional<QuicByteCount> receive_max_size_;
+  std::optional<QuicByteCount> receive_max_size_;
 
   // Only contains data while send in progress or pending, otherwise monostate.
   absl::variant<absl::monostate, std::string, quiche::QuicheMemSlice>
diff --git a/quiche/quic/core/io/event_loop_connecting_client_socket_test.cc b/quiche/quic/core/io/event_loop_connecting_client_socket_test.cc
index b0d4406..c7e18ce 100644
--- a/quiche/quic/core/io/event_loop_connecting_client_socket_test.cc
+++ b/quiche/quic/core/io/event_loop_connecting_client_socket_test.cc
@@ -6,6 +6,7 @@
 
 #include <functional>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -14,7 +15,6 @@
 #include "absl/status/status.h"
 #include "absl/status/statusor.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/core/connecting_client_socket.h"
 #include "quiche/quic/core/io/event_loop_socket_factory.h"
@@ -292,9 +292,9 @@
   std::unique_ptr<QuicEventLoop> event_loop_;
   std::unique_ptr<EventLoopSocketFactory> socket_factory_;
 
-  absl::optional<absl::Status> connect_result_;
-  absl::optional<absl::StatusOr<quiche::QuicheMemSlice>> receive_result_;
-  absl::optional<absl::Status> send_result_;
+  std::optional<absl::Status> connect_result_;
+  std::optional<absl::StatusOr<quiche::QuicheMemSlice>> receive_result_;
+  std::optional<absl::Status> send_result_;
 };
 
 std::string GetTestParamName(
diff --git a/quiche/quic/core/quic_buffered_packet_store.cc b/quiche/quic/core/quic_buffered_packet_store.cc
index 48690ce..3c31b6c 100644
--- a/quiche/quic/core/quic_buffered_packet_store.cc
+++ b/quiche/quic/core/quic_buffered_packet_store.cc
@@ -7,11 +7,11 @@
 #include <cstddef>
 #include <list>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/quic_alarm.h"
 #include "quiche/quic/core/quic_alarm_factory.h"
@@ -105,7 +105,7 @@
     QuicConnectionId connection_id, bool ietf_quic,
     const QuicReceivedPacket& packet, QuicSocketAddress self_address,
     QuicSocketAddress peer_address, const ParsedQuicVersion& version,
-    absl::optional<ParsedClientHello> parsed_chlo,
+    std::optional<ParsedClientHello> parsed_chlo,
     ConnectionIdGeneratorInterface* connection_id_generator) {
   const bool is_chlo = parsed_chlo.has_value();
   QUIC_BUG_IF(quic_bug_12410_1, !GetQuicFlag(quic_allow_chlo_buffering))
@@ -209,7 +209,7 @@
       ParsedQuicVersion unused_parsed_version = UnsupportedQuicVersion();
       QuicConnectionId unused_destination_connection_id;
       QuicConnectionId unused_source_connection_id;
-      absl::optional<absl::string_view> unused_retry_token;
+      std::optional<absl::string_view> unused_retry_token;
       std::string unused_detailed_error;
 
       // We don't need to pass |generator| because we already got the correct
@@ -314,7 +314,7 @@
     std::vector<uint16_t>* out_supported_groups,
     std::vector<std::string>* out_alpns, std::string* out_sni,
     bool* out_resumption_attempted, bool* out_early_data_attempted,
-    absl::optional<uint8_t>* tls_alert) {
+    std::optional<uint8_t>* tls_alert) {
   QUICHE_DCHECK_NE(out_alpns, nullptr);
   QUICHE_DCHECK_NE(out_sni, nullptr);
   QUICHE_DCHECK_NE(tls_alert, nullptr);
diff --git a/quiche/quic/core/quic_buffered_packet_store.h b/quiche/quic/core/quic_buffered_packet_store.h
index 012374a..4cff83d 100644
--- a/quiche/quic/core/quic_buffered_packet_store.h
+++ b/quiche/quic/core/quic_buffered_packet_store.h
@@ -8,10 +8,10 @@
 #include <cstdint>
 #include <list>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/quic_alarm.h"
 #include "quiche/quic/core/quic_alarm_factory.h"
@@ -76,7 +76,7 @@
     std::list<BufferedPacket> buffered_packets;
     QuicTime creation_time;
     // |parsed_chlo| is set iff the entire CHLO has been received.
-    absl::optional<ParsedClientHello> parsed_chlo;
+    std::optional<ParsedClientHello> parsed_chlo;
     // Indicating whether this is an IETF QUIC connection.
     bool ietf_quic;
     // If buffered_packets contains the CHLO, it is the version of the CHLO.
@@ -121,7 +121,7 @@
       QuicConnectionId connection_id, bool ietf_quic,
       const QuicReceivedPacket& packet, QuicSocketAddress self_address,
       QuicSocketAddress peer_address, const ParsedQuicVersion& version,
-      absl::optional<ParsedClientHello> parsed_chlo,
+      std::optional<ParsedClientHello> parsed_chlo,
       ConnectionIdGeneratorInterface* connection_id_generator);
 
   // Returns true if there are any packets buffered for |connection_id|.
@@ -144,7 +144,7 @@
       std::vector<uint16_t>* out_supported_groups,
       std::vector<std::string>* out_alpns, std::string* out_sni,
       bool* out_resumption_attempted, bool* out_early_data_attempted,
-      absl::optional<uint8_t>* tls_alert);
+      std::optional<uint8_t>* tls_alert);
 
   // Returns the list of buffered packets for |connection_id| and removes them
   // from the store. Returns an empty list if no early arrived packets for this
diff --git a/quiche/quic/core/quic_buffered_packet_store_test.cc b/quiche/quic/core/quic_buffered_packet_store_test.cc
index 16a53e2..13f75f8 100644
--- a/quiche/quic/core/quic_buffered_packet_store_test.cc
+++ b/quiche/quic/core/quic_buffered_packet_store_test.cc
@@ -8,11 +8,11 @@
 #include <cstdint>
 #include <list>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/crypto/transport_parameters.h"
 #include "quiche/quic/core/quic_connection_id.h"
@@ -40,8 +40,8 @@
 namespace test {
 namespace {
 
-const absl::optional<ParsedClientHello> kNoParsedChlo;
-const absl::optional<ParsedClientHello> kDefaultParsedChlo =
+const std::optional<ParsedClientHello> kNoParsedChlo;
+const std::optional<ParsedClientHello> kDefaultParsedChlo =
     absl::make_optional<ParsedClientHello>();
 
 using BufferedPacket = QuicBufferedPacketStore::BufferedPacket;
@@ -539,7 +539,7 @@
   bool resumption_attempted = false;
   bool early_data_attempted = false;
   QuicConfig config;
-  absl::optional<uint8_t> tls_alert;
+  std::optional<uint8_t> tls_alert;
 
   EXPECT_FALSE(store_.HasBufferedPackets(connection_id));
   store_.EnqueuePacket(connection_id, false, packet_, self_address_,
@@ -608,7 +608,7 @@
         ParsedQuicVersion unused_parsed_version = UnsupportedQuicVersion();
         QuicConnectionId unused_destination_connection_id;
         QuicConnectionId unused_source_connection_id;
-        absl::optional<absl::string_view> unused_retry_token;
+        std::optional<absl::string_view> unused_retry_token;
         std::string unused_detailed_error;
         QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
             *packet, kQuicDefaultConnectionIdLength, &unused_format,
@@ -627,7 +627,7 @@
   ParsedQuicVersion unused_parsed_version = UnsupportedQuicVersion();
   QuicConnectionId unused_destination_connection_id;
   QuicConnectionId unused_source_connection_id;
-  absl::optional<absl::string_view> unused_retry_token;
+  std::optional<absl::string_view> unused_retry_token;
   std::string unused_detailed_error;
   QuicErrorCode error_code = QUIC_NO_ERROR;
 
diff --git a/quiche/quic/core/quic_chaos_protector.cc b/quiche/quic/core/quic_chaos_protector.cc
index 8daaeb7..6760df4 100644
--- a/quiche/quic/core/quic_chaos_protector.cc
+++ b/quiche/quic/core/quic_chaos_protector.cc
@@ -9,9 +9,9 @@
 #include <cstdint>
 #include <limits>
 #include <memory>
+#include <optional>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/quic_random.h"
 #include "quiche/quic/core/frames/quic_crypto_frame.h"
 #include "quiche/quic/core/frames/quic_frame.h"
@@ -45,10 +45,10 @@
 
 QuicChaosProtector::~QuicChaosProtector() { DeleteFrames(&frames_); }
 
-absl::optional<size_t> QuicChaosProtector::BuildDataPacket(
+std::optional<size_t> QuicChaosProtector::BuildDataPacket(
     const QuicPacketHeader& header, char* buffer) {
   if (!CopyCryptoDataToLocalBuffer()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   SplitCryptoFrame();
   AddPingFrames();
@@ -206,7 +206,7 @@
   }
 }
 
-absl::optional<size_t> QuicChaosProtector::BuildPacket(
+std::optional<size_t> QuicChaosProtector::BuildPacket(
     const QuicPacketHeader& header, char* buffer) {
   QuicStreamFrameDataProducer* original_data_producer =
       framer_->data_producer();
@@ -217,7 +217,7 @@
 
   framer_->set_data_producer(original_data_producer);
   if (length == 0) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return length;
 }
diff --git a/quiche/quic/core/quic_chaos_protector.h b/quiche/quic/core/quic_chaos_protector.h
index 9b7636f..f053f89 100644
--- a/quiche/quic/core/quic_chaos_protector.h
+++ b/quiche/quic/core/quic_chaos_protector.h
@@ -7,8 +7,8 @@
 
 #include <cstddef>
 #include <memory>
+#include <optional>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/quic_random.h"
 #include "quiche/quic/core/frames/quic_crypto_frame.h"
 #include "quiche/quic/core/frames/quic_frame.h"
@@ -41,9 +41,9 @@
   QuicChaosProtector& operator=(QuicChaosProtector&&) = delete;
 
   // Attempts to build a data packet with chaos protection. If an error occurs,
-  // then absl::nullopt is returned. Otherwise returns the serialized length.
-  absl::optional<size_t> BuildDataPacket(const QuicPacketHeader& header,
-                                         char* buffer);
+  // then std::nullopt is returned. Otherwise returns the serialized length.
+  std::optional<size_t> BuildDataPacket(const QuicPacketHeader& header,
+                                        char* buffer);
 
   // From QuicStreamFrameDataProducer.
   WriteStreamDataResult WriteStreamData(QuicStreamId id,
@@ -75,8 +75,8 @@
   void SpreadPadding();
 
   // Serialize |frames_| using |framer_|.
-  absl::optional<size_t> BuildPacket(const QuicPacketHeader& header,
-                                     char* buffer);
+  std::optional<size_t> BuildPacket(const QuicPacketHeader& header,
+                                    char* buffer);
 
   size_t packet_size_;
   std::unique_ptr<char[]> crypto_frame_buffer_;
diff --git a/quiche/quic/core/quic_chaos_protector_test.cc b/quiche/quic/core/quic_chaos_protector_test.cc
index 92d3af9..9c312db 100644
--- a/quiche/quic/core/quic_chaos_protector_test.cc
+++ b/quiche/quic/core/quic_chaos_protector_test.cc
@@ -100,7 +100,7 @@
   }
 
   void BuildEncryptAndParse() {
-    absl::optional<size_t> length =
+    std::optional<size_t> length =
         chaos_protector_->BuildDataPacket(header_, packet_buffer_.get());
     ASSERT_TRUE(length.has_value());
     ASSERT_GT(length.value(), 0u);
diff --git a/quiche/quic/core/quic_config.cc b/quiche/quic/core/quic_config.cc
index f0d78ba..75d29f3 100644
--- a/quiche/quic/core/quic_config.cc
+++ b/quiche/quic/core/quic_config.cc
@@ -476,7 +476,7 @@
   google_handshake_message_to_send_ = std::move(message);
 }
 
-const absl::optional<std::string>&
+const std::optional<std::string>&
 QuicConfig::GetReceivedGoogleHandshakeMessage() const {
   return received_google_handshake_message_;
 }
@@ -1405,7 +1405,7 @@
   received_google_handshake_message_.reset();
 }
 
-absl::optional<QuicSocketAddress> QuicConfig::GetPreferredAddressToSend(
+std::optional<QuicSocketAddress> QuicConfig::GetPreferredAddressToSend(
     quiche::IpAddressFamily address_family) const {
   if (alternate_server_address_ipv6_.HasSendValue() &&
       address_family == quiche::IpAddressFamily::IP_V6) {
@@ -1416,7 +1416,7 @@
       address_family == quiche::IpAddressFamily::IP_V4) {
     return alternate_server_address_ipv4_.GetSendValue();
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 void QuicConfig::ClearAlternateServerAddressToSend(
diff --git a/quiche/quic/core/quic_config.h b/quiche/quic/core/quic_config.h
index 152994b..bf1cc6c 100644
--- a/quiche/quic/core/quic_config.h
+++ b/quiche/quic/core/quic_config.h
@@ -7,9 +7,9 @@
 
 #include <cstddef>
 #include <cstdint>
+#include <optional>
 #include <string>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/transport_parameters.h"
 #include "quiche/quic/core/quic_connection_id.h"
 #include "quiche/quic/core/quic_packets.h"
@@ -250,7 +250,7 @@
 
   void SetGoogleHandshakeMessageToSend(std::string message);
 
-  const absl::optional<std::string>& GetReceivedGoogleHandshakeMessage() const;
+  const std::optional<std::string>& GetReceivedGoogleHandshakeMessage() const;
 
   // Sets initial received connection options.  All received connection options
   // will be initialized with these fields. Initial received options may only be
@@ -413,7 +413,7 @@
   bool HasReceivedPreferredAddressConnectionIdAndToken() const;
   const std::pair<QuicConnectionId, StatelessResetToken>&
   ReceivedPreferredAddressConnectionIdAndToken() const;
-  absl::optional<QuicSocketAddress> GetPreferredAddressToSend(
+  std::optional<QuicSocketAddress> GetPreferredAddressToSend(
       quiche::IpAddressFamily address_family) const;
   void ClearAlternateServerAddressToSend(
       quiche::IpAddressFamily address_family);
@@ -552,7 +552,7 @@
   // Note that received_max_idle_timeout_ is only populated if we receive the
   // peer's value, which isn't guaranteed in IETF QUIC as sending is optional.
   QuicTime::Delta max_idle_timeout_to_send_;
-  absl::optional<QuicTime::Delta> received_max_idle_timeout_;
+  std::optional<QuicTime::Delta> received_max_idle_timeout_;
   // Maximum number of dynamic streams that a Google QUIC connection
   // can support or the maximum number of bidirectional streams that
   // an IETF QUIC connection can support.
@@ -607,7 +607,7 @@
   QuicFixedSocketAddress alternate_server_address_ipv4_;
   // Connection Id data to send from the server or receive at the client as part
   // of the preferred address transport parameter.
-  absl::optional<std::pair<QuicConnectionId, StatelessResetToken>>
+  std::optional<std::pair<QuicConnectionId, StatelessResetToken>>
       preferred_address_connection_id_and_token_;
 
   // Stateless reset token used in IETF public reset packet.
@@ -652,20 +652,20 @@
   // Initial packet sent by the client.
   // Uses the original_destination_connection_id transport parameter in
   // IETF QUIC.
-  absl::optional<QuicConnectionId> original_destination_connection_id_to_send_;
-  absl::optional<QuicConnectionId> received_original_destination_connection_id_;
+  std::optional<QuicConnectionId> original_destination_connection_id_to_send_;
+  std::optional<QuicConnectionId> received_original_destination_connection_id_;
 
   // The value that the endpoint included in the Source Connection ID field of
   // the first Initial packet it sent.
   // Uses the initial_source_connection_id transport parameter in IETF QUIC.
-  absl::optional<QuicConnectionId> initial_source_connection_id_to_send_;
-  absl::optional<QuicConnectionId> received_initial_source_connection_id_;
+  std::optional<QuicConnectionId> initial_source_connection_id_to_send_;
+  std::optional<QuicConnectionId> received_initial_source_connection_id_;
 
   // The value that the server included in the Source Connection ID field of a
   // Retry packet it sent.
   // Uses the retry_source_connection_id transport parameter in IETF QUIC.
-  absl::optional<QuicConnectionId> retry_source_connection_id_to_send_;
-  absl::optional<QuicConnectionId> received_retry_source_connection_id_;
+  std::optional<QuicConnectionId> retry_source_connection_id_to_send_;
+  std::optional<QuicConnectionId> received_retry_source_connection_id_;
 
   // Custom transport parameters that can be sent and received in the TLS
   // handshake.
@@ -673,8 +673,8 @@
   TransportParameters::ParameterMap received_custom_transport_parameters_;
 
   // Google internal handshake message.
-  absl::optional<std::string> google_handshake_message_to_send_;
-  absl::optional<std::string> received_google_handshake_message_;
+  std::optional<std::string> google_handshake_message_to_send_;
+  std::optional<std::string> received_google_handshake_message_;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_connection.cc b/quiche/quic/core/quic_connection.cc
index 838d48d..48e5085 100644
--- a/quiche/quic/core/quic_connection.cc
+++ b/quiche/quic/core/quic_connection.cc
@@ -281,7 +281,7 @@
       default_path_(initial_self_address, QuicSocketAddress(),
                     /*client_connection_id=*/EmptyQuicConnectionId(),
                     server_connection_id,
-                    /*stateless_reset_token=*/absl::nullopt),
+                    /*stateless_reset_token=*/std::nullopt),
       active_effective_peer_migration_type_(NO_CHANGE),
       support_key_update_for_connection_(false),
       current_packet_data_(nullptr),
@@ -1497,7 +1497,7 @@
 }
 
 bool QuicConnection::OnAckFrameEnd(
-    QuicPacketNumber start, const absl::optional<QuicEcnCounts>& ecn_counts) {
+    QuicPacketNumber start, const std::optional<QuicEcnCounts>& ecn_counts) {
   QUIC_BUG_IF(quic_bug_12714_7, !connected_)
       << "Processing ACK frame end when connection is closed. Received packet "
          "info: "
@@ -2869,7 +2869,7 @@
     const PathState& default_path, const PathState& alternative_path,
     const QuicConnectionId& server_connection_id,
     QuicConnectionId* client_connection_id,
-    absl::optional<StatelessResetToken>* stateless_reset_token) {
+    std::optional<StatelessResetToken>* stateless_reset_token) {
   QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER &&
                 version().HasIetfQuicFrames());
   if (peer_issued_cid_manager_ == nullptr ||
@@ -3814,7 +3814,7 @@
 
 bool QuicConnection::IsMsgTooBig(const QuicPacketWriter* writer,
                                  const WriteResult& result) {
-  absl::optional<int> writer_error_code = writer->MessageTooBigErrorCode();
+  std::optional<int> writer_error_code = writer->MessageTooBigErrorCode();
   return (result.status == WRITE_STATUS_MSG_TOO_BIG) ||
          (writer_error_code.has_value() && IsWriteError(result.status) &&
           result.error_code == *writer_error_code);
@@ -3874,7 +3874,7 @@
   const std::string error_details = absl::StrCat(
       "Write failed with error: ", error_code, " (", strerror(error_code), ")");
   QUIC_LOG_FIRST_N(ERROR, 2) << ENDPOINT << error_details;
-  absl::optional<int> writer_error_code = writer_->MessageTooBigErrorCode();
+  std::optional<int> writer_error_code = writer_->MessageTooBigErrorCode();
   if (writer_error_code.has_value() && error_code == *writer_error_code) {
     CloseConnection(QUIC_PACKET_WRITE_ERROR, error_details,
                     ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -5291,7 +5291,7 @@
       sent_packet_manager_.SetRttStats(*alternative_path_.rtt_stats);
 
       // Explicitly clear alternative_path_.rtt_stats
-      alternative_path_.rtt_stats = absl::nullopt;
+      alternative_path_.rtt_stats = std::nullopt;
     }
   }
   // Update to the new peer address.
@@ -5302,7 +5302,7 @@
     SetDefaultPathState(std::move(alternative_path_));
   } else {
     QuicConnectionId client_connection_id;
-    absl::optional<StatelessResetToken> stateless_reset_token;
+    std::optional<StatelessResetToken> stateless_reset_token;
     FindMatchingOrNewClientConnectionIdOrToken(
         previous_default_path, alternative_path_,
         last_received_packet_info_.destination_connection_id,
@@ -5509,7 +5509,7 @@
             << "No validated peer address to send after handshake comfirmed.";
       } else if (!IsReceivedPeerAddressValidated()) {
         QuicConnectionId client_connection_id;
-        absl::optional<StatelessResetToken> stateless_reset_token;
+        std::optional<StatelessResetToken> stateless_reset_token;
         FindMatchingOrNewClientConnectionIdOrToken(
             default_path_, alternative_path_,
             last_received_packet_info_.destination_connection_id,
@@ -6537,10 +6537,10 @@
   known_server_addresses_.push_back(address);
 }
 
-absl::optional<QuicNewConnectionIdFrame>
+std::optional<QuicNewConnectionIdFrame>
 QuicConnection::MaybeIssueNewConnectionIdForPreferredAddress() {
   if (self_issued_cid_manager_ == nullptr) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   return self_issued_cid_manager_
       ->MaybeIssueNewConnectionIdForPreferredAddress();
@@ -6673,7 +6673,7 @@
       return;
     }
     QuicConnectionId client_connection_id, server_connection_id;
-    absl::optional<StatelessResetToken> stateless_reset_token;
+    std::optional<StatelessResetToken> stateless_reset_token;
     if (self_issued_cid_manager_ != nullptr) {
       client_connection_id =
           *self_issued_cid_manager_->ConsumeOneConnectionId();
@@ -7061,7 +7061,7 @@
   bytes_received_before_address_validation = 0;
   bytes_sent_before_address_validation = 0;
   send_algorithm = nullptr;
-  rtt_stats = absl::nullopt;
+  rtt_stats = std::nullopt;
   stateless_reset_token.reset();
   ecn_marked_packet_acked = false;
   ecn_pto_count = 0;
diff --git a/quiche/quic/core/quic_connection.h b/quiche/quic/core/quic_connection.h
index d9b5242..713193b 100644
--- a/quiche/quic/core/quic_connection.h
+++ b/quiche/quic/core/quic_connection.h
@@ -21,11 +21,11 @@
 #include <list>
 #include <map>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/congestion_control/rtt_stats.h"
 #include "quiche/quic/core/crypto/quic_decrypter.h"
 #include "quiche/quic/core/crypto/quic_encrypter.h"
@@ -689,7 +689,7 @@
   bool OnAckTimestamp(QuicPacketNumber packet_number,
                       QuicTime timestamp) override;
   bool OnAckFrameEnd(QuicPacketNumber start,
-                     const absl::optional<QuicEcnCounts>& ecn_counts) override;
+                     const std::optional<QuicEcnCounts>& ecn_counts) override;
   bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
   bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
   bool OnPingFrame(const QuicPingFrame& frame) override;
@@ -1294,7 +1294,7 @@
 
   void AddKnownServerAddress(const QuicSocketAddress& address);
 
-  absl::optional<QuicNewConnectionIdFrame>
+  std::optional<QuicNewConnectionIdFrame>
   MaybeIssueNewConnectionIdForPreferredAddress();
 
   // Kicks off validation of received server preferred address.
@@ -1458,7 +1458,7 @@
               const QuicSocketAddress& alternative_peer_address,
               const QuicConnectionId& client_connection_id,
               const QuicConnectionId& server_connection_id,
-              absl::optional<StatelessResetToken> stateless_reset_token)
+              std::optional<StatelessResetToken> stateless_reset_token)
         : self_address(alternative_self_address),
           peer_address(alternative_peer_address),
           client_connection_id(client_connection_id),
@@ -1477,7 +1477,7 @@
     QuicSocketAddress peer_address;
     QuicConnectionId client_connection_id;
     QuicConnectionId server_connection_id;
-    absl::optional<StatelessResetToken> stateless_reset_token;
+    std::optional<StatelessResetToken> stateless_reset_token;
     // True if the peer address has been validated. Address is considered
     // validated when 1) an address token of the peer address is received and
     // validated, or 2) a HANDSHAKE packet has been successfully processed on
@@ -1490,7 +1490,7 @@
     // Points to the send algorithm on the old default path while connection is
     // validating migrated peer address. Nullptr otherwise.
     std::unique_ptr<SendAlgorithmInterface> send_algorithm;
-    absl::optional<RttStats> rtt_stats;
+    std::optional<RttStats> rtt_stats;
     // If true, an ECN packet was acked on this path, so the path probably isn't
     // dropping ECN-marked packets.
     bool ecn_marked_packet_acked = false;
@@ -1549,7 +1549,7 @@
     QuicByteCount length = 0;
     QuicConnectionId destination_connection_id;
     // Fields below are only populated if packet gets decrypted successfully.
-    // TODO(fayang): consider using absl::optional for following fields.
+    // TODO(fayang): consider using std::optional for following fields.
     bool decrypted = false;
     EncryptionLevel decrypted_level = ENCRYPTION_INITIAL;
     QuicPacketHeader header;
@@ -1679,7 +1679,7 @@
       const PathState& default_path, const PathState& alternative_path,
       const QuicConnectionId& server_connection_id,
       QuicConnectionId* client_connection_id,
-      absl::optional<StatelessResetToken>* stateless_reset_token);
+      std::optional<StatelessResetToken>* stateless_reset_token);
 
   // Returns true and sets connection IDs if (self_address, peer_address)
   // corresponds to either the default path or alternative path. Returns false
@@ -2255,14 +2255,14 @@
   // |server_connection_id_| with the value from that packet and save off the
   // original value of |server_connection_id_| into
   // |original_destination_connection_id_| for validation.
-  absl::optional<QuicConnectionId> original_destination_connection_id_;
+  std::optional<QuicConnectionId> original_destination_connection_id_;
 
   // The connection ID that replaces original_destination_connection_id_.
   QuicConnectionId original_destination_connection_id_replacement_;
 
   // After we receive a RETRY packet, |retry_source_connection_id_| contains
   // the source connection ID from that packet.
-  absl::optional<QuicConnectionId> retry_source_connection_id_;
+  std::optional<QuicConnectionId> retry_source_connection_id_;
 
   // Used to store content of packets which cannot be sent because of write
   // blocked. Packets' encrypted buffers are copied and owned by
diff --git a/quiche/quic/core/quic_connection_id_manager.cc b/quiche/quic/core/quic_connection_id_manager.cc
index b8524d1..9c0d3bd 100644
--- a/quiche/quic/core/quic_connection_id_manager.cc
+++ b/quiche/quic/core/quic_connection_id_manager.cc
@@ -298,9 +298,9 @@
   retire_connection_id_alarm_->Cancel();
 }
 
-absl::optional<QuicNewConnectionIdFrame>
+std::optional<QuicNewConnectionIdFrame>
 QuicSelfIssuedConnectionIdManager::MaybeIssueNewConnectionId() {
-  absl::optional<QuicConnectionId> new_cid =
+  std::optional<QuicConnectionId> new_cid =
       connection_id_generator_.GenerateNextConnectionId(last_connection_id_);
   if (!new_cid.has_value()) {
     return {};
@@ -320,9 +320,9 @@
   return frame;
 }
 
-absl::optional<QuicNewConnectionIdFrame> QuicSelfIssuedConnectionIdManager::
+std::optional<QuicNewConnectionIdFrame> QuicSelfIssuedConnectionIdManager::
     MaybeIssueNewConnectionIdForPreferredAddress() {
-  absl::optional<QuicNewConnectionIdFrame> frame = MaybeIssueNewConnectionId();
+  std::optional<QuicNewConnectionIdFrame> frame = MaybeIssueNewConnectionId();
   QUICHE_DCHECK(!frame.has_value() || (frame->sequence_number == 1u));
   return frame;
 }
@@ -413,8 +413,7 @@
 
 void QuicSelfIssuedConnectionIdManager::MaybeSendNewConnectionIds() {
   while (active_connection_ids_.size() < active_connection_id_limit_) {
-    absl::optional<QuicNewConnectionIdFrame> frame =
-        MaybeIssueNewConnectionId();
+    std::optional<QuicNewConnectionIdFrame> frame = MaybeIssueNewConnectionId();
     if (!frame.has_value()) {
       break;
     }
@@ -434,7 +433,7 @@
   return false;
 }
 
-absl::optional<QuicConnectionId>
+std::optional<QuicConnectionId>
 QuicSelfIssuedConnectionIdManager::ConsumeOneConnectionId() {
   for (const auto& active_cid_data : active_connection_ids_) {
     if (active_cid_data.second >
@@ -447,7 +446,7 @@
       return active_cid_data.first;
     }
   }
-  return absl::nullopt;
+  return std::nullopt;
 }
 
 bool QuicSelfIssuedConnectionIdManager::IsConnectionIdInUse(
diff --git a/quiche/quic/core/quic_connection_id_manager.h b/quiche/quic/core/quic_connection_id_manager.h
index 96c4c97..80f1a6f 100644
--- a/quiche/quic/core/quic_connection_id_manager.h
+++ b/quiche/quic/core/quic_connection_id_manager.h
@@ -12,8 +12,8 @@
 
 #include <cstddef>
 #include <memory>
+#include <optional>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/frames/quic_new_connection_id_frame.h"
 #include "quiche/quic/core/frames/quic_retire_connection_id_frame.h"
@@ -133,7 +133,7 @@
 
   virtual ~QuicSelfIssuedConnectionIdManager();
 
-  absl::optional<QuicNewConnectionIdFrame>
+  std::optional<QuicNewConnectionIdFrame>
   MaybeIssueNewConnectionIdForPreferredAddress();
 
   QuicErrorCode OnRetireConnectionIdFrame(
@@ -155,7 +155,7 @@
   // connection ID with a new probing/migration path when client uses
   // non-empty connection ID.
   bool HasConnectionIdToConsume() const;
-  absl::optional<QuicConnectionId> ConsumeOneConnectionId();
+  std::optional<QuicConnectionId> ConsumeOneConnectionId();
 
   // Returns true if the given connection ID is issued by the
   // QuicSelfIssuedConnectionIdManager and not retired locally yet. Called to
@@ -166,7 +166,7 @@
   friend class test::QuicConnectionIdManagerPeer;
 
   // Issue a new connection ID. Can return nullopt.
-  absl::optional<QuicNewConnectionIdFrame> MaybeIssueNewConnectionId();
+  std::optional<QuicNewConnectionIdFrame> MaybeIssueNewConnectionId();
 
   // This should be set to the min of:
   // (1) # of active connection IDs that peer can maintain.
diff --git a/quiche/quic/core/quic_connection_id_manager_test.cc b/quiche/quic/core/quic_connection_id_manager_test.cc
index 466ba27..eba37f1 100644
--- a/quiche/quic/core/quic_connection_id_manager_test.cc
+++ b/quiche/quic/core/quic_connection_id_manager_test.cc
@@ -1013,7 +1013,7 @@
   QuicConnectionId cid1 = CheckGenerate(cid0);
   EXPECT_CALL(cid_manager_visitor_, MaybeReserveConnectionId(cid1))
       .WillOnce(Return(true));
-  absl::optional<QuicNewConnectionIdFrame> new_cid_frame =
+  std::optional<QuicNewConnectionIdFrame> new_cid_frame =
       cid_manager_.MaybeIssueNewConnectionIdForPreferredAddress();
   ASSERT_TRUE(new_cid_frame.has_value());
   ASSERT_THAT(*new_cid_frame, ExpectedNewConnectionIdFrame(cid1, 1u, 0u));
diff --git a/quiche/quic/core/quic_connection_stats.h b/quiche/quic/core/quic_connection_stats.h
index 5551659..67a3884 100644
--- a/quiche/quic/core/quic_connection_stats.h
+++ b/quiche/quic/core/quic_connection_stats.h
@@ -247,9 +247,9 @@
   // is performed by TlsServerHandshaker. If an operation is done within
   // BoringSSL, e.g. ticket decrypted without using
   // TlsServerHandshaker::SessionTicketOpen, it will not be recorded here.
-  absl::optional<TlsServerOperationStats> tls_server_select_cert_stats;
-  absl::optional<TlsServerOperationStats> tls_server_compute_signature_stats;
-  absl::optional<TlsServerOperationStats> tls_server_decrypt_ticket_stats;
+  std::optional<TlsServerOperationStats> tls_server_select_cert_stats;
+  std::optional<TlsServerOperationStats> tls_server_compute_signature_stats;
+  std::optional<TlsServerOperationStats> tls_server_decrypt_ticket_stats;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_connection_test.cc b/quiche/quic/core/quic_connection_test.cc
index b7f6e1a..ecfb82b 100644
--- a/quiche/quic/core/quic_connection_test.cc
+++ b/quiche/quic/core/quic_connection_test.cc
@@ -17126,7 +17126,7 @@
               GenerateNextConnectionId(connection_id_))
       .WillOnce(Return(server_issued_cid_for_preferred_address));
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_)).WillOnce(Return(true));
-  absl::optional<QuicNewConnectionIdFrame> frame =
+  std::optional<QuicNewConnectionIdFrame> frame =
       connection_.MaybeIssueNewConnectionIdForPreferredAddress();
   ASSERT_TRUE(frame.has_value());
 
@@ -17179,7 +17179,7 @@
               GenerateNextConnectionId(connection_id_))
       .WillOnce(Return(server_issued_cid_for_preferred_address));
   EXPECT_CALL(visitor_, MaybeReserveConnectionId(_)).WillOnce(Return(true));
-  absl::optional<QuicNewConnectionIdFrame> frame =
+  std::optional<QuicNewConnectionIdFrame> frame =
       connection_.MaybeIssueNewConnectionIdForPreferredAddress();
   ASSERT_TRUE(frame.has_value());
 
diff --git a/quiche/quic/core/quic_crypto_stream.cc b/quiche/quic/core/quic_crypto_stream.cc
index 925baa6..a3df09b 100644
--- a/quiche/quic/core/quic_crypto_stream.cc
+++ b/quiche/quic/core/quic_crypto_stream.cc
@@ -4,11 +4,11 @@
 
 #include "quiche/quic/core/quic_crypto_stream.h"
 
+#include <optional>
 #include <string>
 
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/crypto_handshake.h"
 #include "quiche/quic/core/frames/quic_crypto_frame.h"
 #include "quiche/quic/core/quic_connection.h"
diff --git a/quiche/quic/core/quic_crypto_stream_test.cc b/quiche/quic/core/quic_crypto_stream_test.cc
index 70928ae..9aa747f 100644
--- a/quiche/quic/core/quic_crypto_stream_test.cc
+++ b/quiche/quic/core/quic_crypto_stream_test.cc
@@ -500,7 +500,7 @@
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_.ConsumeData(
             QuicUtils::GetCryptoStreamId(connection_->transport_version()), 150,
-            1350, NO_FIN, HANDSHAKE_RETRANSMISSION, absl::nullopt);
+            1350, NO_FIN, HANDSHAKE_RETRANSMISSION, std::nullopt);
       }));
 
   EXPECT_FALSE(stream_->RetransmitStreamData(1350, 1350, false,
diff --git a/quiche/quic/core/quic_datagram_queue.cc b/quiche/quic/core/quic_datagram_queue.cc
index 0b7b3f5..d2137ef 100644
--- a/quiche/quic/core/quic_datagram_queue.cc
+++ b/quiche/quic/core/quic_datagram_queue.cc
@@ -45,10 +45,10 @@
   return MESSAGE_STATUS_BLOCKED;
 }
 
-absl::optional<MessageStatus> QuicDatagramQueue::TrySendingNextDatagram() {
+std::optional<MessageStatus> QuicDatagramQueue::TrySendingNextDatagram() {
   RemoveExpiredDatagrams();
   if (queue_.empty()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   MessageResult result =
@@ -65,7 +65,7 @@
 size_t QuicDatagramQueue::SendDatagrams() {
   size_t num_datagrams = 0;
   for (;;) {
-    absl::optional<MessageStatus> status = TrySendingNextDatagram();
+    std::optional<MessageStatus> status = TrySendingNextDatagram();
     if (!status.has_value()) {
       break;
     }
@@ -94,7 +94,7 @@
     ++expired_datagram_count_;
     queue_.pop_front();
     if (observer_) {
-      observer_->OnDatagramProcessed(absl::nullopt);
+      observer_->OnDatagramProcessed(std::nullopt);
     }
   }
 }
diff --git a/quiche/quic/core/quic_datagram_queue.h b/quiche/quic/core/quic_datagram_queue.h
index ca79265..9f4428b 100644
--- a/quiche/quic/core/quic_datagram_queue.h
+++ b/quiche/quic/core/quic_datagram_queue.h
@@ -7,8 +7,8 @@
 
 #include <cstdint>
 #include <memory>
+#include <optional>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/common/platform/api/quiche_mem_slice.h"
@@ -34,7 +34,7 @@
     // This function is called synchronously in `QuicDatagramQueue` methods.
     // `status` is nullopt when the datagram is dropped due to being in the
     // queue for too long.
-    virtual void OnDatagramProcessed(absl::optional<MessageStatus> status) = 0;
+    virtual void OnDatagramProcessed(std::optional<MessageStatus> status) = 0;
   };
 
   // |session| is not owned and must outlive this object.
@@ -49,7 +49,7 @@
 
   // Attempts to send a single datagram from the queue.  Returns the result of
   // SendMessage(), or nullopt if there were no unexpired datagrams to send.
-  absl::optional<MessageStatus> TrySendingNextDatagram();
+  std::optional<MessageStatus> TrySendingNextDatagram();
 
   // Sends all of the unexpired datagrams until either the connection becomes
   // write-blocked or the queue is empty.  Returns the number of datagrams sent.
diff --git a/quiche/quic/core/quic_datagram_queue_test.cc b/quiche/quic/core/quic_datagram_queue_test.cc
index 7895941..6cbf09f 100644
--- a/quiche/quic/core/quic_datagram_queue_test.cc
+++ b/quiche/quic/core/quic_datagram_queue_test.cc
@@ -4,10 +4,10 @@
 
 #include "quiche/quic/core/quic_datagram_queue.h"
 
+#include <optional>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/null_encrypter.h"
 #include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/core/quic_types.h"
@@ -36,7 +36,7 @@
  public:
   class Context : public quiche::QuicheReferenceCounted {
    public:
-    std::vector<absl::optional<MessageStatus>> statuses;
+    std::vector<std::optional<MessageStatus>> statuses;
   };
 
   QuicDatagramQueueObserver() : context_(new Context()) {}
@@ -44,7 +44,7 @@
   QuicDatagramQueueObserver& operator=(const QuicDatagramQueueObserver&) =
       delete;
 
-  void OnDatagramProcessed(absl::optional<MessageStatus> status) override {
+  void OnDatagramProcessed(std::optional<MessageStatus> status) override {
     context_->statuses.push_back(std::move(status));
   }
 
@@ -108,7 +108,7 @@
   // Verify getting write blocked does not remove the datagram from the queue.
   EXPECT_CALL(*connection_, SendMessage(_, _, _))
       .WillOnce(Return(MESSAGE_STATUS_BLOCKED));
-  absl::optional<MessageStatus> status = queue_.TrySendingNextDatagram();
+  std::optional<MessageStatus> status = queue_.TrySendingNextDatagram();
   ASSERT_TRUE(status.has_value());
   EXPECT_EQ(MESSAGE_STATUS_BLOCKED, *status);
   EXPECT_EQ(1u, queue_.queue_size());
@@ -122,7 +122,7 @@
 }
 
 TEST_F(QuicDatagramQueueTest, EmptyBuffer) {
-  absl::optional<MessageStatus> status = queue_.TrySendingNextDatagram();
+  std::optional<MessageStatus> status = queue_.TrySendingNextDatagram();
   EXPECT_FALSE(status.has_value());
 
   size_t num_messages = queue_.SendDatagrams();
@@ -289,7 +289,7 @@
   EXPECT_TRUE(context_->statuses.empty());
 
   EXPECT_EQ(0u, queue_.SendDatagrams());
-  EXPECT_THAT(context_->statuses, ElementsAre(absl::nullopt));
+  EXPECT_THAT(context_->statuses, ElementsAre(std::nullopt));
 }
 
 }  // namespace
diff --git a/quiche/quic/core/quic_default_packet_writer.cc b/quiche/quic/core/quic_default_packet_writer.cc
index 6d45217..7fd7400 100644
--- a/quiche/quic/core/quic_default_packet_writer.cc
+++ b/quiche/quic/core/quic_default_packet_writer.cc
@@ -34,7 +34,7 @@
 
 void QuicDefaultPacketWriter::SetWritable() { write_blocked_ = false; }
 
-absl::optional<int> QuicDefaultPacketWriter::MessageTooBigErrorCode() const {
+std::optional<int> QuicDefaultPacketWriter::MessageTooBigErrorCode() const {
   return kSocketErrorMsgSize;
 }
 
diff --git a/quiche/quic/core/quic_default_packet_writer.h b/quiche/quic/core/quic_default_packet_writer.h
index ab41c91..cb26266 100644
--- a/quiche/quic/core/quic_default_packet_writer.h
+++ b/quiche/quic/core/quic_default_packet_writer.h
@@ -32,7 +32,7 @@
                           const QuicPacketWriterParams& params) override;
   bool IsWriteBlocked() const override;
   void SetWritable() override;
-  absl::optional<int> MessageTooBigErrorCode() const override;
+  std::optional<int> MessageTooBigErrorCode() const override;
   QuicByteCount GetMaxPacketSize(
       const QuicSocketAddress& peer_address) const override;
   bool SupportsReleaseTime() const override;
diff --git a/quiche/quic/core/quic_dispatcher.cc b/quiche/quic/core/quic_dispatcher.cc
index 9ca0d82..3984426 100644
--- a/quiche/quic/core/quic_dispatcher.cc
+++ b/quiche/quic/core/quic_dispatcher.cc
@@ -11,6 +11,7 @@
 #include <cstdint>
 #include <list>
 #include <memory>
+#include <optional>
 #include <ostream>
 #include <string>
 #include <utility>
@@ -21,7 +22,6 @@
 #include "absl/container/flat_hash_set.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/chlo_extractor.h"
 #include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/crypto/crypto_handshake_message.h"
@@ -1187,7 +1187,7 @@
       packet_info.destination_connection_id,
       packet_info.form != GOOGLE_QUIC_PACKET, packet_info.packet,
       packet_info.self_address, packet_info.peer_address, packet_info.version,
-      /*parsed_chlo=*/absl::nullopt, /*connection_id_generator=*/nullptr);
+      /*parsed_chlo=*/std::nullopt, /*connection_id_generator=*/nullptr);
   if (rs != EnqueuePacketResult::SUCCESS) {
     OnBufferPacketFailure(rs, packet_info.destination_connection_id);
   }
@@ -1291,7 +1291,7 @@
   if (connection_id_generator == nullptr) {
     connection_id_generator = &ConnectionIdGenerator();
   }
-  absl::optional<QuicConnectionId> server_connection_id =
+  std::optional<QuicConnectionId> server_connection_id =
       connection_id_generator->MaybeReplaceConnectionId(original_connection_id,
                                                         version);
   const bool replaced_connection_id = server_connection_id.has_value();
diff --git a/quiche/quic/core/quic_dispatcher.h b/quiche/quic/core/quic_dispatcher.h
index 7224712..151c582 100644
--- a/quiche/quic/core/quic_dispatcher.h
+++ b/quiche/quic/core/quic_dispatcher.h
@@ -12,13 +12,13 @@
 #include <cstdint>
 #include <list>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/container/flat_hash_map.h"
 #include "absl/container/flat_hash_set.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/crypto/quic_compressed_certs_cache.h"
 #include "quiche/quic/core/frames/quic_rst_stream_frame.h"
@@ -371,10 +371,10 @@
 
   struct ExtractChloResult {
     // If set, a full client hello has been successfully parsed.
-    absl::optional<ParsedClientHello> parsed_chlo;
+    std::optional<ParsedClientHello> parsed_chlo;
     // If set, the TLS alert that will cause a connection close.
     // Always empty for Google QUIC.
-    absl::optional<uint8_t> tls_alert;
+    std::optional<uint8_t> tls_alert;
   };
 
   // Try to extract information(sni, alpns, ...) if the full Client Hello has
diff --git a/quiche/quic/core/quic_dispatcher_test.cc b/quiche/quic/core/quic_dispatcher_test.cc
index 03e68c4..f921147 100644
--- a/quiche/quic/core/quic_dispatcher_test.cc
+++ b/quiche/quic/core/quic_dispatcher_test.cc
@@ -8,6 +8,7 @@
 #include <cstdint>
 #include <map>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -16,7 +17,6 @@
 #include "absl/base/macros.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/chlo_extractor.h"
 #include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/crypto/crypto_protocol.h"
@@ -487,7 +487,7 @@
       } else {
         EXPECT_CALL(connection_id_generator_,
                     MaybeReplaceConnectionId(server_connection_id, version))
-            .WillOnce(Return(absl::nullopt));
+            .WillOnce(Return(std::nullopt));
       }
     }
     std::vector<std::unique_ptr<QuicReceivedPacket>> packets =
@@ -590,7 +590,7 @@
   bool expect_generator_is_called_ = true;
   // Set in conditions where the generator should return a different connection
   // ID.
-  absl::optional<QuicConnectionId> generated_connection_id_;
+  std::optional<QuicConnectionId> generated_connection_id_;
   MockConnectionIdGenerator connection_id_generator_;
   std::unique_ptr<NiceMock<TestDispatcher>> dispatcher_;
   MockTimeWaitListManager* time_wait_list_manager_;
@@ -599,7 +599,7 @@
   std::map<QuicConnectionId, std::list<std::string>> data_connection_map_;
   QuicBufferedPacketStore* store_;
   uint64_t connection_id_;
-  absl::optional<std::string> address_token_;
+  std::optional<std::string> address_token_;
 };
 
 class QuicDispatcherTestAllVersions : public QuicDispatcherTestBase {};
@@ -655,7 +655,7 @@
       mock_connection_id_generator;
   EXPECT_CALL(mock_connection_id_generator,
               MaybeReplaceConnectionId(TestConnectionId(1), version_))
-      .WillOnce(Return(absl::nullopt));
+      .WillOnce(Return(std::nullopt));
   EXPECT_CALL(*dispatcher_,
               CreateQuicSession(TestConnectionId(1), _, client_address,
                                 Eq(ExpectedAlpn()), _, MatchParsedClientHello(),
@@ -721,7 +721,7 @@
     new_connection_id = original_connection_id;
     EXPECT_CALL(connection_id_generator_,
                 MaybeReplaceConnectionId(original_connection_id, version_))
-        .WillOnce(Return(absl::nullopt));
+        .WillOnce(Return(std::nullopt));
   }
   QuicConfig client_config = DefaultQuicConfig();
   // Add a 2000-byte custom parameter to increase the length of the CHLO.
@@ -2565,7 +2565,7 @@
   // buffered should be delivered to the session.
   EXPECT_CALL(connection_id_generator_,
               MaybeReplaceConnectionId(conn_id, version_))
-      .WillOnce(Return(absl::nullopt));
+      .WillOnce(Return(std::nullopt));
   EXPECT_CALL(*dispatcher_,
               CreateQuicSession(conn_id, _, client_addr_, Eq(ExpectedAlpn()), _,
                                 MatchParsedClientHello(), _))
@@ -2601,7 +2601,7 @@
   // buffered should be delivered to the session.
   EXPECT_CALL(connection_id_generator_,
               MaybeReplaceConnectionId(conn_id, version_))
-      .WillOnce(Return(absl::nullopt));
+      .WillOnce(Return(std::nullopt));
   EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, _, client_addr_,
                                               Eq(ExpectedAlpn()), _, _, _))
       .WillOnce(Return(ByMove(CreateSession(
@@ -2652,7 +2652,7 @@
     QuicConnectionId conn_id = TestConnectionId(i);
     EXPECT_CALL(connection_id_generator_,
                 MaybeReplaceConnectionId(conn_id, version_))
-        .WillOnce(Return(absl::nullopt));
+        .WillOnce(Return(std::nullopt));
     EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, _, client_address,
                                                 Eq(ExpectedAlpn()), _, _, _))
         .WillOnce(Return(ByMove(CreateSession(
@@ -2700,7 +2700,7 @@
   // buffered should be delivered to the session.
   EXPECT_CALL(connection_id_generator_,
               MaybeReplaceConnectionId(conn_id, version_))
-      .WillOnce(Return(absl::nullopt));
+      .WillOnce(Return(std::nullopt));
   EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id, _, client_addr_,
                                               Eq(ExpectedAlpn()), _, _, _))
       .Times(1)  // Only triggered by 1st CHLO.
@@ -2768,7 +2768,7 @@
     if (conn_id <= kMaxNumSessionsToCreate) {
       EXPECT_CALL(connection_id_generator_,
                   MaybeReplaceConnectionId(TestConnectionId(conn_id), version_))
-          .WillOnce(Return(absl::nullopt));
+          .WillOnce(Return(std::nullopt));
       EXPECT_CALL(
           *dispatcher_,
           CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
@@ -2808,7 +2808,7 @@
        ++conn_id) {
     EXPECT_CALL(connection_id_generator_,
                 MaybeReplaceConnectionId(TestConnectionId(conn_id), version_))
-        .WillOnce(Return(absl::nullopt));
+        .WillOnce(Return(std::nullopt));
     EXPECT_CALL(
         *dispatcher_,
         CreateQuicSession(TestConnectionId(conn_id), _, client_addr_,
@@ -2886,7 +2886,7 @@
   // created using generator2.
   EXPECT_CALL(generator2,
               MaybeReplaceConnectionId(TestConnectionId(conn_id), version_))
-      .WillOnce(Return(absl::nullopt));
+      .WillOnce(Return(std::nullopt));
   EXPECT_CALL(*dispatcher_, CreateQuicSession(TestConnectionId(conn_id), _,
                                               client_addr_, Eq(ExpectedAlpn()),
                                               _, MatchParsedClientHello(), _))
diff --git a/quiche/quic/core/quic_framer.cc b/quiche/quic/core/quic_framer.cc
index b17b8c9..b967645 100644
--- a/quiche/quic/core/quic_framer.cc
+++ b/quiche/quic/core/quic_framer.cc
@@ -10,6 +10,7 @@
 #include <cstdint>
 #include <limits>
 #include <memory>
+#include <optional>
 #include <string>
 #include <type_traits>
 #include <utility>
@@ -23,7 +24,6 @@
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/crypto_framer.h"
 #include "quiche/quic/core/crypto/crypto_handshake.h"
 #include "quiche/quic/core/crypto/crypto_handshake_message.h"
@@ -3481,7 +3481,7 @@
   }
 
   // Done processing the ACK frame.
-  absl::optional<QuicEcnCounts> ecn_counts = absl::nullopt;
+  std::optional<QuicEcnCounts> ecn_counts = std::nullopt;
   if (!visitor_->OnAckFrameEnd(QuicPacketNumber(first_received), ecn_counts)) {
     set_detailed_error(
         "Error occurs when visitor finishes processing the ACK frame.");
@@ -5499,7 +5499,7 @@
 
   // |effective_prev_time| is the exponent-encoded timestamp of the previous
   // packet.
-  absl::optional<QuicTime> effective_prev_time;
+  std::optional<QuicTime> effective_prev_time;
   for (const AckTimestampRange& range : timestamp_ranges) {
     QUIC_DVLOG(3) << "Range: gap:" << range.gap << ", beg:" << range.range_begin
                   << ", end:" << range.range_end;
@@ -6341,7 +6341,7 @@
     QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version,
     QuicConnectionId* destination_connection_id,
     QuicConnectionId* source_connection_id,
-    absl::optional<absl::string_view>* retry_token,
+    std::optional<absl::string_view>* retry_token,
     std::string* detailed_error) {
   QuicDataReader reader(packet.data(), packet.length());
   if (reader.IsDoneReading()) {
@@ -6393,7 +6393,7 @@
     ParsedQuicVersion* parsed_version,
     QuicConnectionId* destination_connection_id,
     QuicConnectionId* source_connection_id,
-    absl::optional<absl::string_view>* retry_token, std::string* detailed_error,
+    std::optional<absl::string_view>* retry_token, std::string* detailed_error,
     ConnectionIdGeneratorInterface& generator) {
   QuicDataReader reader(packet.data(), packet.length());
   // Get the first two bytes.
diff --git a/quiche/quic/core/quic_framer.h b/quiche/quic/core/quic_framer.h
index c173925..62c4ce8 100644
--- a/quiche/quic/core/quic_framer.h
+++ b/quiche/quic/core/quic_framer.h
@@ -165,7 +165,7 @@
   // the reported ECN counts in the ack frame, if present.
   virtual bool OnAckFrameEnd(
       QuicPacketNumber start,
-      const absl::optional<QuicEcnCounts>& ecn_counts) = 0;
+      const std::optional<QuicEcnCounts>& ecn_counts) = 0;
 
   // Called when a StopWaitingFrame has been parsed.
   virtual bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) = 0;
@@ -457,7 +457,7 @@
       QuicVersionLabel* version_label, ParsedQuicVersion* parsed_version,
       QuicConnectionId* destination_connection_id,
       QuicConnectionId* source_connection_id,
-      absl::optional<absl::string_view>* retry_token,
+      std::optional<absl::string_view>* retry_token,
       std::string* detailed_error);
 
   // Parses the unencrypted fields in |packet| and stores them in the other
@@ -475,7 +475,7 @@
       ParsedQuicVersion* parsed_version,
       QuicConnectionId* destination_connection_id,
       QuicConnectionId* source_connection_id,
-      absl::optional<absl::string_view>* retry_token,
+      std::optional<absl::string_view>* retry_token,
       std::string* detailed_error, ConnectionIdGeneratorInterface& generator);
 
   // Serializes a packet containing |frames| into |buffer|.
diff --git a/quiche/quic/core/quic_framer_test.cc b/quiche/quic/core/quic_framer_test.cc
index 9e200ba..e9dded2 100644
--- a/quiche/quic/core/quic_framer_test.cc
+++ b/quiche/quic/core/quic_framer_test.cc
@@ -394,7 +394,7 @@
 
   bool OnAckFrameEnd(
       QuicPacketNumber /*start*/,
-      const absl::optional<QuicEcnCounts>& /*ecn_counts*/) override {
+      const std::optional<QuicEcnCounts>& /*ecn_counts*/) override {
     return true;
   }
 
@@ -1132,7 +1132,7 @@
   QuicVersionLabel version_label;
   std::string detailed_error;
   bool use_length_prefix;
-  absl::optional<absl::string_view> retry_token;
+  std::optional<absl::string_view> retry_token;
   ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
   const QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
       *encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -1209,7 +1209,7 @@
   QuicVersionLabel version_label = 0;
   std::string detailed_error = "";
   bool use_length_prefix;
-  absl::optional<absl::string_view> retry_token;
+  std::optional<absl::string_view> retry_token;
   ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
   const QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
       encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -1237,7 +1237,7 @@
   QuicVersionLabel version_label = 0;
   std::string detailed_error = "";
   bool use_length_prefix;
-  absl::optional<absl::string_view> retry_token;
+  std::optional<absl::string_view> retry_token;
   ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
   const QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
       encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -13043,7 +13043,7 @@
   ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
   QuicConnectionId destination_connection_id = TestConnectionId(1);
   QuicConnectionId source_connection_id = TestConnectionId(2);
-  absl::optional<absl::string_view> retry_token;
+  std::optional<absl::string_view> retry_token;
   std::string detailed_error = "foobar";
   QuicErrorCode header_parse_result = QuicFramer::ParsePublicHeaderDispatcher(
       encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -13121,7 +13121,7 @@
   ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
   QuicConnectionId destination_connection_id = TestConnectionId(1);
   QuicConnectionId source_connection_id = TestConnectionId(2);
-  absl::optional<absl::string_view> retry_token;
+  std::optional<absl::string_view> retry_token;
   std::string detailed_error = "foobar";
   QuicErrorCode header_parse_result = QuicFramer::ParsePublicHeaderDispatcher(
       encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
@@ -14206,7 +14206,7 @@
   QuicVersionLabel version_label;
   std::string detailed_error;
   bool use_length_prefix;
-  absl::optional<absl::string_view> retry_token;
+  std::optional<absl::string_view> retry_token;
   ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
   EXPECT_EQ(QUIC_NO_ERROR,
       QuicFramer::ParsePublicHeaderDispatcherShortHeaderLengthUnknown(
@@ -14248,7 +14248,7 @@
     if (ecn_marks) {
       ack_frame.ecn_counters = QuicEcnCounts(100, 10000, 1000000);
     } else {
-      ack_frame.ecn_counters = absl::nullopt;
+      ack_frame.ecn_counters = std::nullopt;
     }
     QuicFrames frames = {QuicFrame(padding_frame), QuicFrame(&ack_frame)};
     // Build an ACK packet.
diff --git a/quiche/quic/core/quic_generic_session_test.cc b/quiche/quic/core/quic_generic_session_test.cc
index ce5d184..52812e9 100644
--- a/quiche/quic/core/quic_generic_session_test.cc
+++ b/quiche/quic/core/quic_generic_session_test.cc
@@ -10,11 +10,11 @@
 #include <cstddef>
 #include <cstring>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/quic_compressed_certs_cache.h"
 #include "quiche/quic/core/crypto/quic_crypto_client_config.h"
 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
@@ -51,7 +51,7 @@
 class CountingDatagramObserver : public QuicDatagramQueue::Observer {
  public:
   CountingDatagramObserver(int& total) : total_(total) {}
-  void OnDatagramProcessed(absl::optional<MessageStatus>) { ++total_; }
+  void OnDatagramProcessed(std::optional<MessageStatus>) { ++total_; }
 
  private:
   int& total_;
diff --git a/quiche/quic/core/quic_interval_deque.h b/quiche/quic/core/quic_interval_deque.h
index c4bd49c..0aa4543 100644
--- a/quiche/quic/core/quic_interval_deque.h
+++ b/quiche/quic/core/quic_interval_deque.h
@@ -6,8 +6,8 @@
 #define QUICHE_QUIC_CORE_QUIC_INTERVAL_DEQUE_H_
 
 #include <algorithm>
+#include <optional>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_interval.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/platform/api/quic_bug_tracker.h"
@@ -259,7 +259,7 @@
   friend class test::QuicIntervalDequePeer;
 
   C container_;
-  absl::optional<std::size_t> cached_index_;
+  std::optional<std::size_t> cached_index_;
 };
 
 template <class T, class C>
diff --git a/quiche/quic/core/quic_packet_creator.cc b/quiche/quic/core/quic_packet_creator.cc
index f8ae6c6..eacc0c2 100644
--- a/quiche/quic/core/quic_packet_creator.cc
+++ b/quiche/quic/core/quic_packet_creator.cc
@@ -8,6 +8,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <limits>
+#include <optional>
 #include <string>
 #include <utility>
 
@@ -16,7 +17,6 @@
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_join.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/crypto_protocol.h"
 #include "quiche/quic/core/frames/quic_frame.h"
 #include "quiche/quic/core/frames/quic_padding_frame.h"
@@ -756,7 +756,7 @@
   return false;
 }
 
-absl::optional<size_t>
+std::optional<size_t>
 QuicPacketCreator::MaybeBuildDataPacketWithChaosProtection(
     const QuicPacketHeader& header, char* buffer) {
   if (!GetQuicFlag(quic_enable_chaos_protection) ||
@@ -771,13 +771,13 @@
       // Chaos protection relies on the framer using a crypto data producer,
       // which is always the case in practice.
       framer_->data_producer() == nullptr) {
-    return absl::nullopt;
+    return std::nullopt;
   }
   const QuicCryptoFrame& crypto_frame = *queued_frames_[0].crypto_frame;
   if (packet_.encryption_level != crypto_frame.level) {
     QUIC_BUG(chaos frame level)
         << ENDPOINT << packet_.encryption_level << " != " << crypto_frame.level;
-    return absl::nullopt;
+    return std::nullopt;
   }
   QuicChaosProtector chaos_protector(
       crypto_frame, queued_frames_[1].padding_frame.num_padding_bytes,
@@ -843,7 +843,7 @@
   // packet sizes are properly used.
 
   size_t length;
-  absl::optional<size_t> length_with_chaos_protection =
+  std::optional<size_t> length_with_chaos_protection =
       MaybeBuildDataPacketWithChaosProtection(header, encrypted_buffer.buffer);
   if (length_with_chaos_protection.has_value()) {
     length = *length_with_chaos_protection;
diff --git a/quiche/quic/core/quic_packet_creator.h b/quiche/quic/core/quic_packet_creator.h
index 0e0bc82..4cfd566 100644
--- a/quiche/quic/core/quic_packet_creator.h
+++ b/quiche/quic/core/quic_packet_creator.h
@@ -17,12 +17,12 @@
 
 #include <cstddef>
 #include <memory>
+#include <optional>
 #include <utility>
 #include <vector>
 
 #include "absl/base/attributes.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/frames/quic_stream_frame.h"
 #include "quiche/quic/core/quic_coalesced_packet.h"
 #include "quiche/quic/core/quic_connection_id.h"
@@ -488,9 +488,9 @@
   };
 
   // Attempts to build a data packet with chaos protection. If this packet isn't
-  // supposed to be protected or if serialization fails then absl::nullopt is
+  // supposed to be protected or if serialization fails then std::nullopt is
   // returned. Otherwise returns the serialized length.
-  absl::optional<size_t> MaybeBuildDataPacketWithChaosProtection(
+  std::optional<size_t> MaybeBuildDataPacketWithChaosProtection(
       const QuicPacketHeader& header, char* buffer);
 
   // Creates a stream frame which fits into the current open packet. If
diff --git a/quiche/quic/core/quic_packet_writer.h b/quiche/quic/core/quic_packet_writer.h
index dfca5a8..c2b92c6 100644
--- a/quiche/quic/core/quic_packet_writer.h
+++ b/quiche/quic/core/quic_packet_writer.h
@@ -6,9 +6,9 @@
 #define QUICHE_QUIC_CORE_QUIC_PACKET_WRITER_H_
 
 #include <cstddef>
+#include <optional>
 #include <utility>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_packets.h"
 #include "quiche/quic/platform/api/quic_export.h"
 #include "quiche/quic/platform/api/quic_ip_address.h"
@@ -127,7 +127,7 @@
   // The error code used by the writer to indicate that the write failed due to
   // supplied packet being too big.  This is equivalent to returning
   // WRITE_STATUS_MSG_TOO_BIG as a status.
-  virtual absl::optional<int> MessageTooBigErrorCode() const = 0;
+  virtual std::optional<int> MessageTooBigErrorCode() const = 0;
 
   // Returns the maximum size of the packet which can be written using this
   // writer for the supplied peer address.  This size may actually exceed the
diff --git a/quiche/quic/core/quic_packet_writer_wrapper.cc b/quiche/quic/core/quic_packet_writer_wrapper.cc
index c3b4b28..930d4fc 100644
--- a/quiche/quic/core/quic_packet_writer_wrapper.cc
+++ b/quiche/quic/core/quic_packet_writer_wrapper.cc
@@ -26,7 +26,7 @@
 
 void QuicPacketWriterWrapper::SetWritable() { writer_->SetWritable(); }
 
-absl::optional<int> QuicPacketWriterWrapper::MessageTooBigErrorCode() const {
+std::optional<int> QuicPacketWriterWrapper::MessageTooBigErrorCode() const {
   return writer_->MessageTooBigErrorCode();
 }
 
diff --git a/quiche/quic/core/quic_packet_writer_wrapper.h b/quiche/quic/core/quic_packet_writer_wrapper.h
index 901aa6c..898a0e0 100644
--- a/quiche/quic/core/quic_packet_writer_wrapper.h
+++ b/quiche/quic/core/quic_packet_writer_wrapper.h
@@ -31,7 +31,7 @@
                           const QuicPacketWriterParams& params) override;
   bool IsWriteBlocked() const override;
   void SetWritable() override;
-  absl::optional<int> MessageTooBigErrorCode() const override;
+  std::optional<int> MessageTooBigErrorCode() const override;
   QuicByteCount GetMaxPacketSize(
       const QuicSocketAddress& peer_address) const override;
   bool SupportsReleaseTime() const override;
diff --git a/quiche/quic/core/quic_packets.h b/quiche/quic/core/quic_packets.h
index 9bd17f9..3d70fec 100644
--- a/quiche/quic/core/quic_packets.h
+++ b/quiche/quic/core/quic_packets.h
@@ -389,10 +389,10 @@
   // Sum of bytes from frames that are not retransmissions. This field is only
   // populated for packets with "mixed frames": at least one frame of a
   // retransmission type and at least one frame of NOT_RETRANSMISSION type.
-  absl::optional<QuicByteCount> bytes_not_retransmitted;
+  std::optional<QuicByteCount> bytes_not_retransmitted;
   // Only populated if encryption_level is ENCRYPTION_INITIAL.
   // TODO(b/265777524): remove this.
-  absl::optional<QuicPacketHeader> initial_header;
+  std::optional<QuicPacketHeader> initial_header;
 };
 
 // Make a copy of |serialized| (including the underlying frames). |copy_buffer|
@@ -442,7 +442,7 @@
   ParsedQuicVersion version;
   QuicConnectionId destination_connection_id;
   QuicConnectionId source_connection_id;
-  absl::optional<absl::string_view> retry_token;
+  std::optional<absl::string_view> retry_token;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_sent_packet_manager.cc b/quiche/quic/core/quic_sent_packet_manager.cc
index 5786764..1a40e99 100644
--- a/quiche/quic/core/quic_sent_packet_manager.cc
+++ b/quiche/quic/core/quic_sent_packet_manager.cc
@@ -223,7 +223,7 @@
 
 void QuicSentPacketManager::ApplyConnectionOptions(
     const QuicTagVector& connection_options) {
-  absl::optional<CongestionControlType> cc_type;
+  std::optional<CongestionControlType> cc_type;
   if (ContainsQuicTag(connection_options, kB2ON)) {
     cc_type = kBBRv2;
   } else if (ContainsQuicTag(connection_options, kTBBR)) {
@@ -316,7 +316,7 @@
     QuicPacketNumber ack_packet_number, EncryptionLevel ack_decrypted_level,
     const QuicAckFrame& ack_frame, QuicTime ack_receive_time, bool rtt_updated,
     QuicByteCount prior_bytes_in_flight,
-    absl::optional<QuicEcnCounts> ecn_counts) {
+    std::optional<QuicEcnCounts> ecn_counts) {
   unacked_packets_.NotifyAggregatedStreamFrameAcked(
       last_ack_frame_.ack_delay_time);
   InvokeLossDetection(ack_receive_time);
@@ -358,7 +358,7 @@
 
 void QuicSentPacketManager::MaybeInvokeCongestionEvent(
     bool rtt_updated, QuicByteCount prior_in_flight, QuicTime event_time,
-    absl::optional<QuicEcnCounts> ecn_counts,
+    std::optional<QuicEcnCounts> ecn_counts,
     const QuicEcnCounts& previous_counts) {
   if (!rtt_updated && packets_acked_.empty() && packets_lost_.empty()) {
     return;
@@ -745,7 +745,7 @@
       const QuicTime now = clock_->Now();
       InvokeLossDetection(now);
       MaybeInvokeCongestionEvent(false, prior_in_flight, now,
-                                 absl::optional<QuicEcnCounts>(),
+                                 std::optional<QuicEcnCounts>(),
                                  peer_ack_ecn_counts_[APPLICATION_DATA]);
       return LOSS_MODE;
     }
@@ -1278,7 +1278,7 @@
 }
 
 bool QuicSentPacketManager::IsEcnFeedbackValid(
-    PacketNumberSpace space, const absl::optional<QuicEcnCounts>& ecn_counts,
+    PacketNumberSpace space, const std::optional<QuicEcnCounts>& ecn_counts,
     QuicPacketCount newly_acked_ect0, QuicPacketCount newly_acked_ect1) {
   if (!ecn_counts.has_value()) {
     if (newly_acked_ect0 > 0 || newly_acked_ect1 > 0) {
@@ -1325,7 +1325,7 @@
 AckResult QuicSentPacketManager::OnAckFrameEnd(
     QuicTime ack_receive_time, QuicPacketNumber ack_packet_number,
     EncryptionLevel ack_decrypted_level,
-    const absl::optional<QuicEcnCounts>& ecn_counts) {
+    const std::optional<QuicEcnCounts>& ecn_counts) {
   QuicByteCount prior_bytes_in_flight = unacked_packets_.bytes_in_flight();
   QuicPacketCount newly_acked_ect0 = 0;
   QuicPacketCount newly_acked_ect1 = 0;
@@ -1423,7 +1423,7 @@
                       acked_packet.receive_timestamp);
   }
   // Validate ECN feedback.
-  absl::optional<QuicEcnCounts> valid_ecn_counts;
+  std::optional<QuicEcnCounts> valid_ecn_counts;
   if (GetQuicReloadableFlag(quic_send_ect1)) {
     QUIC_RELOADABLE_FLAG_COUNT_N(quic_send_ect1, 1, 8);
     if (IsEcnFeedbackValid(acked_packet_number_space, ecn_counts,
diff --git a/quiche/quic/core/quic_sent_packet_manager.h b/quiche/quic/core/quic_sent_packet_manager.h
index 133b7ae..fe1aa0b 100644
--- a/quiche/quic/core/quic_sent_packet_manager.h
+++ b/quiche/quic/core/quic_sent_packet_manager.h
@@ -352,7 +352,7 @@
   AckResult OnAckFrameEnd(QuicTime ack_receive_time,
                           QuicPacketNumber ack_packet_number,
                           EncryptionLevel ack_decrypted_level,
-                          const absl::optional<QuicEcnCounts>& ecn_counts);
+                          const std::optional<QuicEcnCounts>& ecn_counts);
 
   void EnableMultiplePacketNumberSpacesSupport();
 
@@ -523,7 +523,7 @@
   void MaybeInvokeCongestionEvent(bool rtt_updated,
                                   QuicByteCount prior_in_flight,
                                   QuicTime event_time,
-                                  absl::optional<QuicEcnCounts> ecn_counts,
+                                  std::optional<QuicEcnCounts> ecn_counts,
                                   const QuicEcnCounts& previous_counts);
 
   // Removes the retransmittability and in flight properties from the packet at
@@ -546,7 +546,7 @@
                                     const QuicAckFrame& ack_frame,
                                     QuicTime ack_receive_time, bool rtt_updated,
                                     QuicByteCount prior_bytes_in_flight,
-                                    absl::optional<QuicEcnCounts> ecn_counts);
+                                    std::optional<QuicEcnCounts> ecn_counts);
 
   // Notify observers that packet with QuicTransmissionInfo |info| is a spurious
   // retransmission. It is caller's responsibility to guarantee the packet with
@@ -587,7 +587,7 @@
   // |newly_acked_ect1| count the number of previously unacked packets with
   // those markings that appeared in an ack block for the first time.
   bool IsEcnFeedbackValid(PacketNumberSpace space,
-                          const absl::optional<QuicEcnCounts>& ecn_counts,
+                          const std::optional<QuicEcnCounts>& ecn_counts,
                           QuicPacketCount newly_acked_ect0,
                           QuicPacketCount newly_acked_ect1);
 
@@ -718,7 +718,7 @@
   // Most recent ECN codepoint counts received in an ACK frame sent by the peer.
   QuicEcnCounts peer_ack_ecn_counts_[NUM_PACKET_NUMBER_SPACES];
 
-  absl::optional<QuicTime::Delta> deferred_send_alarm_delay_;
+  std::optional<QuicTime::Delta> deferred_send_alarm_delay_;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_sent_packet_manager_test.cc b/quiche/quic/core/quic_sent_packet_manager_test.cc
index d222b6b..13caeba 100644
--- a/quiche/quic/core/quic_sent_packet_manager_test.cc
+++ b/quiche/quic/core/quic_sent_packet_manager_test.cc
@@ -40,8 +40,8 @@
 // Stream ID for data sent in CreatePacket().
 const QuicStreamId kStreamId = 7;
 
-// The compiler won't allow absl::nullopt as an argument.
-const absl::optional<QuicEcnCounts> kEmptyCounts = absl::nullopt;
+// The compiler won't allow std::nullopt as an argument.
+const std::optional<QuicEcnCounts> kEmptyCounts = std::nullopt;
 
 // Matcher to check that the packet number matches the second argument.
 MATCHER(PacketNumberEq, "") {
@@ -3198,7 +3198,7 @@
   if (!GetQuicReloadableFlag(quic_send_ect1)) {
     return;
   }
-  absl::optional<QuicEcnCounts> ecn_counts1, ecn_counts2, ecn_counts3;
+  std::optional<QuicEcnCounts> ecn_counts1, ecn_counts2, ecn_counts3;
   ecn_counts1 = {1, 0, 3};
   ecn_counts2 = {0, 3, 1};
   ecn_counts3 = {0, 2, 0};
@@ -3249,7 +3249,7 @@
                                 IsEmpty(), 2, 1))
       .Times(1);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange()).Times(1);
-  absl::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
+  std::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
   ecn_counts->ect1 = QuicPacketCount(2);
   ecn_counts->ce = QuicPacketCount(1);
   EXPECT_EQ(PACKETS_NEWLY_ACKED,
@@ -3274,7 +3274,7 @@
                                 IsEmpty(), 2, 1))
       .Times(1);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange()).Times(1);
-  absl::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
+  std::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
   ecn_counts->ect1 = QuicPacketCount(2);
   ecn_counts->ce = QuicPacketCount(1);
   EXPECT_EQ(PACKETS_NEWLY_ACKED,
@@ -3311,7 +3311,7 @@
   manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
                            clock_.Now());
   manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(4));
-  absl::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
+  std::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
   // Report 4 counts, but only 3 packets were sent.
   ecn_counts->ect1 = QuicPacketCount(3);
   ecn_counts->ce = QuicPacketCount(1);
@@ -3339,7 +3339,7 @@
   manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
                            clock_.Now());
   manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(4));
-  absl::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
+  std::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
   // Report the wrong codepoint.
   ecn_counts->ect0 = QuicPacketCount(2);
   ecn_counts->ce = QuicPacketCount(1);
@@ -3373,7 +3373,7 @@
                                 IsEmpty(), 0, 0))
       .Times(1);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange()).Times(1);
-  absl::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
+  std::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
   // 2 ECN packets were newly acked, but only one count was reported.
   ecn_counts->ect1 = QuicPacketCount(1);
   ecn_counts->ce = QuicPacketCount(0);
@@ -3400,7 +3400,7 @@
                                 IsEmpty(), 2, 1))
       .Times(1);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange()).Times(1);
-  absl::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
+  std::optional<QuicEcnCounts> ecn_counts = QuicEcnCounts();
   ecn_counts->ect1 = QuicPacketCount(2);
   ecn_counts->ce = QuicPacketCount(1);
   EXPECT_EQ(PACKETS_NEWLY_ACKED,
@@ -3444,7 +3444,7 @@
                                 IsEmpty(), 0, 0))
       .Times(1);
   EXPECT_CALL(*network_change_visitor_, OnCongestionChange()).Times(1);
-  absl::optional<QuicEcnCounts> ecn_counts = absl::nullopt;
+  std::optional<QuicEcnCounts> ecn_counts = std::nullopt;
   EXPECT_EQ(PACKETS_NEWLY_ACKED,
             manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
                                    ENCRYPTION_FORWARD_SECURE, ecn_counts));
diff --git a/quiche/quic/core/quic_server_id.cc b/quiche/quic/core/quic_server_id.cc
index 45849f5..4a5d8f7 100644
--- a/quiche/quic/core/quic_server_id.cc
+++ b/quiche/quic/core/quic_server_id.cc
@@ -4,6 +4,7 @@
 
 #include "quiche/quic/core/quic_server_id.h"
 
+#include <optional>
 #include <string>
 #include <tuple>
 #include <utility>
@@ -11,14 +12,13 @@
 #include "absl/strings/match.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/common/platform/api/quiche_googleurl.h"
 #include "quiche/common/platform/api/quiche_logging.h"
 
 namespace quic {
 
 // static
-absl::optional<QuicServerId> QuicServerId::ParseFromHostPortString(
+std::optional<QuicServerId> QuicServerId::ParseFromHostPortString(
     absl::string_view host_port_string) {
   url::Component username_component;
   url::Component password_component;
@@ -34,7 +34,7 @@
   if (username_component.is_valid() || password_component.is_valid() ||
       !host_component.is_nonempty() || !port_component.is_nonempty()) {
     QUICHE_DVLOG(1) << "QuicServerId could not be parsed: " << host_port_string;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   std::string hostname(host_port_string.data() + host_component.begin,
@@ -49,7 +49,7 @@
     QUICHE_DVLOG(1)
         << "Port could not be parsed while parsing QuicServerId from: "
         << host_port_string;
-    return absl::nullopt;
+    return std::nullopt;
   }
   QUICHE_DCHECK_LE(parsed_port_number, std::numeric_limits<uint16_t>::max());
 
diff --git a/quiche/quic/core/quic_server_id.h b/quiche/quic/core/quic_server_id.h
index ecbf3aa..7949a9d 100644
--- a/quiche/quic/core/quic_server_id.h
+++ b/quiche/quic/core/quic_server_id.h
@@ -6,11 +6,11 @@
 #define QUICHE_QUIC_CORE_QUIC_SERVER_ID_H_
 
 #include <cstdint>
+#include <optional>
 #include <string>
 
 #include "absl/hash/hash.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/platform/api/quic_export.h"
 
 namespace quic {
@@ -22,7 +22,7 @@
   // Attempts to parse a QuicServerId from a "host:port" string. Returns nullopt
   // if input could not be parsed. Requires input to contain both host and port
   // and no other components of a URL authority.
-  static absl::optional<QuicServerId> ParseFromHostPortString(
+  static std::optional<QuicServerId> ParseFromHostPortString(
       absl::string_view host_port_string);
 
   QuicServerId();
diff --git a/quiche/quic/core/quic_server_id_test.cc b/quiche/quic/core/quic_server_id_test.cc
index 1ca7a70..cbcadb6 100644
--- a/quiche/quic/core/quic_server_id_test.cc
+++ b/quiche/quic/core/quic_server_id_test.cc
@@ -4,9 +4,9 @@
 
 #include "quiche/quic/core/quic_server_id.h"
 
+#include <optional>
 #include <string>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/platform/api/quic_test.h"
 
 namespace quic::test {
@@ -124,7 +124,7 @@
 }
 
 TEST_F(QuicServerIdTest, Parse) {
-  absl::optional<QuicServerId> server_id =
+  std::optional<QuicServerId> server_id =
       QuicServerId::ParseFromHostPortString("host.test:500");
 
   EXPECT_THAT(server_id, Optional(Property(&QuicServerId::host, "host.test")));
@@ -134,35 +134,35 @@
 }
 
 TEST_F(QuicServerIdTest, CannotParseMissingPort) {
-  absl::optional<QuicServerId> server_id =
+  std::optional<QuicServerId> server_id =
       QuicServerId::ParseFromHostPortString("host.test");
 
-  EXPECT_EQ(server_id, absl::nullopt);
+  EXPECT_EQ(server_id, std::nullopt);
 }
 
 TEST_F(QuicServerIdTest, CannotParseEmptyPort) {
-  absl::optional<QuicServerId> server_id =
+  std::optional<QuicServerId> server_id =
       QuicServerId::ParseFromHostPortString("host.test:");
 
-  EXPECT_EQ(server_id, absl::nullopt);
+  EXPECT_EQ(server_id, std::nullopt);
 }
 
 TEST_F(QuicServerIdTest, CannotParseEmptyHost) {
-  absl::optional<QuicServerId> server_id =
+  std::optional<QuicServerId> server_id =
       QuicServerId::ParseFromHostPortString(":500");
 
-  EXPECT_EQ(server_id, absl::nullopt);
+  EXPECT_EQ(server_id, std::nullopt);
 }
 
 TEST_F(QuicServerIdTest, CannotParseUserInfo) {
-  absl::optional<QuicServerId> server_id =
+  std::optional<QuicServerId> server_id =
       QuicServerId::ParseFromHostPortString("userinfo@host.test:500");
 
-  EXPECT_EQ(server_id, absl::nullopt);
+  EXPECT_EQ(server_id, std::nullopt);
 }
 
 TEST_F(QuicServerIdTest, ParseIpv6Literal) {
-  absl::optional<QuicServerId> server_id =
+  std::optional<QuicServerId> server_id =
       QuicServerId::ParseFromHostPortString("[::1]:400");
 
   EXPECT_THAT(server_id, Optional(Property(&QuicServerId::host, "[::1]")));
@@ -172,7 +172,7 @@
 }
 
 TEST_F(QuicServerIdTest, ParseUnbracketedIpv6Literal) {
-  absl::optional<QuicServerId> server_id =
+  std::optional<QuicServerId> server_id =
       QuicServerId::ParseFromHostPortString("::1:400");
 
   EXPECT_THAT(server_id, Optional(Property(&QuicServerId::host, "::1")));
diff --git a/quiche/quic/core/quic_session.cc b/quiche/quic/core/quic_session.cc
index 1ec3c57..ddb0914 100644
--- a/quiche/quic/core/quic_session.cc
+++ b/quiche/quic/core/quic_session.cc
@@ -187,7 +187,7 @@
 void QuicSession::MaybeProcessPendingStream(PendingStream* pending) {
   QUICHE_DCHECK(pending != nullptr);
   QuicStreamId stream_id = pending->id();
-  absl::optional<QuicResetStreamError> stop_sending_error_code =
+  std::optional<QuicResetStreamError> stop_sending_error_code =
       pending->GetStopSendingErrorCode();
   QuicStream* stream = ProcessPendingStream(pending);
   if (stream != nullptr) {
@@ -1349,12 +1349,12 @@
               .Normalized()
               .host()
               .address_family();
-      absl::optional<QuicSocketAddress> preferred_address =
+      std::optional<QuicSocketAddress> preferred_address =
           config_.GetPreferredAddressToSend(address_family);
       if (preferred_address.has_value()) {
         // Set connection ID and token if SPAD has received and a preferred
         // address of the same address family is configured.
-        absl::optional<QuicNewConnectionIdFrame> frame =
+        std::optional<QuicNewConnectionIdFrame> frame =
             connection_->MaybeIssueNewConnectionIdForPreferredAddress();
         if (frame.has_value()) {
           config_.SetPreferredAddressConnectionIdAndTokenToSend(
@@ -1391,9 +1391,9 @@
   }
 }
 
-absl::optional<std::string> QuicSession::OnAlpsData(
-    const uint8_t* /*alps_data*/, size_t /*alps_length*/) {
-  return absl::nullopt;
+std::optional<std::string> QuicSession::OnAlpsData(const uint8_t* /*alps_data*/,
+                                                   size_t /*alps_length*/) {
+  return std::nullopt;
 }
 
 void QuicSession::AdjustInitialFlowControlWindows(size_t stream_window) {
@@ -1731,7 +1731,7 @@
 bool QuicSession::MaybeSendAddressToken() {
   QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER &&
                 connection()->version().HasIetfQuicFrames());
-  absl::optional<CachedNetworkParameters> cached_network_params =
+  std::optional<CachedNetworkParameters> cached_network_params =
       GenerateCachedNetworkParameters();
 
   std::string address_token = GetCryptoStream()->GetAddressToken(
diff --git a/quiche/quic/core/quic_session.h b/quiche/quic/core/quic_session.h
index 71dae7b..1a20486 100644
--- a/quiche/quic/core/quic_session.h
+++ b/quiche/quic/core/quic_session.h
@@ -11,12 +11,12 @@
 #include <cstdint>
 #include <map>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/container/flat_hash_map.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/core/crypto/tls_connection.h"
 #include "quiche/quic/core/frames/quic_ack_frequency_frame.h"
@@ -304,8 +304,8 @@
 
   // Called by the TLS handshaker when ALPS data is received.
   // Returns an error message if an error has occurred, or nullopt otherwise.
-  virtual absl::optional<std::string> OnAlpsData(const uint8_t* alps_data,
-                                                 size_t alps_length);
+  virtual std::optional<std::string> OnAlpsData(const uint8_t* alps_data,
+                                                size_t alps_length);
 
   // From HandshakerDelegateInterface
   bool OnNewDecryptionKeyAvailable(EncryptionLevel level,
@@ -613,7 +613,7 @@
   // Returns the encryption level to send application data.
   EncryptionLevel GetEncryptionLevelToSendApplicationData() const;
 
-  const absl::optional<std::string> user_agent_id() const {
+  const std::optional<std::string> user_agent_id() const {
     return user_agent_id_;
   }
 
@@ -846,11 +846,11 @@
 
   // Only called at a server session. Generate a CachedNetworkParameters that
   // can be sent to the client as part of the address token, based on the latest
-  // bandwidth/rtt information. If return absl::nullopt, address token will not
+  // bandwidth/rtt information. If return std::nullopt, address token will not
   // contain the CachedNetworkParameters.
-  virtual absl::optional<CachedNetworkParameters>
+  virtual std::optional<CachedNetworkParameters>
   GenerateCachedNetworkParameters() const {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // Debug helper for OnCanWrite. Check that after QuicStream::OnCanWrite(),
@@ -994,7 +994,7 @@
 
   // Received information for a connection close.
   QuicConnectionCloseFrame on_closed_frame_;
-  absl::optional<ConnectionCloseSource> source_;
+  std::optional<ConnectionCloseSource> source_;
 
   // Used for connection-level flow control.
   QuicFlowController flow_controller_;
@@ -1042,7 +1042,7 @@
   // negotiation was received.
   ParsedQuicVersionVector client_original_supported_versions_;
 
-  absl::optional<std::string> user_agent_id_;
+  std::optional<std::string> user_agent_id_;
 
   // Initialized to false. Set to true when the session has been properly
   // configured and is ready for general operation.
diff --git a/quiche/quic/core/quic_session_test.cc b/quiche/quic/core/quic_session_test.cc
index e7e304d..079db36 100644
--- a/quiche/quic/core/quic_session_test.cc
+++ b/quiche/quic/core/quic_session_test.cc
@@ -5,6 +5,7 @@
 #include "quiche/quic/core/quic_session.h"
 
 #include <cstdint>
+#include <optional>
 #include <set>
 #include <string>
 #include <utility>
@@ -13,7 +14,6 @@
 #include "absl/memory/memory.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/crypto_protocol.h"
 #include "quiche/quic/core/crypto/null_decrypter.h"
 #include "quiche/quic/core/crypto/null_encrypter.h"
diff --git a/quiche/quic/core/quic_stream.cc b/quiche/quic/core/quic_stream.cc
index f2a2645..3f8fbe0 100644
--- a/quiche/quic/core/quic_stream.cc
+++ b/quiche/quic/core/quic_stream.cc
@@ -5,11 +5,11 @@
 #include "quiche/quic/core/quic_stream.h"
 
 #include <limits>
+#include <optional>
 #include <string>
 
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_error_codes.h"
 #include "quiche/quic/core/quic_flow_controller.h"
 #include "quiche/quic/core/quic_session.h"
@@ -298,15 +298,15 @@
 
 namespace {
 
-absl::optional<QuicFlowController> FlowController(QuicStreamId id,
-                                                  QuicSession* session,
-                                                  StreamType type) {
+std::optional<QuicFlowController> FlowController(QuicStreamId id,
+                                                 QuicSession* session,
+                                                 StreamType type) {
   if (type == CRYPTO) {
     // The only QuicStream with a StreamType of CRYPTO is QuicCryptoStream, when
     // it is using crypto frames instead of stream frames. The QuicCryptoStream
     // doesn't have any flow control in that case, so we don't create a
     // QuicFlowController for it.
-    return absl::nullopt;
+    return std::nullopt;
   }
   return QuicFlowController(
       session, id,
@@ -330,7 +330,7 @@
                        QuicStreamSequencer sequencer, bool is_static,
                        StreamType type, uint64_t stream_bytes_read,
                        bool fin_received,
-                       absl::optional<QuicFlowController> flow_controller,
+                       std::optional<QuicFlowController> flow_controller,
                        QuicFlowController* connection_flow_controller)
     : sequencer_(std::move(sequencer)),
       id_(id),
@@ -1414,17 +1414,17 @@
   flow_controller_->UpdateReceiveWindowSize(size);
 }
 
-absl::optional<QuicByteCount> QuicStream::GetSendWindow() const {
+std::optional<QuicByteCount> QuicStream::GetSendWindow() const {
   return flow_controller_.has_value()
-             ? absl::optional<QuicByteCount>(flow_controller_->SendWindowSize())
-             : absl::nullopt;
+             ? std::optional<QuicByteCount>(flow_controller_->SendWindowSize())
+             : std::nullopt;
 }
 
-absl::optional<QuicByteCount> QuicStream::GetReceiveWindow() const {
+std::optional<QuicByteCount> QuicStream::GetReceiveWindow() const {
   return flow_controller_.has_value()
-             ? absl::optional<QuicByteCount>(
+             ? std::optional<QuicByteCount>(
                    flow_controller_->receive_window_size())
-             : absl::nullopt;
+             : std::nullopt;
 }
 
 void QuicStream::OnStreamCreatedFromPendingStream() {
diff --git a/quiche/quic/core/quic_stream.h b/quiche/quic/core/quic_stream.h
index 69abe7d..42f1775 100644
--- a/quiche/quic/core/quic_stream.h
+++ b/quiche/quic/core/quic_stream.h
@@ -20,10 +20,10 @@
 #include <cstddef>
 #include <cstdint>
 #include <list>
+#include <optional>
 #include <string>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/core/frames/quic_rst_stream_frame.h"
 #include "quiche/quic/core/quic_error_codes.h"
@@ -86,7 +86,7 @@
   void OnStopSending(QuicResetStreamError stop_sending_error_code);
 
   // The error code received from QuicStopSendingFrame (if any).
-  const absl::optional<QuicResetStreamError>& GetStopSendingErrorCode() const {
+  const std::optional<QuicResetStreamError>& GetStopSendingErrorCode() const {
     return stop_sending_error_code_;
   }
 
@@ -132,7 +132,7 @@
   // Stores the buffered frames.
   QuicStreamSequencer sequencer_;
   // The error code received from QuicStopSendingFrame (if any).
-  absl::optional<QuicResetStreamError> stop_sending_error_code_;
+  std::optional<QuicResetStreamError> stop_sending_error_code_;
 };
 
 class QUICHE_EXPORT QuicStream : public QuicStreamSequencer::StreamInterface {
@@ -475,8 +475,8 @@
   virtual void OnWriteSideInDataRecvdState() {}
 
   // Return the current flow control send window in bytes.
-  absl::optional<QuicByteCount> GetSendWindow() const;
-  absl::optional<QuicByteCount> GetReceiveWindow() const;
+  std::optional<QuicByteCount> GetSendWindow() const;
+  std::optional<QuicByteCount> GetReceiveWindow() const;
 
  private:
   friend class test::QuicStreamPeer;
@@ -485,7 +485,7 @@
   QuicStream(QuicStreamId id, QuicSession* session,
              QuicStreamSequencer sequencer, bool is_static, StreamType type,
              uint64_t stream_bytes_read, bool fin_received,
-             absl::optional<QuicFlowController> flow_controller,
+             std::optional<QuicFlowController> flow_controller,
              QuicFlowController* connection_flow_controller);
 
   // Calls MaybeSendBlocked on the stream's flow controller and the connection
@@ -556,7 +556,7 @@
   // True if the stream has sent STOP_SENDING to the session.
   bool stop_sending_sent_;
 
-  absl::optional<QuicFlowController> flow_controller_;
+  std::optional<QuicFlowController> flow_controller_;
 
   // The connection level flow controller. Not owned.
   QuicFlowController* connection_flow_controller_;
diff --git a/quiche/quic/core/quic_stream_priority.cc b/quiche/quic/core/quic_stream_priority.cc
index 5199a43..42e4be4 100644
--- a/quiche/quic/core/quic_stream_priority.cc
+++ b/quiche/quic/core/quic_stream_priority.cc
@@ -30,7 +30,7 @@
             quiche::structured_headers::Item(priority.incremental), {});
   }
 
-  absl::optional<std::string> priority_field_value =
+  std::optional<std::string> priority_field_value =
       quiche::structured_headers::SerializeDictionary(dictionary);
   if (!priority_field_value.has_value()) {
     QUICHE_BUG(priority_field_value_serialization_failed);
@@ -40,12 +40,12 @@
   return *priority_field_value;
 }
 
-absl::optional<HttpStreamPriority> ParsePriorityFieldValue(
+std::optional<HttpStreamPriority> ParsePriorityFieldValue(
     absl::string_view priority_field_value) {
-  absl::optional<quiche::structured_headers::Dictionary> parsed_dictionary =
+  std::optional<quiche::structured_headers::Dictionary> parsed_dictionary =
       quiche::structured_headers::ParseDictionary(priority_field_value);
   if (!parsed_dictionary.has_value()) {
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   uint8_t urgency = HttpStreamPriority::kDefaultUrgency;
diff --git a/quiche/quic/core/quic_stream_priority.h b/quiche/quic/core/quic_stream_priority.h
index 7a4b9d0..8b1df3c 100644
--- a/quiche/quic/core/quic_stream_priority.h
+++ b/quiche/quic/core/quic_stream_priority.h
@@ -6,11 +6,11 @@
 #define QUICHE_QUIC_CORE_QUIC_STREAM_PRIORITY_H_
 
 #include <cstdint>
+#include <optional>
 #include <string>
 #include <tuple>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/variant.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/common/platform/api/quiche_bug_tracker.h"
@@ -134,7 +134,7 @@
 
 // Parses the Priority Field Value field of a PRIORITY_UPDATE frame.
 // Returns nullopt on failure.
-QUICHE_EXPORT absl::optional<HttpStreamPriority> ParsePriorityFieldValue(
+QUICHE_EXPORT std::optional<HttpStreamPriority> ParsePriorityFieldValue(
     absl::string_view priority_field_value);
 
 }  // namespace quic
diff --git a/quiche/quic/core/quic_stream_priority_test.cc b/quiche/quic/core/quic_stream_priority_test.cc
index db5d1a9..e5d4f1c 100644
--- a/quiche/quic/core/quic_stream_priority_test.cc
+++ b/quiche/quic/core/quic_stream_priority_test.cc
@@ -91,7 +91,7 @@
 
 TEST(ParsePriorityFieldValueTest, ParsePriorityFieldValue) {
   // Default values
-  absl::optional<HttpStreamPriority> result = ParsePriorityFieldValue("");
+  std::optional<HttpStreamPriority> result = ParsePriorityFieldValue("");
   ASSERT_TRUE(result.has_value());
   EXPECT_EQ(3, result->urgency);
   EXPECT_FALSE(result->incremental);
diff --git a/quiche/quic/core/quic_stream_test.cc b/quiche/quic/core/quic_stream_test.cc
index 7afbb19..e1e607d 100644
--- a/quiche/quic/core/quic_stream_test.cc
+++ b/quiche/quic/core/quic_stream_test.cc
@@ -5,13 +5,13 @@
 #include "quiche/quic/core/quic_stream.h"
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 
 #include "absl/base/macros.h"
 #include "absl/memory/memory.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/null_encrypter.h"
 #include "quiche/quic/core/frames/quic_rst_stream_frame.h"
 #include "quiche/quic/core/quic_connection.h"
@@ -137,7 +137,7 @@
   QuicConsumedData CloseStreamOnWriteError(
       QuicStreamId id, QuicByteCount /*write_length*/,
       QuicStreamOffset /*offset*/, StreamSendingState /*state*/,
-      TransmissionType /*type*/, absl::optional<EncryptionLevel> /*level*/) {
+      TransmissionType /*type*/, std::optional<EncryptionLevel> /*level*/) {
     session_->ResetStream(id, QUIC_STREAM_CANCELLED);
     return QuicConsumedData(1, false);
   }
@@ -378,7 +378,7 @@
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   stream_->WriteOrBufferData(absl::string_view(kData1, 2), false, nullptr);
   EXPECT_TRUE(session_->HasUnackedStreamData());
@@ -396,7 +396,7 @@
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 2u, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   stream_->WriteOrBufferData(absl::string_view(kData1, 2), true, nullptr);
   EXPECT_TRUE(session_->HasUnackedStreamData());
@@ -442,7 +442,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), kDataLen - 1, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   stream_->WriteOrBufferData(kData1, false, nullptr);
 
@@ -458,7 +458,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), kDataLen - 1, kDataLen - 1,
-                                     NO_FIN, NOT_RETRANSMISSION, absl::nullopt);
+                                     NO_FIN, NOT_RETRANSMISSION, std::nullopt);
       }));
   EXPECT_CALL(*stream_, OnCanWriteNewData());
   stream_->OnCanWrite();
@@ -468,7 +468,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 2u, 2 * kDataLen - 2,
-                                     NO_FIN, NOT_RETRANSMISSION, absl::nullopt);
+                                     NO_FIN, NOT_RETRANSMISSION, std::nullopt);
       }));
   EXPECT_CALL(*stream_, OnCanWriteNewData());
   stream_->OnCanWrite();
@@ -527,7 +527,7 @@
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 1u, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   stream_->WriteOrBufferData(absl::string_view(kData1, 1), false, nullptr);
   EXPECT_TRUE(session_->HasUnackedStreamData());
@@ -564,7 +564,7 @@
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 1u, 0u, FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   stream_->WriteOrBufferData(absl::string_view(kData1, 1), true, nullptr);
   EXPECT_TRUE(fin_sent());
@@ -827,7 +827,7 @@
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 2u, 0u, FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   stream_->WriteOrBufferData(absl::string_view(kData1, 2), true, nullptr);
   EXPECT_TRUE(stream_->write_side_closed());
@@ -844,7 +844,7 @@
   EXPECT_CALL(*session_, WritevData(kTestStreamId, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 2u, 0u, FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   stream_->WriteOrBufferData(absl::string_view(kData1, 2), true, nullptr);
   EXPECT_TRUE(stream_->write_side_closed());
@@ -1130,7 +1130,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   stream_->WriteOrBufferData(data, false, nullptr);
   stream_->WriteOrBufferData(data, false, nullptr);
@@ -1143,7 +1143,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 100, 100u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   // Buffered data size > threshold, do not ask upper layer for more data.
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(0);
@@ -1157,7 +1157,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this, data_to_write]() {
         return session_->ConsumeData(stream_->id(), data_to_write, 200u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   // Buffered data size < threshold, ask upper layer for more data.
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
@@ -1206,7 +1206,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this, data_to_write]() {
         return session_->ConsumeData(stream_->id(), data_to_write, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
 
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
@@ -1279,7 +1279,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 100u, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   // There is no buffered data before, all data should be consumed.
   QuicConsumedData consumed = stream_->WriteMemSlices(span1, false);
@@ -1301,7 +1301,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this, data_to_write]() {
         return session_->ConsumeData(stream_->id(), data_to_write, 100u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   EXPECT_CALL(*stream_, OnCanWriteNewData()).Times(1);
   stream_->OnCanWrite();
@@ -1334,7 +1334,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 5u, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   // There is no buffered data before, all data should be consumed.
   QuicConsumedData consumed = stream_->WriteMemSlice(std::move(slice1), false);
@@ -1474,7 +1474,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 9u, 18u, FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   stream_->OnCanWrite();
   EXPECT_FALSE(stream_->HasPendingRetransmission());
@@ -1504,7 +1504,7 @@
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 9u, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
       .WillOnce(Return(QuicConsumedData(0, true)));
@@ -1591,7 +1591,7 @@
   EXPECT_CALL(*session_, WritevData(stream_->id(), 10, 0, NO_FIN, _, _))
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 8, 0u, NO_FIN,
-                                     NOT_RETRANSMISSION, absl::nullopt);
+                                     NOT_RETRANSMISSION, std::nullopt);
       }));
   EXPECT_FALSE(stream_->RetransmitStreamData(0, 18, true, PTO_RETRANSMISSION));
 
diff --git a/quiche/quic/core/quic_types.h b/quiche/quic/core/quic_types.h
index 727eb73..0389e74 100644
--- a/quiche/quic/core/quic_types.h
+++ b/quiche/quic/core/quic_types.h
@@ -9,13 +9,13 @@
 #include <cstddef>
 #include <cstdint>
 #include <map>
+#include <optional>
 #include <ostream>
 #include <vector>
 
 #include "absl/container/inlined_vector.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_connection_id.h"
 #include "quiche/quic/core/quic_error_codes.h"
 #include "quiche/quic/core/quic_packet_number.h"
@@ -830,13 +830,13 @@
 // overrides the configurations in SSL_CTX.
 struct QUICHE_EXPORT QuicSSLConfig {
   // Whether TLS early data should be enabled. If not set, default to enabled.
-  absl::optional<bool> early_data_enabled;
+  std::optional<bool> early_data_enabled;
   // Whether TLS session tickets are supported. If not set, default to
   // supported.
-  absl::optional<bool> disable_ticket_support;
+  std::optional<bool> disable_ticket_support;
   // If set, used to configure the SSL object with
   // SSL_set_signing_algorithm_prefs.
-  absl::optional<QuicSignatureAlgorithmVector> signing_algorithm_prefs;
+  std::optional<QuicSignatureAlgorithmVector> signing_algorithm_prefs;
   // Client certificate mode for mTLS support. Only used at server side.
   ClientCertMode client_cert_mode = ClientCertMode::kNone;
   // As a client, the ECHConfigList to use with ECH. If empty, ECH is not
@@ -852,10 +852,10 @@
 // configs applied before cert selection.
 struct QUICHE_EXPORT QuicDelayedSSLConfig {
   // Client certificate mode for mTLS support. Only used at server side.
-  // absl::nullopt means do not change client certificate mode.
-  absl::optional<ClientCertMode> client_cert_mode;
+  // std::nullopt means do not change client certificate mode.
+  std::optional<ClientCertMode> client_cert_mode;
   // QUIC transport parameters as serialized by ProofSourceHandle.
-  absl::optional<std::vector<uint8_t>> quic_transport_parameters;
+  std::optional<std::vector<uint8_t>> quic_transport_parameters;
 };
 
 // ParsedClientHello contains client hello information extracted from a fully
diff --git a/quiche/quic/core/quic_utils.h b/quiche/quic/core/quic_utils.h
index 761914e..2c39781 100644
--- a/quiche/quic/core/quic_utils.h
+++ b/quiche/quic/core/quic_utils.h
@@ -8,6 +8,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <initializer_list>
+#include <optional>
 #include <string>
 #include <type_traits>
 
@@ -15,7 +16,6 @@
 #include "absl/numeric/int128.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/core/crypto/quic_random.h"
 #include "quiche/quic/core/frames/quic_frame.h"
@@ -259,9 +259,9 @@
   bool Any() const { return mask_ != 0; }
 
   // Returns the highest bit set, or nullopt if the mask is all zeroes.
-  absl::optional<Index> Max() const {
+  std::optional<Index> Max() const {
     if (!Any()) {
-      return absl::nullopt;
+      return std::nullopt;
     }
     return static_cast<Index>(NumBits() - absl::countl_zero(mask_) - 1);
   }
diff --git a/quiche/quic/core/quic_write_blocked_list_test.cc b/quiche/quic/core/quic_write_blocked_list_test.cc
index ba6569e..cd60e07 100644
--- a/quiche/quic/core/quic_write_blocked_list_test.cc
+++ b/quiche/quic/core/quic_write_blocked_list_test.cc
@@ -85,7 +85,7 @@
   }
 
  private:
-  absl::optional<QuicWriteBlockedList> write_blocked_list_;
+  std::optional<QuicWriteBlockedList> write_blocked_list_;
 };
 
 TEST_F(QuicWriteBlockedListTest, PriorityOrder) {
diff --git a/quiche/quic/core/stream_delegate_interface.h b/quiche/quic/core/stream_delegate_interface.h
index 5a89f82..7ee161d 100644
--- a/quiche/quic/core/stream_delegate_interface.h
+++ b/quiche/quic/core/stream_delegate_interface.h
@@ -6,8 +6,8 @@
 #define QUICHE_QUIC_CORE_STREAM_DELEGATE_INTERFACE_H_
 
 #include <cstddef>
+#include <optional>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_stream_priority.h"
 #include "quiche/quic/core/quic_types.h"
 
diff --git a/quiche/quic/core/tls_chlo_extractor.h b/quiche/quic/core/tls_chlo_extractor.h
index 324365e..c8d7810 100644
--- a/quiche/quic/core/tls_chlo_extractor.h
+++ b/quiche/quic/core/tls_chlo_extractor.h
@@ -71,7 +71,7 @@
   }
 
   // Returns the TLS alert that caused the unrecoverable error, if any.
-  absl::optional<uint8_t> tls_alert() const {
+  std::optional<uint8_t> tls_alert() const {
     QUICHE_DCHECK(!tls_alert_.has_value() ||
                   state_ == State::kUnrecoverableFailure);
     return tls_alert_;
@@ -117,7 +117,7 @@
   }
   bool OnAckFrameEnd(
       QuicPacketNumber /*start*/,
-      const absl::optional<QuicEcnCounts>& /*ecn_counts*/) override {
+      const std::optional<QuicEcnCounts>& /*ecn_counts*/) override {
     return true;
   }
   bool OnStopWaitingFrame(const QuicStopWaitingFrame& /*frame*/) override {
@@ -271,7 +271,7 @@
   bool early_data_attempted_ = false;
   // If set, contains the TLS alert that caused an unrecoverable error, which is
   // an AlertDescription value defined in go/rfc/8446#appendix-B.2.
-  absl::optional<uint8_t> tls_alert_;
+  std::optional<uint8_t> tls_alert_;
   // Exact TLS message bytes.
   std::vector<uint8_t> client_hello_bytes_;
 };
diff --git a/quiche/quic/core/tls_chlo_extractor_test.cc b/quiche/quic/core/tls_chlo_extractor_test.cc
index f08c794..4874689 100644
--- a/quiche/quic/core/tls_chlo_extractor_test.cc
+++ b/quiche/quic/core/tls_chlo_extractor_test.cc
@@ -105,7 +105,7 @@
           QuicSocketAddress(TestPeerIPAddress(), kTestPort),
           QuicSocketAddress(TestPeerIPAddress(), kTestPort), *packet);
       std::string detailed_error;
-      absl::optional<absl::string_view> retry_token;
+      std::optional<absl::string_view> retry_token;
       const QuicErrorCode error = QuicFramer::ParsePublicHeaderDispatcher(
           *packet, /*expected_destination_connection_id_length=*/0,
           &packet_info.form, &packet_info.long_packet_type,
@@ -289,7 +289,7 @@
       QuicSocketAddress(TestPeerIPAddress(), kTestPort),
       QuicSocketAddress(TestPeerIPAddress(), kTestPort), *packets_[0]);
   std::string detailed_error;
-  absl::optional<absl::string_view> retry_token;
+  std::optional<absl::string_view> retry_token;
   const QuicErrorCode error = QuicFramer::ParsePublicHeaderDispatcher(
       *packets_[0], /*expected_destination_connection_id_length=*/0,
       &packet_info.form, &packet_info.long_packet_type,
diff --git a/quiche/quic/core/tls_client_handshaker_test.cc b/quiche/quic/core/tls_client_handshaker_test.cc
index 414ecf2..8b2ea68 100644
--- a/quiche/quic/core/tls_client_handshaker_test.cc
+++ b/quiche/quic/core/tls_client_handshaker_test.cc
@@ -275,7 +275,7 @@
   QuicServerId server_id_;
   CryptoHandshakeMessage message_;
   std::unique_ptr<QuicCryptoClientConfig> crypto_config_;
-  absl::optional<QuicSSLConfig> ssl_config_;
+  std::optional<QuicSSLConfig> ssl_config_;
 
   // Server state.
   std::unique_ptr<QuicCryptoServerConfig> server_crypto_config_;
diff --git a/quiche/quic/core/tls_handshaker.h b/quiche/quic/core/tls_handshaker.h
index e2ee604..c14e12e 100644
--- a/quiche/quic/core/tls_handshaker.h
+++ b/quiche/quic/core/tls_handshaker.h
@@ -225,7 +225,7 @@
     // https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-6
     uint8_t desc;
   };
-  absl::optional<TlsAlert> last_tls_alert_;
+  std::optional<TlsAlert> last_tls_alert_;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/core/tls_server_handshaker.cc b/quiche/quic/core/tls_server_handshaker.cc
index 5a8cb92..8173a5a 100644
--- a/quiche/quic/core/tls_server_handshaker.cc
+++ b/quiche/quic/core/tls_server_handshaker.cc
@@ -65,9 +65,9 @@
     const QuicConnectionId& /*original_connection_id*/,
     absl::string_view /*ssl_capabilities*/, const std::string& hostname,
     absl::string_view /*client_hello*/, const std::string& /*alpn*/,
-    absl::optional<std::string> /*alps*/,
+    std::optional<std::string> /*alps*/,
     const std::vector<uint8_t>& /*quic_transport_params*/,
-    const absl::optional<std::vector<uint8_t>>& /*early_data_context*/,
+    const std::optional<std::vector<uint8_t>>& /*early_data_context*/,
     const QuicSSLConfig& /*ssl_config*/) {
   if (!handshaker_ || !proof_source_) {
     QUIC_BUG(quic_bug_10341_1)
@@ -145,7 +145,7 @@
   const bool is_async =
       (handshaker->expected_ssl_error() == SSL_ERROR_PENDING_TICKET);
 
-  absl::optional<QuicConnectionContextSwitcher> context_switcher;
+  std::optional<QuicConnectionContextSwitcher> context_switcher;
 
   if (is_async) {
     context_switcher.emplace(handshaker->connection_context());
@@ -704,7 +704,7 @@
   QUIC_DVLOG(1) << "OnComputeSignatureDone. ok:" << ok
                 << ", is_sync:" << is_sync
                 << ", len(signature):" << signature.size();
-  absl::optional<QuicConnectionContextSwitcher> context_switcher;
+  std::optional<QuicConnectionContextSwitcher> context_switcher;
 
   if (!is_sync) {
     context_switcher.emplace(connection_context());
@@ -986,7 +986,7 @@
                 << ", len(handshake_hints):" << handshake_hints.size()
                 << ", len(ticket_encryption_key):"
                 << ticket_encryption_key.size();
-  absl::optional<QuicConnectionContextSwitcher> context_switcher;
+  std::optional<QuicConnectionContextSwitcher> context_switcher;
   if (!is_sync) {
     context_switcher.emplace(connection_context());
   }
diff --git a/quiche/quic/core/tls_server_handshaker.h b/quiche/quic/core/tls_server_handshaker.h
index 4506369..682c9f8 100644
--- a/quiche/quic/core/tls_server_handshaker.h
+++ b/quiche/quic/core/tls_server_handshaker.h
@@ -163,7 +163,7 @@
   TlsConnection::Delegate* ConnectionDelegate() override { return this; }
 
   // The status of cert selection. nullopt means it hasn't started.
-  const absl::optional<QuicAsyncStatus>& select_cert_status() const {
+  const std::optional<QuicAsyncStatus>& select_cert_status() const {
     return select_cert_status_;
   }
   // Whether |cert_verify_sig_| contains a valid signature.
@@ -230,9 +230,9 @@
         const QuicConnectionId& original_connection_id,
         absl::string_view ssl_capabilities, const std::string& hostname,
         absl::string_view client_hello, const std::string& alpn,
-        absl::optional<std::string> alps,
+        std::optional<std::string> alps,
         const std::vector<uint8_t>& quic_transport_params,
-        const absl::optional<std::vector<uint8_t>>& early_data_context,
+        const std::optional<std::vector<uint8_t>>& early_data_context,
         const QuicSSLConfig& ssl_config) override;
 
     // Delegates to proof_source_->ComputeTlsSignature.
@@ -292,9 +292,9 @@
     bool success = false;
     // Empty vector if QUIC transport params are not set successfully.
     std::vector<uint8_t> quic_transport_params;
-    // absl::nullopt if there is no application state to begin with.
+    // std::nullopt if there is no application state to begin with.
     // Empty vector if application state is not set successfully.
-    absl::optional<std::vector<uint8_t>> early_data_context;
+    std::optional<std::vector<uint8_t>> early_data_context;
   };
 
   SetTransportParametersResult SetTransportParameters();
@@ -307,7 +307,7 @@
 
   struct QUICHE_EXPORT SetApplicationSettingsResult {
     bool success = false;
-    // TODO(b/239676439): Change type to absl::optional<std::string> and make
+    // TODO(b/239676439): Change type to std::optional<std::string> and make
     // sure SetApplicationSettings() returns nullopt if no ALPS data.
     std::string alps_buffer;
   };
@@ -346,13 +346,13 @@
   bool ignore_ticket_open_ = false;
 
   // nullopt means select cert hasn't started.
-  absl::optional<QuicAsyncStatus> select_cert_status_;
+  std::optional<QuicAsyncStatus> select_cert_status_;
 
   std::string cert_verify_sig_;
   std::unique_ptr<ProofSource::Details> proof_source_details_;
 
   // Count the duration of the current async operation, if any.
-  absl::optional<QuicTimeAccumulator> async_op_timer_;
+  std::optional<QuicTimeAccumulator> async_op_timer_;
 
   std::unique_ptr<ApplicationState> application_state_;
 
diff --git a/quiche/quic/load_balancer/load_balancer_config.cc b/quiche/quic/load_balancer/load_balancer_config.cc
index 5469a1a..6f25c90 100644
--- a/quiche/quic/load_balancer/load_balancer_config.cc
+++ b/quiche/quic/load_balancer/load_balancer_config.cc
@@ -6,9 +6,9 @@
 
 #include <cstdint>
 #include <cstring>
+#include <optional>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "openssl/aes.h"
 #include "quiche/quic/core/quic_connection_id.h"
@@ -37,19 +37,19 @@
 }
 
 // Initialize the key in the constructor
-absl::optional<AES_KEY> BuildKey(absl::string_view key, bool encrypt) {
+std::optional<AES_KEY> BuildKey(absl::string_view key, bool encrypt) {
   if (key.empty()) {
-    return absl::optional<AES_KEY>();
+    return std::optional<AES_KEY>();
   }
   AES_KEY raw_key;
   if (encrypt) {
     if (AES_set_encrypt_key(reinterpret_cast<const uint8_t *>(key.data()),
                             key.size() * 8, &raw_key) < 0) {
-      return absl::optional<AES_KEY>();
+      return std::optional<AES_KEY>();
     }
   } else if (AES_set_decrypt_key(reinterpret_cast<const uint8_t *>(key.data()),
                                  key.size() * 8, &raw_key) < 0) {
-    return absl::optional<AES_KEY>();
+    return std::optional<AES_KEY>();
   }
   return raw_key;
 }
@@ -116,17 +116,17 @@
 
 }  // namespace
 
-absl::optional<LoadBalancerConfig> LoadBalancerConfig::Create(
+std::optional<LoadBalancerConfig> LoadBalancerConfig::Create(
     const uint8_t config_id, const uint8_t server_id_len,
     const uint8_t nonce_len, const absl::string_view key) {
   //  Check for valid parameters.
   if (key.size() != kLoadBalancerKeyLen) {
     QUIC_BUG(quic_bug_433862549_02)
         << "Invalid LoadBalancerConfig Key Length: " << key.size();
-    return absl::optional<LoadBalancerConfig>();
+    return std::optional<LoadBalancerConfig>();
   }
   if (!CommonValidation(config_id, server_id_len, nonce_len)) {
-    return absl::optional<LoadBalancerConfig>();
+    return std::optional<LoadBalancerConfig>();
   }
   auto new_config =
       LoadBalancerConfig(config_id, server_id_len, nonce_len, key);
@@ -134,18 +134,18 @@
     // Something went wrong in assigning the key!
     QUIC_BUG(quic_bug_433862549_03) << "Something went wrong in initializing "
                                        "the load balancing key.";
-    return absl::optional<LoadBalancerConfig>();
+    return std::optional<LoadBalancerConfig>();
   }
   return new_config;
 }
 
 // Creates an unencrypted config.
-absl::optional<LoadBalancerConfig> LoadBalancerConfig::CreateUnencrypted(
+std::optional<LoadBalancerConfig> LoadBalancerConfig::CreateUnencrypted(
     const uint8_t config_id, const uint8_t server_id_len,
     const uint8_t nonce_len) {
   return CommonValidation(config_id, server_id_len, nonce_len)
              ? LoadBalancerConfig(config_id, server_id_len, nonce_len, "")
-             : absl::optional<LoadBalancerConfig>();
+             : std::optional<LoadBalancerConfig>();
 }
 
 bool LoadBalancerConfig::EncryptionPass(absl::Span<uint8_t> target,
@@ -201,6 +201,6 @@
       key_(BuildKey(key, /* encrypt = */ true)),
       block_decrypt_key_((server_id_len + nonce_len == kLoadBalancerBlockSize)
                              ? BuildKey(key, /* encrypt = */ false)
-                             : absl::optional<AES_KEY>()) {}
+                             : std::optional<AES_KEY>()) {}
 
 }  // namespace quic
diff --git a/quiche/quic/load_balancer/load_balancer_config.h b/quiche/quic/load_balancer/load_balancer_config.h
index 7f63edd..f3ca75c 100644
--- a/quiche/quic/load_balancer/load_balancer_config.h
+++ b/quiche/quic/load_balancer/load_balancer_config.h
@@ -6,9 +6,9 @@
 #define QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_CONFIG_H_
 
 #include <cstdint>
+#include <optional>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "openssl/aes.h"
 #include "quiche/quic/platform/api/quic_export.h"
@@ -38,7 +38,7 @@
 class QUIC_EXPORT_PRIVATE LoadBalancerConfig {
  public:
   // This factory function initializes an encrypted LoadBalancerConfig and
-  // returns it in absl::optional, which is empty if the config is invalid.
+  // returns it in std::optional, which is empty if the config is invalid.
   // config_id: The first two bits of the Connection Id. Must be no larger than
   // 2.
   // server_id_len: Expected length of the server ids associated with this
@@ -46,13 +46,13 @@
   // nonce_len: Length of the nonce. Must be at least 4 and no larger than 16.
   // Further the server_id_len + nonce_len must be no larger than 19.
   // key: The encryption key must be 16B long.
-  static absl::optional<LoadBalancerConfig> Create(uint8_t config_id,
-                                                   uint8_t server_id_len,
-                                                   uint8_t nonce_len,
-                                                   absl::string_view key);
+  static std::optional<LoadBalancerConfig> Create(uint8_t config_id,
+                                                  uint8_t server_id_len,
+                                                  uint8_t nonce_len,
+                                                  absl::string_view key);
 
   // Creates an unencrypted config.
-  static absl::optional<LoadBalancerConfig> CreateUnencrypted(
+  static std::optional<LoadBalancerConfig> CreateUnencrypted(
       uint8_t config_id, uint8_t server_id_len, uint8_t nonce_len);
 
   // Handles one pass of 4-pass encryption. Encoder and decoder use of this
@@ -91,12 +91,12 @@
   // All Connection ID encryption and decryption uses the AES_encrypt function
   // at root, so there is a single key for all of it. This is empty if the
   // config is not encrypted.
-  absl::optional<AES_KEY> key_;
+  std::optional<AES_KEY> key_;
   // The one exception is that when total_len == 16, connection ID decryption
   // uses AES_decrypt. The bytes that comprise the key are the same, but
   // AES_decrypt requires an AES_KEY that is initialized differently. In all
   // other cases, block_decrypt_key_ is empty.
-  absl::optional<AES_KEY> block_decrypt_key_;
+  std::optional<AES_KEY> block_decrypt_key_;
 };
 
 }  // namespace quic
diff --git a/quiche/quic/load_balancer/load_balancer_decoder.cc b/quiche/quic/load_balancer/load_balancer_decoder.cc
index a475ada..b1748d6 100644
--- a/quiche/quic/load_balancer/load_balancer_decoder.cc
+++ b/quiche/quic/load_balancer/load_balancer_decoder.cc
@@ -6,8 +6,8 @@
 
 #include <cstdint>
 #include <cstring>
+#include <optional>
 
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/core/quic_connection_id.h"
 #include "quiche/quic/load_balancer/load_balancer_config.h"
@@ -36,19 +36,19 @@
 
 // This is the core logic to extract a server ID given a valid config and
 // connection ID of sufficient length.
-absl::optional<LoadBalancerServerId> LoadBalancerDecoder::GetServerId(
+std::optional<LoadBalancerServerId> LoadBalancerDecoder::GetServerId(
     const QuicConnectionId& connection_id) const {
-  absl::optional<uint8_t> config_id = GetConfigId(connection_id);
+  std::optional<uint8_t> config_id = GetConfigId(connection_id);
   if (!config_id.has_value()) {
-    return absl::optional<LoadBalancerServerId>();
+    return std::optional<LoadBalancerServerId>();
   }
-  absl::optional<LoadBalancerConfig> config = config_[*config_id];
+  std::optional<LoadBalancerConfig> config = config_[*config_id];
   if (!config.has_value()) {
-    return absl::optional<LoadBalancerServerId>();
+    return std::optional<LoadBalancerServerId>();
   }
   if (connection_id.length() < config->total_len()) {
     // Connection ID wasn't long enough
-    return absl::optional<LoadBalancerServerId>();
+    return std::optional<LoadBalancerServerId>();
   }
   // The first byte is complete. Finish the rest.
   const uint8_t* data =
@@ -60,7 +60,7 @@
   uint8_t result[kQuicMaxConnectionIdWithLengthPrefixLength];
   if (config->plaintext_len() == kLoadBalancerKeyLen) {  // single pass
     if (!config->BlockDecrypt(data, result)) {
-      return absl::optional<LoadBalancerServerId>();
+      return std::optional<LoadBalancerServerId>();
     }
   } else {
     // Do 3 or 4 passes. Only 3 are necessary if the server_id is short enough
@@ -70,7 +70,7 @@
     uint8_t end = (config->server_id_len() > config->nonce_len()) ? 1 : 2;
     for (uint8_t i = kNumLoadBalancerCryptoPasses; i >= end; i--) {
       if (!config->EncryptionPass(absl::Span<uint8_t>(result), i)) {
-        return absl::optional<LoadBalancerServerId>();
+        return std::optional<LoadBalancerServerId>();
       }
     }
   }
@@ -78,21 +78,21 @@
       absl::Span<const uint8_t>(result, config->server_id_len()));
 }
 
-absl::optional<uint8_t> LoadBalancerDecoder::GetConfigId(
+std::optional<uint8_t> LoadBalancerDecoder::GetConfigId(
     const QuicConnectionId& connection_id) {
   if (connection_id.IsEmpty()) {
-    return absl::optional<uint8_t>();
+    return std::optional<uint8_t>();
   }
   return GetConfigId(*reinterpret_cast<const uint8_t*>(connection_id.data()));
 }
 
-absl::optional<uint8_t> LoadBalancerDecoder::GetConfigId(
+std::optional<uint8_t> LoadBalancerDecoder::GetConfigId(
     const uint8_t connection_id_first_byte) {
   uint8_t codepoint = (connection_id_first_byte >> kConnectionIdLengthBits);
   if (codepoint < kNumLoadBalancerConfigs) {
     return codepoint;
   }
-  return absl::optional<uint8_t>();
+  return std::optional<uint8_t>();
 }
 
 }  // namespace quic
diff --git a/quiche/quic/load_balancer/load_balancer_decoder.h b/quiche/quic/load_balancer/load_balancer_decoder.h
index f73f3a5..11852a3 100644
--- a/quiche/quic/load_balancer/load_balancer_decoder.h
+++ b/quiche/quic/load_balancer/load_balancer_decoder.h
@@ -6,8 +6,8 @@
 #define QUICHE_QUIC_LOAD_BALANCER_LOAD_BALANCER_DECODER_H_
 
 #include <cstdint>
+#include <optional>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_connection_id.h"
 #include "quiche/quic/load_balancer/load_balancer_config.h"
 #include "quiche/quic/load_balancer/load_balancer_server_id.h"
@@ -40,22 +40,22 @@
   // codepoint, |connection_id| is too short, or there's a decrypt error,
   // returns empty. Will accept |connection_id| that is longer than necessary
   // without error.
-  absl::optional<LoadBalancerServerId> GetServerId(
+  std::optional<LoadBalancerServerId> GetServerId(
       const QuicConnectionId& connection_id) const;
 
   // Returns the config ID stored in the first two bits of |connection_id|, or
   // empty if |connection_id| is empty, or the first two bits of the first byte
   // of |connection_id| are 0b11.
-  static absl::optional<uint8_t> GetConfigId(
+  static std::optional<uint8_t> GetConfigId(
       const QuicConnectionId& connection_id);
 
   // Returns the config ID stored in the first two bits of
   // |connection_id_first_byte|, or empty if the first two bits are 0b11.
-  static absl::optional<uint8_t> GetConfigId(uint8_t connection_id_first_byte);
+  static std::optional<uint8_t> GetConfigId(uint8_t connection_id_first_byte);
 
  private:
   // Decoders can support up to 3 configs at once.
-  absl::optional<LoadBalancerConfig> config_[kNumLoadBalancerConfigs];
+  std::optional<LoadBalancerConfig> config_[kNumLoadBalancerConfigs];
 };
 
 }  // namespace quic
diff --git a/quiche/quic/load_balancer/load_balancer_encoder.cc b/quiche/quic/load_balancer/load_balancer_encoder.cc
index 2d3f15b..e956df2 100644
--- a/quiche/quic/load_balancer/load_balancer_encoder.cc
+++ b/quiche/quic/load_balancer/load_balancer_encoder.cc
@@ -5,9 +5,9 @@
 #include "quiche/quic/load_balancer/load_balancer_encoder.h"
 
 #include <cstdint>
+#include <optional>
 
 #include "absl/numeric/int128.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/quic_random.h"
 #include "quiche/quic/core/quic_connection_id.h"
 #include "quiche/quic/core/quic_data_writer.h"
@@ -49,7 +49,7 @@
 
 }  // namespace
 
-absl::optional<LoadBalancerEncoder> LoadBalancerEncoder::Create(
+std::optional<LoadBalancerEncoder> LoadBalancerEncoder::Create(
     QuicRandom &random, LoadBalancerEncoderVisitorInterface *const visitor,
     const bool len_self_encoded, const uint8_t unroutable_connection_id_len) {
   if (unroutable_connection_id_len == 0 ||
@@ -58,7 +58,7 @@
     QUIC_BUG(quic_bug_435375038_01)
         << "Invalid unroutable_connection_id_len = "
         << static_cast<int>(unroutable_connection_id_len);
-    return absl::optional<LoadBalancerEncoder>();
+    return std::optional<LoadBalancerEncoder>();
   }
   return LoadBalancerEncoder(random, visitor, len_self_encoded,
                              unroutable_connection_id_len);
@@ -170,14 +170,14 @@
   return id;
 }
 
-absl::optional<QuicConnectionId> LoadBalancerEncoder::GenerateNextConnectionId(
+std::optional<QuicConnectionId> LoadBalancerEncoder::GenerateNextConnectionId(
     [[maybe_unused]] const QuicConnectionId &original) {
   // Do not allow new connection IDs if linkable.
-  return (IsEncoding() && !IsEncrypted()) ? absl::optional<QuicConnectionId>()
+  return (IsEncoding() && !IsEncrypted()) ? std::optional<QuicConnectionId>()
                                           : GenerateConnectionId();
 }
 
-absl::optional<QuicConnectionId> LoadBalancerEncoder::MaybeReplaceConnectionId(
+std::optional<QuicConnectionId> LoadBalancerEncoder::MaybeReplaceConnectionId(
     const QuicConnectionId &original, const ParsedQuicVersion &version) {
   // Pre-IETF versions of QUIC can respond poorly to new connection IDs issued
   // during the handshake.
@@ -185,7 +185,7 @@
                               ? config_->total_len()
                               : connection_id_lengths_[kNumLoadBalancerConfigs];
   return (!version.HasIetfQuicFrames() && original.length() == needed_length)
-             ? absl::optional<QuicConnectionId>()
+             ? std::optional<QuicConnectionId>()
              : GenerateConnectionId();
 }
 
diff --git a/quiche/quic/load_balancer/load_balancer_encoder.h b/quiche/quic/load_balancer/load_balancer_encoder.h
index 2d70a7c..2c3dd7e 100644
--- a/quiche/quic/load_balancer/load_balancer_encoder.h
+++ b/quiche/quic/load_balancer/load_balancer_encoder.h
@@ -7,9 +7,9 @@
 
 #include <algorithm>
 #include <cstdint>
+#include <optional>
 
 #include "absl/numeric/int128.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/connection_id_generator.h"
 #include "quiche/quic/core/crypto/quic_random.h"
 #include "quiche/quic/core/quic_connection_id.h"
@@ -89,7 +89,7 @@
   // random. |unroutable_connection_id_length| specifies the length of
   // connection IDs to be generated when there is no active config. It must not
   // be 0 and must not be larger than the RFC9000 maximum of 20.
-  static absl::optional<LoadBalancerEncoder> Create(
+  static std::optional<LoadBalancerEncoder> Create(
       QuicRandom& random, LoadBalancerEncoderVisitorInterface* visitor,
       bool len_self_encoded,
       uint8_t unroutable_connection_id_len = kLoadBalancerUnroutableLen);
@@ -126,9 +126,9 @@
   QuicConnectionId GenerateConnectionId();
 
   // Functions from ConnectionIdGeneratorInterface
-  absl::optional<QuicConnectionId> GenerateNextConnectionId(
+  std::optional<QuicConnectionId> GenerateNextConnectionId(
       const QuicConnectionId& original) override;
-  absl::optional<QuicConnectionId> MaybeReplaceConnectionId(
+  std::optional<QuicConnectionId> MaybeReplaceConnectionId(
       const QuicConnectionId& original,
       const ParsedQuicVersion& version) override;
   uint8_t ConnectionIdLength(uint8_t first_byte) const override;
@@ -154,9 +154,9 @@
   const bool len_self_encoded_;
   LoadBalancerEncoderVisitorInterface* const visitor_;
 
-  absl::optional<LoadBalancerConfig> config_;
+  std::optional<LoadBalancerConfig> config_;
   absl::uint128 seed_, num_nonces_left_ = 0;
-  absl::optional<LoadBalancerServerId> server_id_;
+  std::optional<LoadBalancerServerId> server_id_;
   uint8_t connection_id_lengths_[kNumLoadBalancerConfigs + 1];
 };
 
diff --git a/quiche/quic/load_balancer/load_balancer_encoder_test.cc b/quiche/quic/load_balancer/load_balancer_encoder_test.cc
index 5566df6..929832b 100644
--- a/quiche/quic/load_balancer/load_balancer_encoder_test.cc
+++ b/quiche/quic/load_balancer/load_balancer_encoder_test.cc
@@ -7,11 +7,11 @@
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
+#include <optional>
 #include <queue>
 
 #include "absl/numeric/int128.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/core/crypto/quic_random.h"
 #include "quiche/quic/core/quic_connection_id.h"
@@ -65,7 +65,7 @@
 
  private:
   uint32_t num_adds_ = 0, num_deletes_ = 0;
-  absl::optional<uint8_t> current_config_id_ = absl::optional<uint8_t>();
+  std::optional<uint8_t> current_config_id_ = std::optional<uint8_t>();
 };
 
 // Allows the caller to specify the exact results in 64-bit chunks.
@@ -374,7 +374,7 @@
   ASSERT_TRUE(encoder.has_value());
   EXPECT_EQ(encoder->MaybeReplaceConnectionId(TestConnectionId(1),
                                               ParsedQuicVersion::Q050()),
-            absl::nullopt);
+            std::nullopt);
 }
 
 TEST_F(LoadBalancerEncoderTest, MaybeReplaceConnectionIdReturnsChange) {
@@ -395,7 +395,7 @@
   auto encoder = LoadBalancerEncoder::Create(random_, nullptr, true);
   EXPECT_TRUE(encoder->UpdateConfig(*config, MakeServerId(kServerId, 3)));
   EXPECT_EQ(encoder->GenerateNextConnectionId(TestConnectionId(1)),
-            absl::nullopt);
+            std::nullopt);
 }
 
 TEST_F(LoadBalancerEncoderTest, GenerateNextConnectionIdReturnsChange) {
diff --git a/quiche/quic/load_balancer/load_balancer_server_id.cc b/quiche/quic/load_balancer/load_balancer_server_id.cc
index 7b91b7f..c3cd326 100644
--- a/quiche/quic/load_balancer/load_balancer_server_id.cc
+++ b/quiche/quic/load_balancer/load_balancer_server_id.cc
@@ -7,11 +7,11 @@
 #include <array>
 #include <cstdint>
 #include <cstring>
+#include <optional>
 #include <string>
 
 #include "absl/strings/escaping.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/platform/api/quic_bug_tracker.h"
 
@@ -29,13 +29,13 @@
 
 }  // namespace
 
-absl::optional<LoadBalancerServerId> LoadBalancerServerId::Create(
+std::optional<LoadBalancerServerId> LoadBalancerServerId::Create(
     const absl::Span<const uint8_t> data) {
   if (data.length() == 0 || data.length() > kLoadBalancerMaxServerIdLen) {
     QUIC_BUG(quic_bug_433312504_01)
         << "Attempted to create LoadBalancerServerId with length "
         << data.length();
-    return absl::optional<LoadBalancerServerId>();
+    return std::optional<LoadBalancerServerId>();
   }
   return LoadBalancerServerId(data);
 }
diff --git a/quiche/quic/load_balancer/load_balancer_server_id.h b/quiche/quic/load_balancer/load_balancer_server_id.h
index fdb4604..1a42f9c 100644
--- a/quiche/quic/load_balancer/load_balancer_server_id.h
+++ b/quiche/quic/load_balancer/load_balancer_server_id.h
@@ -7,10 +7,10 @@
 
 #include <array>
 #include <cstdint>
+#include <optional>
 #include <string>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/platform/api/quic_export.h"
 
@@ -29,11 +29,11 @@
 class QUIC_EXPORT_PRIVATE LoadBalancerServerId {
  public:
   // Copies all the bytes from |data| into a new LoadBalancerServerId.
-  static absl::optional<LoadBalancerServerId> Create(
+  static std::optional<LoadBalancerServerId> Create(
       absl::Span<const uint8_t> data);
 
   // For callers with a string_view at hand.
-  static absl::optional<LoadBalancerServerId> Create(absl::string_view data) {
+  static std::optional<LoadBalancerServerId> Create(absl::string_view data) {
     return Create(absl::MakeSpan(reinterpret_cast<const uint8_t*>(data.data()),
                                  data.length()));
   }
diff --git a/quiche/quic/load_balancer/load_balancer_server_id_map.h b/quiche/quic/load_balancer/load_balancer_server_id_map.h
index 1b108fc..6110775 100644
--- a/quiche/quic/load_balancer/load_balancer_server_id_map.h
+++ b/quiche/quic/load_balancer/load_balancer_server_id_map.h
@@ -7,9 +7,9 @@
 
 #include <cstdint>
 #include <memory>
+#include <optional>
 
 #include "absl/container/flat_hash_map.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/load_balancer/load_balancer_server_id.h"
 #include "quiche/quic/platform/api/quic_bug_tracker.h"
 
@@ -28,7 +28,7 @@
 
   // Returns the entry associated with |server_id|, if present. For small |T|,
   // use Lookup. For large |T|, use LookupNoCopy.
-  absl::optional<const T> Lookup(LoadBalancerServerId server_id) const;
+  std::optional<const T> Lookup(LoadBalancerServerId server_id) const;
   const T* LookupNoCopy(LoadBalancerServerId server_id) const;
 
   // Updates the table so that |value| is associated with |server_id|. Sets
@@ -64,17 +64,16 @@
 }
 
 template <typename T>
-absl::optional<const T> LoadBalancerServerIdMap<T>::Lookup(
+std::optional<const T> LoadBalancerServerIdMap<T>::Lookup(
     const LoadBalancerServerId server_id) const {
   if (server_id.length() != server_id_len_) {
     QUIC_BUG(quic_bug_434893339_02)
         << "Lookup with a " << static_cast<int>(server_id.length())
         << " byte server ID, map requires " << static_cast<int>(server_id_len_);
-    return absl::optional<T>();
+    return std::optional<T>();
   }
   auto it = server_id_table_.find(server_id);
-  return (it != server_id_table_.end()) ? it->second
-                                        : absl::optional<const T>();
+  return (it != server_id_table_.end()) ? it->second : std::optional<const T>();
 }
 
 template <typename T>
diff --git a/quiche/quic/load_balancer/load_balancer_server_id_map_test.cc b/quiche/quic/load_balancer/load_balancer_server_id_map_test.cc
index 6fe680f..0b78ab5 100644
--- a/quiche/quic/load_balancer/load_balancer_server_id_map_test.cc
+++ b/quiche/quic/load_balancer/load_balancer_server_id_map_test.cc
@@ -5,8 +5,8 @@
 #include "quiche/quic/load_balancer/load_balancer_server_id_map.h"
 
 #include <cstdint>
+#include <optional>
 
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/load_balancer/load_balancer_server_id.h"
 #include "quiche/quic/platform/api/quic_expect_bug.h"
@@ -58,7 +58,7 @@
   auto pool = LoadBalancerServerIdMap<int>::Create(4);
   EXPECT_NE(pool, nullptr);
   EXPECT_EQ(pool->LookupNoCopy(valid_server_id_), nullptr);
-  absl::optional<int> result = pool->Lookup(valid_server_id_);
+  std::optional<int> result = pool->Lookup(valid_server_id_);
   EXPECT_FALSE(result.has_value());
 }
 
@@ -70,7 +70,7 @@
   EXPECT_TRUE(other_server_id.has_value());
   pool->AddOrReplace(valid_server_id_, record1);
   pool->AddOrReplace(*other_server_id, record2);
-  absl::optional<int> result = pool->Lookup(valid_server_id_);
+  std::optional<int> result = pool->Lookup(valid_server_id_);
   EXPECT_TRUE(result.has_value());
   EXPECT_EQ(*result, record1);
   auto result_ptr = pool->LookupNoCopy(valid_server_id_);
diff --git a/quiche/quic/masque/masque_client_tools.cc b/quiche/quic/masque/masque_client_tools.cc
index 8410529..318cb78 100644
--- a/quiche/quic/masque/masque_client_tools.cc
+++ b/quiche/quic/masque/masque_client_tools.cc
@@ -4,7 +4,8 @@
 
 #include "quiche/quic/masque/masque_client_tools.h"
 
-#include "absl/types/optional.h"
+#include <optional>
+
 #include "quiche/quic/masque/masque_encapsulated_client.h"
 #include "quiche/quic/masque/masque_utils.h"
 #include "quiche/quic/platform/api/quic_default_proof_providers.h"
@@ -37,7 +38,7 @@
   }
 
  private:
-  absl::optional<quiche::QuicheIpAddress> fake_address_;
+  std::optional<quiche::QuicheIpAddress> fake_address_;
   MasqueClientSession* masque_client_session_ = nullptr;
 };
 
diff --git a/quiche/quic/masque/masque_encapsulated_client.cc b/quiche/quic/masque/masque_encapsulated_client.cc
index f24143e..6afdb0e 100644
--- a/quiche/quic/masque/masque_encapsulated_client.cc
+++ b/quiche/quic/masque/masque_encapsulated_client.cc
@@ -187,8 +187,8 @@
 
   void SetWritable() override {}
 
-  absl::optional<int> MessageTooBigErrorCode() const override {
-    return absl::nullopt;
+  std::optional<int> MessageTooBigErrorCode() const override {
+    return std::nullopt;
   }
 
   QuicByteCount GetMaxPacketSize(
diff --git a/quiche/quic/masque/masque_server_session.cc b/quiche/quic/masque/masque_server_session.cc
index 2cd15df..4e7fcdf 100644
--- a/quiche/quic/masque/masque_server_session.cc
+++ b/quiche/quic/masque/masque_server_session.cc
@@ -13,13 +13,13 @@
 #include <cstddef>
 #include <cstdint>
 #include <limits>
+#include <optional>
 
 
 #include "absl/cleanup/cleanup.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/http/spdy_utils.h"
 #include "quiche/quic/core/io/quic_event_loop.h"
 #include "quiche/quic/core/quic_data_reader.h"
@@ -282,12 +282,12 @@
     QUIC_DLOG(ERROR) << "MASQUE request with bad path \"" << path << "\"";
     return CreateBackendErrorResponse("400", "Bad path");
   }
-  absl::optional<std::string> host = quiche::AsciiUrlDecode(path_split[4]);
+  std::optional<std::string> host = quiche::AsciiUrlDecode(path_split[4]);
   if (!host.has_value()) {
     QUIC_DLOG(ERROR) << "Failed to decode host \"" << path_split[4] << "\"";
     return CreateBackendErrorResponse("500", "Failed to decode host");
   }
-  absl::optional<std::string> port = quiche::AsciiUrlDecode(path_split[5]);
+  std::optional<std::string> port = quiche::AsciiUrlDecode(path_split[5]);
   if (!port.has_value()) {
     QUIC_DLOG(ERROR) << "Failed to decode port \"" << path_split[5] << "\"";
     return CreateBackendErrorResponse("500", "Failed to decode port");
diff --git a/quiche/quic/moqt/moqt_framer.cc b/quiche/quic/moqt/moqt_framer.cc
index 1e00c85..4111d78 100644
--- a/quiche/quic/moqt/moqt_framer.cc
+++ b/quiche/quic/moqt/moqt_framer.cc
@@ -6,9 +6,9 @@
 
 #include <cstddef>
 #include <cstdint>
+#include <optional>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_data_writer.h"
 #include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/core/quic_types.h"
@@ -37,7 +37,7 @@
 inline size_t ParameterLen(const uint64_t type, const uint64_t value_len) {
   return NeededVarIntLen(type) + NeededVarIntLen(value_len) + value_len;
 }
-inline size_t LocationLength(const absl::optional<MoqtSubscribeLocation> loc) {
+inline size_t LocationLength(const std::optional<MoqtSubscribeLocation> loc) {
   if (!loc.has_value()) {
     return NeededVarIntLen(MoqtSubscribeLocationMode::kNone);
   }
@@ -79,7 +79,7 @@
 }
 
 inline bool WriteLocation(quic::QuicDataWriter& writer,
-                          absl::optional<MoqtSubscribeLocation> loc) {
+                          std::optional<MoqtSubscribeLocation> loc) {
   if (!loc.has_value()) {
     return writer.WriteVarInt62(
         static_cast<uint64_t>(MoqtSubscribeLocationMode::kNone));
diff --git a/quiche/quic/moqt/moqt_framer.h b/quiche/quic/moqt/moqt_framer.h
index 6d0356b..a5f741b 100644
--- a/quiche/quic/moqt/moqt_framer.h
+++ b/quiche/quic/moqt/moqt_framer.h
@@ -6,9 +6,9 @@
 #define QUICHE_QUIC_MOQT_MOQT_FRAMER_H_
 
 #include <cstddef>
+#include <optional>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/moqt/moqt_messages.h"
 #include "quiche/common/platform/api/quiche_export.h"
diff --git a/quiche/quic/moqt/moqt_messages.h b/quiche/quic/moqt/moqt_messages.h
index 7be848b..15948a1 100644
--- a/quiche/quic/moqt/moqt_messages.h
+++ b/quiche/quic/moqt/moqt_messages.h
@@ -9,11 +9,11 @@
 
 #include <cstddef>
 #include <cstdint>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/common/platform/api/quiche_export.h"
@@ -76,13 +76,13 @@
 
 struct QUICHE_EXPORT MoqtClientSetup {
   std::vector<MoqtVersion> supported_versions;
-  absl::optional<MoqtRole> role;
-  absl::optional<absl::string_view> path;
+  std::optional<MoqtRole> role;
+  std::optional<absl::string_view> path;
 };
 
 struct QUICHE_EXPORT MoqtServerSetup {
   MoqtVersion selected_version;
-  absl::optional<MoqtRole> role;
+  std::optional<MoqtRole> role;
 };
 
 struct QUICHE_EXPORT MoqtObject {
@@ -90,7 +90,7 @@
   uint64_t group_sequence;
   uint64_t object_sequence;
   uint64_t object_send_order;
-  absl::optional<uint64_t> payload_length;
+  std::optional<uint64_t> payload_length;
   // Message also includes the object payload.
 };
 
@@ -101,7 +101,7 @@
   kRelativeNext = 0x3,
 };
 
-// kNone: absl::optional<MoqtSubscribeLocation> is nullopt.
+// kNone: std::optional<MoqtSubscribeLocation> is nullopt.
 // kAbsolute: absolute = true
 // kRelativePrevious: absolute is false; relative_value is negative
 // kRelativeNext: absolute is true; relative_value is positive
@@ -125,12 +125,12 @@
 struct QUICHE_EXPORT MoqtSubscribeRequest {
   absl::string_view track_namespace;
   absl::string_view track_name;
-  // If the mode is kNone, the these are absl::nullopt.
-  absl::optional<MoqtSubscribeLocation> start_group;
-  absl::optional<MoqtSubscribeLocation> start_object;
-  absl::optional<MoqtSubscribeLocation> end_group;
-  absl::optional<MoqtSubscribeLocation> end_object;
-  absl::optional<absl::string_view> authorization_info;
+  // If the mode is kNone, the these are std::nullopt.
+  std::optional<MoqtSubscribeLocation> start_group;
+  std::optional<MoqtSubscribeLocation> start_object;
+  std::optional<MoqtSubscribeLocation> end_group;
+  std::optional<MoqtSubscribeLocation> end_object;
+  std::optional<absl::string_view> authorization_info;
 };
 
 struct QUICHE_EXPORT MoqtSubscribeOk {
@@ -171,7 +171,7 @@
 
 struct QUICHE_EXPORT MoqtAnnounce {
   absl::string_view track_namespace;
-  absl::optional<absl::string_view> authorization_info;
+  std::optional<absl::string_view> authorization_info;
 };
 
 struct QUICHE_EXPORT MoqtAnnounceOk {
diff --git a/quiche/quic/moqt/moqt_parser.cc b/quiche/quic/moqt/moqt_parser.cc
index 2c76502..b672489 100644
--- a/quiche/quic/moqt/moqt_parser.cc
+++ b/quiche/quic/moqt/moqt_parser.cc
@@ -8,12 +8,12 @@
 #include <cstdint>
 #include <cstring>
 #include <memory>
+#include <optional>
 #include <string>
 
 #include "absl/cleanup/cleanup.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_data_reader.h"
 #include "quiche/quic/core/quic_time.h"
 #include "quiche/quic/moqt/moqt_messages.h"
@@ -52,7 +52,7 @@
       return;
     }
   }
-  absl::optional<quic::QuicDataReader> reader = absl::nullopt;
+  std::optional<quic::QuicDataReader> reader = std::nullopt;
   size_t original_buffer_size = buffered_message_.size();
   // There are three cases: the parser has already delivered an OBJECT header
   // and is now delivering payload; part of a message is in the buffer; or
@@ -561,14 +561,14 @@
 }
 
 bool MoqtParser::ReadLocation(quic::QuicDataReader& reader,
-                              absl::optional<MoqtSubscribeLocation>& loc) {
+                              std::optional<MoqtSubscribeLocation>& loc) {
   uint64_t ui64;
   if (!reader.ReadVarInt62(&ui64)) {
     return false;
   }
   auto mode = static_cast<MoqtSubscribeLocationMode>(ui64);
   if (mode == MoqtSubscribeLocationMode::kNone) {
-    loc = absl::nullopt;
+    loc = std::nullopt;
     return true;
   }
   if (!reader.ReadVarInt62(&ui64)) {
diff --git a/quiche/quic/moqt/moqt_parser.h b/quiche/quic/moqt/moqt_parser.h
index b45a707..9dd63b5 100644
--- a/quiche/quic/moqt/moqt_parser.h
+++ b/quiche/quic/moqt/moqt_parser.h
@@ -9,10 +9,10 @@
 
 #include <cstddef>
 #include <cstdint>
+#include <optional>
 #include <string>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_data_reader.h"
 #include "quiche/quic/moqt/moqt_messages.h"
 #include "quiche/common/platform/api/quiche_export.h"
@@ -97,7 +97,7 @@
   bool ReadVarIntPieceVarInt62(quic::QuicDataReader& reader, uint64_t& result);
   // Read a Location field from SUBSCRIBE REQUEST
   bool ReadLocation(quic::QuicDataReader& reader,
-                    absl::optional<MoqtSubscribeLocation>& loc);
+                    std::optional<MoqtSubscribeLocation>& loc);
   // Read a parameter and return the value as a string_view. Returns false if
   // |reader| does not have enough data.
   bool ReadParameter(quic::QuicDataReader& reader, uint64_t& type,
@@ -114,7 +114,7 @@
   std::string buffered_message_;
 
   // Metadata for an object which is delivered in parts.
-  absl::optional<MoqtObject> object_metadata_ = absl::nullopt;
+  std::optional<MoqtObject> object_metadata_ = std::nullopt;
   size_t payload_length_remaining_;
 
   bool processing_ = false;  // True if currently in ProcessData(), to prevent
diff --git a/quiche/quic/moqt/moqt_parser_test.cc b/quiche/quic/moqt/moqt_parser_test.cc
index b91768e..50a0357 100644
--- a/quiche/quic/moqt/moqt_parser_test.cc
+++ b/quiche/quic/moqt/moqt_parser_test.cc
@@ -8,11 +8,11 @@
 #include <cstdint>
 #include <cstring>
 #include <memory>
+#include <optional>
 #include <string>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_data_writer.h"
 #include "quiche/quic/moqt/moqt_messages.h"
 #include "quiche/quic/moqt/test_tools/moqt_test_message.h"
@@ -230,12 +230,12 @@
     parsing_error_ = reason;
   }
 
-  absl::optional<absl::string_view> object_payload_;
+  std::optional<absl::string_view> object_payload_;
   bool end_of_message_ = false;
   bool got_goaway_ = false;
-  absl::optional<absl::string_view> parsing_error_;
+  std::optional<absl::string_view> parsing_error_;
   uint64_t messages_received_ = 0;
-  absl::optional<TestMessageBase::MessageStructuredData> last_message_;
+  std::optional<TestMessageBase::MessageStructuredData> last_message_;
   // Stored strings for last_message_. The visitor API does not promise the
   // memory pointed to by string_views is persistent.
   std::string string0_, string1_, string2_;
diff --git a/quiche/quic/moqt/moqt_session.h b/quiche/quic/moqt/moqt_session.h
index dc98b2c..f33c753 100644
--- a/quiche/quic/moqt/moqt_session.h
+++ b/quiche/quic/moqt/moqt_session.h
@@ -5,11 +5,11 @@
 #ifndef QUICHE_QUIC_MOQT_MOQT_SESSION_H_
 #define QUICHE_QUIC_MOQT_MOQT_SESSION_H_
 
+#include <optional>
 #include <string>
 #include <utility>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_types.h"
 #include "quiche/quic/moqt/moqt_framer.h"
 #include "quiche/quic/moqt/moqt_messages.h"
@@ -102,7 +102,7 @@
     MoqtParser parser_;
     // nullopt means "incoming stream, and we don't know if it's the control
     // stream or a data stream yet".
-    absl::optional<bool> is_control_stream_;
+    std::optional<bool> is_control_stream_;
   };
 
   webtransport::Session* session_;
@@ -111,7 +111,7 @@
   MoqtSessionTerminatedCallback session_terminated_callback_;
   MoqtFramer framer_;
 
-  absl::optional<webtransport::StreamId> control_stream_;
+  std::optional<webtransport::StreamId> control_stream_;
   std::string error_;
 };
 
diff --git a/quiche/quic/moqt/test_tools/moqt_test_message.h b/quiche/quic/moqt/test_tools/moqt_test_message.h
index b25c998..ada4dea 100644
--- a/quiche/quic/moqt/test_tools/moqt_test_message.h
+++ b/quiche/quic/moqt/test_tools/moqt_test_message.h
@@ -8,10 +8,10 @@
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
+#include <optional>
 #include <vector>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/variant.h"
 #include "quiche/quic/core/quic_data_reader.h"
 #include "quiche/quic/core/quic_data_writer.h"
@@ -149,7 +149,7 @@
       /*group_sequence=*/5,
       /*object_sequence=*/6,
       /*object_send_order=*/7,
-      /*payload_length=*/absl::nullopt,
+      /*payload_length=*/std::nullopt,
   };
 };
 
@@ -183,7 +183,7 @@
       0x00, 0x04, 0x05, 0x06, 0x07,  // varints
       0x03, 0x66, 0x6f, 0x6f,        // payload = "foo"
   };
-  absl::optional<uint64_t> payload_length_ = 3;
+  std::optional<uint64_t> payload_length_ = 3;
 };
 
 class QUICHE_NO_EXPORT ObjectMessageWithoutLength : public ObjectMessage {
@@ -195,7 +195,7 @@
 
   bool EqualFieldValues(MessageStructuredData& values) const override {
     auto cast = std::get<MoqtObject>(values);
-    if (cast.payload_length != absl::nullopt) {
+    if (cast.payload_length != std::nullopt) {
       QUIC_LOG(INFO) << "OBJECT Payload Length mismatch";
       return false;
     }
@@ -223,7 +223,7 @@
       : TestMessageBase(MoqtMessageType::kClientSetup) {
     if (webtrans) {
       // Should not send PATH.
-      client_setup_.path = absl::nullopt;
+      client_setup_.path = std::nullopt;
       raw_packet_[5] = 0x01;  // only one parameter
       SetWireImage(raw_packet_, sizeof(raw_packet_) - 5);
     } else {
@@ -321,7 +321,7 @@
   };
   MoqtServerSetup server_setup_ = {
       /*selected_version=*/static_cast<MoqtVersion>(1),
-      /*role=*/absl::nullopt,
+      /*role=*/std::nullopt,
   };
 };
 
@@ -388,8 +388,8 @@
       /*track_name=*/"abcd",
       /*start_group=*/MoqtSubscribeLocation(false, (int64_t)(-4)),
       /*start_object=*/MoqtSubscribeLocation(true, (uint64_t)1),
-      /*end_group=*/absl::nullopt,
-      /*end_object=*/absl::nullopt,
+      /*end_group=*/std::nullopt,
+      /*end_object=*/std::nullopt,
       /*authorization_info=*/"bar",
   };
 };
diff --git a/quiche/quic/qbone/qbone_stream_test.cc b/quiche/quic/qbone/qbone_stream_test.cc
index 00e854f..7ab4dad 100644
--- a/quiche/quic/qbone/qbone_stream_test.cc
+++ b/quiche/quic/qbone/qbone_stream_test.cc
@@ -110,8 +110,8 @@
 
   void SetWritable() override {}
 
-  absl::optional<int> MessageTooBigErrorCode() const override {
-    return absl::nullopt;
+  std::optional<int> MessageTooBigErrorCode() const override {
+    return std::nullopt;
   }
 
   QuicByteCount GetMaxPacketSize(
diff --git a/quiche/quic/test_tools/crypto_test_utils.cc b/quiche/quic/test_tools/crypto_test_utils.cc
index 660f186..62c3a92 100644
--- a/quiche/quic/test_tools/crypto_test_utils.cc
+++ b/quiche/quic/test_tools/crypto_test_utils.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <cstddef>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -14,7 +15,6 @@
 #include "absl/strings/escaping.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/core/crypto/certificate_view.h"
 #include "quiche/quic/core/crypto/crypto_handshake.h"
@@ -937,7 +937,7 @@
       const std::string& signature, const ProofVerifyContext* context,
       std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details,
       std::unique_ptr<ProofVerifierCallback> callback) override {
-    absl::optional<std::string> payload =
+    std::optional<std::string> payload =
         CryptoUtils::GenerateProofPayloadToBeSigned(chlo_hash, server_config);
     if (!payload.has_value()) {
       *error_details = "Failed to serialize signed payload";
diff --git a/quiche/quic/test_tools/fake_proof_source_handle.cc b/quiche/quic/test_tools/fake_proof_source_handle.cc
index ceebb30..18d93d9 100644
--- a/quiche/quic/test_tools/fake_proof_source_handle.cc
+++ b/quiche/quic/test_tools/fake_proof_source_handle.cc
@@ -21,7 +21,7 @@
 class ResultSavingSignatureCallback : public ProofSource::SignatureCallback {
  public:
   explicit ResultSavingSignatureCallback(
-      absl::optional<ComputeSignatureResult>* result)
+      std::optional<ComputeSignatureResult>* result)
       : result_(result) {
     QUICHE_DCHECK(!result_->has_value());
   }
@@ -32,14 +32,14 @@
   }
 
  private:
-  absl::optional<ComputeSignatureResult>* result_;
+  std::optional<ComputeSignatureResult>* result_;
 };
 
 ComputeSignatureResult ComputeSignatureNow(
     ProofSource* delegate, const QuicSocketAddress& server_address,
     const QuicSocketAddress& client_address, const std::string& hostname,
     uint16_t signature_algorithm, absl::string_view in) {
-  absl::optional<ComputeSignatureResult> result;
+  std::optional<ComputeSignatureResult> result;
   delegate->ComputeTlsSignature(
       server_address, client_address, hostname, signature_algorithm, in,
       std::make_unique<ResultSavingSignatureCallback>(&result));
@@ -72,9 +72,9 @@
     const QuicConnectionId& original_connection_id,
     absl::string_view ssl_capabilities, const std::string& hostname,
     absl::string_view client_hello, const std::string& alpn,
-    absl::optional<std::string> alps,
+    std::optional<std::string> alps,
     const std::vector<uint8_t>& quic_transport_params,
-    const absl::optional<std::vector<uint8_t>>& early_data_context,
+    const std::optional<std::vector<uint8_t>>& early_data_context,
     const QuicSSLConfig& ssl_config) {
   if (select_cert_action_ != Action::FAIL_SYNC_DO_NOT_CHECK_CLOSED) {
     QUICHE_CHECK(!closed_);
diff --git a/quiche/quic/test_tools/fake_proof_source_handle.h b/quiche/quic/test_tools/fake_proof_source_handle.h
index 599a1fa..960544a 100644
--- a/quiche/quic/test_tools/fake_proof_source_handle.h
+++ b/quiche/quic/test_tools/fake_proof_source_handle.h
@@ -47,9 +47,9 @@
       const QuicConnectionId& original_connection_id,
       absl::string_view ssl_capabilities, const std::string& hostname,
       absl::string_view client_hello, const std::string& alpn,
-      absl::optional<std::string> alps,
+      std::optional<std::string> alps,
       const std::vector<uint8_t>& quic_transport_params,
-      const absl::optional<std::vector<uint8_t>>& early_data_context,
+      const std::optional<std::vector<uint8_t>>& early_data_context,
       const QuicSSLConfig& ssl_config) override;
 
   QuicAsyncStatus ComputeSignature(const QuicSocketAddress& server_address,
@@ -71,9 +71,9 @@
                    QuicConnectionId original_connection_id,
                    absl::string_view ssl_capabilities, std::string hostname,
                    absl::string_view client_hello, std::string alpn,
-                   absl::optional<std::string> alps,
+                   std::optional<std::string> alps,
                    std::vector<uint8_t> quic_transport_params,
-                   absl::optional<std::vector<uint8_t>> early_data_context,
+                   std::optional<std::vector<uint8_t>> early_data_context,
                    QuicSSLConfig ssl_config)
         : server_address(server_address),
           client_address(client_address),
@@ -94,9 +94,9 @@
     std::string hostname;
     std::string client_hello;
     std::string alpn;
-    absl::optional<std::string> alps;
+    std::optional<std::string> alps;
     std::vector<uint8_t> quic_transport_params;
-    absl::optional<std::vector<uint8_t>> early_data_context;
+    std::optional<std::vector<uint8_t>> early_data_context;
     QuicSSLConfig ssl_config;
   };
 
@@ -184,8 +184,8 @@
   // Action for the next compute signature operation.
   Action compute_signature_action_ = Action::DELEGATE_SYNC;
   const QuicDelayedSSLConfig dealyed_ssl_config_;
-  absl::optional<SelectCertOperation> select_cert_op_;
-  absl::optional<ComputeSignatureOperation> compute_signature_op_;
+  std::optional<SelectCertOperation> select_cert_op_;
+  std::optional<ComputeSignatureOperation> compute_signature_op_;
 
   // Save all the select cert and compute signature args for tests to inspect.
   std::vector<SelectCertArgs> all_select_cert_args_;
diff --git a/quiche/quic/test_tools/first_flight.h b/quiche/quic/test_tools/first_flight.h
index cd16f94..7360cf3 100644
--- a/quiche/quic/test_tools/first_flight.h
+++ b/quiche/quic/test_tools/first_flight.h
@@ -44,8 +44,8 @@
   // Overrides for QuicPacketWriter.
   bool IsWriteBlocked() const override { return false; }
   void SetWritable() override {}
-  absl::optional<int> MessageTooBigErrorCode() const override {
-    return absl::nullopt;
+  std::optional<int> MessageTooBigErrorCode() const override {
+    return std::nullopt;
   }
   QuicByteCount GetMaxPacketSize(
       const QuicSocketAddress& /*peer_address*/) const override {
diff --git a/quiche/quic/test_tools/mock_connection_id_generator.h b/quiche/quic/test_tools/mock_connection_id_generator.h
index 42209d6..4ea34b9 100644
--- a/quiche/quic/test_tools/mock_connection_id_generator.h
+++ b/quiche/quic/test_tools/mock_connection_id_generator.h
@@ -13,10 +13,10 @@
 
 class MockConnectionIdGenerator : public quic::ConnectionIdGeneratorInterface {
  public:
-  MOCK_METHOD(absl::optional<quic::QuicConnectionId>, GenerateNextConnectionId,
+  MOCK_METHOD(std::optional<quic::QuicConnectionId>, GenerateNextConnectionId,
               (const quic::QuicConnectionId& original), (override));
 
-  MOCK_METHOD(absl::optional<quic::QuicConnectionId>, MaybeReplaceConnectionId,
+  MOCK_METHOD(std::optional<quic::QuicConnectionId>, MaybeReplaceConnectionId,
               (const quic::QuicConnectionId& original,
                const quic::ParsedQuicVersion& version),
               (override));
diff --git a/quiche/quic/test_tools/mock_load_balancer_encoder.h b/quiche/quic/test_tools/mock_load_balancer_encoder.h
index f40047e..d313748 100644
--- a/quiche/quic/test_tools/mock_load_balancer_encoder.h
+++ b/quiche/quic/test_tools/mock_load_balancer_encoder.h
@@ -19,9 +19,9 @@
   MOCK_METHOD(bool, IsEncoding, (), (const, override));
   MOCK_METHOD(bool, IsEncrypted, (), (const, override));
   MOCK_METHOD(bool, len_self_encoded, (), (const, override));
-  MOCK_METHOD(absl::optional<QuicConnectionId>, GenerateNextConnectionId,
+  MOCK_METHOD(std::optional<QuicConnectionId>, GenerateNextConnectionId,
               (const QuicConnectionId& original), (override));
-  MOCK_METHOD(absl::optional<QuicConnectionId>, MaybeReplaceConnectionId,
+  MOCK_METHOD(std::optional<QuicConnectionId>, MaybeReplaceConnectionId,
               (const QuicConnectionId& original,
                const ParsedQuicVersion& version),
               (override));
diff --git a/quiche/quic/test_tools/qpack/qpack_offline_decoder.cc b/quiche/quic/test_tools/qpack/qpack_offline_decoder.cc
index 282e33f..da7a865 100644
--- a/quiche/quic/test_tools/qpack/qpack_offline_decoder.cc
+++ b/quiche/quic/test_tools/qpack/qpack_offline_decoder.cc
@@ -130,7 +130,7 @@
     absl::string_view input_filename) {
   // Store data in |input_data_storage|; use a absl::string_view to
   // efficiently keep track of remaining portion yet to be decoded.
-  absl::optional<std::string> input_data_storage =
+  std::optional<std::string> input_data_storage =
       quiche::ReadFileContents(input_filename);
   QUICHE_DCHECK(input_data_storage.has_value());
   absl::string_view input_data(*input_data_storage);
@@ -228,7 +228,7 @@
   // Store data in |expected_headers_data_storage|; use a
   // absl::string_view to efficiently keep track of remaining portion
   // yet to be decoded.
-  absl::optional<std::string> expected_headers_data_storage =
+  std::optional<std::string> expected_headers_data_storage =
       quiche::ReadFileContents(expected_headers_filename);
   QUICHE_DCHECK(expected_headers_data_storage.has_value());
   absl::string_view expected_headers_data(*expected_headers_data_storage);
diff --git a/quiche/quic/test_tools/quic_test_client.cc b/quiche/quic/test_tools/quic_test_client.cc
index 601a2bb..5b66785 100644
--- a/quiche/quic/test_tools/quic_test_client.cc
+++ b/quiche/quic/test_tools/quic_test_client.cc
@@ -614,8 +614,7 @@
 bool QuicTestClient::HaveActiveStream() { return !open_streams_.empty(); }
 
 bool QuicTestClient::WaitUntil(
-    int timeout_ms,
-    absl::optional<quiche::UnretainedCallback<bool()>> trigger) {
+    int timeout_ms, std::optional<quiche::UnretainedCallback<bool()>> trigger) {
   QuicTime::Delta timeout = QuicTime::Delta::FromMilliseconds(timeout_ms);
   const QuicClock* clock = client()->session()->connection()->clock();
   QuicTime end_waiting_time = clock->Now() + timeout;
diff --git a/quiche/quic/test_tools/quic_test_client.h b/quiche/quic/test_tools/quic_test_client.h
index 9ea9cfa..3dbd524 100644
--- a/quiche/quic/test_tools/quic_test_client.h
+++ b/quiche/quic/test_tools/quic_test_client.h
@@ -161,7 +161,7 @@
   QuicSocketAddress local_address() const;
   void ClearPerRequestState();
   bool WaitUntil(int timeout_ms,
-                 absl::optional<quiche::UnretainedCallback<bool()>> trigger);
+                 std::optional<quiche::UnretainedCallback<bool()>> trigger);
   int64_t Send(absl::string_view data);
   bool connected() const;
   bool buffer_body() const;
diff --git a/quiche/quic/test_tools/quic_test_utils.cc b/quiche/quic/test_tools/quic_test_utils.cc
index 4647c98..c5ae06f 100644
--- a/quiche/quic/test_tools/quic_test_utils.cc
+++ b/quiche/quic/test_tools/quic_test_utils.cc
@@ -352,7 +352,7 @@
 
 bool NoOpFramerVisitor::OnAckFrameEnd(
     QuicPacketNumber /*start*/,
-    const absl::optional<QuicEcnCounts>& /*ecn_counts*/) {
+    const std::optional<QuicEcnCounts>& /*ecn_counts*/) {
   return true;
 }
 
@@ -632,7 +632,7 @@
 QuicConsumedData MockQuicSession::ConsumeData(
     QuicStreamId id, size_t write_length, QuicStreamOffset offset,
     StreamSendingState state, TransmissionType /*type*/,
-    absl::optional<EncryptionLevel> /*level*/) {
+    std::optional<EncryptionLevel> /*level*/) {
   if (write_length > 0) {
     auto buf = std::make_unique<char[]>(write_length);
     QuicStream* stream = GetOrCreateStream(id);
@@ -709,7 +709,7 @@
 QuicConsumedData MockQuicSpdySession::ConsumeData(
     QuicStreamId id, size_t write_length, QuicStreamOffset offset,
     StreamSendingState state, TransmissionType /*type*/,
-    absl::optional<EncryptionLevel> /*level*/) {
+    std::optional<EncryptionLevel> /*level*/) {
   if (write_length > 0) {
     auto buf = std::make_unique<char[]>(write_length);
     QuicStream* stream = GetOrCreateStream(id);
@@ -757,7 +757,7 @@
     QuicConnection* connection, const QuicConfig& config,
     const ParsedQuicVersionVector& supported_versions,
     const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config,
-    absl::optional<QuicSSLConfig> ssl_config)
+    std::optional<QuicSSLConfig> ssl_config)
     : QuicSpdyClientSessionBase(connection, nullptr, config,
                                 supported_versions),
       ssl_config_(std::move(ssl_config)) {
@@ -1480,7 +1480,7 @@
   QuicVersionLabel version_label;
   ParsedQuicVersion parsed_version = ParsedQuicVersion::Unsupported();
   QuicConnectionId destination_connection_id, source_connection_id;
-  absl::optional<absl::string_view> retry_token;
+  std::optional<absl::string_view> retry_token;
   std::string detailed_error;
   QuicErrorCode error = QuicFramer::ParsePublicHeaderDispatcher(
       encrypted_packet,
diff --git a/quiche/quic/test_tools/quic_test_utils.h b/quiche/quic/test_tools/quic_test_utils.h
index 37566f4..55b867f 100644
--- a/quiche/quic/test_tools/quic_test_utils.h
+++ b/quiche/quic/test_tools/quic_test_utils.h
@@ -311,7 +311,7 @@
               (override));
   MOCK_METHOD(bool, OnAckTimestamp, (QuicPacketNumber, QuicTime), (override));
   MOCK_METHOD(bool, OnAckFrameEnd,
-              (QuicPacketNumber, const absl::optional<QuicEcnCounts>&),
+              (QuicPacketNumber, const std::optional<QuicEcnCounts>&),
               (override));
   MOCK_METHOD(bool, OnStopWaitingFrame, (const QuicStopWaitingFrame& frame),
               (override));
@@ -395,7 +395,7 @@
   bool OnAckTimestamp(QuicPacketNumber packet_number,
                       QuicTime timestamp) override;
   bool OnAckFrameEnd(QuicPacketNumber start,
-                     const absl::optional<QuicEcnCounts>& ecn_counts) override;
+                     const std::optional<QuicEcnCounts>& ecn_counts) override;
   bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
   bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
   bool OnPingFrame(const QuicPingFrame& frame) override;
@@ -830,7 +830,7 @@
   QuicConsumedData ConsumeData(QuicStreamId id, size_t write_length,
                                QuicStreamOffset offset,
                                StreamSendingState state, TransmissionType type,
-                               absl::optional<EncryptionLevel> level);
+                               std::optional<EncryptionLevel> level);
 
   void ReallyMaybeSendRstStreamFrame(QuicStreamId id,
                                      QuicRstStreamErrorCode error,
@@ -986,7 +986,7 @@
   QuicConsumedData ConsumeData(QuicStreamId id, size_t write_length,
                                QuicStreamOffset offset,
                                StreamSendingState state, TransmissionType type,
-                               absl::optional<EncryptionLevel> level);
+                               std::optional<EncryptionLevel> level);
 
   using QuicSession::ActivateStream;
 
@@ -1094,10 +1094,10 @@
   MockQuicCryptoServerStreamHelper helper_;
   // If not nullopt, override the early_data_enabled value from base class'
   // ssl_config.
-  absl::optional<bool> early_data_enabled_;
+  std::optional<bool> early_data_enabled_;
   // If not nullopt, override the client_cert_mode value from base class'
   // ssl_config.
-  absl::optional<ClientCertMode> client_cert_mode_;
+  std::optional<ClientCertMode> client_cert_mode_;
 };
 
 class TestQuicSpdyClientSession : public QuicSpdyClientSessionBase {
@@ -1106,7 +1106,7 @@
       QuicConnection* connection, const QuicConfig& config,
       const ParsedQuicVersionVector& supported_versions,
       const QuicServerId& server_id, QuicCryptoClientConfig* crypto_config,
-      absl::optional<QuicSSLConfig> ssl_config = absl::nullopt);
+      std::optional<QuicSSLConfig> ssl_config = std::nullopt);
   TestQuicSpdyClientSession(const TestQuicSpdyClientSession&) = delete;
   TestQuicSpdyClientSession& operator=(const TestQuicSpdyClientSession&) =
       delete;
@@ -1160,7 +1160,7 @@
 
   std::unique_ptr<QuicCryptoClientStream> crypto_stream_;
   std::vector<CryptoHandshakeMessage> sent_crypto_handshake_messages_;
-  absl::optional<QuicSSLConfig> ssl_config_;
+  std::optional<QuicSSLConfig> ssl_config_;
 };
 
 class MockPacketWriter : public QuicPacketWriter {
@@ -1177,7 +1177,7 @@
               (override));
   MOCK_METHOD(bool, IsWriteBlocked, (), (const, override));
   MOCK_METHOD(void, SetWritable, (), (override));
-  MOCK_METHOD(absl::optional<int>, MessageTooBigErrorCode, (),
+  MOCK_METHOD(std::optional<int>, MessageTooBigErrorCode, (),
               (const, override));
   MOCK_METHOD(QuicByteCount, GetMaxPacketSize,
               (const QuicSocketAddress& peer_address), (const, override));
@@ -1828,7 +1828,7 @@
 
   bool IsWriteBlocked() const override { return write_blocked_; }
 
-  absl::optional<int> MessageTooBigErrorCode() const override { return 0x1234; }
+  std::optional<int> MessageTooBigErrorCode() const override { return 0x1234; }
 
   void SetWriteBlocked() { write_blocked_ = true; }
 
diff --git a/quiche/quic/test_tools/simple_quic_framer.cc b/quiche/quic/test_tools/simple_quic_framer.cc
index b13fec4..fc50251 100644
--- a/quiche/quic/test_tools/simple_quic_framer.cc
+++ b/quiche/quic/test_tools/simple_quic_framer.cc
@@ -111,7 +111,7 @@
 
   bool OnAckFrameEnd(
       QuicPacketNumber /*start*/,
-      const absl::optional<QuicEcnCounts>& /*ecn_counts*/) override {
+      const std::optional<QuicEcnCounts>& /*ecn_counts*/) override {
     return true;
   }
 
diff --git a/quiche/quic/test_tools/simulator/quic_endpoint_base.cc b/quiche/quic/test_tools/simulator/quic_endpoint_base.cc
index 3ff517a..209994a 100644
--- a/quiche/quic/test_tools/simulator/quic_endpoint_base.cc
+++ b/quiche/quic/test_tools/simulator/quic_endpoint_base.cc
@@ -153,8 +153,8 @@
 
 void QuicEndpointBase::Writer::SetWritable() { is_blocked_ = false; }
 
-absl::optional<int> QuicEndpointBase::Writer::MessageTooBigErrorCode() const {
-  return absl::nullopt;
+std::optional<int> QuicEndpointBase::Writer::MessageTooBigErrorCode() const {
+  return std::nullopt;
 }
 
 QuicByteCount QuicEndpointBase::Writer::GetMaxPacketSize(
diff --git a/quiche/quic/test_tools/simulator/quic_endpoint_base.h b/quiche/quic/test_tools/simulator/quic_endpoint_base.h
index bb3ae10..fe753d5 100644
--- a/quiche/quic/test_tools/simulator/quic_endpoint_base.h
+++ b/quiche/quic/test_tools/simulator/quic_endpoint_base.h
@@ -83,7 +83,7 @@
                             const QuicPacketWriterParams& params) override;
     bool IsWriteBlocked() const override;
     void SetWritable() override;
-    absl::optional<int> MessageTooBigErrorCode() const override;
+    std::optional<int> MessageTooBigErrorCode() const override;
     QuicByteCount GetMaxPacketSize(
         const QuicSocketAddress& peer_address) const override;
     bool SupportsReleaseTime() const override;
diff --git a/quiche/quic/test_tools/simulator/test_harness.h b/quiche/quic/test_tools/simulator/test_harness.h
index 135d744..9c879fc 100644
--- a/quiche/quic/test_tools/simulator/test_harness.h
+++ b/quiche/quic/test_tools/simulator/test_harness.h
@@ -6,9 +6,9 @@
 #define QUICHE_QUIC_TEST_TOOLS_SIMULATOR_TEST_HARNESS_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/quic_bandwidth.h"
 #include "quiche/quic/core/quic_constants.h"
 #include "quiche/quic/core/quic_time.h"
@@ -79,8 +79,8 @@
  private:
   Simulator simulator_;
   Switch switch_;
-  absl::optional<SymmetricLink> client_link_;
-  absl::optional<SymmetricLink> server_link_;
+  std::optional<SymmetricLink> client_link_;
+  std::optional<SymmetricLink> server_link_;
   std::unique_ptr<PacketFilter> client_filter_;
   std::unique_ptr<PacketFilter> server_filter_;
 
diff --git a/quiche/quic/tools/connect_tunnel.cc b/quiche/quic/tools/connect_tunnel.cc
index d31e540..22f6c3b 100644
--- a/quiche/quic/tools/connect_tunnel.cc
+++ b/quiche/quic/tools/connect_tunnel.cc
@@ -5,6 +5,7 @@
 #include "quiche/quic/tools/connect_tunnel.h"
 
 #include <cstdint>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -14,7 +15,6 @@
 #include "absl/status/statusor.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/core/quic_error_codes.h"
 #include "quiche/quic/core/quic_server_id.h"
@@ -34,7 +34,7 @@
 // Arbitrarily chosen. No effort has been made to figure out an optimal size.
 constexpr size_t kReadSize = 4 * 1024;
 
-absl::optional<QuicServerId> ValidateHeadersAndGetAuthority(
+std::optional<QuicServerId> ValidateHeadersAndGetAuthority(
     const spdy::Http2HeaderBlock& request_headers) {
   QUICHE_DCHECK(request_headers.contains(":method"));
   QUICHE_DCHECK(request_headers.find(":method")->second == "CONNECT");
@@ -44,31 +44,31 @@
   if (scheme_it != request_headers.end()) {
     QUICHE_DVLOG(1) << "CONNECT request contains unexpected scheme: "
                     << scheme_it->second;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   auto path_it = request_headers.find(":path");
   if (path_it != request_headers.end()) {
     QUICHE_DVLOG(1) << "CONNECT request contains unexpected path: "
                     << path_it->second;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   auto authority_it = request_headers.find(":authority");
   if (authority_it == request_headers.end() || authority_it->second.empty()) {
     QUICHE_DVLOG(1) << "CONNECT request missing authority";
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   // A valid CONNECT authority must contain host and port and nothing else, per
   // https://www.rfc-editor.org/rfc/rfc9110.html#name-connect. This matches the
   // host and port parsing rules for QuicServerId.
-  absl::optional<QuicServerId> server_id =
+  std::optional<QuicServerId> server_id =
       QuicServerId::ParseFromHostPortString(authority_it->second);
   if (!server_id.has_value()) {
     QUICHE_DVLOG(1) << "CONNECT request authority is malformed: "
                     << authority_it->second;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   return server_id;
@@ -111,7 +111,7 @@
 void ConnectTunnel::OpenTunnel(const spdy::Http2HeaderBlock& request_headers) {
   QUICHE_DCHECK(!IsConnectedToDestination());
 
-  absl::optional<QuicServerId> authority =
+  std::optional<QuicServerId> authority =
       ValidateHeadersAndGetAuthority(request_headers);
   if (!authority.has_value()) {
     TerminateClientStream(
diff --git a/quiche/quic/tools/connect_udp_tunnel.cc b/quiche/quic/tools/connect_udp_tunnel.cc
index d92f63b..4cec8b8 100644
--- a/quiche/quic/tools/connect_udp_tunnel.cc
+++ b/quiche/quic/tools/connect_udp_tunnel.cc
@@ -5,6 +5,7 @@
 #include "quiche/quic/tools/connect_udp_tunnel.h"
 
 #include <cstdint>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -16,7 +17,6 @@
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "absl/types/span.h"
 #include "quiche/quic/core/quic_error_codes.h"
 #include "quiche/quic/core/quic_server_id.h"
@@ -44,7 +44,7 @@
 
 // Only support the default path
 // ("/.well-known/masque/udp/{target_host}/{target_port}/")
-absl::optional<QuicServerId> ValidateAndParseTargetFromPath(
+std::optional<QuicServerId> ValidateAndParseTargetFromPath(
     absl::string_view path) {
   std::string canonicalized_path_str;
   url::StdStringCanonOutput canon_output(&canonicalized_path_str);
@@ -54,7 +54,7 @@
   if (!path_component.is_nonempty()) {
     QUICHE_DVLOG(1) << "CONNECT-UDP request with non-canonicalizable path: "
                     << path;
-    return absl::nullopt;
+    return std::nullopt;
   }
   canon_output.Complete();
   absl::string_view canonicalized_path =
@@ -69,26 +69,26 @@
       path_split[5].empty() || !path_split[6].empty()) {
     QUICHE_DVLOG(1) << "CONNECT-UDP request with bad path: "
                     << canonicalized_path;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
-  absl::optional<std::string> decoded_host =
+  std::optional<std::string> decoded_host =
       quiche::AsciiUrlDecode(path_split[4]);
   if (!decoded_host.has_value()) {
     QUICHE_DVLOG(1) << "CONNECT-UDP request with undecodable host: "
                     << path_split[4];
-    return absl::nullopt;
+    return std::nullopt;
   }
   // Empty host checked above after path split. Expect decoding to never result
   // in an empty decoded host from non-empty encoded host.
   QUICHE_DCHECK(!decoded_host.value().empty());
 
-  absl::optional<std::string> decoded_port =
+  std::optional<std::string> decoded_port =
       quiche::AsciiUrlDecode(path_split[5]);
   if (!decoded_port.has_value()) {
     QUICHE_DVLOG(1) << "CONNECT-UDP request with undecodable port: "
                     << path_split[5];
-    return absl::nullopt;
+    return std::nullopt;
   }
   // Empty port checked above after path split. Expect decoding to never result
   // in an empty decoded port from non-empty encoded port.
@@ -103,7 +103,7 @@
   if (parsed_port_number <= 0) {
     QUICHE_DVLOG(1) << "CONNECT-UDP request with bad port: "
                     << decoded_port.value();
-    return absl::nullopt;
+    return std::nullopt;
   }
   // Expect url::ParsePort() to validate port is uint16_t and otherwise return
   // negative number checked for above.
@@ -114,7 +114,7 @@
 }
 
 // Validate header expectations from RFC 9298, section 3.4.
-absl::optional<QuicServerId> ValidateHeadersAndGetTarget(
+std::optional<QuicServerId> ValidateHeadersAndGetTarget(
     const spdy::Http2HeaderBlock& request_headers) {
   QUICHE_DCHECK(request_headers.contains(":method"));
   QUICHE_DCHECK(request_headers.find(":method")->second == "CONNECT");
@@ -124,7 +124,7 @@
   auto authority_it = request_headers.find(":authority");
   if (authority_it == request_headers.end() || authority_it->second.empty()) {
     QUICHE_DVLOG(1) << "CONNECT-UDP request missing authority";
-    return absl::nullopt;
+    return std::nullopt;
   }
   // For toy server simplicity, skip validating that the authority matches the
   // current server.
@@ -132,19 +132,19 @@
   auto scheme_it = request_headers.find(":scheme");
   if (scheme_it == request_headers.end() || scheme_it->second.empty()) {
     QUICHE_DVLOG(1) << "CONNECT-UDP request missing scheme";
-    return absl::nullopt;
+    return std::nullopt;
   } else if (scheme_it->second != "https") {
     QUICHE_DVLOG(1) << "CONNECT-UDP request contains unexpected scheme: "
                     << scheme_it->second;
-    return absl::nullopt;
+    return std::nullopt;
   }
 
   auto path_it = request_headers.find(":path");
   if (path_it == request_headers.end() || path_it->second.empty()) {
     QUICHE_DVLOG(1) << "CONNECT-UDP request missing path";
-    return absl::nullopt;
+    return std::nullopt;
   }
-  absl::optional<QuicServerId> target_server_id =
+  std::optional<QuicServerId> target_server_id =
       ValidateAndParseTargetFromPath(path_it->second);
 
   return target_server_id;
@@ -190,7 +190,7 @@
     const spdy::Http2HeaderBlock& request_headers) {
   QUICHE_DCHECK(!IsTunnelOpenToTarget());
 
-  absl::optional<QuicServerId> target =
+  std::optional<QuicServerId> target =
       ValidateHeadersAndGetTarget(request_headers);
   if (!target.has_value()) {
     // Malformed request.
@@ -351,7 +351,7 @@
   spdy::Http2HeaderBlock response_headers;
   response_headers[":status"] = "200";
 
-  absl::optional<std::string> capsule_protocol_value =
+  std::optional<std::string> capsule_protocol_value =
       structured_headers::SerializeItem(structured_headers::Item(true));
   QUICHE_CHECK(capsule_protocol_value.has_value());
   response_headers["Capsule-Protocol"] = capsule_protocol_value.value();
@@ -395,7 +395,7 @@
       std::move(proxy_status_item),
       {{"error", std::move(proxy_status_error_item)},
        {"details", std::move(proxy_status_details_item)}});
-  absl::optional<std::string> proxy_status_value =
+  std::optional<std::string> proxy_status_value =
       structured_headers::SerializeList({proxy_status_member});
   QUICHE_CHECK(proxy_status_value.has_value());
   headers["Proxy-Status"] = proxy_status_value.value();
diff --git a/quiche/quic/tools/quic_client_base.h b/quiche/quic/tools/quic_client_base.h
index 955f83a..cf9e0e0 100644
--- a/quiche/quic/tools/quic_client_base.h
+++ b/quiche/quic/tools/quic_client_base.h
@@ -452,7 +452,7 @@
   // If set,
   // - GetNextConnectionId will use this as the next server connection id.
   // - GenerateNewConnectionId will not be called.
-  absl::optional<QuicConnectionId> server_connection_id_override_;
+  std::optional<QuicConnectionId> server_connection_id_override_;
 
   // GenerateNewConnectionId creates a random connection ID of this length.
   // Defaults to 8.
diff --git a/quiche/quic/tools/quic_client_default_network_helper.h b/quiche/quic/tools/quic_client_default_network_helper.h
index fbc42c2..9b9ba35 100644
--- a/quiche/quic/tools/quic_client_default_network_helper.h
+++ b/quiche/quic/tools/quic_client_default_network_helper.h
@@ -7,9 +7,9 @@
 
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <string>
 
-#include "absl/types/optional.h"
 #include "quiche/quic/core/io/quic_event_loop.h"
 #include "quiche/quic/core/io/socket.h"
 #include "quiche/quic/core/quic_default_packet_writer.h"
diff --git a/quiche/quic/tools/quic_memory_cache_backend.cc b/quiche/quic/tools/quic_memory_cache_backend.cc
index 95a8421..29434b3 100644
--- a/quiche/quic/tools/quic_memory_cache_backend.cc
+++ b/quiche/quic/tools/quic_memory_cache_backend.cc
@@ -28,7 +28,7 @@
 QuicMemoryCacheBackend::ResourceFile::~ResourceFile() = default;
 
 void QuicMemoryCacheBackend::ResourceFile::Read() {
-  absl::optional<std::string> maybe_file_contents =
+  std::optional<std::string> maybe_file_contents =
       quiche::ReadFileContents(file_name_);
   if (!maybe_file_contents) {
     QUIC_LOG(DFATAL) << "Failed to read file for the memory cache backend: "
diff --git a/quiche/quic/tools/quic_packet_printer_bin.cc b/quiche/quic/tools/quic_packet_printer_bin.cc
index ca1b433..e507c5e 100644
--- a/quiche/quic/tools/quic_packet_printer_bin.cc
+++ b/quiche/quic/tools/quic_packet_printer_bin.cc
@@ -126,7 +126,7 @@
     return true;
   }
   bool OnAckFrameEnd(QuicPacketNumber start,
-                     const absl::optional<QuicEcnCounts>& ecn_counts) override {
+                     const std::optional<QuicEcnCounts>& ecn_counts) override {
     std::cerr << "OnAckFrameEnd, start: " << start;
     if (ecn_counts.has_value()) {
       std::cerr << "  ECN counts: " << ecn_counts->ToString();
diff --git a/quiche/quic/tools/quic_simple_server_stream.cc b/quiche/quic/tools/quic_simple_server_stream.cc
index b0cb9cb..07c0def 100644
--- a/quiche/quic/tools/quic_simple_server_stream.cc
+++ b/quiche/quic/tools/quic_simple_server_stream.cc
@@ -6,12 +6,12 @@
 
 #include <cstdint>
 #include <list>
+#include <optional>
 #include <utility>
 
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/http/quic_spdy_stream.h"
 #include "quiche/quic/core/http/spdy_utils.h"
 #include "quiche/quic/core/http/web_transport_http3.h"
@@ -363,10 +363,10 @@
 
   if (close_stream) {
     SendHeadersAndBodyAndTrailers(
-        /*response_headers=*/absl::nullopt, data,
+        /*response_headers=*/std::nullopt, data,
         /*response_trailers=*/spdy::Http2HeaderBlock());
   } else {
-    SendIncompleteResponse(/*response_headers=*/absl::nullopt, data);
+    SendIncompleteResponse(/*response_headers=*/std::nullopt, data);
   }
 }
 
@@ -419,7 +419,7 @@
 }
 
 void QuicSimpleServerStream::SendIncompleteResponse(
-    absl::optional<Http2HeaderBlock> response_headers, absl::string_view body) {
+    std::optional<Http2HeaderBlock> response_headers, absl::string_view body) {
   // Headers should be sent iff not sent in a previous response.
   QUICHE_DCHECK_NE(response_headers.has_value(), response_sent_);
 
@@ -449,7 +449,7 @@
 }
 
 void QuicSimpleServerStream::SendHeadersAndBodyAndTrailers(
-    absl::optional<Http2HeaderBlock> response_headers, absl::string_view body,
+    std::optional<Http2HeaderBlock> response_headers, absl::string_view body,
     Http2HeaderBlock response_trailers) {
   // Headers should be sent iff not sent in a previous response.
   QUICHE_DCHECK_NE(response_headers.has_value(), response_sent_);
diff --git a/quiche/quic/tools/quic_simple_server_stream.h b/quiche/quic/tools/quic_simple_server_stream.h
index fe12b70..998429a 100644
--- a/quiche/quic/tools/quic_simple_server_stream.h
+++ b/quiche/quic/tools/quic_simple_server_stream.h
@@ -6,9 +6,9 @@
 #define QUICHE_QUIC_TOOLS_QUIC_SIMPLE_SERVER_STREAM_H_
 
 #include <cstdint>
+#include <optional>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/http/quic_spdy_server_stream_base.h"
 #include "quiche/quic/core/quic_error_codes.h"
 #include "quiche/quic/core/quic_packets.h"
@@ -76,16 +76,16 @@
   // for the body.
   void SendNotFoundResponse();
 
-  // Sends the response header (if not `absl::nullopt`) and body, but not the
+  // Sends the response header (if not `std::nullopt`) and body, but not the
   // fin.
   void SendIncompleteResponse(
-      absl::optional<spdy::Http2HeaderBlock> response_headers,
+      std::optional<spdy::Http2HeaderBlock> response_headers,
       absl::string_view body);
 
   void SendHeadersAndBody(spdy::Http2HeaderBlock response_headers,
                           absl::string_view body);
   void SendHeadersAndBodyAndTrailers(
-      absl::optional<spdy::Http2HeaderBlock> response_headers,
+      std::optional<spdy::Http2HeaderBlock> response_headers,
       absl::string_view body, spdy::Http2HeaderBlock response_trailers);
 
   spdy::Http2HeaderBlock* request_headers() { return &request_headers_; }
diff --git a/quiche/quic/tools/quic_simple_server_stream_test.cc b/quiche/quic/tools/quic_simple_server_stream_test.cc
index ab8b607..975a194 100644
--- a/quiche/quic/tools/quic_simple_server_stream_test.cc
+++ b/quiche/quic/tools/quic_simple_server_stream_test.cc
@@ -6,12 +6,12 @@
 
 #include <list>
 #include <memory>
+#include <optional>
 #include <utility>
 
 #include "absl/base/macros.h"
 #include "absl/memory/memory.h"
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/quic/core/crypto/null_encrypter.h"
 #include "quiche/quic/core/http/http_encoder.h"
 #include "quiche/quic/core/http/spdy_utils.h"
@@ -189,7 +189,7 @@
                                QuicStreamOffset offset,
                                StreamSendingState state,
                                TransmissionType /*type*/,
-                               absl::optional<EncryptionLevel> /*level*/) {
+                               std::optional<EncryptionLevel> /*level*/) {
     if (write_length > 0) {
       auto buf = std::make_unique<char[]>(write_length);
       QuicStream* stream = GetOrCreateStream(id);
diff --git a/quiche/quic/tools/quic_spdy_client_base.cc b/quiche/quic/tools/quic_spdy_client_base.cc
index 9839534..55b6631 100644
--- a/quiche/quic/tools/quic_spdy_client_base.cc
+++ b/quiche/quic/tools/quic_spdy_client_base.cc
@@ -163,9 +163,9 @@
   return client_session() && client_session()->goaway_received();
 }
 
-absl::optional<uint64_t> QuicSpdyClientBase::last_received_http3_goaway_id() {
+std::optional<uint64_t> QuicSpdyClientBase::last_received_http3_goaway_id() {
   return client_session() ? client_session()->last_received_http3_goaway_id()
-                          : absl::nullopt;
+                          : std::nullopt;
 }
 
 bool QuicSpdyClientBase::EarlyDataAccepted() {
diff --git a/quiche/quic/tools/quic_spdy_client_base.h b/quiche/quic/tools/quic_spdy_client_base.h
index 717d92a..a6ef509 100644
--- a/quiche/quic/tools/quic_spdy_client_base.h
+++ b/quiche/quic/tools/quic_spdy_client_base.h
@@ -114,7 +114,7 @@
   bool EarlyDataAccepted() override;
   bool ReceivedInchoateReject() override;
 
-  absl::optional<uint64_t> last_received_http3_goaway_id();
+  std::optional<uint64_t> last_received_http3_goaway_id();
 
   void set_max_inbound_header_list_size(size_t size) {
     max_inbound_header_list_size_ = size;
diff --git a/quiche/quic/tools/quic_toy_server.cc b/quiche/quic/tools/quic_toy_server.cc
index da4e4e9..419fb14 100644
--- a/quiche/quic/tools/quic_toy_server.cc
+++ b/quiche/quic/tools/quic_toy_server.cc
@@ -87,7 +87,7 @@
     for (absl::string_view destination : absl::StrSplit(
              quiche::GetQuicheCommandLineFlag(FLAGS_connect_proxy_destinations),
              ',', absl::SkipEmpty())) {
-      absl::optional<QuicServerId> destination_server_id =
+      std::optional<QuicServerId> destination_server_id =
           QuicServerId::ParseFromHostPortString(destination);
       QUICHE_CHECK(destination_server_id.has_value());
       connect_proxy_destinations.insert(
@@ -98,7 +98,7 @@
     for (absl::string_view target : absl::StrSplit(
              quiche::GetQuicheCommandLineFlag(FLAGS_connect_udp_proxy_targets),
              ',', absl::SkipEmpty())) {
-      absl::optional<QuicServerId> target_server_id =
+      std::optional<QuicServerId> target_server_id =
           QuicServerId::ParseFromHostPortString(target);
       QUICHE_CHECK(target_server_id.has_value());
       connect_udp_proxy_targets.insert(std::move(target_server_id).value());
diff --git a/quiche/spdy/core/http2_frame_decoder_adapter.h b/quiche/spdy/core/http2_frame_decoder_adapter.h
index e7bd420..87ab4c5 100644
--- a/quiche/spdy/core/http2_frame_decoder_adapter.h
+++ b/quiche/spdy/core/http2_frame_decoder_adapter.h
@@ -9,10 +9,10 @@
 
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <string>
 
 #include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 #include "quiche/http2/decoder/decode_status.h"
 #include "quiche/http2/decoder/http2_frame_decoder.h"
 #include "quiche/http2/decoder/http2_frame_decoder_listener.h"
@@ -270,7 +270,7 @@
 
   // Amount of trailing padding. Currently used just as an indicator of whether
   // OnPadLength has been called.
-  absl::optional<size_t> opt_pad_length_;
+  std::optional<size_t> opt_pad_length_;
 
   // Temporary buffers for the AltSvc fields.
   std::string alt_svc_origin_;
diff --git a/quiche/web_transport/complete_buffer_visitor.h b/quiche/web_transport/complete_buffer_visitor.h
index 498f148..2382b66 100644
--- a/quiche/web_transport/complete_buffer_visitor.h
+++ b/quiche/web_transport/complete_buffer_visitor.h
@@ -5,7 +5,8 @@
 #ifndef QUICHE_WEB_TRANSPORT_COMPLETE_BUFFER_VISITOR_H_
 #define QUICHE_WEB_TRANSPORT_COMPLETE_BUFFER_VISITOR_H_
 
-#include "absl/types/optional.h"
+#include <optional>
+
 #include "absl/utility/utility.h"
 #include "quiche/common/quiche_callbacks.h"
 #include "quiche/web_transport/web_transport.h"
@@ -45,8 +46,8 @@
 
  private:
   webtransport::Stream* stream_;
-  absl::optional<std::string> outgoing_data_;
-  absl::optional<AllDataReadCallback> incoming_data_callback_;
+  std::optional<std::string> outgoing_data_;
+  std::optional<AllDataReadCallback> incoming_data_callback_;
   std::string incoming_data_buffer_;
 };