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/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());